diff --git a/build-system/Make/BuildEnvironment.py b/build-system/Make/BuildEnvironment.py index 0769f580bb..49d7da60f5 100644 --- a/build-system/Make/BuildEnvironment.py +++ b/build-system/Make/BuildEnvironment.py @@ -17,9 +17,24 @@ def get_clean_env(): return clean_env +def resolve_executable(program): + def is_executable(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + for path in get_clean_env()["PATH"].split(os.pathsep): + executable_file = os.path.join(path, program) + if is_executable(executable_file): + return executable_file + return None + + def run_executable_with_output(path, arguments): + executable_path = resolve_executable(path) + if executable_path is None: + raise Exception('Could not resolve {} to a valid executable file'.format(path)) + process = subprocess.Popen( - [path] + arguments, + [executable_path] + arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=get_clean_env() @@ -29,8 +44,16 @@ def run_executable_with_output(path, arguments): return output_string -def call_executable(arguments): - subprocess.check_call(arguments, env=get_clean_env()) +def call_executable(arguments, use_clean_environment=True): + executable_path = resolve_executable(arguments[0]) + if executable_path is None: + raise Exception('Could not resolve {} to a valid executable file'.format(arguments[0])) + + if use_clean_environment: + resolved_env = get_clean_env() + else: + resolved_env = os.environ + subprocess.check_call([executable_path] + arguments[1:], env=resolved_env) def get_bazel_version(bazel_path): @@ -73,11 +96,14 @@ class BuildEnvironment: override_bazel_version, override_xcode_version ): - self.base_path = base_path - self.bazel_path = bazel_path - self.bazel_x86_64_path = bazel_x86_64_path + self.base_path = os.path.expanduser(base_path) + self.bazel_path = os.path.expanduser(bazel_path) + if bazel_x86_64_path is not None: + self.bazel_x86_64_path = os.path.expanduser(bazel_x86_64_path) + else: + self.bazel_x86_64_path = None - configuration_path = os.path.join(base_path, 'versions.json') + configuration_path = os.path.join(self.base_path, 'versions.json') with open(configuration_path) as file: configuration_dict = json.load(file) if configuration_dict['bazel'] is None: diff --git a/build-system/Make/Make.py b/build-system/Make/Make.py index 2e6878a95c..d7d5c18e7f 100644 --- a/build-system/Make/Make.py +++ b/build-system/Make/Make.py @@ -2,10 +2,11 @@ import argparse import os +import shlex import sys import tempfile -from BuildEnvironment import is_apple_silicon, call_executable, BuildEnvironment +from BuildEnvironment import is_apple_silicon, resolve_executable, call_executable, BuildEnvironment from ProjectGeneration import generate @@ -224,15 +225,21 @@ def clean(arguments): def resolve_configuration(bazel_command_line: BazelCommandLine, arguments): if arguments.configurationGenerator is not None: - if not os.path.isfile(arguments.configurationGenerator): - print('{} is not a valid executable'.format(arguments.configurationGenerator)) + configuration_generator_arguments = shlex.split(arguments.configurationGenerator) + + configuration_generator_executable = resolve_executable(configuration_generator_arguments[0]) + + if configuration_generator_executable is None: + print('{} is not a valid executable'.format(configuration_generator_arguments[0])) exit(1) temp_configuration_path = tempfile.mkdtemp() - call_executable([ - arguments.configurationGenerator, - temp_configuration_path - ]) + + resolved_configuration_generator_arguments = [configuration_generator_executable] + resolved_configuration_generator_arguments += configuration_generator_arguments[1:] + resolved_configuration_generator_arguments += [temp_configuration_path] + + call_executable(resolved_configuration_generator_arguments, use_clean_environment=False) print('TelegramBuild: using generated configuration in {}'.format(temp_configuration_path)) bazel_command_line.set_configuration_path(temp_configuration_path) @@ -306,12 +313,14 @@ def add_project_and_build_common_arguments(current_parser: argparse.ArgumentPars group.add_argument( '--configurationGenerator', help=''' - Path to an executable that will generate configuration data + A command line invocation that will dynamically generate the configuration data (project constants and provisioning profiles). - The executable will be invoked with one parameter — path to the destination directory. + The expression will be parsed according to the shell parsing rules into program and arguments parts. + The program will be then invoked with the given arguments plus the path to the output directory. See build-system/generate-configuration.sh for an example. + Example: --configurationGenerator="sh ~/my_script.sh argument1" ''', - metavar='path' + metavar='command' )