initial package import

This commit is contained in:
Jan Staněk 2023-10-03 14:04:54 +02:00
commit 2a0ce7c5c2
No known key found for this signature in database
GPG Key ID: 2972F2037B243B6D
5 changed files with 322 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/undici-5.26.4-stripped.tar.gz
/undici-5.26.4-nm-prod.tgz
/undici-5.26.4-nm-dev.tgz
/undici-5.26.4-bundled-licenses.txt

View File

@ -0,0 +1,123 @@
From 9dfb61b331b09552250cea7268fc632335816661 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Stan=C4=9Bk?= <jstanek@redhat.com>
Date: Thu, 2 Nov 2023 15:09:10 +0100
Subject: [PATCH] feat: allow customization of build environment
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This allows for the WASM artifacts to be built elsewhere than only in
the alpine-based node container.
Signed-off-by: Jan Staněk <jstanek@redhat.com>
---
build/wasm.js | 72 +++++++++++++++++++++------------------------------
1 file changed, 29 insertions(+), 43 deletions(-)
diff --git a/build/wasm.js b/build/wasm.js
index fd90ac26..2b63f3c7 100644
--- a/build/wasm.js
+++ b/build/wasm.js
@@ -9,6 +9,18 @@ const WASM_SRC = resolve(__dirname, '../deps/llhttp')
const WASM_OUT = resolve(__dirname, '../lib/llhttp')
const DOCKERFILE = resolve(__dirname, './Dockerfile')
+// These are defined by build environment
+const WASM_CC = process.env.WASM_CC || 'clang'
+let WASM_CFLAGS = process.env.WASM_CFLAGS || '--sysroot=/usr/share/wasi-sysroot -target wasm32-unknown-wasi'
+let WASM_LDFLAGS = process.env.WASM_LDFLAGS || ''
+const WASM_LDLIBS = process.env.WASM_LDLIBS || ''
+
+// These are relevant for undici and should not be overridden
+WASM_CFLAGS += ' -Ofast -fno-exceptions -fvisibility=hidden -mexec-model=reactor'
+WASM_LDFLAGS += ' -Wl,-error-limit=0 -Wl,-O3 -Wl,--lto-O3 -Wl,--strip-all'
+WASM_LDFLAGS += ' -Wl,--allow-undefined -Wl,--export-dynamic -Wl,--export-table'
+WASM_LDFLAGS += ' -Wl,--export=malloc -Wl,--export=free -Wl,--no-entry'
+
let platform = process.env.WASM_PLATFORM
if (!platform && process.argv[2]) {
platform = execSync('docker info -f "{{.OSType}}/{{.Architecture}}"').toString().trim()
@@ -35,35 +47,25 @@ if (process.argv[2] === '--docker') {
process.exit(0)
}
-// Gather information about the tools used for the build
-const buildInfo = execSync('apk info -v').toString()
-if (!buildInfo.includes('wasi-sdk')) {
- console.log('Failed to generate build environment information')
- process.exit(-1)
+const hasApk = (function () {
+ try { execSync('command -v apk'); return true } catch (error) { return false }
+})()
+if (hasApk) {
+ // Gather information about the tools used for the build
+ const buildInfo = execSync('apk info -v').toString()
+ if (!buildInfo.includes('wasi-sdk')) {
+ console.log('Failed to generate build environment information')
+ process.exit(-1)
+ }
+ writeFileSync(join(WASM_OUT, 'wasm_build_env.txt'), buildInfo)
}
-writeFileSync(join(WASM_OUT, 'wasm_build_env.txt'), buildInfo)
// Build wasm binary
-execSync(`clang \
- --sysroot=/usr/share/wasi-sysroot \
- -target wasm32-unknown-wasi \
- -Ofast \
- -fno-exceptions \
- -fvisibility=hidden \
- -mexec-model=reactor \
- -Wl,-error-limit=0 \
- -Wl,-O3 \
- -Wl,--lto-O3 \
- -Wl,--strip-all \
- -Wl,--allow-undefined \
- -Wl,--export-dynamic \
- -Wl,--export-table \
- -Wl,--export=malloc \
- -Wl,--export=free \
- -Wl,--no-entry \
+execSync(`${WASM_CC} ${WASM_CFLAGS} ${WASM_LDFLAGS} \
${join(WASM_SRC, 'src')}/*.c \
-I${join(WASM_SRC, 'include')} \
- -o ${join(WASM_OUT, 'llhttp.wasm')}`, { stdio: 'inherit' })
+ -o ${join(WASM_OUT, 'llhttp.wasm')} \
+ ${WASM_LDLIBS}`, { stdio: 'inherit' })
const base64Wasm = readFileSync(join(WASM_OUT, 'llhttp.wasm')).toString('base64')
writeFileSync(
@@ -72,27 +74,11 @@ writeFileSync(
)
// Build wasm simd binary
-execSync(`clang \
- --sysroot=/usr/share/wasi-sysroot \
- -target wasm32-unknown-wasi \
- -msimd128 \
- -Ofast \
- -fno-exceptions \
- -fvisibility=hidden \
- -mexec-model=reactor \
- -Wl,-error-limit=0 \
- -Wl,-O3 \
- -Wl,--lto-O3 \
- -Wl,--strip-all \
- -Wl,--allow-undefined \
- -Wl,--export-dynamic \
- -Wl,--export-table \
- -Wl,--export=malloc \
- -Wl,--export=free \
- -Wl,--no-entry \
+execSync(`${WASM_CC} ${WASM_CFLAGS} -msimd128 ${WASM_LDFLAGS} \
${join(WASM_SRC, 'src')}/*.c \
-I${join(WASM_SRC, 'include')} \
- -o ${join(WASM_OUT, 'llhttp_simd.wasm')}`, { stdio: 'inherit' })
+ -o ${join(WASM_OUT, 'llhttp_simd.wasm')} \
+ ${WASM_LDLIBS}`, { stdio: 'inherit' })
const base64WasmSimd = readFileSync(join(WASM_OUT, 'llhttp_simd.wasm')).toString('base64')
writeFileSync(
--
2.41.0

87
nodejs-undici.spec Normal file
View File

@ -0,0 +1,87 @@
%global npm_name undici
%global llhttp_version_major 8
%global llhttp_version_minor 1
%global llhttp_version_patch 0
Name: nodejs-%{npm_name}
Summary: An HTTP/1.1 client, written from scratch for Node.js
Version: 5.26.4
Release: %autorelease
License: MIT
URL: https://undici.nodejs.org
# See Source4 on how these archives were generated
Source0: %{npm_name}-%{version}-stripped.tar.gz
Source1: %{npm_name}-%{version}-nm-prod.tgz
Source2: %{npm_name}-%{version}-nm-dev.tgz
Source3: %{npm_name}-%{version}-bundled-licenses.txt
Source4: %{npm_name}-sources.sh
Patch: 0001-feat-allow-customization-of-build-environment.patch
# Binary artifacts in this package are aimed at the wasm32-wasi "architecture".
%global _binaries_in_noarch_packages_terminate_build 0
BuildArch: noarch
ExclusiveArch: %{nodejs_arches} noarch
BuildRequires: clang lld wasi-libc-devel
BuildRequires: nodejs-devel npm
# for autosetup -S git_am
BuildRequires: git-core
# This package bundles it's own copy of llhttp
Provides: bundled(llhttp) = %{llhttp_version_major}.%{llhttp_version_minor}.%{llhttp_version_patch}
%description
An HTTP/1.1 client, written from scratch for Node.js.
%prep
%autosetup -n %{npm_name}-%{version} -S git_am
cp -p %{S:3} .
# Check for bundled llhttp version
if ! grep -q 'LLHTTP_VERSION_MAJOR %{llhttp_version_major}' deps/llhttp/include/llhttp.h \
|| ! grep -q 'LLHTTP_VERSION_MINOR %{llhttp_version_minor}' deps/llhttp/include/llhttp.h \
|| ! grep -q 'LLHTTP_VERSION_PATCH %{llhttp_version_patch}' deps/llhttp/include/llhttp.h
then
echo 'llhttp version mismatch' >&2; exit 2
fi
# Link node_modules
mkdir -p node_modules/.bin/
tar -xzf %{S:1}
ln -srt node_modules/ node_modules_prod/*
ln -srt node_modules/.bin/ node_modules_prod/.bin
%build
export WASM_CC=clang
export WASM_CFLAGS='--target=wasm32-wasi --sysroot=/usr/wasm32-wasi'
export WASM_LDFLAGS='-nodefaultlibs'
export WASM_LDLIBS='-lc'
# `npm run build` uses docker; invoke the build script directly
%{__nodejs} build/wasm.js
npm --offline pack
%install
mkdir -p %{buildroot}%{nodejs_sitelib}/%{npm_name}
tar -C %{buildroot}%{nodejs_sitelib}/%{npm_name} -xzf %{npm_name}-%{version}.tgz --strip-components=1
cp -prt %{buildroot}%{nodejs_sitelib}/%{npm_name} node_modules_prod node_modules
%check
%{__nodejs} -e 'require("./")'
tar -xzf %{S:2}
ln -fsrt node_modules/ node_modules_dev/*
ln -fsrt node_modules/.bin/ node_modules_dev/.bin/*
# Depends on the environment/OpenSSL version, etc. Informational only.
npm --offline run test || :
%files
%doc README.md
%license LICENSE %{npm_name}-%{version}-bundled-licenses.txt
%{nodejs_sitelib}/%{npm_name}
%changelog
%autochangelog

4
sources Normal file
View File

@ -0,0 +1,4 @@
SHA512 (undici-5.26.4-stripped.tar.gz) = f50c3c731dc7cd8af9646fd7abd13e452ba258f66dc53be07feba827475828a16a7641934ae283cc9ca11bc8d0e348c0bfcb8ecccda2bb7afb6bdb01f5ddde63
SHA512 (undici-5.26.4-nm-prod.tgz) = 2b6d0a2728289a91331314d7c40515a784d5d22dcc538fcbf33ffa09c826afd07c5605dff50d54d09b8010b9acdc1b00637e84461c274046ffbcb77bcbeda9a6
SHA512 (undici-5.26.4-nm-dev.tgz) = 67bcd32c485c0385a4e7d9b1c703a23367c05438c6f6c34ac986056e4110b92d107fc7b0eec6d2dfb5036c7120d769fb2694cfd9dcccb3403ed639b9c993a9af
SHA512 (undici-5.26.4-bundled-licenses.txt) = 3e591adb16e09b1c6fb75eb97a6ac51cd06e0aeae2bd5950a15902346e2c9626cb50203bfd0e15c7e8c98af8f24b81c1ce6617c359e7c0e7d0a6366457c844ba

104
undici-sources.sh Executable file
View File

@ -0,0 +1,104 @@
#!/bin/sh
# deps: curl rpm npm nodejs-packaging-bundler
set -e
UNDICI_VERSION="$(rpm --specfile nodejs-undici.spec --qf '%{VERSION}\n')"; readonly UNDICI_VERSION
RPKG=fedpkg
RELEASE=""
OFFLINE=false
usage() {
echo "${0##*/} - download and re-package upstream undici sources."
echo
echo Options:
printf '\t%s\n' '-h, --help: Show this info and exit.'
printf '\t%s\n' '-r<TOOL>, --rpkg=<TOOL>: Use <TOOL> for dist-git interaction [default: fedpkg].'
printf '\t%s\n' '--release=<RELEASE>: Tell <TOOL> to assume working on <RELEASE> [default: detected from current branch].'
printf '\t%s\n' '-n, --offline: Do not upload prepared sources to lookaside cache.'
}
# Construct upstream archive URL
github_archive_url() {
readonly gh_version="${1-${UNDICI_VERSION}}"
printf 'https://github.com/nodejs/undici/archive/v%s/undici-v%s.tar.gz' "${gh_version}" "${gh_version}"
}
# Fetch upstream release
# stdout: name of the original/upstream archive
fetch() {
readonly fetch_version="${1-${UNDICI_VERSION}}"
# npm archive does not contain everything (i.e. build scripts).
# Fetch the github archive instead.
fetch_url="$(github_archive_url "${fetch_version}")"; readonly fetch_url
curl --location --remote-name "${fetch_url}"
printf '%s\n' "${fetch_url##*/}"
}
# Delete any file where a WASM blob is detected
# stdout: relative paths to deleted files
nuke_wasm() {
find "${1-.}" -type f \
-exec grep -q --text -Pe '\x{0}asm|AGFzb' '{}' \; \
-print \
-delete
}
# Remove husky (git hook manager) from prepare scripts
remove_husky() {
cd "${1-undici-v${UNDICI_VERSION}/}" >/dev/null
if grep -q 'husky install' package.json; then
npm pkg delete scripts.prepare
fi
cd - >/dev/null
}
# Package the sources into stripped archive
repackage() {
readonly repackage_version="${1-${UNDICI_VERSION}}"
readonly repackage_rootdir="${2-undici-v${repackage_version}/}"
tar -czf "undici-${repackage_version}-stripped.tar.gz" "${repackage_rootdir}"
rm -rf "${repackage_rootdir}"
echo "undici-${repackage_version}-stripped.tar.gz"
}
# shellcheck disable=SC2046
set -- $(getopt -n "${0##*/}" --unquoted -o hr:n -l help,rpkg:,release:,offline -- "$@")
while test -n "$1"; do
case "$1" in
-h|--help) usage >&2 && exit;;
-r|--rpkg) RPKG="$2"; shift 2;;
-n|--offline) OFFLINE=true; shift 1;;
--release) RELEASE="$2"; shift 2;;
--) break;;
*) printf 'Unknown argument: %s\n' "$1" >&2; exit 2;;
esac
done
printf '=== %s ===\n' 'Fetching and unpacking upstream tarball' >&2
original="$(fetch "${UNDICI_VERSION}")"; readonly original
tar -xzf "${original}"
rootdir="$(ls -d "undici-${UNDICI_VERSION}/")"; readonly rootdir
rm -rf "${original}"
printf '=== %s ===\n' 'Removing following WASM blobs' >&2
nuke_wasm "${rootdir}" >&2
printf '=== %s ===\n' 'Cleaning package scripts' >&2
remove_husky "${rootdir}"
printf '=== %s ===\n' 'Re-packaging clean archive' >&2
repackage "${UNDICI_VERSION}" "${rootdir}"
printf '=== %s ===\n' 'Bundling dependencies' >&2
nodejs-packaging-bundler undici "${UNDICI_VERSION}" "undici-${UNDICI_VERSION}-stripped.tar.gz"
install -p -m0644 -t "${PWD}" "$(rpm -E '%{_sourcedir}')"/undici-"${UNDICI_VERSION}"-*
printf '=== %s ===\n' 'Updating dist-git sources' >&2
# shellcheck disable=SC2086,SC2046
${RPKG} $(test -n "${RELEASE}" && echo --release="${RELEASE}") new-sources $("$OFFLINE" && echo --offline) \
"undici-${UNDICI_VERSION}-stripped.tar.gz" \
"undici-${UNDICI_VERSION}-nm-prod.tgz" \
"undici-${UNDICI_VERSION}-nm-dev.tgz" \
"undici-${UNDICI_VERSION}-bundled-licenses.txt"