# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4

PortSystem          1.0
PortGroup           github 1.0

# Compile oven-sh/bun instead of the npm registry stub (a 6 KB wrapper that
# destroots a prebuilt Mach-O via optionalDependencies).
#
# Upstream's build is ninja driven by an already-installed bun (codegen
# and JS builtins). That cycle is broken the same way Homebrew-core does:
# a checksummed previous-release zip is the bootstrap compiler.
# JavaScriptCore is the checksummed prebuilt from oven-sh/WebKit (building
# JSC from source is the build:release:local path and a 7–18 GB clone).
#
# Pins below match bun-v${version}:
#   bootstrap bun  — pins.bun.version in scripts/build/ci-images/spec.ts
#   WebKit         — WEBKIT_VERSION in scripts/build/deps/webkit.ts
#   LLVM           — LLVM_VERSION_RANGE in scripts/build/tools.ts
#   GIT_SHA        — tag revision (archive tarball has no .git)

github.setup        oven-sh bun 1.4.3 bun-v
github.tarball_from archive
revision            0

set git_sha         c6da4a4d3010e5553438c60f6bd76d981976867c
set bootstrap_version \
                    1.4.2
set webkit_version  0c06faadf65bf8e8c8ad3a5a8aca83e1e9ed653f
set webkit_version16 \
                    [string range ${webkit_version} 0 15]
# Upstream scripts/build/tools.ts: LLVM_VERSION_RANGE >=23.1.0 <23.1.99
# (LLVM_VERSION 23.1.1). Older macOS may need a different pin later.
set llvm_version    23

maintainers         {@oakimov} openmaintainer
categories          devel
license             MIT LGPL-2
supported_archs     arm64 x86_64

description         JavaScript runtime built from scratch to serve the modern JavaScript ecosystem
long_description    Bun is an all-in-one JavaScript runtime and toolkit designed for \
                    speed, complete with a bundler, test runner, and Node.js-compatible \
                    package manager. This port compiles bun from source using LLVM 23, \
                    a bootstrap bun, and a prebuilt JavaScriptCore.

homepage            https://bun.sh

# Upstream WebKit/bootstrap assets reuse fixed filenames across releases
# (bun-webkit-macos-*.tar.gz, bun-darwin-*.zip). Scope distfiles by port
# version so MacPorts mirrors and local caches cannot serve a prior pin.
dist_subdir         ${name}/${version}

checksums           ${distname}${extract.suffix} \
                    rmd160  6a31eb29cfddc164378df2d324490b30b8c426a3 \
                    sha256  2366bc56d092f8535bbe5827788e20d987fbc96798de4d683e0ca78ea286ebf4 \
                    size    77357469

if {${configure.build_arch} eq "arm64"} {
    set bootstrap_distfile  bun-darwin-aarch64.zip
    set bootstrap_dir       bun-darwin-aarch64
    set webkit_distfile     bun-webkit-macos-arm64.tar.gz
    # prebuiltDestDir: webkit-<16>-macos-arm64 (lto off, so no -lto suffix).
    set webkit_cache_key    webkit-${webkit_version16}-macos-arm64
    checksums-append    ${bootstrap_distfile} \
                        rmd160  92976b718196e6ac0ca969e35924416d27661a9b \
                        sha256  90987a3a16d7db556d886ac3d551e7b6d3edf0a1cf43acaed622e8676be1d12f \
                        size    25377591 \
                        ${webkit_distfile} \
                        rmd160  e9c0717fc2019b6980ef02f42de645e06827ff49 \
                        sha256  f3e82adbd0e96debecc74fed5fb88ac736e653a914fb25dc81910c90c2ee7eaa \
                        size    211124082
} elseif {${configure.build_arch} eq "x86_64"} {
    # baseline: no AVX, matching Homebrew-core for generic Intel.
    set bootstrap_distfile  bun-darwin-x64-baseline.zip
    set bootstrap_dir       bun-darwin-x64-baseline
    set webkit_distfile     bun-webkit-macos-amd64.tar.gz
    # prebuiltDestDir: webkit-<16>-macos (x64 has no arch suffix).
    set webkit_cache_key    webkit-${webkit_version16}-macos
    checksums-append    ${bootstrap_distfile} \
                        rmd160  ffb10657ace4edb6c63dc97502652133f98d286f \
                        sha256  bad5bbd6cf14d0980d115f5954c9ff904df619d5e994d2da1ffccd3f316300b0 \
                        size    28440543 \
                        ${webkit_distfile} \
                        rmd160  b5f605df6cf702a5c6e7215e36c2b164734e35d1 \
                        sha256  f6969de3ab2357f20b112926a3cd18b5653beadf4a38840358b32d33eeffad44 \
                        size    221367926
} else {
    known_fail          yes
    set bootstrap_distfile  {}
    set bootstrap_dir       {}
    set webkit_distfile     {}
    set webkit_cache_key    {}
    pre-fetch {
        ui_error "${name} is only supported on arm64 and x86_64"
        return -code error "unsupported architecture"
    }
}

if {${bootstrap_distfile} ne ""} {
    master_sites-append https://github.com/oven-sh/bun/releases/download/bun-v${bootstrap_version}/:bootstrap \
                        https://github.com/oven-sh/WebKit/releases/download/autobuild-${webkit_version}/:webkit
    distfiles-append    ${bootstrap_distfile}:bootstrap \
                        ${webkit_distfile}:webkit
}

extract.only        ${distname}${extract.suffix}

depends_build-append \
                    path:bin/cargo:cargo \
                    port:clang-${llvm_version} \
                    path:bin/cmake:cmake \
                    port:llvm-${llvm_version} \
                    port:ninja \
                    path:bin/pkg-config:pkgconfig \
                    port:rust \
                    port:rust-src

# libjpeg-turbo's x86_64 SIMD is nasm-assembled.
if {${configure.build_arch} eq "x86_64"} {
    depends_build-append port:nasm
}

# Upstream passes -Zbuild-std on every build. Homebrew's rust formula
# installs the library sources and bun 1.4.3 compiles `core` that way;
# MacPorts ships those sources in the rust-src subport. RUSTC_BOOTSTRAP=1
# unlocks -Zbuild-std on stable rustc. Rust 1.99 removed type_info::of;
# Homebrew's 1.4.3 build fails on those calls, and patch-type-info-of.diff
# restores the helper. patch-clang-23.diff is the clang 23 / Apple SDK
# fix from Homebrew's formula. Release builds pass --lto=off so the
# non-LTO WebKit prebuild is the one checksummed above. Without
# --osx-deployment-target, bun uses the SDK major as the minimum OS.
patchfiles          patch-cargo-warnings.diff \
                    patch-clang-23.diff \
                    patch-type-info-of.diff

# Vendor C libraries (boringssl, zstd, …), cargo crates and node_modules
# (esbuild) are still fetched during the bun install / ninja / cargo steps.
# The top-level tarballs above are the ones MacPorts checksums.
#
# use_configure no: compiler.whitelist does not apply. CC/CXX below are
# the clang-mp wrappers so the SDK is visible (raw clang-${llvm_version}
# from libexec does not).

use_configure       no

set llvm_bindir     ${prefix}/libexec/llvm-${llvm_version}/bin
set bun_cache_dir   ${workpath}/bun-cache

post-extract {
    system -W ${workpath} "/usr/bin/unzip -q [shellescape ${distpath}/${bootstrap_distfile}]"

    set webkit_dest ${bun_cache_dir}/${webkit_cache_key}
    xinstall -d ${bun_cache_dir}
    system -W ${workpath} "/usr/bin/tar -xzf [shellescape ${distpath}/${webkit_distfile}]"
    file rename ${workpath}/bun-webkit ${webkit_dest}
    set fd [open ${webkit_dest}/.identity w]
    puts ${fd} ${webkit_version}
    close ${fd}
    # Prebuilt WebKit ships ICU headers that conflict with macOS ICU.
    if {[file isdirectory ${webkit_dest}/include/unicode]} {
        file delete -force ${webkit_dest}/include/unicode
    }
}

build {
    set extra {}
    if {${configure.build_arch} eq "x86_64"} {
        lappend extra --baseline=on
    }
    system -W ${worksrcpath} \
        "env PATH=[shellescape ${workpath}/${bootstrap_dir}:${llvm_bindir}:${prefix}/bin:/usr/bin:/bin] \
        GIT_SHA=[shellescape ${git_sha}] \
        RUSTC_BOOTSTRAP=1 \
        CARGO_HOME=[shellescape ${workpath}/.cargo] \
        CI= \
        SDKROOT=[shellescape ${configure.sdkroot}] \
        MACOSX_DEPLOYMENT_TARGET=[shellescape ${macosx_deployment_target}] \
        CC=[shellescape ${prefix}/bin/clang-mp-${llvm_version}] \
        CXX=[shellescape ${prefix}/bin/clang++-mp-${llvm_version}] \
        AR=[shellescape ${llvm_bindir}/llvm-ar] \
        RANLIB=[shellescape ${llvm_bindir}/llvm-ranlib] \
        [shellescape ${workpath}/${bootstrap_dir}/bun] run build:release --canary=off --lto=off \
        --osx-deployment-target=[shellescape ${macosx_deployment_target}] \
        --cache-dir=[shellescape ${bun_cache_dir}] ${extra}"
}

destroot {
    xinstall -m 0755 ${worksrcpath}/build/release/bun \
        ${destroot}${prefix}/bin/bun
    ln -s bun ${destroot}${prefix}/bin/bunx

    set completions ${worksrcpath}/completions
    if {[file exists ${completions}/bun.bash]} {
        xinstall -d ${destroot}${prefix}/share/bash-completion/completions
        xinstall -m 0644 ${completions}/bun.bash \
            ${destroot}${prefix}/share/bash-completion/completions/bun
    }
    if {[file exists ${completions}/bun.zsh]} {
        xinstall -d ${destroot}${prefix}/share/zsh/site-functions
        xinstall -m 0644 ${completions}/bun.zsh \
            ${destroot}${prefix}/share/zsh/site-functions/_bun
    }
    if {[file exists ${completions}/bun.fish]} {
        xinstall -d ${destroot}${prefix}/share/fish/vendor_completions.d
        xinstall -m 0644 ${completions}/bun.fish \
            ${destroot}${prefix}/share/fish/vendor_completions.d/bun.fish
    }
}

test.run            yes
test.cmd            ${worksrcpath}/build/release/bun
test.target         {}
test.args           --version
