mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 10:33:44 +00:00
Introduce build-deps.py, deprecate build-deps.cmd
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.
This commit is contained in:
@@ -326,7 +326,7 @@ if (WITH_ROCKSDB)
|
||||
else()
|
||||
message(FATAL_ERROR "RocksDB found but neither RocksDB::rocksdb nor RocksDB::rocksdb-shared target exists")
|
||||
endif()
|
||||
# Our win/build-deps.cmd builds RocksDB separately per Debug/Release config into the
|
||||
# Our win/build-deps.py builds RocksDB separately per Debug/Release config into the
|
||||
# same install prefix, so the imported target only ever has DEBUG and RELEASE listed in
|
||||
# IMPORTED_CONFIGURATIONS. On a multi-config generator (Visual Studio), CMake maps any
|
||||
# unmatched build config to the *first* entry of that list, which happens to be DEBUG
|
||||
|
||||
@@ -225,7 +225,7 @@ C++ Build Tools <http://landinghub.visualstudio.com/visual-cpp-build-tools>`__).
|
||||
.. code-block:: bat
|
||||
|
||||
cd IfcOpenShell\win
|
||||
build-deps.cmd
|
||||
python build-deps.py
|
||||
run-cmake.bat
|
||||
|
||||
3. Open and build the solution file in Visual Studio:
|
||||
|
||||
@@ -9,13 +9,14 @@ import platform
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from zipfile import ZipFile
|
||||
|
||||
|
||||
def is_arm64() -> bool:
|
||||
arch = os.environ.get("TARGET_ARCH", "").lower()
|
||||
arch = os.environ.get("VS_PLATFORM", "").lower()
|
||||
if arch in ("arm64", "aarch64"):
|
||||
return True
|
||||
if arch in ("x64", "amd64", "x86_64"):
|
||||
@@ -217,7 +218,7 @@ def build() -> None:
|
||||
os.environ["PYTHON_VERSION"] = python_version
|
||||
print(f"Building for Python {python_version}...")
|
||||
subprocess.run(
|
||||
[str(REPO_WIN / "build-deps.cmd"), build_generator(), "Release"],
|
||||
[sys.executable, str(REPO_WIN / "build-deps.py"), build_generator(), "Release"],
|
||||
check=True,
|
||||
text=True,
|
||||
input="y\n",
|
||||
|
||||
+2
-2
@@ -29,8 +29,8 @@ setlocal EnableDelayedExpansion
|
||||
|
||||
call vs-cfg.cmd %1
|
||||
if not %ERRORLEVEL%==0 GOTO :Error
|
||||
:: Use "yes" trick to break the pause in build-deps.cmd
|
||||
echo y | call .\build-deps %1 %2
|
||||
:: Use "yes" trick to break the pause in build-deps.py
|
||||
echo y | python build-deps.py %1 %2
|
||||
if not %ERRORLEVEL%==0 goto :EOF
|
||||
:: Same trick as in run-cmake.bat
|
||||
set ARGUMENTS=%*
|
||||
|
||||
@@ -162,6 +162,10 @@ call :PrintUsage
|
||||
call cecho.cmd 0 14 "Warning: You will need roughly 8 GB of disk space to proceed."
|
||||
echo.
|
||||
|
||||
call cecho.cmd 0 12 "WARNING: build-deps.cmd is deprecated since 09 Sep 2026 and will be removed very shortly."
|
||||
call cecho.cmd 0 12 "Use `python build-deps.py` instead. It's intended to be a drop-in replacement, so exactly the same args apply."
|
||||
echo.
|
||||
|
||||
call cecho.cmd black cyan "If you are not ready with the above: type `'n`' in the prompt below. Build proceeds on all other inputs!"
|
||||
|
||||
set /p do_continue="> "
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
# /// 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()
|
||||
@@ -40,7 +40,7 @@ for /f "tokens=*" %%f in ('dir BuildDepsCache-*.txt /o:-n /t:a /b') do (
|
||||
set GENERATOR=%1
|
||||
if (%1)==() (
|
||||
if not defined GEN_SHORTHAND (
|
||||
echo BuildDepsCache file does and/or GEN_SHORTHAND missing from it. Run build-deps.cmd to create it.
|
||||
echo BuildDepsCache file does and/or GEN_SHORTHAND missing from it. Run build-deps.py to create it.
|
||||
set IFCOS_PAUSE_ON_ERROR=pause
|
||||
goto :Error
|
||||
)
|
||||
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# 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/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Literal, get_args
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from vs_cfg import VsCfgResult
|
||||
|
||||
|
||||
class C:
|
||||
GREY = "\033[90m"
|
||||
GREEN = "\033[92m"
|
||||
PURPLE = "\033[95m"
|
||||
YELLOW = "\033[33m"
|
||||
RED = "\033[31m"
|
||||
RESET = "\033[0m"
|
||||
|
||||
|
||||
def colorize(text: str, color: str) -> str:
|
||||
return f"{color}{text}{C.RESET}"
|
||||
|
||||
|
||||
class ColorFormatter(logging.Formatter):
|
||||
COLORS = {
|
||||
logging.DEBUG: C.GREY,
|
||||
logging.WARNING: C.YELLOW,
|
||||
logging.ERROR: C.RED,
|
||||
}
|
||||
|
||||
def format(self, record: logging.LogRecord) -> str:
|
||||
color = self.COLORS.get(record.levelno, C.RESET)
|
||||
return f"{color}{super().format(record)}{C.RESET}"
|
||||
|
||||
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(ColorFormatter("%(message)s"))
|
||||
logging.basicConfig(level=logging.INFO, handlers=[handler])
|
||||
logger = logging.getLogger()
|
||||
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
# TODO: used to access nix patch.
|
||||
REPO_ROOT = SCRIPT_DIR.parent
|
||||
PROJECT_NAME = "IfcOpenShell"
|
||||
|
||||
|
||||
def run(
|
||||
*cmd: str,
|
||||
cwd: Path | None = None,
|
||||
env: dict[str, str] | None = None,
|
||||
) -> str:
|
||||
logger.debug(f"$ {shlex.join(cmd)}")
|
||||
return subprocess.check_output(cmd, cwd=cwd, env=env, text=True)
|
||||
|
||||
|
||||
def run_streamed(
|
||||
*cmd: str,
|
||||
cwd: Path | None = None,
|
||||
env: dict[str, str] | None = None,
|
||||
) -> None:
|
||||
logger.info(f"$ {shlex.join(cmd)}")
|
||||
full_env = {**os.environ, **env} if env is not None else None
|
||||
subprocess.check_call(cmd, cwd=cwd, env=full_env)
|
||||
|
||||
|
||||
def is_on_off(value: str | None, *, default: bool) -> bool:
|
||||
if value is None:
|
||||
return default
|
||||
lowered = value.lower()
|
||||
if lowered in {"1", "on", "true", "yes"}:
|
||||
return True
|
||||
if lowered in {"0", "off", "false", "no"}:
|
||||
return False
|
||||
return default
|
||||
|
||||
|
||||
BuildCfg = Literal["MinSizeRel", "Release", "RelWithDebInfo", "Debug"]
|
||||
DebugOrRelease = Literal["Debug", "Release"]
|
||||
|
||||
BUILD_CFGS = get_args(BuildCfg)
|
||||
BUILD_CFG_DEFAULT: BuildCfg = "RelWithDebInfo"
|
||||
|
||||
BuildType = Literal["Build", "Rebuild", "Clean"]
|
||||
|
||||
BUILD_TYPES = get_args(BuildType)
|
||||
BUILD_TYPE_DEFAULT: BuildType = "Build"
|
||||
|
||||
|
||||
def debug_or_release(build_cfg: BuildCfg) -> DebugOrRelease:
|
||||
return "Debug" if build_cfg == "Debug" else "Release"
|
||||
|
||||
|
||||
def require_command(command: str) -> str:
|
||||
path = shutil.which(command)
|
||||
if not path:
|
||||
logger.error(f"Required tool '{command}' not installed or not added to PATH.")
|
||||
sys.exit(1)
|
||||
return path
|
||||
|
||||
|
||||
def validate_cmake_version() -> None:
|
||||
MIN_CMAKE_VERSION = (3, 21, 0)
|
||||
error_msg = f"CMake v{'.'.join(map(str, MIN_CMAKE_VERSION))} or higher is required"
|
||||
|
||||
if not shutil.which("cmake"):
|
||||
logger.error(error_msg)
|
||||
sys.exit(1)
|
||||
|
||||
cmake_version_output = run("cmake", "--version")
|
||||
match = re.search(r"cmake version (\d+)\.(\d+)\.(\d+)", cmake_version_output)
|
||||
if not match or tuple(map(int, match.groups())) < MIN_CMAKE_VERSION:
|
||||
logger.error(error_msg)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class BuildDepsCache:
|
||||
def __init__(self, vs_cfg_vars: VsCfgResult) -> None:
|
||||
if vs_cfg_vars.vs_toolset_override:
|
||||
self.path = SCRIPT_DIR / f"BuildDepsCache-{vs_cfg_vars.vs_platform}-{vs_cfg_vars.vs_toolset_override}.txt"
|
||||
else:
|
||||
self.path = SCRIPT_DIR / f"BuildDepsCache-{vs_cfg_vars.vs_platform}.txt"
|
||||
self.path.write_text("")
|
||||
|
||||
def add_entry(self, key: str, value: str) -> None:
|
||||
with self.path.open("a") as f:
|
||||
f.write(f"{key}={value}\n")
|
||||
@@ -39,7 +39,7 @@ for /f "tokens=*" %%f in ('dir BuildDepsCache-*.txt /o:-n /t:a /b') do (
|
||||
set GENERATOR=%1
|
||||
if (%1)==() (
|
||||
if not defined GEN_SHORTHAND (
|
||||
echo BuildDepsCache file does and/or GEN_SHORTHAND missing from it. Run build-deps.cmd to create it.
|
||||
echo BuildDepsCache file does and/or GEN_SHORTHAND missing from it. Run build-deps.py to create it.
|
||||
set IFCOS_PAUSE_ON_ERROR=pause
|
||||
goto :Error
|
||||
)
|
||||
|
||||
+1250
File diff suppressed because it is too large
Load Diff
+20
-22
@@ -9,34 +9,32 @@ files that can also be invoked e.g. by double-clicking in the File Explorer.
|
||||
|
||||
Usage Instructions
|
||||
------------------
|
||||
Launch the proper Visual Studio command prompt, cd to the 'win' directory inside the IfcOpenShell directory and execute `build-deps.cmd` to fetch, build and install the dependencies. The batch file will print the requirements for a successful execution. The script allows a few user-configurable build options which are listed below.
|
||||
Launch the proper Visual Studio command prompt, cd to the 'win' directory inside the IfcOpenShell directory and execute `python build-deps.py` to fetch, build and install the dependencies. The script will print the requirements for a successful execution. It allows a few user-configurable build options which are listed below (run `python build-deps.py --help` for the full list).
|
||||
|
||||
`build-deps.cmd` expects a CMake generator as `%1` and a build configuration type (`RelWithDebInfo`, `Release`, `MinSizeRel`, or `Debug`, defaults to `RelWithDebInfo`) as `%2`. If the generator is not provided, the generator is deduced from the MSVC environment variables.
|
||||
`build-deps.py` expects a CMake generator as the 1st positional argument and a build configuration type (`RelWithDebInfo`, `Release`, `MinSizeRel`, or `Debug`, defaults to `RelWithDebInfo`) as the 2nd. If the generator is not provided, it is deduced from the MSVC environment variables.
|
||||
|
||||
User-friendly CMake Visual Studio generator shorthands are supported. They are converted to the appropriate CMake generators and options. Shorthands are indeed the preferable way to specify the generator, since they allow a more accurate platform and toolset configuration. Here are some examples:
|
||||
```
|
||||
"vs2013" => cmake -G "Visual Studio 12 2013" -A Win32
|
||||
"vs2013-x86" => cmake -G "Visual Studio 12 2013" -A Win32
|
||||
"vs2015-x64" => cmake -G "Visual Studio 14 2015" -A x64
|
||||
"vs2017-ARM64" => cmake -G "Visual Studio 15 2017" -A ARM64
|
||||
"vs2019-x86-v141" => cmake -G "Visual Studio 16 2019" -A Win32 -T v141
|
||||
"vs2022-x64" => cmake -G "Visual Studio 17 2022" -A x64
|
||||
"vs2022-ARM64" => cmake -G "Visual Studio 17 2022" -A ARM64
|
||||
```
|
||||
Of course not all Visual C++ compilers support any platform or toolset, refer to the Visual Studio and CMake documentation for this. If you do not specify a toolset, the compiler will use the default toolset for the version, i.e. vs2019 will use the v142 toolset.
|
||||
|
||||
A build type (`Build`, `Rebuild`, or `Clean`, defaults to `Build`) can be provided as `%3`.
|
||||
A build type (`Build`, `Rebuild`, or `Clean`, defaults to `Build`) can be provided as the 3rd positional argument.
|
||||
|
||||
See `vs-cfg.cmd` if you wish to change the defaults. The batch file will create `deps\` and `deps-vs<VERSION>-<PLATFORM>[-<TOOLSET>]-installed\` directories to the project root. Debug and release builds of the dependencies can co-exist by simply running:
|
||||
The script will create `_deps\` and `_deps-vs<VERSION>-<PLATFORM>[-<TOOLSET>]-installed\` directories in the project root. Debug and release builds of the dependencies can co-exist by simply running:
|
||||
```
|
||||
> build-deps.cmd <GENERATOR> Debug
|
||||
> build-deps.cmd <GENERATOR> <Release|RelWithDebInfo|MinSizeRel>
|
||||
> python build-deps.py <GENERATOR> Debug
|
||||
> python build-deps.py <GENERATOR> <Release|RelWithDebInfo|MinSizeRel>
|
||||
```
|
||||
|
||||
After the dependencies are build, execute `run-cmake.bat`. The batch file expects a CMake generator as `%1`, that is interpreted just like the `build-deps.cmd` script, and the rest of possible parameters are passed as is. If a generator is not provided, the generator is read from the BuildDepsCache file, or tried to be deduced from the location of `cl.exe`. If passing build options for the script, the generator must be always passed as the first option:
|
||||
After the dependencies are built, execute `run-cmake.bat`. The batch file expects a CMake generator as `%1`, that is interpreted just like the `build-deps.py` script, and the rest of possible parameters are passed as is. If a generator is not provided, the generator is read from the BuildDepsCache file, or tried to be deduced from the location of `cl.exe`. If passing build options for the script, the generator must be always passed as the first option:
|
||||
```
|
||||
> run-cmake.bat vs2015-x64 -DUSE_IFC4=1 -DBUILD_IFCPYTHON=0
|
||||
> run-cmake.bat vs2022-x64 -DGLTF_SUPPORT=ON
|
||||
```
|
||||
|
||||
**If you wish to use any library from a custom location, modify the paths in `run-cmake.bat` accordingly**. The batch script will create a folder of form `build-vs<VERSION>-<PLATFORM>[-<TOOLSET>]\` which will contain the solution and project files for MSVC.
|
||||
**If you wish to use any library from a custom location, modify the paths in `run-cmake.bat` accordingly**. The batch script will create a folder of form `_build-vs<VERSION>-<PLATFORM>[-<TOOLSET>]\` which will contain the solution and project files for MSVC.
|
||||
|
||||
Note that building IfcOpenShell as 64-bit is recommended as many of real life IFC files has been observed to take easily more than 2 GBs of RAM while converting.
|
||||
|
||||
@@ -47,18 +45,18 @@ files expect `%1` and `%2` in same fashion as above and possible extra parameter
|
||||
or regular Command Prompt if BuildDepsCache file exists (the last modified version is used). Running the scripts without extra
|
||||
parameters reads the build options from an existing CMakeCache.txt.
|
||||
|
||||
The project will be installed to `installed-vs<VERSION>-<ARCHITECTURE>\` folder in the project's root folder and the
|
||||
The project will be installed to `_installed-vs<VERSION>-<ARCHITECTURE>\` folder in the project's root folder and the
|
||||
required IfcOpenShell-Python parts are deployed to the `<PYTHONHOME>\Lib\site-packages\` folder. The 3ds Max plug-in,
|
||||
`IfcMax.dli`, needs to be copied manually to the 3ds Max's `plugins` folder.
|
||||
|
||||
Using an already existing Python installation
|
||||
---------------------------------------------
|
||||
|
||||
Let's say you have already installed 64-bit Python 3.5.1 to `C:\Python3`.
|
||||
Let's say you have already installed 64-bit Python 3.13 to `C:\Python3`.
|
||||
Before building the dependencies, disable the script from installing Python:
|
||||
```
|
||||
> set IFCOS_INSTALL_PYTHON=FALSE
|
||||
> buid-deps.cmd
|
||||
> python build-deps.py
|
||||
```
|
||||
|
||||
After building the dependencies, append Python installation directory information to the BuildDepsCache file
|
||||
@@ -74,14 +72,14 @@ Directory Structure
|
||||
------------------
|
||||
```
|
||||
..
|
||||
+---build-* - Created by run-cmake.bat, specific for a certain compiler and and target architecture
|
||||
+---deps - Created by build-deps.cmd, common for all compilers
|
||||
+---deps-*-installed - Created by build-deps.cmd, specific for a certain compiler and target architecture
|
||||
+---installed-* - Created by installing the IFCOS project, specific for a certain compiler and target architecture
|
||||
+---_build-* - Created by run-cmake.bat, specific for a certain compiler and and target architecture
|
||||
+---_deps - Created by build-deps.py, common for all compilers
|
||||
+---_deps-*-installed - Created by build-deps.py, specific for a certain compiler and target architecture
|
||||
+---_installed-* - Created by installing the IFCOS project, specific for a certain compiler and target architecture
|
||||
\---win
|
||||
| build-all.cmd - Runs all of the build scripts for IFCOS and it dependencies in a row without pauses
|
||||
| build-deps.cmd - Fetches and builds all needed dependencies for IFCOS using MSVC
|
||||
| BuildDepsCache-<ARCH>.txt - Cache file created by build-deps.cmd
|
||||
| build-deps.py - Fetches and builds all needed dependencies for IFCOS using MSVC
|
||||
| BuildDepsCache-<ARCH>.txt - Cache file created by build-deps.py
|
||||
| build-ifcopenshell.bat - Builds IFCOS using MSVC
|
||||
| build-type-cfg.cmd - Utility file used by the build scripts
|
||||
| install-ifcopenshell.bat - Installs/deploys IFCOS using MSVC.
|
||||
|
||||
+4
-4
@@ -44,7 +44,7 @@ if (%1)==() (
|
||||
)
|
||||
|
||||
if not defined GEN_SHORTHAND (
|
||||
echo BuildDepsCache file does not exist and/or GEN_SHORTHAND missing from it. Run build-deps.cmd to create it.
|
||||
echo BuildDepsCache file does not exist and/or GEN_SHORTHAND missing from it. Run build-deps.py to create it.
|
||||
set IFCOS_PAUSE_ON_ERROR=pause
|
||||
goto :Error
|
||||
)
|
||||
@@ -135,7 +135,7 @@ echo Arguments = %ARGUMENTS%
|
||||
echo.
|
||||
call cecho.cmd 0 10 "Dependency Environment Variables for %PROJECT_NAME%:"
|
||||
echo BOOST_INSTALL_DIR = %BOOST_INSTALL_DIR%
|
||||
:: OCC_INCLUDE_DIR / OCC_LIBRARY_DIR are legacy vars, they're not defined by build-deps.cmd anymore.
|
||||
:: OCC_INCLUDE_DIR / OCC_LIBRARY_DIR are legacy vars, they're not defined by build-deps.py anymore.
|
||||
echo OCC_INCLUDE_DIR = %OCC_INCLUDE_DIR%
|
||||
echo OCC_LIBRARY_DIR = %OCC_LIBRARY_DIR%
|
||||
echo OCC_INSTALL_DIR = %OCC_INSTALL_DIR%
|
||||
@@ -177,7 +177,7 @@ set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%BOOST_INSTALL_DIR%;%CCACHE_INSTALL_DI
|
||||
set CMake_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%USD_INSTALL_DIR%;%TBB_INSTALL_DIR%
|
||||
set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%OCC_INSTALL_DIR%;%CGAL_INSTALL_DIR%
|
||||
set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%GMP_INSTALL_DIR%;%MPFR_INSTALL_DIR%
|
||||
:: TODO: drop this TRANSITION check once everyone has re-run build-deps.cmd with manifold support.
|
||||
:: TODO: drop this TRANSITION check once everyone has re-run build-deps.py with manifold support.
|
||||
if defined MANIFOLD_INSTALL_PATH set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%MANIFOLD_INSTALL_PATH%
|
||||
if defined QT_DIR set CMAKE_PREFIX_PATH=%CMAKE_PREFIX_PATH%;%QT_DIR%
|
||||
|
||||
@@ -185,7 +185,7 @@ set QT_DIR_OPTION=
|
||||
if defined QT_DIR set QT_DIR_OPTION=-DQT_DIR="%QT_DIR%"
|
||||
set QT_HOST_PATH_OPTION=
|
||||
if defined QT_HOST_PATH set QT_HOST_PATH_OPTION=-DQT_HOST_PATH="%QT_HOST_PATH%"
|
||||
:: TODO: drop this TRANSITION check once everyone has re-run build-deps.cmd with manifold support.
|
||||
:: TODO: drop this TRANSITION check once everyone has re-run build-deps.py with manifold support.
|
||||
set WITH_MANIFOLD_OPTION=
|
||||
if defined MANIFOLD_INSTALL_PATH set WITH_MANIFOLD_OPTION=-DWITH_MANIFOLD=ON
|
||||
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ IF NOT "%CMAKE_PATH%"=="" (
|
||||
FOR /f "delims=" %%i in ('cmake --version ^| findstr /C:"cmake version 4"') DO GOTO :CMake3AndNewer
|
||||
)
|
||||
|
||||
:: reject older CMake, see also build-deps.cmd
|
||||
:: reject older CMake, see also build-deps.py
|
||||
echo "CMake v3.21.0 or higher is required"
|
||||
exit /b 1
|
||||
|
||||
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
# /// script
|
||||
# [tool.ty.environment]
|
||||
# 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 os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Literal, NamedTuple
|
||||
|
||||
from common import SCRIPT_DIR, logger, run
|
||||
|
||||
ArchBits = Literal[32, 64]
|
||||
# TODO: according to cmake docs, there's no `ARM` platform, only `ARM64`.
|
||||
# So it can be deleted?
|
||||
VsPlatform = Literal["Win32", "x64", "ARM", "ARM64"]
|
||||
"""Platform names as used by Visual Studio (e.g. `cmake -A`), but fine to use for general platform checks too."""
|
||||
GeneratorType = Literal["EMPTY", "SHORTHAND", "FULL_NAME"]
|
||||
|
||||
|
||||
class CMakeGeneratorInfo(NamedTuple):
|
||||
name: str
|
||||
"""E.g. "Visual Studio 16 2019"."""
|
||||
generator_num: int
|
||||
"""E.g. 16 for "Visual Studio 16 2019"."""
|
||||
vs_ver: int
|
||||
"""E.g. 2019."""
|
||||
vc_ver: str
|
||||
"""E.g. "14.2"."""
|
||||
vs_toolset: str
|
||||
"""Default toolset for this generator, e.g. "v142".
|
||||
See `VsCfgResult.vs_toolset_override` for an explicit override.
|
||||
"""
|
||||
boost_bootstrap_ver: str
|
||||
"""E.g. "vc142"."""
|
||||
|
||||
|
||||
CMAKE_GENERATORS = {
|
||||
"Visual Studio 12 2013": CMakeGeneratorInfo("Visual Studio 12 2013", 12, 2013, "12.0", "v120", "vc120"),
|
||||
"Visual Studio 14 2015": CMakeGeneratorInfo("Visual Studio 14 2015", 14, 2015, "14.0", "v140", "vc140"),
|
||||
"Visual Studio 15 2017": CMakeGeneratorInfo("Visual Studio 15 2017", 15, 2017, "14.1", "v141", "vc141"),
|
||||
"Visual Studio 16 2019": CMakeGeneratorInfo("Visual Studio 16 2019", 16, 2019, "14.2", "v142", "vc142"),
|
||||
"Visual Studio 17 2022": CMakeGeneratorInfo("Visual Studio 17 2022", 17, 2022, "14.3", "v143", "vc143"),
|
||||
"Visual Studio 18 2026": CMakeGeneratorInfo("Visual Studio 18 2026", 18, 2026, "14.5", "v145", "vc145"),
|
||||
}
|
||||
|
||||
|
||||
class VsCfgResult(NamedTuple):
|
||||
generator: CMakeGeneratorInfo
|
||||
vs_platform: VsPlatform
|
||||
"""E.g. "x64"."""
|
||||
vs_toolset_override: str | None
|
||||
"""E.g. "v142", or None if not explicitly overridden via generator shorthand."""
|
||||
arch_bits: ArchBits
|
||||
boost_toolset: str
|
||||
"""E.g. "msvc-14.2"."""
|
||||
gen_shorthand: str
|
||||
"""E.g. "vs2019-x64"."""
|
||||
deps_dir: Path
|
||||
"""E.g. Path("_deps")."""
|
||||
install_dir: Path
|
||||
"""E.g. Path("_deps-vs2019-x64-installed")."""
|
||||
build_dir: str
|
||||
"""E.g. "_build-vs2019-x64"."""
|
||||
build_deps_cache_path: Path
|
||||
"""E.g. Path("BuildDepsCache-x64-v142.txt")."""
|
||||
|
||||
PRINT_VARS_SKIP = {"gen_shorthand", "deps_dir", "install_dir", "build_dir", "build_deps_cache_path"}
|
||||
|
||||
def print_vars(self) -> None:
|
||||
fields = [f for f in self._fields if f not in self.PRINT_VARS_SKIP]
|
||||
name_width = max(len(f) for f in fields)
|
||||
for field in fields:
|
||||
logger.info(f"{field.upper():<{name_width}}: [{getattr(self, field)}]")
|
||||
|
||||
def is_vs_platform(self, platform: VsPlatform) -> bool:
|
||||
"""Compare against `vs_platform`, just to prevent typos."""
|
||||
return self.vs_platform == platform
|
||||
|
||||
|
||||
VS_TOOLSET_TO_VC_VER = {info.vs_toolset: info.vc_ver for info in CMAKE_GENERATORS.values()}
|
||||
"""E.g. "v142" -> "14.2"."""
|
||||
|
||||
VS_TOOLSET_TO_VS_VER = {info.vs_toolset: info.vs_ver for info in CMAKE_GENERATORS.values()}
|
||||
"""E.g. "v142" -> 2019."""
|
||||
|
||||
|
||||
class VSArchInfo(NamedTuple):
|
||||
vs_platform: VsPlatform
|
||||
arch_bits: ArchBits
|
||||
|
||||
|
||||
VSCMD_ARG_TGT_ARCH_TO_INFO = {
|
||||
"x86": VSArchInfo("Win32", 32),
|
||||
"x64": VSArchInfo("x64", 64),
|
||||
"arm": VSArchInfo("ARM", 32),
|
||||
"arm64": VSArchInfo("ARM64", 64),
|
||||
}
|
||||
|
||||
VS_PLATFORM_TO_INFO = {info.vs_platform: info for info in VSCMD_ARG_TGT_ARCH_TO_INFO.values()}
|
||||
|
||||
|
||||
VSVar = Literal[
|
||||
"VSINSTALLDIR",
|
||||
"VisualStudioVersion",
|
||||
"VSCMD_ARG_TGT_ARCH",
|
||||
"UCRTVersion",
|
||||
]
|
||||
|
||||
|
||||
def get_vs_var(var: VSVar) -> str:
|
||||
value = os.getenv(var)
|
||||
if value is None:
|
||||
logger.error("Visual Studio environment variables not set - cannot proceed.")
|
||||
sys.exit(1)
|
||||
return value
|
||||
|
||||
|
||||
class VsCfg:
|
||||
"""Determines the CMake generator, VS platform/toolset, and derived paths for a build.
|
||||
|
||||
Usage: `VsCfg.build(generator, repo_root)`.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def build(generator: str | None, repo_root: Path) -> VsCfgResult:
|
||||
generator = generator or ""
|
||||
vs_platform: VsPlatform | None = None
|
||||
vs_toolset: str | None = None
|
||||
boost_toolset_ver: str | None = None
|
||||
|
||||
generator_type = VsCfg._determine_generator_type(generator)
|
||||
if generator_type in ("EMPTY", "SHORTHAND"):
|
||||
generator, vs_platform, vs_toolset, boost_toolset_ver = VsCfg._parse_generator_shorthand(
|
||||
generator, generator_type
|
||||
)
|
||||
|
||||
# Just to be double sure.
|
||||
assert generator in CMAKE_GENERATORS
|
||||
VsCfg._ensure_cmake_supports_generator(generator)
|
||||
|
||||
vs_platform = vs_platform or VsCfg._vs_platform_from_env()
|
||||
generator_info = CMAKE_GENERATORS[generator]
|
||||
arch_bits = VS_PLATFORM_TO_INFO[vs_platform].arch_bits
|
||||
|
||||
boost_toolset = f"msvc-{boost_toolset_ver or generator_info.vc_ver}"
|
||||
|
||||
gen_shorthand = f"vs{generator_info.vs_ver}-{vs_platform}"
|
||||
if vs_toolset is not None:
|
||||
gen_shorthand += f"-{vs_toolset}"
|
||||
|
||||
# NOTE For IfcOpenShell we can build all of our deps both x86 and x64 using different VS versions in the same
|
||||
# directories so no need for "-{vs_ver}-{vs_platform}" postfix.
|
||||
deps_dir = repo_root / "_deps"
|
||||
install_dir = repo_root / f"_deps-{gen_shorthand}-installed"
|
||||
# build_dir is a relative build directory used for CMake-based projects.
|
||||
build_dir = f"_build-{gen_shorthand}"
|
||||
|
||||
if vs_toolset is not None:
|
||||
build_deps_cache_path = SCRIPT_DIR / f"BuildDepsCache-{vs_platform}-{vs_toolset}.txt"
|
||||
else:
|
||||
build_deps_cache_path = SCRIPT_DIR / f"BuildDepsCache-{vs_platform}.txt"
|
||||
|
||||
result = VsCfgResult(
|
||||
generator=generator_info,
|
||||
vs_platform=vs_platform,
|
||||
vs_toolset_override=vs_toolset,
|
||||
arch_bits=arch_bits,
|
||||
boost_toolset=boost_toolset,
|
||||
gen_shorthand=gen_shorthand,
|
||||
deps_dir=deps_dir,
|
||||
install_dir=install_dir,
|
||||
build_dir=build_dir,
|
||||
build_deps_cache_path=build_deps_cache_path,
|
||||
)
|
||||
result.print_vars()
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def _generator_from_visual_studio_version() -> str:
|
||||
# E.g. '17.0' -> 17.
|
||||
vs_version = get_vs_var("VisualStudioVersion")
|
||||
generator_num = int(vs_version.replace(".0", ""))
|
||||
|
||||
for candidate, info in CMAKE_GENERATORS.items():
|
||||
if info.generator_num == generator_num:
|
||||
logger.info(
|
||||
f"Generator not passed, but VisualStudioVersion={vs_version} environment variable detected:"
|
||||
)
|
||||
logger.info(f"using '{candidate}' as the generator.")
|
||||
return candidate
|
||||
|
||||
logger.error(
|
||||
f"Generator is not provided and VisualStudioVersion='{vs_version}' is not supported - cannot proceed."
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
@staticmethod
|
||||
def _vs_platform_from_env() -> VsPlatform:
|
||||
# Fall back to `VSCMD_ARG_TGT_ARCH`, the command prompt's target platform, set by vsvarsall.
|
||||
VSCMD_ARG_TGT_ARCH = get_vs_var("VSCMD_ARG_TGT_ARCH")
|
||||
return VSCMD_ARG_TGT_ARCH_TO_INFO[VSCMD_ARG_TGT_ARCH].vs_platform
|
||||
|
||||
@staticmethod
|
||||
def _ensure_cmake_supports_generator(generator: str) -> None:
|
||||
cmake_help = run("cmake", "--help")
|
||||
if generator not in cmake_help:
|
||||
logger.error(f"The used CMake version does not support generator '{generator}' - cannot proceed.")
|
||||
sys.exit(1)
|
||||
|
||||
@staticmethod
|
||||
def _determine_generator_type(generator: str) -> GeneratorType:
|
||||
match generator:
|
||||
case "":
|
||||
return "EMPTY"
|
||||
case _ if "vs20" in generator:
|
||||
# E.g. 'vs2022-x64'.
|
||||
return "SHORTHAND"
|
||||
case _:
|
||||
if generator not in CMAKE_GENERATORS:
|
||||
supported_generators = ", ".join(repr(g) for g in CMAKE_GENERATORS)
|
||||
logger.error(
|
||||
f"Invalid or unsupported CMake generator string passed: '{generator}' - cannot proceed."
|
||||
)
|
||||
logger.error(f"Supported CMake generator strings: {supported_generators}")
|
||||
sys.exit(1)
|
||||
return "FULL_NAME"
|
||||
|
||||
@staticmethod
|
||||
def _parse_generator_shorthand(
|
||||
generator: str, generator_type: GeneratorType
|
||||
) -> tuple[str, VsPlatform | None, str | None, str | None]:
|
||||
# E.g. '2022-x64'.
|
||||
gen_shorthand = generator.replace("vs", "")
|
||||
|
||||
vs_platform = None
|
||||
vs_toolset = None
|
||||
boost_toolset_ver = None
|
||||
|
||||
# Order matters, e.g. "-arm64" also matches "-arm", so it must come last.
|
||||
for arch, info in VSCMD_ARG_TGT_ARCH_TO_INFO.items():
|
||||
if f"-{arch}" in gen_shorthand.lower():
|
||||
vs_platform = info.vs_platform
|
||||
|
||||
for toolset, vc_ver in VS_TOOLSET_TO_VC_VER.items():
|
||||
if f"-{toolset}" in gen_shorthand:
|
||||
vs_toolset = toolset
|
||||
boost_toolset_ver = vc_ver
|
||||
|
||||
vs_ver = gen_shorthand[:4]
|
||||
|
||||
if generator_type == "SHORTHAND":
|
||||
for candidate, info in CMAKE_GENERATORS.items():
|
||||
if info.vs_ver == int(vs_ver):
|
||||
generator = candidate
|
||||
break
|
||||
else:
|
||||
supported_generators = ", ".join(repr(g) for g in CMAKE_GENERATORS)
|
||||
logger.error(f"Invalid or unsupported CMake generator string passed: '{generator}' - cannot proceed.")
|
||||
logger.error(f"Supported CMake generator strings: {supported_generators}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
generator = VsCfg._generator_from_visual_studio_version()
|
||||
|
||||
return generator, vs_platform, vs_toolset, boost_toolset_ver
|
||||
|
||||
|
||||
def vs_cfg(generator: str | None, repo_root: Path) -> VsCfgResult:
|
||||
return VsCfg.build(generator, repo_root)
|
||||
Reference in New Issue
Block a user