Compile a module with the given name. The first path in `paths` is the module file, and the rest are its dependencies. Returns True if the module was recompiled, False if it was up to date.
(name: str, paths: list[pathlib.Path], module_output_path: pathlib.Path)
| 238 | |
| 239 | |
| 240 | def compile_module(name: str, paths: list[pathlib.Path], module_output_path: pathlib.Path) -> bool: |
| 241 | """Compile a module with the given name. The first path in `paths` is the module file, and the rest are its dependencies. Returns True if the module was recompiled, False if it was up to date.""" |
| 242 | module_file: pathlib.Path = paths[0] |
| 243 | if module_output_path.exists(): |
| 244 | module_output_mod: float = module_output_path.stat().st_mtime |
| 245 | if not any((path.exists() and path.stat().st_mtime > module_output_mod) for path in paths): |
| 246 | print_if_verbose(f'Module "{name}" is up to date, skipping compilation.', ANSI_INFO) |
| 247 | return False |
| 248 | try: |
| 249 | module_command: list[str] = [ |
| 250 | sys.executable, |
| 251 | str(pathlib.Path(__file__).resolve()), |
| 252 | # In the special case of GCC and the `std` module, `bits/std.cc` must be entered without the full path. |
| 253 | str(module_file) if not (compiler == "g++" and name == "std") else gcc_std_path, |
| 254 | f"--output={module_output_path.resolve()}", |
| 255 | f"--arch={args.arch}", |
| 256 | f"--compiler={compiler}", |
| 257 | f"--std={args.std}", |
| 258 | f"--type={args.type}", |
| 259 | # Note: Not adding the extra options from the configuration file, since they will be added by the script anyway. |
| 260 | *[f"--define={define}" for define in args.define], |
| 261 | *[f"--include={include}" for include in args.include], |
| 262 | *[f"--flag={flag}" for flag in args.flag], |
| 263 | # For the `std` module in GCC, we also need to add `-fsearch-include-path`. |
| 264 | *(["--flag=-fsearch-include-path"] if (compiler == "g++" and name == "std") else []), |
| 265 | # If compiling the `std` module itself, we need to pass `-u=disable` to avoid infinite recursion. Otherwise, we pass along the specified module path if it exists. |
| 266 | *(["--std-module=disable"] if name == "std" else [f"--std-module={std_module}"] if std_module is not None else []), |
| 267 | "--as-module", |
| 268 | *(["--verbose"] if args.verbose else []), |
| 269 | *(["--disable-exceptions=true"] if disable_exceptions else ["--disable-exceptions=false"]), |
| 270 | ] |
| 271 | print_separator() |
| 272 | print_if_verbose(f'Compiling module "{name}" with command: {subprocess.list2cmdline(module_command)}', ANSI_INFO) |
| 273 | _ = sys.stdout.flush() |
| 274 | module_result = subprocess.run( |
| 275 | args=module_command, |
| 276 | check=False, |
| 277 | text=True, |
| 278 | ) |
| 279 | if module_result.returncode != 0: |
| 280 | print_error_and_exit(f"Module compilation failed with return code: {module_result.returncode}.") |
| 281 | except Exception as exc: |
| 282 | print_error_and_exit(f"Could not compile module due to exception: {exc}.") |
| 283 | else: |
| 284 | return True |
| 285 | |
| 286 | |
| 287 | # Collect the full path(s) to the source file(s). |
no test coverage detected