diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000000..3afb2b0bea496 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [swiftwasm, kateinoigakukun, MaxDesiatov] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index d5084b4b8216d..0000000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ - -Replace this paragraph with a description of your changes and rationale. Provide links to external references/discussions if appropriate. - - -Resolves #NNNNN, fix apple/llvm-project#MMMMM. - - diff --git a/.github/pull.yml b/.github/pull.yml new file mode 100644 index 0000000000000..0f80214603a3c --- /dev/null +++ b/.github/pull.yml @@ -0,0 +1,52 @@ +version: "1" +rules: + - base: swiftwasm + upstream: main + mergeMethod: merge + - base: main + upstream: apple:main + mergeMethod: hardreset + + - base: release/5.3 + upstream: apple:release/5.3 + mergeMethod: hardreset + - base: swiftwasm-release/5.3 + upstream: release/5.3 + mergeMethod: merge + + - base: release/5.4 + upstream: apple:release/5.4 + mergeMethod: hardreset + - base: swiftwasm-release/5.4 + upstream: release/5.4 + mergeMethod: merge + + - base: release/5.5 + upstream: apple:release/5.5 + mergeMethod: hardreset + - base: swiftwasm-release/5.5 + upstream: release/5.5 + mergeMethod: merge + + - base: release/5.6 + upstream: apple:release/5.6 + mergeMethod: hardreset + - base: swiftwasm-release/5.6 + upstream: release/5.6 + mergeMethod: merge + + - base: release/5.7 + upstream: apple:release/5.7 + mergeMethod: hardreset + - base: swiftwasm-release/5.7 + upstream: release/5.7 + mergeMethod: merge + + - base: release/5.8 + upstream: apple:release/5.8 + mergeMethod: hardreset + - base: swiftwasm-release/5.8 + upstream: release/5.8 + mergeMethod: merge + +label: ":arrow_heading_down: Upstream Tracking" diff --git a/.github/scripts/build-matrix.rb b/.github/scripts/build-matrix.rb new file mode 100644 index 0000000000000..5701634d773d6 --- /dev/null +++ b/.github/scripts/build-matrix.rb @@ -0,0 +1,107 @@ +require "json" +require "optparse" + +BASE_MATRIX_ENTRIES = [ + { + "build_os": "ubuntu-18.04", + "agent_query": "ubuntu-20.04", + "target": "ubuntu18.04_x86_64", + "container": "ghcr.io/swiftwasm/swift-ci:main-ubuntu-18.04", + "run_stdlib_test": true, + "run_full_test": false, + "run_e2e_test": true, + "build_hello_wasm": true, + "clean_build_dir": false, + "free_disk_space": true + }, + { + "build_os": "ubuntu-20.04", + "agent_query": "ubuntu-20.04", + "target": "ubuntu20.04_x86_64", + "container": "ghcr.io/swiftwasm/swift-ci:main-ubuntu-20.04", + "run_stdlib_test": true, + "run_full_test": false, + "run_e2e_test": true, + "build_hello_wasm": true, + "clean_build_dir": false, + "free_disk_space": true + }, + { + "build_os": "ubuntu-22.04", + "agent_query": "ubuntu-22.04", + "target": "ubuntu22.04_x86_64", + "container": "ghcr.io/swiftwasm/swift-ci:main-ubuntu-22.04", + "run_stdlib_test": true, + "run_full_test": false, + "run_e2e_test": true, + "build_hello_wasm": true, + "clean_build_dir": false, + "free_disk_space": true + }, + { + "build_os": "amazon-linux-2", + "agent_query": "ubuntu-22.04", + "target": "amazonlinux2_x86_64", + "container": "ghcr.io/swiftwasm/swift-ci:main-amazon-linux-2", + "run_stdlib_test": false, + "run_full_test": false, + "run_e2e_test": false, + "build_hello_wasm": true, + "clean_build_dir": false, + "free_disk_space": true + }, + { + "build_os": "macos-12", + "agent_query": "macos-12", + "target": "macos_x86_64", + "run_stdlib_test": false, + "run_full_test": false, + "run_e2e_test": false, + "build_hello_wasm": false, + "clean_build_dir": false + }, + { + "build_os": "macos-11", + "agent_query": ["self-hosted", "macOS", "ARM64"], + "target": "macos_arm64", + "run_stdlib_test": false, + "run_full_test": false, + "run_e2e_test": false, + "build_hello_wasm": true, + "clean_build_dir": true + } +] + +def main + options = {} + OptionParser.new do |opts| + opts.banner = "Usage: build-matrix.rb [options]" + opts.on("--runner [JSON FILE]", "Path to runner data file") do |v| + options[:runner] = v + end + end.parse! + + matrix_entries = BASE_MATRIX_ENTRIES.dup + if options[:runner] + runner = JSON.parse(File.read(options[:runner])) + if label = runner["outputs"]["ubuntu20_04_aarch64-label"] + matrix_entries << { + "build_os": "ubuntu-20.04", + "agent_query": label, + "target": "ubuntu20.04_aarch64", + "container": "ghcr.io/swiftwasm/swift-ci:main-ubuntu-20.04", + "run_stdlib_test": false, + "run_full_test": false, + "run_e2e_test": false, + "build_hello_wasm": true, + "clean_build_dir": false + } + end + end + + print JSON.generate(matrix_entries) +end + +if $0 == __FILE__ + main +end diff --git a/.github/workflows/build-toolchain.yml b/.github/workflows/build-toolchain.yml new file mode 100644 index 0000000000000..1983f8d8e3537 --- /dev/null +++ b/.github/workflows/build-toolchain.yml @@ -0,0 +1,258 @@ +name: Build Toolchain + +on: + push: + branches: + - swiftwasm + - swiftwasm-release/** + pull_request: + branches: + - swiftwasm + - swiftwasm-release/** + types: [opened, synchronize, reopened] +jobs: + start-runner: + name: Start self-hosted EC2 runner + runs-on: ubuntu-latest + # Run only on main branches to avoid triggers by non-collaborator + if: ${{ github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'check-self-hosted-ci') }} + outputs: + ubuntu20_04_aarch64-label: ${{ steps.start-ubuntu20_04_aarch64-runner.outputs.label }} + ubuntu20_04_aarch64-ec2-instance-id: ${{ steps.start-ubuntu20_04_aarch64-runner.outputs.ec2-instance-id }} + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + - name: Start EC2 runner (ubuntu20_04_aarch64) + id: start-ubuntu20_04_aarch64-runner + uses: machulav/ec2-github-runner@v2 + with: + mode: start + github-token: ${{ secrets.SWIFTWASM_BUILDBOT_TOKEN }} + ec2-image-id: ami-03803f6b50b56647a # swiftwasm-ci/ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-arm64-server-20221201 + ec2-instance-type: c6g.xlarge + subnet-id: subnet-327f4a13 + security-group-id: sg-0429f5ec2bee9dc0c + stop-runner: + name: Stop self-hosted EC2 runner + needs: [start-runner, build-toolchain] + runs-on: ubuntu-latest + # Required to stop the runner even if the error happened in the previous jobs + if: ${{ always() && needs.start-runner.result == 'success' }} + # The runner can be already stopped when re-running a part of failed jobs + continue-on-error: true + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ secrets.AWS_REGION }} + - name: Stop EC2 runner (ubuntu20_04_aarch64) + uses: machulav/ec2-github-runner@v2 + with: + mode: stop + github-token: ${{ secrets.SWIFTWASM_BUILDBOT_TOKEN }} + label: ${{ needs.start-runner.outputs.ubuntu20_04_aarch64-label }} + ec2-instance-id: ${{ needs.start-runner.outputs.ubuntu20_04_aarch64-ec2-instance-id }} + + build-matrix: + name: Build matrix + needs: [start-runner] + runs-on: ubuntu-latest + if: ${{ always() }} + outputs: + entries: ${{ steps.generate.outputs.entries }} + steps: + - uses: actions/checkout@v3 + - name: Generate entries + id: generate + run: | + START_RUNNER_JSON="${{ runner.temp }}/start-runner.json" + cat < "$START_RUNNER_JSON" + ${{ toJson(needs.start-runner) }} + EOF + echo "entries=$(ruby .github/scripts/build-matrix.rb --runner $START_RUNNER_JSON)" >> $GITHUB_OUTPUT + + build-toolchain: + env: + TOOLCHAIN_CHANNEL: DEVELOPMENT + DEVELOPER_DIR: /Applications/Xcode_14.2.app/Contents/Developer/ + # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout + SEGMENT_DOWNLOAD_TIMEOUT_MINS: 30 + needs: [build-matrix] + if: ${{ always() }} + strategy: + fail-fast: false + matrix: + include: ${{ fromJSON(needs.build-matrix.outputs.entries) }} + + name: Target ${{ matrix.target }} + timeout-minutes: 0 + runs-on: ${{ matrix.agent_query }} + steps: + - name: Free disk space + if: ${{ matrix.free_disk_space }} + run: | + df -h + sudo swapoff -a + sudo rm -f /swapfile + sudo rm -rf /opt/hostedtoolcache + sudo rm -rf /usr/share/dotnet + sudo apt clean + + if docker info > /dev/null 2>&1; then + docker rmi $(docker image ls -aq) + fi + df -h + + - uses: actions/checkout@v3 + with: + path: swift + fetch-depth: 0 + + - name: Prepare sccache timestamp + id: cache_key + run: | + export SCCACHE_KEY_PREFIX="${{ matrix.target }}-${{ env.TOOLCHAIN_CHANNEL }}-sccache-v14-" + echo "SCCACHE_KEY_PREFIX=$SCCACHE_KEY_PREFIX" >> $GITHUB_OUTPUT + echo "SCCACHE_KEY=$SCCACHE_KEY_PREFIX$(date +'%Y-%m-%d-%I-%M-%S')" >> $GITHUB_OUTPUT + + - name: Check Xcode version + if: ${{ startsWith(matrix.build_os, 'macos-') }} + run: | + xcodebuild -version + + - uses: actions/cache/restore@v3 + id: build-cache + with: + path: build-cache + key: ${{ steps.cache_key.outputs.SCCACHE_KEY }} + restore-keys: | + ${{ steps.cache_key.outputs.SCCACHE_KEY_PREFIX }} + + - name: Clean build directory + if: ${{ matrix.clean_build_dir }} + run: | + rm -rf ${{ github.workspace }}/target-build \ + ${{ github.workspace }}/host-build \ + ${{ github.workspace }}/build-sdk \ + ${{ github.workspace }}/host-toolchain-sdk \ + ${{ github.workspace }}/dist-toolchain-sdk + + - run: chmod -R 777 ./build-cache + if: ${{ steps.build-cache.outputs.cache-hit }} + - name: Install Homebrew dependencies + if: ${{ startsWith(matrix.build_os, 'macos-') }} + run: brew bundle --file swift/Brewfile && brew install wasmer + - name: Build ${{ matrix.target }} installable archive on Docker container + if: ${{ matrix.container != null }} + timeout-minutes: 300 # Exit before 6 hours limit to allow cache upload + run: | + docker volume create oss-swift-package + docker run --name swiftwasm-ci-buildbot \ + --security-opt=no-new-privileges \ + --cap-add=SYS_PTRACE \ + --security-opt seccomp=unconfined \ + -dit \ + -e TOOLCHAIN_CHANNEL=${{ env.TOOLCHAIN_CHANNEL }} \ + -w /home/build-user/ \ + -v ${{ github.workspace }}:/source \ + -v oss-swift-package:/home/build-user \ + ${{ matrix.container }} + docker exec swiftwasm-ci-buildbot /bin/bash -lc 'env; cp -r /source/* /home/build-user/; ./swift/utils/webassembly/ci.sh' + docker cp swiftwasm-ci-buildbot:/home/build-user/swift-wasm-${{ env.TOOLCHAIN_CHANNEL }}-SNAPSHOT-${{ matrix.target }}.tar.gz . + + - name: Extract build-cache from Docker container + if: ${{ matrix.container != null && always() }} + run: | + rm -rf ${{ github.workspace }}/build-cache + docker cp swiftwasm-ci-buildbot:/home/build-user/build-cache ${{ github.workspace }}/build-cache + + - name: Build ${{ matrix.target }} installable archive + if: ${{ matrix.container == null }} + timeout-minutes: 300 # Exit before 6 hours limit to allow cache upload + env: + SKIP_XCODE_VERSION_CHECK: 1 + run: | + ./swift/utils/webassembly/ci.sh + + - uses: actions/cache/save@v3 + if: ${{ always() }} + with: + path: build-cache + key: ${{ steps.cache_key.outputs.SCCACHE_KEY }} + + - name: Upload ${{ matrix.target }} installable archive + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.target }}-installable + path: swift-wasm-${{ env.TOOLCHAIN_CHANNEL }}-SNAPSHOT-${{ matrix.target }}.tar.gz + + - name: Add wasmer in PATH for testing + run: echo "$HOME/.wasmer/bin" >> $GITHUB_PATH + + - name: Run stdlib tests for wasi-wasm32 + if: ${{ matrix.run_stdlib_test && matrix.container != null }} + run: | + docker exec swiftwasm-ci-buildbot /bin/bash -lc "cd target-build/swift-stdlib-wasi-wasm32 && ninja check-swift-wasi-wasm32-custom" + - name: Run stdlib tests for wasi-wasm32 + if: ${{ matrix.run_stdlib_test && matrix.container == null }} + run: | + TARGET_STDLIB_BUILD_DIR=${{ github.workspace }}/target-build/swift-stdlib-wasi-wasm32 + ninja check-swift-wasi-wasm32-custom -C "$TARGET_STDLIB_BUILD_DIR" + + - name: Run all tests for wasi-wasm32 + if: ${{ matrix.run_full_test }} + run: | + TARGET_STDLIB_BUILD_DIR=${{ github.workspace }}/target-build/swift-stdlib-wasi-wasm32 + # Run all tests but ignore failure temporarily + ninja check-swift-wasi-wasm32 -C "$TARGET_STDLIB_BUILD_DIR" || true + + - name: Pack test results + if: ${{ matrix.run_full_test }} + run: | + tar cJf ./swift-test-results.tar.gz target-build/swift-stdlib-wasi-wasm32/swift-test-results + - name: Upload test results + uses: actions/upload-artifact@v3 + if: ${{ matrix.run_full_test }} + with: + name: ${{ matrix.target }}-test-results + path: ./swift-test-results.tar.gz + + # Run e2e test + - name: Prepare E2E test + run: | + INSTALL_DIR=$(mktemp -d) + tar xf swift-wasm-$TOOLCHAIN_CHANNEL-SNAPSHOT-${{ matrix.target }}.tar.gz -C "$INSTALL_DIR" + echo "TOOLCHAIN=$(find "$INSTALL_DIR" -name "swift-wasm-$TOOLCHAIN_CHANNEL-*" -type d | head -n1)" >> $GITHUB_ENV + - name: Build hello.wasm + shell: bash + if: ${{ matrix.build_hello_wasm }} + run: | + echo 'print("Hello, world!")' > hello.swift + $TOOLCHAIN/usr/bin/swiftc \ + -target wasm32-unknown-wasi \ + -sdk $TOOLCHAIN/usr/share/wasi-sysroot \ + hello.swift -o hello.wasm && \ + echo "Successfully linked hello.wasm" + - name: Upload hello.wasm + if: ${{ matrix.build_hello_wasm }} + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.target }}-hello.wasm + path: hello.wasm + - name: Checkout integration-tests + if: ${{ matrix.run_e2e_test }} + uses: actions/checkout@v3 + with: + repository: swiftwasm/integration-tests + path: integration-tests + - name: Run integration tests + if: ${{ matrix.run_e2e_test }} + run: | + $TOOLCHAIN/usr/bin/swift run # Use TOOLCHAIN env value + working-directory: ${{ github.workspace }}/integration-tests diff --git a/.github/workflows/manual-distribution.yml b/.github/workflows/manual-distribution.yml new file mode 100644 index 0000000000000..184abdd7a8aee --- /dev/null +++ b/.github/workflows/manual-distribution.yml @@ -0,0 +1,82 @@ +name: Manual distribution +on: + workflow_dispatch: + inputs: + channel: + description: 'Release channel' + required: true + toolchain_name: + description: 'Toolchain name' + required: true + branch: + description: 'Branch name used to fetch built artifacts. If empty, use default branch based on channel' + display_name: + description: 'Display name for Darwin toolchain' + display_name_short: + description: 'Short display name for Darwin toolchain' +jobs: + manual-distribution: + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - name: Setup keychain + run: | + security create-keychain -p "$KEYCHAIN_PASSWORD" swiftwasm-ci + KEYCHAIN=$HOME/Library/Keychains/swiftwasm-ci-db + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN + security set-keychain-settings -lut 7200 $KEYCHAIN + security default-keychain -s $KEYCHAIN + echo "$DARWIN_TOOLCHAIN_APPLICATION_CERT_BASE64" | base64 --decode -o developerID_application.p12 + security import developerID_application.p12 -P "$DARWIN_TOOLCHAIN_APPLICATION_CERT_PASSWORD" -T /usr/bin/pkgbuild -T /usr/bin/codesign + echo "$DARWIN_TOOLCHAIN_INSTALLER_CERT_BASE64" | base64 --decode -o developerID_installer.p12 + security import developerID_installer.p12 -P "$DARWIN_TOOLCHAIN_INSTALLER_CERT_PASSWORD" -T /usr/bin/pkgbuild -T /usr/bin/codesign + security set-key-partition-list -S "apple-tool:,apple:" -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DARWIN_TOOLCHAIN_APPLICATION_CERT: ${{ secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT }} + DARWIN_TOOLCHAIN_APPLICATION_CERT_BASE64: ${{ secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT_BASE64 }} + DARWIN_TOOLCHAIN_APPLICATION_CERT_PASSWORD: ${{ secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT_PASSWORD }} + DARWIN_TOOLCHAIN_INSTALLER_CERT: ${{ secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT }} + DARWIN_TOOLCHAIN_INSTALLER_CERT_BASE64: ${{ secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT_BASE64 }} + DARWIN_TOOLCHAIN_INSTALLER_CERT_PASSWORD: ${{ secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT_PASSWORD }} + - name: Run ./utils/webassembly/distribute-latest-toolchain.sh + run: | + BRANCH="${{ github.event.inputs.branch }}" + CHANNEL="${{ github.event.inputs.channel }}" + + case "$CHANNEL" in + "DEVELOPMENT") + export TARGETS_TO_DIST="amazonlinux2_x86_64 ubuntu18.04_x86_64 ubuntu20.04_x86_64 ubuntu20.04_aarch64 macos_x86_64 macos_arm64" + ./utils/webassembly/distribute-latest-toolchain.sh ${BRANCH:-swiftwasm} DEVELOPMENT "${{ github.event.inputs.toolchain_name }}" + ;; + "5.3") + export TARGETS_TO_DIST="ubuntu18.04_x86_64 ubuntu20.04_x86_64 macos_x86_64" + ./utils/webassembly/distribute-latest-toolchain.sh ${BRANCH:-swiftwasm-release/5.3} 5.3 "${{ github.event.inputs.toolchain_name }}" + ;; + "5.4") + export TARGETS_TO_DIST="ubuntu18.04_x86_64 ubuntu20.04_x86_64 macos_x86_64 macos_arm64" + ./utils/webassembly/distribute-latest-toolchain.sh ${BRANCH:-swiftwasm-release/5.4} 5.4 "${{ github.event.inputs.toolchain_name }}" + ;; + "5.5") + export TARGETS_TO_DIST="ubuntu18.04_x86_64 ubuntu20.04_x86_64 macos_x86_64 macos_arm64" + ./utils/webassembly/distribute-latest-toolchain.sh ${BRANCH:-swiftwasm-release/5.5} 5.5 "${{ github.event.inputs.toolchain_name }}" + ;; + "5.6") + export TARGETS_TO_DIST="amazonlinux2_x86_64 ubuntu18.04_x86_64 ubuntu20.04_x86_64 ubuntu20.04_aarch64 macos_x86_64 macos_arm64" + ./utils/webassembly/distribute-latest-toolchain.sh ${BRANCH:-swiftwasm-release/5.6} 5.6 "${{ github.event.inputs.toolchain_name }}" + ;; + *) + export TARGETS_TO_DIST="amazonlinux2_x86_64 ubuntu18.04_x86_64 ubuntu20.04_x86_64 ubuntu20.04_aarch64 ubuntu22.04_x86_64 macos_x86_64 macos_arm64" + ./utils/webassembly/distribute-latest-toolchain.sh ${BRANCH:-swiftwasm-release/$CHANNEL} "$CHANNEL" "${{ github.event.inputs.toolchain_name }}" + ;; + esac + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DARWIN_TOOLCHAIN_APPLICATION_CERT: ${{ secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT }} + DARWIN_TOOLCHAIN_INSTALLER_CERT: ${{ secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT }} + DARWIN_TOOLCHAIN_NOTARIZE_EMAIL: ${{ secrets.DARWIN_TOOLCHAIN_NOTARIZE_EMAIL }} + DARWIN_TOOLCHAIN_NOTARIZE_PASSWORD: ${{ secrets.DARWIN_TOOLCHAIN_NOTARIZE_PASSWORD }} + DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID: ${{ secrets.DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID }} + DARWIN_TOOLCHAIN_DISPLAY_NAME: ${{ github.event.inputs.display_name }} + DARWIN_TOOLCHAIN_DISPLAY_NAME_SHORT: ${{ github.event.inputs.display_name_short }} diff --git a/.github/workflows/nightly-distribution.yml b/.github/workflows/nightly-distribution.yml new file mode 100644 index 0000000000000..06e79a64572e1 --- /dev/null +++ b/.github/workflows/nightly-distribution.yml @@ -0,0 +1,66 @@ +name: Nightly distribution +on: + schedule: + - cron: '0 0 * * *' +jobs: + nightly-distribution: + runs-on: macos-latest + strategy: + matrix: + include: + - branch: "swiftwasm" + channel: "DEVELOPMENT" + targets: "amazonlinux2_x86_64 ubuntu18.04_x86_64 ubuntu20.04_x86_64 ubuntu20.04_aarch64 ubuntu22.04_x86_64 macos_x86_64 macos_arm64" + - branch: "swiftwasm-release/5.3" + channel: "5.3" + targets: "ubuntu18.04_x86_64 ubuntu20.04_x86_64 macos_x86_64" + - branch: "swiftwasm-release/5.4" + channel: "5.4" + targets: "ubuntu18.04_x86_64 ubuntu20.04_x86_64 macos_x86_64 macos_arm64" + - branch: "swiftwasm-release/5.5" + channel: "5.5" + targets: "ubuntu18.04_x86_64 ubuntu20.04_x86_64 macos_x86_64 macos_arm64" + - branch: "swiftwasm-release/5.6" + channel: "5.6" + targets: "amazonlinux2_x86_64 ubuntu18.04_x86_64 ubuntu20.04_x86_64 ubuntu20.04_aarch64 macos_x86_64 macos_arm64" + - branch: "swiftwasm-release/5.7" + channel: "5.7" + targets: "amazonlinux2_x86_64 ubuntu18.04_x86_64 ubuntu20.04_x86_64 ubuntu20.04_aarch64 ubuntu22.04_x86_64 macos_x86_64 macos_arm64" + - branch: "swiftwasm-release/5.8" + channel: "5.8" + targets: "amazonlinux2_x86_64 ubuntu18.04_x86_64 ubuntu20.04_x86_64 ubuntu20.04_aarch64 ubuntu22.04_x86_64 macos_x86_64 macos_arm64" + steps: + - uses: actions/checkout@v1 + - name: Setup keychain + run: | + security create-keychain -p "$KEYCHAIN_PASSWORD" swiftwasm-ci + KEYCHAIN=$HOME/Library/Keychains/swiftwasm-ci-db + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN + security set-keychain-settings -lut 7200 $KEYCHAIN + security default-keychain -s $KEYCHAIN + + echo "$DARWIN_TOOLCHAIN_APPLICATION_CERT_BASE64" | base64 --decode -o developerID_application.p12 + security import developerID_application.p12 -P "$DARWIN_TOOLCHAIN_APPLICATION_CERT_PASSWORD" -T /usr/bin/pkgbuild -T /usr/bin/codesign + echo "$DARWIN_TOOLCHAIN_INSTALLER_CERT_BASE64" | base64 --decode -o developerID_installer.p12 + security import developerID_installer.p12 -P "$DARWIN_TOOLCHAIN_INSTALLER_CERT_PASSWORD" -T /usr/bin/pkgbuild -T /usr/bin/codesign + + security set-key-partition-list -S "apple-tool:,apple:" -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DARWIN_TOOLCHAIN_APPLICATION_CERT: ${{ secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT }} + DARWIN_TOOLCHAIN_APPLICATION_CERT_BASE64: ${{ secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT_BASE64 }} + DARWIN_TOOLCHAIN_APPLICATION_CERT_PASSWORD: ${{ secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT_PASSWORD }} + DARWIN_TOOLCHAIN_INSTALLER_CERT: ${{ secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT }} + DARWIN_TOOLCHAIN_INSTALLER_CERT_BASE64: ${{ secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT_BASE64 }} + DARWIN_TOOLCHAIN_INSTALLER_CERT_PASSWORD: ${{ secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT_PASSWORD }} + + - run: ./utils/webassembly/distribute-latest-toolchain.sh ${{ matrix.branch }} ${{ matrix.channel }} + env: + TARGETS_TO_DIST: ${{ matrix.targets }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BUILDBOT_GITHUB_TOKEN: ${{ secrets.SWIFTWASM_BUILDBOT_TOKEN }} + DARWIN_TOOLCHAIN_APPLICATION_CERT: ${{ secrets.DARWIN_TOOLCHAIN_APPLICATION_CERT }} + DARWIN_TOOLCHAIN_INSTALLER_CERT: ${{ secrets.DARWIN_TOOLCHAIN_INSTALLER_CERT }} + DARWIN_TOOLCHAIN_NOTARIZE_EMAIL: ${{ secrets.DARWIN_TOOLCHAIN_NOTARIZE_EMAIL }} + DARWIN_TOOLCHAIN_NOTARIZE_PASSWORD: ${{ secrets.DARWIN_TOOLCHAIN_NOTARIZE_PASSWORD }} + DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID: ${{ secrets.DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 54597829e7218..8fb1b429b98fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -560,6 +560,11 @@ option(SWIFT_STDLIB_ENABLE_OBJC_INTEROP "Should stdlib be built with Obj-C interop." "${SWIFT_STDLIB_ENABLE_OBJC_INTEROP_default}") +# FIXME(wasm) Reflection tests are temporalily disabled due to lack of linker features +option(SWIFTWASM_DISABLE_REFLECTION_TEST + "Disable building swift-reflection-test for WebAssembly build" + FALSE) + # # User-configurable experimental options. Do not use in production builds. # diff --git a/README.md b/README.md index 1ae622b104e7b..0a7265b93d264 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,23 @@ +# SwiftWasm + +## Compile your Swift code to WebAssembly + +[![CI status](https://github.com/swiftwasm/swift/workflows/Build%20Toolchain/badge.svg?branch=swiftwasm)](https://github.com/swiftwasm/swift/actions?query=workflow%3ABuild) [![Discord](https://img.shields.io/discord/780838335798706197?label=Discord)](https://discord.gg/ashJW8T8yp) + +This is the main repository for SwiftWasm toolchain and SDK. Please refer to [the +SwiftWasm book](https://swiftwasm.github.io/swiftwasm-book/) to get started, and to +the [`awesome-swiftwasm`](https://github.com/swiftwasm/awesome-swiftwasm) list for +more links in the SwiftWasm ecosystem. + +If you'd like to participate in the growing [SwiftWasm](https://swiftwasm.org) community, you're +very welcome to join [our Discord server](https://discord.gg/ashJW8T8yp), or the `#webassembly` +channel in [the SwiftPM Slack](https://swift-package-manager.herokuapp.com/). + +What follows below is `README.md` of the upstream Swift project included verbatim. If you'd like +to track the status of our builds, please refer to our [GitHub Actions page](https://github.com/swiftwasm/swift/actions). + +
+
Swift logo diff --git a/cmake/caches/Runtime-WASI-wasm32.cmake b/cmake/caches/Runtime-WASI-wasm32.cmake index d96dc88502218..925bda5d9c8e2 100644 --- a/cmake/caches/Runtime-WASI-wasm32.cmake +++ b/cmake/caches/Runtime-WASI-wasm32.cmake @@ -8,6 +8,7 @@ set(SWIFT_SDKS WASI CACHE STRING "") set(SWIFT_INCLUDE_TOOLS NO CACHE BOOL "") set(SWIFT_INCLUDE_TESTS TRUE CACHE BOOL "") set(SWIFT_INCLUDE_DOCS NO CACHE BOOL "") +set(SWIFT_BUILD_REMOTE_MIRROR NO CACHE BOOL "") set(SWIFT_BUILD_SOURCEKIT NO CACHE BOOL "") set(SWIFT_ENABLE_SOURCEKIT_TESTS NO CACHE BOOL "") @@ -18,8 +19,17 @@ set(SWIFTWASM_DISABLE_REFLECTION_TEST YES CACHE BOOL "") set(SWIFT_BUILD_STATIC_STDLIB YES CACHE BOOL "") set(SWIFT_BUILD_DYNAMIC_STDLIB NO CACHE BOOL "") set(SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY YES CACHE BOOL "") +# TODO(katei): This should get turned off, as this is not an ABI stable platform. +# But current CMake build system doesn't support SWIFT_STDLIB_STABLE_ABI=NO +set(SWIFT_STDLIB_STABLE_ABI YES CACHE BOOL "") +set(SWIFT_STDLIB_ENABLE_THINCMO YES CACHE BOOL "") # build with the host compiler set(SWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER YES CACHE BOOL "") set(SWIFT_STDLIB_SINGLE_THREADED_CONCURRENCY TRUE CACHE BOOL "") +set(SWIFT_THREADING_PACKAGE TRUE CACHE STRING "none") + +set(SWIFT_STDLIB_SUPPORTS_BACKTRACE_REPORTING FALSE CACHE BOOL "") +set(SWIFT_STDLIB_HAS_DLADDR FALSE CACHE BOOL "") +set(SWIFT_STDLIB_COMPACT_ABSOLUTE_FUNCTION_POINTER TRUE CACHE BOOL "") diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index 248178cd4702f..cb8b7078b78d5 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -397,6 +397,8 @@ function(_add_host_variant_link_flags target) cxx_link_libraries) target_link_libraries(${target} PRIVATE ${cxx_link_libraries}) + elseif("${LFLAGS_SDK}" STREQUAL "WASI") + list(APPEND result "-Wl,wasi-emulated-mman") else() # If lto is enabled, we need to add the object path flag so that the LTO code # generator leaves the intermediate object file in a place where it will not diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index 59afe4fbb3332..bafcd3bc21521 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -91,6 +91,12 @@ static Optional getGlibcModuleMapPath( return getActualModuleMapPath("glibc.modulemap", Opts, triple, vfs); } +static Optional getWASILibcModuleMapPath( + SearchPathOptions &Opts, const llvm::Triple &triple, + const llvm::IntrusiveRefCntPtr &vfs) { + return getActualModuleMapPath("wasi-libc.modulemap", Opts, triple, vfs); +} + static Optional getLibStdCxxModuleMapPath( SearchPathOptions &opts, const llvm::Triple &triple, const llvm::IntrusiveRefCntPtr &vfs) { @@ -183,11 +189,32 @@ static bool shouldInjectGlibcModulemap(const llvm::Triple &triple) { triple.isAndroid(); } +static bool shouldInjectWASILibcModulemap(const llvm::Triple &triple) { + return triple.isOSWASI(); +} + static SmallVector, 2> getGlibcFileMapping( ASTContext &ctx, const llvm::IntrusiveRefCntPtr &vfs) { const llvm::Triple &triple = ctx.LangOpts.Target; - if (!shouldInjectGlibcModulemap(triple)) + + std::string auxiliaryHeaderName; + llvm::Optional maybeActualModuleMapPath; + if (shouldInjectGlibcModulemap(triple)) { + auxiliaryHeaderName = "SwiftGlibc.h"; + maybeActualModuleMapPath = getGlibcModuleMapPath(ctx.SearchPathOpts, triple, vfs); + } else if (shouldInjectWASILibcModulemap(triple)) { + auxiliaryHeaderName = "SwiftWASILibc.h"; + maybeActualModuleMapPath = getWASILibcModuleMapPath(ctx.SearchPathOpts, triple, vfs); + } else { + return {}; + } + + Path actualModuleMapPath; + if (auto path = maybeActualModuleMapPath) + actualModuleMapPath = path.value(); + else + // FIXME: Emit a warning of some kind. return {}; // Extract the Glibc path from Clang driver. @@ -213,24 +240,17 @@ static SmallVector, 2> getGlibcFileMapping( return {}; } - Path actualModuleMapPath; - if (auto path = getGlibcModuleMapPath(ctx.SearchPathOpts, triple, vfs)) - actualModuleMapPath = path.value(); - else - // FIXME: Emit a warning of some kind. - return {}; - // TODO: remove the SwiftGlibc.h header and reference all Glibc headers // directly from the modulemap. Path actualHeaderPath = actualModuleMapPath; llvm::sys::path::remove_filename(actualHeaderPath); - llvm::sys::path::append(actualHeaderPath, "SwiftGlibc.h"); + llvm::sys::path::append(actualHeaderPath, auxiliaryHeaderName); Path injectedModuleMapPath(glibcDir); llvm::sys::path::append(injectedModuleMapPath, "module.modulemap"); Path injectedHeaderPath(glibcDir); - llvm::sys::path::append(injectedHeaderPath, "SwiftGlibc.h"); + llvm::sys::path::append(injectedHeaderPath, auxiliaryHeaderName); return { {std::string(injectedModuleMapPath), std::string(actualModuleMapPath)}, diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 32867832d3852..9044e4adebb69 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1797,6 +1797,13 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, }); } } + } if (OI.SDKPath.empty() && TC.getTriple().isOSWASI()) { + llvm::SmallString<128> SDKPath; + llvm::sys::path::append(SDKPath, getSwiftProgramPath()); + llvm::sys::path::remove_filename(SDKPath); // 'swift' + llvm::sys::path::remove_filename(SDKPath); // 'bin' + llvm::sys::path::append(SDKPath, "share", "wasi-sysroot"); + OI.SDKPath = SDKPath.str().str(); } if (!OI.SDKPath.empty()) { @@ -2397,7 +2404,8 @@ bool Driver::handleImmediateArgs(const ArgList &Args, const ToolChain &TC) { if (Args.hasFlag(options::OPT_static_executable, options::OPT_no_static_executable, false) || Args.hasFlag(options::OPT_static_stdlib, options::OPT_no_static_stdlib, - false)) { + false) || + TC.getTriple().isOSBinFormatWasm()) { commandLine.push_back("-use-static-resource-dir"); } diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index eb1c8a0ade532..8e27d7d34104e 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -660,7 +660,8 @@ ToolChain::constructInvocation(const CompileJobAction &job, if (context.Args.hasFlag(options::OPT_static_executable, options::OPT_no_static_executable, false) || context.Args.hasFlag(options::OPT_static_stdlib, - options::OPT_no_static_stdlib, false)) { + options::OPT_no_static_stdlib, false) || + getTriple().isOSBinFormatWasm()) { Arguments.push_back("-use-static-resource-dir"); } @@ -1188,7 +1189,13 @@ ToolChain::constructInvocation(const MergeModuleJobAction &job, context.Args.AddLastArg(Arguments, options::OPT_import_objc_header); context.Args.AddLastArg(Arguments, options::OPT_disable_incremental_imports); - + if (context.Args.hasFlag(options::OPT_static_executable, + options::OPT_no_static_executable, false) || + context.Args.hasFlag(options::OPT_static_stdlib, + options::OPT_no_static_stdlib, false) || + getTriple().isOSBinFormatWasm()) { + Arguments.push_back("-use-static-resource-dir"); + } Arguments.push_back("-module-name"); Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName)); @@ -1388,6 +1395,14 @@ ToolChain::constructInvocation(const GeneratePCHJobAction &job, addInputsOfType(Arguments, context.InputActions, file_types::TY_ClangHeader); context.Args.AddLastArg(Arguments, options::OPT_index_store_path); + if (context.Args.hasFlag(options::OPT_static_executable, + options::OPT_no_static_executable, false) || + context.Args.hasFlag(options::OPT_static_stdlib, options::OPT_no_static_stdlib, + false) || + getTriple().isOSBinFormatWasm()) { + Arguments.push_back("-use-static-resource-dir"); + } + if (job.isPersistentPCH()) { Arguments.push_back("-emit-pch"); Arguments.push_back("-pch-output-dir"); @@ -1472,7 +1487,8 @@ void ToolChain::getResourceDirPath(SmallVectorImpl &resourceDirPath, if (const Arg *A = args.getLastArg(options::OPT_resource_dir)) { StringRef value = A->getValue(); resourceDirPath.append(value.begin(), value.end()); - } else if (!getTriple().isOSDarwin() && args.hasArg(options::OPT_sdk)) { + } else if (!getTriple().isOSDarwin() && !getTriple().isOSWASI() && args.hasArg(options::OPT_sdk)) { + // for WASI, sdk option points to wasi-sysroot which doesn't have Swift toolchain StringRef value = args.getLastArg(options::OPT_sdk)->getValue(); resourceDirPath.append(value.begin(), value.end()); llvm::sys::path::append(resourceDirPath, "usr"); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index ed9c67dd2596a..cda017bc94115 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -3359,7 +3359,8 @@ llvm::CallBase *swift::irgen::emitCXXConstructorCall( StackProtectorMode IRGenModule::shouldEmitStackProtector(SILFunction *f) { const SILOptions &opts = IRGen.SIL.getOptions(); - return (opts.EnableStackProtection && f->needsStackProtection()) ? + // FIXME(katei): stack protection support will be added by https://github.com/WebAssembly/wasi-libc/pull/351 + return (opts.EnableStackProtection && f->needsStackProtection() && Triple.getObjectFormat() != llvm::Triple::Wasm) ? StackProtectorMode::StackProtector : StackProtectorMode::NoStackProtector; } @@ -3840,7 +3841,7 @@ IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity) { cast(entry), entity); return {gotEquivalent, ConstantReference::Indirect}; }; - + // Dynamically replaceable function keys are stored in the GlobalVars // table, but they don't have an associated Decl, so they require // special treatment here. diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index 6f8a676bef6a3..c77f924e4e4bf 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -118,7 +118,6 @@ getAccessorForComputedComponent(IRGenModule &IGM, accessor = component.getSubscriptIndexHash(); break; } - // If the accessor is not generic, and locally available, we can use it as is. // If it's only externally available, we need a local thunk to relative- // reference. @@ -224,7 +223,8 @@ getAccessorForComputedComponent(IRGenModule &IGM, componentArgsBuf = params.claimNext(); // Pass the argument pointer down to the underlying function, if it // wants it. - if (hasSubscriptIndices) { + // Always forward extra argument to match callee and caller signature on WebAssembly + if (hasSubscriptIndices || IGM.TargetInfo.OutputObjectFormat == llvm::Triple::Wasm) { forwardedArgs.add(componentArgsBuf); } break; @@ -250,6 +250,10 @@ getAccessorForComputedComponent(IRGenModule &IGM, forwardingSubs, &ignoreWitnessMetadata, forwardedArgs); + } else if (IGM.Triple.isOSBinFormatWasm()) { + // wasm: Add null swift.type pointer to match signature even when there is + // no generic environment. + forwardedArgs.add(llvm::ConstantPointerNull::get(IGM.TypeMetadataPtrTy)); } auto fnPtr = FunctionPointer::forDirect(IGM, accessorFn, /*secondaryValue*/ nullptr, @@ -379,6 +383,7 @@ getWitnessTableForComputedComponent(IRGenModule &IGM, /*vararg*/ false); auto destroyFn = llvm::Function::Create(destroyType, llvm::GlobalValue::PrivateLinkage, "keypath_destroy", IGM.getModule()); + destroyFn->setCallingConv(IGM.SwiftCC); destroy = destroyFn; destroyFn->setAttributes(IGM.constructInitialAttributes()); destroyFn->setCallingConv(IGM.SwiftCC); @@ -430,6 +435,7 @@ getWitnessTableForComputedComponent(IRGenModule &IGM, /*vararg*/ false); auto copyFn = llvm::Function::Create(copyType, llvm::GlobalValue::PrivateLinkage, "keypath_copy", IGM.getModule()); + copyFn->setCallingConv(IGM.SwiftCC); copy = copyFn; copyFn->setAttributes(IGM.constructInitialAttributes()); copyFn->setCallingConv(IGM.SwiftCC); diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 4cedea8007dce..c761c37740fd6 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -299,8 +299,9 @@ void verifyKeyPathComponent(SILModule &M, SILFunctionTypeRepresentation::Thin, "getter should be a thin function"); - require(substGetterType->getNumParameters() == 1 + hasIndices, - "getter should have one parameter"); + // FIXME(katei): Disabled for now. Will be replaced by keypath cc + // require(substGetterType->getNumParameters() == 1 + hasIndices, + // "getter should have one parameter"); auto baseParam = substGetterType->getParameters()[0]; require(baseParam.getConvention() == normalArgConvention, "getter base parameter should have normal arg convention"); @@ -351,8 +352,9 @@ void verifyKeyPathComponent(SILModule &M, SILFunctionTypeRepresentation::Thin, "setter should be a thin function"); - require(substSetterType->getNumParameters() == 2 + hasIndices, - "setter should have two parameters"); + // FIXME(katei): Disabled for now. Will be replaced by keypath cc + // require(substSetterType->getNumParameters() == 2 + hasIndices, + // "setter should have two parameters"); auto newValueParam = substSetterType->getParameters()[0]; // TODO: This should probably be unconditionally +1 when we diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 6fb3c14dcded1..49536a15fbd93 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -2994,6 +2994,7 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM, } } + auto Target = SGM.getASTContext().LangOpts.Target; auto genericSig = genericEnv ? genericEnv->getGenericSignature().getCanonicalSignature() : nullptr; @@ -3002,6 +3003,14 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM, genericEnv = nullptr; } + // Add empty generic type parameter to match function signature on WebAssembly + if (!genericSig && Target.isOSBinFormatWasm()) { + auto param = GenericTypeParamType::get(false, 0, 0, SGM.getASTContext()); + auto sig = GenericSignature::get(param, { }); + genericSig = CanGenericSignature(sig); + genericEnv = sig.getGenericEnvironment(); + } + // Build the signature of the thunk as expected by the keypath runtime. auto signature = [&]() { CanType loweredBaseTy, loweredPropTy; @@ -3017,7 +3026,8 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM, SmallVector params; params.push_back({loweredBaseTy, paramConvention}); auto &C = SGM.getASTContext(); - if (!indexes.empty()) + // Always take indexes parameter to match callee and caller signature on WebAssembly + if (!indexes.empty() || C.LangOpts.Target.isOSBinFormatWasm()) params.push_back({C.getUnsafeRawPointerType()->getCanonicalType(), ParameterConvention::Direct_Unowned}); @@ -3080,7 +3090,8 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM, } auto baseArg = entry->createFunctionArgument(baseArgTy); SILValue indexPtrArg; - if (!indexes.empty()) { + // Always take indexes parameter to match callee and caller signature on WebAssembly + if (!indexes.empty() || Target.isOSBinFormatWasm()) { auto indexArgTy = signature->getParameters()[1].getSILStorageType( SGM.M, signature, subSGF.F.getTypeExpansionContext()); indexPtrArg = entry->createFunctionArgument(indexArgTy); @@ -3169,6 +3180,7 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM, } } + auto Target = SGM.getASTContext().LangOpts.Target; auto genericSig = genericEnv ? genericEnv->getGenericSignature().getCanonicalSignature() : nullptr; @@ -3177,6 +3189,14 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM, genericEnv = nullptr; } + // Add empty generic type parameter to match function signature on WebAssembly + if (!genericSig && Target.isOSBinFormatWasm()) { + auto param = GenericTypeParamType::get(false, 0, 0, SGM.getASTContext()); + auto sig = GenericSignature::get(param, { }); + genericSig = CanGenericSignature(sig); + genericEnv = sig.getGenericEnvironment(); + } + // Build the signature of the thunk as expected by the keypath runtime. auto signature = [&]() { CanType loweredBaseTy, loweredPropTy; @@ -3202,7 +3222,8 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM, ? ParameterConvention::Indirect_Inout : paramConvention}); // indexes - if (!indexes.empty()) + // Always take indexes parameter to match callee and caller signature on WebAssembly + if (!indexes.empty() || C.LangOpts.Target.isOSBinFormatWasm()) params.push_back({C.getUnsafeRawPointerType()->getCanonicalType(), ParameterConvention::Direct_Unowned}); @@ -3259,7 +3280,8 @@ static SILFunction *getOrCreateKeyPathSetter(SILGenModule &SGM, auto baseArg = entry->createFunctionArgument(baseArgTy); SILValue indexPtrArg; - if (!indexes.empty()) { + // Always take indexes parameter to match callee and caller signature on WebAssembly + if (!indexes.empty() || Target.isOSBinFormatWasm()) { auto indexArgTy = signature->getParameters()[2].getSILStorageType( SGM.M, signature, subSGF.getTypeExpansionContext()); indexPtrArg = entry->createFunctionArgument(indexArgTy); @@ -3350,6 +3372,7 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, return; } + auto Target = SGM.getASTContext().LangOpts.Target; auto genericSig = genericEnv ? genericEnv->getGenericSignature().getCanonicalSignature() : nullptr; @@ -3359,6 +3382,14 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, genericEnv = nullptr; } + // Add empty generic type parameter to match function signature on WebAssembly + if (!genericSig && Target.isOSBinFormatWasm()) { + auto param = GenericTypeParamType::get(false, 0, 0, SGM.getASTContext()); + auto sig = GenericSignature::get(param, { }); + genericSig = CanGenericSignature(sig); + genericEnv = sig.getGenericEnvironment(); + } + auto &C = SGM.getASTContext(); auto unsafeRawPointerTy = C.getUnsafeRawPointerType()->getCanonicalType(); auto boolTy = C.getBoolType()->getCanonicalType(); diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp index 085e548eb7eec..fc411208ced54 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp @@ -505,6 +505,13 @@ bool SILCombiner::tryOptimizeKeypathKVCString(ApplyInst *AI, } bool SILCombiner::tryOptimizeKeypath(ApplyInst *AI) { + // FIXME(katei): Disable for WebAssembly for now because + // KeyPath cc is unstable and KeyPathProjector hask violates + // some assert assumptions + SILModule &M = AI->getModule(); + if (M.getASTContext().LangOpts.Target.isOSBinFormatWasm()) + return false; + if (SILFunction *callee = AI->getReferencedFunctionOrNull()) { return tryOptimizeKeypathApplication(AI, callee); } @@ -550,6 +557,13 @@ bool SILCombiner::tryOptimizeKeypath(ApplyInst *AI) { /// %addr = struct_element_addr/ref_element_addr %root_object /// // use %inout_addr bool SILCombiner::tryOptimizeInoutKeypath(BeginApplyInst *AI) { + // FIXME(katei): Disable for WebAssembly for now because + // KeyPath cc is unstable and KeyPathProjector hask violates + // some assert assumptions + SILModule &M = AI->getModule(); + if (M.getASTContext().LangOpts.Target.isOSBinFormatWasm()) + return false; + // Disable in OSSA because KeyPathProjector is not fully ported if (AI->getFunction()->hasOwnership()) return false; diff --git a/lib/SILOptimizer/Utils/KeyPathProjector.cpp b/lib/SILOptimizer/Utils/KeyPathProjector.cpp index 6051ae07d3e5b..f66ed98396c14 100644 --- a/lib/SILOptimizer/Utils/KeyPathProjector.cpp +++ b/lib/SILOptimizer/Utils/KeyPathProjector.cpp @@ -233,7 +233,22 @@ class GettablePropertyProjector : public ComponentProjector { assert(getter->getConventions().getNumSILArguments()); auto ref = builder.createFunctionRef(loc, getter); - builder.createApply(loc, ref, subs, {addr, parentValue}); + + std::vector args{addr, parentValue}; + // FIXME(wasm): For wasm, KeyPath getter always take indices parameter + // to match callee and caller signature. So need to pass stub pointer. + // See also: getOrCreateKeyPathSetter and getOrCreateKeyPathGetter + if (builder.getASTContext().LangOpts.Target.isOSBinFormatWasm()) { + auto IntTy = SILType::getBuiltinIntegerType(32, builder.getASTContext()); + auto UnsafeRawPointerTy = SILType::getRawPointerType(builder.getASTContext()); + auto zeroVal = SILValue(builder.createIntegerLiteral(loc, IntTy, 0)); + auto stackBuffer = SILValue(builder.createAllocStack(loc, IntTy)); + builder.createStore(loc, zeroVal, stackBuffer, StoreOwnershipQualifier::Unqualified); + auto nonePointer = builder.createUncheckedAddrCast(loc, stackBuffer, UnsafeRawPointerTy); + args.push_back(SILValue(nonePointer)); + } + + builder.createApply(loc, ref, subs, args); // If we were previously accessing a class member, we're done now. insertEndAccess(beginAccess, builder); diff --git a/stdlib/cmake/modules/AddSwiftStdlib.cmake b/stdlib/cmake/modules/AddSwiftStdlib.cmake index f5a77c4c81a02..6ef66c77883bc 100644 --- a/stdlib/cmake/modules/AddSwiftStdlib.cmake +++ b/stdlib/cmake/modules/AddSwiftStdlib.cmake @@ -323,7 +323,7 @@ function(_add_target_variant_c_compile_flags) endif() if("${CFLAGS_SDK}" STREQUAL "WASI") - list(APPEND result "-D_WASI_EMULATED_MMAN" "-D_WASI_EMULATED_PROCESS_CLOCKS") + list(APPEND result "-D_WASI_EMULATED_MMAN" "-D_WASI_EMULATED_SIGNAL" "-D_WASI_EMULATED_PROCESS_CLOCKS") endif() if(NOT SWIFT_STDLIB_ENABLE_OBJC_INTEROP) diff --git a/stdlib/cmake/modules/SwiftSource.cmake b/stdlib/cmake/modules/SwiftSource.cmake index ac39a16dd67ee..e6e97b77c7345 100644 --- a/stdlib/cmake/modules/SwiftSource.cmake +++ b/stdlib/cmake/modules/SwiftSource.cmake @@ -244,6 +244,10 @@ function(_add_target_variant_swift_compile_flags "-target" "${SWIFT_SDK_${sdk}_ARCH_${arch}_TRIPLE}") endif() + if("${sdk}" STREQUAL "WASI") + list(APPEND result "-Xcc" "-D_WASI_EMULATED_MMAN" "-Xcc" "-D_WASI_EMULATED_SIGNAL" "-Xcc" "-D_WASI_EMULATED_PROCESS_CLOCKS") + endif() + if(NOT BUILD_STANDALONE) list(APPEND result "-resource-dir" "${SWIFTLIB_DIR}") endif() @@ -323,6 +327,10 @@ function(_add_target_variant_swift_compile_flags list(APPEND result "-D" "SWIFT_STDLIB_HAS_STDIN") endif() + if(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) + list(APPEND result "-DSWIFT_STDLIB_SINGLE_THREADED_RUNTIME") + endif() + if(SWIFT_STDLIB_HAS_ENVIRON) list(APPEND result "-D" "SWIFT_STDLIB_HAS_ENVIRON") list(APPEND result "-Xcc" "-DSWIFT_STDLIB_HAS_ENVIRON") diff --git a/stdlib/private/CMakeLists.txt b/stdlib/private/CMakeLists.txt index 05ef455b755c1..3fb32fdca5dd5 100644 --- a/stdlib/private/CMakeLists.txt +++ b/stdlib/private/CMakeLists.txt @@ -23,12 +23,13 @@ endif() if(SWIFT_BUILD_SDK_OVERLAY) add_subdirectory(OSLog) - if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + list_intersect("${SWIFT_APPLE_PLATFORMS}" "${SWIFT_SDKS}" building_darwin_sdks) + if(building_darwin_sdks) add_subdirectory(StdlibUnittestFoundationExtras) endif() - # Currently SwiftReflectionTest cannot be built on Windows, due to - # dependencies on POSIX symbols - if (SWIFT_INCLUDE_TESTS AND (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")) + # Currently SwiftReflectionTest cannot be built on Windows, due to + # dependencies on POSIX symbols + if (SWIFT_INCLUDE_TESTS AND (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") AND NOT SWIFTWASM_DISABLE_REFLECTION_TEST) add_subdirectory(SwiftReflectionTest) endif() endif() diff --git a/stdlib/private/StdlibUnittest/CMakeLists.txt b/stdlib/private/StdlibUnittest/CMakeLists.txt index a8a3f17b60bf6..714cca193cfde 100644 --- a/stdlib/private/StdlibUnittest/CMakeLists.txt +++ b/stdlib/private/StdlibUnittest/CMakeLists.txt @@ -49,19 +49,20 @@ add_swift_target_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} TestHelpers.swift TypeIndexed.swift - SWIFT_MODULE_DEPENDS SwiftPrivate SwiftPrivateThreadExtras SwiftPrivateLibcExtras ${swift_stdlib_unittest_modules} - SWIFT_MODULE_DEPENDS_IOS Darwin - SWIFT_MODULE_DEPENDS_OSX Darwin - SWIFT_MODULE_DEPENDS_TVOS Darwin - SWIFT_MODULE_DEPENDS_WATCHOS Darwin - SWIFT_MODULE_DEPENDS_MACCATALYST Darwin - SWIFT_MODULE_DEPENDS_FREESTANDING "${SWIFT_FREESTANDING_TEST_DEPENDENCIES}" - SWIFT_MODULE_DEPENDS_LINUX Glibc - SWIFT_MODULE_DEPENDS_FREEBSD Glibc - SWIFT_MODULE_DEPENDS_OPENBSD Glibc - SWIFT_MODULE_DEPENDS_CYGWIN Glibc - SWIFT_MODULE_DEPENDS_HAIKU Glibc - SWIFT_MODULE_DEPENDS_WINDOWS CRT WinSDK + SWIFT_MODULE_DEPENDS SwiftPrivate SwiftPrivateLibcExtras ${swift_stdlib_unittest_modules} + SWIFT_MODULE_DEPENDS_IOS Darwin SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_OSX Darwin SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_TVOS Darwin SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_WATCHOS Darwin SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_MACCATALYST Darwin SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_FREESTANDING "${SWIFT_FREESTANDING_TEST_DEPENDENCIES}" SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_LINUX Glibc SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_FREEBSD Glibc SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_OPENBSD Glibc SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_CYGWIN Glibc SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_HAIKU Glibc SwiftPrivateThreadExtras + SWIFT_MODULE_DEPENDS_WASI WASILibc + SWIFT_MODULE_DEPENDS_WINDOWS CRT WinSDK SwiftPrivateThreadExtras C_COMPILE_FLAGS -I${SWIFT_SOURCE_DIR}/stdlib/include SWIFT_COMPILE_FLAGS ${swift_stdlib_unittest_compile_flags} ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} INSTALL_IN_COMPONENT stdlib-experimental diff --git a/stdlib/private/StdlibUnittest/InterceptTraps.cpp b/stdlib/private/StdlibUnittest/InterceptTraps.cpp index 80c3fa5979571..cf81e87255615 100644 --- a/stdlib/private/StdlibUnittest/InterceptTraps.cpp +++ b/stdlib/private/StdlibUnittest/InterceptTraps.cpp @@ -50,8 +50,6 @@ static void CrashCatcher(int Sig) { _exit(0); } -#endif // __wasi__ - #if defined(_WIN32) static LONG WINAPI VectoredCrashHandler(PEXCEPTION_POINTERS ExceptionInfo) { @@ -92,6 +90,8 @@ void installTrapInterceptor() { signal(SIGBUS, CrashCatcher); signal(SIGSYS, CrashCatcher); #endif -} #endif // !defined(__wasi__) +} + +#endif // !defined(__wasi__) \ No newline at end of file diff --git a/stdlib/private/StdlibUnittest/RaceTest.swift b/stdlib/private/StdlibUnittest/RaceTest.swift index 008f17a52000a..368f49d7000d4 100644 --- a/stdlib/private/StdlibUnittest/RaceTest.swift +++ b/stdlib/private/StdlibUnittest/RaceTest.swift @@ -38,7 +38,9 @@ import SwiftPrivate import SwiftPrivateLibcExtras +#if !os(WASI) import SwiftPrivateThreadExtras +#endif #if canImport(Darwin) import Darwin #elseif canImport(Glibc) diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift b/stdlib/private/StdlibUnittest/StdlibUnittest.swift index 9cb21b7d6d197..56aea542128e4 100644 --- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift +++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift @@ -12,7 +12,9 @@ import SwiftPrivate +#if !os(WASI) import SwiftPrivateThreadExtras +#endif import SwiftPrivateLibcExtras #if canImport(Darwin) @@ -22,6 +24,8 @@ import Foundation import Darwin #elseif canImport(Glibc) import Glibc +#elseif os(WASI) +import WASILibc #elseif os(Windows) import CRT import WinSDK @@ -35,6 +39,12 @@ import ObjectiveC import _Concurrency #endif +#if os(WASI) +let platformSupportSpawnChild = false +#else +let platformSupportSpawnChild = true +#endif + extension String { /// Returns the lines in `self`. public var _lines : [String] { @@ -855,8 +865,10 @@ var _testSuiteNameToIndex: [String : Int] = [:] let _stdlibUnittestStreamPrefix = "__STDLIB_UNITTEST__" let _crashedPrefix = "CRASHED:" +#if !os(WASI) @_silgen_name("installTrapInterceptor") func _installTrapInterceptor() +#endif #if _runtime(_ObjC) @objc protocol _StdlibUnittestNSException { @@ -867,7 +879,9 @@ func _installTrapInterceptor() // Avoid serializing references to objc_setUncaughtExceptionHandler in SIL. @inline(never) func _childProcess() { +#if !os(WASI) _installTrapInterceptor() +#endif #if _runtime(_ObjC) objc_setUncaughtExceptionHandler { @@ -923,7 +937,9 @@ func _childProcess() { @available(SwiftStdlib 5.1, *) @inline(never) func _childProcessAsync() async { +#if !os(WASI) _installTrapInterceptor() +#endif #if _runtime(_ObjC) objc_setUncaughtExceptionHandler { @@ -1724,7 +1740,7 @@ public func runAllTests() { if _isChildProcess { _childProcess() } else { - var runTestsInProcess: Bool = false + var runTestsInProcess: Bool = !platformSupportSpawnChild var filter: String? var args = [String]() var i = 0 @@ -1794,7 +1810,7 @@ public func runAllTestsAsync() async { if _isChildProcess { await _childProcessAsync() } else { - var runTestsInProcess: Bool = false + var runTestsInProcess: Bool = !platformSupportSpawnChild var filter: String? var args = [String]() var i = 0 diff --git a/stdlib/private/SwiftPrivate/CMakeLists.txt b/stdlib/private/SwiftPrivate/CMakeLists.txt index a1fc412a15624..f1e7d461d0ea1 100644 --- a/stdlib/private/SwiftPrivate/CMakeLists.txt +++ b/stdlib/private/SwiftPrivate/CMakeLists.txt @@ -26,6 +26,7 @@ add_swift_target_library(swiftSwiftPrivate ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} I SWIFT_MODULE_DEPENDS_OPENBSD Glibc SWIFT_MODULE_DEPENDS_CYGWIN Glibc SWIFT_MODULE_DEPENDS_HAIKU Glibc + SWIFT_MODULE_DEPENDS_WASI WASILibc SWIFT_MODULE_DEPENDS_WINDOWS CRT WinSDK SWIFT_COMPILE_FLAGS ${swift_swiftprivate_compile_flags} ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} INSTALL_IN_COMPONENT stdlib-experimental diff --git a/stdlib/private/SwiftPrivate/IO.swift b/stdlib/private/SwiftPrivate/IO.swift index ba5d26515c3c7..dac3f39dc112d 100644 --- a/stdlib/private/SwiftPrivate/IO.swift +++ b/stdlib/private/SwiftPrivate/IO.swift @@ -16,12 +16,16 @@ import SwiftShims #if canImport(Darwin) import Darwin let (platform_read, platform_write, platform_close) = (read, write, close) -#elseif canImport(Glibc) -import Glibc -let (platform_read, platform_write, platform_close) = (read, write, close) #elseif os(Windows) import CRT import WinSDK +#else +#if os(WASI) +import WASILibc +#elseif canImport(Glibc) +import Glibc +#endif +let (platform_read, platform_write, platform_close) = (read, write, close) #endif #if os(Windows) diff --git a/stdlib/private/SwiftPrivateLibcExtras/CMakeLists.txt b/stdlib/private/SwiftPrivateLibcExtras/CMakeLists.txt index 9095a7008388e..b8058031de88c 100644 --- a/stdlib/private/SwiftPrivateLibcExtras/CMakeLists.txt +++ b/stdlib/private/SwiftPrivateLibcExtras/CMakeLists.txt @@ -36,6 +36,7 @@ add_swift_target_library(swiftSwiftPrivateLibcExtras ${SWIFT_STDLIB_LIBRARY_BUIL SWIFT_MODULE_DEPENDS_OPENBSD Glibc SWIFT_MODULE_DEPENDS_CYGWIN Glibc SWIFT_MODULE_DEPENDS_HAIKU Glibc + SWIFT_MODULE_DEPENDS_WASI WASILibc SWIFT_MODULE_DEPENDS_WINDOWS CRT WinSDK INCORPORATE_OBJECT_LIBRARIES ${swift_private_libc_extras_incorporate_object_libraries} INSTALL_IN_COMPONENT stdlib-experimental diff --git a/stdlib/private/SwiftPrivateThreadExtras/CMakeLists.txt b/stdlib/private/SwiftPrivateThreadExtras/CMakeLists.txt index 35fcf24881c4a..52d2e28b9f5af 100644 --- a/stdlib/private/SwiftPrivateThreadExtras/CMakeLists.txt +++ b/stdlib/private/SwiftPrivateThreadExtras/CMakeLists.txt @@ -17,6 +17,7 @@ add_swift_target_library(swiftSwiftPrivateThreadExtras ${SWIFT_STDLIB_LIBRARY_BU SWIFT_MODULE_DEPENDS_OPENBSD Glibc SWIFT_MODULE_DEPENDS_CYGWIN Glibc SWIFT_MODULE_DEPENDS_HAIKU Glibc + SWIFT_MODULE_DEPENDS_WASI WASILibc SWIFT_MODULE_DEPENDS_WINDOWS CRT WinSDK SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} INSTALL_IN_COMPONENT stdlib-experimental diff --git a/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift b/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift index f854aed44aa5d..1fafe32646505 100644 --- a/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift +++ b/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift @@ -135,7 +135,7 @@ public func _stdlib_thread_join( } return (CInt(result), value) #elseif os(WASI) - // WASI environment has a only single thread + // WASI environment is single-threaded return (0, nil) #else var threadResultRawPtr: UnsafeMutableRawPointer? diff --git a/stdlib/public/CMakeLists.txt b/stdlib/public/CMakeLists.txt index a080c874711d7..6c6883a647575 100644 --- a/stdlib/public/CMakeLists.txt +++ b/stdlib/public/CMakeLists.txt @@ -142,6 +142,10 @@ if(SWIFT_BUILD_STDLIB) add_subdirectory(core) add_subdirectory(SwiftOnoneSupport) + if(WASI IN_LIST SWIFT_SDKS) + add_subdirectory(WASI) + endif() + if(SWIFT_ENABLE_EXPERIMENTAL_DIFFERENTIABLE_PROGRAMMING) add_subdirectory(Differentiation) endif() diff --git a/stdlib/public/Concurrency/AsyncStream.cpp b/stdlib/public/Concurrency/AsyncStream.cpp index 389ebd3d7389a..ac2aae25cd397 100644 --- a/stdlib/public/Concurrency/AsyncStream.cpp +++ b/stdlib/public/Concurrency/AsyncStream.cpp @@ -12,22 +12,26 @@ #include +#include "swift/Runtime/Config.h" #include "swift/Threading/Mutex.h" namespace swift { // return the size in words for the given mutex primitive -extern "C" +extern "C" SWIFT_CC(swift) size_t _swift_async_stream_lock_size() { size_t words = sizeof(Mutex) / sizeof(void *); if (words < 1) { return 1; } return words; } +SWIFT_CC(swift) extern "C" void _swift_async_stream_lock_init(Mutex &lock) { new (&lock) Mutex(); } +SWIFT_CC(swift) extern "C" void _swift_async_stream_lock_lock(Mutex &lock) { lock.lock(); } +SWIFT_CC(swift) extern "C" void _swift_async_stream_lock_unlock(Mutex &lock) { lock.unlock(); } } diff --git a/stdlib/public/Differentiation/CMakeLists.txt b/stdlib/public/Differentiation/CMakeLists.txt index aa895c02bc81f..30ad34900c73b 100644 --- a/stdlib/public/Differentiation/CMakeLists.txt +++ b/stdlib/public/Differentiation/CMakeLists.txt @@ -40,6 +40,7 @@ add_swift_target_library(swift_Differentiation ${SWIFT_STDLIB_LIBRARY_BUILD_TYPE SWIFT_MODULE_DEPENDS_OPENBSD Glibc SWIFT_MODULE_DEPENDS_CYGWIN Glibc SWIFT_MODULE_DEPENDS_HAIKU Glibc + SWIFT_MODULE_DEPENDS_WASI WASILibc SWIFT_MODULE_DEPENDS_WINDOWS CRT C_COMPILE_FLAGS diff --git a/stdlib/public/Platform/CMakeLists.txt b/stdlib/public/Platform/CMakeLists.txt index f478206d6a2a3..cf1fb695500a8 100644 --- a/stdlib/public/Platform/CMakeLists.txt +++ b/stdlib/public/Platform/CMakeLists.txt @@ -96,7 +96,24 @@ add_swift_target_library(swiftGlibc ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_O LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}" TARGET_SDKS "${swiftGlibc_target_sdks}" INSTALL_IN_COMPONENT sdk-overlay - DEPENDS glibc_modulemap) + DEPENDS libc_modulemap) + +add_swift_target_library(swiftWASILibc ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY + ${swift_platform_sources} + POSIXError.swift + + GYB_SOURCES + ${swift_platform_gyb_sources} + WASILibc.swift.gyb + + SWIFT_COMPILE_FLAGS + ${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS} + ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} + ${swift_platform_compile_flags} + LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}" + TARGET_SDKS WASI + INSTALL_IN_COMPONENT sdk-overlay + DEPENDS libc_modulemap) add_swift_target_library(swiftCRT ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY ucrt.swift @@ -115,65 +132,73 @@ add_swift_target_library(swiftCRT ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVE TARGET_SDKS WINDOWS INSTALL_IN_COMPONENT sdk-overlay) -set(glibc_modulemap_target_list) +set(libc_modulemap_target_list) foreach(sdk ${SWIFT_SDKS}) - if(NOT "${sdk}" STREQUAL "LINUX" AND - NOT "${sdk}" STREQUAL "FREEBSD" AND - NOT "${sdk}" STREQUAL "OPENBSD" AND - NOT "${sdk}" STREQUAL "ANDROID" AND - NOT "${sdk}" STREQUAL "CYGWIN" AND - NOT "${sdk}" STREQUAL "HAIKU") + if("${sdk}" STREQUAL "LINUX" OR + "${sdk}" STREQUAL "FREEBSD" OR + "${sdk}" STREQUAL "OPENBSD" OR + "${sdk}" STREQUAL "ANDROID" OR + "${sdk}" STREQUAL "CYGWIN" OR + "${sdk}" STREQUAL "HAIKU") + set(libc_modulemap_source "glibc.modulemap.gyb") + set(libc_header_source "SwiftGlibc.h.gyb") + elseif("${sdk}" STREQUAL "WASI") + set(libc_modulemap_source "wasi-libc.modulemap.gyb") + set(libc_header_source "SwiftWASILibc.h.gyb") + else() continue() endif() + string(REGEX REPLACE "\\.gyb$" "" libc_modulemap_outname "${libc_modulemap_source}") + string(REGEX REPLACE "\\.gyb$" "" libc_header_outname "${libc_header_source}") + foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES}) set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}") set(module_dir "${SWIFTLIB_DIR}/${arch_subdir}") set(module_dir_static "${SWIFTSTATICLIB_DIR}/${arch_subdir}") - set(glibc_modulemap_source "glibc.modulemap.gyb") - set(glibc_modulemap_out "${module_dir}/glibc.modulemap") - set(glibc_modulemap_out_static "${module_dir_static}/glibc.modulemap") + set(libc_modulemap_out "${module_dir}/${libc_modulemap_outname}") + set(libc_modulemap_out_static "${module_dir_static}/${libc_modulemap_outname}") # Configure the module map based on the target. Each platform needs to - # reference different headers, based on what's available in their glibc. - # This is the 'glibc.modulemap' in the 'resource-dir', so + # reference different headers, based on what's available in their libc. + # This is the .modulemap in the 'resource-dir', so # it's the one we'll look at during the build process. - handle_gyb_source_single(glibc_modulemap_target - SOURCE "${glibc_modulemap_source}" - OUTPUT "${glibc_modulemap_out}" + handle_gyb_source_single(libc_modulemap_target + SOURCE "${libc_modulemap_source}" + OUTPUT "${libc_modulemap_out}" FLAGS "-DCMAKE_SDK=${sdk}") - list(APPEND glibc_modulemap_target_list ${glibc_modulemap_target}) + list(APPEND libc_modulemap_target_list ${libc_modulemap_target}) - set(glibc_header_out "${module_dir}/SwiftGlibc.h") - set(glibc_header_out_static "${module_dir_static}/SwiftGlibc.h") - handle_gyb_source_single(glibc_header_target - SOURCE "SwiftGlibc.h.gyb" - OUTPUT "${glibc_header_out}" + set(libc_header_out "${module_dir}/${libc_header_outname}") + set(libc_header_out_static "${module_dir_static}/${libc_header_outname}") + handle_gyb_source_single(libc_header_target + SOURCE "${libc_header_source}" + OUTPUT "${libc_header_out}" FLAGS "-DCMAKE_SDK=${sdk}") - list(APPEND glibc_modulemap_target_list ${glibc_header_target}) + list(APPEND libc_modulemap_target_list ${libc_header_target}) if(SWIFT_BUILD_STATIC_STDLIB) add_custom_command_target( - copy_glibc_modulemap_header_static + copy_libc_modulemap_header_static COMMAND "${CMAKE_COMMAND}" "-E" "make_directory" ${module_dir_static} COMMAND "${CMAKE_COMMAND}" "-E" "copy" - ${glibc_modulemap_out} ${glibc_modulemap_out_static} + ${libc_modulemap_out} ${libc_modulemap_out_static} COMMAND "${CMAKE_COMMAND}" "-E" "copy" - ${glibc_header_out} ${glibc_header_out_static} - OUTPUT ${glibc_modulemap_out_static} ${glibc_header_out_static} + ${libc_header_out} ${libc_header_out_static} + OUTPUT ${libc_modulemap_out_static} ${libc_header_out_static} DEPENDS - "${glibc_modulemap_target}" - "${glibc_header_target}" - COMMENT "Copying Glibc modulemap and header to static resources") + "${libc_modulemap_target}" + "${libc_header_target}" + COMMENT "Copying libc modulemap and header to static resources") - list(APPEND glibc_modulemap_target_list - ${copy_glibc_modulemap_header_static}) + list(APPEND libc_modulemap_target_list + ${copy_libc_modulemap_header_static}) endif() # If this SDK is a target for a non-native host, except if it's for Android @@ -181,15 +206,15 @@ foreach(sdk ${SWIFT_SDKS}) # prefix. This is the one we'll install instead. if(NOT "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_ARCH_${arch}_PATH}" STREQUAL "/" AND NOT (${sdk} STREQUAL ANDROID AND NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL "")) - set(glibc_sysroot_relative_modulemap_out "${module_dir}/sysroot-relative-modulemaps/glibc.modulemap") + set(libc_sysroot_relative_modulemap_out "${module_dir}/sysroot-relative-modulemaps/${libc_modulemap_outname}") - handle_gyb_source_single(glibc_modulemap_native_target - SOURCE "${glibc_modulemap_source}" - OUTPUT "${glibc_sysroot_relative_modulemap_out}" + handle_gyb_source_single(libc_modulemap_native_target + SOURCE "${libc_modulemap_source}" + OUTPUT "${libc_sysroot_relative_modulemap_out}" FLAGS "-DCMAKE_SDK=${sdk}") - list(APPEND glibc_modulemap_target_list ${glibc_modulemap_native_target}) - set(glibc_modulemap_out ${glibc_sysroot_relative_modulemap_out}) + list(APPEND libc_modulemap_target_list ${libc_modulemap_native_target}) + set(libc_modulemap_out ${libc_sysroot_relative_modulemap_out}) endif() # FIXME: When SDK is a cross-compile target (SDK != Host), the generated @@ -197,26 +222,26 @@ foreach(sdk ${SWIFT_SDKS}) # It is not relocatable to the target platform itself. # This affects any cross-compiled targets that use glibc.modulemap. - swift_install_in_component(FILES "${glibc_modulemap_out}" + swift_install_in_component(FILES "${libc_modulemap_out}" DESTINATION "lib/swift/${arch_subdir}" COMPONENT sdk-overlay) - swift_install_in_component(FILES "${glibc_header_out}" + swift_install_in_component(FILES "${libc_header_out}" DESTINATION "lib/swift/${arch_subdir}" COMPONENT sdk-overlay) if(SWIFT_BUILD_STATIC_STDLIB) - swift_install_in_component(FILES "${glibc_modulemap_out}" + swift_install_in_component(FILES "${libc_modulemap_out}" DESTINATION "lib/swift_static/${arch_subdir}" COMPONENT sdk-overlay) - swift_install_in_component(FILES "${glibc_header_out}" + swift_install_in_component(FILES "${libc_header_out}" DESTINATION "lib/swift_static/${arch_subdir}" COMPONENT sdk-overlay) endif() endforeach() endforeach() -add_custom_target(glibc_modulemap DEPENDS ${glibc_modulemap_target_list}) -set_property(TARGET glibc_modulemap PROPERTY FOLDER "Miscellaneous") -add_dependencies(sdk-overlay glibc_modulemap) +add_custom_target(libc_modulemap DEPENDS ${libc_modulemap_target_list}) +set_property(TARGET libc_modulemap PROPERTY FOLDER "Miscellaneous") +add_dependencies(sdk-overlay libc_modulemap) if(WINDOWS IN_LIST SWIFT_SDKS) swift_install_in_component(FILES diff --git a/stdlib/public/Platform/SwiftWASILibc.h.gyb b/stdlib/public/Platform/SwiftWASILibc.h.gyb new file mode 100644 index 0000000000000..c051627f2b7c0 --- /dev/null +++ b/stdlib/public/Platform/SwiftWASILibc.h.gyb @@ -0,0 +1,126 @@ +%{ +headers = [ + 'stdc-predef.h', + 'features.h', + + # C standard library + 'complex.h', + 'ctype.h', + 'errno.h', + 'fenv.h', + 'float.h', + 'inttypes.h', + 'iso646.h', + 'libutil.h', + 'limits.h', + 'locale.h', + 'math.h', + 'pty.h', + # setjmp/longjmp is not available + # 'setjmp.h', + 'signal.h', + 'stdarg.h', + 'stdbool.h', + 'stddef.h', + 'stdint.h', + 'stdio.h', + 'stdlib.h', + 'string.h', + 'tgmath.h', + 'time.h', + 'util.h', + 'utmp.h', + + # POSIX + 'aio.h', + 'arpa/inet.h', + 'bsd/ifaddrs.h', + 'bsd/pty.h', + 'cpio.h', + 'dirent.h', + 'dlfcn.h', + 'fcntl.h', + 'fmtmsg.h', + 'fnmatch.h', + 'ftw.h', + 'glob.h', + 'grp.h', + 'iconv.h', + 'ifaddrs.h', + 'langinfo.h', + 'libgen.h', + 'link.h', + 'monetary.h', + 'net/if.h', + 'netdb.h', + 'netinet/in.h', + 'netinet/tcp.h', + 'nl_types.h', + 'poll.h', + 'pthread.h', + 'pwd.h', + 'regex.h', + 'sched.h', + 'search.h', + 'semaphore.h', + 'spawn.h', + 'strings.h', + 'sys/event.h', + 'sys/file.h', + 'sys/inotify.h', + 'sys/ioctl.h', + 'sys/ipc.h', + 'sys/mman.h', + 'sys/mount.h', + 'sys/msg.h', + 'sys/resource.h', + 'sys/select.h', + 'sys/sem.h', + 'sys/sendfile.h', + 'sys/shm.h', + 'sys/socket.h', + 'sys/stat.h', + 'sys/statvfs.h', + 'sys/time.h', + 'sys/times.h', + 'sys/types.h', + 'sys/uio.h', + 'sys/un.h', + 'sys/user.h', + 'sys/utsname.h', + 'sys/wait.h', + 'sysexits.h', + 'syslog.h', + 'tar.h', + 'termios.h', + 'ulimit.h', + 'unistd.h', + 'utime.h', + 'utmpx.h', + 'wait.h', + 'wordexp.h', + + # WASI specific + 'wasi/api.h', +] +}% + +// FIXME?(katei): +// Those emulations are now enabled by default to have compatibility +// with other platforms as much as possible without any extra modification. +// But we should consider moving them into their own submodules. +#ifndef _WASI_EMULATED_MMAN +# define _WASI_EMULATED_MMAN +#endif +#ifndef _WASI_EMULATED_SIGNAL +# define _WASI_EMULATED_SIGNAL +#endif +#ifndef _WASI_EMULATED_PROCESS_CLOCKS +# define _WASI_EMULATED_PROCESS_CLOCKS +#endif + +% for header in headers: +#if __has_include(<${header}>) +#include <${header}> +#endif +% end diff --git a/stdlib/public/Platform/WASILibc.swift.gyb b/stdlib/public/Platform/WASILibc.swift.gyb new file mode 100644 index 0000000000000..bd6e03ed3c4af --- /dev/null +++ b/stdlib/public/Platform/WASILibc.swift.gyb @@ -0,0 +1,161 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +@_exported import SwiftWASILibc // Clang module + +// Constants defined by +@available(swift, deprecated: 3.0, message: "Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting.") +public let M_PI = Double.pi + +@available(swift, deprecated: 3.0, message: "Please use 'Double.pi / 2' or '.pi / 2' to get the value of correct type and avoid casting.") +public let M_PI_2 = Double.pi / 2 + +@available(swift, deprecated: 3.0, message: "Please use 'Double.pi / 4' or '.pi / 4' to get the value of correct type and avoid casting.") +public let M_PI_4 = Double.pi / 4 + +@available(swift, deprecated: 3.0, message: "Please use '2.squareRoot()'.") +public let M_SQRT2 = 2.squareRoot() + +@available(swift, deprecated: 3.0, message: "Please use '0.5.squareRoot()'.") +public let M_SQRT1_2 = 0.5.squareRoot() + +// Constants defined by +@available(swift, deprecated: 3.0, message: "Please use 'T.radix' to get the radix of a FloatingPoint type 'T'.") +public let FLT_RADIX = Double.radix + +%for type, prefix in [('Float', 'FLT'), ('Double', 'DBL')]: +// Where does the 1 come from? C counts the usually-implicit leading +// significand bit, but Swift does not. Neither is really right or wrong. +@available(swift, deprecated: 3.0, message: "Please use '${type}.significandBitCount + 1'.") +public let ${prefix}_MANT_DIG = ${type}.significandBitCount + 1 + +// Where does the 1 come from? C models floating-point numbers as having a +// significand in [0.5, 1), but Swift (following IEEE 754) considers the +// significand to be in [1, 2). This rationale applies to ${prefix}_MIN_EXP +// as well. +@available(swift, deprecated: 3.0, message: "Please use '${type}.greatestFiniteMagnitude.exponent + 1'.") +public let ${prefix}_MAX_EXP = ${type}.greatestFiniteMagnitude.exponent + 1 + +@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNormalMagnitude.exponent + 1'.") +public let ${prefix}_MIN_EXP = ${type}.leastNormalMagnitude.exponent + 1 + +@available(swift, deprecated: 3.0, message: "Please use '${type}.greatestFiniteMagnitude' or '.greatestFiniteMagnitude'.") +public let ${prefix}_MAX = ${type}.greatestFiniteMagnitude + +@available(swift, deprecated: 3.0, message: "Please use '${type}.ulpOfOne' or '.ulpOfOne'.") +public let ${prefix}_EPSILON = ${type}.ulpOfOne + +@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNormalMagnitude' or '.leastNormalMagnitude'.") +public let ${prefix}_MIN = ${type}.leastNormalMagnitude + +@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNonzeroMagnitude' or '.leastNonzeroMagnitude'.") +public let ${prefix}_TRUE_MIN = ${type}.leastNonzeroMagnitude + +%end + +public let MAP_FAILED: UnsafeMutableRawPointer! = UnsafeMutableRawPointer(bitPattern: -1) + +// TODO: wasi-libc's error.h defines these macros as function-like macros, which +// Swift can't import for now. +%{ +posix_error_codes = [ + "E2BIG", + "EACCES", + "EADDRINUSE", + "EADDRNOTAVAIL", + "EAFNOSUPPORT", + "EAGAIN", + "EALREADY", + "EBADF", + "EBADMSG", + "EBUSY", + "ECANCELED", + "ECHILD", + "ECONNABORTED", + "ECONNREFUSED", + "ECONNRESET", + "EDEADLK", + "EDESTADDRREQ", + "EDOM", + "EDQUOT", + "EEXIST", + "EFAULT", + "EFBIG", + "EHOSTUNREACH", + "EIDRM", + "EILSEQ", + "EINPROGRESS", + "EINTR", + "EINVAL", + "EIO", + "EISCONN", + "EISDIR", + "ELOOP", + "EMFILE", + "EMLINK", + "EMSGSIZE", + "EMULTIHOP", + "ENAMETOOLONG", + "ENETDOWN", + "ENETRESET", + "ENETUNREACH", + "ENFILE", + "ENOBUFS", + "ENODEV", + "ENOENT", + "ENOEXEC", + "ENOLCK", + "ENOLINK", + "ENOMEM", + "ENOMSG", + "ENOPROTOOPT", + "ENOSPC", + "ENOSYS", + "ENOTCONN", + "ENOTDIR", + "ENOTEMPTY", + "ENOTRECOVERABLE", + "ENOTSOCK", + "ENOTSUP", + "ENOTTY", + "ENXIO", + "EOVERFLOW", + "EOWNERDEAD", + "EPERM", + "EPIPE", + "EPROTO", + "EPROTONOSUPPORT", + "EPROTOTYPE", + "ERANGE", + "EROFS", + "ESPIPE", + "ESRCH", + "ESTALE", + "ETIMEDOUT", + "ETXTBSY", + "EXDEV", + "ENOTCAPABLE", +] +}% + +%for ecode in posix_error_codes: + +@available(*, deprecated, message: "Please use 'POSIXErrorCode.${ecode}'.") +public let ${ecode} = POSIXErrorCode.${ecode}.rawValue + +%end + +// TODO: wasi-libc's _seek.h defines these macros as function-like macros, which +// Swift can't import for now. +public let SEEK_SET: Int32 = 0 +public let SEEK_CUR: Int32 = 1 +public let SEEK_END: Int32 = 2 diff --git a/stdlib/public/Platform/wasi-libc.modulemap.gyb b/stdlib/public/Platform/wasi-libc.modulemap.gyb new file mode 100644 index 0000000000000..59be5d56499b8 --- /dev/null +++ b/stdlib/public/Platform/wasi-libc.modulemap.gyb @@ -0,0 +1,18 @@ +//===--- wasi-libc.modulemap.gyb ------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +module SwiftWASILibc [system] { + // C standard library + header "SwiftWASILibc.h" + + export * +} diff --git a/stdlib/public/Resources/wasi/static-executable-args.lnk b/stdlib/public/Resources/wasi/static-executable-args.lnk new file mode 100644 index 0000000000000..a18d5fc3668aa --- /dev/null +++ b/stdlib/public/Resources/wasi/static-executable-args.lnk @@ -0,0 +1,12 @@ +-static +-lswiftSwiftOnoneSupport +-lswiftWasiPthread +-ldl +-lstdc++ +-lm +-lwasi-emulated-mman +-lwasi-emulated-signal +-lwasi-emulated-process-clocks +-Xlinker --error-limit=0 +-Xlinker --no-gc-sections +-Xlinker --threads=1 diff --git a/stdlib/public/SwiftShims/swift/shims/SwiftStdint.h b/stdlib/public/SwiftShims/swift/shims/SwiftStdint.h index 7b83e90d72799..117677e497af3 100644 --- a/stdlib/public/SwiftShims/swift/shims/SwiftStdint.h +++ b/stdlib/public/SwiftShims/swift/shims/SwiftStdint.h @@ -24,7 +24,7 @@ // Clang has been defining __INTxx_TYPE__ macros for a long time. // __UINTxx_TYPE__ are defined only since Clang 3.5. -#if !defined(__APPLE__) && !defined(__linux__) && !defined(__OpenBSD__) +#if !defined(__APPLE__) && !defined(__linux__) && !defined(__OpenBSD__) && !defined(__wasi__) #include typedef int64_t __swift_int64_t; typedef uint64_t __swift_uint64_t; diff --git a/stdlib/public/WASI/CMakeLists.txt b/stdlib/public/WASI/CMakeLists.txt new file mode 100644 index 0000000000000..0d088443ad7be --- /dev/null +++ b/stdlib/public/WASI/CMakeLists.txt @@ -0,0 +1,4 @@ +add_swift_target_library(swiftWasiPthread STATIC IS_STDLIB + Pthread.cpp + TARGET_SDKS WASI + INSTALL_IN_COMPONENT stdlib) diff --git a/stdlib/public/WASI/Pthread.cpp b/stdlib/public/WASI/Pthread.cpp new file mode 100644 index 0000000000000..5a64d9bdb4c39 --- /dev/null +++ b/stdlib/public/WASI/Pthread.cpp @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: 0BSD +// prototypes taken from opengroup +#include +#include +#include +#include + +#define STUB() do {fprintf(stderr, "FakePthread: unsupported %s\n", __func__);abort();}while(0) + +// mutexes: just no-ops + +int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { + return 0; +} + +int pthread_mutex_destroy(pthread_mutex_t *mutex) { + return 0; +} + +int pthread_mutexattr_init(pthread_mutexattr_t *attr) { + return 0; +} + +int pthread_mutexattr_destroy(pthread_mutexattr_t *attr) { + return 0; +} + +int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) { + return 0; +} + +int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) { + return 0; +} + +int pthread_mutex_lock(pthread_mutex_t *mutex) { + return 0; +} + +int pthread_mutex_trylock(pthread_mutex_t *mutex) { + return 0; +} + +int pthread_mutex_unlock(pthread_mutex_t *mutex) { + return 0; +} + +// pthread_cond: STUB + +int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { + return 0; +} + +int pthread_cond_destroy(pthread_cond_t *cond) { + return 0; +} + +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { + STUB(); +} + +int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timespec *abstime) { + STUB(); +} + +int pthread_cond_broadcast(pthread_cond_t *cond) { + return 0; +} + +int pthread_cond_signal(pthread_cond_t *cond) { + return 0; +} + +// tls + +int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) { + STUB(); +} + +void *pthread_getspecific(pthread_key_t key) { + STUB(); +} + +int pthread_setspecific(pthread_key_t key, const void *value) { + STUB(); +} + +// threads + +pthread_t pthread_self() { + return (pthread_t)1234; +} + +#undef pthread_equal + +int pthread_equal(pthread_t t1, pthread_t t2) { + return t1 == t2; +} + +int pthread_join(pthread_t thread, void **value_ptr) { + STUB(); +} + +int pthread_detach(pthread_t thread) { + STUB(); +} + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) { + return 0; +} + +// once + +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { + STUB(); +} + +// rwlock + +int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) { + return 0; +} + +int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) { + return 0; +} + +int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) { + return 0; +} + +int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) { + return 0; +} + +int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) { + return 0; +} + +int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) { + return 0; +} + +int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) { + return 0; +} + +// named semaphores + +sem_t *sem_open(const char *name, int oflag, ...) { + STUB(); +} diff --git a/stdlib/public/core/DebuggerSupport.swift b/stdlib/public/core/DebuggerSupport.swift index ef9eafeab81f7..c8c77d26400ed 100644 --- a/stdlib/public/core/DebuggerSupport.swift +++ b/stdlib/public/core/DebuggerSupport.swift @@ -269,9 +269,12 @@ public func _stringForPrintObject(_ value: Any) -> String { public func _debuggerTestingCheckExpect(_: String, _: String) { } // Utilities to get refcount(s) of class objects. -@_silgen_name("swift_retainCount") -public func _getRetainCount(_ Value: AnyObject) -> UInt -@_silgen_name("swift_unownedRetainCount") -public func _getUnownedRetainCount(_ Value: AnyObject) -> UInt -@_silgen_name("swift_weakRetainCount") -public func _getWeakRetainCount(_ Value: AnyObject) -> UInt +public func _getRetainCount(_ Value: AnyObject) -> UInt { + return UInt(swift_retainCount(unsafeBitCast(Value, to: UnsafeMutablePointer.self))) +} +public func _getUnownedRetainCount(_ Value: AnyObject) -> UInt { + return UInt(swift_unownedRetainCount(unsafeBitCast(Value, to: UnsafeMutablePointer.self))) +} +public func _getWeakRetainCount(_ Value: AnyObject) -> UInt { + return UInt(swift_weakRetainCount(unsafeBitCast(Value, to: UnsafeMutablePointer.self))) +} diff --git a/stdlib/public/core/ValidUTF8Buffer.swift b/stdlib/public/core/ValidUTF8Buffer.swift index 38799a2a86aff..7dd7ca38bee37 100644 --- a/stdlib/public/core/ValidUTF8Buffer.swift +++ b/stdlib/public/core/ValidUTF8Buffer.swift @@ -127,7 +127,10 @@ extension _ValidUTF8Buffer: RandomAccessCollection { @inlinable @inline(__always) public func distance(from i: Index, to j: Index) -> Int { - _debugPrecondition(_isValid(i)) + // FIXME(katei): The precondition check is commented out because it + // causes bad codegen for `stacksave` on WebAssembly. + // See https://github.com/llvm/llvm-project/issues/62235 + // _debugPrecondition(_isValid(i)) _debugPrecondition(_isValid(j)) return ( i._biasedBits.leadingZeroBitCount - j._biasedBits.leadingZeroBitCount diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index 18320c6d7689f..c7f4a07ad026c 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -89,6 +89,7 @@ set(swift_runtime_backtracing_sources set(LLVM_OPTIONAL_SOURCES SwiftRT-COFF.cpp SwiftRT-ELF.cpp + SwiftRT-WASM.cpp ${swift_runtime_sources} ${swift_runtime_objc_sources} ${swift_runtime_leaks_sources} @@ -102,28 +103,34 @@ set(swift_runtime_library_compile_flags ${swift_runtime_compile_flags}) list(APPEND swift_runtime_library_compile_flags -DswiftCore_EXPORTS) list(APPEND swift_runtime_library_compile_flags -I${SWIFT_SOURCE_DIR}/stdlib/include/llvm/Support -I${SWIFT_SOURCE_DIR}/include) -set(sdk "${SWIFT_HOST_VARIANT_SDK}") -if(SWIFT_BUILD_STATIC_STDLIB AND "${sdk}" STREQUAL "LINUX") +if(SWIFT_BUILD_STATIC_STDLIB) set(static_binary_lnk_file_list) - string(TOLOWER "${sdk}" lowercase_sdk) - set(static_binary_lnk_src "${SWIFT_SOURCE_DIR}/stdlib/public/Resources/${lowercase_sdk}/static-executable-args.lnk") - - # Generate the static-executable-args.lnk file used for ELF systems (eg linux) - set(linkfile "${lowercase_sdk}/static-executable-args.lnk") - add_custom_command_target(swift_static_binary_${sdk}_args - COMMAND - "${CMAKE_COMMAND}" -E copy - "${static_binary_lnk_src}" - "${SWIFTSTATICLIB_DIR}/${linkfile}" - OUTPUT - "${SWIFTSTATICLIB_DIR}/${linkfile}" - DEPENDS - "${static_binary_lnk_src}") - - list(APPEND static_binary_lnk_file_list ${swift_static_binary_${sdk}_args}) - swift_install_in_component(FILES "${SWIFTSTATICLIB_DIR}/${linkfile}" - DESTINATION "lib/swift_static/${lowercase_sdk}" - COMPONENT stdlib) + + foreach(sdk ${SWIFT_SDKS}) + if(NOT "${sdk}" STREQUAL "LINUX" AND NOT "${sdk}" STREQUAL "WASI") + continue() + endif() + + string(TOLOWER "${sdk}" lowercase_sdk) + set(static_binary_lnk_src "${SWIFT_SOURCE_DIR}/stdlib/public/Resources/${lowercase_sdk}/static-executable-args.lnk") + + # Generate the static-executable-args.lnk file used for ELF systems (eg linux) + set(linkfile "${lowercase_sdk}/static-executable-args.lnk") + add_custom_command_target(swift_static_binary_${sdk}_args + COMMAND + "${CMAKE_COMMAND}" -E copy + "${static_binary_lnk_src}" + "${SWIFTSTATICLIB_DIR}/${linkfile}" + OUTPUT + "${SWIFTSTATICLIB_DIR}/${linkfile}" + DEPENDS + "${static_binary_lnk_src}") + + list(APPEND static_binary_lnk_file_list ${swift_static_binary_${sdk}_args}) + swift_install_in_component(FILES "${SWIFTSTATICLIB_DIR}/${linkfile}" + DESTINATION "lib/swift_static/${lowercase_sdk}" + COMPONENT stdlib) + endforeach() add_dependencies(stdlib ${static_binary_lnk_file_list}) add_custom_target(static_binary_magic ALL DEPENDS ${static_binary_lnk_file_list}) endif() @@ -140,11 +147,14 @@ add_swift_target_library(swiftRuntime OBJECT_LIBRARY set(ELFISH_SDKS) set(COFF_SDKS) +set(WASM_SDKS) foreach(sdk ${SWIFT_SDKS}) if("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "ELF") list(APPEND ELFISH_SDKS ${sdk}) elseif("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "COFF") list(APPEND COFF_SDKS ${sdk}) + elseif("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "WASM") + list(APPEND WASM_SDKS ${sdk}) endif() endforeach() @@ -160,6 +170,16 @@ add_swift_target_library(swiftImageRegistrationObjectELF TARGET_SDKS ${ELFISH_SDKS} SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} INSTALL_IN_COMPONENT none) + +add_swift_target_library(swiftImageRegistrationObjectWASM + OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE + SwiftRT-WASM.cpp + C_COMPILE_FLAGS ${SWIFT_RUNTIME_CORE_CXX_FLAGS} + LINK_FLAGS ${SWIFT_RUNTIME_CORE_LINK_FLAGS} + TARGET_SDKS ${WASM_SDKS} + SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} + INSTALL_IN_COMPONENT none) + # FIXME(compnerd) this should be compiled twice, once for static and once for # shared. The static version should be used for building the standard library. add_swift_target_library(swiftImageRegistrationObjectCOFF @@ -177,7 +197,8 @@ foreach(sdk ${SWIFT_SDKS}) set(arch_suffix "${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}") if("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "ELF" OR - "${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "COFF") + "${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "COFF" OR + "${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "WASM") # TODO(compnerd) switch to the generator expression when cmake is upgraded # to a version which supports it. # set(swiftrtObject "$") @@ -227,10 +248,31 @@ foreach(sdk ${SWIFT_SDKS}) add_dependencies(stdlib swift-stdlib-${arch_suffix} swiftImageRegistration-${arch_suffix}) endif() + string(TOLOWER "${sdk}" lowercase_sdk) # Generate the static-stdlib-args.lnk file used by -static-stdlib option for # 'GenericUnix' (eg linux) if(${SWIFT_SDK_${sdk}_OBJECT_FORMAT} STREQUAL ELF) string(TOLOWER "${sdk}" lowercase_sdk) + if(SWIFT_${SWIFT_HOST_VARIANT_SDK}_${SWIFT_HOST_VARIANT_ARCH}_ICU_STATICLIB) + set(libicu_i18n_a -licui18nswift) + set(libicu_uc_a -licuucswift) + set(libicu_data_a -licudataswift) + else() + find_package(ICU REQUIRED COMPONENTS uc i18n) + get_filename_component(ICU_UC_LIBDIR "${ICU_UC_LIBRARIES}" DIRECTORY) + get_filename_component(ICU_I18N_LIBDIR "${ICU_I18N_LIBRARIES}" DIRECTORY) + + set(libicu_i18n_a -licui18n) + set(libicu_uc_a -licuuc) + set(libicu_data_a) + if(EXISTS ${ICU_I18N_LIBDIR}/libicui18n.a AND + EXISTS ${ICU_UC_LIBDIR}/libicuuc.a AND + EXISTS ${ICU_UC_LIBDIR}/libicudata.a) + set(libicu_i18n_a ${ICU_I18N_LIBDIR}/libicui18n.a) + set(libicu_uc_a ${ICU_UC_LIBDIR}/libicuuc.a) + set(libicu_data_a ${ICU_UC_LIBDIR}/libicudata.a) + endif() + endif() set(libpthread -lpthread) set(concurrency_libs) set(android_libraries) @@ -257,6 +299,45 @@ ${concurrency_libs} swift_install_in_component(FILES "${SWIFTSTATICLIB_DIR}/${linkfile}" DESTINATION "lib/swift_static/${lowercase_sdk}" COMPONENT stdlib) + elseif("${sdk}" STREQUAL "WASI") + set(linkfile "${lowercase_sdk}/static-stdlib-args.lnk") + file(WRITE "${SWIFTSTATICLIB_DIR}/${linkfile}" " +-ldl +-latomic +-lswiftWasiPthread +-lswiftCore +-licuuc +-licudata +-lstdc++ +-lm +-Xlinker --exclude-libs +-Xlinker ALL") + + swift_install_in_component(FILES "${SWIFTSTATICLIB_DIR}/${linkfile}" + DESTINATION "lib/swift_static/${lowercase_sdk}" + COMPONENT stdlib) + + set(swift_icu_libs_wasi_list) + set(icu_modules UC I18N DATA) + foreach(module IN LISTS icu_modules) + set(module_lib "${SWIFT_WASI_wasm32_ICU_${module}}") + get_filename_component(module_lib_name ${module_lib} NAME) + add_custom_command_target(swift_icu_${module}_${sdk} + COMMAND + "${CMAKE_COMMAND}" -E copy + "${module_lib}" + "${SWIFTSTATICLIB_DIR}/${lowercase_sdk}/${module_lib_name}" + OUTPUT + "${SWIFTSTATICLIB_DIR}/${lowercase_sdk}/${module_lib_name}" + DEPENDS + "${module_lib}") + list(APPEND swift_icu_libs_wasi_list ${swift_icu_${module}_${sdk}}) + swift_install_in_component(FILES "${SWIFTSTATICLIB_DIR}/${lowercase_sdk}/${module_lib_name}" + DESTINATION "lib/swift_static/${lowercase_sdk}" + COMPONENT stdlib) + endforeach() + add_custom_target(swift_icu_libs_wasi ALL DEPENDS ${swift_icu_libs_wasi_list}) + add_dependencies(stdlib swift_icu_libs_wasi) endif() endforeach() endforeach() diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp index 7a585ccc43f4a..55a8a0d3ee433 100644 --- a/stdlib/public/runtime/Demangle.cpp +++ b/stdlib/public/runtime/Demangle.cpp @@ -910,6 +910,7 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type, /// \returns the demangled name. Returns nullptr if the input String is not a /// Swift mangled name. SWIFT_RUNTIME_EXPORT +SWIFT_CC(swift) char *swift_demangle(const char *mangledName, size_t mangledNameLength, char *outputBuffer, diff --git a/stdlib/public/runtime/EnvironmentVariables.cpp b/stdlib/public/runtime/EnvironmentVariables.cpp index 264e44a4db613..3a04eb9c92843 100644 --- a/stdlib/public/runtime/EnvironmentVariables.cpp +++ b/stdlib/public/runtime/EnvironmentVariables.cpp @@ -253,6 +253,7 @@ void swift::runtime::environment::initialize(void *context) { } #endif +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT bool swift_COWChecksEnabled() { return runtime::environment::SWIFT_DEBUG_ENABLE_COW_CHECKS(); diff --git a/stdlib/public/runtime/Heap.cpp b/stdlib/public/runtime/Heap.cpp index 23e09ffa4eef4..dcf13c40960f5 100644 --- a/stdlib/public/runtime/Heap.cpp +++ b/stdlib/public/runtime/Heap.cpp @@ -32,10 +32,11 @@ using namespace swift; /// On Apple platforms, \c malloc() is always 16-byte aligned. static constexpr size_t MALLOC_ALIGN_MASK = 15; -#elif defined(__linux__) || defined(_WIN32) +#elif defined(__linux__) || defined(_WIN32) || defined(__wasi__) /// On Linux and Windows, \c malloc() returns 16-byte aligned pointers on 64-bit /// and 8-byte aligned pointers on 32-bit. -#if defined(__LP64) || defined(_WIN64) +/// On wasi-libc, pointers are 16-byte aligned even though 32-bit for SIMD access. +#if defined(__LP64) || defined(_WIN64) || defined(__wasi__) static constexpr size_t MALLOC_ALIGN_MASK = 15; #else static constexpr size_t MALLOC_ALIGN_MASK = 7; diff --git a/stdlib/public/runtime/RuntimeInvocationsTracking.cpp b/stdlib/public/runtime/RuntimeInvocationsTracking.cpp index bf5812b4ba100..51a9ab16b11ca 100644 --- a/stdlib/public/runtime/RuntimeInvocationsTracking.cpp +++ b/stdlib/public/runtime/RuntimeInvocationsTracking.cpp @@ -130,7 +130,7 @@ static std::uint16_t RuntimeFunctionCountersOffsets[] = { /// Public APIs /// Get the runtime object state associated with an object. -void _swift_getObjectRuntimeFunctionCounters( +SWIFT_CC(swift) void _swift_getObjectRuntimeFunctionCounters( HeapObject *object, RuntimeFunctionCountersState *result) { auto &theSentinel = RuntimeObjectStateCache.get(); Mutex::ScopedLock lock(theSentinel.Lock); @@ -139,7 +139,7 @@ void _swift_getObjectRuntimeFunctionCounters( /// Set the runtime object state associated with an object from a provided /// state. -void _swift_setObjectRuntimeFunctionCounters( +SWIFT_CC(swift) void _swift_setObjectRuntimeFunctionCounters( HeapObject *object, RuntimeFunctionCountersState *state) { auto &theSentinel = RuntimeObjectStateCache.get(); Mutex::ScopedLock lock(theSentinel.Lock); @@ -148,14 +148,14 @@ void _swift_setObjectRuntimeFunctionCounters( /// Get the global runtime state containing the total numbers of invocations for /// each runtime function of interest. -void _swift_getGlobalRuntimeFunctionCounters( +SWIFT_CC(swift) void _swift_getGlobalRuntimeFunctionCounters( RuntimeFunctionCountersState *result) { LazyMutex::ScopedLock lock(RuntimeGlobalFunctionCountersState.Lock); *result = RuntimeGlobalFunctionCountersState.State; } /// Set the global runtime state of function pointers from a provided state. -void _swift_setGlobalRuntimeFunctionCounters( +SWIFT_CC(swift) void _swift_setGlobalRuntimeFunctionCounters( RuntimeFunctionCountersState *state) { LazyMutex::ScopedLock lock(RuntimeGlobalFunctionCountersState.Lock); RuntimeGlobalFunctionCountersState.State = *state; @@ -164,18 +164,20 @@ void _swift_setGlobalRuntimeFunctionCounters( /// Return the names of the runtime functions being tracked. /// Their order is the same as the order of the counters in the /// RuntimeObjectState structure. All these strings are null terminated. -const char **_swift_getRuntimeFunctionNames() { +SWIFT_CC(swift) const char **_swift_getRuntimeFunctionNames() { return RuntimeFunctionNames; } /// Return the offsets of the runtime function counters being tracked. /// Their order is the same as the order of the counters in the /// RuntimeObjectState structure. +SWIFT_CC(swift) const std::uint16_t *_swift_getRuntimeFunctionCountersOffsets() { return RuntimeFunctionCountersOffsets; } /// Return the number of runtime functions being tracked. +SWIFT_CC(swift) std::uint64_t _swift_getNumRuntimeFunctionCounters() { return ID_LastRuntimeFunctionName; } @@ -204,7 +206,7 @@ void _swift_dumpObjectsRuntimeFunctionPointers() { /// Set mode for global runtime function counters. /// Return the old value of this flag. -int _swift_setGlobalRuntimeFunctionCountersMode(int mode) { +SWIFT_CC(swift) int _swift_setGlobalRuntimeFunctionCountersMode(int mode) { int oldMode = UpdateGlobalRuntimeFunctionCounters; UpdateGlobalRuntimeFunctionCounters = mode ? 1 : 0; return oldMode; @@ -212,7 +214,7 @@ int _swift_setGlobalRuntimeFunctionCountersMode(int mode) { /// Set mode for per object runtime function counters. /// Return the old value of this flag. -int _swift_setPerObjectRuntimeFunctionCountersMode(int mode) { +SWIFT_CC(swift) int _swift_setPerObjectRuntimeFunctionCountersMode(int mode) { int oldMode = UpdatePerObjectRuntimeFunctionCounters; UpdatePerObjectRuntimeFunctionCounters = mode ? 1 : 0; return oldMode; diff --git a/stdlib/public/runtime/RuntimeInvocationsTracking.h b/stdlib/public/runtime/RuntimeInvocationsTracking.h index 74d609176563e..3005df2b79c7c 100644 --- a/stdlib/public/runtime/RuntimeInvocationsTracking.h +++ b/stdlib/public/runtime/RuntimeInvocationsTracking.h @@ -61,47 +61,47 @@ using RuntimeFunctionCountersUpdateHandler = /// Get the runtime object state associated with an object and store it /// into the result. -SWIFT_RUNTIME_EXPORT void +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT void _swift_getObjectRuntimeFunctionCounters(HeapObject *object, RuntimeFunctionCountersState *result); /// Get the global runtime state containing the total numbers of invocations for /// each runtime function of interest and store it into the result. -SWIFT_RUNTIME_EXPORT void _swift_getGlobalRuntimeFunctionCounters( +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT void _swift_getGlobalRuntimeFunctionCounters( swift::RuntimeFunctionCountersState *result); /// Return the names of the runtime functions being tracked. /// Their order is the same as the order of the counters in the /// RuntimeObjectState structure. -SWIFT_RUNTIME_EXPORT const char **_swift_getRuntimeFunctionNames(); +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT const char **_swift_getRuntimeFunctionNames(); /// Return the offsets of the runtime function counters being tracked. /// Their order is the same as the order of the counters in the /// RuntimeFunctionCountersState structure. -SWIFT_RUNTIME_EXPORT const uint16_t *_swift_getRuntimeFunctionCountersOffsets(); +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT const uint16_t *_swift_getRuntimeFunctionCountersOffsets(); /// Return the number of runtime functions being tracked. -SWIFT_RUNTIME_EXPORT uint64_t _swift_getNumRuntimeFunctionCounters(); +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT uint64_t _swift_getNumRuntimeFunctionCounters(); /// Dump all per-object runtime function pointers. SWIFT_RUNTIME_EXPORT void _swift_dumpObjectsRuntimeFunctionPointers(); /// Set mode for global runtime function counters. /// Return the old value of this flag. -SWIFT_RUNTIME_EXPORT int +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT int _swift_setPerObjectRuntimeFunctionCountersMode(int mode); /// Set mode for per object runtime function counters. /// Return the old value of this flag. -SWIFT_RUNTIME_EXPORT int _swift_setGlobalRuntimeFunctionCountersMode(int mode); +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT int _swift_setGlobalRuntimeFunctionCountersMode(int mode); /// Set the global runtime state of function pointers from a provided state. -SWIFT_RUNTIME_EXPORT void _swift_setGlobalRuntimeFunctionCounters( +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT void _swift_setGlobalRuntimeFunctionCounters( swift::RuntimeFunctionCountersState *state); /// Set the runtime object state associated with an object from a provided /// state. -SWIFT_RUNTIME_EXPORT void +SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT void _swift_setObjectRuntimeFunctionCounters(HeapObject *object, RuntimeFunctionCountersState *state); diff --git a/stdlib/public/runtime/SwiftRT-WASM.cpp b/stdlib/public/runtime/SwiftRT-WASM.cpp new file mode 100644 index 0000000000000..55dbe7aa851f0 --- /dev/null +++ b/stdlib/public/runtime/SwiftRT-WASM.cpp @@ -0,0 +1,79 @@ +//===--- SwiftRT-WASM.cpp --------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +#include "ImageInspectionCommon.h" +#include "swift/shims/MetadataSections.h" + +#include +#include + +// Link start/stop symbols weakly to link them if they aren't synthesized by the linker. +#define DECLARE_SWIFT_SECTION(name) \ + __attribute__((__visibility__("hidden"),__aligned__(1),weak)) extern const char __start_##name; \ + __attribute__((__visibility__("hidden"),__aligned__(1),weak)) extern const char __stop_##name; + +extern "C" { +DECLARE_SWIFT_SECTION(swift5_protocols) +DECLARE_SWIFT_SECTION(swift5_protocol_conformances) +DECLARE_SWIFT_SECTION(swift5_type_metadata) + +DECLARE_SWIFT_SECTION(swift5_typeref) +DECLARE_SWIFT_SECTION(swift5_reflstr) +DECLARE_SWIFT_SECTION(swift5_fieldmd) +DECLARE_SWIFT_SECTION(swift5_assocty) +DECLARE_SWIFT_SECTION(swift5_replace) +DECLARE_SWIFT_SECTION(swift5_replac2) +DECLARE_SWIFT_SECTION(swift5_builtin) +DECLARE_SWIFT_SECTION(swift5_capture) +DECLARE_SWIFT_SECTION(swift5_mpenum) +DECLARE_SWIFT_SECTION(swift5_accessible_functions) +} + +#undef DECLARE_SWIFT_SECTION + +namespace { +static swift::MetadataSections sections{}; +} + +__attribute__((__constructor__)) +static void swift_image_constructor() { +#define SWIFT_SECTION_RANGE(name) \ + { reinterpret_cast(&__start_##name), \ + static_cast(&__stop_##name - &__start_##name) } + + new (§ions) swift::MetadataSections { + swift::CurrentSectionMetadataVersion, + { 0 }, + + nullptr, + nullptr, + + SWIFT_SECTION_RANGE(swift5_protocols), + SWIFT_SECTION_RANGE(swift5_protocol_conformances), + SWIFT_SECTION_RANGE(swift5_type_metadata), + + SWIFT_SECTION_RANGE(swift5_typeref), + SWIFT_SECTION_RANGE(swift5_reflstr), + SWIFT_SECTION_RANGE(swift5_fieldmd), + SWIFT_SECTION_RANGE(swift5_assocty), + SWIFT_SECTION_RANGE(swift5_replace), + SWIFT_SECTION_RANGE(swift5_replac2), + SWIFT_SECTION_RANGE(swift5_builtin), + SWIFT_SECTION_RANGE(swift5_capture), + SWIFT_SECTION_RANGE(swift5_mpenum), + SWIFT_SECTION_RANGE(swift5_accessible_functions), + }; + +#undef SWIFT_SECTION_RANGE + + swift_addNewDSOImage(§ions); +} diff --git a/stdlib/public/stubs/Random.cpp b/stdlib/public/stubs/Random.cpp index 460e12e8656f6..c694f0508d4a3 100644 --- a/stdlib/public/stubs/Random.cpp +++ b/stdlib/public/stubs/Random.cpp @@ -45,6 +45,7 @@ #endif #include +#include #include "swift/shims/Random.h" #include "swift/Runtime/Debug.h" diff --git a/test/AutolinkExtract/empty.swift b/test/AutolinkExtract/empty.swift index b9ae0068c07d6..c5b612927092a 100644 --- a/test/AutolinkExtract/empty.swift +++ b/test/AutolinkExtract/empty.swift @@ -5,3 +5,4 @@ // CHECK-elf: -lswiftCore // CHECK-coff: -lswiftCore +// CHECK-wasm: -lswiftCore diff --git a/test/AutolinkExtract/empty_archive.swift b/test/AutolinkExtract/empty_archive.swift index ee66d6762610c..a94f40ad68c1b 100644 --- a/test/AutolinkExtract/empty_archive.swift +++ b/test/AutolinkExtract/empty_archive.swift @@ -7,3 +7,4 @@ // CHECK-elf: -lswiftCore // CHECK-coff: -lswiftCore +// CHECK-wasm: -lswiftCore diff --git a/test/AutolinkExtract/import.swift b/test/AutolinkExtract/import.swift index 2b95be66fe0e6..5fe5a77ff4b75 100644 --- a/test/AutolinkExtract/import.swift +++ b/test/AutolinkExtract/import.swift @@ -18,4 +18,7 @@ // CHECK-coff-DAG: -lswiftCore // CHECK-coff-DAG: -lempty +// CHECK-wasm-DAG: -lswiftCore +// CHECK-wasm-DAG: -lempty + import empty diff --git a/test/AutolinkExtract/import_archive.swift b/test/AutolinkExtract/import_archive.swift index 5aa0ee41d74ee..1bd6f5323a87a 100644 --- a/test/AutolinkExtract/import_archive.swift +++ b/test/AutolinkExtract/import_archive.swift @@ -12,4 +12,7 @@ // CHECK-coff-DAG: -lswiftCore // CHECK-coff-DAG: -lempty +// CHECK-wasm-DAG: -lswiftCore +// CHECK-wasm-DAG: -lempty + import empty diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cbbfdeffcbe74..7157254daef96 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -109,7 +109,8 @@ function(get_test_dependencies SDK result_var_name) ("${SDK}" STREQUAL "OPENBSD") OR ("${SDK}" STREQUAL "ANDROID") OR ("${SDK}" STREQUAL "WINDOWS") OR - ("${SDK}" STREQUAL "HAIKU")) + ("${SDK}" STREQUAL "HAIKU") OR + ("${SDK}" STREQUAL "WASI")) # No extra dependencies. else() message(FATAL_ERROR "Unknown SDK: ${SDK}") @@ -149,8 +150,14 @@ if(NOT SWIFT_INCLUDE_TOOLS) ) endif() if(SWIFT_BUILD_STDLIB) - list(APPEND SWIFT_LIT_ARGS - "--param" "test_resource_dir=${SWIFTLIB_DIR}") + # if building only static stdlib, prefer static lib. + if(NOT SWIFT_BUILD_DYNAMIC_STDLIB AND SWIFT_BUILD_STATIC_STDLIB) + list(APPEND SWIFT_LIT_ARGS + "--param" "test_resource_dir=${SWIFTSTATICLIB_DIR}") + else() + list(APPEND SWIFT_LIT_ARGS + "--param" "test_resource_dir=${SWIFTLIB_DIR}") + endif() endif() endif() diff --git a/test/Concurrency/Runtime/actor_assert_precondition_executor.swift b/test/Concurrency/Runtime/actor_assert_precondition_executor.swift index b6a1966f14e5d..17381853f8efa 100644 --- a/test/Concurrency/Runtime/actor_assert_precondition_executor.swift +++ b/test/Concurrency/Runtime/actor_assert_precondition_executor.swift @@ -78,10 +78,12 @@ actor Someone { await MainFriend().callCheckMainActor() } + #if !os(WASI) tests.test("precondition on actor (main): wrongly assume the main executor, from actor on other executor") { expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected 'MainActor' executor.") await Someone().callCheckMainActor() } + #endif // === Global actor ----------------------------------------------------- @@ -94,4 +96,4 @@ actor Someone { await runAllTestsAsync() } -} \ No newline at end of file +} diff --git a/test/Concurrency/Runtime/actor_assume_executor.swift b/test/Concurrency/Runtime/actor_assume_executor.swift index 2c703a4687a27..60652080a9c76 100644 --- a/test/Concurrency/Runtime/actor_assume_executor.swift +++ b/test/Concurrency/Runtime/actor_assume_executor.swift @@ -115,14 +115,17 @@ final class MainActorEcho { await MainFriend().callCheck(echo: echo) } + #if !os(WASI) tests.test("MainActor.assumeIsolated: wrongly assume the main executor, from actor on other executor") { expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected 'MainActor' executor.") await Someone().callCheckMainActor(echo: echo) } + #endif // === some Actor ------------------------------------------------------- let someone = Someone() + #if !os(WASI) tests.test("assumeOnActorExecutor: wrongly assume someone's executor, from 'main() async'") { expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected same executor as a.Someone.") checkAssumeSomeone(someone: someone) @@ -132,6 +135,7 @@ final class MainActorEcho { expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected same executor as a.Someone.") checkAssumeSomeone(someone: someone) } + #endif tests.test("assumeOnActorExecutor: assume someone's executor, from Someone") { await someone.callCheckSomeone() @@ -141,10 +145,12 @@ final class MainActorEcho { await SomeonesFriend(someone: someone).callCheckSomeone() } + #if !os(WASI) tests.test("assumeOnActorExecutor: wrongly assume the main executor, from actor on other executor") { expectCrashLater(withMessage: "Incorrect actor executor assumption; Expected same executor as a.Someone.") await CompleteStranger(someone: someone).callCheckSomeone() } + #endif } diff --git a/test/Concurrency/Runtime/cancellation_handler.swift b/test/Concurrency/Runtime/cancellation_handler.swift index 4cc044c7579bc..b1b154593e059 100644 --- a/test/Concurrency/Runtime/cancellation_handler.swift +++ b/test/Concurrency/Runtime/cancellation_handler.swift @@ -12,6 +12,8 @@ import Darwin #elseif canImport(Glibc) import Glibc +#elseif os(WASI) + import WASILibc #elseif os(Windows) import WinSDK #endif diff --git a/test/Concurrency/Runtime/checked_continuation.swift b/test/Concurrency/Runtime/checked_continuation.swift index 9f9f1d81469d0..9869d12090549 100644 --- a/test/Concurrency/Runtime/checked_continuation.swift +++ b/test/Concurrency/Runtime/checked_continuation.swift @@ -16,6 +16,8 @@ struct TestError: Error {} var tests = TestSuite("CheckedContinuation") if #available(SwiftStdlib 5.1, *) { +// Disable crash tests +#if !os(WASI) tests.test("trap on double resume non-throwing continuation") { expectCrashLater() @@ -42,7 +44,7 @@ struct TestError: Error {} } await task.get() } - +#endif tests.test("test withCheckedThrowingContinuation") { let task2 = detach { do { diff --git a/test/Concurrency/Runtime/continuation_validation.swift b/test/Concurrency/Runtime/continuation_validation.swift index 941fdd559eb09..78c86e94647a4 100644 --- a/test/Concurrency/Runtime/continuation_validation.swift +++ b/test/Concurrency/Runtime/continuation_validation.swift @@ -12,6 +12,7 @@ // UNSUPPORTED: back_deploy_concurrency // UNSUPPORTED: use_os_stdlib // UNSUPPORTED: freestanding +// UNSUPPORTED: OS=wasi import StdlibUnittest diff --git a/test/DebugInfo/modulecache.swift b/test/DebugInfo/modulecache.swift index 1dceafbf15de1..22d126eca7cde 100644 --- a/test/DebugInfo/modulecache.swift +++ b/test/DebugInfo/modulecache.swift @@ -16,7 +16,7 @@ import ClangModule // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s -c -g -o %t.o -module-cache-path %t -I %S/Inputs // RUN: llvm-readobj -h %t/*/ClangModule-*.pcm | %FileCheck %s -// CHECK: Format: {{(Mach-O|ELF|elf64|COFF|elf32-littlearm)}} +// CHECK: Format: {{(Mach-O|ELF|elf64|COFF|elf32-littlearm|WASM)}} // 3. Test that swift-ide-check will not share swiftc's module cache. diff --git a/test/Driver/profiling.swift b/test/Driver/profiling.swift index 45a9f84d12b69..9f48a09002e0c 100644 --- a/test/Driver/profiling.swift +++ b/test/Driver/profiling.swift @@ -6,6 +6,7 @@ // RUN: %swiftc_driver -sdk "" -driver-print-jobs -profile-generate -target x86_64-apple-ios7.1-simulator -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ %s | %FileCheck -check-prefix=CHECK -check-prefix=IOSSIM %s // RUN: %swiftc_driver -sdk "" -driver-print-jobs -profile-generate -target arm64-apple-ios7.1 -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ %s | %FileCheck -check-prefix=CHECK -check-prefix=IOS %s +// RUN: %swiftc_driver -driver-print-jobs -profile-generate -target wasm32-unknown-wasi %s | %FileCheck -check-prefix CHECK -check-prefix WASI %s // RUN: %swiftc_driver -sdk "" -driver-print-jobs -profile-generate -target x86_64-apple-tvos9.0-simulator -resource-dir %S/Inputs/fake-resource-dir-old/lib/swift/ %s | %FileCheck -check-prefix=CHECK -check-prefix=tvOS %s // RUN: %swiftc_driver -sdk "" -driver-print-jobs -profile-generate -target arm64-apple-tvos9.0 -resource-dir %S/Inputs/fake-resource-dir-old/lib/swift/ %s | %FileCheck -check-prefix=CHECK -check-prefix=tvOS %s diff --git a/test/lit.cfg b/test/lit.cfg index d2cecb5015ddc..85592fdcae869 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -345,7 +345,6 @@ config.swift_demangle_yamldump = inferSwiftBinary('swift-demangle-yamldump') config.swift_demangle = inferSwiftBinary('swift-demangle') config.benchmark_o = inferSwiftBinary('Benchmark_O') config.benchmark_driver = inferSwiftBinary('Benchmark_Driver') -config.wasmer = inferSwiftBinary('wasmer') config.wasm_ld = inferSwiftBinary('wasm-ld') config.swift_plugin_server = inferSwiftBinary('swift-plugin-server') @@ -1057,6 +1056,7 @@ target_specific_module_triple = config.variant_triple target_future = target_specific_module_triple config.target_run = '' +config.target_run_with_leaks = '' config.target_rtti_opt = '-fno-rtti' config.target_pic_opt = '' config.target_cxx_lib = '-lc++' @@ -1822,39 +1822,72 @@ elif run_os == 'wasi': config.target_sdk_name = "wasi" config.target_runtime = "native" + # Exclude test cases that use objc-interop because clang doesn't support it + # with WebAssembly binary file yet. + def use_objc_interop(path): + try: + with open(path) as f: + return '-enable-objc-interop' in f.read() + except: + return False + def lldb_related_test(path): + try: + with open(path) as f: + return 'lldb-moduleimport-test' in f.read() + except: + return False + + def disabled_filenames(path): + matches = [] + for root, dirnames, filenames in os.walk(path): + for filename in filenames: + filepath = os.path.join(root, filename) + if use_objc_interop(filepath) or lldb_related_test(filepath): + matches.append(os.path.basename(filepath)) + return matches + + config.excludes += disabled_filenames(config.test_source_root) + config.target_swift_autolink_extract = inferSwiftBinary("swift-autolink-extract") config.target_build_swift = ' '.join([ config.swiftc, '-target', config.variant_triple, - '-Xcc', '--sysroot=%s' % config.variant_sdk, - '-Xclang-linker', '--sysroot=%s' % config.variant_sdk, - '-toolchain-stdlib-rpath', config.resource_dir_opt, + '-sdk', config.variant_sdk, + '-toolchain-stdlib-rpath', config.resource_dir_opt, mcp_opt, config.swift_test_options, config.swift_driver_test_options, swift_execution_tests_extra_flags]) config.target_codesign = "echo" config.target_build_swift_dylib = ( - "%s -parse-as-library -emit-library -o '\\1'" + "%s -parse-as-library -emit-library -static -o '\\1'" % (config.target_build_swift)) config.target_add_rpath = '' config.target_swift_frontend = ' '.join([ config.swift_frontend, '-target', config.variant_triple, - '-Xcc', '--sysroot=%s' % config.variant_sdk, + '-sdk', config.variant_sdk, config.resource_dir_opt, mcp_opt, config.swift_test_options, config.swift_frontend_test_options]) subst_target_swift_frontend_mock_sdk = config.target_swift_frontend subst_target_swift_frontend_mock_sdk_after = "" - config.target_run = '%s run --backend cranelift --' % config.wasmer + config.target_run = os.path.join(config.swift_utils, 'webassembly', 'wasm-run.py') + config.target_env_prefix = 'WASM_RUN_CHILD_' + if 'interpret' in lit_config.params: use_interpreter_for_simple_runs() config.target_sil_opt = ( '%s -target %s %s %s %s' % (config.sil_opt, config.variant_triple, config.resource_dir_opt, mcp_opt, config.sil_test_options)) + subst_target_sil_opt_mock_sdk = config.target_sil_opt + subst_target_sil_opt_mock_sdk_after = "" config.target_swift_symbolgraph_extract = ' '.join([ config.swift_symbolgraph_extract, '-target', config.variant_triple, mcp_opt]) + config.target_swift_api_extract = ' '.join([ + config.swift_api_extract, + '-target', config.variant_triple, + '-sdk', shell_quote(config.variant_sdk)]) config.target_swift_ide_test = ( '%s -target %s %s %s %s %s' % (config.swift_ide_test, config.variant_triple, config.resource_dir_opt, @@ -2275,7 +2308,7 @@ if run_vendor != 'apple': if 'remote_run_host' in lit_config.params: configure_remote_run() -elif not kIsWindows: +elif not kIsWindows and not run_os == 'wasi': if 'use_os_stdlib' in lit_config.params: config.available_features.add('use_os_stdlib') diff --git a/test/stdlib/Duration.swift b/test/stdlib/Duration.swift index def1633b2e51d..fb51dc3710e3a 100644 --- a/test/stdlib/Duration.swift +++ b/test/stdlib/Duration.swift @@ -1,6 +1,9 @@ // RUN: %target-run-simple-swift // REQUIRES: executable_test +// Int128 operations are not supported on 32bit platforms. See `dividingFullWidth` in IntegerTypes.swift.gyb +// UNSUPPORTED: PTRSIZE=32 + import StdlibUnittest var suite = TestSuite("StringIndexTests") diff --git a/test/stdlib/Error.swift b/test/stdlib/Error.swift index 542b15f4f23bb..77e259621d155 100644 --- a/test/stdlib/Error.swift +++ b/test/stdlib/Error.swift @@ -207,6 +207,7 @@ ErrorTests.test("test dealloc empty error box") { } } +#if !os(WASI) var errors: [Error] = [] @inline(never) @@ -249,6 +250,7 @@ ErrorTests.test("willThrow") { expectEqual(2, errors.count) expectEqual(SillyError.self, type(of: errors.last!)) } +#endif runAllTests() diff --git a/test/stdlib/FloatingPointIR.swift b/test/stdlib/FloatingPointIR.swift index a00469c855cf4..00410eee5a4c1 100644 --- a/test/stdlib/FloatingPointIR.swift +++ b/test/stdlib/FloatingPointIR.swift @@ -56,3 +56,6 @@ func testConstantFoldFloatLiterals() { // s390x: call swiftcc void @"$s15FloatingPointIR13acceptFloat32yySfF{{.*}}"(float 1.000000e+00) // s390x: call swiftcc void @"$s15FloatingPointIR13acceptFloat64yySdF{{.*}}"(double 1.000000e+00) + +// wasm32: call swiftcc void @"$s15FloatingPointIR13acceptFloat32yySfF{{.*}}"(float 1.000000e+00) +// wasm32: call swiftcc void @"$s15FloatingPointIR13acceptFloat64yySdF{{.*}}"(double 1.000000e+00) diff --git a/test/stdlib/KeyPath.swift b/test/stdlib/KeyPath.swift index 59d02f7a2e08e..40ff0f79dd1f3 100644 --- a/test/stdlib/KeyPath.swift +++ b/test/stdlib/KeyPath.swift @@ -1078,7 +1078,7 @@ if #available(SwiftStdlib 5.9, *) { let dogAgeKp = _createOffsetBasedKeyPath( root: Dog.self, value: Int.self, - offset: 16 + offset: MemoryLayout.size ) as? KeyPath expectNotNil(dogAgeKp) diff --git a/test/stdlib/PrintStruct.swift b/test/stdlib/PrintStruct.swift index 9ecac23553978..b616e61f5172a 100644 --- a/test/stdlib/PrintStruct.swift +++ b/test/stdlib/PrintStruct.swift @@ -4,7 +4,10 @@ // RUN: %target-codesign %t/main // RUN: %target-run %t/main // REQUIRES: executable_test -// REQUIRES: reflection +// +// FIXME Disable this case because this failed on only CI. +// Failed with 'Caught exception of type "CallIndirectOOB"' +// UNSUPPORTED: CPU=wasm32 import StdlibUnittest import PrintTestTypes diff --git a/test/stdlib/StringAPI.swift b/test/stdlib/StringAPI.swift index 86dc0f174b2a2..6321c9737f725 100644 --- a/test/stdlib/StringAPI.swift +++ b/test/stdlib/StringAPI.swift @@ -342,6 +342,7 @@ StringTests.test("SameTypeComparisons") { expectFalse(xs != xs) } +#if !os(WASI) StringTests.test("CompareStringsWithUnpairedSurrogates") .xfail( .always(" Strings referring to underlying " + @@ -357,6 +358,7 @@ StringTests.test("CompareStringsWithUnpairedSurrogates") ] ) } +#endif StringTests.test("[String].joined() -> String") { let s = ["hello", "world"].joined() diff --git a/test/stdlib/StringAPICString.swift b/test/stdlib/StringAPICString.swift index fa8f005ab3711..5612d9b2a2e47 100644 --- a/test/stdlib/StringAPICString.swift +++ b/test/stdlib/StringAPICString.swift @@ -7,6 +7,12 @@ import StdlibUnittest +#if arch(wasm32) +let enableCrashTests = false +#else +let enableCrashTests = true +#endif + var CStringTests = TestSuite("CStringTests") func getNullUTF8() -> UnsafeMutablePointer? { @@ -227,6 +233,7 @@ CStringTests.test("Substring.withCString") { CStringTests.test("String.cString.with.Array.UInt8.input") { guard #available(SwiftStdlib 5.7, *) else { return } + do { let (u8p, dealloc) = getASCIIUTF8() defer { dealloc() } @@ -239,6 +246,7 @@ CStringTests.test("String.cString.with.Array.UInt8.input") { } } } + guard enableCrashTests else { return } // no need to test every case; that is covered in other tests expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) @@ -263,6 +271,7 @@ CStringTests.test("String.cString.with.Array.CChar.input") { } } } + guard enableCrashTests else { return } // no need to test every case; that is covered in other tests expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) @@ -292,6 +301,7 @@ CStringTests.test("String.cString.with.inout.UInt8.conversion") { var str = String(cString: &c) expectTrue(str.isEmpty) c = 100 + guard enableCrashTests else { return } expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) // withMessage: "input of String.init(cString:) must be null-terminated" @@ -306,6 +316,7 @@ CStringTests.test("String.cString.with.inout.CChar.conversion") { var str = String(cString: &c) expectTrue(str.isEmpty) c = 100 + guard enableCrashTests else { return } expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) // withMessage: "input of String.init(cString:) must be null-terminated" @@ -330,6 +341,7 @@ CStringTests.test("String.validatingUTF8.with.Array.input") { } } } + guard enableCrashTests else { return } // no need to test every case; that is covered in other tests expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) @@ -362,6 +374,7 @@ CStringTests.test("String.validatingUTF8.with.inout.conversion") { expectNotNil(str) expectEqual(str?.isEmpty, true) c = 100 + guard enableCrashTests else { return } expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) // withMessage: "input of String.init(validatingUTF8:) must be null-terminated" @@ -387,6 +400,7 @@ CStringTests.test("String.decodeCString.with.Array.input") { } } } + guard enableCrashTests else { return } // no need to test every case; that is covered in other tests expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) @@ -426,6 +440,7 @@ CStringTests.test("String.decodeCString.with.inout.conversion") { expectEqual(result?.result.isEmpty, true) expectEqual(result?.repairsMade, false) c = 100 + guard enableCrashTests else { return } expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) // withMessage: "input of decodeCString(_:as:repairingInvalidCodeUnits:) must be null-terminated" @@ -449,6 +464,7 @@ CStringTests.test("String.init.decodingCString.with.Array.input") { } } } + guard enableCrashTests else { return } // no need to test every case; that is covered in other tests expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) @@ -478,6 +494,7 @@ CStringTests.test("String.init.decodingCString.with.inout.conversion") { var str = String(decodingCString: &c, as: Unicode.UTF8.self) expectEqual(str.isEmpty, true) c = 100 + guard enableCrashTests else { return } expectCrashLater( // Workaround for https://github.com/apple/swift/issues/58362 (rdar://91365967) // withMessage: "input of String.init(decodingCString:as:) must be null-terminated" diff --git a/test/stdlib/TemporaryAllocation.swift b/test/stdlib/TemporaryAllocation.swift index 906831596533d..494d20ce234fe 100644 --- a/test/stdlib/TemporaryAllocation.swift +++ b/test/stdlib/TemporaryAllocation.swift @@ -70,6 +70,7 @@ TemporaryAllocationTestSuite.test("untypedEmptyAllocationIsStackAllocated") { } } +#if !os(WASI) TemporaryAllocationTestSuite.test("crashOnNegativeByteCount") { expectCrash { let byteCount = Int.random(in: -2 ..< -1) @@ -83,6 +84,7 @@ TemporaryAllocationTestSuite.test("crashOnNegativeAlignment") { withUnsafeTemporaryAllocation(byteCount: 16, alignment: alignment) { _ in } } } +#endif TemporaryAllocationTestSuite.test("untypedAllocationIsAligned") { withUnsafeTemporaryAllocation(byteCount: 1, alignment: 8) { buffer in @@ -136,12 +138,14 @@ TemporaryAllocationTestSuite.test("voidAllocationIsStackAllocated") { } } +#if !os(WASI) TemporaryAllocationTestSuite.test("crashOnNegativeValueCount") { expectCrash { let capacity = Int.random(in: -2 ..< -1) withUnsafeTemporaryAllocation(of: Int.self, capacity: capacity) { _ in } } } +#endif TemporaryAllocationTestSuite.test("typedAllocationIsAligned") { withUnsafeTemporaryAllocation(of: Int.self, capacity: 1) { buffer in diff --git a/test/stdlib/UnsafePointer.swift.gyb b/test/stdlib/UnsafePointer.swift.gyb index cc1775d78a5ab..08b84a61c4e40 100644 --- a/test/stdlib/UnsafePointer.swift.gyb +++ b/test/stdlib/UnsafePointer.swift.gyb @@ -537,6 +537,7 @@ ${SelfName}TestSuite.test("pointer(to:)") { % end } +#if !os(WASI) ${SelfName}TestSuite.test("pointer(to:).overflow") { struct Example { var a = false @@ -558,6 +559,7 @@ ${SelfName}TestSuite.test("pointer(to:).overflow") { let doublePointer = p.pointer(to: \.d) expectNotNil(doublePointer) } +#endif % end diff --git a/test/stdlib/UnsafeRawPointer.swift b/test/stdlib/UnsafeRawPointer.swift index df476c3ebe5cc..ffae95820354b 100644 --- a/test/stdlib/UnsafeRawPointer.swift +++ b/test/stdlib/UnsafeRawPointer.swift @@ -131,6 +131,7 @@ UnsafeMutableRawPointerExtraTestSuite.test("load.unaligned") expectEqual(result, 0xffff_0000) } +#if !os(WASI) UnsafeMutableRawPointerExtraTestSuite.test("load.invalid") .skip(.custom({ !_isDebugAssertConfiguration() }, reason: "This tests a debug precondition..")) @@ -154,6 +155,7 @@ UnsafeMutableRawPointerExtraTestSuite.test("load.invalid.mutable") } expectUnreachable() } +#endif UnsafeMutableRawPointerExtraTestSuite.test("store.unaligned") .skip(.custom({ @@ -184,6 +186,7 @@ UnsafeMutableRawPointerExtraTestSuite.test("store.unaligned") 0) } +#if !os(WASI) UnsafeMutableRawPointerExtraTestSuite.test("store.invalid") .skip(.custom({ !_isDebugAssertConfiguration() }, reason: "This tests a debug precondition..")) @@ -203,6 +206,7 @@ UnsafeMutableRawPointerExtraTestSuite.test("store.invalid") p1.storeBytes(of: m, as: Missile.self) expectUnreachable() } +#endif UnsafeMutableRawPointerExtraTestSuite.test("copyMemory") { let sizeInBytes = 4 * MemoryLayout.stride diff --git a/utils/build-script b/utils/build-script index dcbc39154891e..737a820ce648c 100755 --- a/utils/build-script +++ b/utils/build-script @@ -266,7 +266,6 @@ def validate_arguments(toolchain, args): "--legacy-impl is incompatible with building packages needing " "a toolchain (%s)" % ", ".join(targets_needing_toolchain)) - def default_stdlib_deployment_targets(args): """ Return targets for the Swift stdlib, based on the build machine. diff --git a/utils/build-script-impl b/utils/build-script-impl index 7569f806b1af1..2d2b0671f8765 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -116,12 +116,16 @@ KNOWN_SETTINGS=( darwin-toolchain-require-use-os-runtime "0" "When setting up a plist for a toolchain, require the users of the toolchain to link against the OS instead of the packaged toolchain runtime. 0 for false, 1 for true" darwin-xcrun-toolchain "default" "the name of the toolchain to use on Darwin" + ## WebAssembly/WASI Options + wasi-sysroot "" "An absolute path to the wasi-sysroot that will be used as a libc implementation for Wasm builds" + ## Build Types for Components swift-stdlib-build-type "Debug" "the CMake build variant for Swift" ## Skip Build ... skip-build "" "set to configure as usual while skipping the build step" skip-build-android "" "set to skip building Swift stdlibs for Android" + skip-build-wasm "" "set to skip building Swift stdlibs for WebAssembly" skip-build-benchmarks "" "set to skip building Swift Benchmark Suite" skip-build-clang-tools-extra "" "set to skip building clang-tools-extra as part of llvm" skip-build-compiler-rt "" "set to skip building Compiler-RT" @@ -486,7 +490,8 @@ function verify_host_is_supported() { | wasi-wasm32 \ | android-armv7 \ | android-aarch64 \ - | android-x86_64) + | android-x86_64 \ + | wasi-wasm32) ;; *) echo "Unknown host tools target: ${host}" @@ -1353,6 +1358,9 @@ function common_cross_c_flags() { watchos-*) echo -n " -arch ${arch} -target ${arch}-apple-watchos${DARWIN_DEPLOYMENT_VERSION_WATCHOS}" ;; + wasi-wasm32) + echo -n " -arch wasm32" + ;; esac local build_type=$2 @@ -1737,6 +1745,13 @@ for host in "${ALL_HOSTS[@]}"; do ) fi + if [[ ! "${SKIP_BUILD_WASM}" ]]; then + cmake_options=( + "${cmake_options[@]}" + -DSWIFT_WASI_SYSROOT_PATH:STRING="${WASI_SYSROOT}" + ) + fi + if [[ $(is_cross_tools_host ${host}) && "${host}" == "openbsd-"* && -n "${OPENBSD_USE_TOOLCHAIN_FILE}" ]]; then cmake_options=( "${cmake_options[@]}" diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index 3fc18b3c281bc..e62bfee0e8aeb 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -459,7 +459,7 @@ def create_argument_parser(): help='if set, provide a fixed path for the Swift backtracer') option('--compiler-vendor', store, - choices=['none', 'apple'], + choices=['none', 'apple', 'swiftwasm'], default=defaults.COMPILER_VENDOR, help='Compiler vendor name') option('--clang-compiler-version', store, diff --git a/utils/darwin-installer-scripts/postinstall b/utils/darwin-installer-scripts/postinstall index 8f00806645e78..e9750f04e9555 100755 --- a/utils/darwin-installer-scripts/postinstall +++ b/utils/darwin-installer-scripts/postinstall @@ -13,4 +13,4 @@ INSTALLED_TOOLCHAIN=$2 -ln -fs "${INSTALLED_TOOLCHAIN}" "${INSTALLED_TOOLCHAIN%/*}/swift-latest.xctoolchain" +ln -fhs "${INSTALLED_TOOLCHAIN}" "${INSTALLED_TOOLCHAIN%/*}/swift-latest.xctoolchain" diff --git a/utils/swift_build_support/swift_build_support/host_specific_configuration.py b/utils/swift_build_support/swift_build_support/host_specific_configuration.py index e976cc35920c1..c11ac5b779813 100644 --- a/utils/swift_build_support/swift_build_support/host_specific_configuration.py +++ b/utils/swift_build_support/swift_build_support/host_specific_configuration.py @@ -260,6 +260,8 @@ def __platforms_to_skip_build(self, args, stage_dependent_args): StdlibDeploymentTarget.AppleWatchSimulator) if not stage_dependent_args.build_android: platforms_to_skip_build.add(StdlibDeploymentTarget.Android) + if not args.build_wasm: + platforms_to_skip_build.add(StdlibDeploymentTarget.WASI) return platforms_to_skip_build def __platforms_to_skip_test(self, args, stage_dependent_args): @@ -301,6 +303,8 @@ def __platforms_to_skip_test(self, args, stage_dependent_args): StdlibDeploymentTarget.AppleWatchSimulator) if not stage_dependent_args.test_android: platforms_to_skip_test.add(StdlibDeploymentTarget.Android) + if not args.test_wasm: + platforms_to_skip_test.add(StdlibDeploymentTarget.WASI) return platforms_to_skip_test @@ -341,4 +345,6 @@ def __platforms_to_skip_test_host(self, args, stage_dependent_args): if not stage_dependent_args.test_watchos_host and \ not args.only_non_executable_test: platforms_to_skip_test_host.add(StdlibDeploymentTarget.AppleWatch) + if not args.test_wasm_host: + platforms_to_skip_test_host.add(StdlibDeploymentTarget.WASI) return platforms_to_skip_test_host diff --git a/utils/swift_build_support/swift_build_support/products/llvm.py b/utils/swift_build_support/swift_build_support/products/llvm.py index c0011248316f3..f38040ae21a90 100644 --- a/utils/swift_build_support/swift_build_support/products/llvm.py +++ b/utils/swift_build_support/swift_build_support/products/llvm.py @@ -64,6 +64,13 @@ def _compiler_vendor_flags(self): if self.args.compiler_vendor == "none": return [] + if self.args.compiler_vendor == "swiftwasm": + return [ + ('CLANG_VENDOR', 'SwiftWasm'), + ('CLANG_VENDOR_UTI', 'org.swiftwasm.compilers.llvm.clang'), + ('PACKAGE_VERSION', str(self.args.clang_user_visible_version)) + ] + if self.args.compiler_vendor != "apple": raise RuntimeError("Unknown compiler vendor?!") diff --git a/utils/swift_build_support/swift_build_support/products/swift.py b/utils/swift_build_support/swift_build_support/products/swift.py index de6843b06a1f6..2e8d1caf41f90 100644 --- a/utils/swift_build_support/swift_build_support/products/swift.py +++ b/utils/swift_build_support/swift_build_support/products/swift.py @@ -104,14 +104,22 @@ def _compiler_vendor_flags(self): if self.args.compiler_vendor == "none": return [] - if self.args.compiler_vendor != "apple": - raise RuntimeError("Unknown compiler vendor?! Was build-script \ -updated without updating swift.py?") - swift_compiler_version = "" if self.args.swift_compiler_version is not None: swift_compiler_version = self.args.swift_compiler_version + if self.args.compiler_vendor == "swiftwasm": + return [ + ('SWIFT_VENDOR', 'SwiftWasm'), + ('SWIFT_VENDOR_UTI', 'org.swiftwasm.compilers.llvm.swift'), + ('SWIFT_VERSION', str(self.args.swift_user_visible_version)), + ('SWIFT_COMPILER_VERSION', str(swift_compiler_version)), + ] + + if self.args.compiler_vendor != "apple": + raise RuntimeError("Unknown compiler vendor?! Was build-script \ +updated without updating swift.py?") + return [ ('SWIFT_VENDOR', 'Apple'), ('SWIFT_VENDOR_UTI', 'com.apple.compilers.llvm.swift'), diff --git a/utils/update_checkout/update-checkout-config.json b/utils/update_checkout/update-checkout-config.json index 9e8df6cf6abbb..1fbece833617e 100644 --- a/utils/update_checkout/update-checkout-config.json +++ b/utils/update_checkout/update-checkout-config.json @@ -3,7 +3,7 @@ "https-clone-pattern": "https://github.com/%s.git", "repos" : { "swift": { - "remote": { "id": "apple/swift" } }, + "remote": { "id": "swiftwasm/swift" } }, "cmark": { "remote": { "id": "apple/swift-cmark" } }, "llbuild": { @@ -35,9 +35,9 @@ "swift-stress-tester": { "remote": { "id": "apple/swift-stress-tester" } }, "swift-corelibs-xctest": { - "remote": { "id": "apple/swift-corelibs-xctest" } }, + "remote": { "id": "swiftwasm/swift-corelibs-xctest" } }, "swift-corelibs-foundation": { - "remote": { "id": "apple/swift-corelibs-foundation" } }, + "remote": { "id": "swiftwasm/swift-corelibs-foundation" } }, "swift-corelibs-libdispatch": { "remote": { "id": "apple/swift-corelibs-libdispatch" } }, "swift-integration-tests": { @@ -47,8 +47,7 @@ "ninja": { "remote": { "id": "ninja-build/ninja" } }, "icu": { - "remote": { "id": "unicode-org/icu" }, - "platforms": [ "Linux" ] + "remote": { "id": "unicode-org/icu" } }, "yams": { "remote": { "id": "jpsim/Yams" } @@ -88,8 +87,53 @@ "llvm-project": { "remote": { "id": "apple/llvm-project" } } }, - "default-branch-scheme": "main", + "default-branch-scheme": "wasm", "branch-schemes": { + "wasm": { + "aliases": ["wasm", "swiftwasm"], + "repos": { + "llvm-project": "stable/20221013", + "swift-llvm-bindings": "stable/20221013", + "swift": "swiftwasm", + "cmark": "gfm", + "llbuild": "main", + "swift-tools-support-core": "main", + "swiftpm": "main", + "swift-argument-parser": "1.2.2", + "swift-atomics": "1.0.2", + "swift-collections": "1.0.1", + "swift-crypto": "2.5.0", + "swift-certificates": "0.6.0", + "swift-asn1": "0.8.0", + "swift-driver": "main", + "swift-numerics": "1.0.1", + "swift-syntax": "main", + "swift-system": "1.1.1", + "swift-stress-tester": "main", + "swift-corelibs-xctest": "swiftwasm", + "swift-corelibs-foundation": "swiftwasm", + "swift-corelibs-libdispatch": "main", + "swift-integration-tests": "main", + "swift-xcode-playground-support": "main", + "ninja": "release", + "icu": "release-65-1", + "yams": "5.0.1", + "cmake": "v3.19.6", + "indexstore-db": "main", + "sourcekit-lsp": "main", + "swift-format": "main", + "swift-installer-scripts": "main", + "swift-docc": "main", + "swift-lmdb": "main", + "swift-docc-render-artifact": "main", + "swift-docc-symbolkit": "main", + "swift-markdown": "main", + "swift-cmark-gfm": "gfm", + "swift-nio": "2.31.2", + "swift-nio-ssl": "2.15.0", + "swift-experimental-string-processing": "swift/main" + } + }, "main": { "aliases": ["swift/main", "main", "stable/20221013"], "repos": { diff --git a/utils/webassembly/build-foundation.sh b/utils/webassembly/build-foundation.sh new file mode 100755 index 0000000000000..d30c045a5fb87 --- /dev/null +++ b/utils/webassembly/build-foundation.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -ex +DESTINATION_TOOLCHAIN=$1 +WASI_SYSROOT_PATH=$2 +SOURCE_PATH="$(cd "$(dirname $0)/../../.." && pwd)" +BUILD_SDK_PATH="$SOURCE_PATH/build-sdk" +LIBXML2_PATH="$BUILD_SDK_PATH/libxml2" + +FOUNDATION_BUILD="$SOURCE_PATH/target-build/foundation-wasi-wasm32" + +mkdir -p $FOUNDATION_BUILD +cd $FOUNDATION_BUILD + +cmake -G Ninja \ + -DCMAKE_BUILD_TYPE="Release" \ + -DCMAKE_SYSROOT="$WASI_SYSROOT_PATH" \ + -DCMAKE_Swift_COMPILER="$DESTINATION_TOOLCHAIN/usr/bin/swiftc" \ + -DCMAKE_STAGING_PREFIX="$DESTINATION_TOOLCHAIN/usr" \ + -DCMAKE_TOOLCHAIN_FILE="$SOURCE_PATH/swift/utils/webassembly/toolchain-wasi.cmake" \ + -DLLVM_BIN="$DESTINATION_TOOLCHAIN/usr/bin" \ + -DICU_ROOT="$BUILD_SDK_PATH/icu" \ + -DLIBXML2_INCLUDE_DIR="$LIBXML2_PATH/include/libxml2" \ + -DLIBXML2_LIBRARY="$LIBXML2_PATH/lib" \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_NETWORKING=OFF \ + -DBUILD_TOOLS=OFF \ + -DHAS_LIBDISPATCH_API=OFF \ + -DCMAKE_Swift_COMPILER_FORCED=ON \ + -DCMAKE_Swift_FLAGS="-sdk $WASI_SYSROOT_PATH" \ + "${SOURCE_PATH}/swift-corelibs-foundation" + +ninja +ninja install diff --git a/utils/webassembly/build-presets.ini b/utils/webassembly/build-presets.ini new file mode 100644 index 0000000000000..d82aabeb0631f --- /dev/null +++ b/utils/webassembly/build-presets.ini @@ -0,0 +1,69 @@ +#===----------------------------------------------------------------------===# +# Preset for the WebAssembly toolchain and SDK +#===----------------------------------------------------------------------===# + +[preset: webassembly] +skip-build-benchmarks +llvm-targets-to-build=X86;AArch64;WebAssembly +swift-darwin-supported-archs=%(HOST_ARCHITECTURE)s +compiler-vendor=swiftwasm +enable-experimental-concurrency=1 +enable-experimental-differentiable-programming=1 +enable-experimental-distributed=1 + +[preset: webassembly-install] + +release +assertions +install-swift +install-destdir=%(INSTALL_DESTDIR)s +swift-install-components=autolink-driver;compiler;clang-resource-dir-symlink;stdlib;sdk-overlay;editor-integration;tools;testsuite-tools;toolchain-tools;license;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers +llvm-install-components=llvm-cov;llvm-profdata;IndexStore;clang;clang-resource-headers;compiler-rt;clangd;dsymutil;lld;llvm-ar;llvm-ranlib +install-prefix=/usr + + +[preset: webassembly-host] + +mixin-preset=webassembly +sccache +extra-cmake-options= + -DSWIFT_BUILD_SOURCEKIT=FALSE + -DSWIFT_ENABLE_SOURCEKIT_TESTS=FALSE + -DSWIFT_BUILD_SYNTAXPARSERLIB=FALSE + +[preset: webassembly-host-install] +mixin-preset= + webassembly-host + webassembly-install + +llbuild +swiftpm +indexstore-db +sourcekit-lsp +build-lld + +install-llvm +install-swift +install-llbuild +install-swiftpm +install-sourcekit-lsp +install-swiftsyntax + +[preset: webassembly-linux-host-install] + +mixin-preset=webassembly-host-install + +libdispatch +libicu +foundation +xctest + +install-libicu +install-foundation +install-libdispatch +install-xctest + +skip-test-libicu +skip-test-foundation +skip-test-libdispatch +skip-test-xctest diff --git a/utils/webassembly/build-toolchain.sh b/utils/webassembly/build-toolchain.sh new file mode 100755 index 0000000000000..e1afe969ea863 --- /dev/null +++ b/utils/webassembly/build-toolchain.sh @@ -0,0 +1,269 @@ +#!/bin/bash + +set -ex +SOURCE_PATH="$(cd "$(dirname "$0")/../../.." && pwd)" +UTILS_PATH="$(cd "$(dirname "$0")" && pwd)" + +BUILD_SDK_PATH="$SOURCE_PATH/build-sdk" +WASI_SYSROOT_PATH="$BUILD_SDK_PATH/wasi-sysroot" + +case $(uname -s) in + Darwin) + OS_SUFFIX=macos_$(uname -m) + HOST_PRESET=webassembly-host-install + HOST_SUFFIX=macosx-$(uname -m) + ;; + Linux) + if [ "$(grep RELEASE /etc/lsb-release)" == "DISTRIB_RELEASE=18.04" ]; then + OS_SUFFIX=ubuntu18.04_$(uname -m) + elif [ "$(grep RELEASE /etc/lsb-release)" == "DISTRIB_RELEASE=20.04" ]; then + OS_SUFFIX=ubuntu20.04_$(uname -m) + elif [ "$(grep RELEASE /etc/lsb-release)" == "DISTRIB_RELEASE=22.04" ]; then + OS_SUFFIX=ubuntu22.04_$(uname -m) + elif [[ "$(grep PRETTY_NAME /etc/os-release)" == 'PRETTY_NAME="Amazon Linux 2"' ]]; then + OS_SUFFIX=amazonlinux2_$(uname -m) + else + echo "Unknown Ubuntu version" + exit 1 + fi + HOST_PRESET=webassembly-linux-host-install + HOST_SUFFIX=linux-$(uname -m) + ;; + *) + echo "Unrecognised platform $(uname -s)" + exit 1 + ;; +esac + +OPTIONS_BUILD_HOST_TOOLCHAIN=1 +OPTIONS_DAILY_SNAPSHOT=0 +TOOLCHAIN_CHANNEL=${TOOLCHAIN_CHANNEL:-DEVELOPMENT} + +while [ $# -ne 0 ]; do + case "$1" in + --skip-build-host-toolchain) + OPTIONS_BUILD_HOST_TOOLCHAIN=0 + ;; + --daily-snapshot) + OPTIONS_DAILY_SNAPSHOT=1 + ;; + *) + echo "Unrecognised argument \"$1\"" + exit 1 + ;; + esac + shift +done + +YEAR=$(date +"%Y") +MONTH=$(date +"%m") +DAY=$(date +"%d") + +if [ ${OPTIONS_DAILY_SNAPSHOT} -eq 1 ]; then + TOOLCHAIN_NAME="swift-wasm-${TOOLCHAIN_CHANNEL}-SNAPSHOT-${YEAR}-${MONTH}-${DAY}-a" +else + TOOLCHAIN_NAME="swift-wasm-${TOOLCHAIN_CHANNEL}-SNAPSHOT" +fi + +PACKAGE_ARTIFACT="$SOURCE_PATH/swift-wasm-${TOOLCHAIN_CHANNEL}-SNAPSHOT-${OS_SUFFIX}.tar.gz" + +HOST_TOOLCHAIN_DESTDIR=$SOURCE_PATH/host-toolchain-sdk +DIST_TOOLCHAIN_DESTDIR=$SOURCE_PATH/dist-toolchain-sdk +DIST_TOOLCHAIN_SDK=$DIST_TOOLCHAIN_DESTDIR/$TOOLCHAIN_NAME + + +HOST_BUILD_ROOT=$SOURCE_PATH/host-build +TARGET_BUILD_ROOT=$SOURCE_PATH/target-build +HOST_BUILD_DIR=$HOST_BUILD_ROOT/Ninja-ReleaseAssert + +build_host_toolchain() { + # Build the host toolchain and SDK first. + env SWIFT_BUILD_ROOT="$HOST_BUILD_ROOT" \ + "$SOURCE_PATH/swift/utils/build-script" \ + --preset-file="$UTILS_PATH/build-presets.ini" \ + --preset=$HOST_PRESET \ + --build-dir="$HOST_BUILD_DIR" \ + HOST_ARCHITECTURE="$(uname -m)" \ + INSTALL_DESTDIR="$HOST_TOOLCHAIN_DESTDIR" +} + +build_target_toolchain() { + + local COMPILER_RT_BUILD_DIR="$TARGET_BUILD_ROOT/compiler-rt-wasi-wasm32" + cmake -B "$COMPILER_RT_BUILD_DIR" \ + -D CMAKE_TOOLCHAIN_FILE="$SOURCE_PATH/swift/utils/webassembly/compiler-rt-cache.cmake" \ + -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_C_COMPILER="$HOST_BUILD_DIR/llvm-$HOST_SUFFIX/bin/clang" \ + -D CMAKE_CXX_COMPILER="$HOST_BUILD_DIR/llvm-$HOST_SUFFIX/bin/clang++" \ + -D CMAKE_RANLIB="$HOST_BUILD_DIR/llvm-$HOST_SUFFIX/bin/llvm-ranlib" \ + -D CMAKE_AR="$HOST_BUILD_DIR/llvm-$HOST_SUFFIX/bin/llvm-ar" \ + -D CMAKE_C_COMPILER_LAUNCHER="$(which sccache)" \ + -D CMAKE_CXX_COMPILER_LAUNCHER="$(which sccache)" \ + -D CMAKE_INSTALL_PREFIX="$DIST_TOOLCHAIN_SDK/usr/lib/clang/13.0.0/" \ + -D CMAKE_SYSROOT="${WASI_SYSROOT_PATH}" \ + -G Ninja \ + -S "$SOURCE_PATH/llvm-project/compiler-rt" + + ninja install -C "$COMPILER_RT_BUILD_DIR" + + # Only configure LLVM to use CMake functionalities in LLVM + local LLVM_TARGET_BUILD_DIR="$TARGET_BUILD_ROOT/llvm-wasi-wasm32" + cmake -B "$LLVM_TARGET_BUILD_DIR" \ + -D CMAKE_BUILD_TYPE=Release \ + -D LLVM_ENABLE_ZLIB=NO \ + -D LLVM_ENABLE_LIBXML2=NO \ + -G Ninja \ + -S "$SOURCE_PATH/llvm-project/llvm" + + local SWIFT_STDLIB_BUILD_DIR="$TARGET_BUILD_ROOT/swift-stdlib-wasi-wasm32" + + # FIXME(katei): Platform/WASI is not recognized as a platform in LLVM, so it reports + # "Unable to determine platform" while handling LLVM options. + # Set WASI as a UNIX platform to spoof LLVM + # FIXME(katei): host-build clang's libcxx is capable with LLVM, but it somehow + # fails libcxx version check. So activate LLVM_COMPILER_CHECKED to spoof the checker + # SWIFT_DRIVER_TEST_OPTIONS is used to specify clang resource dir for wasm32-unknown-wasi + # because it's not built beside clang + cmake -B "$SWIFT_STDLIB_BUILD_DIR" \ + -C "$SOURCE_PATH/swift/cmake/caches/Runtime-WASI-wasm32.cmake" \ + -D CMAKE_TOOLCHAIN_FILE="$SOURCE_PATH/swift/utils/webassembly/toolchain-wasi.cmake" \ + -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_C_COMPILER_LAUNCHER="$(which sccache)" \ + -D CMAKE_CXX_COMPILER_LAUNCHER="$(which sccache)" \ + -D CMAKE_INSTALL_PREFIX="$DIST_TOOLCHAIN_SDK/usr" \ + -D LLVM_BIN="$HOST_BUILD_DIR/llvm-$HOST_SUFFIX/bin" \ + -D LLVM_DIR="$LLVM_TARGET_BUILD_DIR/lib/cmake/llvm/" \ + -D LLVM_COMPILER_CHECKED=YES \ + -D UNIX=1 \ + -D SWIFT_NATIVE_SWIFT_TOOLS_PATH="$HOST_BUILD_DIR/swift-$HOST_SUFFIX/bin" \ + -D SWIFT_NATIVE_CLANG_TOOLS_PATH="$HOST_BUILD_DIR/llvm-$HOST_SUFFIX/bin" \ + -D SWIFT_NATIVE_LLVM_TOOLS_PATH="$HOST_BUILD_DIR/llvm-$HOST_SUFFIX/bin" \ + -D SWIFT_LIT_TEST_PATHS="$SWIFT_STDLIB_BUILD_DIR/test-wasi-wasm32/stdlib;$SWIFT_STDLIB_BUILD_DIR/test-wasi-wasm32/Concurrency/Runtime" \ + -D SWIFT_DRIVER_TEST_OPTIONS=" -Xclang-linker -resource-dir -Xclang-linker $COMPILER_RT_BUILD_DIR" \ + -D SWIFT_WASI_SYSROOT_PATH="$WASI_SYSROOT_PATH" \ + -D SWIFT_WASI_wasm32_ICU_UC_INCLUDE="$BUILD_SDK_PATH/icu/include" \ + -D SWIFT_WASI_wasm32_ICU_UC="$BUILD_SDK_PATH/icu/lib/libicuuc.a" \ + -D SWIFT_WASI_wasm32_ICU_I18N_INCLUDE="$BUILD_SDK_PATH/icu/include" \ + -D SWIFT_WASI_wasm32_ICU_I18N="$BUILD_SDK_PATH/icu/lib/libicui18n.a" \ + -D SWIFT_WASI_wasm32_ICU_DATA="$BUILD_SDK_PATH/icu/lib/libicudata.a" \ + -D SWIFT_ENABLE_EXPERIMENTAL_DIFFERENTIABLE_PROGRAMMING=YES \ + -D SWIFT_ENABLE_EXPERIMENTAL_DISTRIBUTED=YES \ + -D SWIFT_ENABLE_EXPERIMENTAL_STRING_PROCESSING=YES \ + -D SWIFT_ENABLE_EXPERIMENTAL_REFLECTION=YES \ + -D SWIFT_PATH_TO_SWIFT_SYNTAX_SOURCE="$SOURCE_PATH/swift-syntax" \ + -D SWIFT_PATH_TO_STRING_PROCESSING_SOURCE="$SOURCE_PATH/swift-experimental-string-processing" \ + -G Ninja \ + -S "$SOURCE_PATH/swift" + + # FIXME(katei): 'sdk-overlay' is explicitly used to build libcxxshim.modulemap + # which is used only in tests, so 'ninja install' doesn't build it + # the header and modulemap custom targets should be added as dependency of install + ninja sdk-overlay install -C "$SWIFT_STDLIB_BUILD_DIR" + + # Link compiler-rt libs to stdlib build dir + mkdir -p "$SWIFT_STDLIB_BUILD_DIR/lib/clang/10.0.0/" + ln -fs "$COMPILER_RT_BUILD_DIR/lib" "$SWIFT_STDLIB_BUILD_DIR/lib/clang/10.0.0/lib" + + # Remove host CoreFoundation module directory to avoid module conflict + # while building Foundation + rm -rf "$DIST_TOOLCHAIN_SDK/usr/lib/swift_static/CoreFoundation" + "$UTILS_PATH/build-foundation.sh" "$DIST_TOOLCHAIN_SDK" "$WASI_SYSROOT_PATH" + "$UTILS_PATH/build-xctest.sh" "$DIST_TOOLCHAIN_SDK" "$WASI_SYSROOT_PATH" + +} + +embed_wasi_sysroot() { + # Merge wasi-sdk and the toolchain + cp -r "$WASI_SYSROOT_PATH" "$DIST_TOOLCHAIN_SDK/usr/share" +} + +swift_version() { + cat "$SOURCE_PATH/swift/CMakeLists.txt" | grep 'set(SWIFT_VERSION ' | sed -E 's/set\(SWIFT_VERSION "(.+)"\)/\1/' +} + +create_darwin_info_plist() { + echo "-- Create Info.plist --" + PLISTBUDDY_BIN="/usr/libexec/PlistBuddy" + + BUNDLE_PREFIX="org.swiftwasm" + DARWIN_TOOLCHAIN_DISPLAY_NAME_SHORT="Swift for WebAssembly Snapshot" + + if [ ${OPTIONS_DAILY_SNAPSHOT} -eq 1 ]; then + DARWIN_TOOLCHAIN_VERSION="$(swift_version).${YEAR}${MONTH}${DAY}" + DARWIN_TOOLCHAIN_BUNDLE_IDENTIFIER="${BUNDLE_PREFIX}.${YEAR}${MONTH}${DAY}" + DARWIN_TOOLCHAIN_DISPLAY_NAME="${DARWIN_TOOLCHAIN_DISPLAY_NAME_SHORT} ${YEAR}-${MONTH}-${DAY}" + else + DARWIN_TOOLCHAIN_VERSION="$(swift_version).9999" + DARWIN_TOOLCHAIN_BUNDLE_IDENTIFIER="${BUNDLE_PREFIX}.dev" + DARWIN_TOOLCHAIN_DISPLAY_NAME="${DARWIN_TOOLCHAIN_DISPLAY_NAME_SHORT} Development" + fi + DARWIN_TOOLCHAIN_ALIAS="swiftwasm" + + DARWIN_TOOLCHAIN_INFO_PLIST="${DIST_TOOLCHAIN_SDK}/Info.plist" + DARWIN_TOOLCHAIN_REPORT_URL="https://github.com/swiftwasm/swift/issues" + COMPATIBILITY_VERSION=2 + COMPATIBILITY_VERSION_DISPLAY_STRING="Xcode 8.0" + DARWIN_TOOLCHAIN_CREATED_DATE="$(date -u +'%a %b %d %T GMT %Y')" + SWIFT_USE_DEVELOPMENT_TOOLCHAIN_RUNTIME="YES" + + rm -f "${DARWIN_TOOLCHAIN_INFO_PLIST}" + + ${PLISTBUDDY_BIN} -c "Add DisplayName string '${DARWIN_TOOLCHAIN_DISPLAY_NAME}'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add ShortDisplayName string '${DARWIN_TOOLCHAIN_DISPLAY_NAME_SHORT}'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add CreatedDate date '${DARWIN_TOOLCHAIN_CREATED_DATE}'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add CompatibilityVersion integer ${COMPATIBILITY_VERSION}" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add CompatibilityVersionDisplayString string ${COMPATIBILITY_VERSION_DISPLAY_STRING}" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add Version string '${DARWIN_TOOLCHAIN_VERSION}'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add CFBundleIdentifier string '${DARWIN_TOOLCHAIN_BUNDLE_IDENTIFIER}'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add ReportProblemURL string '${DARWIN_TOOLCHAIN_REPORT_URL}'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add Aliases array" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add Aliases:0 string '${DARWIN_TOOLCHAIN_ALIAS}'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add OverrideBuildSettings dict" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add OverrideBuildSettings:ENABLE_BITCODE string 'NO'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add OverrideBuildSettings:SWIFT_DISABLE_REQUIRED_ARCLITE string 'YES'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add OverrideBuildSettings:SWIFT_LINK_OBJC_RUNTIME string 'YES'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add OverrideBuildSettings:SWIFT_DEVELOPMENT_TOOLCHAIN string 'YES'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + ${PLISTBUDDY_BIN} -c "Add OverrideBuildSettings:SWIFT_USE_DEVELOPMENT_TOOLCHAIN_RUNTIME string '${SWIFT_USE_DEVELOPMENT_TOOLCHAIN_RUNTIME}'" "${DARWIN_TOOLCHAIN_INFO_PLIST}" + + chmod a+r "${DARWIN_TOOLCHAIN_INFO_PLIST}" +} + +show_sccache_stats() { + # If sccache is installed in PATH + if command -v sccache &> /dev/null; then + sccache --show-stats + else + echo "sccache is not installed in PATH" + fi +} + +if [ ${OPTIONS_BUILD_HOST_TOOLCHAIN} -eq 1 ]; then + build_host_toolchain + echo "==================================" + echo "Host toolchain built successfully!" + echo "==================================" + echo "" + echo "sccache stats:" + show_sccache_stats + rm -rf "$DIST_TOOLCHAIN_DESTDIR" + mkdir -p "$DIST_TOOLCHAIN_SDK" + rsync -a "$HOST_TOOLCHAIN_DESTDIR/" "$DIST_TOOLCHAIN_SDK" +fi + +build_target_toolchain +echo "====================================" +echo "Target toolchain built successfully!" +echo "====================================" +echo "" +echo "sccache stats:" +show_sccache_stats + +embed_wasi_sysroot + +if [[ "$(uname)" == "Darwin" ]]; then + create_darwin_info_plist +fi + +cd "$DIST_TOOLCHAIN_DESTDIR" +tar cfz "$PACKAGE_ARTIFACT" "$TOOLCHAIN_NAME" +echo "Toolchain archive created successfully!" diff --git a/utils/webassembly/build-xctest.sh b/utils/webassembly/build-xctest.sh new file mode 100755 index 0000000000000..7ce858285b30e --- /dev/null +++ b/utils/webassembly/build-xctest.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -ex +DESTINATION_TOOLCHAIN=$1 +WASI_SYSROOT_PATH=$2 +SOURCE_PATH="$(cd "$(dirname $0)/../../.." && pwd)" + +BUILD_DIR="$SOURCE_PATH/target-build/xctest-wasi-wasm32" + +mkdir -p $BUILD_DIR +cd $BUILD_DIR + +cmake -G Ninja \ + -DCMAKE_BUILD_TYPE="Release" \ + -DCMAKE_SYSROOT="$WASI_SYSROOT_PATH" \ + -DCMAKE_Swift_COMPILER="$DESTINATION_TOOLCHAIN/usr/bin/swiftc" \ + -DCMAKE_TOOLCHAIN_FILE="$SOURCE_PATH/swift/utils/webassembly/toolchain-wasi.cmake" \ + -DLLVM_BIN="$DESTINATION_TOOLCHAIN/usr/bin" \ + -DBUILD_SHARED_LIBS=OFF \ + -DCMAKE_Swift_COMPILER_FORCED=ON \ + -DSWIFT_FOUNDATION_PATH=$DESTINATION_TOOLCHAIN/usr/lib/swift_static/wasi/wasm32 \ + "${SOURCE_PATH}/swift-corelibs-xctest" + +ninja -v +DESTDIR="$DESTINATION_TOOLCHAIN/usr/lib" ninja -v install diff --git a/utils/webassembly/ci.sh b/utils/webassembly/ci.sh new file mode 100755 index 0000000000000..0aea922aeeaec --- /dev/null +++ b/utils/webassembly/ci.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -ex + +SOURCE_PATH="$(cd "$(dirname $0)/../../.." && pwd)" +SWIFT_PATH=$SOURCE_PATH/swift +UTILS_PATH=$SWIFT_PATH/utils/webassembly + +$SWIFT_PATH/utils/update-checkout --clone --scheme wasm --skip-repository swift +$UTILS_PATH/install-build-sdk.sh + +export SCCACHE_CACHE_SIZE="50G" +export SCCACHE_DIR="$SOURCE_PATH/build-cache" + +$UTILS_PATH/build-toolchain.sh --daily-snapshot diff --git a/utils/webassembly/compiler-rt-cache.cmake b/utils/webassembly/compiler-rt-cache.cmake new file mode 100644 index 0000000000000..6e11b01d09aba --- /dev/null +++ b/utils/webassembly/compiler-rt-cache.cmake @@ -0,0 +1,13 @@ +set(COMPILER_RT_DEFAULT_TARGET_ARCH wasm32 CACHE STRING "" FORCE) +set(COMPILER_RT_DEFAULT_TARGET_ONLY TRUE CACHE BOOL "" FORCE) +set(CMAKE_C_COMPILER_TARGET wasm32-wasi CACHE STRING "" FORCE) +set(CMAKE_C_COMPILER_FORCED TRUE CACHE BOOL "") +set(CMAKE_CXX_COMPILER_FORCED TRUE CACHE BOOL "") +set(CMAKE_SYSTEM_NAME Wasm) +set(CMAKE_SIZEOF_VOID_P 4 CACHE STRING "") +set(COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "") +set(COMPILER_RT_BUILD_XRAY OFF CACHE BOOL "") +set(COMPILER_RT_INCLUDE_TESTS OFF CACHE BOOL "") +set(COMPILER_RT_HAS_FPIC_FLAG OFF CACHE BOOL "") +set(COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN OFF CACHE BOOL "") +set(COMPILER_RT_OS_DIR wasi CACHE STRING "") diff --git a/utils/webassembly/distribute-latest-toolchain.sh b/utils/webassembly/distribute-latest-toolchain.sh new file mode 100755 index 0000000000000..233f281141dc7 --- /dev/null +++ b/utils/webassembly/distribute-latest-toolchain.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +set -xe +repository='swiftwasm/swift' +workflow_name='build-toolchain.yml' +branch=$1 +channel=$2 +swift_source_dir="$(cd "$(dirname $0)/../.." && pwd)" + +TARGETS_TO_DIST=${TARGETS_TO_DIST:?"Please set TARGETS_TO_DIST"} +targets=($TARGETS_TO_DIST) +DARWIN_TOOLCHAIN_APPLICATION_CERT=${DARWIN_TOOLCHAIN_APPLICATION_CERT:?"Please set DARWIN_TOOLCHAIN_APPLICATION_CERT"} +DARWIN_TOOLCHAIN_INSTALLER_CERT=${DARWIN_TOOLCHAIN_INSTALLER_CERT:?"Please set DARWIN_TOOLCHAIN_APPLICATION_CERT"} +DARWIN_TOOLCHAIN_NOTARIZE_EMAIL=${DARWIN_TOOLCHAIN_NOTARIZE_EMAIL:?"Please set DARWIN_TOOLCHAIN_NOTARIZE_EMAIL"} +DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID=${DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID:?"Please set DARWIN_TOOLCHAIN_NOTARIZE_TEAM_ID"} + +gh_api=https://api.github.com + +github() { + curl --header "authorization: Bearer $GITHUB_TOKEN" "$@" +} + +# workaround: if status=success option is given, the API doesn't return the latest runs list, so remove it temporarily. +latest_run=$(github "${gh_api}/repos/${repository}/actions/workflows/${workflow_name}/runs?branch=${branch}" \ + | jq ".workflow_runs | map(select(.head_branch == \"$branch\")) | map(select(.conclusion == \"success\")) | sort_by(.run_number) | last") + +if [ -z "$latest_run" ] || [ "$latest_run" == "null" ]; then + echo "No successful runs available" + exit 0 +fi + +artifacts_url=$(echo $latest_run | jq .artifacts_url --raw-output) +head_sha=$(echo $latest_run | jq .head_sha --raw-output) + +get_artifact_url() { + local name=$1 + github $artifacts_url --fail | jq ".artifacts[] | select((.name == \"$name\") and (.expired | not)) | .archive_download_url" | sed 's/\"//g' +} + +download_artifact() { + local name=$1 + local artifact_url="$(get_artifact_url $name)" + + if [ -z "$artifact_url" ] || [ "$artifact_url" == "null" ]; then + echo "No successfully built artifacts available for $name" + exit 0 + fi + + github -L "$artifact_url" --fail -o "$name.zip" +} + +is_released() { + local name=$1 + local code=$(github "$gh_api/repos/$repository/releases/tags/$name" -o /dev/null -w '%{http_code}') + test $code = 200 +} + +create_tag() { + local name=$1 + local sha=$2 + local body=$(cat < +Date: Thu Dec 29 10:50:33 2022 +0000 + + Without this patch, Cxx.swiftmodule build fails on macOS host environments + +diff --git a/include/c++/v1/module.modulemap b/include/c++/v1/module.modulemap +index b5781b0..af10440 100644 +--- a/include/c++/v1/module.modulemap ++++ b/include/c++/v1/module.modulemap +@@ -44,10 +44,12 @@ module std [system] { + header "math.h" + export * + } ++ /* XXX(swiftwasm): setjmp.h is unavailable in wasi-libc + module setjmp_h { + header "setjmp.h" + export * + } ++ */ + // FIXME: is missing. + // provided by C library. + // provided by compiler. +@@ -153,10 +155,12 @@ module std [system] { + header "cmath" + export * + } ++ /* XXX(swiftwasm): setjmp.h is unavailable in wasi-libc + module csetjmp { + header "csetjmp" + export * + } ++ */ + module csignal { + header "csignal" + export * +@@ -384,10 +388,12 @@ module std [system] { + header "execution" + export * + } ++ /* XXX(swiftwasm): wasi-sdk configures with LIBCXX_ENABLE_FILESYSTEM=OFF + module filesystem { + header "filesystem" + export * + } ++ */ + module format { + header "format" + export * +@@ -645,11 +651,13 @@ module std [system] { + header "scoped_allocator" + export * + } ++ /* XXX(swiftwasm): semaphore is unavailable due to lack of thread + module semaphore { + requires cplusplus14 + header "semaphore" + export * + } ++ */ + module set { + header "set" + export initializer_list +@@ -816,10 +824,12 @@ module std [system] { + header "experimental/deque" + export * + } ++ /* XXX(swiftwasm): wasi-sdk configures with LIBCXX_ENABLE_FILESYSTEM=OFF + module filesystem { + header "experimental/filesystem" + export * + } ++ */ + module forward_list { + header "experimental/forward_list" + export * diff --git a/utils/webassembly/static-executable-args.lnk b/utils/webassembly/static-executable-args.lnk new file mode 100644 index 0000000000000..a18d5fc3668aa --- /dev/null +++ b/utils/webassembly/static-executable-args.lnk @@ -0,0 +1,12 @@ +-static +-lswiftSwiftOnoneSupport +-lswiftWasiPthread +-ldl +-lstdc++ +-lm +-lwasi-emulated-mman +-lwasi-emulated-signal +-lwasi-emulated-process-clocks +-Xlinker --error-limit=0 +-Xlinker --no-gc-sections +-Xlinker --threads=1 diff --git a/utils/webassembly/sync-update-checkout-config.rb b/utils/webassembly/sync-update-checkout-config.rb new file mode 100755 index 0000000000000..60bc3f9fbd5f3 --- /dev/null +++ b/utils/webassembly/sync-update-checkout-config.rb @@ -0,0 +1,52 @@ +#!/usr/bin/env ruby + +require "json" + +DOWNSTREAM_FORKS = ["swift", "swift-corelibs-foundation", "swift-corelibs-xctest"] + +def sync_checkout(options) + config = JSON.parse(File.read(options[:config_path])) + branch_schemes = config["branch-schemes"] + upstream = branch_schemes[options[:upstream]] + raise "No branch scheme for #{options[:upstream]}" unless upstream + downstream = branch_schemes[options[:downstream]] + raise "No branch scheme for #{options[:downstream]}" unless downstream + + upstream["repos"].each do |project, upstream_branch| + next if DOWNSTREAM_FORKS.include?(project) + downstream_branch = downstream["repos"][project] + next if downstream_branch == upstream_branch + + puts "Please update #{project} to #{upstream_branch} (currently #{downstream_branch})" + end +end + +def main + require "optparse" + options = { + config_path: File.expand_path(File.join(__dir__, "..", "update_checkout", "update-checkout-config.json")), + upstream: "main", + downstream: "wasm", + } + + opts = OptionParser.new do |opts| + opts.banner = "Usage: sync-update-checkout.rb [options]" + + opts.on("--config PATH", "Path to update-checkout-config.json") do |path| + options[:config_path] = path + end + + opts.on("--upstream BRANCH", "Name of upstream branch") do |branch| + options[:upstream] = branch + end + + opts.on("--downstream BRANCH", "Name of downstream branch") do |branch| + options[:downstream] = branch + end + end + opts.parse! + + sync_checkout(options) +end + +main if $0 == __FILE__ diff --git a/utils/webassembly/toolchain-wasi.cmake b/utils/webassembly/toolchain-wasi.cmake new file mode 100644 index 0000000000000..aee54bab1791c --- /dev/null +++ b/utils/webassembly/toolchain-wasi.cmake @@ -0,0 +1,26 @@ +set(CMAKE_SYSTEM_NAME WASI) +set(CMAKE_SYSTEM_VERSION 1) +set(CMAKE_SYSTEM_PROCESSOR wasm32) +set(triple wasm32-unknown-wasi) + +set(CMAKE_C_COMPILER "${LLVM_BIN}/clang") +set(CMAKE_CXX_COMPILER "${LLVM_BIN}/clang++") +set(CMAKE_AR "${LLVM_BIN}/llvm-ar" CACHE STRING "LLVM Archiver for wasm32") +set(CMAKE_RANLIB "${LLVM_BIN}/llvm-ranlib" CACHE STRING "LLVM Ranlib for wasm32") +set(CMAKE_C_COMPILER_TARGET ${triple} CACHE STRING "") +set(CMAKE_CXX_COMPILER_TARGET ${triple} CACHE STRING "") +set(CMAKE_Swift_COMPILER_TARGET ${triple} CACHE STRING "") +set(CMAKE_ASM_COMPILER_TARGET ${triple} CACHE STRING "") + +set(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-threads" CACHE STRING "Single thread options") + +# Don't look in the sysroot for executables to run during the build +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# Only look in the sysroot (not in the host paths) for the rest +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) + +# Some other hacks +set(CMAKE_C_COMPILER_WORKS ON) +set(CMAKE_CXX_COMPILER_WORKS ON) diff --git a/utils/webassembly/wasm-run.py b/utils/webassembly/wasm-run.py new file mode 100755 index 0000000000000..ec4e429f3ad0d --- /dev/null +++ b/utils/webassembly/wasm-run.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +import argparse +import os +import subprocess +import sys + + +def collect_wasm_env(local_env=os.environ, prefix='WASM_RUN_CHILD_'): + return dict((key[len(prefix):], value) + for key, value in local_env.items() if key.startswith(prefix)) + + +class WasmerRunner(object): + def __init__(self): + pass + + def run(self, args): + command = self.invocation(args) + if args.verbose: + print(' '.join(command), file=sys.stderr) + + if not args.dry_run: + subprocess.check_call(command) + + def invocation(self, args): + command = ["wasmer", "run", "--singlepass"] + envs = collect_wasm_env() + for key in envs: + command.append("--env") + command.append(f"{key}={envs[key]}") + command.append("--") + command.extend(args.command) + return command + + +def main(): + parser = argparse.ArgumentParser() + + parser.add_argument('-v', '--verbose', action='store_true', dest='verbose', + help='print commands as they are run') + parser.add_argument('-n', '--dry-run', action='store_true', dest='dry_run', + help="print the commands that would have been run, but" + " don't actually run them") + parser.add_argument('command', nargs=argparse.REMAINDER, + help='the command to run', metavar='command...') + + args = parser.parse_args() + runner = WasmerRunner() + runner.run(args) + + +if __name__ == "__main__": + main()