mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +00:00
bfce5b9415
Moving to Python to make Windows build scripts more maintainable. It's intended to be a drop-in replacement, so it should be possible to just switch `.\build-deps.cmd` to `python build-deps.py`, keeping exactly the same arguments and behaviour will be the same. `build-deps.cmd` is deprecated, but not yet removed, but will be shortly after more testing. Other batch files will be migrated to Python shortly after too.
291 lines
12 KiB
Python
291 lines
12 KiB
Python
# /// script
|
|
# [tool.ty.environment]
|
|
# # Lets ty resolve sibling imports (common, installers, etc).
|
|
# root = ["."]
|
|
# ///
|
|
###############################################################################
|
|
# #
|
|
# This file is part of IfcOpenShell. #
|
|
# #
|
|
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
|
# it under the terms of the Lesser GNU General Public License as published by #
|
|
# the Free Software Foundation, either version 3.0 of the License, or #
|
|
# (at your option) any later version. #
|
|
# #
|
|
# IfcOpenShell is distributed in the hope that it will be useful, #
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
# Lesser GNU General Public License for more details. #
|
|
# #
|
|
# You should have received a copy of the Lesser GNU General Public License #
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
|
# #
|
|
###############################################################################
|
|
#
|
|
import argparse
|
|
import multiprocessing
|
|
import os
|
|
import shutil
|
|
import sys
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
from typing import NamedTuple
|
|
|
|
from common import (
|
|
BUILD_CFG_DEFAULT,
|
|
BUILD_CFGS,
|
|
BUILD_TYPE_DEFAULT,
|
|
BUILD_TYPES,
|
|
PROJECT_NAME,
|
|
REPO_ROOT,
|
|
SCRIPT_DIR,
|
|
BuildCfg,
|
|
BuildDepsCache,
|
|
BuildType,
|
|
C,
|
|
colorize,
|
|
is_on_off,
|
|
logger,
|
|
require_command,
|
|
validate_cmake_version,
|
|
)
|
|
from installers import (
|
|
install_boost,
|
|
install_ccache,
|
|
install_cgal,
|
|
install_eigen,
|
|
install_json,
|
|
install_manifold,
|
|
install_mpfr,
|
|
install_mpir,
|
|
install_nuget,
|
|
install_occt,
|
|
install_opencollada,
|
|
install_proj,
|
|
install_python,
|
|
install_qt6,
|
|
install_rocksdb,
|
|
install_swig,
|
|
install_zstd,
|
|
)
|
|
from vs_cfg import VsCfgResult, get_vs_var, vs_cfg
|
|
|
|
|
|
class Args(NamedTuple):
|
|
generator: str | None
|
|
build_type_cfg: BuildCfg
|
|
build_type: BuildType
|
|
reuse_boost: bool
|
|
|
|
|
|
def print_build_config(
|
|
vs_cfg_vars: VsCfgResult,
|
|
build_type_cfg: BuildCfg,
|
|
build_type: BuildType,
|
|
ifcos_install_python: bool,
|
|
ifcos_install_qt6: bool,
|
|
ifcos_num_build_procs: int,
|
|
) -> None:
|
|
def field(text: str) -> str:
|
|
return colorize(text, C.PURPLE)
|
|
|
|
logger.info(colorize("Script configuration:", C.GREEN))
|
|
logger.info(field(f"* CMake Generator\t= '{vs_cfg_vars.generator.name}'"))
|
|
logger.info(" - Passed to CMake -G option.")
|
|
logger.info(field(f"* Target Platform\t= {vs_cfg_vars.vs_platform}"))
|
|
logger.info(" - Whether were doing 32-bit (Win32) or 64-bit (x64, ARM64) build. Passed to CMake -A option.")
|
|
logger.info(field(f"* Target Toolset Override\t= {vs_cfg_vars.vs_toolset_override}"))
|
|
logger.info(" - Passed to CMake -T option.")
|
|
logger.info(field(f"* Dependency Directory\t= {vs_cfg_vars.deps_dir}"))
|
|
logger.info(f" - The directory where {PROJECT_NAME} dependencies are fetched and built.")
|
|
logger.info(field(f"* Installation Directory = {vs_cfg_vars.install_dir}"))
|
|
logger.info(f" - The directory where {PROJECT_NAME} dependencies are installed.")
|
|
logger.info(field(f"* Build Config Type\t= {build_type_cfg}"))
|
|
logger.info(" - The used build configuration type for the dependencies.")
|
|
logger.info(" Defaults to RelWithDebInfo if not specified.")
|
|
if build_type_cfg == "MinSizeRel":
|
|
logger.warning(" WARNING: MinSizeRel build can suffer from a significant performance loss.")
|
|
logger.info(field(f"* Build Type\t\t= {build_type}"))
|
|
logger.info(" - The used build type for the dependencies (Build, Rebuild, Clean).")
|
|
logger.info(" Defaults to Build if not specified.")
|
|
logger.info(field(f"* IFCOS_INSTALL_PYTHON\t= {ifcos_install_python}"))
|
|
logger.info(" - Download and install Python.")
|
|
logger.info(" Set to something other than TRUE if you wish to use an already installed version of Python.")
|
|
logger.info(
|
|
" But then you'll need to set PYTHONHOME env variable to your Python installation before running run-cmake.bat"
|
|
)
|
|
logger.info(" to your Python installation path.")
|
|
logger.info(field(f"* IFCOS_INSTALL_QT6\t= {ifcos_install_qt6}"))
|
|
logger.info(" - Download and install Qt6 using aqtinstall.")
|
|
logger.info(" Set to something other than TRUE if you wish to use an already installed version of Qt6.")
|
|
logger.info(
|
|
" But then you'll need to set QT_DIR env variable to your Qt6 installation before running run-cmake.bat."
|
|
)
|
|
logger.info(field(f"* IFCOS_NUM_BUILD_PROCS\t= {ifcos_num_build_procs}"))
|
|
logger.info(" - How many MSBuild.exe processes may be run in parallel.")
|
|
logger.info(" Defaults to NUMBER_OF_PROCESSORS. Used also by other IfcOpenShell build scripts.\n")
|
|
|
|
|
|
def print_success(start_time: datetime) -> None:
|
|
logger.info("")
|
|
logger.info(colorize(f"{PROJECT_NAME} dependencies built.", C.GREEN))
|
|
|
|
end_time = datetime.now().replace(microsecond=0)
|
|
logger.info("")
|
|
logger.info(f"Build ended at {end_time}. Time elapsed {end_time - start_time}.")
|
|
|
|
|
|
def parse_args() -> Args:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
"generator",
|
|
nargs="?",
|
|
default=None,
|
|
help=(
|
|
"CMake generator to use. Accepts 3 forms: "
|
|
"(1) omitted - deduced from the active Visual Studio environment; "
|
|
"(2) shorthand, e.g. 'vs2022', 'vs2022-x64', 'vs2019-x86-v141' - optionally provide platform/toolset "
|
|
"using the suffix; "
|
|
"(3) full CMake generator name, e.g. 'Visual Studio 17 2022'."
|
|
),
|
|
)
|
|
parser.add_argument(
|
|
"build_type_cfg",
|
|
nargs="?",
|
|
default=BUILD_CFG_DEFAULT,
|
|
choices=BUILD_CFGS,
|
|
help="Build configuration type. Uses default if not provided.",
|
|
)
|
|
parser.add_argument(
|
|
"build_type",
|
|
nargs="?",
|
|
default=BUILD_TYPE_DEFAULT,
|
|
choices=BUILD_TYPES,
|
|
help="Build type.",
|
|
)
|
|
parser.add_argument(
|
|
"--log-level",
|
|
# TODO: relax default to INFO once things get more stable.
|
|
default="DEBUG",
|
|
choices=("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"),
|
|
help="Logging verbosity.",
|
|
)
|
|
parser.add_argument(
|
|
"--reuse-boost",
|
|
action="store_true",
|
|
help=(
|
|
"Skip building Boost if it's already installed from this script's previous runs, instead of always rebuilding it. "
|
|
"Speeds up the build a bit when iterating/debugging this script."
|
|
),
|
|
)
|
|
args = parser.parse_args()
|
|
logger.setLevel(args.log_level)
|
|
return Args(
|
|
generator=args.generator,
|
|
build_type_cfg=args.build_type_cfg,
|
|
build_type=args.build_type,
|
|
reuse_boost=args.reuse_boost,
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
ARGS = parse_args()
|
|
|
|
logger.info(f"This script fetches and builds all {PROJECT_NAME} dependencies\n")
|
|
|
|
if Path.cwd() != SCRIPT_DIR:
|
|
logger.error(f"This script must be run from '{SCRIPT_DIR}'.")
|
|
sys.exit(1)
|
|
|
|
# Make sure vcvarsall.bat is called and dev env set is up.
|
|
get_vs_var("VSINSTALLDIR")
|
|
|
|
# Check for cl.exe - at least the "Typical" Visual Studio 2015 installation does not include the C++ toolset by default,
|
|
# http://blogs.msdn.com/b/vcblog/archive/2015/07/24/setup-changes-in-visual-studio-2015-affecting-c-developers.aspx
|
|
if not shutil.which("cl"):
|
|
logger.error(
|
|
"cl.exe not in PATH. Make sure to select the C++ toolset when installing Visual Studio- cannot proceed."
|
|
)
|
|
sys.exit(1)
|
|
|
|
vs_cfg_vars = vs_cfg(ARGS.generator, REPO_ROOT)
|
|
build_deps_cache = BuildDepsCache(vs_cfg_vars)
|
|
|
|
# Cache last used CMake generator and configurable dependency dirs for other scripts to use.
|
|
build_deps_cache.add_entry("GEN_SHORTHAND", vs_cfg_vars.gen_shorthand)
|
|
|
|
# Make sure deps and install folders exists.
|
|
vs_cfg_vars.deps_dir.mkdir(parents=True, exist_ok=True)
|
|
vs_cfg_vars.install_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# User-configurable build options.
|
|
# TODO: add as cli options to make them appear in --help.
|
|
IFCOS_INSTALL_PYTHON = is_on_off(os.getenv("IFCOS_INSTALL_PYTHON"), default=True)
|
|
IFCOS_INSTALL_QT6 = is_on_off(os.getenv("IFCOS_INSTALL_QT6"), default=True)
|
|
IFCOS_NUM_BUILD_PROCS = int(os.getenv("IFCOS_NUM_BUILD_PROCS") or multiprocessing.cpu_count())
|
|
|
|
# Note BUILD_TYPE not passed, Clean e.g. wouldn't delete the installed files.
|
|
# TODO: consider inlining.
|
|
MSBUILD_MULTIPROC = (
|
|
"/m",
|
|
f"/p:CL_MPCount={IFCOS_NUM_BUILD_PROCS}",
|
|
"/p:UseMultiToolTask=true",
|
|
"/p:EnforceProcessCountAcrossBuilds=true",
|
|
)
|
|
MSBUILD_CMD = ("MSBuild.exe", "/nologo", *MSBUILD_MULTIPROC)
|
|
|
|
# Check that required tools are in PATH.
|
|
# TODO: drop "powershell" later.
|
|
REQUIRED_COMMANDS = ("powershell", "git", "cmake", "7z")
|
|
for command in REQUIRED_COMMANDS:
|
|
require_command(command)
|
|
|
|
validate_cmake_version()
|
|
|
|
print_build_config(
|
|
vs_cfg_vars,
|
|
ARGS.build_type_cfg,
|
|
ARGS.build_type,
|
|
IFCOS_INSTALL_PYTHON,
|
|
IFCOS_INSTALL_QT6,
|
|
IFCOS_NUM_BUILD_PROCS,
|
|
)
|
|
|
|
logger.warning("Warning: You will need roughly 8 GB of disk space to proceed.\n")
|
|
logger.info(
|
|
"If you are not ready with the above: type 'n' in the prompt below. Build proceeds on all other inputs!"
|
|
)
|
|
# TODO: add a `-y` option to skip this prompt.
|
|
do_continue = input("> ")
|
|
if do_continue == "n":
|
|
sys.exit(0)
|
|
|
|
START_TIME = datetime.now().replace(microsecond=0)
|
|
logger.info(f"Build started at {START_TIME}.")
|
|
|
|
nuget_exe = install_nuget(vs_cfg_vars.deps_dir)
|
|
install_ccache(vs_cfg_vars.deps_dir, nuget_exe, build_deps_cache)
|
|
install_proj(vs_cfg_vars, ARGS.build_type, ARGS.build_type_cfg, MSBUILD_MULTIPROC)
|
|
install_mpir(vs_cfg_vars, vs_cfg_vars.deps_dir, vs_cfg_vars.install_dir, ARGS.build_type_cfg)
|
|
install_mpfr(
|
|
vs_cfg_vars, vs_cfg_vars.deps_dir, vs_cfg_vars.install_dir, ARGS.build_type_cfg, ARGS.build_type, MSBUILD_CMD
|
|
)
|
|
install_boost(vs_cfg_vars, build_deps_cache, ARGS.build_type_cfg, IFCOS_NUM_BUILD_PROCS, ARGS.reuse_boost)
|
|
install_json(vs_cfg_vars.install_dir)
|
|
install_opencollada(vs_cfg_vars, ARGS.build_type, ARGS.build_type_cfg, MSBUILD_MULTIPROC)
|
|
install_occt(vs_cfg_vars, ARGS.build_type, build_deps_cache, ARGS.build_type_cfg, MSBUILD_MULTIPROC)
|
|
pythonhome = install_python(vs_cfg_vars, IFCOS_INSTALL_PYTHON, build_deps_cache, nuget_exe)
|
|
install_swig(vs_cfg_vars, ARGS.build_type, build_deps_cache, MSBUILD_MULTIPROC)
|
|
install_cgal(vs_cfg_vars, ARGS.build_type, ARGS.build_type_cfg, MSBUILD_MULTIPROC)
|
|
install_eigen(vs_cfg_vars)
|
|
install_zstd(vs_cfg_vars, ARGS.build_type, ARGS.build_type_cfg, MSBUILD_MULTIPROC)
|
|
install_rocksdb(vs_cfg_vars, ARGS.build_type, ARGS.build_type_cfg, MSBUILD_MULTIPROC)
|
|
install_qt6(vs_cfg_vars, build_deps_cache, ARGS.build_type_cfg, IFCOS_INSTALL_QT6, pythonhome)
|
|
install_manifold(vs_cfg_vars, ARGS.build_type, build_deps_cache, ARGS.build_type_cfg, MSBUILD_MULTIPROC)
|
|
|
|
print_success(START_TIME)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|