diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2019-06-23 07:53:17 -0700 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2019-06-23 17:53:17 +0300 |
commit | 56f7e5c74f54d31b405fe1c4289a406ef826b757 (patch) | |
tree | 2ebe24ae3ca1c62d3d3ebc6275a67a89d2bd34fa /mesonbuild | |
parent | d61116efc116845d32cd56b82089addd6b9327cc (diff) | |
download | meson-56f7e5c74f54d31b405fe1c4289a406ef826b757.zip meson-56f7e5c74f54d31b405fe1c4289a406ef826b757.tar.gz meson-56f7e5c74f54d31b405fe1c4289a406ef826b757.tar.bz2 |
coredata: Correctly handle receiving a pipe for native/cross files
* coredata: Correctly handle receiving a pipe for native/cross files
In some cases a cross/native file may be a pipe, such as when using bash
process replacement `meson --native-file
<([binaries]llvm-config='/opt/bin/llvm-config')`, for example. In this
case we copy the contents of the pipe into a file in the meson-private
directory so we can create a proper ninja dependency, and be able to
reload the file on --wipe/--reconfigure. This requires some extra
negotiation to preserve these native/cross files.
Fixes #5505
* run_unitests: Add a unit test for native files that are pipes
Using mkfifo.
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/coredata.py | 33 | ||||
-rw-r--r-- | mesonbuild/environment.py | 3 | ||||
-rw-r--r-- | mesonbuild/msetup.py | 57 |
3 files changed, 58 insertions, 35 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 1035488..08e8827 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -346,7 +346,7 @@ _V = TypeVar('_V') class CoreData: - def __init__(self, options): + def __init__(self, options: argparse.Namespace, scratch_dir: str): self.lang_guids = { 'default': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942', 'c': '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942', @@ -364,7 +364,7 @@ class CoreData: self.user_options = {} # : Dict[str, UserOption] self.compiler_options = PerMachine({}, {}) self.base_options = {} # : Dict[str, UserOption] - self.cross_files = self.__load_config_files(options.cross_file, 'cross') + self.cross_files = self.__load_config_files(options, scratch_dir, 'cross') self.compilers = PerMachine(OrderedDict(), OrderedDict()) build_cache = DependencyCache(self.builtins_per_machine, MachineChoice.BUILD) @@ -372,21 +372,42 @@ class CoreData: self.deps = PerMachine(build_cache, host_cache) # type: PerMachine[DependencyCache] self.compiler_check_cache = OrderedDict() # Only to print a warning if it changes between Meson invocations. - self.config_files = self.__load_config_files(options.native_file, 'native') + self.config_files = self.__load_config_files(options, scratch_dir, 'native') self.libdir_cross_fixup() @staticmethod - def __load_config_files(filenames: Optional[List[str]], ftype: str) -> List[str]: + def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: str) -> List[str]: # Need to try and make the passed filenames absolute because when the # files are parsed later we'll have chdir()d. + if ftype == 'cross': + filenames = options.cross_file + else: + filenames = options.native_file + if not filenames: return [] real = [] - for f in filenames: + for i, f in enumerate(filenames): f = os.path.expanduser(os.path.expandvars(f)) if os.path.exists(f): - real.append(os.path.abspath(f)) + if os.path.isfile(f): + real.append(os.path.abspath(f)) + elif os.path.isdir(f): + raise MesonException('Cross and native files must not be directories') + else: + # in this case we've been passed some kind of pipe, copy + # the contents of that file into the meson private (scratch) + # directory so that it can be re-read when wiping/reconfiguring + copy = os.path.join(scratch_dir, '{}.{}.ini'.format(uuid.uuid4(), ftype)) + with open(f, 'r') as rf: + with open(copy, 'w') as wf: + wf.write(rf.read()) + real.append(copy) + + # Also replace the command line argument, as the pipe + # probably wont exist on reconfigure + filenames[i] = copy continue elif sys.platform != 'win32': paths = [ diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 4e2ff92..555c21c 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -403,6 +403,7 @@ class Environment: raise e else: # Just create a fresh coredata in this case + self.scratch_dir = '' self.create_new_coredata(options) ## locally bind some unfrozen configuration @@ -514,7 +515,7 @@ class Environment: # WARNING: Don't use any values from coredata in __init__. It gets # re-initialized with project options by the interpreter during # build file parsing. - self.coredata = coredata.CoreData(options) + self.coredata = coredata.CoreData(options, self.scratch_dir) # Used by the regenchecker script, which runs meson self.coredata.meson_command = mesonlib.meson_command self.first_invocation = True diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 84bcefb..5670b25 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -19,6 +19,9 @@ import os.path import platform import cProfile as profile import argparse +import tempfile +import shutil +import glob from . import environment, interpreter, mesonlib from . import build @@ -60,38 +63,36 @@ class MesonApp: options.sourcedir, options.reconfigure, options.wipe) - if options.wipe: # Make a copy of the cmd line file to make sure we can always # restore that file if anything bad happens. For example if # configuration fails we need to be able to wipe again. - filename = coredata.get_cmd_line_file(self.build_dir) - try: - with open(filename, 'r') as f: - content = f.read() - except FileNotFoundError: - raise MesonException( - 'Cannot find cmd_line.txt. This is probably because this ' - 'build directory was configured with a meson version < 0.49.0.') - - coredata.read_cmd_line_file(self.build_dir, options) - - try: - # Don't delete the whole tree, just all of the files and - # folders in the tree. Otherwise calling wipe form the builddir - # will cause a crash - for l in os.listdir(self.build_dir): - l = os.path.join(self.build_dir, l) - if os.path.isdir(l): - mesonlib.windows_proof_rmtree(l) - else: - mesonlib.windows_proof_rm(l) - finally: - # Restore the file - path = os.path.dirname(filename) - os.makedirs(path, exist_ok=True) - with open(filename, 'w') as f: - f.write(content) + restore = [] + with tempfile.TemporaryDirectory() as d: + for filename in [coredata.get_cmd_line_file(self.build_dir)] + glob.glob(os.path.join(self.build_dir, environment.Environment.private_dir, '*.ini')): + try: + restore.append((shutil.copy(filename, d), filename)) + except FileNotFoundError: + raise MesonException( + 'Cannot find cmd_line.txt. This is probably because this ' + 'build directory was configured with a meson version < 0.49.0.') + + coredata.read_cmd_line_file(self.build_dir, options) + + try: + # Don't delete the whole tree, just all of the files and + # folders in the tree. Otherwise calling wipe form the builddir + # will cause a crash + for l in os.listdir(self.build_dir): + l = os.path.join(self.build_dir, l) + if os.path.isdir(l): + mesonlib.windows_proof_rmtree(l) + else: + mesonlib.windows_proof_rm(l) + finally: + for b, f in restore: + os.makedirs(os.path.dirname(f), exist_ok=True) + shutil.move(b, f) self.options = options |