first commit
This commit is contained in:
commit
5893b00dd2
1669 changed files with 1982740 additions and 0 deletions
293
libraries/FastLED/ci/cpp_test_compile.py
Normal file
293
libraries/FastLED/ci/cpp_test_compile.py
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
import argparse
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Tuple
|
||||
|
||||
from ci.paths import PROJECT_ROOT
|
||||
from ci.running_process import RunningProcess
|
||||
|
||||
BUILD_DIR = PROJECT_ROOT / "tests" / ".build"
|
||||
BUILD_DIR.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def clean_build_directory():
|
||||
print("Cleaning build directory...")
|
||||
shutil.rmtree(BUILD_DIR, ignore_errors=True)
|
||||
BUILD_DIR.mkdir(parents=True, exist_ok=True)
|
||||
print("Build directory cleaned.")
|
||||
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
|
||||
WASM_BUILD = False
|
||||
USE_ZIG = False
|
||||
USE_CLANG = False
|
||||
|
||||
|
||||
def _has_system_clang_compiler() -> bool:
|
||||
CLANG = shutil.which("clang")
|
||||
CLANGPP = shutil.which("clang++")
|
||||
LLVM_AR = shutil.which("llvm-ar")
|
||||
return CLANG is not None and CLANGPP is not None and LLVM_AR is not None
|
||||
|
||||
|
||||
def use_clang_compiler() -> Tuple[Path, Path, Path]:
|
||||
assert _has_system_clang_compiler(), "Clang system compiler not found"
|
||||
CLANG = shutil.which("clang")
|
||||
CLANGPP = shutil.which("clang++")
|
||||
LLVM_AR = shutil.which("llvm-ar")
|
||||
assert CLANG is not None, "clang compiler not found"
|
||||
assert CLANGPP is not None, "clang++ compiler not found"
|
||||
assert LLVM_AR is not None, "llvm-ar not found"
|
||||
# Set environment variables for C and C++ compilers
|
||||
os.environ["CC"] = CLANG
|
||||
os.environ["CXX"] = CLANGPP
|
||||
os.environ["AR"] = LLVM_AR
|
||||
|
||||
os.environ["CXXFLAGS"] = os.environ.get("CXXFLAGS", "") + " -ferror-limit=1"
|
||||
os.environ["CFLAGS"] = os.environ.get("CFLAGS", "") + " -ferror-limit=1"
|
||||
|
||||
if WASM_BUILD:
|
||||
wasm_flags = [
|
||||
"--target=wasm32",
|
||||
"-O3",
|
||||
"-flto",
|
||||
# "-nostdlib",
|
||||
# "-Wl,--no-entry",
|
||||
# "-Wl,--export-all",
|
||||
# "-Wl,--lto-O3",
|
||||
# "-Wl,-z,stack-size=8388608", # 8 * 1024 * 1024 (8MiB)
|
||||
]
|
||||
os.environ["CFLAGS"] = " ".join(wasm_flags)
|
||||
os.environ["CXXFLAGS"] = " ".join(wasm_flags)
|
||||
|
||||
print(f"CC: {CLANG}")
|
||||
print(f"CXX: {CLANGPP}")
|
||||
print(f"AR: {LLVM_AR}")
|
||||
|
||||
return Path(CLANG), Path(CLANGPP), Path(LLVM_AR)
|
||||
|
||||
|
||||
def use_zig_compiler() -> Tuple[Path, Path, Path]:
|
||||
assert 0 == os.system(
|
||||
"uv run python -m ziglang version"
|
||||
), "Zig-clang compiler not found"
|
||||
uv_path_str: str | None = shutil.which("uv")
|
||||
assert uv_path_str is not None, "uv not found in PATH"
|
||||
uv_path = Path(uv_path_str).resolve()
|
||||
zig_command = f'"{uv_path}" run python -m ziglang'
|
||||
# We are going to build up shell scripts that look like cc, c++, and ar. It will contain the actual build command.
|
||||
CC_PATH = BUILD_DIR / "cc"
|
||||
CXX_PATH = BUILD_DIR / "c++"
|
||||
AR_PATH = BUILD_DIR / "ar"
|
||||
if sys.platform == "win32":
|
||||
CC_PATH = CC_PATH.with_suffix(".cmd")
|
||||
CXX_PATH = CXX_PATH.with_suffix(".cmd")
|
||||
AR_PATH = AR_PATH.with_suffix(".cmd")
|
||||
CC_PATH.write_text(f"@echo off\n{zig_command} cc %* 2>&1\n")
|
||||
CXX_PATH.write_text(f"@echo off\n{zig_command} c++ %* 2>&1\n")
|
||||
AR_PATH.write_text(f"@echo off\n{zig_command} ar %* 2>&1\n")
|
||||
else:
|
||||
cc_cmd = f'#!/bin/bash\n{zig_command} cc "$@"\n'
|
||||
cxx_cmd = f'#!/bin/bash\n{zig_command} c++ "$@"\n'
|
||||
ar_cmd = f'#!/bin/bash\n{zig_command} ar "$@"\n'
|
||||
CC_PATH.write_text(cc_cmd)
|
||||
CXX_PATH.write_text(cxx_cmd)
|
||||
AR_PATH.write_text(ar_cmd)
|
||||
CC_PATH.chmod(0o755)
|
||||
CXX_PATH.chmod(0o755)
|
||||
AR_PATH.chmod(0o755)
|
||||
|
||||
# if WASM_BUILD:
|
||||
# wasm_flags = [
|
||||
# # "--target=wasm32",
|
||||
# # "-O3",
|
||||
# # "-flto",
|
||||
# # "-nostdlib",
|
||||
# "-Wl,--no-entry",
|
||||
# # "-Wl,--export-all",
|
||||
# # "-Wl,--lto-O3",
|
||||
# "-Wl,-z,stack-size=8388608", # 8 * 1024 * 1024 (8MiB)
|
||||
# ]
|
||||
# os.environ["CFLAGS"] = " ".join(wasm_flags)
|
||||
# os.environ["CXXFLAGS"] = " ".join(wasm_flags)
|
||||
|
||||
cc, cxx = CC_PATH, CXX_PATH
|
||||
# use the system path, so on windows this looks like "C:\Program Files\Zig\zig.exe"
|
||||
cc_path: Path | str = cc.resolve()
|
||||
cxx_path: Path | str = cxx.resolve()
|
||||
if sys.platform == "win32":
|
||||
cc_path = str(cc_path).replace("/", "\\")
|
||||
cxx_path = str(cxx_path).replace("/", "\\")
|
||||
|
||||
# print out the paths
|
||||
print(f"CC: {cc_path}")
|
||||
print(f"CXX: {cxx_path}")
|
||||
print(f"AR: {AR_PATH}")
|
||||
# sys.exit(1)
|
||||
|
||||
# Set environment variables for C and C++ compilers
|
||||
os.environ["CC"] = str(cc_path)
|
||||
os.environ["CXX"] = str(cxx_path)
|
||||
os.environ["AR"] = str(AR_PATH)
|
||||
return CC_PATH, CXX_PATH, AR_PATH
|
||||
|
||||
|
||||
def run_command(command: str, cwd: Path | None = None) -> None:
|
||||
process = RunningProcess(command, cwd=cwd)
|
||||
process.wait()
|
||||
if process.returncode != 0:
|
||||
print(f"{Path(__file__).name}: Error executing command: {command}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def compile_fastled(specific_test: str | None = None) -> None:
|
||||
if USE_ZIG:
|
||||
print("USING ZIG COMPILER")
|
||||
rtn = subprocess.run(
|
||||
"python -m ziglang version", shell=True, capture_output=True
|
||||
).returncode
|
||||
zig_is_installed = rtn == 0
|
||||
assert (
|
||||
zig_is_installed
|
||||
), 'Zig compiler not when using "python -m ziglang version" command'
|
||||
use_zig_compiler()
|
||||
elif USE_CLANG:
|
||||
print("USING CLANG COMPILER")
|
||||
use_clang_compiler()
|
||||
|
||||
cmake_configure_command_list: list[str] = [
|
||||
"cmake",
|
||||
"-S",
|
||||
str(PROJECT_ROOT / "tests"),
|
||||
"-B",
|
||||
str(BUILD_DIR),
|
||||
"-G",
|
||||
"Ninja",
|
||||
"-DCMAKE_VERBOSE_MAKEFILE=ON",
|
||||
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
|
||||
]
|
||||
|
||||
if WASM_BUILD:
|
||||
cmake_configure_command_list.extend(
|
||||
[
|
||||
"-DCMAKE_C_COMPILER_TARGET=wasm32-wasi",
|
||||
"-DCMAKE_CXX_COMPILER_TARGET=wasm32-wasi",
|
||||
"-DCMAKE_C_COMPILER_WORKS=TRUE",
|
||||
"-DCMAKE_CXX_COMPILER_WORKS=TRUE",
|
||||
"-DCMAKE_SYSTEM_NAME=Generic",
|
||||
"-DCMAKE_CROSSCOMPILING=TRUE",
|
||||
"-DCMAKE_EXE_LINKER_FLAGS=-Wl,--no-entry -Wl,--export-all -Wl,--lto-O3 -Wl,-z,stack-size=8388608",
|
||||
]
|
||||
)
|
||||
|
||||
cmake_configure_command = subprocess.list2cmdline(cmake_configure_command_list)
|
||||
run_command(cmake_configure_command, cwd=BUILD_DIR)
|
||||
|
||||
# Build the project
|
||||
if specific_test:
|
||||
cmake_build_command = f"cmake --build {BUILD_DIR} --target test_{specific_test}"
|
||||
else:
|
||||
cmake_build_command = f"cmake --build {BUILD_DIR}"
|
||||
run_command(cmake_build_command)
|
||||
|
||||
print("FastLED library compiled successfully.")
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Compile FastLED library with different compiler options."
|
||||
)
|
||||
parser.add_argument("--use-zig", action="store_true", help="Use Zig compiler")
|
||||
parser.add_argument("--use-clang", action="store_true", help="Use Clang compiler")
|
||||
parser.add_argument("--wasm", action="store_true", help="Build for WebAssembly")
|
||||
parser.add_argument(
|
||||
"--clean",
|
||||
action="store_true",
|
||||
help="Clean the build directory before compiling",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--test",
|
||||
help="Specific test to compile (without test_ prefix)",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def get_build_info(args: argparse.Namespace) -> dict[str, str | dict[str, str]]:
|
||||
return {
|
||||
"USE_ZIG": str(USE_ZIG),
|
||||
"USE_CLANG": str(USE_CLANG),
|
||||
"WASM_BUILD": str(WASM_BUILD),
|
||||
"CC": os.environ.get("CC", ""),
|
||||
"CXX": os.environ.get("CXX", ""),
|
||||
"AR": os.environ.get("AR", ""),
|
||||
"CFLAGS": os.environ.get("CFLAGS", ""),
|
||||
"CXXFLAGS": os.environ.get("CXXFLAGS", ""),
|
||||
"ARGS": {
|
||||
"use_zig": str(args.use_zig),
|
||||
"use_clang": str(args.use_clang),
|
||||
"wasm": str(args.wasm),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def should_clean_build(build_info: dict[str, str | dict[str, str]]) -> bool:
|
||||
build_info_file = BUILD_DIR / "build_info.json"
|
||||
if not build_info_file.exists():
|
||||
return True
|
||||
|
||||
with open(build_info_file, "r") as f:
|
||||
old_build_info = json.load(f)
|
||||
|
||||
return old_build_info != build_info
|
||||
|
||||
|
||||
def update_build_info(build_info: dict[str, str | dict[str, str]]):
|
||||
build_info_file = BUILD_DIR / "build_info.json"
|
||||
with open(build_info_file, "w") as f:
|
||||
json.dump(build_info, f, indent=2)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
global USE_ZIG, USE_CLANG, WASM_BUILD
|
||||
|
||||
args = parse_arguments()
|
||||
USE_ZIG = args.use_zig # use Zig's clang compiler
|
||||
USE_CLANG = args.use_clang # Use pure Clang for WASM builds
|
||||
WASM_BUILD = args.wasm
|
||||
|
||||
using_gcc = not USE_ZIG and not USE_CLANG and not WASM_BUILD
|
||||
if using_gcc:
|
||||
if not shutil.which("g++"):
|
||||
print(
|
||||
"gcc compiler not found in PATH, falling back zig's built in clang compiler"
|
||||
)
|
||||
USE_ZIG = True
|
||||
USE_CLANG = False
|
||||
|
||||
if USE_CLANG:
|
||||
if not _has_system_clang_compiler():
|
||||
print(
|
||||
"Clang compiler not found in PATH, falling back to Zig-clang compiler"
|
||||
)
|
||||
USE_ZIG = True
|
||||
USE_CLANG = False
|
||||
|
||||
os.chdir(str(HERE))
|
||||
print(f"Current directory: {Path('.').absolute()}")
|
||||
|
||||
build_info = get_build_info(args)
|
||||
if args.clean or should_clean_build(build_info):
|
||||
clean_build_directory()
|
||||
|
||||
compile_fastled(args.test)
|
||||
update_build_info(build_info)
|
||||
print("FastLED library compiled successfully.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue