From 2f432d148a109ed5100f754d5e0cd484f7d16d30 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Wed, 7 May 2025 14:26:57 +0800 Subject: [PATCH] Remove build artifacts; add dist & downloads to .gitignore --- .gitignore | 13 +- builds/linux/build-linux.sh | 34 +++ .../linux}/spc/libgeos-linux.php | 0 {docker => builds/linux}/spc/libgeos-unix.php | 0 .../linux/static-build.Dockerfile | 47 ++- builds/osx/build-osx.sh | 170 +++++++++++ builds/osx/spc/UnixBuilderBase-macos.php | 271 ++++++++++++++++++ builds/osx/spc/libgeos-macos.php | 12 + builds/osx/spc/libgeos-unix.php | 33 +++ 9 files changed, 575 insertions(+), 5 deletions(-) create mode 100644 builds/linux/build-linux.sh rename {docker => builds/linux}/spc/libgeos-linux.php (100%) rename {docker => builds/linux}/spc/libgeos-unix.php (100%) rename static-build.Dockerfile => builds/linux/static-build.Dockerfile (61%) create mode 100755 builds/osx/build-osx.sh create mode 100644 builds/osx/spc/UnixBuilderBase-macos.php create mode 100644 builds/osx/spc/libgeos-macos.php create mode 100644 builds/osx/spc/libgeos-unix.php diff --git a/.gitignore b/.gitignore index 183c4c43..f4877760 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,15 @@ packages/customer-portal # wip packages/solid solid -verdaccio \ No newline at end of file +verdaccio +# asdf +.tools-versions +# binary build resources +builds/osx/frankenphp +# build artifacts +/builds/dist/ +/builds/linux/spc/downloads/* +*.exe +*.dll +*.so +*.dylib \ No newline at end of file diff --git a/builds/linux/build-linux.sh b/builds/linux/build-linux.sh new file mode 100644 index 00000000..f788edb2 --- /dev/null +++ b/builds/linux/build-linux.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +set -e + +# Resolve the directory the script is located in +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" + +APP_NAME="Fleetbase" +IMAGE_NAME="fleetbase-linux-static" +CONTAINER_NAME="fleetbase-linux-build" +DIST_DIR="$ROOT_DIR/builds/dist" +BINARY_NAME="fleetbase-linux-x86_64" +DOCKERFILE="$ROOT_DIR/builds/linux/static-build.Dockerfile" + +# Build the image +echo "πŸ“¦ Building static Linux binary for ${APP_NAME}..." +docker build -f "$DOCKERFILE" -t "$IMAGE_NAME" . + +# Create a container from the built image +echo "πŸ“¦ Creating container to extract binary..." +docker create --name "$CONTAINER_NAME" "$IMAGE_NAME" + +# Make sure dist folder exist +mkdir -p "$DIST_DIR" + +# Copy binary from container to local dist folder +echo "πŸ“‚ Extracting binary..." +docker cp "$CONTAINER_NAME:/go/src/app/dist/frankenphp-linux-x86_64" "$DIST_DIR/$BINARY_NAME" + +# Cleanup the temp container +docker rm "$CONTAINER_NAME" + +echo "βœ… Build complete! Binary is located at: $DIST_DIR/$BINARY_NAME" \ No newline at end of file diff --git a/docker/spc/libgeos-linux.php b/builds/linux/spc/libgeos-linux.php similarity index 100% rename from docker/spc/libgeos-linux.php rename to builds/linux/spc/libgeos-linux.php diff --git a/docker/spc/libgeos-unix.php b/builds/linux/spc/libgeos-unix.php similarity index 100% rename from docker/spc/libgeos-unix.php rename to builds/linux/spc/libgeos-unix.php diff --git a/static-build.Dockerfile b/builds/linux/static-build.Dockerfile similarity index 61% rename from static-build.Dockerfile rename to builds/linux/static-build.Dockerfile index a6eadb4b..9d867bef 100644 --- a/static-build.Dockerfile +++ b/builds/linux/static-build.Dockerfile @@ -3,14 +3,33 @@ FROM --platform=linux/amd64 dunglas/frankenphp:static-builder WORKDIR /go/src/app # Copy Fleetbase app -COPY ./api ./dist/app +COPY ../../api ./dist/app + +# Set working directory to the embedded Fleetbase app +WORKDIR /go/src/app/dist/app + +# Setup for production environment +ENV APP_ENV=production +ENV APP_DEBUG=false +ENV BROADCAST_DRIVER=socketcluster +ENV OSRM_HOST="https://router.project-osrm.org" +ENV REGISTRY_PREINSTALLED_EXTENSIONS=true + +# Optional: Ensure writable storage +RUN chmod -R 775 bootstrap/cache storage + +# Set permissions for deploy script +RUN chmod +x ./deploy.sh + +# Move back to main app directory before running build-static.sh +WORKDIR /go/src/app # Install geos lib RUN apk add --no-cache geos geos-dev # Inject the libgeos library handlers -COPY ./docker/spc/libgeos-linux.php ./dist/static-php-cli/src/SPC/builder/linux/library/libgeos.php -COPY ./docker/spc/libgeos-unix.php ./dist/static-php-cli/src/SPC/builder/unix/library/libgeos.php +COPY ./builds/linux/spc/libgeos-linux.php ./dist/static-php-cli/src/SPC/builder/linux/library/libgeos.php +COPY ./builds/linux/spc/libgeos-unix.php ./dist/static-php-cli/src/SPC/builder/unix/library/libgeos.php # Patch source.json to add geos extension source RUN jq '. + {"php-geos": {"type": "url", "url": "https://github.com/libgeos/php-geos/archive/dfe1ab17b0f155cc315bc13c75689371676e02e1.zip", "license": [{"type": "file", "path": "php-geos-dfe1ab17b0f155cc315bc13c75689371676e02e1/MIT-LICENSE"}, {"type": "file", "path": "php-geos-dfe1ab17b0f155cc315bc13c75689371676e02e1/LGPL-2"}]}}' \ @@ -37,15 +56,35 @@ WORKDIR /go/src/app/dist/static-php-cli RUN composer install --no-dev -a # Set PHP extensions to be built (including geos!) -ENV PHP_EXTENSIONS="pdo_mysql,gd,bcmath,redis,intl,zip,gmp,apcu,opcache,imagick,sockets,pcntl,geos" +ENV PHP_EXTENSIONS="pdo_mysql,gd,bcmath,redis,intl,zip,gmp,apcu,opcache,imagick,sockets,pcntl,geos,iconv,mbstring,fileinfo,ctype,tokenizer,simplexml,dom,filter,session" ENV PHP_EXTENSION_LIBS="libgeos,libzip,bzip2,libxml2,openssl,zlib" # Force SPC to use the local source version (not download binary) ENV SPC_REL_TYPE=source +# Debug build +ENV SPC_LOG_LEVEL=debug + +# Skip compression +ENV NO_COMPRESS=1 + +# set PHP version +ENV PHP_VERSION=8.2 + # Move to the app directory WORKDIR /go/src/app +# Make sure pkg-config is available within the static build container +COPY ./builds/linux/spc/downloads/pkg-config-0.29.2.tar.gz ./dist/static-php-cli/downloads/pkg-config-0.29.2.tar.gz + +# Pre-build pkg-config using the existing tarball +RUN apk add --no-cache build-base && \ + tar -xzf ./dist/static-php-cli/downloads/pkg-config-0.29.2.tar.gz -C /tmp && \ + cd /tmp/pkg-config-0.29.2 && \ + ./configure --with-internal-glib --prefix=/go/src/app/dist/static-php-cli/build/bin && \ + make && make install && \ + rm -rf /tmp/pkg-config-0.29.2 + # Do not run git pull RUN sed -i 's/^[ \t]*git pull/# git pull/' ./build-static.sh diff --git a/builds/osx/build-osx.sh b/builds/osx/build-osx.sh new file mode 100755 index 00000000..c4454a26 --- /dev/null +++ b/builds/osx/build-osx.sh @@ -0,0 +1,170 @@ +#!/bin/bash + +set -e + +log() { + echo -e "\033[1;34m[πŸ”§ $1]\033[0m" +} + +log_success() { + echo -e "\033[1;32m[βœ… $1]\033[0m" +} + +log_warn() { + echo -e "\033[1;33m[⚠️ $1]\033[0m" +} + +log_error() { + echo -e "\033[1;31m[❌ $1]\033[0m" +} + +# Define base paths +log "Resolving directories..." +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" +OSX_DIR="$ROOT_DIR/builds/osx" +DIST_DIR="$ROOT_DIR/builds/dist" +APP_DIR="$ROOT_DIR/api" +BREW_PREFIX="/opt/homebrew" + +OS="$(uname -s | tr '[:upper:]' '[:lower:]')" +ARCH="$(uname -m)" +BINARY_NAME="fleetbase-$OS-$ARCH" + +log "Binary will be: $BINARY_NAME" + +# Setup PHP 8.4 +log "Detecting current PHP version..." +ORIGINAL_PHP_PATH="$(which php)" +ORIGINAL_PHP_VERSION="$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION.".".PHP_RELEASE_VERSION;' 2>/dev/null)" +IS_ASDF_MANAGED=false + +if [[ "$ORIGINAL_PHP_PATH" == *".asdf"* ]]; then + IS_ASDF_MANAGED=true +fi + +# πŸ” Trap to restore PHP when script exits +trap 'if [ "$IS_ASDF_MANAGED" = true ]; then + log "Restoring asdf-managed PHP version: $ORIGINAL_PHP_VERSION" + asdf set php "$ORIGINAL_PHP_VERSION" + log "Reverted to PHP $(php -v | head -n 1)" + else + log "Unsetting asdf set to restore system PHP" + asdf set php system + log "Reverted to PHP $(php -v | head -n 1)" + fi' EXIT + +log "Detected PHP version: $ORIGINAL_PHP_VERSION" +log "Detected PHP binary: $ORIGINAL_PHP_PATH" + +if ! asdf list php | grep -q "8.4.0"; then + # Use brew to install required dependencies for asdf php management + log "Checking and installing Homebrew packages required for PHP 8.4 build..." + + for pkg in autoconf automake bison freetype gd gettext icu4c krb5 libedit libiconv libjpeg libpng libxml2 libzip pkg-config re2c zlib sqlite3 libsodium oniguruma openssl@3 nasm; do + if ! brew list "$pkg" &>/dev/null; then + log_warn "$pkg not found. Installing..." + arch -arm64 brew install "$pkg" + else + log "$pkg already installed. Skipping." + fi + done + + # Set necessary env flags/paths for PHP build on OSX ARM64 + export CPPFLAGS="-I$BREW_PREFIX/opt/oniguruma/include -I$BREW_PREFIX/opt/libsodium/include -I$BREW_PREFIX/opt/bzip2/include -I$BREW_PREFIX/opt/zlib/include -I$BREW_PREFIX/opt/openssl@3/include -I$BREW_PREFIX/opt/libxml2/include -I$BREW_PREFIX/opt/libedit/include -I$BREW_PREFIX/opt/curl/include -I$BREW_PREFIX/opt/sqlite3/include -I$BREW_PREFIX/opt/freetype/include -I$BREW_PREFIX/opt/jpeg/include -I$BREW_PREFIX/opt/libpng/include -I$BREW_PREFIX/opt/libzip/include" + export LDFLAGS="-L$BREW_PREFIX/opt/openssl@3/lib -lssl -lcrypto -lz -L$BREW_PREFIX/opt/oniguruma/lib -lonig -L$BREW_PREFIX/opt/libsodium/lib -lsodium -L$BREW_PREFIX/opt/bzip2/lib -Wl,-rpath,$BREW_PREFIX/opt/bzip2/lib -lbz2 -L$BREW_PREFIX/opt/zlib/lib -L$BREW_PREFIX/opt/openssl@3/lib -L$BREW_PREFIX/opt/libxml2/lib -L$BREW_PREFIX/opt/libedit/lib -L$BREW_PREFIX/opt/sqlite3/lib -lsqlite3 -L$BREW_PREFIX/opt/curl/lib -lcurl -L$BREW_PREFIX/opt/freetype/lib -L$BREW_PREFIX/opt/jpeg/lib -L$BREW_PREFIX/opt/libpng/lib -L$BREW_PREFIX/opt/libzip/lib -lzip -lz" + export PKG_CONFIG_PATH="$BREW_PREFIX/opt/openssl/lib/pkgconfig:$BREW_PREFIX/opt/oniguruma/lib/pkgconfig:$BREW_PREFIX/opt/libsodium/lib/pkgconfig:$BREW_PREFIX/opt/libzip/lib/pkgconfig:$BREW_PREFIX/opt/gd/lib/pkgconfig:$BREW_PREFIX/opt/zlib/lib/pkgconfig:$BREW_PREFIX/opt/openssl@3/lib/pkgconfig:$BREW_PREFIX/opt/libxml2/lib/pkgconfig:$BREW_PREFIX/opt/curl/lib/pkgconfig:$BREW_PREFIX/opt/sqlite3/lib/pkgconfig:$BREW_PREFIX/opt/freetype/lib/pkgconfig:$BREW_PREFIX/opt/jpeg/lib/pkgconfig:$BREW_PREFIX/opt/libpng/lib/pkgconfig" + export PHP_CONFIGURE_OPTIONS="--with-openssl=$(brew --prefix openssl) --with-iconv=$(brew --prefix libiconv)" + + log "Installing PHP 8.4.0 with asdf..." + asdf install php 8.4.0 --verbose +fi + +log "Switching to PHP 8.4.0 with asdf set..." +asdf set php 8.4.0 --home + +# Clone FrankenPHP +if [ ! -d "$OSX_DIR/frankenphp" ]; then + log "Cloning FrankenPHP..." + git clone https://github.com/dunglas/frankenphp "$OSX_DIR/frankenphp" +else + log_warn "FrankenPHP already cloned. Skipping." +fi + +cd "$OSX_DIR/frankenphp" + +# Patch build script +log "Patching build-static.sh to skip git pull..." +sed -i '' 's/^[ \t]*git pull/# git pull/' ./build-static.sh + +# Set environment variables +log "Exporting build environment variables..." +export PHP_VERSION=8.2 +export PHP_EXTENSIONS="pdo_mysql,gd,bcmath,redis,intl,zip,gmp,apcu,opcache,imagick,sockets,pcntl,geos,iconv,mbstring,fileinfo,ctype,tokenizer,simplexml,dom,filter,session" +export PHP_EXTENSION_LIBS="libgeos,libzip,bzip2,libxml2,openssl,zlib" +export SPC_REL_TYPE=source +export NO_COMPRESS=1 +export SPC_OPT_BUILD_ARGS="--debug" +export CMAKE_OSX_ARCHITECTURES=arm64 + +# Clone and prepare static-php-cli in dist/ +STATIC_PHP_CLI_DIR="$OSX_DIR/frankenphp/dist/static-php-cli" +if [ ! -d "$STATIC_PHP_CLI_DIR" ]; then + log "Cloning static-php-cli into dist/..." + git clone https://github.com/crazywhalecc/static-php-cli.git "$STATIC_PHP_CLI_DIR" +else + log_warn "static-php-cli already exists in dist/. Skipping clone." +fi + +# Inject libgeos support +log "Injecting libgeos patch files..." +cp "$ROOT_DIR/builds/osx/spc/libgeos-unix.php" "$STATIC_PHP_CLI_DIR/src/SPC/builder/unix/library/libgeos.php" +cp "$ROOT_DIR/builds/osx/spc/libgeos-macos.php" "$STATIC_PHP_CLI_DIR/src/SPC/builder/macos/library/libgeos.php" +cp "$ROOT_DIR/builds/osx/spc/UnixBuilderBase-macos.php" "$STATIC_PHP_CLI_DIR/src/SPC/builder/unix/UnixBuilderBase.php" + +# Patch SPC config +log "Patching SPC config files (source.json, ext.json, lib.json)..." +jq '. + {"php-geos": {"type": "url", "url": "https://github.com/libgeos/php-geos/archive/dfe1ab17b0f155cc315bc13c75689371676e02e1.zip", "license": [{"type": "file", "path": "php-geos-dfe1ab17b0f155cc315bc13c75689371676e02e1/MIT-LICENSE"}, {"type": "file", "path": "php-geos-dfe1ab17b0f155cc315bc13c75689371676e02e1/LGPL-2"}]}}' \ + "$STATIC_PHP_CLI_DIR/config/source.json" > "$STATIC_PHP_CLI_DIR/config/source.tmp.json" && \ + mv "$STATIC_PHP_CLI_DIR/config/source.tmp.json" "$STATIC_PHP_CLI_DIR/config/source.json" + +jq '. + {"libgeos": {"type": "url", "url": "https://download.osgeo.org/geos/geos-3.12.1.tar.bz2", "filename": "geos-3.12.1.tar.bz2", "extract": "geos-3.12.1", "build-dir": "build", "license": [{"type": "file", "path": "COPYING"}]}}' \ + "$STATIC_PHP_CLI_DIR/config/source.json" > "$STATIC_PHP_CLI_DIR/config/source.tmp.json" && \ + mv "$STATIC_PHP_CLI_DIR/config/source.tmp.json" "$STATIC_PHP_CLI_DIR/config/source.json" + +jq '. + {"libgeos": {"source": "libgeos", "static-libs-unix": ["libgeos.a", "libgeos_c.a"]}}' \ + "$STATIC_PHP_CLI_DIR/config/lib.json" > "$STATIC_PHP_CLI_DIR/config/lib.tmp.json" && \ + mv "$STATIC_PHP_CLI_DIR/config/lib.tmp.json" "$STATIC_PHP_CLI_DIR/config/lib.json" + +jq '. + {"geos": {"type": "external", "arg-type": "enable", "source": "php-geos", "lib-depends": ["libgeos"]}}' \ + "$STATIC_PHP_CLI_DIR/config/ext.json" > "$STATIC_PHP_CLI_DIR/config/ext.tmp.json" && \ + mv "$STATIC_PHP_CLI_DIR/config/ext.tmp.json" "$STATIC_PHP_CLI_DIR/config/ext.json" + +# Prepare app embed folder +log "πŸ“¦ Preparing embedded app directory..." +rm -rf ./dist/app +mkdir -p ./dist/app +cp -R "$APP_DIR"/* ./dist/app/ + +log "Patching build-static.sh to skip git pull and composer install..." + +# Skip `git pull` +sed -i '' 's/^[[:space:]]*git pull/# git pull/' "$OSX_DIR/frankenphp/build-static.sh" + +# Patch add CoreServices framework for Caddy build on OSX +sed -i '' 's/-framework CoreFoundation -framework SystemConfiguration/& -framework CoreServices/' "$OSX_DIR/frankenphp/build-static.sh" + +# Build the binary +log "βš™οΈ Running FrankenPHP build-static.sh..." +EMBED=dist/app ./build-static.sh + +# Move built binary to dist +log "Moving built binary to output folder..." +mkdir -p "$DIST_DIR" +mv dist/frankenphp-mac-$ARCH "$DIST_DIR/$BINARY_NAME" + +log_success "βœ… macOS binary built at: $DIST_DIR/$BINARY_NAME" + +# Clean up frankenphp build and app embed folder +log "🧹 Cleaning temporary app directory..." +rm -rf "$OSX_DIR/frankenphp" \ No newline at end of file diff --git a/builds/osx/spc/UnixBuilderBase-macos.php b/builds/osx/spc/UnixBuilderBase-macos.php new file mode 100644 index 00000000..175e84c3 --- /dev/null +++ b/builds/osx/spc/UnixBuilderBase-macos.php @@ -0,0 +1,271 @@ +libs as $lib) { + foreach ($lib->getDependencies() as $dep) { + $libs[] = $dep; + } + $libs[] = $lib; + } + + $libFiles = []; + $libNames = []; + // merge libs + foreach ($libs as $lib) { + if (!in_array($lib::NAME, $libNames, true)) { + $libNames[] = $lib::NAME; + array_unshift($libFiles, ...$lib->getStaticLibs()); + } + } + return array_map(fn ($x) => realpath(BUILD_LIB_PATH . "/{$x}"), $libFiles); + } + + /** + * Return generic cmake options when configuring cmake projects + */ + public function makeCmakeArgs(): string + { + $extra = $this instanceof LinuxBuilder ? '-DCMAKE_C_COMPILER=' . getenv('CC') . ' ' : ''; + + // NEW: allow env-variable override + $arch = getenv('CMAKE_OSX_ARCHITECTURES') ?: 'arm64'; + + return $extra . + '-DCMAKE_BUILD_TYPE=Release ' . + '-DCMAKE_INSTALL_PREFIX=' . BUILD_ROOT_PATH . ' ' . + '-DCMAKE_INSTALL_BINDIR=bin ' . + '-DCMAKE_INSTALL_LIBDIR=lib ' . + '-DCMAKE_INSTALL_INCLUDEDIR=include ' . + "-DCMAKE_OSX_ARCHITECTURES={$arch} " . + "-DCMAKE_TOOLCHAIN_FILE={$this->cmake_toolchain_file}"; + } + + /** + * Generate configure flags + */ + public function makeAutoconfFlags(int $flag = AUTOCONF_ALL): string + { + $extra = ''; + // TODO: add auto pkg-config support + if (($flag & AUTOCONF_LIBS) === AUTOCONF_LIBS) { + $extra .= 'LIBS="' . BUILD_LIB_PATH . '" '; + } + if (($flag & AUTOCONF_CFLAGS) === AUTOCONF_CFLAGS) { + $extra .= 'CFLAGS="-I' . BUILD_INCLUDE_PATH . '" '; + } + if (($flag & AUTOCONF_CPPFLAGS) === AUTOCONF_CPPFLAGS) { + $extra .= 'CPPFLAGS="-I' . BUILD_INCLUDE_PATH . '" '; + } + if (($flag & AUTOCONF_LDFLAGS) === AUTOCONF_LDFLAGS) { + $extra .= 'LDFLAGS="-L' . BUILD_LIB_PATH . '" '; + } + return $extra; + } + + public function proveLibs(array $sorted_libraries): void + { + // search all supported libs + $support_lib_list = []; + $classes = FileSystem::getClassesPsr4( + ROOT_DIR . '/src/SPC/builder/' . osfamily2dir() . '/library', + 'SPC\builder\\' . osfamily2dir() . '\library' + ); + foreach ($classes as $class) { + if (defined($class . '::NAME') && $class::NAME !== 'unknown' && Config::getLib($class::NAME) !== null) { + $support_lib_list[$class::NAME] = $class; + } + } + + // if no libs specified, compile all supported libs + if ($sorted_libraries === [] && $this->isLibsOnly()) { + $libraries = array_keys($support_lib_list); + $sorted_libraries = DependencyUtil::getLibs($libraries); + } + + // add lib object for builder + foreach ($sorted_libraries as $library) { + if (!in_array(Config::getLib($library, 'type', 'lib'), ['lib', 'package'])) { + continue; + } + // if some libs are not supported (but in config "lib.json", throw exception) + if (!isset($support_lib_list[$library])) { + throw new WrongUsageException('library [' . $library . '] is in the lib.json list but not supported to compile, but in the future I will support it!'); + } + $lib = new ($support_lib_list[$library])($this); + $this->addLib($lib); + } + + // calculate and check dependencies + foreach ($this->libs as $lib) { + $lib->calcDependency(); + } + $this->lib_list = $sorted_libraries; + } + + /** + * Sanity check after build complete + * + * @throws RuntimeException + */ + protected function sanityCheck(int $build_target): void + { + // sanity check for php-cli + if (($build_target & BUILD_TARGET_CLI) === BUILD_TARGET_CLI) { + logger()->info('running cli sanity check'); + [$ret, $output] = shell()->execWithResult(BUILD_ROOT_PATH . '/bin/php -n -r "echo \"hello\";"'); + $raw_output = implode('', $output); + if ($ret !== 0 || trim($raw_output) !== 'hello') { + throw new RuntimeException("cli failed sanity check: ret[{$ret}]. out[{$raw_output}]"); + } + + foreach ($this->getExts(false) as $ext) { + logger()->debug('testing ext: ' . $ext->getName()); + $ext->runCliCheckUnix(); + } + } + + // sanity check for phpmicro + if (($build_target & BUILD_TARGET_MICRO) === BUILD_TARGET_MICRO) { + $test_task = $this->getMicroTestTasks(); + foreach ($test_task as $task_name => $task) { + $test_file = SOURCE_PATH . '/' . $task_name . '.exe'; + if (file_exists($test_file)) { + @unlink($test_file); + } + file_put_contents($test_file, file_get_contents(SOURCE_PATH . '/php-src/sapi/micro/micro.sfx') . $task['content']); + chmod($test_file, 0755); + [$ret, $out] = shell()->execWithResult($test_file); + foreach ($task['conditions'] as $condition => $closure) { + if (!$closure($ret, $out)) { + $raw_out = trim(implode('', $out)); + throw new RuntimeException("micro failed sanity check: {$task_name}, condition [{$condition}], ret[{$ret}], out[{$raw_out}]"); + } + } + } + } + + // sanity check for embed + if (($build_target & BUILD_TARGET_EMBED) === BUILD_TARGET_EMBED) { + logger()->info('running embed sanity check'); + $sample_file_path = SOURCE_PATH . '/embed-test'; + if (!is_dir($sample_file_path)) { + @mkdir($sample_file_path); + } + // copy embed test files + copy(ROOT_DIR . '/src/globals/common-tests/embed.c', $sample_file_path . '/embed.c'); + copy(ROOT_DIR . '/src/globals/common-tests/embed.php', $sample_file_path . '/embed.php'); + $util = new SPCConfigUtil($this); + $config = $util->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); + $lens = "{$config['cflags']} {$config['ldflags']} {$config['libs']}"; + if (PHP_OS_FAMILY === 'Linux' && getenv('SPC_LIBC') === 'musl') { + $lens .= ' -static'; + } + [$ret, $out] = shell()->cd($sample_file_path)->execWithResult(getenv('CC') . ' -o embed embed.c ' . $lens); + if ($ret !== 0) { + throw new RuntimeException('embed failed sanity check: build failed. Error message: ' . implode("\n", $out)); + } + // if someone changed to --enable-embed=shared, we need to add LD_LIBRARY_PATH + if (getenv('SPC_CMD_VAR_PHP_EMBED_TYPE') === 'shared') { + $ext_path = 'LD_LIBRARY_PATH=' . BUILD_ROOT_PATH . '/lib:$LD_LIBRARY_PATH '; + FileSystem::removeFileIfExists(BUILD_ROOT_PATH . '/lib/libphp.a'); + } else { + $ext_path = ''; + FileSystem::removeFileIfExists(BUILD_ROOT_PATH . '/lib/libphp.so'); + } + [$ret, $output] = shell()->cd($sample_file_path)->execWithResult($ext_path . './embed'); + if ($ret !== 0 || trim(implode('', $output)) !== 'hello') { + throw new RuntimeException('embed failed sanity check: run failed. Error message: ' . implode("\n", $output)); + } + } + } + + /** + * ε°†ηΌ–θ―‘ε₯½ηš„δΊŒθΏ›εˆΆζ–‡δ»Άε‘εΈƒεˆ° buildroot + * + * @param int $type ε‘εΈƒη±»εž‹ + * @throws RuntimeException + * @throws FileSystemException + */ + protected function deployBinary(int $type): bool + { + $src = match ($type) { + BUILD_TARGET_CLI => SOURCE_PATH . '/php-src/sapi/cli/php', + BUILD_TARGET_MICRO => SOURCE_PATH . '/php-src/sapi/micro/micro.sfx', + BUILD_TARGET_FPM => SOURCE_PATH . '/php-src/sapi/fpm/php-fpm', + default => throw new RuntimeException('Deployment does not accept type ' . $type), + }; + logger()->info('Deploying ' . $this->getBuildTypeName($type) . ' file'); + FileSystem::createDir(BUILD_ROOT_PATH . '/bin'); + shell()->exec('cp ' . escapeshellarg($src) . ' ' . escapeshellarg(BUILD_ROOT_PATH . '/bin/')); + return true; + } + + /** + * Run php clean + * + * @throws RuntimeException + */ + protected function cleanMake(): void + { + logger()->info('cleaning up'); + shell()->cd(SOURCE_PATH . '/php-src')->exec('make clean'); + } + + /** + * Patch phpize and php-config if needed + * @throws FileSystemException + */ + protected function patchPhpScripts(): void + { + // patch phpize + if (file_exists(BUILD_BIN_PATH . '/phpize')) { + logger()->debug('Patching phpize prefix'); + FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', "prefix=''", "prefix='" . BUILD_ROOT_PATH . "'"); + FileSystem::replaceFileStr(BUILD_BIN_PATH . '/phpize', 's##', 's#/usr/local#'); + } + // patch php-config + if (file_exists(BUILD_BIN_PATH . '/php-config')) { + logger()->debug('Patching php-config prefix and libs order'); + $php_config_str = FileSystem::readFile(BUILD_BIN_PATH . '/php-config'); + $php_config_str = str_replace('prefix=""', 'prefix="' . BUILD_ROOT_PATH . '"', $php_config_str); + // move mimalloc to the beginning of libs + $php_config_str = preg_replace('/(libs=")(.*?)\s*(' . preg_quote(BUILD_LIB_PATH, '/') . '\/mimalloc\.o)\s*(.*?)"/', '$1$3 $2 $4"', $php_config_str); + // move lstdc++ to the end of libs + $php_config_str = preg_replace('/(libs=")(.*?)\s*(-lstdc\+\+)\s*(.*?)"/', '$1$2 $4 $3"', $php_config_str); + FileSystem::writeFile(BUILD_BIN_PATH . '/php-config', $php_config_str); + } + } +} diff --git a/builds/osx/spc/libgeos-macos.php b/builds/osx/spc/libgeos-macos.php new file mode 100644 index 00000000..6175332c --- /dev/null +++ b/builds/osx/spc/libgeos-macos.php @@ -0,0 +1,12 @@ +source_dir . '/build'); + + shell()->cd($this->source_dir . '/build') + ->setEnv([ + 'CFLAGS' => $this->getLibExtraCFlags(), + 'LDFLAGS' => $this->getLibExtraLdFlags(), + 'LIBS' => $this->getLibExtraLibs(), + ]) + ->execWithEnv("cmake {$this->builder->makeCmakeArgs()} -DBUILD_SHARED_LIBS=OFF ..") + ->execWithEnv("make -j{$this->builder->concurrency}") + ->execWithEnv('make install'); + + $this->patchPkgconfPrefix(['geos.pc']); + } +} \ No newline at end of file