1af6a4c17SAlex Richardson#!/usr/bin/env python3 2af6a4c17SAlex Richardson# PYTHON_ARGCOMPLETE_OKAY 3af6a4c17SAlex Richardson# - 44d846d26SWarner Losh# SPDX-License-Identifier: BSD-2-Clause 5af6a4c17SAlex Richardson# 6af6a4c17SAlex Richardson# Copyright (c) 2018 Alex Richardson <arichardson@FreeBSD.org> 7af6a4c17SAlex Richardson# 8af6a4c17SAlex Richardson# Redistribution and use in source and binary forms, with or without 9af6a4c17SAlex Richardson# modification, are permitted provided that the following conditions 10af6a4c17SAlex Richardson# are met: 11af6a4c17SAlex Richardson# 1. Redistributions of source code must retain the above copyright 12af6a4c17SAlex Richardson# notice, this list of conditions and the following disclaimer. 13af6a4c17SAlex Richardson# 2. Redistributions in binary form must reproduce the above copyright 14af6a4c17SAlex Richardson# notice, this list of conditions and the following disclaimer in the 15af6a4c17SAlex Richardson# documentation and/or other materials provided with the distribution. 16af6a4c17SAlex Richardson# 17af6a4c17SAlex Richardson# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18af6a4c17SAlex Richardson# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19af6a4c17SAlex Richardson# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20af6a4c17SAlex Richardson# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21af6a4c17SAlex Richardson# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22af6a4c17SAlex Richardson# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23af6a4c17SAlex Richardson# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24af6a4c17SAlex Richardson# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25af6a4c17SAlex Richardson# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26af6a4c17SAlex Richardson# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27af6a4c17SAlex Richardson# SUCH DAMAGE. 28af6a4c17SAlex Richardson# 29af6a4c17SAlex Richardson# 30af6a4c17SAlex Richardson 31af6a4c17SAlex Richardson# This script makes it easier to build on non-FreeBSD systems by bootstrapping 32af6a4c17SAlex Richardson# bmake and inferring required compiler variables. 33af6a4c17SAlex Richardson# 34af6a4c17SAlex Richardson# On FreeBSD you can use it the same way as just calling make: 35af6a4c17SAlex Richardson# `MAKEOBJDIRPREFIX=~/obj ./tools/build/make.py buildworld -DWITH_FOO` 36af6a4c17SAlex Richardson# 3781fc74fdSJohn Baldwin# On Linux and MacOS you may need to explicitly indicate the cross toolchain 3881fc74fdSJohn Baldwin# to use. You can do this by: 3981fc74fdSJohn Baldwin# - setting XCC/XCXX/XLD/XCPP to the paths of each tool 4081fc74fdSJohn Baldwin# - using --cross-bindir to specify the path to the cross-compiler bindir: 41af6a4c17SAlex Richardson# `MAKEOBJDIRPREFIX=~/obj ./tools/build/make.py 42af6a4c17SAlex Richardson# --cross-bindir=/path/to/cross/compiler buildworld -DWITH_FOO TARGET=foo 43af6a4c17SAlex Richardson# TARGET_ARCH=bar` 4481fc74fdSJohn Baldwin# - using --cross-toolchain to specify the package containing the cross-compiler 4581fc74fdSJohn Baldwin# (MacOS only currently): 4681fc74fdSJohn Baldwin# `MAKEOBJDIRPREFIX=~/obj ./tools/build/make.py 4781fc74fdSJohn Baldwin# --cross-toolchain=llvm@NN buildworld -DWITH_FOO TARGET=foo 4881fc74fdSJohn Baldwin# TARGET_ARCH=bar` 4981fc74fdSJohn Baldwin# 5081fc74fdSJohn Baldwin# On MacOS, this tool will search for an llvm toolchain installed via brew and 5181fc74fdSJohn Baldwin# use it as the cross toolchain if an explicit toolchain is not specified. 5281fc74fdSJohn Baldwin 53af6a4c17SAlex Richardsonimport argparse 54e68d702bSJohn Baldwinimport functools 55af6a4c17SAlex Richardsonimport os 56af6a4c17SAlex Richardsonimport shlex 57af6a4c17SAlex Richardsonimport shutil 58af6a4c17SAlex Richardsonimport subprocess 59af6a4c17SAlex Richardsonimport sys 60af6a4c17SAlex Richardsonfrom pathlib import Path 61af6a4c17SAlex Richardson 62af6a4c17SAlex Richardson 635157b451SJessica Clarke# List of targets that are independent of TARGET/TARGET_ARCH and thus do not 645157b451SJessica Clarke# need them to be set. Keep in the same order as Makefile documents them (if 655157b451SJessica Clarke# they are documented). 665157b451SJessica Clarkemach_indep_targets = [ 675157b451SJessica Clarke "cleanuniverse", 685157b451SJessica Clarke "universe", 695157b451SJessica Clarke "universe-toolchain", 70edec803cSJessica Clarke "tinderbox", 715157b451SJessica Clarke "worlds", 725157b451SJessica Clarke "kernels", 735157b451SJessica Clarke "kernel-toolchains", 745157b451SJessica Clarke "targets", 755157b451SJessica Clarke "toolchains", 765157b451SJessica Clarke "makeman", 775157b451SJessica Clarke "sysent", 785157b451SJessica Clarke] 795157b451SJessica Clarke 805157b451SJessica Clarke 81af6a4c17SAlex Richardsondef run(cmd, **kwargs): 82af6a4c17SAlex Richardson cmd = list(map(str, cmd)) # convert all Path objects to str 83af6a4c17SAlex Richardson debug("Running", cmd) 84af6a4c17SAlex Richardson subprocess.check_call(cmd, **kwargs) 85af6a4c17SAlex Richardson 86af6a4c17SAlex Richardson 8769cfdc81SJessica Clarke# Always bootstraps in order to control bmake's config to ensure compatibility 88af6a4c17SAlex Richardsondef bootstrap_bmake(source_root, objdir_prefix): 89af6a4c17SAlex Richardson bmake_source_dir = source_root / "contrib/bmake" 90af6a4c17SAlex Richardson bmake_build_dir = objdir_prefix / "bmake-build" 91af6a4c17SAlex Richardson bmake_install_dir = objdir_prefix / "bmake-install" 92af6a4c17SAlex Richardson bmake_binary = bmake_install_dir / "bin/bmake" 9369cfdc81SJessica Clarke bmake_config = bmake_install_dir / ".make-py-config" 94af6a4c17SAlex Richardson 9569cfdc81SJessica Clarke bmake_source_version = subprocess.run([ 96b771d570SJessica Clarke "sh", "-c", ". \"$0\"/VERSION; echo $_MAKE_VERSION", bmake_source_dir], 97b771d570SJessica Clarke stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip() 9869cfdc81SJessica Clarke try: 9969cfdc81SJessica Clarke bmake_source_version = int(bmake_source_version) 10069cfdc81SJessica Clarke except ValueError: 10169cfdc81SJessica Clarke sys.exit("Invalid source bmake version '" + bmake_source_version + "'") 10269cfdc81SJessica Clarke 10369cfdc81SJessica Clarke bmake_installed_version = 0 10469cfdc81SJessica Clarke if bmake_binary.exists(): 10569cfdc81SJessica Clarke bmake_installed_version = subprocess.run([ 10669cfdc81SJessica Clarke bmake_binary, "-r", "-f", "/dev/null", "-V", "MAKE_VERSION"], 107b771d570SJessica Clarke stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.strip() 10869cfdc81SJessica Clarke try: 10969cfdc81SJessica Clarke bmake_installed_version = int(bmake_installed_version.strip()) 11069cfdc81SJessica Clarke except ValueError: 11169cfdc81SJessica Clarke print("Invalid installed bmake version '" + 11269cfdc81SJessica Clarke bmake_installed_version + "', treating as not present") 113af6a4c17SAlex Richardson 114af6a4c17SAlex Richardson configure_args = [ 11562f243acSJessica Clarke "--with-default-sys-path=.../share/mk:" + 11662f243acSJessica Clarke str(bmake_install_dir / "share/mk"), 117af6a4c17SAlex Richardson "--with-machine=amd64", # TODO? "--with-machine-arch=amd64", 118af6a4c17SAlex Richardson "--without-filemon", "--prefix=" + str(bmake_install_dir)] 11969cfdc81SJessica Clarke 12069cfdc81SJessica Clarke configure_args_str = ' '.join([shlex.quote(x) for x in configure_args]) 12169cfdc81SJessica Clarke if bmake_config.exists(): 12269cfdc81SJessica Clarke last_configure_args_str = bmake_config.read_text() 12369cfdc81SJessica Clarke else: 12469cfdc81SJessica Clarke last_configure_args_str = "" 12569cfdc81SJessica Clarke 12669cfdc81SJessica Clarke debug("Source bmake version: " + str(bmake_source_version)) 12769cfdc81SJessica Clarke debug("Installed bmake version: " + str(bmake_installed_version)) 12869cfdc81SJessica Clarke debug("Configure args: " + configure_args_str) 12969cfdc81SJessica Clarke debug("Last configure args: " + last_configure_args_str) 13069cfdc81SJessica Clarke 13169cfdc81SJessica Clarke if bmake_installed_version == bmake_source_version and \ 13269cfdc81SJessica Clarke configure_args_str == last_configure_args_str: 13369cfdc81SJessica Clarke return bmake_binary 13469cfdc81SJessica Clarke 13569cfdc81SJessica Clarke print("Bootstrapping bmake...") 13669cfdc81SJessica Clarke if bmake_build_dir.exists(): 13769cfdc81SJessica Clarke shutil.rmtree(str(bmake_build_dir)) 13869cfdc81SJessica Clarke if bmake_install_dir.exists(): 13969cfdc81SJessica Clarke shutil.rmtree(str(bmake_install_dir)) 14069cfdc81SJessica Clarke 14169cfdc81SJessica Clarke os.makedirs(str(bmake_build_dir)) 14269cfdc81SJessica Clarke 14369cfdc81SJessica Clarke env = os.environ.copy() 14469cfdc81SJessica Clarke global new_env_vars 14569cfdc81SJessica Clarke env.update(new_env_vars) 14669cfdc81SJessica Clarke 147af6a4c17SAlex Richardson run(["sh", bmake_source_dir / "boot-strap"] + configure_args, 148af6a4c17SAlex Richardson cwd=str(bmake_build_dir), env=env) 149af6a4c17SAlex Richardson run(["sh", bmake_source_dir / "boot-strap", "op=install"] + configure_args, 150af6a4c17SAlex Richardson cwd=str(bmake_build_dir)) 15169cfdc81SJessica Clarke bmake_config.write_text(configure_args_str) 15269cfdc81SJessica Clarke 153af6a4c17SAlex Richardson print("Finished bootstrapping bmake...") 154af6a4c17SAlex Richardson return bmake_binary 155af6a4c17SAlex Richardson 156af6a4c17SAlex Richardson 157af6a4c17SAlex Richardsondef debug(*args, **kwargs): 158af6a4c17SAlex Richardson global parsed_args 159af6a4c17SAlex Richardson if parsed_args.debug: 160af6a4c17SAlex Richardson print(*args, **kwargs) 161af6a4c17SAlex Richardson 162af6a4c17SAlex Richardson 163af6a4c17SAlex Richardsondef is_make_var_set(var): 164af6a4c17SAlex Richardson return any( 165af6a4c17SAlex Richardson x.startswith(var + "=") or x == ("-D" + var) for x in sys.argv[1:]) 166af6a4c17SAlex Richardson 167af6a4c17SAlex Richardson 168af6a4c17SAlex Richardsondef check_required_make_env_var(varname, binary_name, bindir): 169af6a4c17SAlex Richardson global new_env_vars 170af6a4c17SAlex Richardson if os.getenv(varname): 171af6a4c17SAlex Richardson return 172af6a4c17SAlex Richardson if not bindir: 173af6a4c17SAlex Richardson sys.exit("Could not infer value for $" + varname + ". Either set $" + 17481fc74fdSJohn Baldwin varname + " or pass --cross-bindir=/cross/compiler/dir/bin" + 17581fc74fdSJohn Baldwin " or --cross-toolchain=<package>") 176af6a4c17SAlex Richardson # try to infer the path to the tool 177af6a4c17SAlex Richardson guess = os.path.join(bindir, binary_name) 178af6a4c17SAlex Richardson if not os.path.isfile(guess): 179af6a4c17SAlex Richardson sys.exit("Could not infer value for $" + varname + ": " + guess + 180af6a4c17SAlex Richardson " does not exist") 181af6a4c17SAlex Richardson new_env_vars[varname] = guess 182af6a4c17SAlex Richardson debug("Inferred", varname, "as", guess) 183accf9611SUlrich Spörlein global parsed_args 184accf9611SUlrich Spörlein if parsed_args.debug: 185accf9611SUlrich Spörlein run([guess, "--version"]) 186af6a4c17SAlex Richardson 1873b4da25eSJessica Clarke 1882b181156SAlex Richardsondef check_xtool_make_env_var(varname, binary_name): 1892b181156SAlex Richardson # Avoid calling brew --prefix on macOS if all variables are already set: 1902b181156SAlex Richardson if os.getenv(varname): 1912b181156SAlex Richardson return 1922b181156SAlex Richardson global parsed_args 1932b181156SAlex Richardson if parsed_args.cross_bindir is None: 19481fc74fdSJohn Baldwin cross_bindir = cross_toolchain_bindir(binary_name, 19581fc74fdSJohn Baldwin parsed_args.cross_toolchain) 196e68d702bSJohn Baldwin else: 197e68d702bSJohn Baldwin cross_bindir = parsed_args.cross_bindir 1982b181156SAlex Richardson return check_required_make_env_var(varname, binary_name, 199e68d702bSJohn Baldwin cross_bindir) 200af6a4c17SAlex Richardson 2013b4da25eSJessica Clarke 202e68d702bSJohn Baldwin@functools.cache 203e68d702bSJohn Baldwindef brew_prefix(package: str) -> str: 204e68d702bSJohn Baldwin path = subprocess.run(["brew", "--prefix", package], stdout=subprocess.PIPE, 205e68d702bSJohn Baldwin stderr=subprocess.PIPE).stdout.strip() 206e68d702bSJohn Baldwin debug("Inferred", package, "dir as", path) 207e68d702bSJohn Baldwin return path.decode("utf-8") 208e68d702bSJohn Baldwin 209e68d702bSJohn Baldwindef binary_path(bindir: str, binary_name: str) -> "Optional[str]": 210e68d702bSJohn Baldwin try: 211e68d702bSJohn Baldwin if bindir and Path(bindir, "bin", binary_name).exists(): 212e68d702bSJohn Baldwin return str(Path(bindir, "bin")) 213e68d702bSJohn Baldwin except OSError: 214e68d702bSJohn Baldwin pass 215e68d702bSJohn Baldwin return None 216e68d702bSJohn Baldwin 21781fc74fdSJohn Baldwindef cross_toolchain_bindir(binary_name: str, package: "Optional[str]") -> str: 218af6a4c17SAlex Richardson # default to homebrew-installed clang on MacOS if available 219af6a4c17SAlex Richardson if sys.platform.startswith("darwin"): 220af6a4c17SAlex Richardson if shutil.which("brew"): 22181fc74fdSJohn Baldwin if not package: 22281fc74fdSJohn Baldwin package = "llvm" 22381fc74fdSJohn Baldwin bindir = binary_path(brew_prefix(package), binary_name) 224e68d702bSJohn Baldwin if bindir: 225e68d702bSJohn Baldwin return bindir 226e68d702bSJohn Baldwin 227e68d702bSJohn Baldwin # brew installs lld as a separate package for LLVM 19 and later 228e68d702bSJohn Baldwin if binary_name == "ld.lld": 22981fc74fdSJohn Baldwin lld_package = package.replace("llvm", "lld") 23081fc74fdSJohn Baldwin bindir = binary_path(brew_prefix(lld_package), binary_name) 231e68d702bSJohn Baldwin if bindir: 232e68d702bSJohn Baldwin return bindir 233af6a4c17SAlex Richardson return None 234af6a4c17SAlex Richardson 235af6a4c17SAlex Richardson 236af6a4c17SAlex Richardsonif __name__ == "__main__": 237af6a4c17SAlex Richardson parser = argparse.ArgumentParser( 238af6a4c17SAlex Richardson formatter_class=argparse.ArgumentDefaultsHelpFormatter) 239af6a4c17SAlex Richardson parser.add_argument("--host-bindir", 240af6a4c17SAlex Richardson help="Directory to look for cc/c++/cpp/ld to build " 241af6a4c17SAlex Richardson "host (" + sys.platform + ") binaries", 242af6a4c17SAlex Richardson default="/usr/bin") 243a26ace4dSAlex Richardson parser.add_argument("--cross-bindir", default=None, 244af6a4c17SAlex Richardson help="Directory to look for cc/c++/cpp/ld to build " 245af6a4c17SAlex Richardson "target binaries (only needed if XCC/XCPP/XLD " 246af6a4c17SAlex Richardson "are not set)") 247af6a4c17SAlex Richardson parser.add_argument("--cross-compiler-type", choices=("clang", "gcc"), 248af6a4c17SAlex Richardson default="clang", 249af6a4c17SAlex Richardson help="Compiler type to find in --cross-bindir (only " 250af6a4c17SAlex Richardson "needed if XCC/XCPP/XLD are not set)" 251af6a4c17SAlex Richardson "Note: using CC is currently highly experimental") 25281fc74fdSJohn Baldwin parser.add_argument("--cross-toolchain", default=None, 25381fc74fdSJohn Baldwin help="Name of package containing cc/c++/cpp/ld to build " 25481fc74fdSJohn Baldwin "target binaries (only needed if XCC/XCPP/XLD " 25581fc74fdSJohn Baldwin "are not set)") 256af6a4c17SAlex Richardson parser.add_argument("--host-compiler-type", choices=("cc", "clang", "gcc"), 257af6a4c17SAlex Richardson default="cc", 258af6a4c17SAlex Richardson help="Compiler type to find in --host-bindir (only " 259af6a4c17SAlex Richardson "needed if CC/CPP/CXX are not set). ") 260af6a4c17SAlex Richardson parser.add_argument("--debug", action="store_true", 261af6a4c17SAlex Richardson help="Print information on inferred env vars") 26231ba4ce8SAlex Richardson parser.add_argument("--bootstrap-toolchain", action="store_true", 26331ba4ce8SAlex Richardson help="Bootstrap the toolchain instead of using an " 26431ba4ce8SAlex Richardson "external one (experimental and not recommended)") 265af6a4c17SAlex Richardson parser.add_argument("--clean", action="store_true", 266af6a4c17SAlex Richardson help="Do a clean rebuild instead of building with " 26743e083beSAlex Richardson "-DWITHOUT_CLEAN") 268af6a4c17SAlex Richardson parser.add_argument("--no-clean", action="store_false", dest="clean", 269af6a4c17SAlex Richardson help="Do a clean rebuild instead of building with " 27043e083beSAlex Richardson "-DWITHOUT_CLEAN") 271af6a4c17SAlex Richardson try: 272af6a4c17SAlex Richardson import argcomplete # bash completion: 273af6a4c17SAlex Richardson 274af6a4c17SAlex Richardson argcomplete.autocomplete(parser) 275af6a4c17SAlex Richardson except ImportError: 276af6a4c17SAlex Richardson pass 277af6a4c17SAlex Richardson parsed_args, bmake_args = parser.parse_known_args() 278af6a4c17SAlex Richardson 279af6a4c17SAlex Richardson MAKEOBJDIRPREFIX = os.getenv("MAKEOBJDIRPREFIX") 280af6a4c17SAlex Richardson if not MAKEOBJDIRPREFIX: 281af6a4c17SAlex Richardson sys.exit("MAKEOBJDIRPREFIX is not set, cannot continue!") 282af6a4c17SAlex Richardson if not Path(MAKEOBJDIRPREFIX).is_dir(): 283af6a4c17SAlex Richardson sys.exit( 284d55de30eSJose Luis Duran "Chosen MAKEOBJDIRPREFIX=" + MAKEOBJDIRPREFIX + " doesn't exist!") 285af6a4c17SAlex Richardson objdir_prefix = Path(MAKEOBJDIRPREFIX).absolute() 286af6a4c17SAlex Richardson source_root = Path(__file__).absolute().parent.parent.parent 287af6a4c17SAlex Richardson 288af6a4c17SAlex Richardson new_env_vars = {} 289af6a4c17SAlex Richardson if not sys.platform.startswith("freebsd"): 290af6a4c17SAlex Richardson if not is_make_var_set("TARGET") or not is_make_var_set("TARGET_ARCH"): 2915157b451SJessica Clarke if not set(sys.argv).intersection(set(mach_indep_targets)): 292af6a4c17SAlex Richardson sys.exit("TARGET= and TARGET_ARCH= must be set explicitly " 293af6a4c17SAlex Richardson "when building on non-FreeBSD") 29431ba4ce8SAlex Richardson if not parsed_args.bootstrap_toolchain: 295af6a4c17SAlex Richardson # infer values for CC/CXX/CPP 296af6a4c17SAlex Richardson if parsed_args.host_compiler_type == "gcc": 297af6a4c17SAlex Richardson default_cc, default_cxx, default_cpp = ("gcc", "g++", "cpp") 298accf9611SUlrich Spörlein # FIXME: this should take values like `clang-9` and then look for 299accf9611SUlrich Spörlein # clang-cpp-9, etc. Would alleviate the need to set the bindir on 300accf9611SUlrich Spörlein # ubuntu/debian at least. 301af6a4c17SAlex Richardson elif parsed_args.host_compiler_type == "clang": 302af6a4c17SAlex Richardson default_cc, default_cxx, default_cpp = ( 303af6a4c17SAlex Richardson "clang", "clang++", "clang-cpp") 304af6a4c17SAlex Richardson else: 305af6a4c17SAlex Richardson default_cc, default_cxx, default_cpp = ("cc", "c++", "cpp") 306af6a4c17SAlex Richardson 307af6a4c17SAlex Richardson check_required_make_env_var("CC", default_cc, parsed_args.host_bindir) 308af6a4c17SAlex Richardson check_required_make_env_var("CXX", default_cxx, 309af6a4c17SAlex Richardson parsed_args.host_bindir) 310af6a4c17SAlex Richardson check_required_make_env_var("CPP", default_cpp, 311af6a4c17SAlex Richardson parsed_args.host_bindir) 312af6a4c17SAlex Richardson # Using the default value for LD is fine (but not for XLD!) 313af6a4c17SAlex Richardson 314af6a4c17SAlex Richardson # On non-FreeBSD we need to explicitly pass XCC/XLD/X_COMPILER_TYPE 315d037edf8SAlex Richardson use_cross_gcc = parsed_args.cross_compiler_type == "gcc" 3162b181156SAlex Richardson check_xtool_make_env_var("XCC", "gcc" if use_cross_gcc else "clang") 3172b181156SAlex Richardson check_xtool_make_env_var("XCXX", "g++" if use_cross_gcc else "clang++") 3182b181156SAlex Richardson check_xtool_make_env_var("XCPP", 3192b181156SAlex Richardson "cpp" if use_cross_gcc else "clang-cpp") 3202b181156SAlex Richardson check_xtool_make_env_var("XLD", "ld" if use_cross_gcc else "ld.lld") 321d037edf8SAlex Richardson 322d037edf8SAlex Richardson # We also need to set STRIPBIN if there is no working strip binary 323d037edf8SAlex Richardson # in $PATH. 324d037edf8SAlex Richardson if not shutil.which("strip"): 325d037edf8SAlex Richardson if sys.platform.startswith("darwin"): 326d037edf8SAlex Richardson # On macOS systems we have to use /usr/bin/strip. 32788db1cc9SAlex Richardson sys.exit("Cannot find required tool 'strip'. Please install " 32888db1cc9SAlex Richardson "the host compiler and command line tools.") 329d037edf8SAlex Richardson if parsed_args.host_compiler_type == "clang": 330d037edf8SAlex Richardson strip_binary = "llvm-strip" 331d037edf8SAlex Richardson else: 332d037edf8SAlex Richardson strip_binary = "strip" 333d037edf8SAlex Richardson check_required_make_env_var("STRIPBIN", strip_binary, 3342b181156SAlex Richardson parsed_args.host_bindir) 335d037edf8SAlex Richardson if os.getenv("STRIPBIN") or "STRIPBIN" in new_env_vars: 336d037edf8SAlex Richardson # If we are setting STRIPBIN, we have to set XSTRIPBIN to the 337d037edf8SAlex Richardson # default if it is not set otherwise already. 338d037edf8SAlex Richardson if not os.getenv("XSTRIPBIN") and not is_make_var_set("XSTRIPBIN"): 339d037edf8SAlex Richardson # Use the bootstrapped elftoolchain strip: 340d037edf8SAlex Richardson new_env_vars["XSTRIPBIN"] = "strip" 341af6a4c17SAlex Richardson 342af6a4c17SAlex Richardson bmake_binary = bootstrap_bmake(source_root, objdir_prefix) 343af6a4c17SAlex Richardson # at -j1 cleandir+obj is unbearably slow. AUTO_OBJ helps a lot 344af6a4c17SAlex Richardson debug("Adding -DWITH_AUTO_OBJ") 345af6a4c17SAlex Richardson bmake_args.append("-DWITH_AUTO_OBJ") 346af6a4c17SAlex Richardson if parsed_args.clean is False: 347af6a4c17SAlex Richardson bmake_args.append("-DWITHOUT_CLEAN") 348af6a4c17SAlex Richardson if (parsed_args.clean is None and not is_make_var_set("NO_CLEAN") 349af6a4c17SAlex Richardson and not is_make_var_set("WITHOUT_CLEAN")): 350af6a4c17SAlex Richardson # Avoid accidentally deleting all of the build tree and wasting lots of 351af6a4c17SAlex Richardson # time cleaning directories instead of just doing a rm -rf ${.OBJDIR} 3523b4da25eSJessica Clarke want_clean = input("You did not set -DWITHOUT_CLEAN/--(no-)clean." 353af6a4c17SAlex Richardson " Did you really mean to do a clean build? y/[N] ") 354af6a4c17SAlex Richardson if not want_clean.lower().startswith("y"): 35543e083beSAlex Richardson bmake_args.append("-DWITHOUT_CLEAN") 356af6a4c17SAlex Richardson 357af6a4c17SAlex Richardson env_cmd_str = " ".join( 358af6a4c17SAlex Richardson shlex.quote(k + "=" + v) for k, v in new_env_vars.items()) 359af6a4c17SAlex Richardson make_cmd_str = " ".join( 360af6a4c17SAlex Richardson shlex.quote(s) for s in [str(bmake_binary)] + bmake_args) 361af6a4c17SAlex Richardson debug("Running `env ", env_cmd_str, " ", make_cmd_str, "`", sep="") 362af6a4c17SAlex Richardson os.environ.update(new_env_vars) 363b7ac17b4SAlfredo Dal'Ava Junior 364b7ac17b4SAlfredo Dal'Ava Junior # Fedora defines bash function wrapper for some shell commands and this 365b7ac17b4SAlfredo Dal'Ava Junior # makes 'which <command>' return the function's source code instead of 366b7ac17b4SAlfredo Dal'Ava Junior # the binary path. Undefine it to restore the original behavior. 367b7ac17b4SAlfredo Dal'Ava Junior os.unsetenv("BASH_FUNC_which%%") 368b7ac17b4SAlfredo Dal'Ava Junior os.unsetenv("BASH_FUNC_ml%%") 369b7ac17b4SAlfredo Dal'Ava Junior os.unsetenv("BASH_FUNC_module%%") 370b7ac17b4SAlfredo Dal'Ava Junior 371af6a4c17SAlex Richardson os.chdir(str(source_root)) 372af6a4c17SAlex Richardson os.execv(str(bmake_binary), [str(bmake_binary)] + bmake_args) 373