diff --git a/nix/build-all.py b/nix/build-all.py index b0ab4e0a14..18c2c8ef64 100644 --- a/nix/build-all.py +++ b/nix/build-all.py @@ -3,6 +3,8 @@ # dependencies = [ # "typing_extensions", # ] +# [tool.ty.environment] +# root = ["."] # /// ############################################################################### # # @@ -135,12 +137,11 @@ from pathlib import Path from typing import Literal, NamedTuple, TypeAlias from urllib.request import urlretrieve +from common import ColorFormatter, HelpStrings, resolve_cli_or_env from typing_extensions import assert_never -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -ch = logging.StreamHandler() -logger.addHandler(ch) +# `common` configures the root logger on import, so reuse it here. +logger = logging.getLogger() def is_on_off(value: str | None, *, default: bool) -> bool: @@ -208,6 +209,7 @@ class Args(NamedTuple): occt_shared: bool mac_cross_compile_intel: bool wasm: bool + num_build_procs: int class DynamicArgs(NamedTuple): @@ -310,7 +312,20 @@ def parse_args() -> tuple[Args, DynamicArgs]: help="Cross compile for Intel Mac on Apple Silicon host.", ) arg_parser.add_argument("-wasm", "--wasm", action="store_true", default=False, help="Compile for wasm.") + arg_parser.add_argument( + "--num-build-procs", + dest="num_build_procs", + type=int, + default=argparse.SUPPRESS, + help=HelpStrings.NUM_BUILD_PROCS, + ) namespace, unknown_flags = arg_parser.parse_known_args() + num_build_procs = resolve_cli_or_env( + getattr(namespace, "num_build_procs", None), + "IFCOS_NUM_BUILD_PROCS", + multiprocessing.cpu_count() + 1, + arg_type="int", + ) args = Args( explicit_targets=namespace.explicit_targets, build_examples=namespace.build_examples, @@ -322,6 +337,7 @@ def parse_args() -> tuple[Args, DynamicArgs]: occt_shared=namespace.occt_shared or namespace.shared, mac_cross_compile_intel=namespace.mac_cross_compile_intel, wasm=namespace.wasm, + num_build_procs=num_build_procs, ) dynamic_args = DynamicArgs.from_unknown_flags(unknown_flags, arg_parser) @@ -409,7 +425,7 @@ if APPLE: # /Users/runner/work/IfcOpenShell/IfcOpenShell/src/ifcparse/IfcFile.cpp:539:14: error: 'exists' is unavailable: introduced in macOS 10.15 TOOLSET = "10.15" -IFCOS_NUM_BUILD_PROCS = os.getenv("IFCOS_NUM_BUILD_PROCS", multiprocessing.cpu_count() + 1) +IFCOS_NUM_BUILD_PROCS = ARGS.num_build_procs SCRIPT_PATH = Path(__file__).parent REPO_PATH = SCRIPT_PATH.parent @@ -508,8 +524,8 @@ def gather_dependencies(dep: str) -> Generator[str]: if ARGS.verbose: logger.setLevel(logging.DEBUG) - formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") - ch.setFormatter(formatter) + formatter = ColorFormatter("%(asctime)s - %(levelname)s - %(message)s") + logger.handlers[0].setFormatter(formatter) else: logger.setLevel(logging.INFO) diff --git a/nix/common.py b/nix/common.py new file mode 120000 index 0000000000..19bf40a8ea --- /dev/null +++ b/nix/common.py @@ -0,0 +1 @@ +../win/common.py \ No newline at end of file diff --git a/win/build-deps.py b/win/build-deps.py index 3136a7f383..b47ec4556b 100644 --- a/win/build-deps.py +++ b/win/build-deps.py @@ -38,7 +38,6 @@ from common import ( REPO_ROOT, SCRIPT_DIR, BuildCfg, - BuildDepsCache, BuildType, C, HelpStrings, @@ -49,6 +48,7 @@ from common import ( resolve_cli_or_env, validate_cmake_version, ) +from common_win import BuildDepsCache from installers import ( install_boost, install_ccache, diff --git a/win/build-ifcopenshell.py b/win/build-ifcopenshell.py index 31f8da6ac9..a62deb6c5a 100644 --- a/win/build-ifcopenshell.py +++ b/win/build-ifcopenshell.py @@ -38,9 +38,9 @@ from common import ( ensure_script_dir, logger, resolve_cli_or_env, - resolve_generator, run_streamed, ) +from common_win import resolve_generator from vs_cfg import vs_cfg diff --git a/win/common.py b/win/common.py index e8e8fd25da..4fb2f05a31 100644 --- a/win/common.py +++ b/win/common.py @@ -27,10 +27,7 @@ import shutil import subprocess import sys from pathlib import Path -from typing import TYPE_CHECKING, Any, Literal, TypeVar, cast, get_args - -if TYPE_CHECKING: - from vs_cfg import VsCfgResult +from typing import Any, Literal, TypeVar, cast, get_args class C: @@ -195,46 +192,3 @@ def validate_cmake_version() -> None: 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") - - @staticmethod - def parse(path: Path) -> dict[str, str]: - entries: dict[str, str] = {} - for line in path.read_text().splitlines(): - key, _, value = line.partition("=") - entries[key] = value - return entries - - -def resolve_generator(generator: str | None) -> str: - """Return `generator` as-is, or fall back to the GEN_SHORTHAND from the most recently modified - BuildDepsCache-*.txt. Exits if neither is available. - """ - if generator is not None: - return generator - - cache_files = sorted(SCRIPT_DIR.glob("BuildDepsCache-*.txt"), key=lambda p: p.stat().st_mtime, reverse=True) - cached_generator = None - if cache_files: - cache_file = cache_files[0] - logger.info(f"Found {cache_file.name}, reading GEN_SHORTHAND from it.") - cached_generator = BuildDepsCache.parse(cache_file).get("GEN_SHORTHAND") - - if cached_generator is None: - logger.error( - "BuildDepsCache file does not exist and/or GEN_SHORTHAND missing from it. Run build-deps.py to create it." - ) - sys.exit(1) - return cached_generator diff --git a/win/common_win.py b/win/common_win.py new file mode 100644 index 0000000000..cb6ac7d9d4 --- /dev/null +++ b/win/common_win.py @@ -0,0 +1,72 @@ +############################################################################### +# # +# 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 . # +# # +############################################################################### +# +from __future__ import annotations + +import sys +from pathlib import Path +from typing import TYPE_CHECKING + +from common import SCRIPT_DIR, logger + +if TYPE_CHECKING: + from vs_cfg import VsCfgResult + + +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") + + @staticmethod + def parse(path: Path) -> dict[str, str]: + entries: dict[str, str] = {} + for line in path.read_text().splitlines(): + key, _, value = line.partition("=") + entries[key] = value + return entries + + +def resolve_generator(generator: str | None) -> str: + """Return `generator` as-is, or fall back to the GEN_SHORTHAND from the most recently modified + BuildDepsCache-*.txt. Exits if neither is available. + """ + if generator is not None: + return generator + + cache_files = sorted(SCRIPT_DIR.glob("BuildDepsCache-*.txt"), key=lambda p: p.stat().st_mtime, reverse=True) + cached_generator = None + if cache_files: + cache_file = cache_files[0] + logger.info(f"Found {cache_file.name}, reading GEN_SHORTHAND from it.") + cached_generator = BuildDepsCache.parse(cache_file).get("GEN_SHORTHAND") + + if cached_generator is None: + logger.error( + "BuildDepsCache file does not exist and/or GEN_SHORTHAND missing from it. Run build-deps.py to create it." + ) + sys.exit(1) + return cached_generator diff --git a/win/installers.py b/win/installers.py index 30531dbe55..7f272e5e20 100644 --- a/win/installers.py +++ b/win/installers.py @@ -34,7 +34,6 @@ from common import ( REPO_ROOT, SCRIPT_DIR, BuildCfg, - BuildDepsCache, BuildType, debug_or_release, logger, @@ -42,6 +41,7 @@ from common import ( run, run_streamed, ) +from common_win import BuildDepsCache from vs_cfg import CMAKE_GENERATORS, VS_TOOLSET_TO_VS_VER, VsCfgResult, get_vs_var diff --git a/win/run-cmake.py b/win/run-cmake.py index cc9e139b95..e7ea2b04c1 100644 --- a/win/run-cmake.py +++ b/win/run-cmake.py @@ -33,17 +33,16 @@ from common import ( OFF_ON, PROJECT_NAME, REPO_ROOT, - BuildDepsCache, C, HelpStrings, colorize, ensure_script_dir, logger, resolve_cli_or_env, - resolve_generator, run, run_streamed, ) +from common_win import BuildDepsCache, resolve_generator from vs_cfg import VsCfgResult, vs_cfg