From 521af84797447ac281f24e8f3c908424d125d645 Mon Sep 17 00:00:00 2001 From: crazywhalecc Date: Mon, 9 Jun 2025 00:16:18 +0800 Subject: [PATCH] Add cmake executor and default library path var wrapper --- src/SPC/builder/LibraryBase.php | 15 ++ src/SPC/builder/unix/executor/Executor.php | 22 +++ .../unix/executor/UnixCMakeExecutor.php | 180 ++++++++++++++++++ 3 files changed, 217 insertions(+) create mode 100644 src/SPC/builder/unix/executor/Executor.php create mode 100644 src/SPC/builder/unix/executor/UnixCMakeExecutor.php diff --git a/src/SPC/builder/LibraryBase.php b/src/SPC/builder/LibraryBase.php index abf9dd50..0d8ab739 100644 --- a/src/SPC/builder/LibraryBase.php +++ b/src/SPC/builder/LibraryBase.php @@ -328,6 +328,21 @@ abstract class LibraryBase return false; } + public function getIncludeDir(): string + { + return BUILD_INCLUDE_PATH; + } + + public function getBuildRootPath(): string + { + return BUILD_ROOT_PATH; + } + + public function getLibDir(): string + { + return BUILD_LIB_PATH; + } + /** * Build this library. * diff --git a/src/SPC/builder/unix/executor/Executor.php b/src/SPC/builder/unix/executor/Executor.php new file mode 100644 index 00000000..0d50d49a --- /dev/null +++ b/src/SPC/builder/unix/executor/Executor.php @@ -0,0 +1,22 @@ +initCMakeBuildDir(); + FileSystem::resetDir($this->cmake_build_dir); + + // prepare environment variables + $env = [ + 'CFLAGS' => $this->library->getLibExtraCFlags(), + 'LDFLAGS' => $this->library->getLibExtraLdFlags(), + 'LIBS' => $this->library->getLibExtraLibs(), + ]; + + // prepare shell + $shell = shell()->cd($this->cmake_build_dir)->setEnv($env); + + // config + $shell->execWithEnv("cmake {$this->getConfigureArgs()} {$this->getDefaultCMakeArgs()}"); + + // make + $shell->execWithEnv("cmake --build . -j {$this->library->getBuilder()->concurrency}"); + + // install + $shell->execWithEnv('make install'); + } + + /** + * Add optional library configuration. + * This method checks if a library is available and adds the corresponding arguments to the CMake configuration. + * + * @param string $name library name to check + * @param string $true_args arguments to use if the library is available + * @param string $false_args arguments to use if the library is not available + * @return $this + */ + public function optionalLib(string $name, string $true_args, string $false_args = ''): static + { + $this->addConfigureArgs($this->library->getBuilder()->getLib($name) ? $true_args : $false_args); + return $this; + } + + /** + * Add configure args. + */ + public function addConfigureArgs(...$args): static + { + $this->configure_args = [$this->configure_args, ...$args]; + return $this; + } + + /** + * Set custom CMake build directory. + * + * @param string $dir custom CMake build directory + */ + public function setCMakeBuildDir(string $dir): static + { + $this->cmake_build_dir = $dir; + return $this; + } + + /** + * Set the custom default args. + */ + public function setCustomDefaultArgs(...$args): static + { + $this->custom_default_args = $args; + return $this; + } + + /** + * Get configure argument line. + */ + private function getConfigureArgs(): string + { + return implode(' ', $this->configure_args); + } + + /** + * @throws WrongUsageException + * @throws FileSystemException + */ + private function getDefaultCMakeArgs(): string + { + return implode(' ', $this->custom_default_args ?? [ + '-DCMAKE_BUILD_TYPE=Release', + "-DCMAKE_INSTALL_PREFIX={$this->library->getBuildRootPath()}", + '-DCMAKE_INSTALL_BINDIR=bin', + '-DCMAKE_INSTALL_LIBDIR=lib', + '-DCMAKE_INSTALL_INCLUDE_DIR=include', + "-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}", + '..', + ]); + } + + /** + * Initialize the CMake build directory. + * If the directory is not set, it defaults to the library's source directory with '/build' appended. + * + * @throws FileSystemException + */ + private function initCMakeBuildDir(): void + { + if ($this->cmake_build_dir === null) { + $this->cmake_build_dir = "{$this->library->getSourceDir()}/build"; + } + FileSystem::resetDir($this->cmake_build_dir); + } + + /** + * @return string CMake toolchain file path + * @throws FileSystemException + * @throws WrongUsageException + */ + private function makeCmakeToolchainFile(): string + { + static $created; + if (isset($created)) { + return $created; + } + $os = PHP_OS_FAMILY; + $target_arch = arch2gnu(php_uname('m')); + $cflags = getenv('SPC_DEFAULT_C_FLAGS'); + $cc = getenv('CC'); + $cxx = getenv('CCX'); + logger()->debug("making cmake tool chain file for {$os} {$target_arch} with CFLAGS='{$cflags}'"); + $root = BUILD_ROOT_PATH; + $ccLine = ''; + if ($cc) { + $ccLine = 'SET(CMAKE_C_COMPILER ' . $cc . ')'; + } + $cxxLine = ''; + if ($cxx) { + $cxxLine = 'SET(CMAKE_CXX_COMPILER ' . $cxx . ')'; + } + $toolchain = <<