# -*- 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.4 bun-v
github.tarball_from archive
revision            0

set git_sha         38afee6c84fcf48c0edb2466aa4b27d287a59c30
set bootstrap_version \
                    1.4.2
set webkit_version  d6375c72affe0f70222cdcb45012b10f0bf3a9d5
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
# macOS 13 (darwin 22) and later.
platforms           {darwin >= 22}

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  c440e5eacfd143b8d854561d29bdfd6c9388e80a \
                    sha256  00ce37fa5ac393a7d225bcf847365982fceb818b56a19b6884fefd67918468ff \
                    size    92967768

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  d4127be98d16dc8f83e2fa5b36fe06d84d989a4e \
                        sha256  e5cbd2720ed2019384ce0a091c9e07c384fc4f70762033b5af7a320560162ded \
                        size    211274104
} 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  1e2fabdbc892ec44f9b10a89c2fcd97c94cef30e \
                        sha256  84e316da854bf533bb88f671e66a34bf20f9af52021e00a700c5eca0615ef292 \
                        size    221505222
} 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-once-default.diff \
                    patch-type-info-of.diff

# Ventura's Xcode 14 ld parses -Wl,-ld_new as -l d_new. Xcode 15 already
# defaults to the new linker, including on macOS 13.5+, so the selector
# is omitted on darwin 22.
platform darwin 22 {
    patchfiles-append patch-ventura-no-ld-new.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
