diff options
Diffstat (limited to 'mesonbuild/scripts/externalproject.py')
-rw-r--r-- | mesonbuild/scripts/externalproject.py | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/mesonbuild/scripts/externalproject.py b/mesonbuild/scripts/externalproject.py new file mode 100644 index 0000000..17c2251 --- /dev/null +++ b/mesonbuild/scripts/externalproject.py @@ -0,0 +1,116 @@ +# Copyright 2019 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. +from __future__ import annotations + +import os +import argparse +import multiprocessing +import subprocess +from pathlib import Path +import typing as T + +from ..mesonlib import Popen_safe, split_args + +class ExternalProject: + def __init__(self, options: argparse.Namespace): + self.name = options.name + self.src_dir = options.srcdir + self.build_dir = options.builddir + self.install_dir = options.installdir + self.log_dir = options.logdir + self.verbose = options.verbose + self.stampfile = options.stampfile + self.depfile = options.depfile + self.make = split_args(options.make) + + def write_depfile(self) -> None: + with open(self.depfile, 'w', encoding='utf-8') as f: + f.write(f'{self.stampfile}: \\\n') + for dirpath, dirnames, filenames in os.walk(self.src_dir): + dirnames[:] = [d for d in dirnames if not d.startswith('.')] + for fname in filenames: + if fname.startswith('.'): + continue + path = Path(dirpath, fname) + f.write(' {} \\\n'.format(path.as_posix().replace(' ', '\\ '))) + + def write_stampfile(self) -> None: + with open(self.stampfile, 'w', encoding='utf-8'): + pass + + def supports_jobs_flag(self) -> bool: + p, o, e = Popen_safe(self.make + ['--version']) + if p.returncode == 0 and ('GNU Make' in o or 'waf' in o): + return True + return False + + def build(self) -> int: + make_cmd = self.make.copy() + if self.supports_jobs_flag(): + make_cmd.append(f'-j{multiprocessing.cpu_count()}') + rc = self._run('build', make_cmd) + if rc != 0: + return rc + + install_cmd = self.make.copy() + install_env = {} + install_env['DESTDIR'] = self.install_dir + install_cmd.append('install') + rc = self._run('install', install_cmd, install_env) + if rc != 0: + return rc + + self.write_depfile() + self.write_stampfile() + + return 0 + + def _run(self, step: str, command: T.List[str], env: T.Optional[T.Dict[str, str]] = None) -> int: + m = 'Running command ' + str(command) + ' in directory ' + str(self.build_dir) + '\n' + log_filename = Path(self.log_dir, f'{self.name}-{step}.log') + output = None + if not self.verbose: + output = open(log_filename, 'w', encoding='utf-8') + output.write(m + '\n') + output.flush() + else: + print(m) + run_env = os.environ.copy() + if env: + run_env.update(env) + p, o, e = Popen_safe(command, stderr=subprocess.STDOUT, stdout=output, + cwd=self.build_dir, + env=run_env) + if p.returncode != 0: + m = f'{step} step returned error code {p.returncode}.' + if not self.verbose: + m += '\nSee logs: ' + str(log_filename) + print(m) + return p.returncode + +def run(args: T.List[str]) -> int: + parser = argparse.ArgumentParser() + parser.add_argument('--name') + parser.add_argument('--srcdir') + parser.add_argument('--builddir') + parser.add_argument('--installdir') + parser.add_argument('--logdir') + parser.add_argument('--make') + parser.add_argument('--verbose', action='store_true') + parser.add_argument('stampfile') + parser.add_argument('depfile') + + options = parser.parse_args(args) + ep = ExternalProject(options) + return ep.build() |