From 4403c40755808cea508d92985d54b9ccf64dc086 Mon Sep 17 00:00:00 2001 From: dave caruso Date: Thu, 2 Nov 2023 22:40:00 -0700 Subject: [PATCH] chore: build and publish canary windows builds (#6834) Co-authored-by: Jarred Sumner --- .gitattributes | 30 +- .github/workflows/bun-mac-x64-baseline.yml | 12 +- .github/workflows/bun-mac-x64.yml | 12 +- .github/workflows/bun-windows-x64.yml | 351 ++- .gitignore | 3 + .vscode/tasks.json | 29 +- CMakeLists.txt | 2405 ++++++++++---------- Dockerfile | 15 +- Makefile | 28 +- build.zig | 19 +- bun.lockb | Bin 72151 -> 72172 bytes docs/installation.md | 2 +- docs/project/building-windows.md | 18 +- packages/bun-usockets/src/eventing/libuv.c | 2 +- scripts/all-dependencies.sh | 1 + scripts/build-libarchive.ps1 | 2 +- scripts/build-libuv.ps1 | 26 +- scripts/calculate-canary-revision.sh | 35 + scripts/clean-dependencies.sh | 1 + scripts/cross-compile-codegen.sh | 30 +- scripts/download-webkit.ps1 | 2 +- scripts/download-webkit.sh | 17 +- scripts/env.ps1 | 2 +- scripts/env.sh | 1 + scripts/make-old-js.ps1 | 35 + scripts/setup-zig.ps1 | 7 + scripts/update-submodules.ps1 | 16 + scripts/update-submodules.sh | 4 +- src/__global.zig | 39 +- src/bun.ico | Bin 0 -> 270622 bytes src/bun.js/WebKit | 2 +- src/bun.js/api/bun/socket.zig | 2 +- src/bun.js/api/bun/subprocess.zig | 2 +- src/bun.js/bindings/BunProcess.cpp | 6 +- src/bun.js/bindings/ZigGlobalObject.cpp | 7 - src/bun.js/bindings/root.h | 5 +- src/bun.js/node/syscall.zig | 1337 ----------- src/bun.js/node/types.zig | 11 +- src/bun.zig | 17 +- src/cli.zig | 2 +- src/cli/README-for-init.md | 2 +- src/cli/install.ps1 | 117 + src/cli/run_command.zig | 32 +- src/cli/upgrade_command.zig | 95 +- src/codegen/bundle-functions.ts | 1 - src/deps/zlib | 2 +- src/env.zig | 14 + src/env_loader.zig | 7 +- src/fs.zig | 23 +- src/install/install.zig | 21 +- src/resolver/resolver.zig | 2 +- src/string_immutable.zig | 4 + src/sys.zig | 37 +- src/which.zig | 13 +- src/windows-app-info.rc | 29 + src/windows.zig | 2 + test/cli/bun.test.ts | 6 +- test/cli/init/init.test.ts | 37 + 58 files changed, 2099 insertions(+), 2880 deletions(-) create mode 100755 scripts/calculate-canary-revision.sh create mode 100644 scripts/make-old-js.ps1 create mode 100644 scripts/setup-zig.ps1 create mode 100755 scripts/update-submodules.ps1 create mode 100644 src/bun.ico delete mode 100644 src/bun.js/node/syscall.zig create mode 100644 src/cli/install.ps1 create mode 100644 src/windows-app-info.rc create mode 100644 test/cli/init/init.test.ts diff --git a/.gitattributes b/.gitattributes index 57b4c5b300..1de733f4ad 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,39 +17,23 @@ *.mjs text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 *.mts text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 +*.lockb binary diff=lockb + .vscode/launch.json linguist-generated src/api/schema.d.ts linguist-generated fixture.*.c linguist-generated src/api/schema.js linguist-generated -src/bun.js/bindings/sqlite/sqlite3.c linguist-vendored -src/bun.js/bindings/sqlite/sqlite3_local.h linguist-vendored -*.lockb binary diff=lockb -src/bun.js/bindings/simdutf.cpp linguist-vendored -src/bun.js/bindings/simdutf.h linguist-vendored - *-fixture* linguist-generated - -src/js/out/WebCoreJSBuiltins.cpp linguist-generated -src/js/out/WebCoreJSBuiltins.h linguist-generated -src/js/out/WebCoreJSBuiltins.d.ts linguist-generated - -src/bun.js/bindings/ZigGeneratedClasses.h linguist-generated -src/bun.js/bindings/ZigGeneratedClasses.cpp linguist-generated - src/bun.js/bindings/ZigGeneratedCode.h linguist-generated src/bun.js/bindings/ZigGeneratedCode.cpp linguist-generated - src/bun.js/bindings/headers.h linguist-generated src/bun.js/bindings/headers.zig linguist-generated -src/bun.js/bindings/JSSink.h linguist-generated -src/bun.js/bindings/JSSink.zig linguist-generated +packages/bun-uws/fuzzing/seed-corpus/**/* linguist-generated -src/bun.js/bindings/ZigGeneratedClasses+DOMClientIsoSubspaces.h linguist-generated -src/bun.js/bindings/ZigGeneratedClasses+DOMIsoSubspaces.h linguist-generated -src/bun.js/bindings/ZigGeneratedClasses+lazyStructureHeader.h linguist-generated -src/bun.js/bindings/ZigGeneratedClasses+lazyStructureImpl.h linguist-generated +src/bun.js/bindings/sqlite/sqlite3.c linguist-vendored +src/bun.js/bindings/sqlite/sqlite3_local.h linguist-vendored +src/bun.js/bindings/simdutf.cpp linguist-vendored +src/bun.js/bindings/simdutf.h linguist-vendored docs/**/* linguist-documentation - -packages/bun-uws/fuzzing/seed-corpus/**/* linguist-generated diff --git a/.github/workflows/bun-mac-x64-baseline.yml b/.github/workflows/bun-mac-x64-baseline.yml index 479521811b..5cc585b22e 100644 --- a/.github/workflows/bun-mac-x64-baseline.yml +++ b/.github/workflows/bun-mac-x64-baseline.yml @@ -203,10 +203,10 @@ jobs: echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH brew link --overwrite llvm@$LLVM_VERSION - curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64.zip" - unzip bun-darwin-x64.zip + curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64-baseline.zip" + unzip bun-darwin-x64-baseline.zip mkdir -p ${{ runner.temp }}/.bun/bin - mv bun-darwin-x64/bun ${{ runner.temp }}/.bun/bin/bun + mv bun-darwin-x64-baseline/bun ${{ runner.temp }}/.bun/bin/bun chmod +x ${{ runner.temp }}/.bun/bin/bun echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH @@ -274,10 +274,10 @@ jobs: echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH brew link --overwrite llvm@$LLVM_VERSION - curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64.zip" - unzip bun-darwin-x64.zip + curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64-baseline.zip" + unzip bun-darwin-x64-baseline.zip mkdir -p ${{ runner.temp }}/.bun/bin - mv bun-darwin-x64/bun ${{ runner.temp }}/.bun/bin/bun + mv bun-darwin-x64-baseline/bun ${{ runner.temp }}/.bun/bin/bun chmod +x ${{ runner.temp }}/.bun/bin/bun echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH diff --git a/.github/workflows/bun-mac-x64.yml b/.github/workflows/bun-mac-x64.yml index 57f3d17816..d262e52cb9 100644 --- a/.github/workflows/bun-mac-x64.yml +++ b/.github/workflows/bun-mac-x64.yml @@ -201,10 +201,10 @@ jobs: echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH brew link --overwrite llvm@$LLVM_VERSION - curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64.zip" - unzip bun-darwin-x64.zip + curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64-baseline.zip" + unzip bun-darwin-x64-baseline.zip mkdir -p ${{ runner.temp }}/.bun/bin - mv bun-darwin-x64/bun ${{ runner.temp }}/.bun/bin/bun + mv bun-darwin-x64-baseline/bun ${{ runner.temp }}/.bun/bin/bun chmod +x ${{ runner.temp }}/.bun/bin/bun echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH @@ -273,10 +273,10 @@ jobs: echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH brew link --overwrite llvm@$LLVM_VERSION - curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64.zip" - unzip bun-darwin-x64.zip + curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-x64-baseline.zip" + unzip bun-darwin-x64-baseline.zip mkdir -p ${{ runner.temp }}/.bun/bin - mv bun-darwin-x64/bun ${{ runner.temp }}/.bun/bin/bun + mv bun-darwin-x64-baseline/bun ${{ runner.temp }}/.bun/bin/bun chmod +x ${{ runner.temp }}/.bun/bin/bun echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH diff --git a/.github/workflows/bun-windows-x64.yml b/.github/workflows/bun-windows-x64.yml index 9eb6d73a5b..8cfbf4d6a1 100644 --- a/.github/workflows/bun-windows-x64.yml +++ b/.github/workflows/bun-windows-x64.yml @@ -1,159 +1,274 @@ -# TODO(@paperdave) -# this workflow is a work in progress name: bun-windows-x64 concurrency: group: bun-windows-x64-${{ github.ref }} cancel-in-progress: true +env: + # note: in other files, this version is only the major version, but for windows it is the full version + LLVM_VERSION: 16.0.6 + BUN_DOWNLOAD_URL_BASE: https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/latest + + cpu: native + arch: x86_64 + tag: bun-windows-x64 + on: - # push: - # branches: [main] - # paths: - # - "src/**/*" - # - "test/**/*" - # - "packages/bun-usockets/src/**/*" - # - "build.zig" - # - "Makefile" - # - "Dockerfile" - # pull_request: - # branches: [main] - # paths: - # - "src/**/*" - # - "test/**/*" - # - "packages/bun-usockets/src/**/*" - # - "build.zig" - # - "Makefile" - # - "Dockerfile" + push: + branches: [main] + paths: + - "src/**/*" + - "test/**/*" + - "packages/bun-usockets/src/**/*" + - "build.zig" + - "Makefile" + - "Dockerfile" + pull_request: + branches: [main] + paths: + - "src/**/*" + - "test/**/*" + - "packages/bun-usockets/src/**/*" + - "build.zig" + - "Makefile" + - "Dockerfile" # Allows you to run this workflow manually from the Actions tab workflow_dispatch: jobs: - # windows-zig: - # name: Windows Zig Object - # runs-on: med-ubuntu - # if: github.repository_owner == 'oven-sh' - # strategy: - # matrix: - # include: - # - cpu: native - # arch: x86_64 - # tag: bun-windows-x64 - # steps: - # - uses: actions/checkout@v4 - # - name: Setup Docker Buildx - # uses: docker/setup-buildx-action@v2 - # id: buildx - # with: - # install: true + windows-zig: + name: Zig Build + runs-on: med-ubuntu + if: github.repository_owner == 'oven-sh' + steps: + - uses: actions/checkout@v4 + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v2 + id: buildx + with: + install: true - # - name: Login to GitHub Container Registry - # uses: docker/login-action@v2 - # with: - # registry: ghcr.io - # username: ${{ github.actor }} - # password: ${{ secrets.GITHUB_TOKEN }} + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - # - name: Compile Zig Object - # uses: docker/build-push-action@v3 - # if: runner.arch == 'X64' - # with: - # context: . - # push: false - # # This doesnt seem to work - # # cache-from: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto - # # cache-to: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto - # build-args: | - # BUILDARCH=${{ runner.arch == 'X64' && 'amd64' || 'arm64' }} - # BUILD_MACHINE_ARCH=${{ runner.arch == 'X64' && 'x86_64' || 'aarch64' }} - # ARCH=${{ matrix.arch }} - # CPU_TARGET=${{ matrix.cpu }} - # TRIPLET=${{ matrix.arch }}-windows-msvc - # GIT_SHA=${{ github.sha }} - # platforms: linux/${{ runner.arch == 'X64' && 'amd64' || 'arm64' }} - # target: build_release_obj - # outputs: type=local,dest=${{runner.temp}}/release + # this calculation only needs to be done for the Zig code + - name: Calculate Canary Revision + id: canary + run: | + echo "canary_revision=$(GITHUB_TOKEN="${{ secrets.GITHUB_TOKEN }}" bash ./scripts/calculate-canary-revision.sh --raw)" >> $GITHUB_OUTPUT - # - name: Upload Zig Object - # uses: actions/upload-artifact@v3 - # with: - # name: ${{ matrix.tag }}-zig - # path: ${{runner.temp}}/release/bun-zig.o + - name: Compile Zig Object + uses: docker/build-push-action@v3 + if: runner.arch == 'X64' + with: + context: . + push: false + # This doesnt seem to work + # cache-from: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto + # cache-to: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto + build-args: | + BUILDARCH=${{ runner.arch == 'X64' && 'amd64' || 'arm64' }} + BUILD_MACHINE_ARCH=${{ runner.arch == 'X64' && 'x86_64' || 'aarch64' }} + ARCH=${{ env.arch }} + CPU_TARGET=${{ env.cpu }} + TRIPLET=${{ env.arch }}-windows-msvc + GIT_SHA=${{ github.sha }} + CANARY=${{ steps.canary.outputs.canary_revision }} + platforms: linux/${{ runner.arch == 'X64' && 'amd64' || 'arm64' }} + target: build_release_obj + outputs: type=local,dest=${{runner.temp}}/release - # windows-dependencies: - # strategy: - # matrix: - # include: - # - runner: windows-latest - # arch: amd64 - # tag: bun-windows-x64 - # runs-on: windows-latest - # timeout-minutes: 90 - # steps: - # - uses: actions/checkout@v4 - # - uses: ilammy/msvc-dev-cmd@7315a94840631165970262a99c72cfb48a65d25d - # with: - # arch: ${{ matrix.arch }} - # - uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e - # with: - # version: 16.0.6 - # - run: choco install -y ninja - # - name: Build Dependencies - # run: | - # git submodule update --init --recursive --progress --depth=1 --checkout - # Invoke-WebRequest -Uri "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip" -OutFile nasm.zip - # Expand-Archive nasm.zip (mkdir -Force "nasm") - # $Nasm = (Get-ChildItem "nasm") - # $env:Path += ";${Nasm}" - # $env:BUN_DEPS_OUT_DIR = (mkdir -Force "./bun-deps") - # ./scripts/all-dependencies.ps1 - # - uses: actions/upload-artifact@v3 - # with: - # name: bun-deps/ - # path: bun-windows-x64-deps + - name: Upload Zig Object + uses: actions/upload-artifact@v3 + with: + name: ${{ env.tag }}-zig + path: ${{runner.temp}}/release/bun-zig.o + + windows-dependencies: + name: Dependencies + runs-on: windows-latest + timeout-minutes: 90 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Clone Submodules + run: .\scripts\update-submodules.ps1 + - name: Hash submodule versions + shell: pwsh + run: | + $data = "$(& { + git submodule | Where-Object { $_ -notmatch 'WebKit' } + clang --version + rustc --version + Get-Content -Path (Get-ChildItem -Path 'scripts/build*.sh', 'scripts/all-dependencies.sh' | Sort-Object -Property Name).FullName | Out-String + })" + $hash = ( -join ((New-Object -TypeName System.Security.Cryptography.SHA1CryptoServiceProvider).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($data)) | ForEach-Object { $_.ToString("x2") } )).Substring(0, 10) + echo "sha=${hash}" >> $env:GITHUB_OUTPUT + id: submodule-versions + + - name: Try fetch dependencies + id: cache-deps-restore + uses: actions/cache/restore@v3 + with: + path: bun-deps + key: bun-deps-${{ env.tag }}-${{ steps.submodule-versions.outputs.sha }} + + - name: Install LLVM ${{ env.LLVM_VERSION }} + if: ${{ !steps.cache-deps-restore.outputs.cache-hit }} + uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e + with: + version: ${{ env.LLVM_VERSION }} + + - name: Install Ninja + if: ${{ !steps.cache-deps-restore.outputs.cache-hit }} + run: choco install -y ninja + + - name: Build Dependencies + if: ${{ !steps.cache-deps-restore.outputs.cache-hit }} + run: | + .\scripts\env.ps1 + Invoke-WebRequest -Uri "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip" -OutFile nasm.zip + Expand-Archive nasm.zip (mkdir -Force "nasm") + $Nasm = (Get-ChildItem "nasm") + $env:Path += ";${Nasm}" + $env:BUN_DEPS_OUT_DIR = (mkdir -Force "./bun-deps") + .\scripts\all-dependencies.ps1 + + - name: Upload Dependencies + uses: actions/upload-artifact@v3 + with: + name: ${{ env.tag }}-deps + path: bun-deps/ + + - name: Cache Dependencies + if: ${{ !steps.cache-deps-restore.outputs.cache-hit }} + id: cache-deps-save + uses: actions/cache/save@v3 + with: + path: bun-deps + key: ${{ steps.cache-deps-restore.outputs.cache-primary-key }} windows-codegen: + name: Codegen runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: | - curl -fsSL ${{ secrets.BUN_DOWNLOAD_URL_BASE }}/bun-linux-x64.zip > bun.zip + curl -fsSL $BUN_DOWNLOAD_URL_BASE/bun-linux-x64.zip > bun.zip unzip bun.zip export PATH="$PWD/bun-linux-x64:$PATH" ./scripts/cross-compile-codegen.sh win32 x64 - uses: actions/upload-artifact@v3 with: - name: bun-windows-x64-codegen + name: ${{ env.tag }}-codegen path: build-codegen-win32-x64/ - windows-dependencies: - strategy: - matrix: - include: - - runner: windows-latest - arch: amd64 - tag: bun-windows-x64 + windows-cpp: + name: C++ Build + needs: [windows-codegen] runs-on: windows-latest timeout-minutes: 90 steps: - uses: actions/checkout@v4 - - uses: ilammy/msvc-dev-cmd@7315a94840631165970262a99c72cfb48a65d25d - with: - arch: ${{ matrix.arch }} - uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e with: - version: 16.0.6 + version: ${{ env.LLVM_VERSION }} - run: choco install -y ninja - - uses: actions/download-artifact@v2 + - name: Download Codegen + uses: actions/download-artifact@v3 with: - name: bun-windows-x64-codegen + name: ${{ env.tag }}-codegen path: build - - name: Build Dependencies + - name: Build C++ run: | - git submodule update --init --recursive --progress --depth=1 --checkout + # Using SCCache is blocked by + # https://github.com/mozilla/sccache/issues/1843 + # https://github.com/mozilla/sccache/pull/1856 + # $sczip = "sccache-v0.6.0-x86_64-pc-windows-msvc" + + # Invoke-WebRequest -Uri "https://github.com/mozilla/sccache/releases/download/v0.6.0/${sczip}.zip" -OutFile "${sczip}.zip" + # Expand-Archive "${sczip}.zip" + # $env:SCCACHE_BUCKET="bun" + # $env:SCCACHE_REGION="auto" + # $env:SCCACHE_S3_USE_SSL="true" + # $env:SCCACHE_ENDPOINT="${{ secrets.CACHE_S3_ENDPOINT }}" + # $env:AWS_ACCESS_KEY_ID="${{ secrets.CACHE_S3_ACCESS_KEY_ID }}" + # $env:AWS_SECRET_ACCESS_KEY="${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }}" + # $SCCACHE="$PWD/${sczip}/${sczip}/sccache.exe" + + .\scripts\env.ps1 + .\scripts\update-submodules.ps1 + .\scripts\build-libuv.ps1 -CloneOnly $True cd build - cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DNO_CODEGEN=1 -DNO_CONFIGURE_DEPENDS=1 + # "-DCCACHE_PROGRAM=${SCCACHE}" + cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DNO_CODEGEN=1 -DNO_CONFIGURE_DEPENDS=1 -DCANARY=1 -DBUN_CPP_ONLY=1 + if ($LASTEXITCODE -ne 0) { throw "CMake configuration failed" } + .\compile-cpp-only.ps1 -v + if ($LASTEXITCODE -ne 0) { throw "C++ compilation failed" } - uses: actions/upload-artifact@v3 with: - name: bun-deps/ - path: bun-windows-x64-deps + name: ${{ env.tag }}-cpp + path: build/bun-cpp-objects.a + + windows-link: + name: Link + needs: [windows-dependencies, windows-codegen, windows-cpp, windows-zig] + runs-on: windows-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v4 + - uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e + with: + version: ${{ env.LLVM_VERSION }} + - run: choco install -y ninja + - name: Download Codegen + uses: actions/download-artifact@v3 + with: + name: ${{ env.tag }}-codegen + path: build + - name: Download Dependencies + uses: actions/download-artifact@v3 + with: + name: ${{ env.tag }}-deps + path: bun-deps + - name: Download Zig Object + uses: actions/download-artifact@v3 + with: + name: ${{ env.tag }}-zig + path: bun-zig + - name: Download C++ Objects + uses: actions/download-artifact@v3 + with: + name: ${{ env.tag }}-cpp + path: bun-cpp + - name: Link + run: | + .\scripts\update-submodules.ps1 + .\scripts\env.ps1 + Set-Location build + cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release ` + -DNO_CODEGEN=1 ` + -DNO_CONFIGURE_DEPENDS=1 ` + -DCANARY=1 ` + -DBUN_LINK_ONLY=1 ` + "-DBUN_DEPS_OUT_DIR=$(Resolve-Path ../bun-deps)" ` + "-DBUN_CPP_ARCHIVE=$(Resolve-Path ../bun-cpp/bun-cpp-objects.a)" ` + "-DBUN_ZIG_OBJ=$(Resolve-Path ../bun-zig/bun-zig.o)" + if ($LASTEXITCODE -ne 0) { throw "CMake configuration failed" } + ninja -v + if ($LASTEXITCODE -ne 0) { throw "Link failed!" } + + # TODO: code sign? + - name: Package + run: | + $Dist = mkdir -Force "${{ env.tag }}" + cp -r build\bun.exe "$Dist\bun.exe" + Compress-Archive $Dist ${{ env.tag }}.zip + - uses: actions/upload-artifact@v3 + with: + name: ${{ env.tag }} + path: ${{ env.tag }}.zip diff --git a/.gitignore b/.gitignore index a2052aec81..8afca8fd22 100644 --- a/.gitignore +++ b/.gitignore @@ -154,5 +154,8 @@ x64 **/*.pdb /.webkit-cache +/.cache /src/deps/libuv /build-*/ + +.vs \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index bf08fb4360..ae67585340 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,33 +2,10 @@ "version": "2.0.0", "tasks": [ { - "label": "build", + "label": "Rebuild Debug", + "command": "ninja", + "args": ["-Cbuild"], "type": "process", - "command": "zig", - "args": ["build"], - "presentation": { - "echo": true, - "reveal": "silent", - "focus": false, - "panel": "shared", - "showReuseMessage": false, - "clear": false - }, - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "run", - "type": "process", - "command": "zig", - "args": ["run", "${file}"], - "group": "build", - "presentation": { - "showReuseMessage": false, - "clear": true - } } ] } diff --git a/CMakeLists.txt b/CMakeLists.txt index 3281ad6bf4..dc7094c597 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1189 +1,1216 @@ -cmake_minimum_required(VERSION 3.22) - -cmake_policy(SET CMP0091 NEW) -cmake_policy(SET CMP0067 NEW) - -set(Bun_VERSION "1.0.8") -set(WEBKIT_TAG 46689737b98c78e48d9eb6885f0b3e8365d79310) - -set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}") -message(STATUS "Configuring Bun ${Bun_VERSION} in ${BUN_WORKDIR}") - -# --- Build Type --- -# This is done at the start simply so this is the first message printed -if(NOT CMAKE_BUILD_TYPE) - message(WARNING "No CMAKE_BUILD_TYPE value specified, defaulting to Debug.\nSet a build type with -DCMAKE_BUILD_TYPE=") - set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build (Debug, Release)" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release)$") - message(FATAL_ERROR - "Invalid CMAKE_BUILD_TYPE value specified: ${CMAKE_BUILD_TYPE}\n" - "CMAKE_BUILD_TYPE must be Debug or Release.") - endif() - - message(STATUS "The CMake build type is: ${CMAKE_BUILD_TYPE}") -endif() - -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(DEBUG ON) - set(ZIG_OPTIMIZE "Debug") - set(bun "bun-debug") -elseif(CMAKE_BUILD_TYPE STREQUAL "Release") - set(DEBUG OFF) - set(ZIG_OPTIMIZE "ReleaseFast") - set(bun "bun-profile") -endif() - -# --- LLVM --- -# This detection is a little overkill, but it ensures that the set LLVM_VERSION matches under -# any case possible. Sorry for the complexity... -# -# Bun and WebKit must be compiled with the same compiler, so we do as much as we can to ensure that -# the compiler used for the prebuilt WebKit, LLVM 16, is the one that we detect in this process. -# -# It has to be done before project() is called, so that CMake doesnt pick a compiler for us, but even then -# we do some extra work afterwards to double-check, and we will rerun BUN_FIND_LLVM if the compiler did not match. -# -# If the user passes -DLLVM_PREFIX, most of this logic is skipped, but we still warn if invalid. -set(LLVM_VERSION 16) - -macro(BUN_FIND_LLVM) - find_program( - _LLVM_CXX_PATH - NAMES clang++-${LLVM_VERSION} clang++ - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s clang++ binary. Please pass -DLLVM_PREFIX with the path to LLVM" - ) - - if(NOT _LLVM_CXX_PATH) - message(FATAL_ERROR "Could not find LLVM ${LLVM_VERSION}, search paths: ${PLATFORM_LLVM_SEARCH_PATHS}") - endif() - - set(CMAKE_CXX_COMPILER "${_LLVM_CXX_PATH}") - find_program( - _LLVM_C_PATH - NAMES clang-${LLVM_VERSION} clang - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s clang binary. Please pass -DLLVM_PREFIX with the path to LLVM" - ) - - if(NOT _LLVM_C_PATH) - message(FATAL_ERROR "Could not find LLVM ${LLVM_VERSION}, search paths: ${PLATFORM_LLVM_SEARCH_PATHS}") - endif() - - set(CMAKE_C_COMPILER "${_LLVM_C_PATH}") - - find_program( - STRIP - NAMES llvm-strip - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" - ) - find_program( - STRIP - NAMES strip - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" - ) - find_program( - DSYMUTIL - NAMES dsymutil - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s dsymutil binary" - ) - find_program( - AR - NAMES llvm-ar - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" - ) - find_program( - AR - NAMES ar - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" - ) - find_program( - RANLIB - NAMES llvm-ranlib - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" - ) - - execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE _tmp) - string(REGEX MATCH "version ([0-9]+)\\.([0-9]+)\\.([0-9]+)" CMAKE_CXX_COMPILER_VERSION "${_tmp}") - set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") -endmacro() - -if(UNIX) - if(LLVM_PREFIX) - set(PLATFORM_LLVM_SEARCH_PATHS ${LLVM_PREFIX}/bin) - else() - set(PLATFORM_LLVM_SEARCH_PATHS /usr/lib/llvm-${LLVM_VERSION}/bin /usr/lib/llvm${LLVM_VERSION}/bin /usr/bin /usr/local/bin) - - if(APPLE) - set(PLATFORM_LLVM_SEARCH_PATHS /opt/homebrew/opt/llvm@${LLVM_VERSION}/bin /opt/homebrew/bin ${PLATFORM_LLVM_SEARCH_PATHS}) - endif() - endif() - - if(CMAKE_CXX_COMPILER) - set(_LLVM_CXX_PATH "${CMAKE_CXX_COMPILER}") - endif() - - if(CMAKE_C_COMPILER) - set(_LLVM_C_PATH "${CMAKE_C_COMPILER}") - endif() - - BUN_FIND_LLVM() -else() - # Windows uses Clang-CL - # TODO: good configuration in this regard. -G Ninja will pick clang-cl if possible, which should be fine for most users. - find_program( - STRIP - NAMES llvm-strip - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" - ) - find_program( - AR - NAMES llvm-ar - PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} - DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" - ) -endif() - -set(CMAKE_COLOR_DIAGNOSTICS ON) -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_C_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_C_STANDARD_REQUIRED ON) - -project(Bun VERSION "${Bun_VERSION}") - -# More effort to prevent using the wrong C++ compiler -if(UNIX) - if((NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR(NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${LLVM_VERSION}\.")) - # Attempt to auto-correct the compiler - message(STATUS "Compiler mismatch, attempting to auto-correct") - unset(_LLVM_CXX_PATH) - BUN_FIND_LLVM() - - if((NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR(NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${LLVM_VERSION}\.")) - message(WARNING "Expected LLVM ${LLVM_VERSION} as the C++ compiler, build may fail or break at runtime.") - endif() - endif() -endif() - -message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} at ${CMAKE_CXX_COMPILER}") - -# --- End LLVM --- -set(SHELL "bash") -set(SCRIPT_EXTENSION "sh") - -if(WIN32) - set(SCRIPT_EXTENSION "ps1") -endif() - -set(DEFAULT_ON_UNLESS_APPLE ON) - -set(DEFAULT_USE_STATIC_LIBATOMIC ON) -if(UNIX AND NOT APPLE) - execute_process(COMMAND cat /etc/os-release COMMAND head -n1 OUTPUT_VARIABLE LINUX_DISTRO) - if(${LINUX_DISTRO} STREQUAL "NAME=\"Arch Linux\"\n") - set(DEFAULT_USE_STATIC_LIBATOMIC OFF) - endif() -endif() -if(APPLE) - set(DEFAULT_ON_UNLESS_APPLE OFF) -endif() - -set(CI OFF) - -if(DEFINED ENV{CI} OR DEFINED ENV{GITHUB_ACTIONS}) - set(CI ON) -endif() - -# -- Build Flags -- -option(USE_STATIC_SQLITE "Statically link SQLite?" ${DEFAULT_ON_UNLESS_APPLE}) -option(USE_CUSTOM_ZLIB "Use Bun's recommended version of zlib" ON) -option(USE_CUSTOM_BORINGSSL "Use Bun's recommended version of BoringSSL" ON) -option(USE_CUSTOM_LIBARCHIVE "Use Bun's recommended version of libarchive" ON) -option(USE_CUSTOM_MIMALLOC "Use Bun's recommended version of Mimalloc" ON) -option(USE_CUSTOM_ZSTD "Use Bun's recommended version of zstd" ON) -option(USE_CUSTOM_CARES "Use Bun's recommended version of c-ares" ON) -option(USE_CUSTOM_BASE64 "Use Bun's recommended version of libbase64" ON) -option(USE_CUSTOM_LOLHTML "Use Bun's recommended version of lolhtml" ON) -option(USE_CUSTOM_TINYCC "Use Bun's recommended version of tinycc" ON) -option(USE_CUSTOM_LIBUV "Use Bun's recommended version of libuv (Windows only)" ON) -option(USE_BASELINE_BUILD "Build Bun for baseline (older) CPUs" OFF) - -option(USE_DEBUG_JSC "Enable assertions and use a debug build of JavaScriptCore" OFF) -option(USE_UNIFIED_SOURCES "Use unified sources to speed up the build" OFF) - -option(CANARY "Make `bun --revision` report a canary release" OFF) -option(USE_STATIC_LIBATOMIC "statically link libatomic, requires the presence of libatomic.a" ${DEFAULT_USE_STATIC_LIBATOMIC}) -set(ERROR_LIMIT 100 CACHE STRING "Maximum number of errors to show when compiling C++ code") - -set(ARCH x86_64) - -if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|arm") - set(ARCH aarch64) -endif() - -if(NOT CPU_TARGET) - if(ENV{CPU_TARGET}) - set(CPU_TARGET $ENV{CPU_TARGET}) - else() - set(CPU_TARGET "native" CACHE STRING "CPU target for the compiler" FORCE) - - if(ARCH STREQUAL "x86_64") - if(NOT MSVC) - if(USE_BASELINE_BUILD) - set(CPU_TARGET "nehalem") - else() - set(CPU_TARGET "haswell") - endif() - endif() - endif() - endif() -endif() - -message(STATUS "Building for CPU Target: ${CPU_TARGET}") - -if(NOT ZIG_TARGET) - set(ZIG_TARGET "native") - - if(WIN32) - set(ZIG_TARGET "${ARCH}-windows-msvc") - endif() -endif() - -set(CONFIGURE_DEPENDS "CONFIGURE_DEPENDS") - -if(NO_CONFIGURE_DEPENDS) - set(CONFIGURE_DEPENDS "") -endif() - -# --- CLI Paths --- -set(REQUIRED_IF_NOT_ONLY_CPP_OR_LINK "") - -if(NOT BUN_CPP_ONLY AND NOT BUN_LINK_ONLY) - set(REQUIRED_IF_NOT_ONLY_CPP_OR_LINK "REQUIRED") -endif() - -# Zig Compiler -function(validate_zig validator_result_var item) - set(${validator_result_var} FALSE PARENT_SCOPE) - - # We will allow any valid zig compiler, as long as it contains some text from `zig zen` - # Ideally we would do a version or feature check, but that would be quite slow - execute_process(COMMAND ${item} zen OUTPUT_VARIABLE ZIG_ZEN_OUTPUT) - - if(ZIG_ZEN_OUTPUT MATCHES "Together we serve the users") - set(${validator_result_var} TRUE PARENT_SCOPE) - else() - set(${validator_result_var} FALSE PARENT_SCOPE) - endif() -endfunction() - -find_program(ZIG_COMPILER zig ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to the Zig compiler" VALIDATOR validate_zig) -message(STATUS "Found Zig Compiler: ${ZIG_COMPILER}") - -# Bun -if(NOT WIN32) - find_program(BUN_EXECUTABLE bun ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to an already built release of Bun") - message(STATUS "Found Bun: ${BUN_EXECUTABLE}") -else() - set(BUN_EXECUTABLE "echo") -endif() - -# Prettier -find_program(PRETTIER prettier DOC "Path to prettier" PATHS ./node_modules/.bin ENV PATH) - -# Esbuild (TODO: switch these to "bun build") -find_program(ESBUILD esbuild DOC "Path to esbuild" PATHS ./node_modules/.bin ENV PATH) - -# Ruby (only needed for unified sources) -if(USE_UNIFIED_SOURCES) - # ruby 'WebKit/Source/WTF/Scripts/generate-unified-source-bundles.rb' source_list.txt --source-tree-path . --derived-sources-path build/unified-sources - find_program(RUBY ruby DOC "Path to ruby") -endif() - -# CCache -find_program(CCACHE_PROGRAM ccache) - -if(CCACHE_PROGRAM) - set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") - set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") - message(STATUS "Using ccache: ${CCACHE_PROGRAM}") -endif() - -# --- WebKit --- -# WebKit is either prebuilt and distributed via NPM, or you can pass WEBKIT_DIR to use a local build. -# We cannot include their CMake build files (TODO: explain why, for now ask @paperdave why) -# -# On Unix, this will pull from NPM the single package that is needed and use that -if(WIN32) - set(STATIC_LIB_EXT "lib") - set(libJavaScriptCore "JavaScriptCore") - set(libWTF "WTF") -else() - set(STATIC_LIB_EXT "a") - set(libJavaScriptCore "libJavaScriptCore") - set(libWTF "libWTF") -endif() - -if(NOT WEBKIT_DIR) - set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "") - set(ASSERT_ENABLED "0") - - if(USE_DEBUG_JSC) - set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "-debug") - set(ASSERT_ENABLED "1") - elseif(NOT DEBUG AND NOT WIN32) - set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "-lto") - set(ASSERT_ENABLED "0") - endif() - - if(WIN32) - set(BUN_WEBKIT_PACKAGE_PLATFORM "windows") - elseif(APPLE) - set(BUN_WEBKIT_PACKAGE_PLATFORM "macos") - else() - set(BUN_WEBKIT_PACKAGE_PLATFORM "linux") - endif() - - if(ARCH STREQUAL "x86_64") - set(BUN_WEBKIT_PACKAGE_ARCH "amd64") - elseif(ARCH MATCHES "aarch64|arm64|arm") - set(BUN_WEBKIT_PACKAGE_ARCH "arm64") - endif() - - set(BUN_WEBKIT_PACKAGE_NAME "bun-webkit-${BUN_WEBKIT_PACKAGE_PLATFORM}-${BUN_WEBKIT_PACKAGE_ARCH}${BUN_WEBKIT_PACKAGE_NAME_SUFFIX}") - - message(STATUS "Using Pre-built WebKit: ${BUN_WEBKIT_PACKAGE_NAME}") - execute_process( - COMMAND "${SHELL}" - "${CMAKE_CURRENT_SOURCE_DIR}/scripts/download-webkit.${SCRIPT_EXTENSION}" - "${BUN_WORKDIR}/bun-webkit" - "${WEBKIT_TAG}" - "${BUN_WEBKIT_PACKAGE_NAME}" - WORKING_DIRECTORY ${BUN_WORKDIR} - ) - - if(NOT EXISTS "${BUN_WORKDIR}/bun-webkit") - message(FATAL_ERROR "Prebuilt WebKit package ${BUN_WEBKIT_PACKAGE_NAME} failed to install") - endif() - - set(WEBKIT_INCLUDE_DIR "${BUN_WORKDIR}/bun-webkit/include") - set(WEBKIT_LIB_DIR "${BUN_WORKDIR}/bun-webkit/lib") -elseif(WEBKIT_DIR STREQUAL "omit") - message(STATUS "Not using WebKit. This is only valid if you are only trying to build Zig code") -else() - # Setting WEBKIT_DIR means you either have a path to the WebKit repo, or you have a path to packaged webkit - # Non-packaged webkit has CMakeLists.txt - if(EXISTS "${WEBKIT_DIR}/CMakeLists.txt") - # Since we may be doing a Debug build of Bun but with a Release build of JSC, we can't - # include their CMakeLists directly here, but rather we need to run `cmake` as a dependency - # of our build. It'll still have decent caching which is what really matters. - - # cmake WEBKIT_DIR -B WEBKIT_DIR/WebKitBuild/WEBKIT_BUILD_TYPE - # -DPORT=JSCOnly - # -DENABLE_STATIC_JSC=ON - # -DENABLE_SINGLE_THREADED_VM_ENTRY_SCOPE=ON - # -DCMAKE_BUILD_TYPE=Debug - # -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON - # -DUSE_THIN_ARCHIVES=OFF - # -DENABLE_FTL_JIT=ON - # -DCMAKE_C_COMPILER=(which clang-16) - # -DDCMAKE_CXX_COMPILER=(which clang++-16) - # -DDUSE_BUN_JSC_ADDITIONS=1 - # -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" - # -DCMAKE_AR=$(which llvm-ar) - # -DCMAKE_RANLIB=$(which llvm-ranlib) - # -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON - # -G Ninja - # -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 - # -DPTHREAD_JIT_PERMISSIONS_API=1 - # -DUSE_PTHREAD_JIT_PERMISSIONS_API=ON - # -DENABLE_REMOTE_INSPECTOR=ON - message(FATAL_ERROR "TODO: Setting WEBKIT_DIR to the WebKit repository to enable automatic builds. For now you need to run the release script, and point to the packaged directory.") - else() - if(NOT EXISTS "${WEBKIT_DIR}/lib/${libWTF}.${STATIC_LIB_EXT}" OR NOT EXISTS "${WEBKIT_DIR}/lib/${libJavaScriptCore}.${STATIC_LIB_EXT}") - if(WEBKIT_DIR MATCHES "src/bun.js/WebKit$") - message(FATAL_ERROR "WebKit directory ${WEBKIT_DIR} does not contain all the required files for Bun. Did you forget to init submodules?") - endif() - - message(FATAL_ERROR "WebKit directory ${WEBKIT_DIR} does not contain all the required files for Bun. Expected a path to the oven-sh/WebKit repository, or a path to a folder containing `include` and `lib`.") - endif() - - set(WEBKIT_INCLUDE_DIR "${WEBKIT_DIR}/include") - set(WEBKIT_LIB_DIR "${WEBKIT_DIR}/lib") - - message(STATUS "Using specified WebKit directory: ${WEBKIT_DIR}") - - set(ASSERT_ENABLED "0") - message(STATUS "WebKit assertions: OFF") - endif() -endif() - -# --- CMake Macros --- - -# Append the given dependencies to the source file -macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps) - set(_tmp) - get_source_file_property(_tmp ${_source} OBJECT_DEPENDS) - - if(NOT _tmp) - set(_tmp "") - endif() - - foreach(f ${_deps}) - list(APPEND _tmp "${f}") - endforeach() - - set_source_files_properties(${_source} PROPERTIES OBJECT_DEPENDS "${_tmp}") - unset(_tmp) -endmacro() - -# --- BUILD --- -set(BUN_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src") -set(BUN_DEPS_DIR "${BUN_SRC}/deps") -set(BUN_CODEGEN_SRC "${BUN_SRC}/codegen") - -if(NOT BUN_DEPS_OUT_DIR) - set(BUN_DEPS_OUT_DIR "${BUN_DEPS_DIR}") -endif() - -set(BUN_RAW_SOURCES, "") - -file(GLOB BUN_CPP ${CONFIGURE_DEPENDS} - "${BUN_SRC}/deps/*.cpp" - "${BUN_SRC}/io/*.cpp" - "${BUN_SRC}/bun.js/modules/*.cpp" - "${BUN_SRC}/bun.js/bindings/*.cpp" - "${BUN_SRC}/bun.js/bindings/webcore/*.cpp" - "${BUN_SRC}/bun.js/bindings/sqlite/*.cpp" - "${BUN_SRC}/bun.js/bindings/webcrypto/*.cpp" - "${BUN_SRC}/bun.js/bindings/webcrypto/*/*.cpp" - "${BUN_SRC}/deps/picohttpparser/picohttpparser.c" -) -list(APPEND BUN_RAW_SOURCES ${BUN_CPP}) - -set(USOCKETS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src") -file(GLOB USOCKETS_FILES ${CONFIGURE_DEPENDS} - "${USOCKETS_SRC}/*.c" - "${USOCKETS_SRC}/eventing/*.c" - "${USOCKETS_SRC}/internal/*.c" - "${USOCKETS_SRC}/crypto/*.c" - "${USOCKETS_SRC}/crypto/*.cpp" -) -list(APPEND BUN_RAW_SOURCES ${USOCKETS_FILES}) - -# --- Classes Generator --- -file(GLOB BUN_CLASSES_TS ${CONFIGURE_DEPENDS} - "${BUN_SRC}/bun.js/*.classes.ts" - "${BUN_SRC}/bun.js/api/*.classes.ts" - "${BUN_SRC}/bun.js/test/*.classes.ts" - "${BUN_SRC}/bun.js/webcore/*.classes.ts" - "${BUN_SRC}/bun.js/node/*.classes.ts" -) -add_custom_command( - OUTPUT "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureHeader.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMClientIsoSubspaces.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMIsoSubspaces.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureImpl.h" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" - COMMAND ${BUN_EXECUTABLE} "${BUN_CODEGEN_SRC}/generate-classes.ts" ${BUN_CLASSES_TS} "${BUN_WORKDIR}/codegen" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - MAIN_DEPENDENCY "${BUN_CODEGEN_SRC}/generate-classes.ts" - DEPENDS ${BUN_CLASSES_TS} - VERBATIM - COMMENT "Generating *.classes.ts bindings" -) -list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp") - -# --- JSSink Generator --- -add_custom_command( - OUTPUT "${BUN_WORKDIR}/codegen/JSSink.cpp" - "${BUN_WORKDIR}/codegen/JSSink.h" - COMMAND ${BUN_EXECUTABLE} "src/codegen/generate-jssink.ts" "${BUN_WORKDIR}/codegen" - VERBATIM - MAIN_DEPENDENCY "src/codegen/generate-jssink.ts" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Generating JSSink" -) -list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/JSSink.cpp") - -# --- .lut.h Generator --- -set(BUN_OBJECT_LUT_SOURCES - bun.js/bindings/BunObject.cpp - bun.js/bindings/ZigGlobalObject.lut.txt - bun.js/bindings/JSBuffer.cpp - bun.js/bindings/BunProcess.cpp - bun.js/bindings/ProcessBindingConstants.cpp - bun.js/bindings/ProcessBindingNatives.cpp -) -set(BUN_OBJECT_LUT_OUTPUTS "") -set(BUN_HASH_LUT_GENERATOR "${BUN_CODEGEN_SRC}/create-hash-table.ts") - -if(NOT BUN_LINK_ONLY) - macro(GENERATE_HASH_LUT _input _output _display_name) - if(NOT NO_CODEGEN) - add_custom_command( - OUTPUT ${_output} - MAIN_DEPENDENCY ${BUN_HASH_LUT_GENERATOR} - DEPENDS ${_input} - COMMAND ${BUN_EXECUTABLE} ${BUN_HASH_LUT_GENERATOR} ${_input} ${_output} - VERBATIM - COMMENT "Generating ${_display_name}" - ) - endif() - - list(APPEND BUN_OBJECT_LUT_OUTPUTS "${_output}") - - # list(APPEND Bun_HEADERS ${_output}) - WEBKIT_ADD_SOURCE_DEPENDENCIES(${_input} ${_output}) - endmacro() - - foreach(_file ${BUN_OBJECT_LUT_SOURCES}) - if(NOT EXISTS "${BUN_SRC}/${_file}") - message(FATAL_ERROR "Could not find ${_file} needed for LUT generation") - endif() - - get_filename_component(_name ${_file} NAME_WE) - - # workaround for ZigGlobalObject - if(_name MATCHES "ZigGlobalObject") - set(_name "ZigGlobalObject") - endif() - - GENERATE_HASH_LUT(${BUN_SRC}/${_file} ${BUN_WORKDIR}/codegen/${_name}.lut.h ${_name}.lut.h) - endforeach() - - WEBKIT_ADD_SOURCE_DEPENDENCIES(${BUN_SRC}/bun.js/bindings/ZigGlobalObject.cpp ${BUN_WORKDIR}/codegen/ZigGlobalObject.lut.h) -endif() - -# --- Identifier Cache --- -if(NOT NO_CODEGEN) - set(BUN_IDENTIFIER_CACHE_OUT - "${BUN_SRC}/js_lexer/id_continue_bitset.blob" - "${BUN_SRC}/js_lexer/id_continue_bitset.meta.blob" - "${BUN_SRC}/js_lexer/id_start_bitset.blob" - "${BUN_SRC}/js_lexer/id_start_bitset.meta.blob") - add_custom_command( - OUTPUT ${BUN_IDENTIFIER_CACHE_OUT} - MAIN_DEPENDENCY "${BUN_SRC}/js_lexer/identifier_data.zig" - DEPENDS "${BUN_SRC}/js_lexer/identifier_cache.zig" - COMMAND ${ZIG_COMPILER} run "${BUN_SRC}/js_lexer/identifier_data.zig" - VERBATIM - COMMENT "Building Identifier Cache" - DEPENDS_EXPLICIT_ONLY - ) -endif() - -# --- Bundled TS/JS --- -# Note: It's not worth doing this in parallel at the CMake/Ninja level, because this bundling -# requires all the JS files to be known, but also Bun will use all cores during bundling anyways. -if(NOT NO_CODEGEN) - file(GLOB BUN_TS_MODULES ${CONFIGURE_DEPENDS} - "${BUN_SRC}/js/node/*.ts" - "${BUN_SRC}/js/node/*.js" - "${BUN_SRC}/js/bun/*.js" - "${BUN_SRC}/js/bun/*.ts" - "${BUN_SRC}/js/thirdparty/*.js" - "${BUN_SRC}/js/thirdparty/*.ts" - "${BUN_SRC}/js/internal/*.js" - "${BUN_SRC}/js/internal/*.ts" - ) - file(GLOB BUN_TS_FUNCTIONS ${CONFIGURE_DEPENDS} "${BUN_SRC}/js/builtins/*.ts") - - file(GLOB CODEGEN_FILES ${CONFIGURE_DEPENDS} "${BUN_CODEGEN_SRC}/*.ts") - - add_custom_command( - OUTPUT - "${BUN_WORKDIR}/codegen/InternalModuleRegistryConstants.h" - "${BUN_WORKDIR}/codegen/InternalModuleRegistry+createInternalModuleById.h" - "${BUN_WORKDIR}/codegen/InternalModuleRegistry+enum.h" - "${BUN_WORKDIR}/codegen/InternalModuleRegistry+numberOfModules.h" - "${BUN_WORKDIR}/codegen/NativeModuleImpl.h" - "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" - "${BUN_WORKDIR}/codegen/SyntheticModuleType.h" - COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-modules.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" - DEPENDS ${BUN_TS_MODULES} ${CODEGEN_FILES} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Bundling JS modules" - ) -endif() - -WEBKIT_ADD_SOURCE_DEPENDENCIES( - "${BUN_SRC}/bun.js/bindings/InternalModuleRegistry.cpp" - "${BUN_WORKDIR}/codegen/InternalModuleRegistryConstants.h" -) - -add_custom_command( - OUTPUT "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp" - "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.h" - COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-functions.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" - DEPENDS ${BUN_TS_FUNCTIONS} ${CODEGEN_FILES} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Bundling JS builtin functions" -) -list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp") - -# --- Peechy API --- -# if(NOT NO_CODEGEN) -# add_custom_command( -# OUTPUT "${BUN_SRC}/api/schema.js" -# "${BUN_SRC}/api/schema.d.ts" -# "${BUN_SRC}/api/schema.zig" -# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" -# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/.bin/peechy" -# "--schema" "${BUN_SRC}/api/schema.peechy" -# "--esm" "${BUN_SRC}/api/schema.js" -# "--ts" "${BUN_SRC}/api/schema.d.ts" -# "--zig" "${BUN_SRC}/api/schema.zig" -# COMMAND "${ZIG_COMPILER}" "fmt" "src/api/schema.zig" -# COMMAND "${PRETTIER}" "--config=.prettierrc.cjs" "--write" "src/api/schema.js" "src/api/schema.d.ts" -# DEPENDS "${BUN_SRC}/api/schema.peechy" -# COMMENT "Building schema" -# ) -# add_custom_command( -# OUTPUT "${BUN_SRC}/analytics/analytics_schema.zig" -# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" -# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/.bin/peechy" -# "--schema" "${BUN_SRC}/analytics/schema.peechy" -# "--zig" "${BUN_SRC}/analytics/analytics_schema.zig" -# COMMAND "${ZIG_COMPILER}" "fmt" "${BUN_SRC}/analytics/analytics_schema.zig" -# DEPENDS "${BUN_SRC}/api/schema.peechy" -# COMMENT "Building analytics_schema.zig" -# ) -# endif() - -# --- Runtime.js --- -if(NOT NO_CODEGEN) - add_custom_command( - OUTPUT "src/fallback.out.js" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMAND "${ESBUILD}" "--target=esnext" "--bundle" "src/fallback.ts" "--format=iife" "--platform=browser" "--minify" "--outfile=src/fallback.out.js" - DEPENDS "src/fallback.ts" - ) -endif() - -# --- Zig Object --- -file(GLOB ZIG_FILES - "${BUN_SRC}/*.zig" - "${BUN_SRC}/**/*.zig" - "${BUN_SRC}/**/**/*.zig" - "${BUN_SRC}/**/**/**/*.zig" -) - -if(NOT BUN_ZIG_OBJ) - set(BUN_ZIG_OBJ "${BUN_WORKDIR}/CMakeFiles/bun-zig.o") -else() - get_filename_component(BUN_ZIG_OBJ "${BUN_ZIG_OBJ}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") -endif() - -set(USES_TERMINAL_NOT_IN_CI "") -if(NOT CI) - set(USES_TERMINAL_NOT_IN_CI "USES_TERMINAL") -endif() - -if(NOT BUN_LINK_ONLY AND NOT BUN_CPP_ONLY) - add_custom_command( - OUTPUT "${BUN_ZIG_OBJ}" - COMMAND - "${ZIG_COMPILER}" "build" "obj" - "-Doutput-file=${BUN_ZIG_OBJ}" - "-Dgenerated-code=${BUN_WORKDIR}/codegen" - "-Dversion=${Bun_VERSION}" - "-Dcanary=$,true,false>" - "-Doptimize=${ZIG_OPTIMIZE}" - "-Dcpu=${CPU_TARGET}" - "-Dtarget=${ZIG_TARGET}" - DEPENDS - "${CMAKE_CURRENT_SOURCE_DIR}/build.zig" - "${ZIG_FILES}" - "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" - "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" - "${BUN_IDENTIFIER_CACHE_OUT}" - "${BUN_SRC}/api/schema.zig" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Building zig code" - VERBATIM - - # This is here to show Zig's progress indicator - ${USES_TERMINAL_NOT_IN_CI} - ) -endif() -add_custom_target(zig DEPENDS "${BUN_ZIG_OBJ}") - -if(WIN32) - list(APPEND BUN_RAW_SOURCES "${BUN_SRC}/bun.js/bindings/windows/musl-memmem.c") - include_directories("${BUN_SRC}/bun.js/bindings/windows") -endif() - -if(NOT BUN_CPP_ARCHIVE) - # TODO: unified sources - set(BUN_SOURCES ${BUN_RAW_SOURCES}) -else() - # used by ci - set(BUN_SOURCES "") - link_libraries(${BUN_CPP_ARCHIVE}) -endif() - -# -- The Buntime™️ --- -if(NOT BUN_CPP_ONLY) - add_executable(${bun} "${BUN_SOURCES}" "${BUN_ZIG_OBJ}") -else() - add_executable(${bun} "${BUN_SOURCES}") -endif() - -set_target_properties(${bun} PROPERTIES - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS YES - CXX_VISIBILITY_PRESET hidden - C_STANDARD 17 - C_STANDARD_REQUIRED YES - VISIBILITY_INLINES_HIDDEN YES -) - -if(NOT BUN_CPP_ARCHIVE) - if(NOT WIN32) - string(REPLACE ";" ".o\n " BUN_OBJECT_LIST "${BUN_SOURCES}.o") - string(REPLACE "${BUN_WORKDIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - write_file("${BUN_WORKDIR}/compile-cpp-only.sh" - "#!/usr/bin/env bash\n" - "set -e\n" - "OBJ_LIST=(\n ${BUN_OBJECT_LIST}\n)\n" - "ninja \${OBJ_LIST[@]} $@\n" - "${AR} rcvs bun-cpp-objects.a \${OBJ_LIST[@]}\n" - "echo '-> bun-cpp-objects.a'\n" - ) - else() - string(REPLACE ";" ".obj\",\n \"" BUN_OBJECT_LIST "\"${BUN_SOURCES}.obj\"") - string(REPLACE "${BUN_WORKDIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") - write_file("${BUN_WORKDIR}/compile-cpp-only.ps1" - "$ErrorActionPreference = \"Stop\"\n" - "OBJ_LIST=@(\n ${BUN_OBJECT_LIST}\n)\n" - "ninja @OBJ_LIST\n" - "Write-Host \"TODO: AR\"\n" - ) - endif() -else() - set_target_properties(${bun} PROPERTIES LINKER_LANGUAGE CXX) -endif() - -# Set /subsystem:console on bun for windows -if(WIN32) - set_target_properties(${bun} PROPERTIES LINK_FLAGS " /SUBSYSTEM:CONSOLE ") -endif() - -add_compile_definitions( - - # TODO: are all of these variables strictly necessary? - "_HAS_EXCEPTIONS=0" - "LIBUS_USE_OPENSSL=1" - "UWS_HTTPRESPONSE_NO_WRITEMARK=1" - "LIBUS_USE_BORINGSSL=1" - "WITH_BORINGSSL=1" - "STATICALLY_LINKED_WITH_JavaScriptCore=1" - "STATICALLY_LINKED_WITH_WTF=1" - "STATICALLY_LINKED_WITH_BMALLOC=1" - "BUILDING_WITH_CMAKE=1" - "JSC_OBJC_API_ENABLED=0" - "BUN_SINGLE_THREADED_PER_VM_ENTRY_SCOPE=1" - "NAPI_EXPERIMENTAL=ON" - "NOMINMAX" - "IS_BUILD" - "BUILDING_JSCONLY__" - "ASSERT_ENABLED=$,1,0>" - "BUN_DYNAMIC_JS_LOAD_PATH=\"${BUN_WORKDIR}/js\"" -) - -if(NOT ASSERT_ENABLED) - add_compile_definitions("NDEBUG=1") -endif() - -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/packages/ - ${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets - ${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/webcore - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/webcrypto - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/sqlite - ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/modules - ${CMAKE_CURRENT_SOURCE_DIR}/src/js/builtins - ${CMAKE_CURRENT_SOURCE_DIR}/src/napi - ${CMAKE_CURRENT_SOURCE_DIR}/src/deps - ${CMAKE_CURRENT_SOURCE_DIR}/src/deps/picohttpparser - ${WEBKIT_INCLUDE_DIR} - "${BUN_WORKDIR}/codegen" -) - -# --- clang and linker flags --- -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - if(NOT MSVC) - target_compile_options(${bun} PUBLIC -g3 -O1) - endif() - - add_compile_definitions("BUN_DEBUG=1") -elseif(CMAKE_BUILD_TYPE STREQUAL "Release") - if(MSVC) - target_compile_options(${bun} PUBLIC /O2) - else() - target_compile_options(${bun} PUBLIC -O3 -flto=full -emit-llvm) - endif() -endif() - -if(NOT MSVC) - if(NOT CI) - target_compile_options(${bun} PRIVATE -fdiagnostics-color=always) - endif() - - target_compile_options(${bun} PUBLIC - -march=${CPU_TARGET} - -mtune=${CPU_TARGET} - -fconstexpr-steps=1271242 - -fconstexpr-depth=27 - -fno-exceptions - -fvisibility=hidden - -fvisibility-inlines-hidden - -fno-rtti - -ferror-limit=${ERROR_LIMIT} - -fno-omit-frame-pointer - ) - - if(NOT WIN32) - target_compile_options(${bun} PUBLIC -fPIC) - endif() - - if(NOT APPLE) - target_link_options(${bun} PUBLIC -fuse-ld=lld) - endif() - - string(APPEND CMAKE_CXX_FLAGS " -std=c++2a ") -else() # MSVC - string(APPEND SUPPRESS_WARNING_NUMBERS - - # JSC deletes operator delete to prevent accidental use - "/wd4291 " - - # we use #pragma mark in some places - "/wd4068" - ) - string(APPEND CMAKE_CXX_FLAGS " /EHsc /GR-") - string(APPEND CMAKE_C_FLAGS " /EHsc /GR- ${SUPPRESS_WARNING_NUMBERS} /experimental:c11atomics /std:c17") - string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus /Zc:inline /bigobj ${SUPPRESS_WARNING_NUMBERS}") -endif() - -if(APPLE) - if(ARCH STREQUAL "x86_64") - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") - else() - set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") - endif() - - target_link_options(${bun} PUBLIC "-dead_strip") - target_link_options(${bun} PUBLIC "-dead_strip_dylibs") - - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - # bun install will stack overflow on start in debug builds if the stack size isn't at least 12 MB - target_link_options(${bun} PUBLIC "-Wl,-stack_size,0x1200000") - endif() - - target_link_options(${bun} PUBLIC "-exported_symbols_list" "${BUN_SRC}/symbols.txt") - set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.txt") - - target_link_options(${bun} PUBLIC "-fno-keep-static-consts") - target_link_libraries(${bun} PRIVATE "resolv") -endif() - -if(UNIX AND NOT APPLE) - target_link_options(${bun} PUBLIC - "-static-libstdc++" - "-static-libgcc" - "-fuse-ld=lld" - "-Wl,-z,now" - "-Wl,--as-needed" - "-Wl,--gc-sections" - "-Wl,-z,stack-size=12800000" - "-Wl,--wrap=fcntl" - "-Wl,--wrap=fcntl64" - "-Wl,--wrap=stat64" - "-Wl,--wrap=pow" - "-Wl,--wrap=exp" - "-Wl,--wrap=log" - "-Wl,--wrap=log2" - "-Wl,--wrap=lstat" - "-Wl,--wrap=stat" - "-Wl,--wrap=fstat" - "-Wl,--wrap=fstatat" - "-Wl,--wrap=lstat64" - "-Wl,--wrap=stat64" - "-Wl,--wrap=fstat64" - "-Wl,--wrap=fstatat64" - "-Wl,--wrap=mknod" - "-Wl,--wrap=mknodat" - "-Wl,--wrap=statx " - "-Wl,--compress-debug-sections=zlib" - "-Bsymbolics-functions" - "-rdynamic" - "-Wl,--dynamic-list=${BUN_SRC}/symbols.dyn" - "-Wl,--version-script=${BUN_SRC}/linker.lds" - ) - - target_link_libraries(${bun} PRIVATE "c") - target_link_libraries(${bun} PRIVATE "pthread") - target_link_libraries(${bun} PRIVATE "dl") - - if(NOT USE_STATIC_LIBATOMIC) - target_link_libraries(${bun} PUBLIC "libatomic.so") - else() - target_link_libraries(${bun} PRIVATE "libatomic.a") - endif() - - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicudata.a") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicui18n.a") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicuuc.a") - - set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/linker.lds") - set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.dyn") -endif() - -if(WIN32) - add_compile_definitions( - "WIN32" - "_WINDOWS" - "_CRT_SECURE_NO_WARNINGS" - "WIN32_LEAN_AND_MEAN=1" - ) - - set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") -endif() - -# --- ICU --- -if(APPLE) - # TODO: a much better check can be done to find this path - find_path( - ICU4C_DIR NAMES lib/libicudata.a - PATHS ENV PATH /usr/local/opt/icu4c /opt/homebrew/opt/icu4c - ) - find_path( - ICONV_DIR NAMES lib/libiconv.a - PATHS ENV PATH /usr/local/opt/libiconv /opt/homebrew/opt/libiconv - ) - - target_link_libraries(${bun} PRIVATE "icucore") - target_link_libraries(${bun} PRIVATE "${ICONV_DIR}/lib/libiconv.a") - target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicudata.a") - target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicui18n.a") - target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicuuc.a") - include_directories(${ICU4C_DIR}/include) -endif() - -# --- Stripped Binary "bun" -if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32) - # add_custom_command( - # TARGET ${bun} - # POST_BUILD - # COMMAND ${DSYMUTIL} -o ${BUN_WORKDIR}/bun.dSYM ${BUN_WORKDIR}/${bun} - # COMMENT "Stripping Symbols" - # ) - add_custom_command( - TARGET ${bun} - POST_BUILD - COMMAND ${STRIP} -s -x -S -o ${BUN_WORKDIR}/bun ${BUN_WORKDIR}/${bun} - COMMENT "Stripping Symbols" - ) -endif() - -# --- Dependencies --- -if(USE_CUSTOM_ZLIB) - include_directories(${BUN_DEPS_DIR}/zlib) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/zlibstatic.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libz.a") - endif() -else() - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_DIR}/zlib_maybethisworks.lib") - else() - find_package(ZLIB REQUIRED) - target_link_libraries(${bun} PRIVATE ZLIB::ZLIB) - endif() -endif() - -if(USE_CUSTOM_BORINGSSL) - include_directories(${BUN_DEPS_DIR}/boringssl/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/crypto.lib") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/ssl.lib") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/decrepit.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libcrypto.a") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libssl.a") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libdecrepit.a") - endif() -else() - include(FindBoringSSL) - FindBoringSSL(${bun}) -endif() - -if(USE_CUSTOM_LIBARCHIVE) - include_directories(${BUN_DEPS_DIR}/libarchive/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/archive.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libarchive.a") - endif() -else() - find_package(LibArchive REQUIRED) - target_link_libraries(${bun} PRIVATE LibArchive::LibArchive) -endif() - -if(USE_CUSTOM_MIMALLOC) - include_directories(${BUN_DEPS_DIR}/mimalloc/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/mimalloc-static.lib") - elseif(APPLE) - # https://github.com/microsoft/mimalloc/issues/512 - # Linking mimalloc via object file on macOS x64 can cause heap corruption - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc.a") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc.o") - endif() -else() - find_package(mimalloc REQUIRED) - target_link_libraries(${bun} PRIVATE mimalloc) -endif() - -if(USE_CUSTOM_ZSTD) - include_directories(${BUN_DEPS_DIR}/zstd/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/zstd.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libzstd.a") - endif() -else() - find_package(zstd CONFIG REQUIRED) - target_link_libraries(${bun} PRIVATE zstd::libzstd) -endif() - -if(USE_CUSTOM_CARES) - include_directories(${BUN_DEPS_DIR}/c-ares/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/cares.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libcares.a") - endif() -else() - find_package(c-ares CONFIG REQUIRED) - target_link_libraries(${bun} PRIVATE c-ares::cares) -endif() - -if(USE_CUSTOM_BASE64) - include_directories(${BUN_DEPS_DIR}/base64/include) - - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/base64.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libbase64.a") - endif() -else() - find_package(base64 REQUIRED) - target_link_libraries(${bun} PRIVATE base64::base64) -endif() - -if(NOT WIN32) - if(USE_CUSTOM_TINYCC) - if(WIN32) - # target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/tcc.lib") - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/tcc.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libtcc.a") - endif() - else() - find_package(tinycc REQUIRED) - target_link_libraries(${bun} PRIVATE tinycc::tinycc) - endif() -endif() - -if(USE_CUSTOM_LOLHTML) - if(WIN32) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/lolhtml.lib") - else() - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/liblolhtml.a") - endif() -else() - find_package(lolhtml REQUIRED) - target_link_libraries(${bun} PRIVATE lolhtml::lolhtml) -endif() - -if(WIN32) - if(USE_CUSTOM_LIBUV) - target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libuv.lib") - else() - find_package(libuv CONFIG REQUIRED) - target_link_libraries(${bun} PRIVATE $,libuv::uv_a,libuv::uv>) - endif() -endif() - -if(USE_STATIC_SQLITE) - add_library(sqlite3 STATIC src/bun.js/bindings/sqlite/sqlite3.c) - target_include_directories(sqlite3 PUBLIC src/bun.js/bindings/sqlite) - target_compile_definitions(sqlite3 PRIVATE - "SQLITE_ENABLE_COLUMN_METADATA=" - "SQLITE_MAX_VARIABLE_NUMBER=250000" - "SQLITE_ENABLE_RTREE=1" - "SQLITE_ENABLE_FTS3=1" - "SQLITE_ENABLE_FTS3_PARENTHESIS=1" - "SQLITE_ENABLE_FTS5=1" - "SQLITE_ENABLE_JSON1=1" - ) - target_link_libraries(${bun} PRIVATE sqlite3) - message(STATUS "Using static sqlite3") - target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=0") -else() - message(STATUS "Using dynamicly linked sqlite3") - target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=1") -endif() - -if(NOT MSVC) - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libWTF.a") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libJavaScriptCore.a") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libbmalloc.a") -else() - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/WTF.lib") - target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/JavaScriptCore.lib") - - if(WIN32) - set_target_properties(${bun} PROPERTIES LINK_FLAGS " /SUBSYSTEM:CONSOLE /STACK:4194304,2097152") - endif() - - # include_directories(C:/Users/windo/Build/WebKit/WebKitBuild/WTF/DerivedSources) - # include_directories(C:/Users/windo/Build/WebKit/WebKitBuild/WTF/Headers) - target_include_directories(${bun} PUBLIC C:/Users/windo/Code/WebKit/WebKitLibraries/win/include) - target_link_directories(${bun} PUBLIC C:/Users/windo/Code/WebKit/WebKitLibraries/win/lib64) - target_link_directories(${bun} PUBLIC C:/Users/windo/Code/lib64) - - target_link_libraries(${bun} PUBLIC icuuc icudt icutu icuio icuin icutest) - target_link_libraries(${bun} PUBLIC winmm ws2_32 bcrypt ntdll kernel32 shell32 shlwapi advapi32 vcruntime ucrt legacy_stdio_definitions) -endif() - -if(NO_CODEGEN AND NOT CODEGEN) - message(STATUS "NO_CODEGEN is ON, a handful of build steps will not run.") -endif() +cmake_minimum_required(VERSION 3.22) +cmake_policy(SET CMP0091 NEW) +cmake_policy(SET CMP0067 NEW) + +set(Bun_VERSION "1.0.9") +set(WEBKIT_TAG 7cd84abfa787e4b96b27c3ef1e28a4eb1aa49aa1) + +set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}") +message(STATUS "Configuring Bun ${Bun_VERSION} in ${BUN_WORKDIR}") + +# --- Build Type --- +if(NOT CMAKE_BUILD_TYPE) + message(WARNING "No CMAKE_BUILD_TYPE value specified, defaulting to Debug.\nSet a build type with -DCMAKE_BUILD_TYPE=") + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build (Debug, Release)" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release)$") + message(FATAL_ERROR + "Invalid CMAKE_BUILD_TYPE value specified: ${CMAKE_BUILD_TYPE}\n" + "CMAKE_BUILD_TYPE must be Debug or Release.") + endif() + + message(STATUS "The CMake build type is: ${CMAKE_BUILD_TYPE}") +endif() + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(DEBUG ON) + set(ZIG_OPTIMIZE "Debug") + set(bun "bun-debug") +elseif(CMAKE_BUILD_TYPE STREQUAL "Release") + set(DEBUG OFF) + set(ZIG_OPTIMIZE "ReleaseFast") + if(WIN32) + # lld-link will strip it for you, so we can build directly to bun.exe + set(bun "bun") + else() + set(bun "bun-profile") + endif() +endif() + +# --- LLVM --- +# This detection is a little overkill, but it ensures that the set LLVM_VERSION matches under +# any case possible. Sorry for the complexity... +# +# Bun and WebKit must be compiled with the same compiler, so we do as much as we can to ensure that +# the compiler used for the prebuilt WebKit, LLVM 16, is the one that we detect in this process. +# +# It has to be done before project() is called, so that CMake doesnt pick a compiler for us, but even then +# we do some extra work afterwards to double-check, and we will rerun BUN_FIND_LLVM if the compiler did not match. +# +# If the user passes -DLLVM_PREFIX, most of this logic is skipped, but we still warn if invalid. +set(LLVM_VERSION 16) + +macro(BUN_FIND_LLVM) + find_program( + _LLVM_CXX_PATH + NAMES clang++-${LLVM_VERSION} clang++ + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s clang++ binary. Please pass -DLLVM_PREFIX with the path to LLVM" + ) + + if(NOT _LLVM_CXX_PATH) + message(FATAL_ERROR "Could not find LLVM ${LLVM_VERSION}, search paths: ${PLATFORM_LLVM_SEARCH_PATHS}") + endif() + + set(CMAKE_CXX_COMPILER "${_LLVM_CXX_PATH}") + find_program( + _LLVM_C_PATH + NAMES clang-${LLVM_VERSION} clang + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s clang binary. Please pass -DLLVM_PREFIX with the path to LLVM" + ) + + if(NOT _LLVM_C_PATH) + message(FATAL_ERROR "Could not find LLVM ${LLVM_VERSION}, search paths: ${PLATFORM_LLVM_SEARCH_PATHS}") + endif() + + set(CMAKE_C_COMPILER "${_LLVM_C_PATH}") + + find_program( + STRIP + NAMES llvm-strip + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" + ) + find_program( + STRIP + NAMES strip + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" + ) + find_program( + DSYMUTIL + NAMES dsymutil + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s dsymutil binary" + ) + find_program( + AR + NAMES llvm-ar + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" + ) + find_program( + AR + NAMES ar + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" + ) + find_program( + RANLIB + NAMES llvm-ranlib + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" + ) + + execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE _tmp) + string(REGEX MATCH "version ([0-9]+)\\.([0-9]+)\\.([0-9]+)" CMAKE_CXX_COMPILER_VERSION "${_tmp}") + set(CMAKE_CXX_COMPILER_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") +endmacro() + +if(UNIX) + if(LLVM_PREFIX) + set(PLATFORM_LLVM_SEARCH_PATHS ${LLVM_PREFIX}/bin) + else() + set(PLATFORM_LLVM_SEARCH_PATHS /usr/lib/llvm-${LLVM_VERSION}/bin /usr/lib/llvm${LLVM_VERSION}/bin /usr/bin /usr/local/bin) + + if(APPLE) + set(PLATFORM_LLVM_SEARCH_PATHS /opt/homebrew/opt/llvm@${LLVM_VERSION}/bin /opt/homebrew/bin ${PLATFORM_LLVM_SEARCH_PATHS}) + endif() + endif() + + if(CMAKE_CXX_COMPILER) + set(_LLVM_CXX_PATH "${CMAKE_CXX_COMPILER}") + endif() + + if(CMAKE_C_COMPILER) + set(_LLVM_C_PATH "${CMAKE_C_COMPILER}") + endif() + + BUN_FIND_LLVM() +else() + # Windows uses Clang-CL + # TODO: good configuration in this regard. -G Ninja will pick clang-cl if possible, which should be fine for most users. + if(NOT CMAKE_C_COMPILER) + set(CMAKE_C_COMPILER "clang-cl") + endif() + if(NOT CMAKE_CXX_COMPILER) + set(CMAKE_CXX_COMPILER "clang-cl") + endif() + + find_program( + STRIP + NAMES llvm-strip + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-strip binary" + ) + find_program( + AR + NAMES llvm-ar + PATHS ENV PATH ${PLATFORM_LLVM_SEARCH_PATHS} + DOC "Path to LLVM ${LLVM_VERSION}'s llvm-ar binary" + ) +endif() + +set(CMAKE_COLOR_DIAGNOSTICS ON) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_C_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD_REQUIRED ON) + +project(Bun VERSION "${Bun_VERSION}") + +#if(MSVC) +# message(FATAL_ERROR "Bun does not support building with MSVC. Please use `cmake -G Ninja` with LLVM ${LLVM_VERSION} and Ninja.") +#endif() + +# More effort to prevent using the wrong C++ compiler +if(UNIX) + if((NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR(NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${LLVM_VERSION}\.")) + # Attempt to auto-correct the compiler + message(STATUS "Compiler mismatch, attempting to auto-correct") + unset(_LLVM_CXX_PATH) + BUN_FIND_LLVM() + + if((NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR(NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${LLVM_VERSION}\.")) + message(WARNING "Expected LLVM ${LLVM_VERSION} as the C++ compiler, build may fail or break at runtime.") + endif() + endif() +endif() + +message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} at ${CMAKE_CXX_COMPILER}") + +# --- End LLVM --- +if(NOT WIN32) + set(SHELL "bash") + set(SCRIPT_EXTENSION "sh") +else() + set(SCRIPT_EXTENSION "ps1") + # pwsh is the new powershell, powershell is the old one. + find_program(SHELL NAMES pwsh powershell) +endif() + +set(DEFAULT_ON_UNLESS_APPLE ON) + +if(APPLE) + set(DEFAULT_ON_UNLESS_APPLE OFF) +endif() + +set(CI OFF) + +if(DEFINED ENV{CI} OR DEFINED ENV{GITHUB_ACTIONS}) + set(CI ON) +endif() + +set(DEFAULT_USE_STATIC_LIBATOMIC ON) +if(UNIX AND NOT APPLE) + execute_process(COMMAND cat /etc/os-release COMMAND head -n1 OUTPUT_VARIABLE LINUX_DISTRO) + if(${LINUX_DISTRO} STREQUAL "NAME=\"Arch Linux\"\n") + set(DEFAULT_USE_STATIC_LIBATOMIC OFF) + endif() +endif() + +# -- Build Flags -- +option(USE_STATIC_SQLITE "Statically link SQLite?" ${DEFAULT_ON_UNLESS_APPLE}) +option(USE_CUSTOM_ZLIB "Use Bun's recommended version of zlib" ON) +option(USE_CUSTOM_BORINGSSL "Use Bun's recommended version of BoringSSL" ON) +option(USE_CUSTOM_LIBARCHIVE "Use Bun's recommended version of libarchive" ON) +option(USE_CUSTOM_MIMALLOC "Use Bun's recommended version of Mimalloc" ON) +option(USE_CUSTOM_ZSTD "Use Bun's recommended version of zstd" ON) +option(USE_CUSTOM_CARES "Use Bun's recommended version of c-ares" ON) +option(USE_CUSTOM_BASE64 "Use Bun's recommended version of libbase64" ON) +option(USE_CUSTOM_LOLHTML "Use Bun's recommended version of lolhtml" ON) +option(USE_CUSTOM_TINYCC "Use Bun's recommended version of tinycc" ON) +option(USE_CUSTOM_LIBUV "Use Bun's recommended version of libuv (Windows only)" ON) +option(USE_BASELINE_BUILD "Build Bun for baseline (older) CPUs" OFF) + +option(USE_DEBUG_JSC "Enable assertions and use a debug build of JavaScriptCore" OFF) +option(USE_UNIFIED_SOURCES "Use unified sources to speed up the build" OFF) +option(USE_STATIC_LIBATOMIC "Statically link libatomic, requires the presence of libatomic.a" ${DEFAULT_USE_STATIC_LIBATOMIC}) + +if (NOT CANARY) + set(CANARY 0) +endif() + +set(ERROR_LIMIT 100 CACHE STRING "Maximum number of errors to show when compiling C++ code") + +set(ARCH x86_64) + +if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|arm") + set(ARCH aarch64) +endif() + +if(NOT CPU_TARGET) + if(ENV{CPU_TARGET}) + set(CPU_TARGET $ENV{CPU_TARGET}) + else() + set(CPU_TARGET "native" CACHE STRING "CPU target for the compiler" FORCE) + + if(ARCH STREQUAL "x86_64") + if(USE_BASELINE_BUILD) + set(CPU_TARGET "nehalem") + else() + set(CPU_TARGET "haswell") + endif() + endif() + endif() +endif() + +message(STATUS "Building for CPU Target: ${CPU_TARGET}") + +if(NOT ZIG_TARGET) + set(ZIG_TARGET "native") + + if(WIN32) + set(ZIG_TARGET "${ARCH}-windows-msvc") + endif() +endif() + +set(CONFIGURE_DEPENDS "CONFIGURE_DEPENDS") + +if(NO_CONFIGURE_DEPENDS) + set(CONFIGURE_DEPENDS "") +endif() + +# --- CLI Paths --- +set(REQUIRED_IF_NOT_ONLY_CPP_OR_LINK "") + +if(NOT BUN_CPP_ONLY AND NOT BUN_LINK_ONLY) + set(REQUIRED_IF_NOT_ONLY_CPP_OR_LINK "REQUIRED") +endif() + +# Zig Compiler +function(validate_zig validator_result_var item) + set(${validator_result_var} FALSE PARENT_SCOPE) + + # We will allow any valid zig compiler, as long as it contains some text from `zig zen` + # Ideally we would do a version or feature check, but that would be quite slow + execute_process(COMMAND ${item} zen OUTPUT_VARIABLE ZIG_ZEN_OUTPUT) + + if(ZIG_ZEN_OUTPUT MATCHES "Together we serve the users") + set(${validator_result_var} TRUE PARENT_SCOPE) + else() + set(${validator_result_var} FALSE PARENT_SCOPE) + endif() +endfunction() + +find_program(ZIG_COMPILER zig ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to the Zig compiler" VALIDATOR validate_zig) +message(STATUS "Found Zig Compiler: ${ZIG_COMPILER}") + +# Bun +if(NOT WIN32) + find_program(BUN_EXECUTABLE bun ${REQUIRED_IF_NOT_ONLY_CPP_OR_LINK} DOC "Path to an already built release of Bun") + message(STATUS "Found Bun: ${BUN_EXECUTABLE}") +else() + set(BUN_EXECUTABLE "echo") +endif() + +# Prettier +find_program(PRETTIER prettier DOC "Path to prettier" PATHS ./node_modules/.bin ENV PATH) + +# Esbuild (TODO: switch these to "bun build") +find_program(ESBUILD esbuild DOC "Path to esbuild" PATHS ./node_modules/.bin ENV PATH) + +# Ruby (only needed for unified sources) +if(USE_UNIFIED_SOURCES) + # ruby 'WebKit/Source/WTF/Scripts/generate-unified-source-bundles.rb' source_list.txt --source-tree-path . --derived-sources-path build/unified-sources + find_program(RUBY ruby DOC "Path to ruby") +endif() + +# CCache +find_program(CCACHE_PROGRAM sccache) +find_program(CCACHE_PROGRAM ccache) +if(CCACHE_PROGRAM) + set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") + set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") + message(STATUS "Using ccache: ${CCACHE_PROGRAM}") +endif() + +# --- WebKit --- +# WebKit is either prebuilt and distributed via NPM, or you can pass WEBKIT_DIR to use a local build. +# We cannot include their CMake build files (TODO: explain why, for now ask @paperdave why) +# +# On Unix, this will pull from NPM the single package that is needed and use that +if(WIN32) + set(STATIC_LIB_EXT "lib") + set(libJavaScriptCore "JavaScriptCore") + set(libWTF "WTF") +else() + set(STATIC_LIB_EXT "a") + set(libJavaScriptCore "libJavaScriptCore") + set(libWTF "libWTF") +endif() + +if(NOT WEBKIT_DIR) + set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "") + set(ASSERT_ENABLED "0") + + if(USE_DEBUG_JSC) + set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "-debug") + set(ASSERT_ENABLED "1") + elseif(NOT DEBUG AND NOT WIN32) + set(BUN_WEBKIT_PACKAGE_NAME_SUFFIX "-lto") + set(ASSERT_ENABLED "0") + endif() + + if(WIN32) + set(BUN_WEBKIT_PACKAGE_PLATFORM "windows") + elseif(APPLE) + set(BUN_WEBKIT_PACKAGE_PLATFORM "macos") + else() + set(BUN_WEBKIT_PACKAGE_PLATFORM "linux") + endif() + + if(ARCH STREQUAL "x86_64") + set(BUN_WEBKIT_PACKAGE_ARCH "amd64") + elseif(ARCH MATCHES "aarch64|arm64|arm") + set(BUN_WEBKIT_PACKAGE_ARCH "arm64") + endif() + + set(BUN_WEBKIT_PACKAGE_NAME "bun-webkit-${BUN_WEBKIT_PACKAGE_PLATFORM}-${BUN_WEBKIT_PACKAGE_ARCH}${BUN_WEBKIT_PACKAGE_NAME_SUFFIX}") + + message(STATUS "Using Pre-built WebKit: ${BUN_WEBKIT_PACKAGE_NAME}") + execute_process( + COMMAND "${SHELL}" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/download-webkit.${SCRIPT_EXTENSION}" + "${BUN_WORKDIR}/bun-webkit" + "${WEBKIT_TAG}" + "${BUN_WEBKIT_PACKAGE_NAME}" + WORKING_DIRECTORY ${BUN_WORKDIR} + ) + + if(NOT EXISTS "${BUN_WORKDIR}/bun-webkit") + message(FATAL_ERROR "Prebuilt WebKit package ${BUN_WEBKIT_PACKAGE_NAME} failed to install") + endif() + + set(WEBKIT_INCLUDE_DIR "${BUN_WORKDIR}/bun-webkit/include") + set(WEBKIT_LIB_DIR "${BUN_WORKDIR}/bun-webkit/lib") +elseif(WEBKIT_DIR STREQUAL "omit") + message(STATUS "Not using WebKit. This is only valid if you are only trying to build Zig code") +else() + # Setting WEBKIT_DIR means you either have a path to the WebKit repo, or you have a path to packaged webkit + # Non-packaged webkit has CMakeLists.txt + if(EXISTS "${WEBKIT_DIR}/CMakeLists.txt") + # Since we may be doing a Debug build of Bun but with a Release build of JSC, we can't + # include their CMakeLists directly here, but rather we need to run `cmake` as a dependency + # of our build. It'll still have decent caching which is what really matters. + + # cmake WEBKIT_DIR -B WEBKIT_DIR/WebKitBuild/WEBKIT_BUILD_TYPE + # -DPORT=JSCOnly + # -DENABLE_STATIC_JSC=ON + # -DENABLE_SINGLE_THREADED_VM_ENTRY_SCOPE=ON + # -DCMAKE_BUILD_TYPE=Debug + # -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON + # -DUSE_THIN_ARCHIVES=OFF + # -DENABLE_FTL_JIT=ON + # -DCMAKE_C_COMPILER=(which clang-16) + # -DDCMAKE_CXX_COMPILER=(which clang++-16) + # -DDUSE_BUN_JSC_ADDITIONS=1 + # -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" + # -DCMAKE_AR=$(which llvm-ar) + # -DCMAKE_RANLIB=$(which llvm-ranlib) + # -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON + # -G Ninja + # -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 + # -DPTHREAD_JIT_PERMISSIONS_API=1 + # -DUSE_PTHREAD_JIT_PERMISSIONS_API=ON + # -DENABLE_REMOTE_INSPECTOR=ON + message(FATAL_ERROR "TODO: Setting WEBKIT_DIR to the WebKit repository to enable automatic builds. For now you need to run the release script, and point to the packaged directory.") + else() + if(NOT EXISTS "${WEBKIT_DIR}/lib/${libWTF}.${STATIC_LIB_EXT}" OR NOT EXISTS "${WEBKIT_DIR}/lib/${libJavaScriptCore}.${STATIC_LIB_EXT}") + if(WEBKIT_DIR MATCHES "src/bun.js/WebKit$") + message(FATAL_ERROR "WebKit directory ${WEBKIT_DIR} does not contain all the required files for Bun. Did you forget to init submodules?") + endif() + + message(FATAL_ERROR "WebKit directory ${WEBKIT_DIR} does not contain all the required files for Bun. Expected a path to the oven-sh/WebKit repository, or a path to a folder containing `include` and `lib`.") + endif() + + set(WEBKIT_INCLUDE_DIR "${WEBKIT_DIR}/include") + set(WEBKIT_LIB_DIR "${WEBKIT_DIR}/lib") + + message(STATUS "Using specified WebKit directory: ${WEBKIT_DIR}") + + set(ASSERT_ENABLED "0") + message(STATUS "WebKit assertions: OFF") + endif() +endif() + +# --- CMake Macros --- + +# Append the given dependencies to the source file +macro(WEBKIT_ADD_SOURCE_DEPENDENCIES _source _deps) + set(_tmp) + get_source_file_property(_tmp ${_source} OBJECT_DEPENDS) + + if(NOT _tmp) + set(_tmp "") + endif() + + foreach(f ${_deps}) + list(APPEND _tmp "${f}") + endforeach() + + set_source_files_properties(${_source} PROPERTIES OBJECT_DEPENDS "${_tmp}") + unset(_tmp) +endmacro() + +# --- BUILD --- +set(BUN_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src") +set(BUN_DEPS_DIR "${BUN_SRC}/deps") +set(BUN_CODEGEN_SRC "${BUN_SRC}/codegen") + +if(NOT BUN_DEPS_OUT_DIR) + set(BUN_DEPS_OUT_DIR "${BUN_DEPS_DIR}") +endif() + +set(BUN_RAW_SOURCES, "") + +file(GLOB BUN_CPP ${CONFIGURE_DEPENDS} + "${BUN_SRC}/deps/*.cpp" + "${BUN_SRC}/io/*.cpp" + "${BUN_SRC}/bun.js/modules/*.cpp" + "${BUN_SRC}/bun.js/bindings/*.cpp" + "${BUN_SRC}/bun.js/bindings/webcore/*.cpp" + "${BUN_SRC}/bun.js/bindings/sqlite/*.cpp" + "${BUN_SRC}/bun.js/bindings/webcrypto/*.cpp" + "${BUN_SRC}/bun.js/bindings/webcrypto/*/*.cpp" + "${BUN_SRC}/deps/picohttpparser/picohttpparser.c" +) +list(APPEND BUN_RAW_SOURCES ${BUN_CPP}) + +set(USOCKETS_SRC "${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src") +file(GLOB USOCKETS_FILES ${CONFIGURE_DEPENDS} + "${USOCKETS_SRC}/*.c" + "${USOCKETS_SRC}/eventing/*.c" + "${USOCKETS_SRC}/internal/*.c" + "${USOCKETS_SRC}/crypto/*.c" + "${USOCKETS_SRC}/crypto/*.cpp" +) +list(APPEND BUN_RAW_SOURCES ${USOCKETS_FILES}) + +# --- Classes Generator --- +file(GLOB BUN_CLASSES_TS ${CONFIGURE_DEPENDS} + "${BUN_SRC}/bun.js/*.classes.ts" + "${BUN_SRC}/bun.js/api/*.classes.ts" + "${BUN_SRC}/bun.js/test/*.classes.ts" + "${BUN_SRC}/bun.js/webcore/*.classes.ts" + "${BUN_SRC}/bun.js/node/*.classes.ts" +) +add_custom_command( + OUTPUT "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureHeader.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMClientIsoSubspaces.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+DOMIsoSubspaces.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses+lazyStructureImpl.h" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" + COMMAND ${BUN_EXECUTABLE} "${BUN_CODEGEN_SRC}/generate-classes.ts" ${BUN_CLASSES_TS} "${BUN_WORKDIR}/codegen" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + MAIN_DEPENDENCY "${BUN_CODEGEN_SRC}/generate-classes.ts" + DEPENDS ${BUN_CLASSES_TS} + VERBATIM + COMMENT "Generating *.classes.ts bindings" +) +list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.cpp") + +# --- JSSink Generator --- +add_custom_command( + OUTPUT "${BUN_WORKDIR}/codegen/JSSink.cpp" + "${BUN_WORKDIR}/codegen/JSSink.h" + COMMAND ${BUN_EXECUTABLE} "src/codegen/generate-jssink.ts" "${BUN_WORKDIR}/codegen" + VERBATIM + MAIN_DEPENDENCY "src/codegen/generate-jssink.ts" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generating JSSink" +) +list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/JSSink.cpp") + +# --- .lut.h Generator --- +set(BUN_OBJECT_LUT_SOURCES + bun.js/bindings/BunObject.cpp + bun.js/bindings/ZigGlobalObject.lut.txt + bun.js/bindings/JSBuffer.cpp + bun.js/bindings/BunProcess.cpp + bun.js/bindings/ProcessBindingConstants.cpp + bun.js/bindings/ProcessBindingNatives.cpp +) +set(BUN_OBJECT_LUT_OUTPUTS "") +set(BUN_HASH_LUT_GENERATOR "${BUN_CODEGEN_SRC}/create-hash-table.ts") +if(NOT BUN_LINK_ONLY) + macro(GENERATE_HASH_LUT _input _output _display_name) + if(NOT NO_CODEGEN) + add_custom_command( + OUTPUT ${_output} + MAIN_DEPENDENCY ${BUN_HASH_LUT_GENERATOR} + DEPENDS ${_input} + COMMAND ${BUN_EXECUTABLE} ${BUN_HASH_LUT_GENERATOR} ${_input} ${_output} + VERBATIM + COMMENT "Generating ${_display_name}" + ) + endif() + list(APPEND BUN_OBJECT_LUT_OUTPUTS "${_output}") + + # list(APPEND Bun_HEADERS ${_output}) + WEBKIT_ADD_SOURCE_DEPENDENCIES(${_input} ${_output}) + endmacro() + + foreach(_file ${BUN_OBJECT_LUT_SOURCES}) + if(NOT EXISTS "${BUN_SRC}/${_file}") + message(FATAL_ERROR "Could not find ${_file} needed for LUT generation") + endif() + + get_filename_component(_name ${_file} NAME_WE) + + # workaround for ZigGlobalObject + if(_name MATCHES "ZigGlobalObject") + set(_name "ZigGlobalObject") + endif() + + GENERATE_HASH_LUT(${BUN_SRC}/${_file} ${BUN_WORKDIR}/codegen/${_name}.lut.h ${_name}.lut.h) + endforeach() + + WEBKIT_ADD_SOURCE_DEPENDENCIES(${BUN_SRC}/bun.js/bindings/ZigGlobalObject.cpp ${BUN_WORKDIR}/codegen/ZigGlobalObject.lut.h) +endif() + +# --- Identifier Cache --- +if(NOT NO_CODEGEN) + set(BUN_IDENTIFIER_CACHE_OUT + "${BUN_SRC}/js_lexer/id_continue_bitset.blob" + "${BUN_SRC}/js_lexer/id_continue_bitset.meta.blob" + "${BUN_SRC}/js_lexer/id_start_bitset.blob" + "${BUN_SRC}/js_lexer/id_start_bitset.meta.blob") + add_custom_command( + OUTPUT ${BUN_IDENTIFIER_CACHE_OUT} + MAIN_DEPENDENCY "${BUN_SRC}/js_lexer/identifier_data.zig" + DEPENDS "${BUN_SRC}/js_lexer/identifier_cache.zig" + COMMAND ${ZIG_COMPILER} run "${BUN_SRC}/js_lexer/identifier_data.zig" + VERBATIM + COMMENT "Building Identifier Cache" + ) +endif() + +# --- Bundled TS/JS --- +# Note: It's not worth doing this in parallel at the CMake/Ninja level, because this bundling +# requires all the JS files to be known, but also Bun will use all cores during bundling anyways. +if(NOT NO_CODEGEN) + file(GLOB BUN_TS_MODULES ${CONFIGURE_DEPENDS} + "${BUN_SRC}/js/node/*.ts" + "${BUN_SRC}/js/node/*.js" + "${BUN_SRC}/js/bun/*.js" + "${BUN_SRC}/js/bun/*.ts" + "${BUN_SRC}/js/thirdparty/*.js" + "${BUN_SRC}/js/thirdparty/*.ts" + "${BUN_SRC}/js/internal/*.js" + "${BUN_SRC}/js/internal/*.ts" + ) + file(GLOB BUN_TS_FUNCTIONS ${CONFIGURE_DEPENDS} "${BUN_SRC}/js/builtins/*.ts") + + file(GLOB CODEGEN_FILES ${CONFIGURE_DEPENDS} "${BUN_CODEGEN_SRC}/*.ts") + + add_custom_command( + OUTPUT + "${BUN_WORKDIR}/codegen/InternalModuleRegistryConstants.h" + "${BUN_WORKDIR}/codegen/InternalModuleRegistry+createInternalModuleById.h" + "${BUN_WORKDIR}/codegen/InternalModuleRegistry+enum.h" + "${BUN_WORKDIR}/codegen/InternalModuleRegistry+numberOfModules.h" + "${BUN_WORKDIR}/codegen/NativeModuleImpl.h" + "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" + "${BUN_WORKDIR}/codegen/SyntheticModuleType.h" + COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-modules.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" + DEPENDS ${BUN_TS_MODULES} ${CODEGEN_FILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Bundling JS modules" + ) +endif() + +WEBKIT_ADD_SOURCE_DEPENDENCIES( + "${BUN_SRC}/bun.js/bindings/InternalModuleRegistry.cpp" + "${BUN_WORKDIR}/codegen/InternalModuleRegistryConstants.h" +) + +add_custom_command( + OUTPUT "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp" + "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.h" + COMMAND ${BUN_EXECUTABLE} "${BUN_SRC}/codegen/bundle-functions.ts" "--debug=${DEBUG}" "${BUN_WORKDIR}" + DEPENDS ${BUN_TS_FUNCTIONS} ${CODEGEN_FILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Bundling JS builtin functions" +) +list(APPEND BUN_RAW_SOURCES "${BUN_WORKDIR}/codegen/WebCoreJSBuiltins.cpp") + +# --- Peechy API --- +# if(NOT NO_CODEGEN) +# add_custom_command( +# OUTPUT "${BUN_SRC}/api/schema.js" +# "${BUN_SRC}/api/schema.d.ts" +# "${BUN_SRC}/api/schema.zig" +# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/.bin/peechy" +# "--schema" "${BUN_SRC}/api/schema.peechy" +# "--esm" "${BUN_SRC}/api/schema.js" +# "--ts" "${BUN_SRC}/api/schema.d.ts" +# "--zig" "${BUN_SRC}/api/schema.zig" +# COMMAND "${ZIG_COMPILER}" "fmt" "src/api/schema.zig" +# COMMAND "${PRETTIER}" "--config=.prettierrc.cjs" "--write" "src/api/schema.js" "src/api/schema.d.ts" +# DEPENDS "${BUN_SRC}/api/schema.peechy" +# COMMENT "Building schema" +# ) +# add_custom_command( +# OUTPUT "${BUN_SRC}/analytics/analytics_schema.zig" +# WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +# COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/node_modules/.bin/peechy" +# "--schema" "${BUN_SRC}/analytics/schema.peechy" +# "--zig" "${BUN_SRC}/analytics/analytics_schema.zig" +# COMMAND "${ZIG_COMPILER}" "fmt" "${BUN_SRC}/analytics/analytics_schema.zig" +# DEPENDS "${BUN_SRC}/api/schema.peechy" +# COMMENT "Building analytics_schema.zig" +# ) +# endif() + +# --- Runtime.js --- +if(NOT NO_CODEGEN) + add_custom_command( + OUTPUT "src/fallback.out.js" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMAND "${ESBUILD}" "--target=esnext" "--bundle" "src/fallback.ts" "--format=iife" "--platform=browser" "--minify" "--outfile=src/fallback.out.js" + DEPENDS "src/fallback.ts" + ) +endif() + +# --- Zig Object --- +file(GLOB ZIG_FILES + "${BUN_SRC}/*.zig" + "${BUN_SRC}/**/*.zig" + "${BUN_SRC}/**/**/*.zig" + "${BUN_SRC}/**/**/**/*.zig" +) + +if(NOT BUN_ZIG_OBJ) + set(BUN_ZIG_OBJ "${BUN_WORKDIR}/CMakeFiles/bun-zig.o") +endif() + +get_filename_component(BUN_ZIG_OBJ "${BUN_ZIG_OBJ}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") + +set(USES_TERMINAL_NOT_IN_CI "") + +if(NOT CI) + set(USES_TERMINAL_NOT_IN_CI "USES_TERMINAL") +endif() + +if(NOT BUN_LINK_ONLY AND NOT BUN_CPP_ONLY) + add_custom_command( + OUTPUT "${BUN_ZIG_OBJ}" + COMMAND + "${ZIG_COMPILER}" "build" "obj" + "-Doutput-file=${BUN_ZIG_OBJ}" + "-Dgenerated-code=${BUN_WORKDIR}/codegen" + "-Dversion=${Bun_VERSION}" + "-Dcanary=${CANARY}" + "-Doptimize=${ZIG_OPTIMIZE}" + "-Dcpu=${CPU_TARGET}" + "-Dtarget=${ZIG_TARGET}" + DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/build.zig" + "${ZIG_FILES}" + "${BUN_WORKDIR}/codegen/ZigGeneratedClasses.zig" + "${BUN_WORKDIR}/codegen/ResolvedSourceTag.zig" + "${BUN_IDENTIFIER_CACHE_OUT}" + "${BUN_SRC}/api/schema.zig" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Building zig code" + VERBATIM + + # This is here to show Zig's progress indicator + ${USES_TERMINAL_NOT_IN_CI} + ) +endif() + +if(WIN32) + list(APPEND BUN_RAW_SOURCES "${BUN_SRC}/bun.js/bindings/windows/musl-memmem.c") + include_directories("${BUN_SRC}/bun.js/bindings/windows") +endif() + +if(NOT BUN_CPP_ARCHIVE) + # TODO: unified sources + set(BUN_SOURCES ${BUN_RAW_SOURCES}) +else() + # used by ci + set(BUN_SOURCES "") + add_link_options("${BUN_CPP_ARCHIVE}") +endif() + +# -- Windows resources (app icon) -- +if(CANARY GREATER 0) + set(Bun_VERSION_WITH_TAG "${Bun_VERSION}-canary.${CANARY}") +else() + set(Bun_VERSION_WITH_TAG "${Bun_VERSION}") +endif() +if(WIN32) + set(BUN_ICO_PATH "${BUN_SRC}/bun.ico") + configure_file("${BUN_SRC}/windows-app-info.rc" "${BUN_WORKDIR}/CMakeFiles/windows-app-info.rc") + list(APPEND BUN_SOURCES "${BUN_WORKDIR}/CMakeFiles/windows-app-info.rc") +endif() + +# -- The Buntime™️ --- +if(NOT BUN_CPP_ONLY) + add_executable(${bun} "${BUN_SOURCES}" "${BUN_ZIG_OBJ}") +else() + add_executable(${bun} "${BUN_SOURCES}") +endif() + +set_target_properties(${bun} PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS YES + CXX_VISIBILITY_PRESET hidden + C_STANDARD 17 + C_STANDARD_REQUIRED YES + VISIBILITY_INLINES_HIDDEN YES +) + +add_compile_definitions( + # TODO: are all of these variables strictly necessary? + "_HAS_EXCEPTIONS=0" + "LIBUS_USE_OPENSSL=1" + "UWS_HTTPRESPONSE_NO_WRITEMARK=1" + "LIBUS_USE_BORINGSSL=1" + "WITH_BORINGSSL=1" + "STATICALLY_LINKED_WITH_JavaScriptCore=1" + "STATICALLY_LINKED_WITH_WTF=1" + "STATICALLY_LINKED_WITH_BMALLOC=1" + "BUILDING_WITH_CMAKE=1" + "JSC_OBJC_API_ENABLED=0" + "BUN_SINGLE_THREADED_PER_VM_ENTRY_SCOPE=1" + "NAPI_EXPERIMENTAL=ON" + "NOMINMAX" + "IS_BUILD" + "BUILDING_JSCONLY__" + "ASSERT_ENABLED=$,1,0>" + "BUN_DYNAMIC_JS_LOAD_PATH=\"${BUN_WORKDIR}/js\"" +) + +if(NOT ASSERT_ENABLED) + add_compile_definitions("NDEBUG=1") +endif() + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/packages/ + ${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets + ${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets/src + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/webcore + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/webcrypto + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/bindings/sqlite + ${CMAKE_CURRENT_SOURCE_DIR}/src/bun.js/modules + ${CMAKE_CURRENT_SOURCE_DIR}/src/js/builtins + ${CMAKE_CURRENT_SOURCE_DIR}/src/napi + ${CMAKE_CURRENT_SOURCE_DIR}/src/deps + ${CMAKE_CURRENT_SOURCE_DIR}/src/deps/picohttpparser + ${WEBKIT_INCLUDE_DIR} + "${BUN_WORKDIR}/codegen" +) + +# -- BUN_CPP_ONLY Target +if(NOT BUN_CPP_ARCHIVE) + if (BUN_CPP_ONLY) + if(NOT WIN32) + string(REPLACE ";" ".o\n " BUN_OBJECT_LIST "${BUN_SOURCES}.o") + string(REPLACE "${BUN_WORKDIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + write_file("${BUN_WORKDIR}/compile-cpp-only.sh" + "#!/usr/bin/env bash\n" + "# this file is generated in CMakeLists.txt\n" + "set -e\n" + "OBJ_LIST=(\n ${BUN_OBJECT_LIST}\n)\n" + "ninja \${OBJ_LIST[@]} $@\n" + "\"${AR}\" rcvs bun-cpp-objects.a \${OBJ_LIST[@]}\n" + "echo '-> bun-cpp-objects.a'\n" + ) + else() + string(REPLACE ";" ".obj\",\n \"" BUN_OBJECT_LIST "\"${BUN_SOURCES}.obj\"") + string(REPLACE "rc.obj" "rc.res" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + string(REPLACE "${BUN_WORKDIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "CMakeFiles/${bun}.dir/" BUN_OBJECT_LIST "${BUN_OBJECT_LIST}") + write_file("${BUN_WORKDIR}/compile-cpp-only.ps1" + "# this file is generated in CMakeLists.txt\n" + "$ErrorActionPreference = \"Stop\"\n" + "$ObjectFiles=@(\n ${BUN_OBJECT_LIST}\n)\n" + "ninja @ObjectFiles @args\n" + "& \"${AR}\" rcvs bun-cpp-objects.a @ObjectFiles\n" + "Write-Host '-> bun-cpp-objects.a'\n" + ) + endif() + endif() +else() + set_target_properties(${bun} PROPERTIES LINKER_LANGUAGE CXX) +endif() + +# --- clang and linker flags --- +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if(NOT WIN32) + target_compile_options(${bun} PUBLIC -g3 -O1 -gdwarf-4) + else() + target_compile_options(${bun} PUBLIC -O1) + endif() + add_compile_definitions("BUN_DEBUG=1") +elseif(CMAKE_BUILD_TYPE STREQUAL "Release") + if(NOT WIN32) + target_compile_options(${bun} PUBLIC -O3 -flto=full -emit-llvm) + else() + target_compile_options(${bun} PUBLIC /O2 -flto=full) + target_link_options(${bun} PUBLIC /LTCG) + endif() +endif() + +if(NOT CI AND NOT WIN32) + target_compile_options(${bun} PRIVATE -fdiagnostics-color=always) +endif() + +target_compile_options(${bun} PUBLIC + -march=${CPU_TARGET} + -ferror-limit=${ERROR_LIMIT} +) + +if(WIN32) + add_compile_definitions( + "WIN32" + "_WINDOWS" + "WIN32_LEAN_AND_MEAN=1" + "_CRT_SECURE_NO_WARNINGS" + "BORINGSSL_NO_CXX=1" # lol + ) + + set_property(TARGET ${bun} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") + target_compile_options(${bun} PUBLIC "/EHsc" "/GR-") + target_link_options(${bun} PUBLIC "/STACK:4194304,2097152") +else() + target_compile_options(${bun} PUBLIC + -fPIC + -mtune=${CPU_TARGET} + -fconstexpr-steps=1271242 + -fconstexpr-depth=27 + -fno-exceptions + -fvisibility=hidden + -fvisibility-inlines-hidden + -fno-rtti + -fno-omit-frame-pointer + ) + string(APPEND CMAKE_CXX_FLAGS " -std=c++2a") +endif() + +if(APPLE) + if(ARCH STREQUAL "x86_64") + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") + else() + set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") + endif() + + target_link_options(${bun} PUBLIC "-dead_strip") + target_link_options(${bun} PUBLIC "-dead_strip_dylibs") + target_link_options(${bun} PUBLIC "-Wl,-stack_size,0x1200000") + target_link_options(${bun} PUBLIC "-exported_symbols_list" "${BUN_SRC}/symbols.txt") + set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.txt") + + target_link_options(${bun} PUBLIC "-fno-keep-static-consts") + target_link_libraries(${bun} PRIVATE "resolv") +endif() + +if(UNIX AND NOT APPLE) + target_link_options(${bun} PUBLIC + "-fuse-ld=lld" + "-static-libstdc++" + "-static-libgcc" + "-fuse-ld=lld" + "-Wl,-z,now" + "-Wl,--as-needed" + "-Wl,--gc-sections" + "-Wl,-z,stack-size=12800000" + "-Wl,--wrap=fcntl" + "-Wl,--wrap=fcntl64" + "-Wl,--wrap=stat64" + "-Wl,--wrap=pow" + "-Wl,--wrap=exp" + "-Wl,--wrap=log" + "-Wl,--wrap=log2" + "-Wl,--wrap=lstat" + "-Wl,--wrap=stat" + "-Wl,--wrap=fstat" + "-Wl,--wrap=fstatat" + "-Wl,--wrap=lstat64" + "-Wl,--wrap=stat64" + "-Wl,--wrap=fstat64" + "-Wl,--wrap=fstatat64" + "-Wl,--wrap=mknod" + "-Wl,--wrap=mknodat" + "-Wl,--wrap=statx" + "-Wl,--compress-debug-sections=zlib" + "-Bsymbolics-functions" + "-rdynamic" + "-Wl,--dynamic-list=${BUN_SRC}/symbols.dyn" + "-Wl,--version-script=${BUN_SRC}/linker.lds" + ) + + target_link_libraries(${bun} PRIVATE "c") + target_link_libraries(${bun} PRIVATE "pthread") + target_link_libraries(${bun} PRIVATE "dl") + + if(NOT USE_STATIC_LIBATOMIC) + target_link_libraries(${bun} PUBLIC "libatomic.so") + else() + target_link_libraries(${bun} PRIVATE "libatomic.a") + endif() + + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicudata.a") + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicui18n.a") + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libicuuc.a") + + set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/linker.lds") + set_target_properties(${bun} PROPERTIES LINK_DEPENDS "${BUN_SRC}/symbols.dyn") +endif() + +# --- ICU --- +if(APPLE) + # TODO: a much better check can be done to find this path + find_path( + ICU4C_DIR NAMES lib/libicudata.a + PATHS ENV PATH /usr/local/opt/icu4c /opt/homebrew/opt/icu4c + ) + find_path( + ICONV_DIR NAMES lib/libiconv.a + PATHS ENV PATH /usr/local/opt/libiconv /opt/homebrew/opt/libiconv + ) + + target_link_libraries(${bun} PRIVATE "icucore") + target_link_libraries(${bun} PRIVATE "${ICONV_DIR}/lib/libiconv.a") + target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicudata.a") + target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicui18n.a") + target_link_libraries(${bun} PRIVATE "${ICU4C_DIR}/lib/libicuuc.a") + include_directories(${ICU4C_DIR}/include) +endif() + +# --- Stripped Binary "bun" +if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32) + # add_custom_command( + # TARGET ${bun} + # POST_BUILD + # COMMAND ${DSYMUTIL} -o ${BUN_WORKDIR}/bun.dSYM ${BUN_WORKDIR}/${bun} + # COMMENT "Stripping Symbols" + # ) + add_custom_command( + TARGET ${bun} + POST_BUILD + COMMAND ${STRIP} -s -x -S -o ${BUN_WORKDIR}/bun ${BUN_WORKDIR}/${bun} + COMMENT "Stripping Symbols" + ) +endif() + +if(WIN32) + # Kill all instances of bun before linking. + add_custom_command( + TARGET ${bun} + PRE_BUILD + COMMAND + "powershell" + "/C" + "Stop-Process -Name '${bun}' -Force -ErrorAction SilentlyContinue; exit 0" + ) +endif() + +# --- Dependencies --- +if(USE_CUSTOM_ZLIB) + include_directories(${BUN_DEPS_DIR}/zlib) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/zlib.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libz.a") + endif() +else() + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_DIR}/zlib_maybethisworks.lib") + else() + find_package(ZLIB REQUIRED) + target_link_libraries(${bun} PRIVATE ZLIB::ZLIB) + endif() +endif() + +if(USE_CUSTOM_BORINGSSL) + include_directories(${BUN_DEPS_DIR}/boringssl/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/crypto.lib") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/ssl.lib") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/decrepit.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libcrypto.a") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libssl.a") + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libdecrepit.a") + endif() +else() + include(FindBoringSSL) + FindBoringSSL(${bun}) +endif() + +if(USE_CUSTOM_LIBARCHIVE) + include_directories(${BUN_DEPS_DIR}/libarchive/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/archive.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libarchive.a") + endif() +else() + find_package(LibArchive REQUIRED) + target_link_libraries(${bun} PRIVATE LibArchive::LibArchive) +endif() + +if(USE_CUSTOM_MIMALLOC) + include_directories(${BUN_DEPS_DIR}/mimalloc/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/mimalloc.lib") + elseif(APPLE) + # https://github.com/microsoft/mimalloc/issues/512 + # Linking mimalloc via object file on macOS x64 can cause heap corruption + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc.a") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libmimalloc.o") + endif() +else() + find_package(mimalloc REQUIRED) + target_link_libraries(${bun} PRIVATE mimalloc) +endif() + +if(USE_CUSTOM_ZSTD) + include_directories(${BUN_DEPS_DIR}/zstd/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/zstd.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libzstd.a") + endif() +else() + find_package(zstd CONFIG REQUIRED) + target_link_libraries(${bun} PRIVATE zstd::libzstd) +endif() + +if(USE_CUSTOM_CARES) + include_directories(${BUN_DEPS_DIR}/c-ares/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/cares.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libcares.a") + endif() +else() + find_package(c-ares CONFIG REQUIRED) + target_link_libraries(${bun} PRIVATE c-ares::cares) +endif() + +if(USE_CUSTOM_BASE64) + include_directories(${BUN_DEPS_DIR}/base64/include) + + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/base64.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libbase64.a") + endif() +else() + find_package(base64 REQUIRED) + target_link_libraries(${bun} PRIVATE base64::base64) +endif() + +if(NOT WIN32) + if(USE_CUSTOM_TINYCC) + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/tcc.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libtcc.a") + endif() + else() + find_package(tinycc REQUIRED) + target_link_libraries(${bun} PRIVATE tinycc::tinycc) + endif() +endif() + +if(USE_CUSTOM_LOLHTML) + if(WIN32) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/lolhtml.lib") + else() + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/liblolhtml.a") + endif() +else() + find_package(lolhtml REQUIRED) + target_link_libraries(${bun} PRIVATE lolhtml::lolhtml) +endif() + +if(WIN32) + if(USE_CUSTOM_LIBUV) + target_link_libraries(${bun} PRIVATE "${BUN_DEPS_OUT_DIR}/libuv.lib") + include_directories(${bun} PRIVATE "${BUN_DEPS_DIR}/libuv/include") + else() + find_package(libuv CONFIG REQUIRED) + target_link_libraries(${bun} PRIVATE $,libuv::uv_a,libuv::uv>) + endif() +endif() + +if(USE_STATIC_SQLITE) + add_library(sqlite3 STATIC src/bun.js/bindings/sqlite/sqlite3.c) + target_include_directories(sqlite3 PUBLIC src/bun.js/bindings/sqlite) + target_compile_definitions(sqlite3 PRIVATE + "SQLITE_ENABLE_COLUMN_METADATA=" + "SQLITE_MAX_VARIABLE_NUMBER=250000" + "SQLITE_ENABLE_RTREE=1" + "SQLITE_ENABLE_FTS3=1" + "SQLITE_ENABLE_FTS3_PARENTHESIS=1" + "SQLITE_ENABLE_FTS5=1" + "SQLITE_ENABLE_JSON1=1" + ) + target_link_libraries(${bun} PRIVATE sqlite3) + message(STATUS "Using static sqlite3") + target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=0") +else() + message(STATUS "Using dynamicly linked sqlite3") + target_compile_definitions(${bun} PRIVATE "LAZY_LOAD_SQLITE=1") +endif() + +if(NOT WIN32) + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libWTF.a") + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libJavaScriptCore.a") + target_link_libraries(${bun} PRIVATE "${WEBKIT_LIB_DIR}/libbmalloc.a") +else() + target_link_options(${bun} PRIVATE "-static") + target_link_libraries(${bun} PRIVATE + "${WEBKIT_LIB_DIR}/WTF.lib" + "${WEBKIT_LIB_DIR}/JavaScriptCore.lib" + "${WEBKIT_LIB_DIR}/sicudt.lib" + "${WEBKIT_LIB_DIR}/sicuin.lib" + "${WEBKIT_LIB_DIR}/sicuuc.lib" + winmm + bcrypt + ntdll + ucrt + userenv + dbghelp + ) +endif() + +if(BUN_LINK_ONLY) + message(STATUS "NOTE: BUN_LINK_ONLY is ON, this build config will only link the Bun executable") +endif() +if(BUN_CPP_ONLY) + message(STATUS "NOTE: BUN_CPP_ONLY is ON, this build will only work with 'compile-cpp-only.${SCRIPT_EXTENSION}'") +endif() +if(NO_CODEGEN) + message(STATUS "NOTE: NO_CODEGEN is ON, this build expects ./codegen to exist") +endif() diff --git a/Dockerfile b/Dockerfile index 80a0aa6cb5..90d49ea22c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,7 @@ ARG BUILDARCH=amd64 ARG TRIPLET=${ARCH}-linux-gnu ARG GIT_SHA="unknown" ARG BUN_DOWNLOAD_URL_BASE="https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/latest" +ARG CANARY=0 ARG BUN_VERSION="1.0.7" ARG NODE_VERSION="20" @@ -318,6 +319,8 @@ RUN mkdir ${BUN_DIR}/bun-webkit \ FROM bun-base as bun-cpp-objects +ARG CANARY + COPY --from=bun-webkit ${BUN_DIR}/bun-webkit ${BUN_DIR}/bun-webkit COPY packages ${BUN_DIR}/packages @@ -330,7 +333,7 @@ ENV CCACHE_DIR=/ccache RUN --mount=type=cache,target=/ccache mkdir ${BUN_DIR}/build \ && cd ${BUN_DIR}/build \ && mkdir -p tmp_modules tmp_functions js codegen \ - && cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUN_CPP_ONLY=1 -DWEBKIT_DIR=/build/bun/bun-webkit \ + && cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBUN_CPP_ONLY=1 -DWEBKIT_DIR=/build/bun/bun-webkit -DCANARY=${CANARY} \ && bash compile-cpp-only.sh FROM bun-base-with-zig as bun-codegen-for-zig @@ -355,6 +358,7 @@ ARG ZIG_PATH ARG TRIPLET ARG GIT_SHA ARG CPU_TARGET +ARG CANARY=0 COPY *.zig package.json CMakeLists.txt ${BUN_DIR}/ COPY completions ${BUN_DIR}/completions @@ -380,8 +384,8 @@ RUN mkdir -p build \ -DNO_CONFIGURE_DEPENDS=1 \ -DNO_CODEGEN=1 \ -DBUN_ZIG_OBJ="/tmp/bun-zig.o" \ - && ONLY_ZIG=1 ninja "/tmp/bun-zig.o" \ - && echo "-> /tmp/bun-zig.o" + -DCANARY="${CANARY}" \ + && ONLY_ZIG=1 ninja "/tmp/bun-zig.o" FROM scratch as build_release_obj @@ -393,6 +397,8 @@ COPY --from=bun-compile-zig-obj /tmp/bun-zig.o / FROM bun-base as bun-link ARG CPU_TARGET +ARG CANARY + ENV CPU_TARGET=${CPU_TARGET} WORKDIR $BUN_DIR @@ -428,6 +434,9 @@ RUN cmake .. \ -DBUN_CPP_ARCHIVE="${BUN_DIR}/build/bun-cpp-objects.a" \ -DWEBKIT_DIR="${BUN_DIR}/bun-webkit" \ -DBUN_DEPS_OUT_DIR="${BUN_DEPS_OUT_DIR}" \ + -DCPU_TARGET="${CPU_TARGET}" \ + -DNO_CONFIGURE_DEPENDS=1 \ + -DCANARY="${CANARY}" \ && ninja \ && mkdir -p /build/out \ && mv bun bun-profile /build/out \ diff --git a/Makefile b/Makefile index e542eb5813..61a9d335ed 100644 --- a/Makefile +++ b/Makefile @@ -1909,29 +1909,29 @@ vendor-dev: assert-deps submodule npm-install-dev vendor-without-npm .PHONY: bun bun: - echo makefile is deprecated - use `cmake` / `bun run build` - echo 'See https://bun.sh/docs/project/contributing for more details' + @echo 'makefile is deprecated - use `cmake` / `bun run build`' + @echo 'See https://bun.sh/docs/project/contributing for more details' cpp: - echo makefile is deprecated - use `cmake` / `bun run build` - echo 'See https://bun.sh/docs/project/contributing for more details' + @echo 'makefile is deprecated - use `cmake` / `bun run build`' + @echo 'See https://bun.sh/docs/project/contributing for more details' zig: - echo makefile is deprecated - use `cmake` / `bun run build` - echo 'See https://bun.sh/docs/project/contributing for more details' + @echo 'makefile is deprecated - use `cmake` / `bun run build`' + @echo 'See https://bun.sh/docs/project/contributing for more details' dev: - echo makefile is deprecated - use `cmake` / `bun run build` - echo 'See https://bun.sh/docs/project/contributing for more details' + @echo 'makefile is deprecated - use `cmake` / `bun run build`' + @echo 'See https://bun.sh/docs/project/contributing for more details' setup: - echo makefile is deprecated - use `cmake` / `bun run build` - echo 'See https://bun.sh/docs/project/contributing for more details' + @echo 'makefile is deprecated - use `cmake` / `bun run build`' + @echo 'See https://bun.sh/docs/project/contributing for more details' bindings: - echo makefile is deprecated - use `cmake` / `bun run build` - echo 'See https://bun.sh/docs/project/contributing for more details' + @echo 'makefile is deprecated - use `cmake` / `bun run build`' + @echo 'See https://bun.sh/docs/project/contributing for more details' help: - echo makefile is deprecated - use `cmake` / `bun run build` - echo 'See https://bun.sh/docs/project/contributing for more details' + @echo 'makefile is deprecated - use `cmake` / `bun run build`' + @echo 'See https://bun.sh/docs/project/contributing for more details' diff --git a/build.zig b/build.zig index 5b094713fe..747b2404e1 100644 --- a/build.zig +++ b/build.zig @@ -82,7 +82,8 @@ fn addInternalPackages(b: *Build, step: *CompileStep, _: std.mem.Allocator, _: [ } const BunBuildOptions = struct { - canary: bool = false, + is_canary: bool = false, + canary_revision: u32 = 0, sha: [:0]const u8 = "", version: []const u8 = "", baseline: bool = false, @@ -125,7 +126,8 @@ const BunBuildOptions = struct { pub fn step(this: BunBuildOptions, b: anytype) *std.build.OptionsStep { var opts = b.addOptions(); - opts.addOption(@TypeOf(this.canary), "is_canary", this.canary); + opts.addOption(@TypeOf(this.is_canary), "is_canary", this.is_canary); + opts.addOption(@TypeOf(this.canary_revision), "canary_revision", this.canary_revision); opts.addOption( std.SemanticVersion, "version", @@ -333,11 +335,16 @@ pub fn build_(b: *Build) !void { } } - const is_canary = - b.option(bool, "canary", "Treat this as a canary build") orelse - ((b.env_map.get("BUN_CANARY") orelse "0")[0] == '1'); + const is_canary, const canary_revision = if (b.option(u32, "canary", "Treat this as a canary build")) |rev| + if (rev == 0) + .{ false, 0 } + else + .{ true, rev } + else + .{ false, 0 }; break :brk .{ - .canary = is_canary, + .is_canary = is_canary, + .canary_revision = canary_revision, .version = b.option([]const u8, "version", "Value of `Bun.version`") orelse "0.0.0", .sha = git_sha, .baseline = is_baseline, diff --git a/bun.lockb b/bun.lockb index 6116d7891d14859c5b1bd82d8dcd54172f4066f0..c6d9f15ae5f5e9f6c2593ee45f154546db6e4168 100755 GIT binary patch delta 8063 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 delta 8127 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 diff --git a/docs/installation.md b/docs/installation.md index 6aa51737a6..e2de4212a6 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -82,7 +82,7 @@ To see the precise commit of [oven-sh/bun](https://github.com/oven-sh/bun) that ```sh $ bun --revision -1.x.y+b7982ac1318937560f38e0f8eb18f45eaa43480f +1.x.y+b7982ac13189 ``` If you've installed Bun but are seeing a `command not found` error, you may have to manually add the installation directory (`~/.bun/bin`) to your `PATH`. diff --git a/docs/project/building-windows.md b/docs/project/building-windows.md index 8f6f0ec911..f3d0456e05 100644 --- a/docs/project/building-windows.md +++ b/docs/project/building-windows.md @@ -2,14 +2,28 @@ ### System Dependencies -- [Visual Studio](https://visualstudio.microsoft.com) with the "Desktop development with C++" workload. You should install Git and CMake from here, if not already installed. +- [Visual Studio](https://visualstudio.microsoft.com) with the "Desktop Development with C++" workload. You should install Git and CMake from here, if not already installed. - Ninja - Go - Rust - NASM - Perl - - Do not use Strawberry Perl, it includes tools from MSys2 which will break your build. - Ruby +- Node.js (until bun runs stably on windows) + + + +### Enable Scripts + +By default, scripts are blocked. + +```ps1 +Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted +``` ### Zig diff --git a/packages/bun-usockets/src/eventing/libuv.c b/packages/bun-usockets/src/eventing/libuv.c index 4bb76f8024..db65902e5c 100644 --- a/packages/bun-usockets/src/eventing/libuv.c +++ b/packages/bun-usockets/src/eventing/libuv.c @@ -247,7 +247,7 @@ void *us_timer_ext(struct us_timer_t *timer) { sizeof(uv_timer_t); } -void us_timer_close(struct us_timer_t *t) { +void us_timer_close(struct us_timer_t *t, int fallthrough) { struct us_internal_callback_t *cb = (struct us_internal_callback_t *)t; uv_timer_t *uv_timer = (uv_timer_t *)(cb + 1); diff --git a/scripts/all-dependencies.sh b/scripts/all-dependencies.sh index 48c367b9bb..c2e2a17dc2 100755 --- a/scripts/all-dependencies.sh +++ b/scripts/all-dependencies.sh @@ -1,3 +1,4 @@ +#!/usr/bin/env bash set -euo pipefail source "$(dirname -- "${BASH_SOURCE[0]}")/env.sh" FORCE= diff --git a/scripts/build-libarchive.ps1 b/scripts/build-libarchive.ps1 index e85b8ba9db..62983b8696 100644 --- a/scripts/build-libarchive.ps1 +++ b/scripts/build-libarchive.ps1 @@ -8,7 +8,7 @@ try { Run cmake @CMAKE_FLAGS -DBUILD_SHARED_LIBS=OFF -DENABLE_TEST=OFF -DENABLE_INSTALL=OFF -DENABLE_WERROR=0 .. Run cmake --build . --clean-first --config Release - Copy-Item libarchive\archive.lib $BUN_DEPS_OUT_DIR + Copy-Item libarchive\archive_static.lib $BUN_DEPS_OUT_DIR\archive.lib Write-Host "-> libarchive.lib" } finally { diff --git a/scripts/build-libuv.ps1 b/scripts/build-libuv.ps1 index 9a10121d83..82adfa8449 100644 --- a/scripts/build-libuv.ps1 +++ b/scripts/build-libuv.ps1 @@ -1,3 +1,7 @@ +param( + [bool] $CloneOnly = $false +) + $ErrorActionPreference = 'Stop' # Setting strict mode, similar to 'set -euo pipefail' in bash . (Join-Path $PSScriptRoot "env.ps1") $CWD = Get-Location @@ -27,14 +31,16 @@ if (!(Test-Path -PathType Container $Source)) { } finally { Pop-Location } } -Push-Location $Source -try { - $null = mkdir build -ErrorAction SilentlyContinue - Set-Location build - - Run cmake .. @CMAKE_FLAGS "-DCMAKE_C_FLAGS=/DWIN32 /D_WINDOWS -Wno-int-conversion" - Run cmake --build . --clean-first --config Release +if(!($CloneOnly)) { + Push-Location $Source + try { + $null = mkdir build -ErrorAction SilentlyContinue + Set-Location build + + Run cmake .. @CMAKE_FLAGS "-DCMAKE_C_FLAGS=/DWIN32 /D_WINDOWS -Wno-int-conversion" + Run cmake --build . --clean-first --config Release - Copy-Item libuv.lib $BUN_DEPS_OUT_DIR - Write-Host "-> libuv.lib" -} finally { Pop-Location } + Copy-Item libuv.lib $BUN_DEPS_OUT_DIR + Write-Host "-> libuv.lib" + } finally { Pop-Location } +} diff --git a/scripts/calculate-canary-revision.sh b/scripts/calculate-canary-revision.sh new file mode 100755 index 0000000000..754b2baabd --- /dev/null +++ b/scripts/calculate-canary-revision.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +if [ -z "$GITHUB_TOKEN" ]; then + echo "GITHUB_TOKEN is not set" + exit 1 +fi + +query="\"query{repository(owner:\\\"oven-sh\\\",name:\\\"bun\\\"){releases(first:1){edges{node{tagName}}}}}\"" +tagName=$(curl -fsSL "https://api.github.com/graphql" -X POST -d '{"query":'${query}'}' \ + -H "Authorization: bearer ${GITHUB_TOKEN}" -H "Content-Type: application/json" \ + | jq -r '.data.repository.releases.edges[0].node.tagName') + +if [ -z "$headRef" ]; then + headRef=$(git rev-parse HEAD) +fi + +query="\"query{repository(owner:\\\"oven-sh\\\",name:\\\"bun\\\"){ref(qualifiedName:\\\"${tagName}\\\"){compare(headRef:\\\"${headRef}\\\"){aheadBy}}}}\"" +aheadBy=$(curl -fsSL "https://api.github.com/graphql" -X POST -d '{"query":'${query}'}' \ + -H "Authorization: bearer ${GITHUB_TOKEN}" -H "Content-Type: application/json" \ + | jq -r '.data.repository.ref.compare.aheadBy') + +if [ "$1" == '--raw' ]; then + if [ "$aheadBy" == "null" ]; then + echo "1" + else + echo "${aheadBy}" + fi +else + echo "Latest version is ${tagName}" + if [ "$aheadBy" == "null" ]; then + echo "Current commit is not available on GitHub.com" + else + echo "Ahead by ${aheadBy} commits." + fi + echo "(call script with --raw to print just a number)" +fi \ No newline at end of file diff --git a/scripts/clean-dependencies.sh b/scripts/clean-dependencies.sh index 0c8b54c9bf..b56919f879 100755 --- a/scripts/clean-dependencies.sh +++ b/scripts/clean-dependencies.sh @@ -1,3 +1,4 @@ +#!/usr/bin/env bash FORCE= SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) diff --git a/scripts/cross-compile-codegen.sh b/scripts/cross-compile-codegen.sh index 2fb1d8488b..ee17496c5f 100755 --- a/scripts/cross-compile-codegen.sh +++ b/scripts/cross-compile-codegen.sh @@ -6,14 +6,30 @@ export TARGET_ARCH=${2:-x64} cd "$(dirname "${BASH_SOURCE[0]}")/../" -OUT=$(realpath build-codegen-${TARGET_PLATFORM}-${TARGET_ARCH}) +OUT=build-codegen-${TARGET_PLATFORM}-${TARGET_ARCH} rm -rf "$OUT" mkdir -p "$OUT" +mkdir -p "$OUT/"{codegen,js,tmp_functions,tmp_modules} -bun ./src/codegen/bundle-functions.ts --debug=OFF "$OUT" & +OUT=$(realpath "$OUT") -bun ./src/codegen/bundle-modules.ts --debug=OFF "$OUT" & +task() { + echo '$ '"$@" + "$@" + if [ "$?" != "0" ]; then + # some scripts are flaky, run them again + echo "!!! retrying" + "$@" + if [ "$?" != "0" ]; then + echo "!!! failed" + exit 1 + fi + fi +} + +task bun ./src/codegen/bundle-functions.ts --debug=OFF "$OUT" +task bun ./src/codegen/bundle-modules.ts --debug=OFF "$OUT" rm -rf "$OUT/tmp_functions" rm -rf "$OUT/tmp_modules" @@ -25,7 +41,7 @@ CLASSES=( ./src/bun.js/webcore/*.classes.ts ./src/bun.js/node/*.classes.ts ) -bun "./src/codegen/generate-classes.ts" ${CLASSES[@]} "$OUT/codegen" & +task bun "./src/codegen/generate-classes.ts" ${CLASSES[@]} "$OUT/codegen" LUTS=( ./src/bun.js/bindings/BunObject.cpp @@ -36,10 +52,12 @@ LUTS=( ./src/bun.js/bindings/ProcessBindingNatives.cpp ) for lut in ${LUTS[@]}; do - result=$(basename $lut | sed 's/.lut.txt/.cpp/' | sed 's/.cpp/.h/') - echo bun "./src/codegen/create-hash-table.ts" "$lut" "$OUT/codegen/$result" + result=$(basename $lut | sed 's/.lut.txt/.cpp/' | sed 's/.cpp/.lut.h/') + task bun "./src/codegen/create-hash-table.ts" "$lut" "$OUT/codegen/$result" done +task bun "./src/codegen/generate-jssink.ts" "$OUT/codegen" + wait rm -rf "$OUT/tmp"* diff --git a/scripts/download-webkit.ps1 b/scripts/download-webkit.ps1 index b25871c076..b2b504cd49 100644 --- a/scripts/download-webkit.ps1 +++ b/scripts/download-webkit.ps1 @@ -8,7 +8,7 @@ param ( $ErrorActionPreference = "Stop" $Url = "https://github.com/oven-sh/WebKit/releases/download/autobuild-$Tag/$PackageName.tar.gz" -$CacheDir = (mkdir -Force (Join-Path $PSScriptRoot "../.webkit-cache")) +$CacheDir = (mkdir -Force (Join-Path $PSScriptRoot "../.cache")) $TarPath = Join-Path $CacheDir "$PackageName-$Tag.tar.gz" if (Test-Path $OutDir\.tag) { diff --git a/scripts/download-webkit.sh b/scripts/download-webkit.sh index 78ef76e342..b257a77fe3 100644 --- a/scripts/download-webkit.sh +++ b/scripts/download-webkit.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e OUTDIR="$1" @@ -18,12 +18,21 @@ if [ -z "$PKG" ]; then exit 1 fi -mkdir -p "$OUTDIR" url="https://github.com/oven-sh/WebKit/releases/download/autobuild-$TAG/$PKG.tar.gz" -tar_dir="$(dirname "$0")/../.webkit-cache" + +old_tar_dir="$(dirname "$0")/../.webkit-cache" +tar_dir="$(dirname "$0")/../.cache" +if [ -d "$old_tar_dir" ]; then + # migration step from the old system + mkdir "$tar_dir" + mv "$old_tar_dir"/* "$tar_dir" + rm -r "$old_tar_dir" +fi + tar="$tar_dir/$PKG-$TAG.tar.gz" +mkdir -p "$OUTDIR" mkdir -p "$tar_dir" # TODO: Remove this block, future builds may not include a package.json @@ -52,6 +61,6 @@ if [ ! -f "$tar" ]; then fi fi -tar -xzf "$tar" -C "$(dirname "$OUTDIR")" +tar -xzf "$tar" -C "$(dirname "$OUTDIR")" || (rm "$tar" && exit 1) echo "$TAG" > "$OUTDIR/.tag" diff --git a/scripts/env.ps1 b/scripts/env.ps1 index 16d8bbe3c6..5429f1ac2c 100644 --- a/scripts/env.ps1 +++ b/scripts/env.ps1 @@ -10,7 +10,7 @@ if ($env:VSINSTALLDIR -eq $null) { if ($vsDir -eq $null) { throw "Visual Studio directory not found." } - Push-Location $vsDir + Push-Location $vsDir.FullName try { . (Join-Path -Path $vsDir.FullName -ChildPath "Common7\Tools\Launch-VsDevShell.ps1") -Arch amd64 -HostArch amd64 } finally { Pop-Location } diff --git a/scripts/env.sh b/scripts/env.sh index 4f3974d094..768cf1ea75 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -1,3 +1,4 @@ +#!/usr/bin/env bash # this is the environment script for building bun's dependencies # it sets c compiler and flags export SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) diff --git a/scripts/make-old-js.ps1 b/scripts/make-old-js.ps1 new file mode 100644 index 0000000000..761bfb9ec9 --- /dev/null +++ b/scripts/make-old-js.ps1 @@ -0,0 +1,35 @@ +$npm_client = "npm" + +& ${npm_client} i + +$root = Join-Path (Split-Path -Path $MyInvocation.MyCommand.Definition -Parent) "..\" +$esbuild = Join-Path $root "node_modules\.bin\esbuild" + +$env:NODE_ENV = "production" + +# runtime.js +& ${esbuild} "--define:process.env.NODE_ENV=`"production`"" --target=esnext --bundle src/runtime/index.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.js +Add-Content src/runtime.out.js (Get-Content src/runtime.footer.js) +& ${esbuild} "--define:process.env.NODE_ENV=`"production`"" --target=esnext --bundle src/runtime/index-with-refresh.ts --format=iife --platform=browser --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.out.refresh.js +Add-Content src/runtime.out.refresh.js (Get-Content src/runtime.footer.with-refresh.js) +& ${esbuild} "--define:process.env.NODE_ENV=`"production`"" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.node.pre.out.js +Add-Content src/runtime.node.out.js (Get-Content src/runtime.node.pre.out.js) +Add-Content src/runtime.node.out.js (Get-Content src/runtime.footer.node.js) +& ${esbuild} "--define:process.env.NODE_ENV=`"production`"" --target=esnext --bundle src/runtime/index-without-hmr.ts --format=iife --platform=node --global-name=BUN_RUNTIME --minify --external:/bun:* > src/runtime.bun.pre.out.js +Add-Content src/runtime.bun.out.js (Get-Content src/runtime.node.pre.out.js) +Add-Content src/runtime.bun.out.js (Get-Content src/runtime.footer.node.js) + +# fallback_decoder +& ${esbuild} --target=esnext --bundle src/fallback.ts --format=iife --platform=browser --minify > src/fallback.out.js + +# bun-error +Push-Location packages\bun-error +& ${npm_client} install +& ${npm_client} run build +Pop-Location + +# node-fallbacks +Push-Location src\node-fallbacks +& ${npm_client} install +& ${esbuild} --bundle @(Get-Item .\*.js) --outdir=out --format=esm --minify --platform=browser +Pop-Location diff --git a/scripts/setup-zig.ps1 b/scripts/setup-zig.ps1 new file mode 100644 index 0000000000..1e9fbaa1f8 --- /dev/null +++ b/scripts/setup-zig.ps1 @@ -0,0 +1,7 @@ +# TODO(@paperdave): finalize this script out +$ZigVersion = "0.12.0-dev.1297+a9e66ed73" + +$Url = "https://ziglang.org/builds/zig-windows-x86_64-${ZigVersion}.zip" + +Invoke-WebRequest $Url -OutFile .cache\zig-${ZigVersion}.zip +Expand-Archive zig-${ZigVersion}.zip diff --git a/scripts/update-submodules.ps1 b/scripts/update-submodules.ps1 new file mode 100755 index 0000000000..0cc3286bc9 --- /dev/null +++ b/scripts/update-submodules.ps1 @@ -0,0 +1,16 @@ +$ErrorActionPreference = 'Stop' +$ScriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +Push-Location (Join-Path $ScriptDir '..') +try { + $Names = Get-Content .gitmodules | Select-String 'path = (.*)' | ForEach-Object { $_.Matches.Groups[1].Value } + + # we will exclude webkit unless you explicity clone it yourself (a huge download) + if (-not (Test-Path "src/bun.js/WebKit/.git")) { + $Names = $Names | Where-Object { $_ -ne 'src/bun.js/WebKit' } + } + + git submodule update --init --recursive --progress --depth 1 --checkout @NAMES + if ($LASTEXITCODE -ne 0) { + throw "git submodule update failed" + } +} finally { Pop-Location } \ No newline at end of file diff --git a/scripts/update-submodules.sh b/scripts/update-submodules.sh index 7dbb34c14f..62995685e0 100755 --- a/scripts/update-submodules.sh +++ b/scripts/update-submodules.sh @@ -1,5 +1,5 @@ - -cd -- "$(dirname -- "${BASH_SOURCE[0]}")" +#!/usr/bin/env bash +cd "$(dirname "${BASH_SOURCE[0]}")" cd .. NAMES=$(cat .gitmodules | grep 'path = ' | awk '{print $3}') diff --git a/src/__global.zig b/src/__global.zig index 8ef9784be8..23e68bec8a 100644 --- a/src/__global.zig +++ b/src/__global.zig @@ -9,39 +9,46 @@ const bun = @import("root").bun; const version_string = Environment.version_string; +/// Does not have the canary tag, because it is exposed in `Bun.version` +/// "1.0.0" or "1.0.0-debug" pub const package_json_version = if (Environment.isDebug) - version_string ++ "_debug" + version_string ++ "-debug" else version_string; +/// This is used for `bun` without any arguments, it `package_json_version` but with canary if it is a canary build. +/// like "1.0.0-canary.12" +pub const package_json_version_with_canary = if (Environment.isDebug) + version_string ++ "-debug" +else if (Environment.is_canary) + std.fmt.comptimePrint("{s}-canary.{d}", .{ version_string, Environment.canary_revision }) +else + version_string; + +/// The version and a short hash in parenthesis. pub const package_json_version_with_sha = if (Environment.git_sha.len == 0) package_json_version else if (Environment.isDebug) - std.fmt.comptimePrint("{s}_debug ({s})", .{ version_string, Environment.git_sha[0..@min(Environment.git_sha.len, 8)] }) + std.fmt.comptimePrint("{s} ({s})", .{ version_string, Environment.git_sha[0..@min(Environment.git_sha.len, 8)] }) +else if (Environment.is_canary) + std.fmt.comptimePrint("{s}-canary.{d} ({s})", .{ version_string, Environment.canary_revision, Environment.git_sha[0..@min(Environment.git_sha.len, 8)] }) else std.fmt.comptimePrint("{s} ({s})", .{ version_string, Environment.git_sha[0..@min(Environment.git_sha.len, 8)] }); +/// What is printed by `bun --revision` +/// "1.0.0+abcdefghi" or "1.0.0-canary.12+abcdefghi" pub const package_json_version_with_revision = if (Environment.git_sha.len == 0) package_json_version else if (Environment.isDebug) - std.fmt.comptimePrint(version_string ++ "-debug+{s}", .{Environment.git_sha}) + std.fmt.comptimePrint(version_string ++ "-debug+{s}", .{Environment.git_sha_short}) else if (Environment.is_canary) - std.fmt.comptimePrint(version_string ++ "-canary+{s}", .{Environment.git_sha}) + std.fmt.comptimePrint(version_string ++ "-canary.{d}+{s}", .{ Environment.canary_revision, Environment.git_sha_short }) else if (Environment.isTest) - std.fmt.comptimePrint(version_string ++ "-test+{s}", .{Environment.git_sha}) + std.fmt.comptimePrint(version_string ++ "-test+{s}", .{Environment.git_sha_short}) else - std.fmt.comptimePrint(version_string ++ "+{s}", .{Environment.git_sha}); + std.fmt.comptimePrint(version_string ++ "+{s}", .{Environment.git_sha_short}); -pub const os_name = if (Environment.isWindows) - "win32" -else if (Environment.isMac) - "darwin" -else if (Environment.isLinux) - "linux" -else if (Environment.isWasm) - "wasm" -else - "unknown"; +pub const os_name = Environment.os.nameString(); pub const arch_name = if (Environment.isX64) "x64" diff --git a/src/bun.ico b/src/bun.ico new file mode 100644 index 0000000000000000000000000000000000000000..8e08cb1b3618f1122f15ab53096ff067056d9198 GIT binary patch literal 270622 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 literal 0 HcmV?d00001 diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit index af34f971a4..7cd84abfa7 160000 --- a/src/bun.js/WebKit +++ b/src/bun.js/WebKit @@ -1 +1 @@ -Subproject commit af34f971a48a8a689f9858731b0e6478d946bd4a +Subproject commit 7cd84abfa787e4b96b27c3ef1e28a4eb1aa49aa1 diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 258238d374..1c91173d93 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -929,7 +929,7 @@ pub const Listener = struct { exception.* = err.toErrorInstance(globalObject).asObjectRef(); return .zero; }; - + var connection: Listener.UnixOrHost = if (port) |port_| .{ .host = .{ .host = (hostname_or_unix.cloneIfNeeded(bun.default_allocator) catch unreachable).slice(), .port = port_ }, } else .{ diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 865ff34287..ae1126b28f 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -1782,7 +1782,7 @@ pub const Subprocess = struct { } pub fn onWaitPid(this: *Subprocess, sync: bool, this_jsvalue: JSC.JSValue, waitpid_result_: JSC.Maybe(PosixSpawn.WaitPidResult)) void { - if(Environment.isWindows) { + if (Environment.isWindows) { @panic("windows doesnt support subprocess yet. haha"); } defer if (sync) this.updateHasPendingActivity(); diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index c8269e1f63..11a1cf5c4d 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -1037,6 +1037,10 @@ static JSValue constructProcessDisconnect(VM& vm, JSObject* processObject) } } +#if OS(WINDOWS) +#define getpid _getpid +#endif + static JSValue constructPid(VM& vm, JSObject* processObject) { return jsNumber(getpid()); @@ -1045,7 +1049,7 @@ static JSValue constructPid(VM& vm, JSObject* processObject) static JSValue constructPpid(VM& vm, JSObject* processObject) { #if OS(WINDOWS) - return jsUndefined(); + return jsNumber(0); #else return jsNumber(getppid()); #endif diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 97dfcb100b..519a828e5b 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -452,11 +452,7 @@ static String computeErrorInfoWithPrepareStackTrace(JSC::VM& vm, Zig::GlobalObje // We need to sourcemap it if it's a GlobalObject. if (globalObject == lexicalGlobalObject) { size_t framesCount = stackTrace.size(); -#if OS(WINDOWS) // MSVC workaround - ZigStackFrame* remappedFrames = new ZigStackFrame[framesCount]; -#else ZigStackFrame remappedFrames[framesCount]; -#endif for (int i = 0; i < framesCount; i++) { memset(remappedFrames + i, 0, sizeof(ZigStackFrame)); remappedFrames[i].source_url = Bun::toString(lexicalGlobalObject, stackTrace.at(i).sourceURL()); @@ -484,9 +480,6 @@ static String computeErrorInfoWithPrepareStackTrace(JSC::VM& vm, Zig::GlobalObje callSite->setLineNumber(lineNumber); } } -#if OS(WINDOWS) // MSVC workaround - delete remappedFrames; -#endif } globalObject->formatStackTrace(vm, lexicalGlobalObject, errorObject, callSites, prepareStackTrace); diff --git a/src/bun.js/bindings/root.h b/src/bun.js/bindings/root.h index 6d1739b882..f5c978926b 100644 --- a/src/bun.js/bindings/root.h +++ b/src/bun.js/bindings/root.h @@ -40,7 +40,7 @@ #include -#define JS_EXPORT_PRIVATE +#define JS_EXPORT_PRIVATE #ifdef __cplusplus #undef new @@ -56,9 +56,6 @@ */ #if COMPILER(MSVC) #pragma warning(disable : 4206) - -// __builtin_unreachable() polyfill -static __declspec(noreturn) void __builtin_unreachable() { __assume(0); } #endif #ifndef WEBCORE_EXPORT diff --git a/src/bun.js/node/syscall.zig b/src/bun.js/node/syscall.zig deleted file mode 100644 index 18dc4a0ef0..0000000000 --- a/src/bun.js/node/syscall.zig +++ /dev/null @@ -1,1337 +0,0 @@ -// This file is entirely based on Zig's std.os -// The differences are in error handling -const std = @import("std"); -const os = std.os; -const builtin = @import("builtin"); - -const Syscall = @This(); -const Environment = @import("root").bun.Environment; -const default_allocator = @import("root").bun.default_allocator; -const JSC = @import("root").bun.JSC; -const SystemError = JSC.SystemError; -const bun = @import("root").bun; -const MAX_PATH_BYTES = bun.MAX_PATH_BYTES; -const fd_t = bun.FileDescriptor; -const C = @import("root").bun.C; -const linux = os.linux; -const Maybe = JSC.Maybe; -const kernel32 = bun.windows; - -const log = bun.Output.scoped(.SYS, false); -pub const syslog = log; - -// On Linux AARCh64, zig is missing stat & lstat syscalls -const use_libc = !(Environment.isLinux and Environment.isX64); -pub const system = if (Environment.isLinux) linux else @import("root").bun.AsyncIO.system; -pub const S = struct { - pub usingnamespace if (Environment.isLinux) linux.S else if (Environment.isPosix) std.os.S else struct {}; -}; -const sys = std.os.system; - -const statSym = if (use_libc) - C.stat -else if (Environment.isLinux) - linux.stat -else - @compileError("STAT"); - -const fstatSym = if (use_libc) - C.fstat -else if (Environment.isLinux) - linux.fstat -else - @compileError("STAT"); - -const lstat64 = if (use_libc) - C.lstat -else if (Environment.isLinux) - linux.lstat -else - @compileError("STAT"); - -const windows = bun.windows; - -pub const Tag = enum(u8) { - TODO, - dup, - access, - chmod, - chown, - clonefile, - close, - copy_file_range, - copyfile, - fchmod, - fchown, - fcntl, - fdatasync, - fstat, - fsync, - ftruncate, - futimens, - getdents64, - getdirentries64, - lchmod, - lchown, - link, - lseek, - lstat, - lutimes, - mkdir, - mkdtemp, - fnctl, - mmap, - munmap, - open, - pread, - pwrite, - read, - readlink, - rename, - stat, - symlink, - unlink, - utimes, - write, - getcwd, - chdir, - fcopyfile, - recv, - send, - sendfile, - splice, - rmdir, - - kevent, - kqueue, - epoll_ctl, - kill, - waitpid, - posix_spawn, - getaddrinfo, - writev, - pwritev, - readv, - preadv, - NtQueryDirectoryFile, - - pub var strings = std.EnumMap(Tag, JSC.C.JSStringRef).initFull(null); -}; -const PathString = @import("root").bun.PathString; - -const mode_t = os.mode_t; - -const open_sym = system.open; - -const mem = std.mem; - -pub fn getcwd(buf: *[bun.MAX_PATH_BYTES]u8) Maybe([]const u8) { - const Result = Maybe([]const u8); - buf[0] = 0; - const rc = std.c.getcwd(buf, bun.MAX_PATH_BYTES); - return if (rc != null) - Result{ .result = std.mem.sliceTo(rc.?[0..bun.MAX_PATH_BYTES], 0) } - else - Result.errnoSys(0, .getcwd).?; -} - -pub fn fchmod(fd_: bun.FileDescriptor, mode: bun.Mode) Maybe(void) { - const fd = bun.fdcast(fd_); - return Maybe(void).errnoSys(C.fchmod(fd, mode), .fchmod) orelse - Maybe(void).success; -} - -pub fn chdirOSPath(destination: bun.OSPathSlice) Maybe(void) { - if (comptime Environment.isPosix) { - const rc = sys.chdir(destination); - return Maybe(void).errnoSys(rc, .chdir) orelse Maybe(void).success; - } - - if (comptime Environment.isWindows) { - if (kernel32.SetCurrentDirectory(destination) != 0) { - return Maybe(void).errnoSys(0, .chdir) orelse Maybe(void).success; - } - - return Maybe(void).success; - } - - @compileError("Not implemented yet"); -} - -pub fn chdir(destination: anytype) Maybe(void) { - const Type = @TypeOf(destination); - - if (comptime Environment.isPosix) { - if (comptime Type == []u8 or Type == []const u8) { - return chdirOSPath( - &(std.os.toPosixPath(destination) catch return .{ .err = .{ - .errno = @intFromEnum(bun.C.SystemErrno.EINVAL), - .syscall = .chdir, - } }), - ); - } - - return chdirOSPath(destination); - } - - if (comptime Environment.isWindows) { - if (comptime Type == bun.OSPathSlice or Type == [:0]u16) { - return chdirOSPath(@as(bun.OSPathSlice, destination)); - } - - if (comptime Type == *[*:0]u16) { - if (kernel32.SetCurrentDirectory(destination) != 0) { - return Maybe(void).errnoSys(0, .chdir) orelse Maybe(void).success; - } - - return Maybe(void).success; - } - - var wbuf: bun.MAX_WPATH = undefined; - return chdirOSPath(bun.strings.toWPath(&wbuf, destination)); - } - - return Maybe(void).todo; -} - -pub fn stat(path: [:0]const u8) Maybe(bun.Stat) { - var stat_ = mem.zeroes(bun.Stat); - const rc = statSym(path, &stat_); - - if (comptime Environment.allow_assert) - log("stat({s}) = {d}", .{ bun.asByteSlice(path), rc }); - - if (Maybe(bun.Stat).errnoSys(rc, .stat)) |err| return err; - return Maybe(bun.Stat){ .result = stat_ }; -} - -pub fn lstat(path: [:0]const u8) Maybe(bun.Stat) { - var stat_ = mem.zeroes(bun.Stat); - if (Maybe(bun.Stat).errnoSys(lstat64(path, &stat_), .lstat)) |err| return err; - return Maybe(bun.Stat){ .result = stat_ }; -} - -pub fn fstat(fd: bun.FileDescriptor) Maybe(bun.Stat) { - var stat_ = mem.zeroes(bun.Stat); - - const rc = fstatSym(fd, &stat_); - - if (comptime Environment.allow_assert) - log("fstat({d}) = {d}", .{ fd, rc }); - - if (Maybe(bun.Stat).errnoSys(rc, .fstat)) |err| return err; - return Maybe(bun.Stat){ .result = stat_ }; -} - -pub fn mkdir(file_path: [:0]const u8, flags: bun.Mode) Maybe(void) { - if (comptime Environment.isMac) { - return Maybe(void).errnoSysP(system.mkdir(file_path, flags), .mkdir, file_path) orelse Maybe(void).success; - } - - if (comptime Environment.isLinux) { - return Maybe(void).errnoSysP(linux.mkdir(file_path, flags), .mkdir, file_path) orelse Maybe(void).success; - } - var wbuf: bun.MAX_WPATH = undefined; - _ = kernel32.CreateDirectoryW(bun.strings.toWPath(&wbuf, file_path).ptr, null); - - return Maybe(void).errnoSysP(0, .mkdir, file_path) orelse Maybe(void).success; -} - -pub fn fcntl(fd_: bun.FileDescriptor, cmd: i32, arg: usize) Maybe(usize) { - const fd = bun.fdcast(fd_); - const result = fcntl_symbol(fd, cmd, arg); - if (Maybe(usize).errnoSys(result, .fcntl)) |err| return err; - return .{ .result = @as(usize, @intCast(result)) }; -} - -pub fn getErrno(rc: anytype) bun.C.E { - if (comptime Environment.isWindows) { - if (bun.windows.Win32Error.get().toSystemErrno()) |e| { - return e.toE(); - } - - return bun.C.E.UNKNOWN; - } - - if (comptime use_libc) return std.os.errno(rc); - const Type = @TypeOf(rc); - - return switch (Type) { - comptime_int, usize => std.os.linux.getErrno(@as(usize, rc)), - i32, c_int, isize => std.os.linux.getErrno(@as(usize, @bitCast(@as(isize, rc)))), - else => @compileError("Not implemented yet for type " ++ @typeName(Type)), - }; -} - -// pub fn openOptionsFromFlagsWindows(flags: u32) windows.OpenFileOptions { -// const w = windows; -// const O = std.os.O; - -// var access_mask: w.ULONG = w.READ_CONTROL | w.FILE_WRITE_ATTRIBUTES | w.SYNCHRONIZE; -// if (flags & O.RDWR != 0) { -// access_mask |= w.GENERIC_READ | w.GENERIC_WRITE; -// } else if (flags & O.WRONLY != 0) { -// access_mask |= w.GENERIC_WRITE; -// } else { -// access_mask |= w.GENERIC_READ | w.GENERIC_WRITE; -// } - -// const filter: windows.OpenFileOptions.Filter = if (flags & O.DIRECTORY != 0) .dir_only else .file_only; -// const follow_symlinks: bool = flags & O.NOFOLLOW == 0; - -// const creation: w.ULONG = blk: { -// if (flags & O.CREAT != 0) { -// if (flags & O.EXCL != 0) { -// break :blk w.FILE_CREATE; -// } -// } -// break :blk w.FILE_OPEN; -// }; - -// return .{ -// .access_mask = access_mask, -// .io_mode = .blocking, -// .creation = creation, -// .filter = filter, -// .follow_symlinks = follow_symlinks, -// }; -// } -const O = std.os.O; -const w = std.os.windows; - -pub fn openatWindows(dirfD: bun.FileDescriptor, path: []const u16, flags: bun.Mode) Maybe(bun.FileDescriptor) { - const nonblock = flags & O.NONBLOCK != 0; - - var access_mask: w.ULONG = w.READ_CONTROL | w.FILE_WRITE_ATTRIBUTES | w.SYNCHRONIZE; - - if (flags & O.RDWR != 0) { - access_mask |= w.GENERIC_READ | w.GENERIC_WRITE; - } else if (flags & O.WRONLY != 0) { - access_mask |= w.GENERIC_WRITE; - } else if (flags & O.APPEND != 0) { - access_mask |= w.FILE_APPEND_DATA; - } else { - access_mask |= w.GENERIC_READ; - } - - var result: windows.HANDLE = undefined; - - const path_len_bytes = std.math.cast(u16, path.len * 2) orelse return .{ - .err = .{ - .errno = @intFromEnum(bun.C.E.NOMEM), - .syscall = .open, - }, - }; - var nt_name = windows.UNICODE_STRING{ - .Length = path_len_bytes, - .MaximumLength = path_len_bytes, - .Buffer = @constCast(path.ptr), - }; - var attr = windows.OBJECT_ATTRIBUTES{ - .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), - .RootDirectory = if (dirfD == bun.invalid_fd or std.fs.path.isAbsoluteWindowsWTF16(path)) null else bun.fdcast(dirfD), - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; - var io: windows.IO_STATUS_BLOCK = undefined; - const blocking_flag: windows.ULONG = if (!nonblock) windows.FILE_SYNCHRONOUS_IO_NONALERT else 0; - const file_or_dir_flag: windows.ULONG = switch (flags & O.DIRECTORY != 0) { - // .file_only => windows.FILE_NON_DIRECTORY_FILE, - true => windows.FILE_DIRECTORY_FILE, - false => 0, - }; - const follow_symlinks = flags & O.NOFOLLOW == 0; - const creation: w.ULONG = blk: { - if (flags & O.CREAT != 0) { - if (flags & O.EXCL != 0) { - break :blk w.FILE_CREATE; - } - } - break :blk w.FILE_OPEN; - }; - - const wflags: windows.ULONG = if (follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | windows.FILE_OPEN_REPARSE_POINT; - - while (true) { - const rc = windows.ntdll.NtCreateFile( - &result, - access_mask, - &attr, - &io, - null, - w.FILE_ATTRIBUTE_NORMAL, - w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE, - creation, - wflags, - null, - 0, - ); - switch (windows.Win32Error.fromNTStatus(rc)) { - .SUCCESS => { - return JSC.Maybe(bun.FileDescriptor){ - .result = bun.toFD(result), - }; - }, - else => |code| { - if (code.toSystemErrno()) |sys_err| { - return .{ - .err = .{ - .errno = @truncate(@intFromEnum(sys_err)), - .syscall = .open, - }, - }; - } - - return .{ - .err = .{ - .errno = @intFromEnum(bun.C.E.UNKNOWN), - .syscall = .open, - }, - }; - }, - } - } -} - -pub fn openatOSPath(dirfd: bun.FileDescriptor, file_path: bun.OSPathSlice, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { - if (comptime Environment.isMac) { - // https://opensource.apple.com/source/xnu/xnu-7195.81.3/libsyscall/wrappers/open-base.c - const rc = bun.AsyncIO.darwin.@"openat$NOCANCEL"(dirfd, file_path.ptr, @as(c_uint, @intCast(flags)), @as(c_int, @intCast(perm))); - log("openat({d}, {s}) = {d}", .{ dirfd, file_path, rc }); - - return switch (Syscall.getErrno(rc)) { - .SUCCESS => .{ .result = @as(bun.FileDescriptor, @intCast(rc)) }, - else => |err| .{ - .err = .{ - .errno = @as(Syscall.Error.Int, @truncate(@intFromEnum(err))), - .syscall = .open, - }, - }, - }; - } - - if (comptime Environment.isWindows) { - return openatWindows(dirfd, file_path, flags); - } - - while (true) { - const rc = Syscall.system.openat(@as(Syscall.system.fd_t, @intCast(dirfd)), file_path, flags, perm); - log("openat({d}, {s}) = {d}", .{ dirfd, file_path, rc }); - return switch (Syscall.getErrno(rc)) { - .SUCCESS => .{ .result = @as(bun.FileDescriptor, @intCast(rc)) }, - .INTR => continue, - else => |err| { - return Maybe(std.os.fd_t){ - .err = .{ - .errno = @as(Syscall.Error.Int, @truncate(@intFromEnum(err))), - .syscall = .open, - }, - }; - }, - }; - } - - unreachable; -} - -pub fn openat(dirfd: bun.FileDescriptor, file_path: [:0]const u8, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { - if (comptime Environment.isWindows) { - var wbuf: bun.MAX_WPATH = undefined; - return openatWindows(dirfd, bun.strings.toWPath(&wbuf, file_path), flags); - } - - return openatOSPath(dirfd, file_path, flags, perm); -} - -pub fn open(file_path: [:0]const u8, flags: bun.Mode, perm: bun.Mode) Maybe(bun.FileDescriptor) { - // this is what open() does anyway. - return openat(bun.toFD((std.fs.cwd().fd)), file_path, flags, perm); -} - -/// This function will prevent stdout and stderr from being closed. -pub fn close(fd: bun.FileDescriptor) ?Syscall.Error { - if (fd == bun.STDOUT_FD or fd == bun.STDERR_FD) { - log("close({d}) SKIPPED", .{fd}); - return null; - } - - return closeAllowingStdoutAndStderr(fd); -} - -pub fn closeAllowingStdoutAndStderr(fd: bun.FileDescriptor) ?Syscall.Error { - log("close({d})", .{fd}); - std.debug.assert(fd != bun.invalid_fd); - if (comptime std.meta.trait.isSignedInt(@TypeOf(fd))) - std.debug.assert(fd > -1); - - if (comptime Environment.isMac) { - // This avoids the EINTR problem. - return switch (system.getErrno(system.@"close$NOCANCEL"(fd))) { - .BADF => Syscall.Error{ .errno = @intFromEnum(os.E.BADF), .syscall = .close }, - else => null, - }; - } - - if (comptime Environment.isLinux) { - return switch (linux.getErrno(linux.close(fd))) { - .BADF => Syscall.Error{ .errno = @intFromEnum(os.E.BADF), .syscall = .close }, - else => null, - }; - } - - if (comptime Environment.isWindows) { - if (kernel32.CloseHandle(bun.fdcast(fd)) == 0) { - return Syscall.Error{ .errno = @intFromEnum(os.E.BADF), .syscall = .close }; - } - - return null; - } - - @compileError("Not implemented yet"); -} - -const max_count = switch (builtin.os.tag) { - .linux => 0x7ffff000, - .macos, .ios, .watchos, .tvos => std.math.maxInt(i32), - else => std.math.maxInt(isize), -}; - -pub fn write(fd_: bun.FileDescriptor, bytes: []const u8) Maybe(usize) { - const fd = bun.fdcast(fd_); - const adjusted_len = @min(max_count, bytes.len); - - if (comptime Environment.isMac) { - const rc = system.@"write$NOCANCEL"(fd, bytes.ptr, adjusted_len); - log("write({d}, {d}) = {d}", .{ fd, adjusted_len, rc }); - - if (Maybe(usize).errnoSysFd(rc, .write, fd)) |err| { - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } else { - while (true) { - const rc = sys.write(fd, bytes.ptr, adjusted_len); - log("write({d}, {d}) = {d}", .{ fd, adjusted_len, rc }); - - if (Maybe(usize).errnoSysFd(rc, .write, fd)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - unreachable; - } -} - -fn veclen(buffers: anytype) usize { - var len: usize = 0; - for (buffers) |buffer| { - len += buffer.iov_len; - } - return len; -} - -pub fn writev(fd_: bun.FileDescriptor, buffers: []std.os.iovec) Maybe(usize) { - const fd = bun.fdcast(fd_); - if (comptime Environment.isMac) { - const rc = writev_sym(fd, @as([*]std.os.iovec_const, @ptrCast(buffers.ptr)), @as(i32, @intCast(buffers.len))); - if (comptime Environment.allow_assert) - log("writev({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); - - if (Maybe(usize).errnoSysFd(rc, .writev, fd)) |err| { - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } else { - while (true) { - const rc = writev_sym(fd, @as([*]std.os.iovec_const, @ptrCast(buffers.ptr)), buffers.len); - if (comptime Environment.allow_assert) - log("writev({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); - - if (Maybe(usize).errnoSysFd(rc, .writev, fd)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - unreachable; - } -} - -pub fn pwritev(fd_: bun.FileDescriptor, buffers: []std.os.iovec, position: isize) Maybe(usize) { - const fd = bun.fdcast(fd_); - if (comptime Environment.isMac) { - const rc = pwritev_sym(fd, @as([*]std.os.iovec_const, @ptrCast(buffers.ptr)), @as(i32, @intCast(buffers.len)), position); - if (comptime Environment.allow_assert) - log("pwritev({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); - - if (Maybe(usize).errnoSysFd(rc, .pwritev, fd)) |err| { - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } else { - while (true) { - const rc = pwritev_sym(fd, @as([*]std.os.iovec_const, @ptrCast(buffers.ptr)), buffers.len, position); - if (comptime Environment.allow_assert) - log("pwritev({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); - - if (Maybe(usize).errnoSysFd(rc, .pwritev, fd)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - unreachable; - } -} - -pub fn readv(fd_: bun.FileDescriptor, buffers: []std.os.iovec) Maybe(usize) { - const fd = bun.fdcast(fd_); - if (comptime Environment.isMac) { - const rc = readv_sym(fd, buffers.ptr, @as(i32, @intCast(buffers.len))); - if (comptime Environment.allow_assert) - log("readv({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); - - if (Maybe(usize).errnoSysFd(rc, .readv, fd)) |err| { - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } else { - while (true) { - const rc = readv_sym(fd, buffers.ptr, buffers.len); - if (comptime Environment.allow_assert) - log("readv({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); - - if (Maybe(usize).errnoSysFd(rc, .readv, fd)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - unreachable; - } -} - -pub fn preadv(fd_: bun.FileDescriptor, buffers: []std.os.iovec, position: isize) Maybe(usize) { - const fd = bun.fdcast(fd_); - if (comptime Environment.isMac) { - const rc = preadv_sym(fd, buffers.ptr, @as(i32, @intCast(buffers.len)), position); - if (comptime Environment.allow_assert) - log("preadv({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); - - if (Maybe(usize).errnoSysFd(rc, .preadv, fd)) |err| { - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } else { - while (true) { - const rc = preadv_sym(fd, buffers.ptr, buffers.len, position); - if (comptime Environment.allow_assert) - log("preadv({d}, {d}) = {d}", .{ fd, veclen(buffers), rc }); - - if (Maybe(usize).errnoSysFd(rc, .preadv, fd)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - unreachable; - } -} - -const preadv_sym = if (builtin.os.tag == .linux and builtin.link_libc) - std.os.linux.preadv -else if (builtin.os.tag.isDarwin()) - system.@"preadv$NOCANCEL" -else - system.preadv; - -const readv_sym = if (builtin.os.tag == .linux and builtin.link_libc) - std.os.linux.readv -else if (builtin.os.tag.isDarwin()) - system.@"readv$NOCANCEL" -else - system.readv; - -const pwritev_sym = if (builtin.os.tag == .linux and builtin.link_libc) - std.os.linux.pwritev -else if (builtin.os.tag.isDarwin()) - system.@"pwritev$NOCANCEL" -else - system.pwritev; - -const writev_sym = if (builtin.os.tag == .linux and builtin.link_libc) - std.os.linux.writev -else if (builtin.os.tag.isDarwin()) - system.@"writev$NOCANCEL" -else - system.writev; - -const pread_sym = if (builtin.os.tag == .linux and builtin.link_libc) - sys.pread64 -else if (builtin.os.tag.isDarwin()) - system.@"pread$NOCANCEL" -else - system.pread; - -const fcntl_symbol = system.fcntl; - -pub fn pread(fd_: bun.FileDescriptor, buf: []u8, offset: i64) Maybe(usize) { - const fd = bun.fdcast(fd_); - const adjusted_len = @min(buf.len, max_count); - - const ioffset = @as(i64, @bitCast(offset)); // the OS treats this as unsigned - while (true) { - const rc = pread_sym(fd, buf.ptr, adjusted_len, ioffset); - if (Maybe(usize).errnoSys(rc, .pread)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - unreachable; -} - -const pwrite_sym = if (builtin.os.tag == .linux and builtin.link_libc) - sys.pwrite64 -else - sys.pwrite; - -pub fn pwrite(fd_: bun.FileDescriptor, bytes: []const u8, offset: i64) Maybe(usize) { - const fd = bun.fdcast(fd_); - const adjusted_len = @min(bytes.len, max_count); - - const ioffset = @as(i64, @bitCast(offset)); // the OS treats this as unsigned - while (true) { - const rc = pwrite_sym(fd, bytes.ptr, adjusted_len, ioffset); - return if (Maybe(usize).errnoSysFd(rc, .pwrite, fd)) |err| { - switch (err.getErrno()) { - .INTR => continue, - else => return err, - } - } else Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - - unreachable; -} - -pub fn read(fd_: bun.FileDescriptor, buf: []u8) Maybe(usize) { - const fd = bun.fdcast(fd_); - const debug_timer = bun.Output.DebugTimer.start(); - const adjusted_len = @min(buf.len, max_count); - if (comptime Environment.isMac) { - const rc = system.@"read$NOCANCEL"(fd, buf.ptr, adjusted_len); - - log("read({d}, {d}) = {d} ({any})", .{ fd, adjusted_len, rc, debug_timer }); - - if (Maybe(usize).errnoSys(rc, .read)) |err| { - return err; - } - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } else { - while (true) { - const rc = sys.read(fd, buf.ptr, adjusted_len); - log("read({d}, {d}) = {d} ({any})", .{ fd, adjusted_len, rc, debug_timer }); - - if (Maybe(usize).errnoSysFd(rc, .read, fd)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - } - unreachable; -} - -pub fn recv(fd_: bun.FileDescriptor, buf: []u8, flag: u32) Maybe(usize) { - const fd = bun.fdcast(fd_); - const adjusted_len = @min(buf.len, max_count); - - if (comptime Environment.isMac) { - const rc = system.@"recvfrom$NOCANCEL"(fd, buf.ptr, adjusted_len, flag, null, null); - log("recv({d}, {d}, {d}) = {d}", .{ fd, adjusted_len, flag, rc }); - - if (Maybe(usize).errnoSys(rc, .recv)) |err| { - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } else { - while (true) { - const rc = linux.recvfrom(fd, buf.ptr, adjusted_len, flag | os.SOCK.CLOEXEC | linux.MSG.CMSG_CLOEXEC, null, null); - log("recv({d}, {d}, {d}) = {d}", .{ fd, adjusted_len, flag, rc }); - - if (Maybe(usize).errnoSysFd(rc, .recv, fd)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - } - unreachable; -} - -pub fn send(fd_: bun.FileDescriptor, buf: []const u8, flag: u32) Maybe(usize) { - const fd = bun.fdcast(fd_); - if (comptime Environment.isMac) { - const rc = system.@"sendto$NOCANCEL"(fd, buf.ptr, buf.len, flag, null, 0); - if (Maybe(usize).errnoSys(rc, .send)) |err| { - return err; - } - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } else { - while (true) { - const rc = linux.sendto(fd, buf.ptr, buf.len, flag | os.SOCK.CLOEXEC | os.MSG.NOSIGNAL, null, 0); - - if (Maybe(usize).errnoSys(rc, .send)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - } - unreachable; -} - -pub fn readlink(in: [:0]const u8, buf: []u8) Maybe(usize) { - while (true) { - const rc = sys.readlink(in, buf.ptr, buf.len); - - if (Maybe(usize).errnoSys(rc, .readlink)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(usize){ .result = @as(usize, @intCast(rc)) }; - } - unreachable; -} - -pub fn ftruncate(fd: fd_t, size: isize) Maybe(void) { - if (comptime Environment.isWindows) { - if (kernel32.SetFileValidData(bun.fdcast(fd), size) == 0) { - return Maybe(void).errnoSys(0, .ftruncate) orelse Maybe(void).success; - } - - return Maybe(void).success; - } - while (true) { - if (Maybe(void).errnoSys(sys.ftruncate(fd, size), .ftruncate)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(void).success; - } - unreachable; -} - -pub fn rename(from: [:0]const u8, to: [:0]const u8) Maybe(void) { - while (true) { - if (Maybe(void).errnoSys(sys.rename(from, to), .rename)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(void).success; - } - unreachable; -} - -pub fn chown(path: [:0]const u8, uid: os.uid_t, gid: os.gid_t) Maybe(void) { - while (true) { - if (Maybe(void).errnoSys(C.chown(path, uid, gid), .chown)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(void).success; - } - unreachable; -} - -pub fn symlink(from: [:0]const u8, to: [:0]const u8) Maybe(void) { - while (true) { - if (Maybe(void).errnoSys(sys.symlink(from, to), .symlink)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(void).success; - } - unreachable; -} - -pub fn clonefile(from: [:0]const u8, to: [:0]const u8) Maybe(void) { - if (comptime !Environment.isMac) @compileError("macOS only"); - - while (true) { - if (Maybe(void).errnoSys(C.darwin.clonefile(from, to, 0), .clonefile)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(void).success; - } - unreachable; -} - -pub fn copyfile(from: [:0]const u8, to: [:0]const u8, flags: c_int) Maybe(void) { - if (comptime !Environment.isMac) @compileError("macOS only"); - - while (true) { - if (Maybe(void).errnoSys(C.darwin.copyfile(from, to, null, flags), .copyfile)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(void).success; - } - unreachable; -} - -pub fn fcopyfile(fd_in: std.os.fd_t, fd_out: std.os.fd_t, flags: u32) Maybe(void) { - if (comptime !Environment.isMac) @compileError("macOS only"); - - while (true) { - if (Maybe(void).errnoSys(system.fcopyfile(fd_in, fd_out, null, flags), .fcopyfile)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(void).success; - } - unreachable; -} - -pub fn unlink(from: [:0]const u8) Maybe(void) { - while (true) { - if (Maybe(void).errnoSys(sys.unlink(from), .unlink)) |err| { - if (err.getErrno() == .INTR) continue; - return err; - } - return Maybe(void).success; - } - unreachable; -} - -pub fn getFdPath(fd_: bun.FileDescriptor, out_buffer: *[MAX_PATH_BYTES]u8) Maybe([]u8) { - const fd = bun.fdcast(fd_); - switch (comptime builtin.os.tag) { - .windows => { - var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined; - const wide_slice = std.os.windows.GetFinalPathNameByHandle(fd, .{}, wide_buf[0..]) catch { - return Maybe([]u8){ .err = .{ .errno = @intFromEnum(bun.C.SystemErrno.EBADF) } }; - }; - // Trust that Windows gives us valid UTF-16LE. - var slash_buf: [MAX_PATH_BYTES * 2]u8 = undefined; - var slash_str = bun.strings.fromWPath(&slash_buf, wide_slice); - - return .{ .result = bun.path.normalizeStringBuf(slash_str, out_buffer, false, .loose) }; - }, - .macos, .ios, .watchos, .tvos => { - // On macOS, we can use F.GETPATH fcntl command to query the OS for - // the path to the file descriptor. - @memset(out_buffer[0..MAX_PATH_BYTES], 0); - if (Maybe([]u8).errnoSys(system.fcntl(fd, os.F.GETPATH, out_buffer), .fcntl)) |err| { - return err; - } - const len = mem.indexOfScalar(u8, out_buffer[0..], @as(u8, 0)) orelse MAX_PATH_BYTES; - return .{ .result = out_buffer[0..len] }; - }, - .linux => { - // TODO: alpine linux may not have /proc/self - var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined; - const proc_path = std.fmt.bufPrintZ(procfs_buf[0..], "/proc/self/fd/{d}\x00", .{fd}) catch unreachable; - - return switch (readlink(proc_path, out_buffer)) { - .err => |err| return .{ .err = err }, - .result => |len| return .{ .result = out_buffer[0..len] }, - }; - }, - // .solaris => { - // var procfs_buf: ["/proc/self/path/-2147483648".len:0]u8 = undefined; - // const proc_path = std.fmt.bufPrintZ(procfs_buf[0..], "/proc/self/path/{d}", .{fd}) catch unreachable; - - // const target = readlinkZ(proc_path, out_buffer) catch |err| switch (err) { - // error.UnsupportedReparsePointType => unreachable, - // error.NotLink => unreachable, - // else => |e| return e, - // }; - // return target; - // }, - else => @compileError("querying for canonical path of a handle is unsupported on this host"), - } -} - -/// Use of a mapped region can result in these signals: -/// * SIGSEGV - Attempted write into a region mapped as read-only. -/// * SIGBUS - Attempted access to a portion of the buffer that does not correspond to the file -fn mmap( - ptr: ?[*]align(mem.page_size) u8, - length: usize, - prot: u32, - flags: u32, - fd_: bun.FileDescriptor, - offset: u64, -) Maybe([]align(mem.page_size) u8) { - const fd = bun.fdcast(fd_); - const ioffset = @as(i64, @bitCast(offset)); // the OS treats this as unsigned - const rc = std.c.mmap(ptr, length, prot, flags, fd, ioffset); - const fail = std.c.MAP.FAILED; - if (rc == fail) { - return Maybe([]align(mem.page_size) u8){ - .err = .{ .errno = @as(Syscall.Error.Int, @truncate(@intFromEnum(std.c.getErrno(@as(i64, @bitCast(@intFromPtr(fail))))))), .syscall = .mmap }, - }; - } - - return Maybe([]align(mem.page_size) u8){ .result = @as([*]align(mem.page_size) u8, @ptrCast(@alignCast(rc)))[0..length] }; -} - -pub fn mmapFile(path: [:0]const u8, flags: u32, wanted_size: ?usize, offset: usize) Maybe([]align(mem.page_size) u8) { - const fd = switch (open(path, os.O.RDWR, 0)) { - .result => |fd| fd, - .err => |err| return .{ .err = err }, - }; - - var size = std.math.sub(usize, @as(usize, @intCast(switch (fstat(fd)) { - .result => |result| result.size, - .err => |err| { - _ = close(fd); - return .{ .err = err }; - }, - })), offset) catch 0; - - if (wanted_size) |size_| size = @min(size, size_); - - const map = switch (mmap(null, size, os.PROT.READ | os.PROT.WRITE, flags, fd, offset)) { - .result => |map| map, - - .err => |err| { - _ = close(fd); - return .{ .err = err }; - }, - }; - - if (close(fd)) |err| { - _ = munmap(map); - return .{ .err = err }; - } - - return .{ .result = map }; -} - -pub fn munmap(memory: []align(mem.page_size) const u8) Maybe(void) { - if (Maybe(void).errnoSys(system.munmap(memory.ptr, memory.len), .munmap)) |err| { - return err; - } else return Maybe(void).success; -} - -pub const Error = struct { - const E = bun.C.E; - const max_errno_value = brk: { - const errno_values = std.enums.values(E); - var err = @intFromEnum(E.SUCCESS); - for (errno_values) |errn| { - err = @max(err, @intFromEnum(errn)); - } - break :brk err; - }; - pub const Int: type = std.math.IntFittingRange(0, max_errno_value + 5); - - errno: Int, - syscall: Syscall.Tag = @as(Syscall.Tag, @enumFromInt(0)), - path: []const u8 = "", - fd: bun.FileDescriptor = bun.invalid_fd, - - pub inline fn isRetry(this: *const Error) bool { - return this.getErrno() == .AGAIN; - } - - pub fn fromCode(errno: E, syscall: Syscall.Tag) Error { - return .{ .errno = @as(Int, @truncate(@intFromEnum(errno))), .syscall = syscall }; - } - - pub fn format(self: Error, comptime fmt: []const u8, opts: std.fmt.FormatOptions, writer: anytype) !void { - try self.toSystemError().format(fmt, opts, writer); - } - - pub const oom = fromCode(E.NOMEM, .read); - - pub const retry = Error{ - .errno = if (Environment.isLinux) - @as(Int, @intCast(@intFromEnum(E.AGAIN))) - else if (Environment.isMac) - @as(Int, @intCast(@intFromEnum(E.WOULDBLOCK))) - else - @as(Int, @intCast(@intFromEnum(E.INTR))), - .syscall = .retry, - }; - - pub inline fn getErrno(this: Error) E { - return @as(E, @enumFromInt(this.errno)); - } - - pub inline fn withPath(this: Error, path: anytype) Error { - return Error{ - .errno = this.errno, - .syscall = this.syscall, - .path = bun.span(path), - }; - } - - pub inline fn withFd(this: Error, fd: anytype) Error { - return Error{ - .errno = this.errno, - .syscall = this.syscall, - .fd = @intCast(fd), - }; - } - - pub inline fn withPathLike(this: Error, pathlike: anytype) Error { - return switch (pathlike) { - .fd => |fd| this.withFd(fd), - .path => |path| this.withPath(path.slice()), - }; - } - - pub inline fn withSyscall(this: Error, syscall: Syscall) Error { - return Error{ - .errno = this.errno, - .syscall = syscall, - .path = this.path, - }; - } - - pub const todo_errno = std.math.maxInt(Int) - 1; - pub const todo = Error{ .errno = todo_errno }; - - pub fn toSystemError(this: Error) SystemError { - var err = SystemError{ - .errno = @as(c_int, this.errno) * -1, - .syscall = bun.String.static(@tagName(this.syscall)), - }; - - // errno label - if (this.errno > 0 and this.errno < C.SystemErrno.max) { - const system_errno = @as(C.SystemErrno, @enumFromInt(this.errno)); - err.code = bun.String.static(@tagName(system_errno)); - if (C.SystemErrno.labels.get(system_errno)) |label| { - err.message = bun.String.static(label); - } - } - - if (this.path.len > 0) { - err.path = bun.String.create(this.path); - } - - if (this.fd != bun.invalid_fd) { - if (this.fd <= std.math.maxInt(i32)) { - err.fd = @intCast(this.fd); - } - } - - return err; - } - - pub fn toJS(this: Error, ctx: JSC.C.JSContextRef) JSC.C.JSObjectRef { - return this.toSystemError().toErrorInstance(ctx.ptr()).asObjectRef(); - } - - pub fn toJSC(this: Error, ptr: *JSC.JSGlobalObject) JSC.JSValue { - return this.toSystemError().toErrorInstance(ptr); - } -}; - -pub fn setPipeCapacityOnLinux(fd_: bun.FileDescriptor, capacity: usize) Maybe(usize) { - const fd = bun.fdcast(fd_); - if (comptime !Environment.isLinux) @compileError("Linux-only"); - std.debug.assert(capacity > 0); - - // In Linux versions before 2.6.11, the capacity of a - // pipe was the same as the system page size (e.g., 4096 - // bytes on i386). Since Linux 2.6.11, the pipe - // capacity is 16 pages (i.e., 65,536 bytes in a system - // with a page size of 4096 bytes). Since Linux 2.6.35, - // the default pipe capacity is 16 pages, but the - // capacity can be queried and set using the - // fcntl(2) F_GETPIPE_SZ and F_SETPIPE_SZ operations. - // See fcntl(2) for more information. - //:# define F_SETPIPE_SZ 1031 /* Set pipe page size array. - const F_SETPIPE_SZ = 1031; - const F_GETPIPE_SZ = 1032; - - // We don't use glibc here - // It didn't work. Always returned 0. - const pipe_len = std.os.linux.fcntl(fd, F_GETPIPE_SZ, 0); - if (Maybe(usize).errno(pipe_len)) |err| return err; - if (pipe_len == 0) return Maybe(usize){ .result = 0 }; - if (pipe_len >= capacity) return Maybe(usize){ .result = pipe_len }; - - const new_pipe_len = std.os.linux.fcntl(fd, F_SETPIPE_SZ, capacity); - if (Maybe(usize).errno(new_pipe_len)) |err| return err; - return Maybe(usize){ .result = new_pipe_len }; -} - -pub fn getMaxPipeSizeOnLinux() usize { - return @as( - usize, - @intCast(bun.once(struct { - fn once() c_int { - const strings = bun.strings; - const default_out_size = 512 * 1024; - const pipe_max_size_fd = switch (bun.sys.open("/proc/sys/fs/pipe-max-size", std.os.O.RDONLY, 0)) { - .result => |fd2| fd2, - .err => |err| { - log("Failed to open /proc/sys/fs/pipe-max-size: {d}\n", .{err.errno}); - return default_out_size; - }, - }; - defer _ = bun.sys.close(pipe_max_size_fd); - var max_pipe_size_buf: [128]u8 = undefined; - const max_pipe_size = switch (bun.sys.read(pipe_max_size_fd, max_pipe_size_buf[0..])) { - .result => |bytes_read| std.fmt.parseInt(i64, strings.trim(max_pipe_size_buf[0..bytes_read], "\n"), 10) catch |err| { - log("Failed to parse /proc/sys/fs/pipe-max-size: {any}\n", .{@errorName(err)}); - return default_out_size; - }, - .err => |err| { - log("Failed to read /proc/sys/fs/pipe-max-size: {d}\n", .{err.errno}); - return default_out_size; - }, - }; - - // we set the absolute max to 8 MB because honestly that's a huge pipe - // my current linux machine only goes up to 1 MB, so that's very unlikely to be hit - return @min(@as(c_int, @truncate(max_pipe_size -| 32)), 1024 * 1024 * 8); - } - }.once, c_int)), - ); -} - -pub fn existsOSPath(path: bun.OSPathSlice) bool { - if (comptime Environment.isPosix) { - return system.access(path, 0) == 0; - } - - if (comptime Environment.isWindows) { - const rc = kernel32.GetFileAttributesW(path) != windows.INVALID_FILE_ATTRIBUTES; - if (rc == windows.FALSE) { - return false; - } - return true; - } - - @compileError("TODO: existsOSPath"); -} - -pub fn isExecutableFileOSPath(path: bun.OSPathSlice) bool { - if (comptime Environment.isPosix) { - return bun.is_executable_fileZ(path); - } - - if (comptime Environment.isWindows) { - var out: windows.DWORD = 8; - const rc = kernel32.GetBinaryTypeW(path, &out); - log("GetBinaryTypeW({}) = {d}", .{ bun.String.init(path), out }); - - if (rc == windows.FALSE) { - return false; - } - - return switch (out) { - kernel32.SCS_32BIT_BINARY, - kernel32.SCS_64BIT_BINARY, - kernel32.SCS_DOS_BINARY, - kernel32.SCS_OS216_BINARY, - kernel32.SCS_PIF_BINARY, - kernel32.SCS_POSIX_BINARY, - => true, - else => false, - }; - } - - @compileError("TODO: isExecutablePath"); -} - -pub fn isExecutableFilePath(path: anytype) bool { - const Type = @TypeOf(path); - if (comptime Environment.isPosix) { - switch (Type) { - *[*:0]const u8, *[*:0]u8, [*:0]const u8, [*:0]u8 => return bun.is_executable_fileZ(path), - [:0]const u8, [:0]u8 => return bun.is_executable_fileZ(path.ptr), - []const u8, []u8 => return bun.is_executable_fileZ(&(std.os.toPosixPath(path) catch return false)), - else => @compileError("TODO: isExecutableFilePath"), - } - } - - if (comptime Environment.isWindows) { - var buf: [(bun.MAX_PATH_BYTES / 2) + 1]u16 = undefined; - return isExecutableFileOSPath(bun.strings.toWPath(&buf, path)); - } - - @compileError("TODO: isExecutablePath"); -} - -pub fn setFileOffset(fd: bun.FileDescriptor, offset: usize) Maybe(void) { - if (comptime Environment.isLinux) { - return Maybe(void).errnoSysFd( - linux.lseek(@intCast(fd), @intCast(offset), os.SEEK.SET), - .lseek, - @as(bun.FileDescriptor, @intCast(fd)), - ) orelse Maybe(void).success; - } - - if (comptime Environment.isMac) { - return Maybe(void).errnoSysFd( - std.c.lseek(fd, @as(std.c.off_t, @intCast(offset)), os.SEEK.SET), - .lseek, - @as(bun.FileDescriptor, @intCast(fd)), - ) orelse Maybe(void).success; - } - - if (comptime Environment.isWindows) { - const offset_high: u64 = @as(u32, @intCast(offset >> 32)); - const offset_low: u64 = @as(u32, @intCast(offset & 0xFFFFFFFF)); - var plarge_integer: i64 = @bitCast(offset_high); - const rc = kernel32.SetFilePointerEx( - bun.fdcast(fd), - @as(windows.LARGE_INTEGER, @bitCast(offset_low)), - &plarge_integer, - windows.FILE_BEGIN, - ); - if (rc == windows.FALSE) { - return Maybe(void).errnoSys(0, .lseek) orelse Maybe(void).success; - } - return Maybe(void).success; - } -} - -pub fn dup(fd: bun.FileDescriptor) Maybe(bun.FileDescriptor) { - if (comptime Environment.isWindows) { - var target: windows.HANDLE = undefined; - const process = kernel32.GetCurrentProcess(); - const out = kernel32.DuplicateHandle( - process, - bun.fdcast(fd), - process, - &target, - 0, - w.TRUE, - w.DUPLICATE_SAME_ACCESS, - ); - if (out == 0) { - if (Maybe(bun.FileDescriptor).errnoSysFd(0, .dup, fd)) |err| { - return err; - } - } - return Maybe(bun.FileDescriptor){ .result = bun.toFD(target.*) }; - } - - const out = std.c.dup(fd); - return Maybe(bun.FileDescriptor).errnoSysFd(out, .dup, fd) orelse Maybe(bun.FileDescriptor){ .result = bun.toFD(out) }; -} diff --git a/src/bun.js/node/types.zig b/src/bun.js/node/types.zig index f0609f45ed..c5138e0945 100644 --- a/src/bun.js/node/types.zig +++ b/src/bun.js/node/types.zig @@ -2554,14 +2554,15 @@ pub const Process = struct { // When we update the cwd from JS, we have to update the bundler's version as well // However, this might be called many times in a row, so we use a pre-allocated buffer // that way we don't have to worry about garbage collector - JSC.VirtualMachine.get().bundler.fs.top_level_dir = bun.getcwd(&JSC.VirtualMachine.get().bundler.fs.top_level_dir_buf) catch { - _ = Syscall.chdir(@as([:0]const u8, @ptrCast(JSC.VirtualMachine.get().bundler.fs.top_level_dir))); + var fs = JSC.VirtualMachine.get().bundler.fs; + fs.top_level_dir = bun.getcwd(&fs.top_level_dir_buf) catch { + _ = Syscall.chdir(@as([:0]const u8, @ptrCast(fs.top_level_dir))); return JSC.toInvalidArguments("Invalid path", .{}, globalObject.ref()); }; - JSC.VirtualMachine.get().bundler.fs.top_level_dir_buf[JSC.VirtualMachine.get().bundler.fs.top_level_dir.len] = std.fs.path.sep; - JSC.VirtualMachine.get().bundler.fs.top_level_dir_buf[JSC.VirtualMachine.get().bundler.fs.top_level_dir.len + 1] = 0; - JSC.VirtualMachine.get().bundler.fs.top_level_dir = JSC.VirtualMachine.get().bundler.fs.top_level_dir_buf[0 .. JSC.VirtualMachine.get().bundler.fs.top_level_dir.len + 1]; + fs.top_level_dir_buf[fs.top_level_dir.len] = std.fs.path.sep; + fs.top_level_dir_buf[fs.top_level_dir.len + 1] = 0; + fs.top_level_dir = fs.top_level_dir_buf[0 .. fs.top_level_dir.len + 1]; return JSC.JSValue.jsUndefined(); }, diff --git a/src/bun.zig b/src/bun.zig index 4da5a99844..c2cb0f1f01 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -1052,7 +1052,6 @@ pub const fs = @import("./fs.zig"); pub const Bundler = bundler.Bundler; pub const bundler = @import("./bundler.zig"); pub const which = @import("./which.zig").which; -pub const is_executable_fileZ = @import("./which.zig").is_executable_file; pub const js_parser = @import("./js_parser.zig"); pub const js_printer = @import("./js_printer.zig"); pub const js_lexer = @import("./js_lexer.zig"); @@ -1140,11 +1139,13 @@ pub fn getcwdAlloc(allocator: std.mem.Allocator) ![]u8 { /// On Linux, when `/proc/self/fd` is not available, this function will attempt to use `fchdir` and `getcwd` to get the path instead. pub fn getFdPath(fd_: anytype, buf: *[@This().MAX_PATH_BYTES]u8) ![]u8 { const fd = fdcast(toFD(fd_)); + if (comptime Environment.isWindows) { var temp: [MAX_PATH_BYTES]u8 = undefined; var temp_slice = try std.os.getFdPath(fd, &temp); return path.normalizeBuf(temp_slice, buf, .loose); } + if (comptime !Environment.isLinux) { return try std.os.getFdPath(fd, buf); } @@ -1990,3 +1991,17 @@ pub fn makePath(dir: std.fs.Dir, sub_path: []const u8) !void { } pub const Async = @import("async"); + +/// This is a helper for writing path string literals that are compatible with Windows. +/// Returns the string as-is on linux, on windows replace `/` with `\` +pub inline fn pathLiteral(comptime literal: anytype) *const [literal.len:0]u8 { + if (!Environment.isWindows) return literal; + return comptime { + var buf: [literal.len:0]u8 = undefined; + for (literal, 0..) |c, i| { + buf[i] = if (c == '/') '\\' else c; + } + buf[buf.len] = 0; + return &buf; + }; +} diff --git a/src/cli.zig b/src/cli.zig index 18289732b8..a4effd042b 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -936,7 +936,7 @@ pub const HelpCommand = struct { switch (reason) { .explicit => Output.pretty( - "Bun: a fast JavaScript runtime, package manager, bundler and test runner. (" ++ Global.package_json_version ++ ")\n\n" ++ fmt, + "Bun: a fast JavaScript runtime, package manager, bundler and test runner. (" ++ Global.package_json_version_with_revision ++ ")\n\n" ++ fmt, args, ), .invalid_command => Output.prettyError( diff --git a/src/cli/README-for-init.md b/src/cli/README-for-init.md index 7a0dced5d9..9dbda4bb7d 100644 --- a/src/cli/README-for-init.md +++ b/src/cli/README-for-init.md @@ -12,4 +12,4 @@ To run: bun run {[entryPoint]s} ``` -This project was created using `bun init` in bun v{[bunVersion]any}. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. +This project was created using `bun init` in bun v{[bunVersion]s}. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/src/cli/install.ps1 b/src/cli/install.ps1 new file mode 100644 index 0000000000..3ae81f67a2 --- /dev/null +++ b/src/cli/install.ps1 @@ -0,0 +1,117 @@ +#!/usr/bin/env pwsh +param( + # TODO: change this to 'latest' when Bun for Windows is stable. + [string]$Version = "canary" +); + +$ErrorActionPreference = "Stop" + +# filter out 32 bit and arm +if ($env:PROCESSOR_ARCHITECTURE -ne "AMD64") { + Write-Output "Install Failed:" + Write-Output "Bun for Windows is only available for 64-bit Windows.`n" + exit 1 +} + +# if a semver is given, we need to adjust it to this format: bun-v0.0.0 +if ($Version -match "^\d+\.\d+\.\d+$") { + $Version = "bun-v$Version" +} +elseif ($Version -match "^v\d+\.\d+\.\d+$") { + $Version = "bun-$Version" +} +# todo: remove this when Bun for Windows is stable +elseif ($Version -eq "latest") { + $Version = "canary" +} + +$BunRoot = if ($env:BUN_INSTALL) { $env:BUN_INSTALL } else { "${Home}\.bun" } +$BunBin = mkdir -Force "${BunRoot}\bin" + +$Target = "bun-windows-x64" +$BaseURL = "https://github.com/oven-sh/bun/releases" +$URL = "$BaseURL/$(if ($Version -eq "latest") { "latest/download" } else { "download/$Version" })/$Target.zip" + +$ZipPath = "${BunBin}\$Target.zip" + +$DisplayVersion = $( + if ($Version -eq "latest") { "Bun" } + elseif ($Version -eq "canary") { "Bun Canary" } + elseif ($Version -match "^bun-v\d+\.\d+\.\d+$") { "Bun $($Version.Substring(4))" } + else { "Bun tag='${Version}'" } +) + +$null = mkdir -Force $BunBin +Remove-Item -Force $ZipPath -ErrorAction SilentlyContinue +curl.exe "-#SfLo" "$ZipPath" "$URL" +if ($LASTEXITCODE -ne 0) { + Write-Output "Install Failed - could not download $URL" + Write-Output "The command 'curl.exe $URL -o $ZipPath' exited with code ${LASTEXITCODE}`n" + exit 1 +} +if (!(Test-Path $ZipPath)) { + Write-Output "Install Failed - could not download $URL" + Write-Output "The file '$ZipPath' does not exist. Did an antivirus delete it?`n" + exit 1 +} +try { + $lastProgressPreference = $global:ProgressPreference + $global:ProgressPreference = 'SilentlyContinue'; + Expand-Archive "$ZipPath" "$BunBin" -Force + $global:ProgressPreference = $lastProgressPreference + if (!(Test-Path "${BunBin}\$Target\bun.exe")) { + throw "The file '${BunBin}\$Target\bun.exe' does not exist. Did an antivirus delete it?`n" + } +} catch { + Write-Output "Install Failed - could not unzip $ZipPath" + Write-Error $_ + exit 1 +} +Move-Item "${BunBin}\$Target\bun.exe" "${BunBin}\bun.exe" -Force + +Remove-Item "${BunBin}\$Target" -Recurse -Force +Remove-Item $ZipPath -Force + +$BunRevision = "$(& "${BunBin}\bun.exe" --revision)" +if ($LASTEXITCODE -ne 0) { + Write-Output "Install Failed - could not verify bun.exe" + Write-Output "The command '${BunBin}\bun.exe --revision' exited with code ${LASTEXITCODE}`n" + exit 1 +} +$DisplayVersion = if ($BunRevision -like "*-canary.*") { + "${BunRevision}" +} else { + "$(& "${BunBin}\bun.exe" --version)" +} + +$C_RESET = [char]27 + "[0m" +$C_GREEN = [char]27 + "[1;32m" + +Write-Output "${C_GREEN}Bun ${DisplayVersion} was installed successfully!${C_RESET}" +Write-Output "The binary is located at ${BunBin}\bun.exe`n" + +Write-Warning "Bun for Windows is currently experimental.`nFor a more stable experience, please install Bun within WSL:`nhttps://bun.sh/docs/installation`n" + +$hasExistingOther = $false; +try { + $existing = Get-Command bun -ErrorAction + if ($existing.Source -ne "${BunBin}\bun.exe") { + Write-Warning "Note: Another bun.exe is already in %PATH% at $($existing.Source)`nTyping 'bun' in your terminal will not use what was just installed.`n" + $hasExistingOther = $true; + } +} catch {} + +$User = [System.EnvironmentVariableTarget]::User +$Path = [System.Environment]::GetEnvironmentVariable('Path', $User) -split ';' +if ($Path -notcontains $BunBin) { + $env:Path = ($Path -join ';') + ";${BunBin}" + [System.Environment]::SetEnvironmentVariable('Path', "${env:Path}", $User) +} + +if(!$hasExistingOther) { + if((Get-Command -ErrorAction SilentlyContinue bun) -eq $null) { + Write-Output "To get started, restart your terminal session, then type ``bun```n" + } else { + Write-Output "Type ``bun`` in your terminal to get started`n" + } +} diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index 391e5c02ad..66c9966f90 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -265,7 +265,11 @@ pub const RunCommand = struct { combined_script = combined_script_buf; } - var argv = [_]string{ shell_bin, "-c", combined_script }; + var argv = [_]string{ + shell_bin, + if (Environment.isWindows) "/c" else "-c", + combined_script, + }; if (!silent) { Output.prettyErrorln("$ {s}", .{combined_script}); @@ -595,11 +599,11 @@ pub const RunCommand = struct { } { - var needs_colon = false; + var needs_delim = false; if (package_json_dir.len > 0) { - defer needs_colon = true; - if (needs_colon) { - try new_path.append(':'); + defer needs_delim = true; + if (needs_delim) { + try new_path.append(std.fs.path.delimiter); } try new_path.appendSlice(package_json_dir); } @@ -609,19 +613,19 @@ pub const RunCommand = struct { // Directories are added to bin_dirs in top-down order // That means the parent-most node_modules/.bin will be first while (bin_dir_i >= 0) : (bin_dir_i -= 1) { - defer needs_colon = true; - if (needs_colon) { - try new_path.append(':'); + defer needs_delim = true; + if (needs_delim) { + try new_path.append(std.fs.path.delimiter); } try new_path.appendSlice(bin_dirs[@as(usize, @intCast(bin_dir_i))]); } - if (needs_colon) { - try new_path.append(':'); + if (needs_delim) { + try new_path.append(std.fs.path.delimiter); } try new_path.appendSlice(root_dir_info.abs_path); - try new_path.appendSlice("node_modules/.bin"); - try new_path.append(':'); + try new_path.appendSlice(bun.pathLiteral("node_modules/.bin")); + try new_path.append(std.fs.path.delimiter); try new_path.appendSlice(PATH); } @@ -1131,10 +1135,10 @@ pub const RunCommand = struct { const PATH = this_bundler.env.map.get("PATH") orelse ""; var path_for_which = PATH; if (comptime bin_dirs_only) { - path_for_which = ""; - if (ORIGINAL_PATH.len < PATH.len) { path_for_which = PATH[0 .. PATH.len - (ORIGINAL_PATH.len + 1)]; + } else { + path_for_which = ""; } } diff --git a/src/cli/upgrade_command.zig b/src/cli/upgrade_command.zig index 0103c7d4c1..196569df88 100644 --- a/src/cli/upgrade_command.zig +++ b/src/cli/upgrade_command.zig @@ -394,8 +394,17 @@ pub const UpgradeCommand = struct { return null; } - const exe_subpath = Version.folder_name ++ std.fs.path.sep_str ++ "bun"; - const profile_exe_subpath = Version.profile_folder_name ++ std.fs.path.sep_str ++ "bun-profile"; + + const exe_suffix = if (Environment.isWindows) ".exe" else ""; + + const exe_subpath = Version.folder_name ++ std.fs.path.sep_str ++ "bun" ++ exe_suffix; + const profile_exe_subpath = Version.profile_folder_name ++ std.fs.path.sep_str ++ "bun-profile" ++ exe_suffix; + + const manual_upgrade_command = switch (Environment.os) { + .linux, .mac => "curl -fsSL https://bun.sh/install | bash", + .windows => "TODO", + else => "TODO", + }; pub fn exec(ctx: Command.Context) !void { @setCold(true); @@ -405,10 +414,10 @@ pub const UpgradeCommand = struct { \\Bun upgrade failed with error: {s} \\ \\Please upgrade manually: - \\ curl -fsSL https://bun.sh/install | bash + \\ {s} \\ \\ - , .{@errorName(err)}); + , .{ @errorName(err), manual_upgrade_command }); Global.exit(1); }; } @@ -626,7 +635,7 @@ pub const UpgradeCommand = struct { // Run a powershell script to unzip the file var unzip_script = try std.fmt.allocPrint( ctx.allocator, - "Expand-Archive -Path {s} -DestinationPath {s} -Force", + "Expand-Archive -Path {s} {s} -Force", .{ tmpname, tmpdir_path, @@ -729,13 +738,13 @@ pub const UpgradeCommand = struct { // Check if the versions are the same const target_stat = target_dir.statFile(target_filename) catch |err| { save_dir_.deleteTree(version_name) catch {}; - Output.prettyErrorln("error: Failed to stat target Bun {s}", .{@errorName(err)}); + Output.prettyErrorln("error: {s} while trying to stat target {s} ", .{ @errorName(err), target_filename }); Global.exit(1); }; const dest_stat = save_dir.statFile(exe) catch |err| { save_dir_.deleteTree(version_name) catch {}; - Output.prettyErrorln("error: Failed to stat source Bun {s}", .{@errorName(err)}); + Output.prettyErrorln("error: {s} while trying to stat source {s}", .{ @errorName(err), exe }); Global.exit(1); }; @@ -744,13 +753,13 @@ pub const UpgradeCommand = struct { const target_hash = bun.hash(target_dir.readFile(target_filename, input_buf) catch |err| { save_dir_.deleteTree(version_name) catch {}; - Output.prettyErrorln("error: Failed to read target Bun {s}", .{@errorName(err)}); + Output.prettyErrorln("error: Failed to read target bun {s}", .{@errorName(err)}); Global.exit(1); }); const source_hash = bun.hash(save_dir.readFile(exe, input_buf) catch |err| { save_dir_.deleteTree(version_name) catch {}; - Output.prettyErrorln("error: Failed to read source Bun {s}", .{@errorName(err)}); + Output.prettyErrorln("error: Failed to read source bun {s}", .{@errorName(err)}); Global.exit(1); }); @@ -769,21 +778,31 @@ pub const UpgradeCommand = struct { } } + var outdated_filename: if (Environment.isWindows) ?stringZ else ?void = null; + if (env_loader.map.get("BUN_DRY_RUN") == null) { if (comptime Environment.isWindows) { // On Windows, we cannot replace the running executable directly. // we rename the old executable to a temporary name, and then move the new executable to the old name. // This is because Windows locks the executable while it's running. - - // var tmpname = try std.fmt.allocPrint(ctx.allocator, "{s}.old.exe", .{target_filename}); - - } else { - C.moveFileZ(save_dir.fd, exe, target_dir.fd, target_filename) catch |err| { + current_executable_buf[target_dir_.len] = '\\'; + outdated_filename = try std.fmt.allocPrintZ(ctx.allocator, "{s}\\{s}.outdated", .{ + target_dirname, + target_filename, + }); + std.os.rename(destination_executable_, outdated_filename.?) catch |err| { save_dir_.deleteTree(version_name) catch {}; - Output.prettyErrorln("error: Failed to move new version of Bun due to {s}. You could try the install script instead:\n curl -fsSL https://bun.sh/install | bash", .{@errorName(err)}); + Output.prettyErrorln("error: Failed to rename current executable {s}", .{@errorName(err)}); Global.exit(1); }; + current_executable_buf[target_dir_.len] = 0; } + + C.moveFileZ(save_dir.fd, exe, target_dir.fd, target_filename) catch |err| { + save_dir_.deleteTree(version_name) catch {}; + Output.prettyErrorln("error: Failed to move new version of Bun due to {s}. You could try the install script instead:\n curl -fsSL https://bun.sh/install | bash", .{@errorName(err)}); + Global.exit(1); + }; } // Ensure completions are up to date. @@ -849,7 +868,51 @@ pub const UpgradeCommand = struct { } Output.flush(); - return; + + if (Environment.isWindows) { + if (outdated_filename) |to_remove| { + current_executable_buf[target_dir_.len] = '\\'; + var delete_old_script = try std.fmt.allocPrint( + ctx.allocator, + // What is this? + // 1. spawns powershell + // 2. waits for all processes with the same path as the current executable to exit (including the current process) + // 3. deletes the old executable + // + // probably possible to hit a race condition, but i think the worst case is simply the file not getting deleted. + // + // in that edge case, the next time you upgrade it will simply override itself, fixing the bug. + // + // -NoNewWindow doesnt work, will keep the parent alive it seems + // -WindowStyle Hidden seems to just do nothing, not sure why. + // Using -WindowStyle Minimized seems to work, but you can spot a powershell icon appear in your taskbar for about ~1 second + // + // Alternative: we could simply do nothing and leave the `.outdated` file. + \\Start-Process powershell.exe -WindowStyle Minimized -ArgumentList "-NoProfile","-ExecutionPolicy","Bypass","-Command",'&{{$ErrorActionPreference=''SilentlyContinue''; Get-Process|Where-Object{{ $_.Path -eq ''{s}'' }}|Wait-Process; Remove-Item -Path ''{s}'' -Force }};'; exit + , + .{ + destination_executable_, + to_remove, + }, + ); + + var delete_argv = [_]string{ + "powershell.exe", + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command", + delete_old_script, + }; + + _ = std.ChildProcess.run(.{ + .allocator = ctx.allocator, + .argv = &delete_argv, + .cwd = tmpdir_path, + .max_output_bytes = 512, + }) catch {}; + } + } } } }; diff --git a/src/codegen/bundle-functions.ts b/src/codegen/bundle-functions.ts index 7b33d0dbb1..7d6e8263e0 100644 --- a/src/codegen/bundle-functions.ts +++ b/src/codegen/bundle-functions.ts @@ -28,7 +28,6 @@ const { requireTransformer, } = createInternalModuleRegistry(path.join(import.meta.dir, "../js")); -if (existsSync(TMP_DIR)) rmSync(TMP_DIR, { recursive: true }); mkdirSync(TMP_DIR, { recursive: true }); interface ParsedBuiltin { diff --git a/src/deps/zlib b/src/deps/zlib index 8856740263..886098f3f3 160000 --- a/src/deps/zlib +++ b/src/deps/zlib @@ -1 +1 @@ -Subproject commit 885674026394870b7e7a05b7bf1ec5eb7bd8a9c0 +Subproject commit 886098f3f339617b4243b286f5ed364b9989e245 diff --git a/src/env.zig b/src/env.zig index beb2385706..86d481e4b9 100644 --- a/src/env.zig +++ b/src/env.zig @@ -32,12 +32,15 @@ const BuildOptions = if (isTest) struct { pub const sha = "0000000000000000000000000000000000000000"; pub const is_canary = false; pub const base_path = "/tmp"; + pub const canary_revision = 0; } else @import("root").build_options; pub const baseline = BuildOptions.baseline; pub const enableSIMD: bool = !baseline; pub const git_sha = BuildOptions.sha; +pub const git_sha_short = if (BuildOptions.sha.len > 0) BuildOptions.sha[0..9] else ""; pub const is_canary = BuildOptions.is_canary; +pub const canary_revision = if (is_canary) BuildOptions.canary_revision else ""; pub const dump_source = isDebug and !isTest; pub const base_path = BuildOptions.base_path ++ "/"; @@ -57,6 +60,7 @@ pub const OperatingSystem = enum { // wAsM is nOt aN oPeRaTiNg SyStEm wasm, + /// user-facing name with capitalization pub fn displayString(self: OperatingSystem) []const u8 { return switch (self) { .mac => "macOS", @@ -65,6 +69,16 @@ pub const OperatingSystem = enum { .wasm => "WASM", }; } + + /// same format as `process.platform` + pub fn nameString(self: OperatingSystem) []const u8 { + return switch (self) { + .mac => "darwin", + .linux => "linux", + .windows => "win32", + .wasm => "wasm", + }; + } }; pub const os: OperatingSystem = if (isMac) diff --git a/src/env_loader.zig b/src/env_loader.zig index a0ff6d4123..2e18e5cca5 100644 --- a/src/env_loader.zig +++ b/src/env_loader.zig @@ -915,7 +915,12 @@ pub const Map = struct { while (iter_.next()) |entry| { // Allow var from .env.development or .env.production to be loaded again if (!entry.value_ptr.conditional) { - try env_map.putMove(bun.constStrToU8(entry.key_ptr.*), bun.constStrToU8(entry.value_ptr.value)); + // TODO(@paperdave): this crashes on windows. i remember there being a merge conflict with these two implementations. not sure what we should keep + if (Environment.isWindows) { + try env_map.put(bun.constStrToU8(entry.key_ptr.*), bun.constStrToU8(entry.value_ptr.value)); + } else { + try env_map.putMove(bun.constStrToU8(entry.key_ptr.*), bun.constStrToU8(entry.value_ptr.value)); + } } } diff --git a/src/fs.zig b/src/fs.zig index 01a2451a95..a7948ff2a2 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -34,7 +34,7 @@ pub const Preallocate = struct { }; pub const FileSystem = struct { - top_level_dir: string = "/", + top_level_dir: string = if (Environment.isWindows) "C:\\" else "/", // used on subsequent updates top_level_dir_buf: [bun.MAX_PATH_BYTES]u8 = undefined, @@ -106,29 +106,26 @@ pub const FileSystem = struct { } pub fn initWithForce( - top_level_dir: ?string, + top_level_dir_: ?string, comptime force: bool, ) !*FileSystem { const allocator = bun.fs_allocator; - var _top_level_dir = top_level_dir orelse (if (Environment.isBrowser) "/project/" else try bun.getcwdAlloc(allocator)); + var top_level_dir = top_level_dir_ orelse (if (Environment.isBrowser) "/project/" else try bun.getcwdAlloc(allocator)); // Ensure there's a trailing separator in the top level directory // This makes path resolution more reliable - if (!bun.path.isSepAny(_top_level_dir[_top_level_dir.len - 1])) { - const tld = try allocator.alloc(u8, _top_level_dir.len + 1); - bun.copy(u8, tld, _top_level_dir); - tld[tld.len - 1] = '/'; - // if (!isBrowser) { - // allocator.free(_top_level_dir); - // } - _top_level_dir = tld; + if (!bun.path.isSepAny(top_level_dir[top_level_dir.len - 1])) { + const tld = try allocator.alloc(u8, top_level_dir.len + 1); + bun.copy(u8, tld, top_level_dir); + tld[tld.len - 1] = std.fs.path.sep; + top_level_dir = tld; } if (!instance_loaded or force) { instance = FileSystem{ - .top_level_dir = _top_level_dir, + .top_level_dir = top_level_dir, .fs = Implementation.init( - _top_level_dir, + top_level_dir, ), // must always use default_allocator since the other allocators may not be threadsafe when an element resizes .dirname_store = DirnameStore.init(bun.default_allocator), diff --git a/src/install/install.zig b/src/install/install.zig index 9fba86e7dc..0818a62d27 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -4834,7 +4834,7 @@ pub const PackageManager = struct { explicit_global_directory: string = "", /// destination directory to link bins into // must be a variable due to global installs and bunx - bin_path: stringZ = "node_modules/.bin", + bin_path: stringZ = bun.pathLiteral("node_modules/.bin"), lockfile_path: stringZ = Lockfile.default_filename, did_override_default_scope: bool = false, @@ -4932,11 +4932,20 @@ pub const PackageManager = struct { return try std.fs.cwd().makeOpenPathIterable(path, .{}); } - if (bun.getenvZ("XDG_CACHE_HOME") orelse bun.getenvZ("HOME")) |home_dir| { - var buf: [bun.MAX_PATH_BYTES]u8 = undefined; - var parts = [_]string{ ".bun", "install", "global" }; - var path = Path.joinAbsStringBuf(home_dir, &buf, &parts, .auto); - return try std.fs.cwd().makeOpenPathIterable(path, .{}); + if (!Environment.isWindows) { + if (bun.getenvZ("XDG_CACHE_HOME") orelse bun.getenvZ("HOME")) |home_dir| { + var buf: [bun.MAX_PATH_BYTES]u8 = undefined; + var parts = [_]string{ ".bun", "install", "global" }; + var path = Path.joinAbsStringBuf(home_dir, &buf, &parts, .auto); + return try std.fs.cwd().makeOpenPathIterable(path, .{}); + } + } else { + if (bun.getenvZ("USERPROFILE")) |home_dir| { + var buf: [bun.MAX_PATH_BYTES]u8 = undefined; + var parts = [_]string{ ".bun", "install", "global" }; + var path = Path.joinAbsStringBuf(home_dir, &buf, &parts, .auto); + return try std.fs.cwd().makeOpenPathIterable(path, .{}); + } } return error.@"No global directory found"; diff --git a/src/resolver/resolver.zig b/src/resolver/resolver.zig index 7e39a062c1..a507d06802 100644 --- a/src/resolver/resolver.zig +++ b/src/resolver/resolver.zig @@ -3694,7 +3694,7 @@ pub const Resolver = struct { } const this_dir = std.fs.Dir{ .fd = bun.fdcast(fd) }; - var file = this_dir.openDirZ("node_modules/.bin", .{}, true) catch break :append_bin_dir; + var file = this_dir.openDirZ(bun.pathLiteral("node_modules/.bin"), .{}, true) catch break :append_bin_dir; defer file.close(); var bin_path = bun.getFdPath(file.fd, bufs(.node_bin_path)) catch break :append_bin_dir; bin_folders_lock.lock(); diff --git a/src/string_immutable.zig b/src/string_immutable.zig index 309d394fa2..86d7d2501f 100644 --- a/src/string_immutable.zig +++ b/src/string_immutable.zig @@ -929,6 +929,10 @@ pub fn hasPrefixComptime(self: string, comptime alt: anytype) bool { return self.len >= alt.len and eqlComptimeCheckLenWithType(u8, self[0..alt.len], alt, false); } +pub fn hasPrefixComptimeUTF16(self: []const u16, comptime alt: []const u8) bool { + return self.len >= alt.len and eqlComptimeCheckLenWithType(u16, self[0..alt.len], comptime toUTF16Literal(alt), false); +} + pub fn hasSuffixComptime(self: string, comptime alt: anytype) bool { return self.len >= alt.len and eqlComptimeCheckLenWithType(u8, self[self.len - alt.len ..], alt, false); } diff --git a/src/sys.zig b/src/sys.zig index 4f8164a192..07c70a5777 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -407,7 +407,7 @@ pub noinline fn openDirAtWindowsA( var wbuf: bun.MAX_WPATH = undefined; return openDirAtWindows(dirFd, bun.strings.toNTDir(&wbuf, path), iterable, no_follow); } -pub fn openatWindows(dirfD: bun.FileDescriptor, path: []const u16, flags: bun.Mode) Maybe(bun.FileDescriptor) { +pub fn openatWindows(dirfD: bun.FileDescriptor, path_: []const u16, flags: bun.Mode) Maybe(bun.FileDescriptor) { const nonblock = flags & O.NONBLOCK != 0; var access_mask: w.ULONG = w.READ_CONTROL | w.FILE_WRITE_ATTRIBUTES | w.SYNCHRONIZE; @@ -423,6 +423,8 @@ pub fn openatWindows(dirfD: bun.FileDescriptor, path: []const u16, flags: bun.Mo var result: windows.HANDLE = undefined; + const path = if (bun.strings.hasPrefixComptimeUTF16(path_, ".\\")) path_[2..] else path_; + const path_len_bytes = std.math.cast(u16, path.len * 2) orelse return .{ .err = .{ .errno = @intFromEnum(bun.C.E.NOMEM), @@ -1380,11 +1382,7 @@ pub fn existsOSPath(path: bun.OSPathSlice) bool { } if (comptime Environment.isWindows) { - const rc = kernel32.GetFileAttributesW(path) != windows.INVALID_FILE_ATTRIBUTES; - if (rc == windows.FALSE) { - return false; - } - return true; + return kernel32.GetFileAttributesW(path.ptr) != windows.INVALID_FILE_ATTRIBUTES; } @compileError("TODO: existsOSPath"); @@ -1398,27 +1396,26 @@ pub fn exists(path: []const u8) bool { if (comptime Environment.isWindows) { var wbuf: bun.MAX_WPATH = undefined; const path_to_use = bun.strings.toWPath(&wbuf, path); - return kernel32.GetFileAttributesW(path_to_use.ptr) != os.windows.INVALID_FILE_ATTRIBUTES; + return kernel32.GetFileAttributesW(path_to_use.ptr) != windows.INVALID_FILE_ATTRIBUTES; } @compileError("TODO: existsOSPath"); } +pub extern "C" fn is_executable_file(path: [*:0]const u8) bool; + pub fn isExecutableFileOSPath(path: bun.OSPathSlice) bool { if (comptime Environment.isPosix) { - return bun.is_executable_fileZ(path); + return is_executable_file(path); } if (comptime Environment.isWindows) { - var out: windows.DWORD = 8; + var out: windows.DWORD = 0; const rc = kernel32.GetBinaryTypeW(path, &out); - log("GetBinaryTypeW({}) = {d}", .{ bun.strings.fmtUTF16(path), out }); - if (rc == windows.FALSE) { - return false; - } - - return switch (out) { + const result = if (rc == windows.FALSE) + false + else switch (out) { kernel32.SCS_32BIT_BINARY, kernel32.SCS_64BIT_BINARY, kernel32.SCS_DOS_BINARY, @@ -1428,6 +1425,10 @@ pub fn isExecutableFileOSPath(path: bun.OSPathSlice) bool { => true, else => false, }; + + log("GetBinaryTypeW({}) = {d}. isExecutable={}", .{ bun.strings.fmtUTF16(path), out, result }); + + return result; } @compileError("TODO: isExecutablePath"); @@ -1437,9 +1438,9 @@ pub fn isExecutableFilePath(path: anytype) bool { const Type = @TypeOf(path); if (comptime Environment.isPosix) { switch (Type) { - *[*:0]const u8, *[*:0]u8, [*:0]const u8, [*:0]u8 => return bun.is_executable_fileZ(path), - [:0]const u8, [:0]u8 => return bun.is_executable_fileZ(path.ptr), - []const u8, []u8 => return bun.is_executable_fileZ( + *[*:0]const u8, *[*:0]u8, [*:0]const u8, [*:0]u8 => return is_executable_file(path), + [:0]const u8, [:0]u8 => return is_executable_file(path.ptr), + []const u8, []u8 => return is_executable_file( &(std.os.toPosixPath(path) catch return false), ), else => @compileError("TODO: isExecutableFilePath"), diff --git a/src/which.zig b/src/which.zig index 2a0dc77940..10423621bb 100644 --- a/src/which.zig +++ b/src/which.zig @@ -1,21 +1,16 @@ const std = @import("std"); const bun = @import("root").bun; + fn isValid(buf: *[bun.MAX_PATH_BYTES]u8, segment: []const u8, bin: []const u8) ?u16 { bun.copy(u8, buf, segment); buf[segment.len] = std.fs.path.sep; bun.copy(u8, buf[segment.len + 1 ..], bin); buf[segment.len + 1 + bin.len ..][0] = 0; const filepath = buf[0 .. segment.len + 1 + bin.len :0]; - if (!checkPath(filepath)) return null; + if (!bun.sys.isExecutableFilePath(filepath)) return null; return @as(u16, @intCast(filepath.len)); } -pub extern "C" fn is_executable_file(path: [*:0]const u8) bool; -fn checkPath(filepath: [:0]const u8) bool { - bun.JSC.markBinding(@src()); - return bun.sys.isExecutableFilePath(filepath); -} - // Like /usr/bin/which but without needing to exec a child process // Remember to resolve the symlink if necessary pub fn which(buf: *[bun.MAX_PATH_BYTES]u8, path: []const u8, cwd: []const u8, bin: []const u8) ?[:0]const u8 { @@ -26,7 +21,7 @@ pub fn which(buf: *[bun.MAX_PATH_BYTES]u8, path: []const u8, cwd: []const u8, bi bun.copy(u8, buf, bin); buf[bin.len] = 0; var binZ: [:0]u8 = buf[0..bin.len :0]; - if (checkPath(binZ)) return binZ; + if (bun.sys.isExecutableFilePath(binZ)) return binZ; // note that directories are often executable // TODO: should we return null here? What about the case where ytou have @@ -39,7 +34,7 @@ pub fn which(buf: *[bun.MAX_PATH_BYTES]u8, path: []const u8, cwd: []const u8, bi } } - var path_iter = std.mem.tokenize(u8, path, ":"); + var path_iter = std.mem.tokenizeScalar(u8, path, std.fs.path.delimiter); while (path_iter.next()) |segment| { if (isValid(buf, segment, bin)) |len| { return buf[0..len :0]; diff --git a/src/windows-app-info.rc b/src/windows-app-info.rc new file mode 100644 index 0000000000..2822798ed0 --- /dev/null +++ b/src/windows-app-info.rc @@ -0,0 +1,29 @@ +#include "windows.h" + +IDI_MYICON ICON "@BUN_ICO_PATH@" + +VS_VERSION_INFO VERSIONINFO +FILEVERSION @Bun_VERSION_MAJOR@,@Bun_VERSION_MINOR@,@Bun_VERSION_PATCH@,0 +PRODUCTVERSION @Bun_VERSION_MAJOR@,@Bun_VERSION_MINOR@,@Bun_VERSION_PATCH@,0 +FILEOS 0x4L +FILETYPE 0x1L +FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "Bun\0" + VALUE "FileVersion", "@Bun_VERSION_WITH_TAG@\0" + VALUE "InternalName", "bun\0" + VALUE "OriginalFilename", "bun.exe\0" + VALUE "ProductName", "Bun\0" + VALUE "ProductVersion", "@Bun_VERSION_WITH_TAG@\0" + VALUE "Copyright", "See https://bun.sh/docs/project/licensing" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file diff --git a/src/windows.zig b/src/windows.zig index 12531fa7c8..47930f20a6 100644 --- a/src/windows.zig +++ b/src/windows.zig @@ -58,6 +58,8 @@ pub usingnamespace ntdll; pub const user32 = windows.user32; pub const advapi32 = windows.advapi32; +pub const INVALID_FILE_ATTRIBUTES = -1; + const std = @import("std"); pub const HANDLE = win32.HANDLE; diff --git a/test/cli/bun.test.ts b/test/cli/bun.test.ts index 5c5715168b..9b48eeba3e 100644 --- a/test/cli/bun.test.ts +++ b/test/cli/bun.test.ts @@ -52,12 +52,10 @@ describe("bun", () => { var revision = stdout.toString().trim(); expect(exitCode).toBe(0); - expect(revision).toStartWith(version.replaceAll("_", "-")); + expect(revision).toStartWith(version); // https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string expect(revision).toMatch( - new RegExp( - "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", - ), + /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/, ); }); }); diff --git a/test/cli/init/init.test.ts b/test/cli/init/init.test.ts new file mode 100644 index 0000000000..d74639fa3e --- /dev/null +++ b/test/cli/init/init.test.ts @@ -0,0 +1,37 @@ +import fs from "fs"; +import path from "path"; +import os from "os"; +import { bunExe, bunEnv } from "harness"; + +test("bun init works", () => { + const temp = fs.mkdtempSync(path.join(os.tmpdir(), "bun-init-X")); + + Bun.spawnSync({ + cmd: [bunExe(), "init", "-y"], + cwd: temp, + stdio: ["ignore", "inherit", "inherit"], + env: bunEnv, + }); + + const pkg = JSON.parse(fs.readFileSync(path.join(temp, "package.json"), "utf8")); + expect(pkg).toEqual({ + "name": path.basename(temp).toLowerCase(), + "module": "index.ts", + "type": "module", + "devDependencies": { + "bun-types": "latest", + }, + "peerDependencies": { + "typescript": "^5.0.0", + }, + }); + const readme = fs.readFileSync(path.join(temp, "README.md"), "utf8"); + expect(readme).toStartWith("# " + path.basename(temp).toLowerCase() + "\n"); + expect(readme).toInclude("v" + Bun.version); + expect(readme).toInclude("index.ts"); + + expect(fs.existsSync(path.join(temp, "index.ts"))).toBe(true); + expect(fs.existsSync(path.join(temp, ".gitignore"))).toBe(true); + expect(fs.existsSync(path.join(temp, "node_modules"))).toBe(true); + expect(fs.existsSync(path.join(temp, "tsconfig.json"))).toBe(true); +});