diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2018-07-18 22:47:58 +0300 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2018-07-18 22:52:22 +0300 |
commit | e3b0145e73b266a7fc3c1e5a494dbdd9cc1f0114 (patch) | |
tree | 49fdabd2e89638a1bdab95f3d5f1a426cc536fd6 | |
parent | efba19387292054b0c9c72d9e445992a4e3e473c (diff) | |
download | meson-builddirupgrade.zip meson-builddirupgrade.tar.gz meson-builddirupgrade.tar.bz2 |
Can upgrade build directory from an old version.builddirupgrade
-rw-r--r-- | mesonbuild/backend/backends.py | 10 | ||||
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 1 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 3 | ||||
-rw-r--r-- | mesonbuild/backend/xcodebackend.py | 3 | ||||
-rw-r--r-- | mesonbuild/compilers/compilers.py | 14 | ||||
-rw-r--r-- | mesonbuild/coredata.py | 15 | ||||
-rw-r--r-- | mesonbuild/environment.py | 2 | ||||
-rw-r--r-- | mesonbuild/mesonmain.py | 4 | ||||
-rw-r--r-- | mesonbuild/mupgrade.py | 93 |
9 files changed, 139 insertions, 6 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 354d25a..e9012e5 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -24,6 +24,7 @@ from ..mesonlib import MesonException, OrderedSet from ..mesonlib import classify_unity_sources from ..mesonlib import File from ..compilers import CompilerArgs +from ..mupgrade import create_dump_dict from collections import OrderedDict import shlex @@ -120,6 +121,7 @@ class OptionOverrideProxy: # This class contains the basic functionality that is needed by all backends. # Feel free to move stuff in and out of it as you see fit. class Backend: + def __init__(self, build): self.build = build self.environment = build.environment @@ -922,3 +924,11 @@ class Backend: for s in self.build.postconf_scripts: cmd = s['exe'] + s['args'] subprocess.check_call(cmd, env=child_env) + + def dump_state_file(self): + import json + build_dir = self.environment.get_build_dir() + dumpfile = os.path.join(build_dir, 'meson-private', 'upgrade-state.json') + s = create_dump_dict(self.environment, self.build) + with open(dumpfile, 'w') as f: + json.dump(s, f) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 09c4904..cde2151 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -238,6 +238,7 @@ int dummy; # fully created. os.replace(tempfilename, outfilename) self.generate_compdb() + self.dump_state_file() # http://clang.llvm.org/docs/JSONCompilationDatabase.html def generate_compdb(self): diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index d42e91d..aee3754 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1,4 +1,4 @@ -# Copyright 2014-2016 The Meson development team +# Copyright 2014-2018 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -167,6 +167,7 @@ class Vs2010Backend(backends.Backend): self.generate_solution(sln_filename, projlist) self.generate_regen_info() Vs2010Backend.touch_regen_timestamp(self.environment.get_build_dir()) + self.dump_state_file() @staticmethod def get_regen_stampfile(build_dir): diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index 9a9f88b..276e365 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -1,4 +1,4 @@ -# Copyright 2014-2016 The Meson development team +# Copyright 2014-2018 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -103,6 +103,7 @@ class XCodeBackend(backends.Backend): self.generate_xc_build_configuration() self.generate_xc_configurationList() self.generate_suffix() + self.dump_state_file() def get_xcodetype(self, fname): return self.xcodetypemap[fname.split('.')[-1]] diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 25835a3..cefc741 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1,4 +1,4 @@ -# Copyright 2012-2017 The Meson development team +# Copyright 2012-2018 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -72,6 +72,18 @@ cflags_mapping = {'c': 'CFLAGS', 'vala': 'VALAFLAGS', 'rust': 'RUSTFLAGS'} +compiler_envvars = {'c': 'CC', + 'cpp': 'CXX', + 'java': 'JAVAC', + 'd': 'DC', + 'objc': 'OBJC', + 'objcpp': 'OBJCXX', + 'fortran': 'FC', + 'rust': 'RUSTC', + 'vala': 'VALAC', + 'cs': 'CSC', + } + # All these are only for C-linkable languages; see `clink_langs` above. def sort_clink(lang): diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index b26516c..0d6676e 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -410,9 +410,16 @@ class CoreData: sub = 'In subproject {}: '.format(subproject) if subproject else '' mlog.warning('{}Unknown options: "{}"'.format(sub, unknown_options)) + def get_all_option_classes(self): + return (self.backend_options, + self.user_options, + self.compiler_options, + self.base_options) + def load(build_dir): filename = os.path.join(build_dir, 'meson-private', 'coredata.dat') load_fail_msg = 'Coredata file {!r} is corrupted. Try with a fresh build tree.'.format(filename) + state_file_exists = os.path.isfile(os.path.join(build_dir, 'meson-private', 'upgrade_state.json')) try: with open(filename, 'rb') as f: obj = pickle.load(f) @@ -421,8 +428,12 @@ def load(build_dir): if not isinstance(obj, CoreData): raise MesonException(load_fail_msg) if obj.version != version: - raise MesonException('Build directory has been generated with Meson version %s, which is incompatible with current version %s.\nPlease delete this build directory AND create a new one.' % - (obj.version, version)) + msg = 'Build directory has been generated with Meson version %s, which is incompatible with current version %s.\n' + if state_file_exists: + msg += 'Upgrade the build directory by invoking the "upgrade-builddir" target.' + else: + msg += 'Please delete this build directory AND create a new one.' + raise MesonException(msg % (obj.version, version)) return obj def save(obj, build_dir): diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 0aa0b32..ee206e3 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -1,4 +1,4 @@ -# Copyright 2012-2016 The Meson development team +# Copyright 2012-2018 The Meson development team # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 011ac14..fdf4d23 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -307,6 +307,10 @@ def run(original_args, mainfile): sys.argv[1:] = remaining_args[1:] runpy.run_path(script_file, run_name='__main__') sys.exit(0) + elif cmd_name == 'upgrade-builddir': + from . import mupgrade + mupgrade.do_upgrade(args[1:] + ['.']) + sys.exit(0) # No special command? Do the basic setup/reconf. if len(args) >= 2 and args[0] == '--internal': diff --git a/mesonbuild/mupgrade.py b/mesonbuild/mupgrade.py new file mode 100644 index 0000000..7a97497 --- /dev/null +++ b/mesonbuild/mupgrade.py @@ -0,0 +1,93 @@ +# Copyright 2018 The Meson development team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys, os +import json +import subprocess +import shlex +from .mesonlib import meson_command +from .compilers.compilers import compiler_envvars + +dump_format_version = 1 + +def upgrade(state_file): + d = json.load(open(state_file, 'r')) + version = d.get('dump_format_version', 'missing') + if version != dump_format_version: + sys.exit('Can not upgrade because state dump file format is not compatible: %d != %d.' % (version, dump_format_version)) + state = d['state'] + env = os.environ.copy() + for c in state['compilers']: + ename = compiler_envvars[c[0]] + eval = ' '.join([shlex.quote(x) for x in c[1]]) + env[ename] = eval + cmd_args = [state['source_root'], + state['build_root']] + if 'cross_file' in state: + cmd_args += ['--cross-file', state['cross_file']] + for o in state['options']: + cmd_args.append('-D%s=%s' % (o[0], o[1])) + pc = subprocess.run(meson_command + cmd_args) + if pc.returncode != 0: + sys.exit(1) # The output from above should be enough to debug any issues. + +def do_upgrade(potential_builddirs): + for bd in potential_builddirs: + state_file = os.path.join(bd, 'meson-private', 'upgrade-state.json') + corefile = os.path.join(bd, 'meson-private', 'coredata.dat') + corefile_bak = corefile + '~' + if os.path.exists(state_file): + was_success = False + try: + os.replace(corefile, corefile_bak) + upgrade(state_file) + was_success = True + finally: + if not was_success: + try: + os.replace(corefile_bak, corefile) + except Exception as e: + print('Could not restore original state: %s\nYou probably need to wipe the builddir' % str(e)) + return + sys.exit('Could not find upgrade state file. Can not upgrade') + +def build_opt_array(environment): + options = [] + for optclass in environment.coredata.get_all_option_classes(): + for k, v in optclass.items(): + options.append((k, str(v.value))) + return options + +def build_compiler_array(build): + result = [] + # Only native ones, cross compilers come from the cross file. + for k, v in build.compilers.items(): + result.append((k, v.exelist)) + return result + +def build_state_dict(environment, build): + result = {} + result['source_root'] = environment.get_source_dir() + result['build_root'] = environment.get_build_dir() + if environment.coredata.cross_file: + result['cross_file'] = environment.coredata.cross_file + result['options'] = build_opt_array(environment) + result['compilers'] = build_compiler_array(build) + return result + +def create_dump_dict(environment, build): + s = {} + s['dump_format_version'] = dump_format_version + s['state'] = build_state_dict(environment, build) + return s |