# Copyright 2020 The IREE Authors # # Licensed under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # This configure script wraps a normal CMake configure of the project for use # in CI pipelines, doing some sanity checks, discovery and work-arounding. # This future is needed to print Python2 EOL message from __future__ import print_function import sys if sys.version_info < (3,): print("Python 2 has reached end-of-life and is no longer supported.") sys.exit(-1) if sys.platform == "win32" and sys.maxsize.bit_length() == 31: print( "32-bit Windows Python runtime is not supported. Please switch to 64-bit Python." ) sys.exit(-1) import importlib import json import os import platform import subprocess import sysconfig import tempfile is_windows = platform.system() == "Windows" def display_help(): print("Syntax: python build_tools/cmake/cmake_ci.py [--install|--build] ...") print("If neither --install or --build are the first argument, then it is ") print("assumed to be a generate invocation") mode = "generate" if len(sys.argv) < 2: display_help() sys.exit(1) if sys.argv[1] == "--install": mode = "install" elif sys.argv[1] == "--build": mode = "build" def report(*args): print("--", *args) def get_setting(varname, default_value): value = os.environ.get(varname) if value is None: return default_value return value def get_bool_setting(varname, default_value): value = get_setting(varname, default_value) if value is True or value is False: return value return value == "" or value == "ON" or value == "1" def which(thefile): path = os.environ.get("PATH", os.defpath).split(os.pathsep) for d in path: fname = os.path.join(d, thefile) fnames = [fname] if sys.platform == "win32": exts = os.environ.get("PATHEXT", "").split(os.pathsep) fnames += [fname + ext for ext in exts] for name in fnames: if os.access(name, os.F_OK | os.X_OK) and not os.path.isdir(name): return name return None def use_tool_path(toolname, varname=None): if not varname: varname = toolname.upper() value = get_setting(f"USE_{varname}", "ON") if value.upper() == "OFF": return None if value.upper() == "ON" or value == "": return which(toolname) if os.access(value, os.F_OK | os.X_OK) and not os.path.isdir(value): return value ### Detect cmake. use_cmake = use_tool_path("cmake") or "cmake" cmake_command_prefix = [use_cmake] cmake_environ = os.environ def cmake_commandline(args): return cmake_command_prefix + args if is_windows: # Bazel needs msys bash and TensorFlow will melt down and cry if it finds # system bash. Because, of course it will. # Note that we don't set this as a CMake option because it may have spaces # in the path, use backslashes or various other things that get corrupted # in the five or six layers of shoddy string transformations between here # and where it gets used. bash_exe = which("bash") report("Found Windows bash:", bash_exe) report( "NOTE: If the above is system32 bash and you are using bazel to build " "TensorFlow, you are going to have a bad time. Suggest being explicit " "adding the correct directory to your path. I'm really sorry. " "I didn't make this mess... just the messenger" ) report(f'Full path = {os.environ.get("PATH")}') def invoke_generate(): ############################################################################## # Figure out where we are and where we are going. ############################################################################## repo_root = os.path.abspath( get_setting("REPO_DIR", os.path.join(os.path.dirname(__file__), "..", "..")) ) report(f"Using REPO_DIR = {repo_root}") ############################################################################## # Load version_info.json ############################################################################## def load_version_info(): with open(os.path.join(repo_root, "version_info.json"), "rt") as f: return json.load(f) try: version_info = load_version_info() except FileNotFoundError: report("version_info.json found") version_info = {} ############################################################################## # CMake configure. ############################################################################## cmake_args = [ f"-S{repo_root}", f"-DPython3_EXECUTABLE:FILEPATH={sys.executable}", # The old python package settings should not be needed, but since there # can be configuration races between packages that use both mechanisms, # be explicit. f"-DPYTHON_EXECUTABLE:FILEPATH={sys.executable}", f'-DPython3_INCLUDE_DIR:PATH={sysconfig.get_path("include")}', f'-DPYTHON_INCLUDE_DIR:PATH={sysconfig.get_path("include")}', f'-DIREE_RELEASE_PACKAGE_SUFFIX:STRING={version_info.get("package-suffix") or ""}', f'-DIREE_RELEASE_VERSION:STRING={version_info.get("package-version") or "0.0.1a1"}', f'-DIREE_RELEASE_REVISION:STRING={version_info.get("iree-revision") or "HEAD"}', ] ### Detect generator. if use_tool_path("ninja"): report("Using ninja") cmake_args.append("-GNinja") elif is_windows: cmake_args.extend(["-G", "NMake Makefiles"]) # Detect other build tools. use_ccache = use_tool_path("ccache") if not is_windows and use_ccache: report(f"Using ccache {use_ccache}") cmake_args.append(f"-DCMAKE_CXX_COMPILER_LAUNCHER={use_ccache}") # Clang use_clang = use_tool_path("clang") if not is_windows and use_clang: report(f"Using clang {use_clang}") cmake_args.append(f"-DCMAKE_C_COMPILER={use_clang}") use_clangcpp = use_tool_path("clang++", "CLANGCPP") if not is_windows and use_clangcpp: report(f"Using clang++ {use_clangcpp}") cmake_args.append(f"-DCMAKE_CXX_COMPILER={use_clangcpp}") # LLD use_lld = use_tool_path("lld") if not is_windows and use_lld: report(f"Using linker {use_lld}") cmake_args.append("-DIREE_ENABLE_LLD=ON") cmake_args.extend(sys.argv[1:]) report(f'Running cmake (generate): {" ".join(cmake_args)}') subprocess.check_call(cmake_commandline(cmake_args), env=cmake_environ) # Select which mode. if mode == "generate": invoke_generate() else: # Just pass-through. cmake_args = cmake_commandline(sys.argv[1:]) report("Invoke CMake:", " ".join(cmake_args)) subprocess.check_call(cmake_args, env=cmake_environ)