feat: add candidate FreeCAD naming SDK and attachment oracles
Build and verify the candidate-only FreeCAD naming bridge and OCCT worker path, including three-stage StringHasher restoration. Add Datum, ShapeBinder, attachment-mode, and PartDesign structure oracles plus offline SDK build plans and CI boundary checks.
This commit is contained in:
85
scripts/build-cpython-wasm.sh
Normal file
85
scripts/build-cpython-wasm.sh
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
PYTHON_ROOT="${CPYTHON_WASM_CACHE_DIR:-${ROOT_DIR}/.cache/toolchains/python}"
|
||||
DOWNLOAD_DIR="${PYTHON_ROOT}/downloads"
|
||||
SOURCE_DIR="${PYTHON_ROOT}/src"
|
||||
BUILD_DIR="${PYTHON_ROOT}/build-wasm"
|
||||
INSTALL_DIR="${PYTHON_ROOT}/install-wasm"
|
||||
EM_CACHE_DIR="${ROOT_DIR}/.cache/toolchains/emscripten-freecad-cache"
|
||||
ARCHIVE="${DOWNLOAD_DIR}/Python-3.13.5.tar.xz"
|
||||
DOWNLOAD_URL="${CPYTHON_DOWNLOAD_URL:-https://repo.huaweicloud.com/python/3.13.5/Python-3.13.5.tar.xz}"
|
||||
EXPECTED_MD5="dbaa8833aa736eddbb18a6a6ae0c10fa"
|
||||
EXPECTED_SHA256="93e583f243454e6e9e4588ca2c2662206ad961659863277afcdb96801647d640"
|
||||
SOURCE_DATE_EPOCH_VALUE="1735689600"
|
||||
JOBS="${JOBS:-$(nproc)}"
|
||||
|
||||
if [[ "$(emcc --version | sed -n '1s/.* \([0-9][0-9.]*\) .*/\1/p')" != "3.1.69" ]]; then
|
||||
echo "CPython wasm SDK must use Emscripten 3.1.69." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$(python3.13 --version | awk '{print $2}')" != "3.13.5" ]]; then
|
||||
echo "CPython wasm cross-build requires host Python 3.13.5." >&2
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "${DOWNLOAD_DIR}" "${SOURCE_DIR}" "${BUILD_DIR}" "${INSTALL_DIR}/include/python3.13" "${INSTALL_DIR}/lib"
|
||||
if [[ ! -f "${ARCHIVE}" ]]; then
|
||||
curl --fail --location --retry 3 --connect-timeout 15 --output "${ARCHIVE}.part" "${DOWNLOAD_URL}"
|
||||
mv "${ARCHIVE}.part" "${ARCHIVE}"
|
||||
fi
|
||||
[[ "$(md5sum "${ARCHIVE}" | awk '{print $1}')" == "${EXPECTED_MD5}" ]] || { echo "CPython archive MD5 mismatch." >&2; exit 1; }
|
||||
[[ "$(sha256sum "${ARCHIVE}" | awk '{print $1}')" == "${EXPECTED_SHA256}" ]] || { echo "CPython archive SHA-256 mismatch." >&2; exit 1; }
|
||||
if [[ ! -f "${SOURCE_DIR}/configure" ]]; then
|
||||
tar -xJf "${ARCHIVE}" -C "${SOURCE_DIR}" --strip-components=1
|
||||
fi
|
||||
|
||||
(
|
||||
cd "${BUILD_DIR}"
|
||||
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH_VALUE}" \
|
||||
CONFIG_SITE="${SOURCE_DIR}/Tools/wasm/config.site-wasm32-emscripten" \
|
||||
EM_FROZEN_CACHE=0 EM_CACHE="${EM_CACHE_DIR}" emconfigure "${SOURCE_DIR}/configure" -C \
|
||||
--host=wasm32-unknown-emscripten \
|
||||
--build="$("${SOURCE_DIR}/config.guess")" \
|
||||
--with-emscripten-target=node \
|
||||
--enable-wasm-pthreads \
|
||||
--disable-wasm-dynamic-linking \
|
||||
--with-build-python=/usr/bin/python3.13 \
|
||||
--with-ensurepip=no \
|
||||
--disable-test-modules \
|
||||
--without-mimalloc
|
||||
)
|
||||
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH_VALUE}" EM_FROZEN_CACHE=0 EM_CACHE="${EM_CACHE_DIR}" \
|
||||
emmake make -C "${BUILD_DIR}" -j"${JOBS}" libpython3.13.a pybuilddir.txt
|
||||
PYTHON_SYSCONFIG_DATA="${BUILD_DIR}/$(tr -d '\n' < "${BUILD_DIR}/pybuilddir.txt")/_sysconfigdata__emscripten_wasm32-emscripten.py"
|
||||
[[ -s "${PYTHON_SYSCONFIG_DATA}" ]] || { echo "CPython wasm sysconfig data is missing." >&2; exit 1; }
|
||||
touch --date="@${SOURCE_DATE_EPOCH_VALUE}" "${PYTHON_SYSCONFIG_DATA}"
|
||||
rm -f "${BUILD_DIR}/usr/local/lib/python313.zip"
|
||||
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH_VALUE}" EM_FROZEN_CACHE=1 EM_CACHE="${EM_CACHE_DIR}" \
|
||||
emmake make -C "${BUILD_DIR}" wasm_stdlib
|
||||
cp -a "${SOURCE_DIR}/Include/." "${INSTALL_DIR}/include/python3.13/"
|
||||
cp -f "${BUILD_DIR}/pyconfig.h" "${INSTALL_DIR}/include/python3.13/pyconfig.h"
|
||||
cp -f "${BUILD_DIR}/libpython3.13.a" "${INSTALL_DIR}/lib/libpython3.13.a"
|
||||
mkdir -p "${INSTALL_DIR}/lib/python-deps" "${INSTALL_DIR}/share/python-wasm-stdlib"
|
||||
cp -f "${BUILD_DIR}/Modules/_decimal/libmpdec/libmpdec.a" "${INSTALL_DIR}/lib/python-deps/libmpdec.a"
|
||||
cp -f "${BUILD_DIR}/Modules/expat/libexpat.a" "${INSTALL_DIR}/lib/python-deps/libexpat.a"
|
||||
cp -f "${BUILD_DIR}/Modules/_hacl/libHacl_Hash_SHA2.a" "${INSTALL_DIR}/lib/python-deps/libHacl_Hash_SHA2.a"
|
||||
cp -f "${EM_CACHE_DIR}/sysroot/lib/wasm32-emscripten/libz.a" "${INSTALL_DIR}/lib/python-deps/libz.a"
|
||||
cp -f "${EM_CACHE_DIR}/sysroot/lib/wasm32-emscripten/libbz2.a" "${INSTALL_DIR}/lib/python-deps/libbz2.a"
|
||||
cp -f "${EM_CACHE_DIR}/sysroot/lib/wasm32-emscripten/libsqlite3-mt.a" "${INSTALL_DIR}/lib/python-deps/libsqlite3-mt.a"
|
||||
cp -a "${BUILD_DIR}/usr/local/." "${INSTALL_DIR}/share/python-wasm-stdlib/"
|
||||
|
||||
cd "${ROOT_DIR}"
|
||||
node --input-type=module - "${INSTALL_DIR}" <<'NODE'
|
||||
import { inspectWasmStaticArchive } from './scripts/freecad-naming-sdk-lib.mjs'
|
||||
const install = process.argv[2]
|
||||
const dependencies = ['libmpdec.a', 'libexpat.a', 'libHacl_Hash_SHA2.a', 'libz.a', 'libbz2.a', 'libsqlite3-mt.a']
|
||||
console.log(JSON.stringify({
|
||||
status: 'cpython-wasm-pass',
|
||||
version: '3.13.5',
|
||||
pthread: true,
|
||||
archive: await inspectWasmStaticArchive(`${install}/lib/libpython3.13.a`),
|
||||
dependencies: Object.fromEntries(await Promise.all(dependencies.map(async (name) => [name, await inspectWasmStaticArchive(`${install}/lib/python-deps/${name}`)]))),
|
||||
wasmStdlib: `${install}/share/python-wasm-stdlib/lib/python313.zip`,
|
||||
}, null, 2))
|
||||
NODE
|
||||
Reference in New Issue
Block a user