TERMUX_PKG_HOMEPAGE=https://emscripten.org TERMUX_PKG_DESCRIPTION="Emscripten: An LLVM-to-WebAssembly Compiler" TERMUX_PKG_LICENSE="MIT" TERMUX_PKG_MAINTAINER="@truboxl" TERMUX_PKG_VERSION="3.1.25" TERMUX_PKG_SRCURL=https://github.com/emscripten-core/emscripten.git TERMUX_PKG_GIT_BRANCH=$TERMUX_PKG_VERSION TERMUX_PKG_PLATFORM_INDEPENDENT=true TERMUX_PKG_RECOMMENDS="emscripten-llvm, emscripten-binaryen, python, nodejs-lts | nodejs" TERMUX_PKG_HOSTBUILD=true TERMUX_PKG_NO_STATICSPLIT=true TERMUX_PKG_AUTO_UPDATE=true # remove files according to emsdk/upstream directory after running # ./emsdk install latest TERMUX_PKG_RM_AFTER_INSTALL=" opt/emscripten-llvm/bin/clang-check opt/emscripten-llvm/bin/clang-cl opt/emscripten-llvm/bin/clang-cpp opt/emscripten-llvm/bin/clang-extdef-mapping opt/emscripten-llvm/bin/clang-format opt/emscripten-llvm/bin/clang-func-mapping opt/emscripten-llvm/bin/clang-import-test opt/emscripten-llvm/bin/clang-linker-wrapper opt/emscripten-llvm/bin/clang-nvlink-wrapper opt/emscripten-llvm/bin/clang-offload-bundler opt/emscripten-llvm/bin/clang-offload-packager opt/emscripten-llvm/bin/clang-offload-wrapper opt/emscripten-llvm/bin/clang-pseudo opt/emscripten-llvm/bin/clang-refactor opt/emscripten-llvm/bin/clang-rename opt/emscripten-llvm/bin/clang-repl opt/emscripten-llvm/bin/clang-scan-deps opt/emscripten-llvm/bin/diagtool opt/emscripten-llvm/bin/git-clang-format opt/emscripten-llvm/bin/hmaptool opt/emscripten-llvm/bin/ld.lld opt/emscripten-llvm/bin/ld64.lld opt/emscripten-llvm/bin/ld64.lld.darwin* opt/emscripten-llvm/bin/lld-link opt/emscripten-llvm/bin/llvm-cov opt/emscripten-llvm/bin/llvm-lib opt/emscripten-llvm/bin/llvm-ml opt/emscripten-llvm/bin/llvm-pdbutil opt/emscripten-llvm/bin/llvm-profdata opt/emscripten-llvm/bin/llvm-rc opt/emscripten-llvm/bin/llvm-strings opt/emscripten-llvm/lib/libclang.so* opt/emscripten-llvm/share opt/emscripten/LICENSE " # https://github.com/emscripten-core/emscripten/issues/11362 # can switch to stable LLVM to save space once above is fixed _LLVM_COMMIT=effd75bda4b1a9b26e554c1cda3e3b4c72fa0aa8 _LLVM_TGZ_SHA256=5e7b8c543b9021110de8e8ae49f651e5bdaafdb2cecfa56a079d60e03188a56d # https://github.com/emscripten-core/emscripten/issues/12252 # upstream says better bundle the right binaryen revision for now _BINARYEN_COMMIT=52079ae8ea3abec509c3184720d1824b9093cb2f _BINARYEN_TGZ_SHA256=65b72e311b9850dba5739dd5b462206b00eaaf3cd96e16d5ecb462b629bba39a # https://github.com/emscripten-core/emsdk/blob/main/emsdk.py # https://chromium.googlesource.com/emscripten-releases/+/refs/heads/main/src/build.py # https://github.com/llvm/llvm-project _LLVM_BUILD_ARGS=" -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_CROSSCOMPILING=ON -DCMAKE_INSTALL_PREFIX=$TERMUX_PREFIX/opt/emscripten-llvm -DDEFAULT_SYSROOT=$(dirname $TERMUX_PREFIX) -DGENERATOR_IS_MULTI_CONFIG=ON -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_ENABLE_BINDINGS=OFF -DLLVM_ENABLE_LIBEDIT=OFF -DLLVM_ENABLE_LIBPFM=OFF -DLLVM_ENABLE_LIBXML2=OFF -DLLVM_ENABLE_PROJECTS=clang;compiler-rt;lld -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INSTALL_TOOLCHAIN_ONLY=ON -DLLVM_LINK_LLVM_DYLIB=ON -DLLVM_TABLEGEN=$TERMUX_PKG_HOSTBUILD_DIR/bin/llvm-tblgen -DCLANG_DEFAULT_LINKER=lld -DCLANG_ENABLE_ARCMT=OFF -DCLANG_ENABLE_STATIC_ANALYZER=OFF -DCLANG_TABLEGEN=$TERMUX_PKG_HOSTBUILD_DIR/bin/clang-tblgen -DCOMPILER_RT_BUILD_CRT=OFF -DCOMPILER_RT_BUILD_LIBFUZZER=OFF -DCOMPILER_RT_BUILD_MEMPROF=OFF -DCOMPILER_RT_BUILD_PROFILE=OFF -DCOMPILER_RT_BUILD_SANITIZERS=OFF -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_INCLUDE_TESTS=OFF " # https://github.com/WebAssembly/binaryen/blob/main/CMakeLists.txt _BINARYEN_BUILD_ARGS=" -DCMAKE_INSTALL_PREFIX=$TERMUX_PREFIX/opt/emscripten-binaryen -DBUILD_TESTS=OFF " # based on scripts/updates/internal/termux_github_auto_update.sh termux_pkg_auto_update() { local latest_tag latest_tag=$(termux_github_api_get_tag "${TERMUX_PKG_SRCURL}" "${TERMUX_PKG_UPDATE_TAG_TYPE}") if [ -z "$latest_tag" ]; then termux_error_exit "ERROR: Unable to get tag from ${TERMUX_PKG_SRCURL}" fi if [ "$latest_tag" = "$TERMUX_PKG_VERSION" ]; then echo "INFO: No update needed. Already at version '$TERMUX_PKG_VERSION'." return 0 fi # https://github.com/emscripten-core/emscripten/blob/main/docs/packaging.md # https://github.com/archlinux/svntogit-community/tree/packages/emscripten/trunk # below generates commit hash for the deps according to emscripten releases local releases_tags release_tag deps_revision deps_json llvm_commit binaryen_commit llvm_tgz_sha256 binaryen_tgz_sha256 releases_tags=$(curl -s https://raw.githubusercontent.com/emscripten-core/emsdk/main/emscripten-releases-tags.json) release_tag=$(echo "$releases_tags" | python3 -c "import json,sys;print(json.load(sys.stdin)[\"releases\"][\"$latest_tag\"])") deps_revision=$(curl -s "https://chromium.googlesource.com/emscripten-releases/+/$release_tag/DEPS?format=text" | base64 -d | grep "_revision':" | sed -e "s|'|\"|g") deps_json=$(echo -e "{\n${deps_revision}EOL" | sed -e "s|,EOL|\n}|") llvm_commit=$(echo "$deps_json" | python3 -c "import json,sys;print(json.load(sys.stdin)[\"llvm_project_revision\"])") binaryen_commit=$(echo "$deps_json" | python3 -c "import json,sys;print(json.load(sys.stdin)[\"binaryen_revision\"])") curl -LC - "https://github.com/llvm/llvm-project/archive/$llvm_commit.tar.gz" -o "${TMPDIR:-/tmp}/$llvm_commit.tar.gz" curl -LC - "https://github.com/WebAssembly/binaryen/archive/$binaryen_commit.tar.gz" -o "${TMPDIR:-/tmp}/$binaryen_commit.tar.gz" llvm_tgz_sha256=$(sha256sum "${TMPDIR:-/tmp}/$llvm_commit.tar.gz" | sed -e "s| .*$||") binaryen_tgz_sha256=$(sha256sum "${TMPDIR:-/tmp}/$binaryen_commit.tar.gz" | sed -e "s| .*$||") echo "INFO: Generated *.tar.gz checksum for:" echo "_LLVM_COMMIT $llvm_commit = $llvm_tgz_sha256" echo "_BINARYEN_COMMIT $binaryen_commit = $binaryen_tgz_sha256" sed -i "$TERMUX_PKG_BUILDER_DIR/build.sh" -e "s|^_LLVM_COMMIT=.*|_LLVM_COMMIT=${llvm_commit}|" sed -i "$TERMUX_PKG_BUILDER_DIR/build.sh" -e "s|^_LLVM_TGZ_SHA256=.*|_LLVM_TGZ_SHA256=${llvm_tgz_sha256}|" sed -i "$TERMUX_PKG_BUILDER_DIR/build.sh" -e "s|^_BINARYEN_COMMIT=.*|_BINARYEN_COMMIT=${binaryen_commit}|" sed -i "$TERMUX_PKG_BUILDER_DIR/build.sh" -e "s|^_BINARYEN_TGZ_SHA256=.*|_BINARYEN_TGZ_SHA256=${binaryen_tgz_sha256}|" rm -f "${TMPDIR:-/tmp}/$llvm_commit.tar.gz" "${TMPDIR:-/tmp}/$binaryen_commit.tar.gz" termux_pkg_upgrade_version "$latest_tag" } termux_step_post_get_source() { termux_download \ "https://github.com/llvm/llvm-project/archive/$_LLVM_COMMIT.tar.gz" \ "$TERMUX_PKG_CACHEDIR/llvm.tar.gz" \ "$_LLVM_TGZ_SHA256" termux_download \ "https://github.com/WebAssembly/binaryen/archive/$_BINARYEN_COMMIT.tar.gz" \ "$TERMUX_PKG_CACHEDIR/binaryen.tar.gz" \ "$_BINARYEN_TGZ_SHA256" tar -xf "$TERMUX_PKG_CACHEDIR/llvm.tar.gz" -C "$TERMUX_PKG_CACHEDIR" tar -xf "$TERMUX_PKG_CACHEDIR/binaryen.tar.gz" -C "$TERMUX_PKG_CACHEDIR" local llvm_patches=$(find "$TERMUX_PKG_BUILDER_DIR" -mindepth 1 -maxdepth 1 -type f -name 'llvm-project-*.patch.diff') if [ -n "$llvm_patches" ]; then cd "$TERMUX_PKG_CACHEDIR/llvm-project-$_LLVM_COMMIT" for patch in $llvm_patches; do patch -p1 -i "$patch" || : done local llvm_patches_rej=$(find . -type f -name '*.rej') if [ -n "$llvm_patches_rej" ]; then echo "INFO: Patch failed! Printing *.rej files ..." for rej in $llvm_patches_rej; do echo -e "\n\n${rej}" cat "$rej" done termux_error_exit "Patch failed! Please check patch errors above!" fi fi local binaryen_patches=$(find "$TERMUX_PKG_BUILDER_DIR" -mindepth 1 -maxdepth 1 -type f -name 'binaryen-*.patch.diff') if [ -n "$binaryen_patches" ]; then cd "$TERMUX_PKG_CACHEDIR/binaryen-$_BINARYEN_COMMIT" for patch in $binaryen_patches; do patch -p1 -i "$patch" || : done local binaryen_patches_rej=$(find . -type f -name '*.rej') if [ -n "$binaryen_patches_rej" ]; then echo "INFO: Patch failed! Printing *.rej files ..." for rej in $binaryen_patches_rej; do echo -e "\n\n${rej}" cat "$rej" done termux_error_exit "Patch failed! Please check patch errors above!" fi fi } termux_step_host_build() { termux_setup_cmake termux_setup_ninja cmake \ -G Ninja \ -S "$TERMUX_PKG_CACHEDIR/llvm-project-$_LLVM_COMMIT/llvm" \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PROJECTS=clang cmake \ --build "$TERMUX_PKG_HOSTBUILD_DIR" \ -j "$TERMUX_MAKE_PROCESSES" \ --target llvm-tblgen clang-tblgen } termux_step_make() { termux_setup_cmake termux_setup_ninja # from packages/libllvm/build.sh export _LLVM_DEFAULT_TARGET_TRIPLE=${CCTERMUX_HOST_PLATFORM/-/-unknown-} export _LLVM_TARGET_ARCH if [ "$TERMUX_ARCH" = arm ]; then _LLVM_TARGET_ARCH=ARM elif [ "$TERMUX_ARCH" = aarch64 ]; then _LLVM_TARGET_ARCH=AArch64 elif [ "$TERMUX_ARCH" = i686 ] || [ "$TERMUX_ARCH" = x86_64 ]; then _LLVM_TARGET_ARCH=X86 else termux_error_exit "Invalid arch: $TERMUX_ARCH" fi _LLVM_BUILD_ARGS+=" -DLLVM_TARGET_ARCH=$_LLVM_TARGET_ARCH" _LLVM_BUILD_ARGS+=" -DLLVM_TARGETS_TO_BUILD=WebAssembly;$_LLVM_TARGET_ARCH" _LLVM_BUILD_ARGS+=" -DLLVM_HOST_TRIPLE=$_LLVM_DEFAULT_TARGET_TRIPLE" cmake \ -G Ninja \ -S "$TERMUX_PKG_CACHEDIR/llvm-project-$_LLVM_COMMIT/llvm" \ -B "$TERMUX_PKG_BUILDDIR/build-llvm" \ $_LLVM_BUILD_ARGS cmake \ --build "$TERMUX_PKG_BUILDDIR/build-llvm" \ -j "$TERMUX_MAKE_PROCESSES" \ --target install cmake \ -G Ninja \ -S "$TERMUX_PKG_CACHEDIR/binaryen-$_BINARYEN_COMMIT" \ -B "$TERMUX_PKG_BUILDDIR/build-binaryen" \ $_BINARYEN_BUILD_ARGS cmake \ --build "$TERMUX_PKG_BUILDDIR/build-binaryen" \ -j "$TERMUX_MAKE_PROCESSES" \ --target install } termux_step_make_install() { cd "$TERMUX_PKG_SRCDIR" # https://github.com/emscripten-core/emscripten/pull/15840 sed -e "s|-git||" -i "$TERMUX_PKG_SRCDIR/emscripten-version.txt" # skip using Makefile which does host npm install rm -fr "$TERMUX_PREFIX/opt/emscripten" ./tools/install.py "$TERMUX_PREFIX/opt/emscripten" # subpackage optional third party test suite files cp -fr "$TERMUX_PKG_SRCDIR/test/third_party" "$TERMUX_PREFIX/opt/emscripten/test/third_party" # first run generates .emscripten and exits immediately rm -f "$TERMUX_PKG_SRCDIR/.emscripten" ./emcc --generate-config sed -i .emscripten -e "s|^EMSCRIPTEN_ROOT.*|EMSCRIPTEN_ROOT = '$TERMUX_PREFIX/opt/emscripten' # directory|" sed -i .emscripten -e "s|^LLVM_ROOT.*|LLVM_ROOT = '$TERMUX_PREFIX/opt/emscripten-llvm/bin' # directory|" sed -i .emscripten -e "s|^BINARYEN_ROOT.*|BINARYEN_ROOT = '$TERMUX_PREFIX/opt/emscripten-binaryen' # directory|" sed -i .emscripten -e "s|^NODE_JS.*|NODE_JS = '$TERMUX_PREFIX/bin/node' # executable|" grep "$TERMUX_PREFIX" "$TERMUX_PKG_SRCDIR/.emscripten" install -Dm644 "$TERMUX_PKG_SRCDIR/.emscripten" "$TERMUX_PREFIX/opt/emscripten/.emscripten" # add emscripten directory to PATH var cat <<- EOF > "$TERMUX_PKG_TMPDIR/emscripten.sh" #!$TERMUX_PREFIX/bin/sh export PATH=\$PATH:$TERMUX_PREFIX/opt/emscripten EOF install -Dm644 "$TERMUX_PKG_TMPDIR/emscripten.sh" "$TERMUX_PREFIX/etc/profile.d/emscripten.sh" # add useful tools not installed by LLVM_INSTALL_TOOLCHAIN_ONLY=ON for tool in llc llvm-{addr2line,dwarfdump,dwp,link,mc,nm,objdump,ranlib,readobj,size} opt; do install -Dm755 "$TERMUX_PKG_BUILDDIR/build-llvm/bin/$tool" "$TERMUX_PREFIX/opt/emscripten-llvm/bin/$tool" done # wasm32 triplets ln -fsT "clang" "$TERMUX_PREFIX/opt/emscripten-llvm/bin/wasm32-clang" ln -fsT "clang++" "$TERMUX_PREFIX/opt/emscripten-llvm/bin/wasm32-clang++" ln -fsT "clang" "$TERMUX_PREFIX/opt/emscripten-llvm/bin/wasm32-wasi-clang" ln -fsT "clang++" "$TERMUX_PREFIX/opt/emscripten-llvm/bin/wasm32-wasi-clang++" ln -fsT "lld" "$TERMUX_PREFIX/opt/emscripten-llvm/bin/wasm-ld" } termux_step_create_debscripts() { # emscripten's package-lock.json is generated with nodejs v12.13.0 # which comes with npm v6 which used lockfile version 1 # which isn't compatible with lockfile version 2 used in npm v7 and v8 cat <<- EOF > postinst #!$TERMUX_PREFIX/bin/bash if [ -n "\$(command -v npm)" ]; then cd "$TERMUX_PREFIX/opt/emscripten" NPM_VERSION=\$(npm --version) NPM_MAJOR_VERSION=\${NPM_VERSION:0:1} if [ "\$NPM_MAJOR_VERSION" = 6 ]; then echo 'Running "npm ci --production --no-optional" in $TERMUX_PREFIX/opt/emscripten ...' npm ci --production --no-optional else echo 'Running "npm install --omit=dev --omit=optional" in $TERMUX_PREFIX/opt/emscripten ...' rm package-lock.json npm install --omit=dev --omit=optional fi else echo ' WARNING: npm is not installed! Emscripten may not work properly without installing node modules! ' >&2 fi echo ' ==================== Post-install notice: If this is the first time installing Emscripten, please start a new session to take effect. If you are upgrading, you may want to clear the cache by running the command below to fix issues. emcc --clear-cache ====================' EOF cat <<- EOF > postrm #!$TERMUX_PREFIX/bin/sh case "\$1" in purge|remove) rm -fr "$TERMUX_PREFIX/opt/emscripten" esac EOF } # Emscripten Test Suite (Optional) # Some preparations need to be made in Emscripten directory before running # test suite on Android / Termux. Refer docs below: # https://emscripten.org/docs/getting_started/test-suite.html # https://github.com/emscripten-core/emscripten/pull/13493 # https://github.com/emscripten-core/emscripten/issues/9098 # # Steps: # - pkg install cmake emscripten-tests-third-party ndk-sysroot openjdk-17 # - cd $PREFIX/opt/emscripten # - MATHLIB="m" pip install -r requirements-dev.txt # - npm install --omit=optional # - export EMTEST_SKIP_V8=1 # - test/runner {test_name}