diff --git a/bin/_config.sh b/bin/_config.sh index fa3bfa5..e92b0d6 100644 --- a/bin/_config.sh +++ b/bin/_config.sh @@ -1,6 +1,7 @@ # All of our build recipes, order matters: recipes run sequentially, so put the # most popular/important ones first. Recipes with a should-build.sh that gates # them out for a given version are skipped instantly. +# centos7-toolchain must be listed first as other recipes FROM it. recipes=( # Active recipes, ordered by likely popularity "headers" @@ -9,12 +10,13 @@ recipes=( "riscv64" "loong64" "riscv64-pointer-compression" + "centos7-toolchain" # Shared recipe should be built first + "x86" + "x64-glibc-217" + "x64-pointer-compression" # Legacy recipes, currently gated out for modern Node.js versions - "x86" # major < 22 "armv6l" # major < 24 - "x64-glibc-217" # major < 24 - "x64-pointer-compression" # major < 23 "x64-debug" # major < 24 "x64-usdt" # major <= 18 ) diff --git a/bin/local_build.sh b/bin/local_build.sh index 8c62156..fef548a 100755 --- a/bin/local_build.sh +++ b/bin/local_build.sh @@ -97,6 +97,13 @@ fi echo "Building ${recipe} recipe and tagging as ${image_tag_pfx}${recipe}..." docker build "${__dirname}/../fetch-source/" -t "${image_tag_pfx}fetch-source" --build-arg UID=${USER_ID} --build-arg GID=${GROUP_ID} + +# If the recipe depends on the centos7-toolchain base image, build it first +if grep -q "FROM.*centos7-toolchain" "${recipes_dir}/${recipe}/Dockerfile" 2>/dev/null; then + echo "Building centos7-toolchain base image first..." + docker build "${recipes_dir}/centos7-toolchain/" -t "${image_tag_pfx}centos7-toolchain" --build-arg UID=${USER_ID} --build-arg GID=${GROUP_ID} +fi + docker build "${recipes_dir}/${recipe}/" -t "${image_tag_pfx}${recipe}" --build-arg UID=${USER_ID} --build-arg GID=${GROUP_ID} ## -- DOWNLOAD SOURCE -- ## diff --git a/fetch-source/run.sh b/fetch-source/run.sh index 886a473..0314cab 100755 --- a/fetch-source/run.sh +++ b/fetch-source/run.sh @@ -32,7 +32,7 @@ cd /home/node curl_with_retry "$source_url" if [[ "$disttype" = "release" ]]; then - curl_with_retry https://github.com/nodejs/release-keys/raw/HEAD/gpg-only-active-keys/pubring.kbx + curl_with_retry https://github.com/nodejs/release-keys/raw/HEAD/gpg/pubring.kbx curl_with_retry "${source_urlbase}/SHASUMS256.txt.asc" gpgv --keyring="$(pwd)/pubring.kbx" --output - < SHASUMS256.txt.asc \ diff --git a/recipes/centos7-toolchain/Dockerfile b/recipes/centos7-toolchain/Dockerfile new file mode 100644 index 0000000..d25fcfe --- /dev/null +++ b/recipes/centos7-toolchain/Dockerfile @@ -0,0 +1,21 @@ +FROM --platform=linux/amd64 centos:7 + +ARG GID=1000 +ARG UID=1000 + +RUN groupadd --gid $GID node \ + && adduser --gid $GID --uid $UID node + +COPY --chmod=755 files/installPrerequisites /root/installPrerequisites +COPY files/*.repo /etc/yum.repos.d/ +RUN /root/installPrerequisites + +COPY --chmod=755 files/installFromSourceCode /root/installFromSourceCode +COPY --chmod=755 files/opt__gcc15__enable /opt/gcc15/enable +COPY --chmod=755 files/checksums.sh /root/checksums.sh + +RUN --mount=type=cache,target=/root/.ccache --mount=type=tmpfs,target=/usr/src . /root/checksums.sh && /root/installFromSourceCode https://www.python.org/ftp/python/3.9.23/Python-3.9.23.tar.xz "$sha256_python39" '--prefix=/usr/local/' +RUN --mount=type=cache,target=/root/.ccache --mount=type=tmpfs,target=/usr/src . /root/checksums.sh && /root/installFromSourceCode https://www.python.org/ftp/python/3.13.5/Python-3.13.5.tar.xz "$sha256_python313" '--prefix=/usr/local/' +RUN --mount=type=cache,target=/root/.ccache --mount=type=tmpfs,target=/usr/src . /root/checksums.sh && /root/installFromSourceCode https://gcc.gnu.org/pub/gcc/releases/gcc-15.1.0/gcc-15.1.0.tar.xz "$sha256_gcc15" '--prefix=/opt/gcc15/ --with-default-libstdcxx-abi=gcc4-compatible --enable-languages=c,c++ --enable-checking=release --enable-gnu-indirect-function --with-linker-hash-style=gnu --disable-bootstrap --disable-multilib --build=x86_64-redhat-linux' + +COPY --chmod=755 --chown=node:node run.sh /home/node/ diff --git a/recipes/centos7-toolchain/files/checksums.sh b/recipes/centos7-toolchain/files/checksums.sh new file mode 100644 index 0000000..b000ca7 --- /dev/null +++ b/recipes/centos7-toolchain/files/checksums.sh @@ -0,0 +1,4 @@ +# SHA256 checksums for source tarballs +sha256_python39='61a42919e13d539f7673cf11d1c404380e28e540510860b9d242196e165709c9' +sha256_python313='93e583f243454e6e9e4588ca2c2662206ad961659863277afcdb96801647d640' +sha256_gcc15='e2b09ec21660f01fecffb715e0120265216943f038d0e48a9868713e54f06cea' diff --git a/recipes/centos7-toolchain/files/etc__yum.repos.d__devtoolset.repo b/recipes/centos7-toolchain/files/etc__yum.repos.d__devtoolset.repo new file mode 100644 index 0000000..81064ea --- /dev/null +++ b/recipes/centos7-toolchain/files/etc__yum.repos.d__devtoolset.repo @@ -0,0 +1,4 @@ +[devtoolset-12] +name=Devtoolset 12 +baseurl=https://buildlogs.centos.org/c7-devtoolset-12.x86_64/ +gpgcheck=0 diff --git a/recipes/centos7-toolchain/files/installFromSourceCode b/recipes/centos7-toolchain/files/installFromSourceCode new file mode 100644 index 0000000..4b281d2 --- /dev/null +++ b/recipes/centos7-toolchain/files/installFromSourceCode @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +set -e +set -x + +# Args: url expectedSha256 configureArgsStr + +url="$1" +expectedSha256="$2" +configureArgsStr="$3" + +base=$(basename "$url") +name=${base%.*} +name=${name%.tar} +ext=${base:${#name}} + +case "$ext" in + .tar.xz|.txz) formatOpt=--xz;; + .tar.gz|.tgz) formatOpt=--gzip;; + .tar.bz2|.tbz2) formatOpt=--bzip2;; + *) formatOpt=--auto-compress +esac + +# Download and verify checksum +tmpFile="/usr/src/${base}" +curl -fL -o "$tmpFile" "$url" + +if [ -n "$expectedSha256" ]; then + actualSha256=$(sha256sum "$tmpFile" | awk '{print $1}') + if [ "$actualSha256" != "$expectedSha256" ]; then + echo "SHA256 mismatch for $base!" >&2 + echo " expected: $expectedSha256" >&2 + echo " actual: $actualSha256" >&2 + exit 1 + fi + echo "SHA256 verified: $base" +fi + +tar --extract --file="$tmpFile" --directory=/usr/src "$formatOpt" +rm -f "$tmpFile" + +source /opt/gcc15/enable +export CC='ccache gcc' +export CXX='ccache g++' + +cd "/usr/src/$name" +chmod +x ./contrib/download_prerequisites 2>/dev/null && ./contrib/download_prerequisites +./configure $configureArgsStr +make -j $(nproc) +make install + +hash -r +ccache -s > "/root/ccacheStat_$name.txt" diff --git a/recipes/centos7-toolchain/files/installPrerequisites b/recipes/centos7-toolchain/files/installPrerequisites new file mode 100644 index 0000000..a55a436 --- /dev/null +++ b/recipes/centos7-toolchain/files/installPrerequisites @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e +set -x + +sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* +sed -i 's|#baseurl=http://mirror.centos.org|baseurl=https://vault.centos.org|g' /etc/yum.repos.d/CentOS-* +yum install -y epel-release # Adds extra repos +yum upgrade -y + +yum install -y bzip2 # Required to compile gcc +yum install -y gcc-c++ # Required to compile Node.js v7- +yum install -y make # Allows compilation +yum install -y ccache # Allows caching +yum install -y devtoolset-12 # Includes gcc 12.1.1 diff --git a/recipes/centos7-toolchain/files/opt__gcc15__enable b/recipes/centos7-toolchain/files/opt__gcc15__enable new file mode 100644 index 0000000..50f1235 --- /dev/null +++ b/recipes/centos7-toolchain/files/opt__gcc15__enable @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e +set -x + +DIR=/opt/gcc15 + +source /opt/rh/devtoolset-12/enable + +export PATH="$DIR/bin${PATH:+:${PATH}}" +export MANPATH="$DIR/share/man${MANPATH:+:${MANPATH}}" +export INFOPATH="$DIR/share/info${INFOPATH:+:${INFOPATH}}" +export LD_LIBRARY_PATH="$DIR/lib64:$DIR/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" +export PKG_CONFIG_PATH="$DIR/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}" + +if [ -f "$DIR/bin/gcc" ]; then + export LDFLAGS='-static-libstdc++' +fi diff --git a/recipes/x64-glibc-217/run.sh b/recipes/centos7-toolchain/run.sh similarity index 59% rename from recipes/x64-glibc-217/run.sh rename to recipes/centos7-toolchain/run.sh index 94660e4..3a8b94d 100755 --- a/recipes/x64-glibc-217/run.sh +++ b/recipes/centos7-toolchain/run.sh @@ -13,12 +13,13 @@ source_url="$7" source_urlbase="$8" config_flags="" -cd /home/node +homeDir=/home/node +nodeDir="$homeDir/node-$fullversion" -tar -xf node.tar.xz +tar --directory="$homeDir" -xf "$homeDir/node.tar.xz" # configuring cares correctly to not use sys/random.h on this target -cd "node-${fullversion}"/deps/cares +cd "$nodeDir/deps/cares" sed -i 's/define HAVE_SYS_RANDOM_H 1/undef HAVE_SYS_RANDOM_H/g' ./config/linux/ares_config.h sed -i 's/define HAVE_GETRANDOM 1/undef HAVE_GETRANDOM/g' ./config/linux/ares_config.h @@ -27,22 +28,32 @@ if [[ "$(grep -o 'ARES_VERSION_STR "[^"]*"' ./include/ares_version.h | awk '{pri sed -i 's/MSG_FASTOPEN/TCP_FASTOPEN_CONNECT/g' ./src/lib/ares__socket.c fi -cd /home/node +# Linux implementation of experimental WASM memory control requires Linux 3.17 & glibc 2.27 so disable it +cd "$nodeDir/deps/v8/src" +[ -f d8/d8.cc ] && sed -i -e 's/#if V8_TARGET_OS_LINUX/#if false/g' wasm/wasm-objects.cc d8/d8.cc -cd "node-${fullversion}" +cd "$nodeDir" export CCACHE_BASEDIR="$PWD" export CC="ccache gcc" export CXX="ccache g++" export MAJOR_VERSION=$(echo ${fullversion} | cut -d . -f 1 | tr --delete v) -. /opt/rh/devtoolset-12/enable -. /opt/rh/rh-python38/enable +isNodeVersionGE() { + printf "$1\n$fullversion" | sort -VC +} + +source "$homeDir/run_other.sh" +source "$homeDir/run_versions.sh" +cd "$nodeDir" + +setPython +setGCC make -j$(getconf _NPROCESSORS_ONLN) binary V= \ - DESTCPU="x64" \ - ARCH="x64" \ - VARIATION="glibc-217" \ + DESTCPU="$destCPU" \ + ARCH="$arch" \ + VARIATION="$variation" \ DISTTYPE="$disttype" \ CUSTOMTAG="$customtag" \ DATESTRING="$datestring" \ @@ -50,4 +61,5 @@ make -j$(getconf _NPROCESSORS_ONLN) binary V= \ RELEASE_URLBASE="$release_urlbase" \ CONFIG_FLAGS="$config_flags" +"$nodeDir/node" -p process.versions # Make sure there is no "Segmentation fault" error (example: node v21.0~v21.2 x64-pointer-compression) mv node-*.tar.?z /out/ diff --git a/recipes/centos7-toolchain/should-build.sh b/recipes/centos7-toolchain/should-build.sh new file mode 100644 index 0000000..cfde68b --- /dev/null +++ b/recipes/centos7-toolchain/should-build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +# This is a base image used by other recipes, not a build recipe itself. +# Always skip during the build phase. +exit 1 diff --git a/recipes/headers/run.sh b/recipes/headers/run.sh index 153395c..3fee927 100755 --- a/recipes/headers/run.sh +++ b/recipes/headers/run.sh @@ -19,7 +19,7 @@ curl -fsSLO --compressed "${source_urlbase}/node-${fullversion}-headers.tar.xz" if [[ "$disttype" = "release" ]]; then pubring=$(mktemp) - curl -sSLo "$pubring" https://github.com/nodejs/release-keys/raw/HEAD/gpg-only-active-keys/pubring.kbx + curl -sSLo "$pubring" https://github.com/nodejs/release-keys/raw/HEAD/gpg/pubring.kbx curl -sSL "${source_urlbase}/SHASUMS256.txt.asc" \ | gpgv --keyring="${pubring}" --output - \ diff --git a/recipes/x64-glibc-217/Dockerfile b/recipes/x64-glibc-217/Dockerfile index f83868d..b996d41 100644 --- a/recipes/x64-glibc-217/Dockerfile +++ b/recipes/x64-glibc-217/Dockerfile @@ -1,39 +1,6 @@ -FROM centos:7 +FROM --platform=linux/amd64 unofficial-build-recipe-centos7-toolchain -ARG GID=1000 -ARG UID=1000 - -RUN groupadd --gid $GID node \ - && adduser --gid $GID --uid $UID node - -RUN cat <=3.8 from source as it is needed for node >=v22 -ENV PYTHON_VERSION="3.10.15" -RUN yum groupinstall -y "Development Tools" \ - && yum install -y \ - gcc \ - gcc-c++ \ - make \ - zlib-devel \ - bzip2-devel \ - openssl-devel \ - libffi-devel \ - sqlite-devel \ - readline-devel \ - && curl https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz -O \ - && tar xzf Python-${PYTHON_VERSION}.tgz \ - && cd Python-${PYTHON_VERSION} \ - && ./configure --enable-optimizations \ - && make altinstall \ - && PYTHON_MAJOR_MINOR_VERSION=$(echo $PYTHON_VERSION | cut -d. -f1,2) \ - && ln -sf /usr/local/bin/python${PYTHON_MAJOR_MINOR_VERSION} /usr/bin/python3 - -COPY --chown=node:node run.sh /home/node/run.sh +COPY --chmod=755 --chown=node:node run_other.sh run_versions.sh /home/node/ VOLUME /home/node/.ccache VOLUME /out diff --git a/recipes/x64-pointer-compression/cloudlinux.repo b/recipes/x64-pointer-compression/cloudlinux.repo deleted file mode 100644 index 2ca8962..0000000 --- a/recipes/x64-pointer-compression/cloudlinux.repo +++ /dev/null @@ -1,9 +0,0 @@ -[cloudlinux-sclo-devtoolset-8] -name=Cloudlinux devtoolset-8 -baseurl=https://repo.cloudlinux.com/cloudlinux/7/sclo/devtoolset-8/x86_64/ -gpgcheck=0 - -[cloudlinux-sclo-devtoolset-9] -name=Cloudlinux devtoolset-9 -baseurl=https://repo.cloudlinux.com/cloudlinux/7/sclo/devtoolset-9/x86_64/ -gpgcheck=0 diff --git a/recipes/x64-pointer-compression/run.sh b/recipes/x64-pointer-compression/run.sh deleted file mode 100755 index c483beb..0000000 --- a/recipes/x64-pointer-compression/run.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash - -set -e -set -x - -release_urlbase="$1" -disttype="$2" -customtag="$3" -datestring="$4" -commit="$5" -fullversion="$6" -source_url="$7" -source_urlbase="$8" -config_flags=--experimental-enable-pointer-compression - -cd /home/node - -tar -xf node.tar.xz - -# configuring cares correctly to not use sys/random.h on this target -cd "node-${fullversion}"/deps/cares/config/linux -sed -i 's/define HAVE_SYS_RANDOM_H 1/undef HAVE_SYS_RANDOM_H/g' ./ares_config.h -sed -i 's/define HAVE_GETRANDOM 1/undef HAVE_GETRANDOM/g' ./ares_config.h - -cd /home/node - -cd "node-${fullversion}" - -export CCACHE_BASEDIR="$PWD" -export CC="ccache gcc" -export CXX="ccache g++" -export MAJOR_VERSION=$(echo ${fullversion} | cut -d . -f 1 | tr --delete v) - -if [ $MAJOR_VERSION -ge 16 ]; then - . /opt/rh/devtoolset-9/enable -fi - -make -j$(getconf _NPROCESSORS_ONLN) binary V= \ - DESTCPU="x64" \ - ARCH="x64" \ - VARIATION="pointer-compression" \ - DISTTYPE="$disttype" \ - CUSTOMTAG="$customtag" \ - DATESTRING="$datestring" \ - COMMIT="$commit" \ - RELEASE_URLBASE="$release_urlbase" \ - CONFIG_FLAGS="$config_flags" - -mv node-*.tar.?z /out/ diff --git a/recipes/x64-pointer-compression/run_other.sh b/recipes/x64-pointer-compression/run_other.sh new file mode 100644 index 0000000..7a0c2bd --- /dev/null +++ b/recipes/x64-pointer-compression/run_other.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -e +set -x + +config_flags=--experimental-enable-pointer-compression +destCPU=x64 +arch=x64 +variation=pointer-compression diff --git a/recipes/x64-pointer-compression/run_versions.sh b/recipes/x64-pointer-compression/run_versions.sh new file mode 100644 index 0000000..3fbf23b --- /dev/null +++ b/recipes/x64-pointer-compression/run_versions.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e +set -x + +setPython() { + if isNodeVersionGE 'v22.3'; then export PYTHON='python3.13'; return; fi # Python 3.13: Node.js v22.3 ~ latest (v24.3) + if isNodeVersionGE 'v14.14'; then export PYTHON='python3.9'; return; fi # Python 3.9: Node.js v14.14 ~ latest (v24.3) + if isNodeVersionGE 'v4.0'; then export PYTHON='python2.7'; return; fi # Python 2.7: Node.js v4.0 ~ v15.14 (latest) + + # Node.js v16.0 is first version not supporting Python 2.7 but supports Python 3.6 ~ 3.9 so Python 3.9 is chosen +} + +setGCC() { + if isNodeVersionGE 'v22.3'; then source /opt/gcc15/enable; return; fi # GCC 15.1: Node.js v22.3 ~ latest (v24.3) + if isNodeVersionGE 'v8.0'; then source /opt/rh/devtoolset-12/enable; return; fi # GCC 12.1: Node.js v8.0 ~ v22.1 + # GCC 4.8.5: Node.js v4.0 ~ v10.14 +} diff --git a/recipes/x64-pointer-compression/should-build.sh b/recipes/x64-pointer-compression/should-build.sh index 513aff9..6c2fb6f 100755 --- a/recipes/x64-pointer-compression/should-build.sh +++ b/recipes/x64-pointer-compression/should-build.sh @@ -3,8 +3,20 @@ __dirname=$1 fullversion=$2 -. ${__dirname}/_decode_version.sh +isNodeVersionGE() { + printf "$1\n$fullversion" | sort -VC +} -decode "$fullversion" +isNodeVersionLT() { + ! printf "$1\n$fullversion" | sort -VC +} -test "$major" -ge "14" && test "$major" -lt "23" +isNodeVersionGE 'v13.4' # Pointer compression is supported since Node.js v13.4 + +isNodeVersionLT 'v17.0' || isNodeVersionGE 'v18.0' # Node.js v17 requires GCC version between 4.8.5 and 12.1 which is not installed +isNodeVersionLT 'v22.2' || isNodeVersionGE 'v22.3' # Node.js v22.2 requires GCC version between 12.1 and 15.1 which is not installed + +isNodeVersionLT 'v20.17' || isNodeVersionGE 'v21.0' # Pointer compression does not work in Node.js v20.17~v20.19 (Compilation error) +isNodeVersionLT 'v21.0' || isNodeVersionGE 'v21.3' # Pointer compression does not work in Node.js v21.0~v21.2 (Segmentation fault) +isNodeVersionLT 'v22.6' || isNodeVersionGE 'v22.17' # Pointer compression does not work in Node.js v22.6~v22.16 (Compilation error) +isNodeVersionLT 'v23.0' || isNodeVersionGE 'v24.2' # Pointer compression does not work in Node.js v23.0~v24.1 (Compilation error) diff --git a/recipes/x64-usdt/Dockerfile b/recipes/x64-usdt/Dockerfile index 448fd84..aa0a1e5 100644 --- a/recipes/x64-usdt/Dockerfile +++ b/recipes/x64-usdt/Dockerfile @@ -9,7 +9,7 @@ RUN groupadd --gid $GID node \ COPY cloudlinux.repo /etc/yum.repos.d/cloudlinux.repo RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* \ - && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* \ + && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=https://vault.centos.org|g' /etc/yum.repos.d/CentOS-* \ && yum install -y epel-release \ && yum upgrade -y \ && yum install -y \ diff --git a/recipes/x86/Dockerfile b/recipes/x86/Dockerfile index d195706..36a7cb8 100644 --- a/recipes/x86/Dockerfile +++ b/recipes/x86/Dockerfile @@ -1,4 +1,4 @@ -FROM centos:7 +FROM --platform=linux/386 centos:7 ARG GID=1000 ARG UID=1000 @@ -6,25 +6,20 @@ ARG UID=1000 RUN groupadd --gid $GID node \ && adduser --gid $GID --uid $UID node -COPY cloudlinux.repo /etc/yum.repos.d/cloudlinux.repo - -RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* \ - && sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* \ - && yum install -y epel-release \ - && yum upgrade -y \ - && yum install -y \ - git \ - curl \ - make \ - python2 \ - python3 \ - ccache \ - xz-utils \ - devtoolset-6.i686 \ - devtoolset-9.i686 \ - glibc-devel.i686 - -COPY --chown=node:node run.sh /home/node/run.sh +COPY --chmod=755 files/installPrerequisites /root/installPrerequisites +COPY files/*.repo /etc/yum.repos.d/ +RUN /root/installPrerequisites + +COPY --chmod=755 files/installFromSourceCode /root/installFromSourceCode +COPY --chmod=755 files/opt__gcc15__enable /opt/gcc15/enable +COPY --chmod=755 files/checksums.sh /root/checksums.sh + +RUN --mount=type=cache,target=/root/.ccache --mount=type=tmpfs,target=/usr/src . /root/checksums.sh && /root/installFromSourceCode https://www.python.org/ftp/python/3.9.23/Python-3.9.23.tar.xz "$sha256_python39" '--prefix=/usr/local/' +RUN --mount=type=cache,target=/root/.ccache --mount=type=tmpfs,target=/usr/src . /root/checksums.sh && /root/installFromSourceCode https://www.python.org/ftp/python/3.13.5/Python-3.13.5.tar.xz "$sha256_python313" '--prefix=/usr/local/' +RUN --mount=type=cache,target=/root/.ccache --mount=type=tmpfs,target=/usr/src . /root/checksums.sh && /root/installFromSourceCode https://gcc.gnu.org/pub/gcc/releases/gcc-15.1.0/gcc-15.1.0.tar.xz "$sha256_gcc15" '--prefix=/opt/gcc15/ --with-default-libstdcxx-abi=gcc4-compatible --enable-languages=c,c++ --enable-checking=release --enable-gnu-indirect-function --with-linker-hash-style=gnu --disable-bootstrap --disable-multilib --build=i686-redhat-linux' +RUN --mount=type=cache,target=/root/.ccache --mount=type=tmpfs,target=/usr/src . /root/checksums.sh && /root/installFromSourceCode https://sourceware.org/pub/binutils/releases/binutils-2.44.tar.xz "$sha256_binutils" '--prefix=/opt/gcc15/ --without-debuginfod --disable-nls LDFLAGS=-pthread' + +COPY --chmod=755 --chown=node:node run.sh run_other.sh run_versions.sh /home/node/ VOLUME /home/node/.ccache VOLUME /out diff --git a/recipes/x86/cloudlinux.repo b/recipes/x86/cloudlinux.repo deleted file mode 100644 index e4551b0..0000000 --- a/recipes/x86/cloudlinux.repo +++ /dev/null @@ -1,9 +0,0 @@ -[cloudlinux-sclo-devtoolset-6] -name=Cloudlinux devtoolset-6 -baseurl=https://repo.cloudlinux.com/cloudlinux/7/sclo/devtoolset-6/i386/ -gpgcheck=0 - -[cloudlinux-sclo-devtoolset-9] -name=Cloudlinux devtoolset-9 -baseurl=https://repo.cloudlinux.com/cloudlinux/7/sclo/devtoolset-9/i386/ -gpgcheck=0 diff --git a/recipes/x86/files/checksums.sh b/recipes/x86/files/checksums.sh new file mode 100644 index 0000000..99fb2f4 --- /dev/null +++ b/recipes/x86/files/checksums.sh @@ -0,0 +1,5 @@ +# SHA256 checksums for source tarballs +sha256_python39='61a42919e13d539f7673cf11d1c404380e28e540510860b9d242196e165709c9' +sha256_python313='93e583f243454e6e9e4588ca2c2662206ad961659863277afcdb96801647d640' +sha256_gcc15='e2b09ec21660f01fecffb715e0120265216943f038d0e48a9868713e54f06cea' +sha256_binutils='ce2017e059d63e67ddb9240e9d4ec49c2893605035cd60e92ad53177f4377237' diff --git a/recipes/x86/files/etc__yum.repos.d__devtoolset.repo b/recipes/x86/files/etc__yum.repos.d__devtoolset.repo new file mode 100644 index 0000000..4d03dac --- /dev/null +++ b/recipes/x86/files/etc__yum.repos.d__devtoolset.repo @@ -0,0 +1,4 @@ +[cloudlinux-sclo-devtoolset-9] +name=Cloudlinux devtoolset-9 +baseurl=https://repo.cloudlinux.com/cloudlinux/7/sclo/devtoolset-9/i386/ +gpgcheck=0 diff --git a/recipes/x86/files/etc__yum.repos.d__epel.repo b/recipes/x86/files/etc__yum.repos.d__epel.repo new file mode 100644 index 0000000..cd99e33 --- /dev/null +++ b/recipes/x86/files/etc__yum.repos.d__epel.repo @@ -0,0 +1,4 @@ +[epel] +name=epel +baseurl=https://buildlogs.centos.org/c7-epel.i386/ +gpgcheck=0 diff --git a/recipes/x86/files/installFromSourceCode b/recipes/x86/files/installFromSourceCode new file mode 100644 index 0000000..4b281d2 --- /dev/null +++ b/recipes/x86/files/installFromSourceCode @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +set -e +set -x + +# Args: url expectedSha256 configureArgsStr + +url="$1" +expectedSha256="$2" +configureArgsStr="$3" + +base=$(basename "$url") +name=${base%.*} +name=${name%.tar} +ext=${base:${#name}} + +case "$ext" in + .tar.xz|.txz) formatOpt=--xz;; + .tar.gz|.tgz) formatOpt=--gzip;; + .tar.bz2|.tbz2) formatOpt=--bzip2;; + *) formatOpt=--auto-compress +esac + +# Download and verify checksum +tmpFile="/usr/src/${base}" +curl -fL -o "$tmpFile" "$url" + +if [ -n "$expectedSha256" ]; then + actualSha256=$(sha256sum "$tmpFile" | awk '{print $1}') + if [ "$actualSha256" != "$expectedSha256" ]; then + echo "SHA256 mismatch for $base!" >&2 + echo " expected: $expectedSha256" >&2 + echo " actual: $actualSha256" >&2 + exit 1 + fi + echo "SHA256 verified: $base" +fi + +tar --extract --file="$tmpFile" --directory=/usr/src "$formatOpt" +rm -f "$tmpFile" + +source /opt/gcc15/enable +export CC='ccache gcc' +export CXX='ccache g++' + +cd "/usr/src/$name" +chmod +x ./contrib/download_prerequisites 2>/dev/null && ./contrib/download_prerequisites +./configure $configureArgsStr +make -j $(nproc) +make install + +hash -r +ccache -s > "/root/ccacheStat_$name.txt" diff --git a/recipes/x86/files/installPrerequisites b/recipes/x86/files/installPrerequisites new file mode 100644 index 0000000..f4414a4 --- /dev/null +++ b/recipes/x86/files/installPrerequisites @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -e +set -x + +sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* +sed -i 's|#baseurl=http://mirror.centos.org|baseurl=https://vault.centos.org|g' /etc/yum.repos.d/CentOS-* +yum upgrade -y + +yum install -y bzip2 # Required to compile gcc +yum install -y zlib-devel # Required to compile Python +yum install -y bzip2-devel # Required to compile Python with bz2 module (required by Node.js) +yum install -y gcc-c++ # Required to compile Node.js v7- +yum install -y make # Allows compilation +yum install -y ccache # Allows caching +yum install -y devtoolset-9.i686 # Includes gcc 9.3.1 + +# Fix bugs +sed -i -e 's/:\${MANPATH}/\${MANPATH:+:\${MANPATH}}/g' /opt/rh/devtoolset-9/enable diff --git a/recipes/x86/files/opt__gcc15__enable b/recipes/x86/files/opt__gcc15__enable new file mode 100644 index 0000000..4088ba8 --- /dev/null +++ b/recipes/x86/files/opt__gcc15__enable @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e +set -x + +DIR=/opt/gcc15 + +source /opt/rh/devtoolset-9/enable + +export PATH="$DIR/bin${PATH:+:${PATH}}" +export MANPATH="$DIR/share/man${MANPATH:+:${MANPATH}}" +export INFOPATH="$DIR/share/info${INFOPATH:+:${INFOPATH}}" +export LD_LIBRARY_PATH="$DIR/lib64:$DIR/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" +export PKG_CONFIG_PATH="$DIR/lib64/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}" + +if [ -f "$DIR/bin/gcc" ]; then + export LDFLAGS='-static-libstdc++' +fi diff --git a/recipes/x86/run.sh b/recipes/x86/run.sh index f2c7f68..3a8b94d 100755 --- a/recipes/x86/run.sh +++ b/recipes/x86/run.sh @@ -11,36 +11,49 @@ commit="$5" fullversion="$6" source_url="$7" source_urlbase="$8" -config_flags=--openssl-no-asm +config_flags="" -cd /home/node +homeDir=/home/node +nodeDir="$homeDir/node-$fullversion" -tar -xf node.tar.xz +tar --directory="$homeDir" -xf "$homeDir/node.tar.xz" # configuring cares correctly to not use sys/random.h on this target -cd "node-${fullversion}"/deps/cares/config/linux -sed -i 's/define HAVE_SYS_RANDOM_H 1/undef HAVE_SYS_RANDOM_H/g' ./ares_config.h -sed -i 's/define HAVE_GETRANDOM 1/undef HAVE_GETRANDOM/g' ./ares_config.h +cd "$nodeDir/deps/cares" +sed -i 's/define HAVE_SYS_RANDOM_H 1/undef HAVE_SYS_RANDOM_H/g' ./config/linux/ares_config.h +sed -i 's/define HAVE_GETRANDOM 1/undef HAVE_GETRANDOM/g' ./config/linux/ares_config.h -cd /home/node +# fix https://github.com/c-ares/c-ares/issues/850 +if [[ "$(grep -o 'ARES_VERSION_STR "[^"]*"' ./include/ares_version.h | awk '{print $2}' | tr -d '"')" == "1.33.0" ]]; then + sed -i 's/MSG_FASTOPEN/TCP_FASTOPEN_CONNECT/g' ./src/lib/ares__socket.c +fi + +# Linux implementation of experimental WASM memory control requires Linux 3.17 & glibc 2.27 so disable it +cd "$nodeDir/deps/v8/src" +[ -f d8/d8.cc ] && sed -i -e 's/#if V8_TARGET_OS_LINUX/#if false/g' wasm/wasm-objects.cc d8/d8.cc -cd "node-${fullversion}" +cd "$nodeDir" export CCACHE_BASEDIR="$PWD" export CC="ccache gcc" export CXX="ccache g++" -export CXXFLAGS=-m32 -export CFLAGS=-m32 export MAJOR_VERSION=$(echo ${fullversion} | cut -d . -f 1 | tr --delete v) -if [ $MAJOR_VERSION -ge 16 ]; then - . /opt/rh/devtoolset-9/enable -fi +isNodeVersionGE() { + printf "$1\n$fullversion" | sort -VC +} + +source "$homeDir/run_other.sh" +source "$homeDir/run_versions.sh" +cd "$nodeDir" + +setPython +setGCC make -j$(getconf _NPROCESSORS_ONLN) binary V= \ - DESTCPU="x86" \ - ARCH="x86" \ - VARIATION="" \ + DESTCPU="$destCPU" \ + ARCH="$arch" \ + VARIATION="$variation" \ DISTTYPE="$disttype" \ CUSTOMTAG="$customtag" \ DATESTRING="$datestring" \ @@ -48,4 +61,5 @@ make -j$(getconf _NPROCESSORS_ONLN) binary V= \ RELEASE_URLBASE="$release_urlbase" \ CONFIG_FLAGS="$config_flags" +"$nodeDir/node" -p process.versions # Make sure there is no "Segmentation fault" error (example: node v21.0~v21.2 x64-pointer-compression) mv node-*.tar.?z /out/ diff --git a/recipes/x86/run_other.sh b/recipes/x86/run_other.sh new file mode 100644 index 0000000..7527db6 --- /dev/null +++ b/recipes/x86/run_other.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -e +set -x + +config_flags= +destCPU=x86 +arch=x86 +variation= + +# GCC forbids SSE by default for x86 but it is required by Node.js so enable it manually +export CFLAGS='-msse2' +export CXXFLAGS='-msse2' +# export CFLAGS='-msse4.2' # This can be used too for modern CPUs (~2008) +# export CFLAGS='-mavx' # This can be used too for modern CPUs (~2011) +# export CFLAGS='-mavx2' # This can be used too for modern CPUs (~2013) +# export CFLAGS='-mavx2 -maes' # This can be used too for modern CPUs (~2015) +# export CFLAGS='-march=znver1' # This can be used too for modern AMD CPUs (~2017) +# export CFLAGS='-march=sandybridge' # This can be used too for modern Intel CPUs (~2011) + +# x86 does not support _mm_cvtsi128_si64 instruction so forbid it's usage and fallback to non-SSE solution +cd "$nodeDir/deps/v8/src" +find . -name '*.cc' -type f -print0 | xargs -0 sed -i -e 's/#ifdef __SSE2__/#if false/g' + +# Replace %ifdef with #ifdef in assembler code +cd "$nodeDir/deps/openssl/config/archs/linux-elf/asm" && +find . -name '*.S' -type f -print0 | xargs -0 --no-run-if-empty sed -i -e 's/%ifdef/#ifdef/g' -e 's/%endif/#endif/g' + +# Fix https://github.com/nodejs/node/issues/58458 +str1='return __ Tuple\(result, __ Word32Constant\(0\)\);' +str2='V result_ = result; return __ Tuple\(result_, __ Word32Constant\(0\)\);' +cd "$nodeDir/deps/v8/src/compiler/turboshaft" && +[ -f int64-lowering-reducer.h ] && sed -i -E "s/$str1/$str2/g" int64-lowering-reducer.h +# https://github.com/nodejs/node/issues/58458#issuecomment-2916873746 +# https://github.com/nodejs/node/commit/02f8cdb0c7a73d970ed7134a481a211bbd599c02 + +true # To allow "&&" above diff --git a/recipes/x86/run_versions.sh b/recipes/x86/run_versions.sh new file mode 100644 index 0000000..b4253b3 --- /dev/null +++ b/recipes/x86/run_versions.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e +set -x + +setPython() { + if isNodeVersionGE 'v22.3'; then export PYTHON='python3.13'; return; fi # Python 3.13: Node.js v22.3 ~ latest (v24.3) + if isNodeVersionGE 'v14.14'; then export PYTHON='python3.9'; return; fi # Python 3.9: Node.js v14.14 ~ latest (v24.3) + if isNodeVersionGE 'v4.0'; then export PYTHON='python2.7'; return; fi # Python 2.7: Node.js v4.0 ~ v15.14 (latest) + + # Node.js v16.0 is first version not supporting Python 2.7 but supports Python 3.6 ~ 3.9 so Python 3.9 is chosen +} + +setGCC() { + if isNodeVersionGE 'v22.3'; then source /opt/gcc15/enable; return; fi # GCC 15.1: Node.js v22.3 ~ latest (v24.3) + if isNodeVersionGE 'v7.10'; then source /opt/rh/devtoolset-9/enable; return; fi # GCC 9.3: Node.js v7.10 ~ v21.7 (latest) + # GCC 4.8.5: Node.js v4.0 ~ v10.14 +} diff --git a/recipes/x86/should-build.sh b/recipes/x86/should-build.sh index 10ff5ba..ed3bad4 100755 --- a/recipes/x86/should-build.sh +++ b/recipes/x86/should-build.sh @@ -3,8 +3,14 @@ __dirname=$1 fullversion=$2 -. ${__dirname}/_decode_version.sh +isNodeVersionGE() { + printf "$1\n$fullversion" | sort -VC +} -decode "$fullversion" +isNodeVersionLT() { + ! printf "$1\n$fullversion" | sort -VC +} -test "$major" -lt "22" +isNodeVersionGE 'v6.2' # Node.js v6.1- cannot download required files due to broken links + +isNodeVersionLT 'v22.0' || isNodeVersionGE 'v22.3' # Node.js v22.0~v22.2 requires GCC version between 9.3 and 15.1 which is not installed