diff --git a/packages/alex/build.ncl b/packages/alex/build.ncl new file mode 100644 index 00000000..7e7d5311 --- /dev/null +++ b/packages/alex/build.ncl @@ -0,0 +1,42 @@ +let { BuildSpec, Local, OutputBin, Source, .. } = import "minimal.ncl" in +let base = import "../base/build.ncl" in +let bash = import "../bash/build.ncl" in +let ghc-bootstrap = import "../ghc-bootstrap/build.ncl" in +let gmp = import "../gmp/build.ncl" in +let toolchain = import "../toolchain/build.ncl" in + +let version = "3.5.1.0" in +{ + name = "alex", + + build_deps = [ + { file = "build.sh" } | Local, + { + url = "https://hackage.haskell.org/package/alex-%{version}/alex-%{version}.tar.gz", + sha256 = "c92efe86f8eb959ee03be6c04ee57ebc7e4abc75a6c4b26551215d7443e92a07", + extract = true, + } | Source, + base, + bash, + ghc-bootstrap, + toolchain, + ], + + runtime_deps = [ + base, + gmp, + ], + + cmd = "./build.sh", + build_args = { + include version, + }, + + outputs = { + alex = { glob = "usr/bin/alex" } | OutputBin, + }, + + attrs = { + upstream_version = version, + }, +} | BuildSpec diff --git a/packages/alex/build.sh b/packages/alex/build.sh new file mode 100755 index 00000000..0fedae42 --- /dev/null +++ b/packages/alex/build.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -euo pipefail + +cd "alex-$MINIMAL_ARG_VERSION" + +# Determine setup file +SETUP_FILE="Setup.hs" +if [ -f Setup.lhs ]; then + SETUP_FILE="Setup.lhs" +elif [ ! -f Setup.hs ]; then + echo "import Distribution.Simple" > Setup.hs + echo "main = defaultMain" >> Setup.hs + SETUP_FILE="Setup.hs" +fi + +ghc --make "$SETUP_FILE" +./Setup configure --prefix=/usr +./Setup build +./Setup copy --destdir="$OUTPUT_DIR" diff --git a/packages/ghc-bootstrap/build.ncl b/packages/ghc-bootstrap/build.ncl new file mode 100644 index 00000000..1cc87a3c --- /dev/null +++ b/packages/ghc-bootstrap/build.ncl @@ -0,0 +1,64 @@ +let { BuildSpec, Local, OutputBin, OutputData, OutputLib, Source, .. } = import "minimal.ncl" in +let { target, .. } = import "config.ncl" in +let base = import "../base/build.ncl" in +let bash = import "../bash/build.ncl" in +let gmp = import "../gmp/build.ncl" in +let make = import "../make/build.ncl" in +let ncurses = import "../ncurses/build.ncl" in +let perl = import "../perl/build.ncl" in +let tar = import "../tar/build.ncl" in +let toolchain = import "../toolchain/build.ncl" in +let xz = import "../xz/build.ncl" in + +let version = "9.8.1" in +{ + name = "ghc-bootstrap", + + build_deps = [ + { file = "build.sh" } | Local, + match { + { arch = 'Amd64, .. } => + { + url = "https://downloads.haskell.org/~ghc/%{version}/ghc-%{version}-x86_64-deb11-linux.tar.xz", + sha256 = "ca4dde3a6f34f1fe6d0783767671f02e862f1b0222ef2dc2c5c68cc2abc1abae", + extract = false, + } | Source, + { arch = 'Arm64, .. } => + { + url = "https://downloads.haskell.org/~ghc/%{version}/ghc-%{version}-aarch64-deb10-linux.tar.xz", + sha256 = "aab7af72614f8bf9ca624407aa4dbc69bc009c2b4cc1a0f3c062008db81bdb95", + extract = false, + } | Source, + } target, + base, + bash, + gmp, + make, + ncurses, + perl, + tar, + toolchain, + xz, + ], + + runtime_deps = [ + base, + gmp, + ncurses, + ], + + cmd = "./build.sh", + build_args = { + include version, + }, + + outputs = { + bins = { glob = "usr/bin/*" } | OutputBin, + libs = { glob = "usr/lib/ghc-%{version}/**", allow_executable = true } | OutputData, + libtinfo = { glob = "usr/lib/*.so*" } | OutputLib, + }, + + attrs = { + upstream_version = version, + }, +} | BuildSpec diff --git a/packages/ghc-bootstrap/build.sh b/packages/ghc-bootstrap/build.sh new file mode 100755 index 00000000..3c515059 --- /dev/null +++ b/packages/ghc-bootstrap/build.sh @@ -0,0 +1,90 @@ +#!/bin/bash +set -euo pipefail + +BOOTSTRAP_ARCH="$(uname -m)" +case "$BOOTSTRAP_ARCH" in + x86_64) + BOOTSTRAP_TAR="ghc-${MINIMAL_ARG_VERSION}-x86_64-deb11-linux.tar.xz" + ;; + aarch64) + BOOTSTRAP_TAR="ghc-${MINIMAL_ARG_VERSION}-aarch64-deb10-linux.tar.xz" + ;; + *) + echo "Unsupported architecture: $BOOTSTRAP_ARCH" + exit 1 + ;; +esac + +# Extract prebuilt GHC +mkdir -p bootstrap-src +tar -xof "$BOOTSTRAP_TAR" -C bootstrap-src --strip-components=1 + +# Configure and install GHC to $OUTPUT_DIR/usr +cd bootstrap-src +./configure --prefix=/usr +make install_bin install_lib update_package_db DESTDIR="$OUTPUT_DIR" + +# Find the real ncurses library dynamically +NCURSES_PATH="" +for path in \ + /usr/lib/libncursesw.so.6 \ + /usr/lib/libncurses.so.6 \ + /usr/lib64/libncursesw.so.6 \ + /usr/lib64/libncurses.so.6 \ + /lib/*/libncursesw.so.6 \ + /lib/*/libncurses.so.6 \ + /usr/lib/*/libncursesw.so.6 \ + /usr/lib/*/libncurses.so.6 \ + /lib/libncursesw.so.6 \ + /lib/libncurses.so.6; do + if [ -f "$path" ]; then + NCURSES_PATH="$path" + break + fi +done + +if [ -z "$NCURSES_PATH" ]; then + if command -v gcc >/dev/null 2>&1; then + for libname in libncursesw.so.6 libncurses.so.6; do + GCC_FOUND_PATH="$(gcc -print-file-name=$libname)" + if [ -f "$GCC_FOUND_PATH" ]; then + NCURSES_PATH="$GCC_FOUND_PATH" + break + fi + done + fi +fi + +if [ -z "$NCURSES_PATH" ]; then + if command -v ldconfig >/dev/null 2>&1; then + for libname in libncursesw.so.6 libncurses.so.6; do + LDCONFIG_PATH="$(ldconfig -p | awk -v lib="$libname" '$0 ~ lib {print $NF; exit}')" + if [ -f "$LDCONFIG_PATH" ]; then + NCURSES_PATH="$LDCONFIG_PATH" + break + fi + done + fi +fi + +if [ -z "$NCURSES_PATH" ]; then + echo "Error: Could not locate libncursesw.so.6 or libncurses.so.6" >&2 + exit 1 +fi + +# We also need a libtinfo.so.6, which GHC expects. +mkdir -p "$OUTPUT_DIR/usr/lib" +cp -p "$NCURSES_PATH" "$OUTPUT_DIR/usr/lib/libtinfo.so.6" + +# Let's also copy it in the GHC lib directory: +GHC_LIB_DIR="$OUTPUT_DIR/usr/lib/ghc-${MINIMAL_ARG_VERSION}/lib" +if [ -d "$GHC_LIB_DIR" ]; then + cp -p "$NCURSES_PATH" "$GHC_LIB_DIR/libtinfo.so.6" +fi + +# Modify bootstrap settings to use standard ld instead of ld.gold +SETTINGS_FILE="$OUTPUT_DIR/usr/lib/ghc-${MINIMAL_ARG_VERSION}/lib/settings" +if [ -f "$SETTINGS_FILE" ]; then + sed -i 's/-fuse-ld=gold//g' "$SETTINGS_FILE" + sed -i 's|/usr/bin/ld.gold|/usr/bin/ld|g' "$SETTINGS_FILE" +fi diff --git a/packages/ghc/build.ncl b/packages/ghc/build.ncl index 69a9fd8f..22931c3b 100644 --- a/packages/ghc/build.ncl +++ b/packages/ghc/build.ncl @@ -1,4 +1,5 @@ let { Attrs, BuildSpec, Local, Needs, OutputBin, OutputData, OutputLib, Source, Test, .. } = import "minimal.ncl" in +let alex = import "../alex/build.ncl" in let base = import "../base/build.ncl" in let bash = import "../bash/build.ncl" in let binutils = import "../binutils/build.ncl" in @@ -15,6 +16,8 @@ let automake = import "../automake/build.ncl" in let m4 = import "../m4/build.ncl" in let curl = import "../curl/build.ncl" in let make = import "../make/build.ncl" in +let ghc-bootstrap = import "../ghc-bootstrap/build.ncl" in +let happy = import "../happy/build.ncl" in let version = "9.10.3" in { @@ -27,33 +30,16 @@ let version = "9.10.3" in sha256 = "d266864b9e0b7b741abe8c9d6a790d7c01c21cf43a1419839119255878ebc59a", extract = false, } | Source, - { - url = "https://downloads.haskell.org/~ghc/9.8.1/ghc-9.8.1-x86_64-deb11-linux.tar.xz", - sha256 = "ca4dde3a6f34f1fe6d0783767671f02e862f1b0222ef2dc2c5c68cc2abc1abae", - extract = false, - } | Source, - { - url = "https://downloads.haskell.org/~ghc/9.8.1/ghc-9.8.1-aarch64-deb10-linux.tar.xz", - sha256 = "aab7af72614f8bf9ca624407aa4dbc69bc009c2b4cc1a0f3c062008db81bdb95", - extract = false, - } | Source, { url = "https://downloads.haskell.org/~ghc/%{version}/hadrian-bootstrap-sources/hadrian-bootstrap-sources-9.8.1.tar.gz", sha256 = "eec7233763bc31801fcbc996edc9c1f5abae707c1661deb8b22f0a7c2780b5e9", extract = false, } | Source, - { - url = "https://hackage.haskell.org/package/alex-3.5.1.0/alex-3.5.1.0.tar.gz", - sha256 = "c92efe86f8eb959ee03be6c04ee57ebc7e4abc75a6c4b26551215d7443e92a07", - extract = false, - } | Source, - { - url = "https://hackage.haskell.org/package/happy-1.20.1.1/happy-1.20.1.1.tar.gz", - sha256 = "8b4e7dc5a6c5fd666f8f7163232931ab28746d0d17da8fa1cbd68be9e878881b", - extract = false, - } | Source, + alex, base, bash, + ghc-bootstrap, + happy, perl, python, gmp, diff --git a/packages/ghc/build.sh b/packages/ghc/build.sh index 0f356e02..827ce68d 100755 --- a/packages/ghc/build.sh +++ b/packages/ghc/build.sh @@ -9,87 +9,19 @@ cd "ghc-${MINIMAL_ARG_VERSION}" sed -i 's/extern void\* malloc();/extern void\* malloc(long unsigned int);/' utils/hp2ps/Utilities.c sed -i 's/extern void \*realloc();/extern void \*realloc(void \*, long unsigned int);/' utils/hp2ps/Utilities.c -# Detect architecture for bootstrap binary selection -BOOTSTRAP_ARCH="$(uname -m)" -case "$BOOTSTRAP_ARCH" in - x86_64) BOOTSTRAP_TAR="ghc-9.8.1-x86_64-deb11-linux.tar.xz"; BOOTSTRAP_LIB_ARCH="x86_64-linux-ghc-9.8.1" ;; - aarch64) BOOTSTRAP_TAR="ghc-9.8.1-aarch64-deb10-linux.tar.xz"; BOOTSTRAP_LIB_ARCH="aarch64-linux-ghc-9.8.1" ;; - *) echo "Unsupported architecture: $BOOTSTRAP_ARCH"; exit 1 ;; -esac - -# Extract bootstrap GHC source and install it properly -mkdir -p ../bootstrap-src -tar -xof "../${BOOTSTRAP_TAR}" -C ../bootstrap-src --strip-components=1 -export BOOTSTRAP_DIR="$PWD/../bootstrap" -mkdir -p "$BOOTSTRAP_DIR" - -# Configure and install the bootstrap GHC -( - cd ../bootstrap-src - ./configure --prefix="$BOOTSTRAP_DIR" - make install_bin install_lib update_package_db -) - -# To run the bootstrap GHC, we need to set LD_LIBRARY_PATH so it can find its own libraries -export LD_LIBRARY_PATH="$BOOTSTRAP_DIR/lib/${BOOTSTRAP_LIB_ARCH}" - -# Ensure the bootstrap GHC and the build-produced tools (like alex/happy) are in PATH -export PATH="$BOOTSTRAP_DIR/bin:$PWD/_build/bin:$PATH" - -# We also need a libtinfo.so.6, which GHC expects but we don't have. We can link it to the system libncursesw.so.6. -mkdir -p "$BOOTSTRAP_DIR/lib" -ln -sf /usr/lib/libncursesw.so.6 "$BOOTSTRAP_DIR/lib/libtinfo.so.6" -export LD_LIBRARY_PATH="$BOOTSTRAP_DIR/lib:$LD_LIBRARY_PATH" - -# Modify bootstrap settings to use standard ld instead of ld.gold -if [ -f "$BOOTSTRAP_DIR/lib/settings" ]; then - sed -i 's/-fuse-ld=gold//g' "$BOOTSTRAP_DIR/lib/settings" - sed -i 's|/usr/bin/ld.gold|/usr/bin/ld|g' "$BOOTSTRAP_DIR/lib/settings" -fi - -# Extract and build alex -mkdir -p ../alex-src -tar -xof ../alex-3.5.1.0.tar.gz -C ../alex-src --strip-components=1 -( - cd ../alex-src - if [ ! -f Setup.hs ] && [ ! -f Setup.lhs ]; then - echo "import Distribution.Simple" > Setup.hs - echo "main = defaultMain" >> Setup.hs - fi - "$BOOTSTRAP_DIR/bin/ghc" --make Setup.hs - ./Setup configure --prefix="$BOOTSTRAP_DIR" - ./Setup build - ./Setup install -) - -# Extract and build happy -mkdir -p ../happy-src -tar -xof ../happy-1.20.1.1.tar.gz -C ../happy-src --strip-components=1 -( - cd ../happy-src - if [ ! -f Setup.hs ] && [ ! -f Setup.lhs ]; then - echo "import Distribution.Simple" > Setup.hs - echo "main = defaultMain" >> Setup.hs - fi - "$BOOTSTRAP_DIR/bin/ghc" --make Setup.hs - ./Setup configure --prefix="$BOOTSTRAP_DIR" - ./Setup build - ./Setup install -) - -# Create stubs for tools ./configure checks for but aren't strictly needed -# hadrian bootstrap will download the real cabal via internet access -mkdir -p "$BOOTSTRAP_DIR/bin" +# Create stubs for tools ./configure / bootstrap.py checks for but aren't strictly needed +STUB_DIR="$PWD/../stub-bin" +mkdir -p "$STUB_DIR" # Cabal stub - ./configure just checks it exists via AC_PATH_PROG(CABAL,cabal) -cat << 'EOF' > "$BOOTSTRAP_DIR/bin/cabal" +cat << 'EOF' > "$STUB_DIR/cabal" #!/bin/sh exit 0 EOF -chmod +x "$BOOTSTRAP_DIR/bin/cabal" +chmod +x "$STUB_DIR/cabal" # Sphinx stub - skip actual doc generation -cat << 'EOF' > "$BOOTSTRAP_DIR/bin/sphinx-build" +cat << 'EOF' > "$STUB_DIR/sphinx-build" #!/bin/sh if [ "$1" = "--version" ]; then echo "sphinx-build 4.0.0" @@ -97,27 +29,32 @@ if [ "$1" = "--version" ]; then fi exit 0 EOF -chmod +x "$BOOTSTRAP_DIR/bin/sphinx-build" +chmod +x "$STUB_DIR/sphinx-build" + +# Ensure stubs and build-produced tools are in PATH +export PATH="$STUB_DIR:$PWD/_build/bin:$PATH" # Bootstrap Hadrian # We must explicitly pass the bootstrap GHC path and also pass --bootstrap-sources to force # the bootstrap.py script to use the local offline tarballs instead of downloading them. -python3 hadrian/bootstrap/bootstrap.py -w "$BOOTSTRAP_DIR/bin/ghc" --bootstrap-sources ../hadrian-bootstrap-sources-9.8.1.tar.gz +python3 hadrian/bootstrap/bootstrap.py -w "$(command -v ghc)" --bootstrap-sources ../hadrian-bootstrap-sources-9.8.1.tar.gz -# Add pseudostore lib dirs to LD_LIBRARY_PATH so bootstrapped tools (like alex/happy) can find their dependencies +# Add pseudostore lib dirs to LD_LIBRARY_PATH so bootstrapped tools can find their dependencies PSEUDO_LIBS="$(find _build/pseudostore -name "*.so*" -exec dirname {} \; | sort -u | paste -sd : || true)" if [ -n "$PSEUDO_LIBS" ]; then - export LD_LIBRARY_PATH="$PSEUDO_LIBS:$LD_LIBRARY_PATH" + if [ -n "${LD_LIBRARY_PATH:-}" ]; then + export LD_LIBRARY_PATH="$PSEUDO_LIBS:$LD_LIBRARY_PATH" + else + export LD_LIBRARY_PATH="$PSEUDO_LIBS" + fi fi # Now we can configure GHC. -# Since alex/happy are now in _build/bin, configure will detect them correctly! ./configure \ --prefix=/usr \ - GHC="$BOOTSTRAP_DIR/bin/ghc" + GHC=ghc # Now we can run the build! -# GHC 9.10.3 uses Hadrian to build. _build/bin/hadrian -j"$(nproc)" --flavour=quickest --docs=none # And install! @@ -127,4 +64,4 @@ DESTDIR=$OUTPUT_DIR _build/bin/hadrian install --prefix=/usr --docs=none GHC_PKG="$(find "$OUTPUT_DIR" -name ghc-pkg -type f | head -1)" if [ -n "$GHC_PKG" ]; then "$GHC_PKG" recache -fi +fi \ No newline at end of file diff --git a/packages/happy/build.ncl b/packages/happy/build.ncl new file mode 100644 index 00000000..90513d61 --- /dev/null +++ b/packages/happy/build.ncl @@ -0,0 +1,42 @@ +let { BuildSpec, Local, OutputBin, Source, .. } = import "minimal.ncl" in +let base = import "../base/build.ncl" in +let bash = import "../bash/build.ncl" in +let ghc-bootstrap = import "../ghc-bootstrap/build.ncl" in +let gmp = import "../gmp/build.ncl" in +let toolchain = import "../toolchain/build.ncl" in + +let version = "1.20.1.1" in +{ + name = "happy", + + build_deps = [ + { file = "build.sh" } | Local, + { + url = "https://hackage.haskell.org/package/happy-%{version}/happy-%{version}.tar.gz", + sha256 = "8b4e7dc5a6c5fd666f8f7163232931ab28746d0d17da8fa1cbd68be9e878881b", + extract = true, + } | Source, + base, + bash, + ghc-bootstrap, + toolchain, + ], + + runtime_deps = [ + base, + gmp, + ], + + cmd = "./build.sh", + build_args = { + include version, + }, + + outputs = { + happy = { glob = "usr/bin/happy" } | OutputBin, + }, + + attrs = { + upstream_version = version, + }, +} | BuildSpec diff --git a/packages/happy/build.sh b/packages/happy/build.sh new file mode 100755 index 00000000..debbc31d --- /dev/null +++ b/packages/happy/build.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -euo pipefail + +cd "happy-$MINIMAL_ARG_VERSION" + +# Determine setup file +SETUP_FILE="Setup.hs" +if [ -f Setup.lhs ]; then + SETUP_FILE="Setup.lhs" +elif [ ! -f Setup.hs ]; then + echo "import Distribution.Simple" > Setup.hs + echo "main = defaultMain" >> Setup.hs + SETUP_FILE="Setup.hs" +fi + +ghc --make "$SETUP_FILE" +./Setup configure --prefix=/usr +./Setup build +./Setup copy --destdir="$OUTPUT_DIR"