Skip to content

Commit 4d5b3de

Browse files
committed
Initial commit
Signed-off-by: Aditya Alok <[email protected]>
0 parents  commit 4d5b3de

9 files changed

+300
-0
lines changed

Diff for: .github/workflows/build.yml

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
name: build
2+
3+
on:
4+
push:
5+
tags:
6+
- ghc-v[0-9]+.[0-9]+.[0-9]+
7+
workflow_dispatch:
8+
inputs:
9+
release_tag:
10+
description: Tag to be used for github release
11+
required: true
12+
13+
jobs:
14+
set-env-variables:
15+
runs-on: ubuntu-latest
16+
outputs:
17+
RELEASE_TAG: ${{ steps.env.outputs.RELEASE_TAG }}
18+
steps:
19+
- id: env
20+
run: |
21+
if [ "${{ github.event_name }}" != "workflow_dispatch" ]; then
22+
TAG="${GITHUB_REF#refs/*/}"
23+
else
24+
TAG="${{ github.event.inputs.release_tag }}"
25+
fi
26+
echo "::set-output name=RELEASE_TAG::${TAG}"
27+
28+
build:
29+
runs-on: ubuntu-latest
30+
env:
31+
ANDROID_HOME: "/opt/termux/android-sdk"
32+
NDK: "/opt/termux/android-ndk"
33+
strategy:
34+
matrix:
35+
target_arch: [aarch64, arm, i686, x86_64]
36+
fail-fast: false
37+
steps:
38+
- name: Clone repository
39+
uses: actions/checkout@v3
40+
with:
41+
fetch-depth: 1000
42+
- name: Build
43+
run: |
44+
mkdir ./out-dir
45+
46+
# Process tag '%ci:no-build' that may be added as line to commit message.
47+
# Forces CI to cancel current build with status 'passed'.
48+
if grep -qiP '^\s*%ci:no-build\s*$' <(git log --format="%B" -n 1 "HEAD"); then
49+
echo "[!] Force exiting as tag '%ci:no-build' was applied to HEAD commit message."
50+
touch ./out-dir/placeholder.zip
51+
exit 0
52+
fi
53+
54+
./run-docker.sh \
55+
./compile.sh ./out-dir ${{ matrix.target_arch }}
56+
57+
- name: Store files
58+
uses: actions/upload-artifact@v3
59+
with:
60+
name: ghc-${{ matrix.target_arch }}
61+
path: ./packages/out-dir/*
62+
63+
create-release:
64+
needs:
65+
- set-env-variables
66+
- build
67+
runs-on: "ubuntu-latest"
68+
permissions:
69+
contents: write
70+
steps:
71+
# Must perform checkout first, since it deletes the target directory
72+
# before running, and would therefore delete the downloaded artifacts
73+
- uses: actions/checkout@v3
74+
75+
- name: Get files
76+
uses: actions/download-artifact@v3
77+
78+
- name: Create new release
79+
env:
80+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
81+
RELEASE_TAG: ${{ needs.set-env-variables.outputs.RELEASE_TAG }}
82+
run: |
83+
if gh release view "${RELEASE_TAG}"; then
84+
# Release already exists. Update it:
85+
echo "Updating release '${RELEASE_TAG}' ..."
86+
gh release upload "${RELEASE_TAG}" ./ghc-*/*.xz --clobber
87+
else
88+
echo "Creating release '${RELEASE_TAG}' ..."
89+
gh release create "${RELEASE_TAG}" ./ghc-*/*.xz
90+
fi

Diff for: README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# About
2+
3+
Haskell cross-compiler (GHC) targeting Android.
4+
5+
Build arch: x86_64
6+
7+
## Available for archs (Target archs)
8+
9+
- aarch64/arm64
10+
- arm/arm32
11+
- i686
12+
- x86_64

Diff for: compile.sh

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/bash
2+
3+
set -e -u
4+
5+
TAR_OUTPUT_DIR="$(realpath "$1")"
6+
ARCH="$2"
7+
8+
source ./utils.sh
9+
10+
mkdir -p "$TAR_OUTPUT_DIR"
11+
12+
clone_termux_packages
13+
cp -r ./packages/ghc-cross termux-packages/packages/
14+
15+
cd termux-packages
16+
./build-package.sh -I -a "$ARCH" ghc-cross
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--- ghc-9.12.1/compiler/GHC/Driver/DynFlags.hs 2024-12-16 00:59:45.000000000 +0530
2+
+++ ghc-9.12.1.mod/compiler/GHC/Driver/DynFlags.hs 2025-01-04 19:52:30.600705081 +0530
3+
@@ -1311,6 +1311,8 @@
4+
(OSDarwin, ArchAArch64) -> [Opt_PIC]
5+
(OSLinux, ArchAArch64) -> [Opt_PIC, Opt_ExternalDynamicRefs]
6+
(OSLinux, ArchARM {}) -> [Opt_PIC, Opt_ExternalDynamicRefs]
7+
+ (OSLinux, ArchX86_64) -> [Opt_PIC, Opt_ExternalDynamicRefs]
8+
+ (OSLinux, ArchX86) -> [Opt_PIC, Opt_ExternalDynamicRefs]
9+
(OSLinux, ArchRISCV64 {}) -> [Opt_PIC, Opt_ExternalDynamicRefs]
10+
(OSOpenBSD, ArchX86_64) -> [Opt_PIC] -- Due to PIE support in
11+
-- OpenBSD since 5.3 release

Diff for: packages/ghc-cross/build.sh

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
TERMUX_PKG_HOMEPAGE=https://www.haskell.org/ghc/
2+
TERMUX_PKG_DESCRIPTION="The Glasgow Haskell Compiler"
3+
TERMUX_PKG_LICENSE="custom"
4+
TERMUX_PKG_MAINTAINER="Aditya Alok <[email protected]>"
5+
TERMUX_PKG_VERSION=9.12.1
6+
TERMUX_PKG_SRCURL="https://downloads.haskell.org/~ghc/$TERMUX_PKG_VERSION/ghc-$TERMUX_PKG_VERSION-src.tar.xz"
7+
TERMUX_PKG_SHA256=4a7410bdeec70f75717087b8f94bf5a6598fd61b3a0e1f8501d8f10be1492754
8+
TERMUX_PKG_DEPENDS="libiconv, libffi, libgmp, libandroid-posix-semaphore, bionic-host"
9+
TERMUX_PKG_BUILD_IN_SRC=true
10+
TERMUX_PKG_EXTRA_CONFIGURE_ARGS="
11+
--host=$TERMUX_BUILD_TUPLE
12+
--with-system-libffi"
13+
14+
TERMUX_PKG_NO_STATICSPLIT=true
15+
16+
termux_step_post_get_source() {
17+
termux_setup_ghc && termux_setup_cabal
18+
cabal update
19+
}
20+
21+
termux_step_pre_configure() {
22+
export CONF_CC_OPTS_STAGE1="$CFLAGS $CPPFLAGS" CONF_GCC_LINKER_OPTS_STAGE1="$LDFLAGS"
23+
export CONF_CC_OPTS_STAGE2="$CFLAGS $CPPFLAGS" CONF_GCC_LINKER_OPTS_STAGE2="$LDFLAGS"
24+
25+
export target="$TERMUX_HOST_PLATFORM"
26+
if [ "$TERMUX_ARCH" = "arm" ]; then
27+
target="armv7a-linux-androideabi"
28+
fi
29+
TERMUX_PKG_EXTRA_CONFIGURE_ARGS+=" --target=$target"
30+
31+
./boot.source
32+
}
33+
34+
termux_step_make() {
35+
unset CFLAGS CPPFLAGS LDFLAGS # For stage0 compilation.
36+
37+
./hadrian/build binary-dist-dir --flavour=quickest+no_profiled_libs --docs=none \
38+
"stage1.*.ghc.*.opts += -optl-landroid-posix-semaphore"
39+
}
40+
41+
termux_step_make_install() {
42+
43+
cd ./_build/bindist/ghc-* || exit 1
44+
45+
./configure --prefix="$TERMUX_PREFIX" --host="$target"
46+
make install
47+
48+
# We may build GHC with `llc-9` etc., but only `llc` is present in Termux
49+
sed -i 's/"LLVM llc command", "llc.*"/"LLVM llc command", "llc"/' \
50+
"$TERMUX_PREFIX/lib/$target-ghc-$TERMUX_PKG_VERSION/lib/settings" || :
51+
sed -i 's/"LLVM opt command", "opt.*"/"LLVM opt command", "opt"/' \
52+
"$TERMUX_PREFIX/lib/$target-ghc-$TERMUX_PKG_VERSION/lib/settings" || :
53+
}
54+
55+
termux_step_install_license() {
56+
install -Dm600 -t "$TERMUX_PREFIX/share/doc/$TERMUX_PKG_NAME" \
57+
"$TERMUX_PKG_SRCDIR/LICENSE"
58+
}
59+
60+
termux_step_post_massage() {
61+
# Package for Termux ci:
62+
63+
local host_platform="${TERMUX_HOST_PLATFORM}"
64+
[ "${TERMUX_ARCH}" = "arm" ] && host_platform="armv7a-linux-androideabi"
65+
66+
for f in "bin/${host_platform}"-{ghc,ghc-$TERMUX_PKG_VERSION,ghc-pkg*,hsc2hs,hp2ps}; do
67+
# Fix shebang and $topdir.
68+
sed -i -e "s|^#!${TERMUX_PREFIX}/bin/sh|#!/usr/bin/sh|" \
69+
-e "s|${host_platform}-ghc-${TERMUX_PKG_VERSION}|ghc-${TERMUX_PKG_VERSION}|g" \
70+
"$f"
71+
biname="$(basename "$f")"
72+
mv "$f" "bin/${biname/${host_platform}-/}"
73+
done
74+
75+
rm -rf "bin/$host_platform"-* || : # Remove rest binaries.
76+
77+
mkdir -p lib/ghc-"${TERMUX_PKG_VERSION}"/bin
78+
cp lib/"${host_platform}"-ghc-"${TERMUX_PKG_VERSION}"/settings lib/ghc-"${TERMUX_PKG_VERSION}"
79+
cp lib/"${host_platform}"-ghc-"${TERMUX_PKG_VERSION}"/bin/{ghc,ghc-pkg,hsc2hs,hp2ps,unlit} lib/ghc-"${TERMUX_PKG_VERSION}"/bin
80+
81+
tar -cvzf "${TAR_OUTPUT_DIR}/ghc-cross-bin-${TERMUX_PKG_VERSION}-${TERMUX_ARCH}.tar.xz" \
82+
lib/ghc-"${TERMUX_PKG_VERSION}" \
83+
bin/
84+
85+
exit
86+
}

Diff for: packages/ghc-cross/cabal-set-default-prefix.patch

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--- ghc-9.12.1/libraries/Cabal/Cabal/src/Distribution/Simple/InstallDirs.hs 2024-12-16 01:00:10.000000000 +0530
2+
+++ ghc-9.12.1.mod/libraries/Cabal/Cabal/src/Distribution/Simple/InstallDirs.hs 2025-01-04 20:05:06.846734461 +0530
3+
@@ -205,7 +205,7 @@
4+
windowsProgramFilesDir <- getWindowsProgramFilesDir
5+
return (windowsProgramFilesDir </> "Haskell")
6+
Haiku -> return "/boot/system/non-packaged"
7+
- _ -> return "/usr/local"
8+
+ _ -> return "@TERMUX_PREFIX@"
9+
installLibDir <-
10+
case buildOS of
11+
Windows -> return "$prefix"

Diff for: packages/ghc-cross/elf_types.patch

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--- ghc-9.12.1/rts/linker/ElfTypes.h 2024-12-16 00:59:46.000000000 +0530
2+
+++ ghc-9.12.1.mod/rts/linker/ElfTypes.h 2025-01-04 21:31:55.550538431 +0530
3+
@@ -8,6 +8,11 @@
4+
#include <elf.h>
5+
#include "linker/InitFini.h"
6+
7+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
8+
+
9+
+/* For ELF64 the definitions are the same. */
10+
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o)
11+
+
12+
/*
13+
* Define a set of types which can be used for both ELF32 and ELF64
14+
*/

Diff for: run-docker.sh

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/bin/sh
2+
set -e -u
3+
4+
CONTAINER_HOME_DIR=/home/builder
5+
6+
UNAME=$(uname)
7+
REPOROOT="$(dirname $(readlink -f $0))"
8+
9+
TERMUX_BUILDER_IMAGE_NAME="ghcr.io/termux/package-builder"
10+
CONTAINER_NAME="termux-package-builder"
11+
12+
USER=builder
13+
14+
echo "Running container '$CONTAINER_NAME' from image '$TERMUX_BUILDER_IMAGE_NAME'..."
15+
16+
docker start $CONTAINER_NAME >/dev/null 2>&1 || {
17+
echo "Creating new container..."
18+
docker run \
19+
--detach \
20+
--name $CONTAINER_NAME \
21+
--volume $REPOROOT:$CONTAINER_HOME_DIR/termux-packages \
22+
--tty \
23+
$TERMUX_BUILDER_IMAGE_NAME
24+
25+
if [ $(id -u) -ne 1000 -a $(id -u) -ne 0 ]; then
26+
echo "Changed builder uid/gid... (this may take a while)"
27+
docker exec $CONTAINER_NAME sudo chown -R $(id -u) $CONTAINER_HOME_DIR
28+
docker exec $CONTAINER_NAME sudo chown -R $(id -u) /data
29+
docker exec $CONTAINER_NAME sudo usermod -u $(id -u) builder
30+
docker exec $CONTAINER_NAME sudo groupmod -g $(id -g) builder
31+
fi
32+
}
33+
34+
docker exec --interactive $CONTAINER_NAME "$@"

Diff for: utils.sh

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
clone_termux_packages() {
4+
# clone termux-packages into container
5+
git clone https://github.com/termux/termux-packages.git
6+
}
7+
8+
download() {
9+
url="$1"
10+
destination="$2"
11+
checksum="$3"
12+
13+
curl --fail --retry 20 --retry-connrefused --retry-delay 30 --location -o "${destination}" "${url}" || {
14+
echo "Failed to download '${url}'."
15+
exit 1
16+
}
17+
18+
if [ "${checksum}" != "SKIP" ]; then
19+
actual_checksum=$(sha256sum "${destination}" | cut -f 1 -d ' ')
20+
if [ "${checksum}" != "${actual_checksum}" ]; then
21+
printf >&2 "Wrong checksum for %s:\nExpected: %s\nActual: %s\n" \
22+
"${url}" "${checksum}" "${actual_checksum}"
23+
return 1
24+
fi
25+
fi
26+
}

0 commit comments

Comments
 (0)