├── .dockerignore ├── .github └── workflows │ ├── build.yml │ ├── docker.yml │ ├── msvcrt.yml │ ├── release.yml │ ├── store-version.sh │ ├── test-libcxx.yml │ ├── test-llvm.yml │ └── test-system-clang.yml ├── .gitignore ├── Dockerfile ├── Dockerfile.cross ├── Dockerfile.dev ├── Dockerfile.system-clang ├── Dockerfile.toolchain ├── LICENSE.txt ├── README.md ├── build-all.sh ├── build-compiler-rt.sh ├── build-cross-tools.sh ├── build-libcxx.sh ├── build-lldb-mi.sh ├── build-llvm.sh ├── build-make.sh ├── build-mingw-w64-libraries.sh ├── build-mingw-w64-tools.sh ├── build-mingw-w64.sh ├── build-openmp.sh ├── build-python.sh ├── copy-msys-dependencies.sh ├── extract-docker.sh ├── install-wrappers.sh ├── prepare-cross-toolchain-unix.sh ├── prepare-cross-toolchain.sh ├── release-macos.sh ├── release.sh ├── run-lldb-tests.sh ├── run-tests.sh ├── strip-llvm.sh ├── test-libcxx-module.sh ├── test ├── .gitignore ├── Makefile ├── atomic-helpers.c ├── autoimport-lib.c ├── autoimport-lib.h ├── autoimport-main.c ├── bufferoverflow.c ├── cfguard-test.c ├── crt-test.c ├── exception-locale.cpp ├── exception-reduced.cpp ├── global-terminate.cpp ├── hello-cpp.cpp ├── hello-exception.cpp ├── hello-omp.c ├── hello-res-rc.rc ├── hello-res.c ├── hello-res.h ├── hello-tls.c ├── hello.c ├── idltest.c ├── idltest.idl ├── longjmp-cleanup.cpp ├── setjmp.c ├── stacksmash.c ├── tchar.c ├── test-scan-deps.cpp ├── throwcatch-lib.cpp ├── throwcatch-lib.h ├── throwcatch-main.cpp ├── tlstest-lib.cpp ├── tlstest-main.cpp ├── ubsan.c └── uwp-error.c └── wrappers ├── aarch64-w64-windows-gnu.cfg ├── arm64ec-w64-windows-gnu.cfg ├── armv7-w64-windows-gnu.cfg ├── clang-scan-deps-wrapper.c ├── clang-target-wrapper.c ├── clang-target-wrapper.sh ├── i686-w64-windows-gnu.cfg ├── ld-wrapper.sh ├── llvm-wrapper.c ├── mingw32-common.cfg ├── native-wrapper.h ├── objdump-wrapper.sh └── x86_64-w64-windows-gnu.cfg /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | llvm-project 3 | mingw-w64 4 | lldb-mi 5 | make-* 6 | libffi 7 | cpython* 8 | python-native 9 | **/*.exe 10 | **/*.dll 11 | **/*.lib 12 | **/*.pdb 13 | **/*.a 14 | *.tar.xz 15 | *.zip 16 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: Build docker images 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | ref: 6 | description: 'Ref to extract from' 7 | type: string 8 | default: 'master' 9 | login: 10 | description: 'Log in to Docker Hub' 11 | type: boolean 12 | default: true 13 | push: 14 | description: 'Push the built images' 15 | type: boolean 16 | default: false 17 | 18 | jobs: 19 | prepare: 20 | runs-on: ubuntu-latest 21 | outputs: 22 | TAG: ${{steps.get-parameters.outputs.TAG}} 23 | steps: 24 | - name: Download build parameters 25 | uses: dawidd6/action-download-artifact@v10 26 | with: 27 | workflow: build.yml 28 | workflow_conclusion: success 29 | ref: ${{inputs.ref}} 30 | event: push 31 | name: parameters 32 | - name: Get build parameters 33 | id: get-parameters 34 | run: | 35 | cat parameters.txt >> $GITHUB_OUTPUT 36 | cat $GITHUB_OUTPUT 37 | 38 | docker-build-dev: 39 | needs: [prepare] 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@v4 43 | with: 44 | ref: ${{inputs.ref}} 45 | - name: Log in to Docker Hub 46 | if: ${{inputs.login}} 47 | uses: docker/login-action@v3 48 | with: 49 | username: ${{vars.DOCKER_USERNAME}} 50 | password: ${{secrets.DOCKER_PASSWORD}} 51 | - name: Build Docker images 52 | uses: docker/build-push-action@v5 53 | with: 54 | context: . 55 | push: ${{inputs.push}} 56 | file: ./Dockerfile.dev 57 | tags: | 58 | mstorsjo/llvm-mingw:dev 59 | mstorsjo/llvm-mingw:dev-${{needs.prepare.outputs.TAG}} 60 | - name: Inspect Docker images 61 | run: | 62 | docker images 63 | 64 | docker-build: 65 | needs: [prepare] 66 | runs-on: ubuntu-latest 67 | strategy: 68 | fail-fast: false 69 | matrix: 70 | include: 71 | - { file: Dockerfile, key: amd64 } 72 | - { file: Dockerfile.toolchain, platforms: linux/arm64, key: arm64 } 73 | steps: 74 | - uses: actions/checkout@v4 75 | with: 76 | ref: ${{inputs.ref}} 77 | - name: Download toolchain 78 | if: ${{matrix.file == 'Dockerfile.toolchain'}} 79 | uses: dawidd6/action-download-artifact@v10 80 | with: 81 | workflow: build.yml 82 | workflow_conclusion: success 83 | ref: ${{inputs.ref}} 84 | event: push 85 | name: linux-ucrt-.* 86 | name_is_regexp: true 87 | path: toolchain 88 | - name: Set up QEMU 89 | if: ${{matrix.file == 'Dockerfile.toolchain'}} 90 | uses: docker/setup-qemu-action@v3 91 | - name: Set up Docker Buildx 92 | uses: docker/setup-buildx-action@v3 93 | - name: Log in to Docker Hub 94 | if: ${{inputs.login}} 95 | uses: docker/login-action@v3 96 | with: 97 | username: ${{vars.DOCKER_USERNAME}} 98 | password: ${{secrets.DOCKER_PASSWORD}} 99 | - name: Build Docker images 100 | uses: docker/build-push-action@v5 101 | id: build 102 | with: 103 | context: . 104 | platforms: ${{matrix.platforms}} 105 | push: ${{inputs.push}} 106 | file: ./${{matrix.file}} 107 | outputs: | 108 | type=image,name=mstorsjo/llvm-mingw,push-by-digest=true,name-canonical=true 109 | - name: Write outputs for later steps 110 | uses: cloudposse/github-action-matrix-outputs-write@main 111 | id: out 112 | with: 113 | matrix-step-name: ${{github.job}} 114 | matrix-key: ${{matrix.key}} 115 | outputs: |- 116 | digest: ${{steps.build.outputs.digest}} 117 | 118 | docker-create: 119 | needs: [docker-build, prepare] 120 | runs-on: ubuntu-latest 121 | if: ${{inputs.push}} 122 | steps: 123 | - uses: cloudposse/github-action-matrix-outputs-read@main 124 | id: read 125 | with: 126 | matrix-step-name: docker-build 127 | - name: Set up Docker Buildx 128 | uses: docker/setup-buildx-action@v3 129 | - name: Log in to Docker Hub 130 | uses: docker/login-action@v3 131 | with: 132 | username: ${{vars.DOCKER_USERNAME}} 133 | password: ${{secrets.DOCKER_PASSWORD}} 134 | - name: Create final image 135 | run: | 136 | set -x 137 | for tag in latest ${{needs.prepare.outputs.TAG}}; do 138 | docker buildx imagetools create -t mstorsjo/llvm-mingw:$tag mstorsjo/llvm-mingw@${{fromJson(steps.read.outputs.result).digest.amd64}} mstorsjo/llvm-mingw@${{fromJson(steps.read.outputs.result).digest.arm64}} 139 | done 140 | -------------------------------------------------------------------------------- /.github/workflows/msvcrt.yml: -------------------------------------------------------------------------------- 1 | name: Build msvcrt toolchains 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | ref: 6 | description: 'Ref to extract from' 7 | type: string 8 | default: 'master' 9 | upload: 10 | description: 'Upload the artifacts' 11 | type: boolean 12 | default: false 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | prepare: 19 | runs-on: ubuntu-latest 20 | outputs: 21 | LLVM_VERSION: ${{steps.get-parameters.outputs.LLVM_VERSION}} 22 | MINGW_W64_VERSION: ${{steps.get-parameters.outputs.MINGW_W64_VERSION}} 23 | PYTHON_VERSION_MINGW: ${{steps.get-parameters.outputs.PYTHON_VERSION_MINGW}} 24 | TAG: ${{steps.get-parameters.outputs.TAG}} 25 | COMMIT_DATE_UNIX: ${{steps.get-parameters.outputs.COMMIT_DATE_UNIX}} 26 | BUILD_DATE: ${{steps.get-parameters.outputs.BUILD_DATE}} 27 | BUILD_DATE_UNIX: ${{steps.get-parameters.outputs.BUILD_DATE_UNIX}} 28 | steps: 29 | - name: Download build parameters 30 | uses: dawidd6/action-download-artifact@v10 31 | with: 32 | workflow: build.yml 33 | workflow_conclusion: success 34 | ref: ${{inputs.ref}} 35 | event: push 36 | name: parameters 37 | - name: Get build parameters 38 | id: get-parameters 39 | run: | 40 | cat parameters.txt >> $GITHUB_OUTPUT 41 | cat $GITHUB_OUTPUT 42 | 43 | # Build a new toolchain with a different CRT choice. 44 | linux-msvcrt: 45 | needs: [prepare] 46 | runs-on: ubuntu-22.04 47 | steps: 48 | - uses: actions/checkout@v4 49 | with: 50 | ref: ${{inputs.ref}} 51 | - name: Download toolchain 52 | uses: dawidd6/action-download-artifact@v10 53 | with: 54 | workflow: build.yml 55 | workflow_conclusion: success 56 | ref: ${{inputs.ref}} 57 | event: push 58 | name: linux-ucrt-x86_64-toolchain 59 | - name: Unpack original toolchain 60 | run: | 61 | tar -Jxf llvm-mingw-*.tar.xz 62 | rm llvm-mingw-*.tar.xz 63 | mkdir install 64 | mv llvm-mingw* install/llvm-mingw 65 | - name: Build 66 | env: 67 | LLVM_VERSION: ${{needs.prepare.outputs.LLVM_VERSION}} 68 | MINGW_W64_VERSION: ${{needs.prepare.outputs.MINGW_W64_VERSION}} 69 | TAG: ${{needs.prepare.outputs.TAG}} 70 | SOURCE_DATE_EPOCH: ${{needs.prepare.outputs.COMMIT_DATE_UNIX}} 71 | BUILD_DATE: ${{needs.prepare.outputs.BUILD_DATE}} 72 | run: | 73 | ./build-all.sh $(pwd)/install/llvm-mingw --no-tools --wipe-runtimes --with-default-msvcrt=msvcrt 74 | .github/workflows/store-version.sh install/llvm-mingw/versions.txt 75 | cd install 76 | DISTRO=ubuntu-$(grep DISTRIB_RELEASE /etc/lsb-release | cut -f 2 -d =)-$(uname -m) 77 | NAME=llvm-mingw-$TAG-msvcrt-$DISTRO 78 | mv llvm-mingw $NAME 79 | tar -Jcf ../$NAME.tar.xz --format=ustar --numeric-owner --owner=0 --group=0 --sort=name --mtime="$BUILD_DATE" $NAME 80 | - uses: actions/upload-artifact@v4 81 | with: 82 | name: linux-msvcrt-x86_64-toolchain 83 | path: | 84 | llvm-mingw-*.tar.xz 85 | retention-days: 7 86 | 87 | linux-cross-windows: 88 | needs: [linux-msvcrt, prepare] 89 | runs-on: ubuntu-latest 90 | strategy: 91 | fail-fast: false 92 | matrix: 93 | include: 94 | - { arch: i686, crt: msvcrt } 95 | - { arch: x86_64, crt: msvcrt } 96 | steps: 97 | - uses: actions/download-artifact@v4 98 | with: 99 | name: linux-${{matrix.crt}}-x86_64-toolchain 100 | - name: Unpack cross toolchain 101 | run: | 102 | tar -Jxf llvm-mingw-*.tar.xz 103 | rm llvm-mingw-*.tar.xz 104 | sudo mv llvm-mingw* /opt/llvm-mingw 105 | echo /opt/llvm-mingw/bin >> $GITHUB_PATH 106 | - uses: actions/checkout@v4 107 | with: 108 | ref: ${{inputs.ref}} 109 | - name: Build 110 | env: 111 | LLVM_VERSION: ${{needs.prepare.outputs.LLVM_VERSION}} 112 | MINGW_W64_VERSION: ${{needs.prepare.outputs.MINGW_W64_VERSION}} 113 | PYTHON_VERSION_MINGW: ${{needs.prepare.outputs.PYTHON_VERSION_MINGW}} 114 | TAG: ${{needs.prepare.outputs.TAG}} 115 | run: | 116 | sudo apt-get update && sudo apt-get install libltdl-dev swig autoconf-archive 117 | ./build-cross-tools.sh /opt/llvm-mingw $(pwd)/install/llvm-mingw ${{matrix.arch}} --with-python 118 | .github/workflows/store-version.sh install/llvm-mingw/versions.txt 119 | cd install 120 | NAME=llvm-mingw-$TAG-${{matrix.crt}}-${{matrix.arch}} 121 | mv llvm-mingw $NAME 122 | zip -9rq ../$NAME.zip $NAME 123 | - uses: actions/upload-artifact@v4 124 | with: 125 | name: windows-${{matrix.crt}}-${{matrix.arch}}-toolchain 126 | path: | 127 | llvm-mingw-*.zip 128 | retention-days: 7 129 | 130 | # Run llvm-mingw's tests on x86_64 and i686 with the cross-built corresponding 131 | # toolchains from above. 132 | test-toolchain: 133 | needs: [linux-cross-windows] 134 | runs-on: windows-latest 135 | defaults: 136 | run: 137 | shell: msys2 {0} 138 | strategy: 139 | fail-fast: false 140 | matrix: 141 | include: 142 | - { arch: i686, crt: msvcrt } 143 | - { arch: x86_64, crt: msvcrt } 144 | steps: 145 | - uses: msys2/setup-msys2@v2 146 | with: 147 | msystem: mingw64 148 | install: >- 149 | unzip 150 | make 151 | - uses: actions/download-artifact@v4 152 | with: 153 | name: windows-${{matrix.crt}}-${{matrix.arch}}-toolchain 154 | - name: Unpack toolchain 155 | run: | 156 | unzip -q llvm-mingw-*.zip 157 | rm llvm-mingw-*.zip 158 | mv llvm-mingw-* /llvm-mingw 159 | echo /llvm-mingw/bin >> $GITHUB_PATH 160 | - uses: actions/checkout@v4 161 | with: 162 | ref: ${{inputs.ref}} 163 | - name: Run tests 164 | run: | 165 | ./run-tests.sh /llvm-mingw 166 | ./run-lldb-tests.sh /llvm-mingw 167 | 168 | upload: 169 | if: ${{inputs.upload}} 170 | permissions: 171 | contents: write 172 | needs: [linux-msvcrt, linux-cross-windows, test-toolchain, prepare] 173 | runs-on: ubuntu-latest 174 | steps: 175 | - name: Download all artifacts 176 | uses: actions/download-artifact@v4 177 | - name: Rearrange files 178 | run: | 179 | rm -rf linux-asserts* 180 | mv *-toolchain/*.zip *-toolchain/*.tar.xz . 181 | - name: Upload binaries 182 | env: 183 | GITHUB_TOKEN: ${{github.token}} 184 | TAG: ${{needs.prepare.outputs.TAG}} 185 | run: | 186 | gh release upload $TAG *.tar.xz *.zip --clobber -R ${{github.repository}} 187 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Make a release, upload artifacts 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | ref: 6 | description: 'Ref to extract from' 7 | type: string 8 | default: 'master' 9 | tag: 10 | description: 'Tag to create/upload to' 11 | required: true 12 | type: string 13 | title: 14 | description: 'Release title' 15 | type: string 16 | make_tag: 17 | description: 'Make a tag' 18 | type: boolean 19 | default: true 20 | create_release: 21 | description: 'Create release' 22 | type: boolean 23 | default: true 24 | prerelease: 25 | description: 'Set as pre-release' 26 | type: boolean 27 | default: false 28 | 29 | permissions: 30 | contents: read 31 | 32 | jobs: 33 | upload-release: 34 | permissions: 35 | contents: write 36 | runs-on: ubuntu-latest 37 | steps: 38 | - name: Download artifacts 39 | uses: dawidd6/action-download-artifact@v10 40 | with: 41 | workflow: build.yml 42 | workflow_conclusion: success 43 | ref: ${{inputs.ref}} 44 | event: push 45 | - name: Rearrange files 46 | run: | 47 | rm -rf linux-asserts* 48 | rm -rf msys2* 49 | mv *-toolchain/*.zip *-toolchain/*.tar.xz . 50 | - name: Set environment 51 | run: | 52 | cat parameters/parameters.txt >> $GITHUB_ENV 53 | - uses: actions/checkout@v4 54 | with: 55 | ref: ${{inputs.ref}} 56 | path: repo 57 | - name: Make a tag 58 | if: ${{inputs.make_tag}} 59 | run: | 60 | if [ "$TAG" != "${{inputs.tag}}" ]; then 61 | echo Tag mismatch, \"$TAG\" in workflow vs \"${{inputs.tag}}\" as input 62 | exit 1 63 | fi 64 | cd repo 65 | git config --global user.name "GitHub Actions" 66 | git config --global user.email martin@martin.st 67 | git tag -a ${{inputs.tag}} -m "${{inputs.title}}" 68 | # If the commit isn't the tip of a branch, and there are 69 | # differences in workflow files compared with the tip of the 70 | # branch, GitHub rejects this push with "refusing to allow a 71 | # GitHub App to create or update workflow 72 | # `.github/workflows/build.yml` without `workflows` permission". 73 | # In such cases, manually create and push the tag and rerun with 74 | # make_tag set to false. 75 | git push origin ${{inputs.tag}} 76 | - name: Create release and upload binaries 77 | env: 78 | GITHUB_TOKEN: ${{github.token}} 79 | run: | 80 | if ${{inputs.prerelease}}; then 81 | prerelease="--prerelease" 82 | fi 83 | if ${{inputs.create_release}}; then 84 | gh release create ${{inputs.tag}} --verify-tag $prerelease --title "${{inputs.title}}" --notes "" *.tar.xz *.zip -R ${{github.repository}} 85 | else 86 | gh release upload ${{inputs.tag}} *.tar.xz *.zip --clobber -R ${{github.repository}} 87 | fi 88 | -------------------------------------------------------------------------------- /.github/workflows/store-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | OUT="$1" 4 | 5 | if [ -n "$LLVM_VERSION" ]; then 6 | echo "Nightly $(TZ=UTC date +%Y-%m-%d)" >> $OUT 7 | for i in LLVM_VERSION MINGW_W64_VERSION PYTHON_VERSION_MINGW; do 8 | eval val=\"\$$i\" 9 | if [ -n "$val" ]; then 10 | echo "$i=$val" >> $OUT 11 | fi 12 | done 13 | fi 14 | -------------------------------------------------------------------------------- /.github/workflows/test-libcxx.yml: -------------------------------------------------------------------------------- 1 | name: Run libcxx/libcxxabi/libunwind tests 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | ref: 6 | description: 'Ref to extract from' 7 | type: string 8 | default: 'master' 9 | pipeline_type: 10 | description: 'Pipeline type' 11 | required: true 12 | default: 'push' 13 | type: choice 14 | options: 15 | - push 16 | - schedule 17 | schedule: 18 | - cron: '30 13 * * 0' # 13:30 UTC on Sundays 19 | 20 | jobs: 21 | prepare: 22 | if: (github.event_name != 'schedule') || (github.repository == 'mstorsjo/llvm-mingw') 23 | runs-on: ubuntu-latest 24 | outputs: 25 | LLVM_VERSION: ${{steps.get-parameters.outputs.LLVM_VERSION}} 26 | steps: 27 | - name: Download build parameters 28 | uses: dawidd6/action-download-artifact@v10 29 | with: 30 | workflow: build.yml 31 | workflow_conclusion: success 32 | ref: ${{github.event_name == 'schedule' && 'master' || inputs.ref}} 33 | event: ${{github.event_name == 'schedule' && 'schedule' || inputs.pipeline_type}} 34 | name: parameters 35 | - name: Get build parameters 36 | id: get-parameters 37 | run: | 38 | cat parameters.txt >> $GITHUB_OUTPUT 39 | cat $GITHUB_OUTPUT 40 | 41 | test-libcxx: 42 | if: (github.event_name != 'schedule') || (github.repository == 'mstorsjo/llvm-mingw') 43 | needs: [prepare] 44 | strategy: 45 | fail-fast: false 46 | matrix: 47 | include: 48 | - { arch: x86_64, target_arch: i686 } 49 | - { arch: x86_64, target_arch: x86_64 } 50 | - { arch: aarch64, target_arch: armv7 } 51 | - { arch: aarch64, target_arch: aarch64 } 52 | runs-on: ${{startsWith(matrix.arch, 'a') && 'windows-11-arm' || 'windows-latest'}} 53 | steps: 54 | - name: Install dependencies 55 | run: | 56 | choco install ninja 57 | - name: Download toolchain 58 | uses: dawidd6/action-download-artifact@v10 59 | with: 60 | workflow: build.yml 61 | workflow_conclusion: success 62 | ref: ${{github.event_name == 'schedule' && 'master' || inputs.ref}} 63 | event: ${{github.event_name == 'schedule' && 'schedule' || inputs.pipeline_type}} 64 | name: windows-ucrt-${{matrix.arch}}-toolchain 65 | - name: Unpack toolchain 66 | run: | 67 | Expand-Archive llvm-mingw-*.zip -DestinationPath . 68 | del llvm-mingw-*.zip 69 | mv llvm-mingw-* c:\llvm-mingw 70 | echo "c:\llvm-mingw\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append 71 | echo "c:\llvm-mingw\python\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append 72 | echo "PYTHON_EXE=c:/llvm-mingw/python/bin/python3.exe" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append 73 | - uses: actions/checkout@v4 74 | - name: Checkout llvm-project 75 | env: 76 | LLVM_VERSION: ${{needs.prepare.outputs.LLVM_VERSION}} 77 | run: | 78 | bash -c "CHECKOUT_ONLY=1 ./build-llvm.sh" 79 | - name: Build and test libcxx 80 | run: | 81 | cd llvm-project 82 | mkdir build 83 | cd build 84 | cmake ../runtimes ` 85 | -G Ninja ` 86 | -DCMAKE_BUILD_TYPE=Release ` 87 | -DPython3_EXECUTABLE="$Env:PYTHON_EXE" ` 88 | -DLIBCXX_ENABLE_WERROR=YES ` 89 | -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" ` 90 | -DLIBCXX_CXX_ABI=libcxxabi ` 91 | -DCMAKE_C_COMPILER=${{matrix.target_arch}}-w64-mingw32-clang ` 92 | -DCMAKE_CXX_COMPILER=${{matrix.target_arch}}-w64-mingw32-clang++ ` 93 | -DCMAKE_CXX_COMPILER_TARGET=${{matrix.target_arch}}-w64-windows-gnu ` 94 | -DLIBCXXABI_ENABLE_SHARED=NO ` 95 | -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=YES ` 96 | -DLIBCXX_USE_COMPILER_RT=YES ` 97 | -DLIBCXXABI_USE_COMPILER_RT=YES ` 98 | -DLIBUNWIND_USE_COMPILER_RT=YES ` 99 | -DLIBCXXABI_USE_LLVM_UNWINDER=YES ` 100 | -DLIBCXX_EXTRA_SITE_DEFINES="__USE_MINGW_ANSI_STDIO=${{startsWith(matrix.arch, 'a') && '0' || '1'}}" ` 101 | -DCMAKE_INSTALL_MESSAGE=NEVER ` 102 | -DLLVM_LIT_ARGS="-v --time-tests" 103 | ninja 104 | ninja check-runtimes 105 | -------------------------------------------------------------------------------- /.github/workflows/test-llvm.yml: -------------------------------------------------------------------------------- 1 | name: Run LLVM tests 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | ref: 6 | description: 'Ref to extract from' 7 | type: string 8 | default: 'master' 9 | pipeline_type: 10 | description: 'Pipeline type' 11 | required: true 12 | default: 'push' 13 | type: choice 14 | options: 15 | - push 16 | - schedule 17 | schedule: 18 | - cron: '30 13 * * 0' # 13:30 UTC on Sundays 19 | 20 | jobs: 21 | prepare: 22 | if: (github.event_name != 'schedule') || (github.repository == 'mstorsjo/llvm-mingw') 23 | runs-on: ubuntu-latest 24 | outputs: 25 | LLVM_VERSION: ${{steps.get-parameters.outputs.LLVM_VERSION}} 26 | steps: 27 | - name: Download build parameters 28 | uses: dawidd6/action-download-artifact@v10 29 | with: 30 | workflow: build.yml 31 | workflow_conclusion: success 32 | ref: ${{github.event_name == 'schedule' && 'master' || inputs.ref}} 33 | event: ${{github.event_name == 'schedule' && 'schedule' || inputs.pipeline_type}} 34 | name: parameters 35 | - name: Get build parameters 36 | id: get-parameters 37 | run: | 38 | cat parameters.txt >> $GITHUB_OUTPUT 39 | cat $GITHUB_OUTPUT 40 | 41 | test-llvm: 42 | if: (github.event_name != 'schedule') || (github.repository == 'mstorsjo/llvm-mingw') 43 | needs: [prepare] 44 | strategy: 45 | fail-fast: false 46 | matrix: 47 | arch: 48 | - x86_64 49 | - aarch64 50 | runs-on: ${{startsWith(matrix.arch, 'a') && 'windows-11-arm' || 'windows-latest'}} 51 | steps: 52 | - name: Install dependencies 53 | run: | 54 | choco install ninja 55 | - name: Download toolchain 56 | uses: dawidd6/action-download-artifact@v10 57 | with: 58 | workflow: build.yml 59 | workflow_conclusion: success 60 | ref: ${{github.event_name == 'schedule' && 'master' || inputs.ref}} 61 | event: ${{github.event_name == 'schedule' && 'schedule' || inputs.pipeline_type}} 62 | name: windows-ucrt-${{matrix.arch}}-toolchain 63 | - name: Unpack toolchain 64 | run: | 65 | Expand-Archive llvm-mingw-*.zip -DestinationPath . 66 | del llvm-mingw-*.zip 67 | mv llvm-mingw-* c:\llvm-mingw 68 | echo "c:\llvm-mingw\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append 69 | echo "c:\llvm-mingw\python\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append 70 | echo "PYTHON_EXE=c:/llvm-mingw/python/bin/python3.exe" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append 71 | - uses: actions/checkout@v4 72 | - name: Checkout llvm-project 73 | env: 74 | LLVM_VERSION: ${{needs.prepare.outputs.LLVM_VERSION}} 75 | run: | 76 | git config --global core.autocrlf false 77 | bash -c "CHECKOUT_ONLY=1 ./build-llvm.sh" 78 | # Not passing -DPython3_EXECUTABLE="$Env:PYTHON_EXE" here. The bundled Python doesn't normally have 79 | # zlib enabled, which some tests require. 80 | - name: Build the project and unittests 81 | run: | 82 | cd llvm-project 83 | mkdir build 84 | cd build 85 | cmake ../llvm ` 86 | -G Ninja ` 87 | -DCMAKE_BUILD_TYPE=Release ` 88 | -DLLVM_HOST_TRIPLE=${{matrix.arch}}-w64-windows-gnu ` 89 | -DCMAKE_SYSTEM_PROCESSOR=${{matrix.arch}} ` 90 | -DCMAKE_SYSTEM_NAME=Windows ` 91 | -DLLVM_TARGETS_TO_BUILD="AArch64;X86" ` 92 | -DLLVM_ENABLE_PROJECTS="clang;lld;clang-tools-extra" ` 93 | -DLLVM_WINDOWS_PREFER_FORWARD_SLASH=OFF ` 94 | -DCMAKE_C_COMPILER=clang ` 95 | -DCMAKE_CXX_COMPILER=clang++ ` 96 | -DLLVM_LIT_ARGS="-v --time-tests" 97 | ninja test-depends 98 | cp c:\llvm-mingw\bin\libc++.dll bin 99 | cp c:\llvm-mingw\bin\libunwind.dll bin 100 | - name: Run tests 101 | run: | 102 | cd llvm-project 103 | cd build 104 | ninja check 105 | -------------------------------------------------------------------------------- /.github/workflows/test-system-clang.yml: -------------------------------------------------------------------------------- 1 | name: Test installing with a system clang 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | docker-build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - name: Build Docker images 11 | uses: docker/build-push-action@v5 12 | with: 13 | context: . 14 | push: false 15 | file: ./Dockerfile.system-clang 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /llvm-project 2 | /mingw-w64 3 | /lldb-mi 4 | /make-* 5 | /libffi 6 | /cpython* 7 | /python-native 8 | /toolchain 9 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | 3 | RUN apt-get update -qq && \ 4 | DEBIAN_FRONTEND="noninteractive" apt-get install -qqy --no-install-recommends \ 5 | git wget bzip2 file unzip libtool pkg-config cmake build-essential \ 6 | automake nasm gettext autopoint vim-tiny python3 \ 7 | ninja-build ca-certificates curl less zip && \ 8 | apt-get clean -y && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | 12 | RUN git config --global user.name "LLVM MinGW" && \ 13 | git config --global user.email root@localhost 14 | 15 | WORKDIR /build 16 | 17 | ENV TOOLCHAIN_PREFIX=/opt/llvm-mingw 18 | 19 | ARG TOOLCHAIN_ARCHS="i686 x86_64 armv7 aarch64" 20 | 21 | ARG DEFAULT_CRT=ucrt 22 | 23 | ARG CFGUARD_ARGS=--enable-cfguard 24 | 25 | # Build everything that uses the llvm monorepo. We need to build the mingw runtime before the compiler-rt/libunwind/libcxxabi/libcxx runtimes. 26 | COPY build-llvm.sh build-lldb-mi.sh strip-llvm.sh install-wrappers.sh build-mingw-w64.sh build-mingw-w64-tools.sh build-compiler-rt.sh build-libcxx.sh build-mingw-w64-libraries.sh build-openmp.sh ./ 27 | COPY wrappers/*.sh wrappers/*.c wrappers/*.h wrappers/*.cfg ./wrappers/ 28 | RUN ./build-llvm.sh $TOOLCHAIN_PREFIX && \ 29 | ./build-lldb-mi.sh $TOOLCHAIN_PREFIX && \ 30 | ./strip-llvm.sh $TOOLCHAIN_PREFIX && \ 31 | ./install-wrappers.sh $TOOLCHAIN_PREFIX && \ 32 | ./build-mingw-w64.sh $TOOLCHAIN_PREFIX --with-default-msvcrt=$DEFAULT_CRT $CFGUARD_ARGS && \ 33 | ./build-mingw-w64-tools.sh $TOOLCHAIN_PREFIX && \ 34 | ./build-compiler-rt.sh $TOOLCHAIN_PREFIX $CFGUARD_ARGS && \ 35 | ./build-libcxx.sh $TOOLCHAIN_PREFIX $CFGUARD_ARGS && \ 36 | ./build-mingw-w64-libraries.sh $TOOLCHAIN_PREFIX $CFGUARD_ARGS && \ 37 | ./build-compiler-rt.sh $TOOLCHAIN_PREFIX --build-sanitizers && \ 38 | ./build-openmp.sh $TOOLCHAIN_PREFIX $CFGUARD_ARGS && \ 39 | rm -rf /build/* 40 | 41 | ENV PATH=$TOOLCHAIN_PREFIX/bin:$PATH 42 | -------------------------------------------------------------------------------- /Dockerfile.cross: -------------------------------------------------------------------------------- 1 | # Cross compile an llvm-mingw toolchain for windows. 2 | # 3 | # This needs to be built with --build-arg BASE=, where image is the name 4 | # of a docker image that contains a working llvm-mingw cross compiler 5 | # from a similar enough version. 6 | # 7 | # This builds LLVM and all other build tools that need to run on the target 8 | # platform, but just copies over the runtime libraries from the existing 9 | # toolchain in the base docker image. 10 | 11 | ARG BASE=mstorsjo/llvm-mingw:dev 12 | FROM $BASE 13 | 14 | RUN apt-get update -qq && \ 15 | apt-get install -qqy libltdl-dev swig autoconf-archive && \ 16 | apt-get clean -y && \ 17 | rm -rf /var/lib/apt/lists/* 18 | 19 | COPY build-python.sh . 20 | 21 | ARG WITH_PYTHON 22 | 23 | RUN if [ -n "$WITH_PYTHON" ]; then \ 24 | ./build-python.sh /opt/python; \ 25 | fi 26 | 27 | ENV PATH=/opt/python/bin:$PATH 28 | 29 | ARG CROSS_ARCH=x86_64 30 | ENV CROSS_TOOLCHAIN_PREFIX=/opt/llvm-mingw-$CROSS_ARCH 31 | 32 | ENV HOST=$CROSS_ARCH-w64-mingw32 33 | 34 | RUN if [ -n "$WITH_PYTHON" ]; then \ 35 | ./build-python.sh $CROSS_TOOLCHAIN_PREFIX/python --host=$HOST && \ 36 | mkdir -p $CROSS_TOOLCHAIN_PREFIX/bin && \ 37 | cp $CROSS_TOOLCHAIN_PREFIX/python/bin/*.dll $CROSS_TOOLCHAIN_PREFIX/bin; \ 38 | fi 39 | 40 | ARG FULL_LLVM 41 | 42 | COPY build-llvm.sh . 43 | RUN if [ -n "$WITH_PYTHON" ]; then ARG="--with-python"; fi && \ 44 | ./build-llvm.sh $CROSS_TOOLCHAIN_PREFIX --host=$HOST $ARG 45 | 46 | COPY build-lldb-mi.sh . 47 | RUN ./build-lldb-mi.sh $CROSS_TOOLCHAIN_PREFIX --host=$HOST 48 | 49 | COPY strip-llvm.sh . 50 | RUN ./strip-llvm.sh $CROSS_TOOLCHAIN_PREFIX --host=$HOST 51 | 52 | ARG TOOLCHAIN_ARCHS="i686 x86_64 armv7 aarch64" 53 | 54 | COPY build-mingw-w64.sh build-mingw-w64-tools.sh ./ 55 | RUN ./build-mingw-w64-tools.sh $CROSS_TOOLCHAIN_PREFIX --skip-include-triplet-prefix --host=$HOST 56 | 57 | COPY wrappers/*.sh wrappers/*.c wrappers/*.h wrappers/*.cfg ./wrappers/ 58 | COPY install-wrappers.sh . 59 | RUN ./install-wrappers.sh $CROSS_TOOLCHAIN_PREFIX --host=$HOST 60 | 61 | COPY prepare-cross-toolchain.sh . 62 | RUN ./prepare-cross-toolchain.sh $TOOLCHAIN_PREFIX $CROSS_TOOLCHAIN_PREFIX $CROSS_ARCH 63 | 64 | COPY build-make.sh . 65 | RUN ./build-make.sh $CROSS_TOOLCHAIN_PREFIX --host=$HOST 66 | 67 | ARG TAG 68 | RUN ln -s $CROSS_TOOLCHAIN_PREFIX llvm-mingw-$TAG$CROSS_ARCH && \ 69 | zip -9r /llvm-mingw-$TAG$CROSS_ARCH.zip llvm-mingw-$TAG$CROSS_ARCH && \ 70 | ls -lh /llvm-mingw-$TAG$CROSS_ARCH.zip 71 | -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | 3 | RUN apt-get update -qq && \ 4 | DEBIAN_FRONTEND="noninteractive" apt-get install -qqy --no-install-recommends \ 5 | git wget bzip2 file unzip libtool pkg-config cmake build-essential \ 6 | automake nasm gettext autopoint vim-tiny python3 \ 7 | ninja-build ca-certificates curl less zip && \ 8 | apt-get clean -y && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | 12 | RUN git config --global user.name "LLVM MinGW" && \ 13 | git config --global user.email root@localhost 14 | 15 | WORKDIR /build 16 | 17 | ENV TOOLCHAIN_PREFIX=/opt/llvm-mingw 18 | 19 | ARG FULL_LLVM 20 | 21 | # Build LLVM 22 | COPY build-llvm.sh ./ 23 | RUN ./build-llvm.sh $TOOLCHAIN_PREFIX 24 | 25 | # Build LLDB-MI 26 | COPY build-lldb-mi.sh ./ 27 | RUN ./build-lldb-mi.sh $TOOLCHAIN_PREFIX 28 | 29 | # Strip the LLVM install output immediately. (This doesn't reduce the 30 | # total docker image size as long as it is in a separate RUN layer though, 31 | # but reduces build times if tweaking the contents of strip-llvm.sh.) 32 | # Most of the size of the docker image comes from the build directory that 33 | # we keep in any case. 34 | COPY strip-llvm.sh ./ 35 | RUN ./strip-llvm.sh $TOOLCHAIN_PREFIX 36 | 37 | ARG TOOLCHAIN_ARCHS="i686 x86_64 armv7 aarch64" 38 | 39 | # Install the usual $TUPLE-clang binaries 40 | COPY wrappers/*.sh wrappers/*.c wrappers/*.h wrappers/*.cfg ./wrappers/ 41 | COPY install-wrappers.sh ./ 42 | RUN ./install-wrappers.sh $TOOLCHAIN_PREFIX 43 | 44 | ARG DEFAULT_CRT=ucrt 45 | 46 | ARG CFGUARD_ARGS=--enable-cfguard 47 | 48 | # Build MinGW-w64 49 | COPY build-mingw-w64.sh ./ 50 | RUN ./build-mingw-w64.sh $TOOLCHAIN_PREFIX --with-default-msvcrt=$DEFAULT_CRT $CFGUARD_ARGS 51 | 52 | COPY build-mingw-w64-tools.sh ./ 53 | RUN ./build-mingw-w64-tools.sh $TOOLCHAIN_PREFIX 54 | 55 | # Build compiler-rt 56 | COPY build-compiler-rt.sh ./ 57 | RUN ./build-compiler-rt.sh $TOOLCHAIN_PREFIX $CFGUARD_ARGS 58 | 59 | # Build libunwind/libcxxabi/libcxx 60 | COPY build-libcxx.sh ./ 61 | RUN ./build-libcxx.sh $TOOLCHAIN_PREFIX $CFGUARD_ARGS 62 | 63 | # Build mingw-w64's extra libraries 64 | COPY build-mingw-w64-libraries.sh ./ 65 | RUN ./build-mingw-w64-libraries.sh $TOOLCHAIN_PREFIX $CFGUARD_ARGS 66 | 67 | # Build C test applications 68 | ENV PATH=$TOOLCHAIN_PREFIX/bin:$PATH 69 | 70 | COPY test/*.c test/*.h test/*.idl ./test/ 71 | RUN cd test && \ 72 | for arch in $TOOLCHAIN_ARCHS; do \ 73 | mkdir -p $arch && \ 74 | for test in hello hello-tls crt-test setjmp; do \ 75 | $arch-w64-mingw32-clang $test.c -o $arch/$test.exe || exit 1; \ 76 | done; \ 77 | for test in autoimport-lib; do \ 78 | $arch-w64-mingw32-clang $test.c -shared -o $arch/$test.dll -Wl,--out-implib,$arch/lib$test.dll.a || exit 1; \ 79 | done; \ 80 | for test in autoimport-main; do \ 81 | $arch-w64-mingw32-clang $test.c -o $arch/$test.exe -L$arch -l${test%-main}-lib || exit 1; \ 82 | done; \ 83 | for test in idltest; do \ 84 | # The IDL output isn't arch specific, but test each arch frontend \ 85 | $arch-w64-mingw32-widl $test.idl -h -o $arch/$test.h && \ 86 | $arch-w64-mingw32-clang $test.c -I$arch -o $arch/$test.exe -lole32 || exit 1; \ 87 | done; \ 88 | for test in stacksmash; do \ 89 | $arch-w64-mingw32-clang $test.c -o $arch/$test.exe -fstack-protector-strong || exit 1; \ 90 | done; \ 91 | for test in bufferoverflow; do \ 92 | $arch-w64-mingw32-clang $test.c -o $arch/$test.exe -D_FORTIFY_SOURCE=2 -O2 || exit 1; \ 93 | done; \ 94 | done 95 | 96 | # Build C++ test applications 97 | COPY test/*.cpp ./test/ 98 | RUN cd test && \ 99 | for arch in $TOOLCHAIN_ARCHS; do \ 100 | mkdir -p $arch && \ 101 | for test in hello-cpp hello-exception tlstest-main exception-locale exception-reduced global-terminate longjmp-cleanup; do \ 102 | $arch-w64-mingw32-clang++ $test.cpp -o $arch/$test.exe || exit 1; \ 103 | done; \ 104 | for test in hello-exception; do \ 105 | $arch-w64-mingw32-clang++ $test.cpp -static -o $arch/$test-static.exe || exit 1; \ 106 | done; \ 107 | for test in tlstest-lib throwcatch-lib; do \ 108 | $arch-w64-mingw32-clang++ $test.cpp -shared -o $arch/$test.dll -Wl,--out-implib,$arch/lib$test.dll.a || exit 1; \ 109 | done; \ 110 | for test in throwcatch-main; do \ 111 | $arch-w64-mingw32-clang++ $test.cpp -o $arch/$test.exe -L$arch -l${test%-main}-lib || exit 1; \ 112 | done; \ 113 | done 114 | 115 | # Build sanitizers. Ubsan includes from the C++ headers, so 116 | # we need to build this after libcxx. 117 | # $CFGUARD_ARGS is intentionally omitted here. 118 | RUN ./build-compiler-rt.sh $TOOLCHAIN_PREFIX --build-sanitizers 119 | 120 | # Sanitizers on windows only support x86. 121 | RUN cd test && \ 122 | for arch in $TOOLCHAIN_ARCHS; do \ 123 | case $arch in \ 124 | i686|x86_64) \ 125 | ;; \ 126 | *) \ 127 | continue \ 128 | ;; \ 129 | esac && \ 130 | for test in stacksmash; do \ 131 | $arch-w64-mingw32-clang $test.c -o $arch/$test-asan.exe -fsanitize=address -g -gcodeview -Wl,--pdb= || exit 1; \ 132 | done; \ 133 | for test in ubsan; do \ 134 | $arch-w64-mingw32-clang $test.c -o $arch/$test.exe -fsanitize=undefined -fno-sanitize-recover=all || exit 1; \ 135 | done; \ 136 | done 137 | 138 | # Build OpenMP 139 | COPY build-openmp.sh ./ 140 | RUN ./build-openmp.sh $TOOLCHAIN_PREFIX $CFGUARD_ARGS 141 | 142 | RUN cd test && \ 143 | for arch in $TOOLCHAIN_ARCHS; do \ 144 | for test in hello-omp; do \ 145 | $arch-w64-mingw32-clang $test.c -o $arch/$test.exe -fopenmp=libomp || exit 1; \ 146 | done; \ 147 | done 148 | 149 | RUN cd test && \ 150 | for arch in $TOOLCHAIN_ARCHS; do \ 151 | cp $TOOLCHAIN_PREFIX/$arch-w64-mingw32/bin/*.dll $arch || exit 1; \ 152 | done 153 | -------------------------------------------------------------------------------- /Dockerfile.system-clang: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | 3 | RUN apt-get update -qq && \ 4 | DEBIAN_FRONTEND="noninteractive" apt-get install -qqy --no-install-recommends \ 5 | git wget bzip2 file unzip libtool pkg-config cmake build-essential \ 6 | automake nasm gettext autopoint vim-tiny python3 \ 7 | ninja-build ca-certificates curl less zip && \ 8 | apt-get clean -y && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | # Separate step for system-clang; the RUN line above is similar to other dockerfiles. 12 | RUN apt-get update -qq && \ 13 | apt-get install -qqy clang-18 lld-18 llvm-18 && \ 14 | apt-get clean -y && \ 15 | rm -rf /var/lib/apt/lists/* 16 | 17 | 18 | RUN git config --global user.name "LLVM MinGW" && \ 19 | git config --global user.email root@localhost 20 | 21 | WORKDIR /build 22 | 23 | ENV TOOLCHAIN_PREFIX=/opt/llvm-mingw 24 | 25 | ARG TOOLCHAIN_ARCHS="i686 x86_64 armv7 aarch64" 26 | 27 | ARG DEFAULT_CRT=ucrt 28 | 29 | ARG CFGUARD_ARGS=--enable-cfguard 30 | 31 | COPY build-all.sh build-llvm.sh install-wrappers.sh build-mingw-w64.sh build-mingw-w64-tools.sh build-compiler-rt.sh build-libcxx.sh build-mingw-w64-libraries.sh build-openmp.sh ./ 32 | COPY wrappers/*.sh wrappers/*.c wrappers/*.h wrappers/*.cfg ./wrappers/ 33 | RUN ./build-all.sh $TOOLCHAIN_PREFIX --host-clang=clang-18 && \ 34 | rm -rf /build/* 35 | 36 | ENV PATH=$TOOLCHAIN_PREFIX/bin:$PATH 37 | 38 | # Test the installation 39 | COPY test/*.c test/*.cpp test/*.h test/*.idl test/*.rc test/Makefile ./test/ 40 | COPY run-tests.sh ./ 41 | RUN ./run-tests.sh $TOOLCHAIN_PREFIX 42 | -------------------------------------------------------------------------------- /Dockerfile.toolchain: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | 3 | RUN apt-get update -qq && \ 4 | DEBIAN_FRONTEND="noninteractive" apt-get install -qqy --no-install-recommends \ 5 | git wget bzip2 file unzip libtool pkg-config cmake build-essential \ 6 | automake nasm gettext autopoint vim-tiny python3 \ 7 | ninja-build ca-certificates curl less zip && \ 8 | apt-get clean -y && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | 12 | RUN git config --global user.name "LLVM MinGW" && \ 13 | git config --global user.email root@localhost 14 | 15 | WORKDIR /build 16 | 17 | ENV TOOLCHAIN_PREFIX=/opt/llvm-mingw 18 | 19 | ARG TOOLCHAIN_ARCHS="i686 x86_64 armv7 aarch64" 20 | 21 | # Copy prebuilt toolchains for the current architecture. 22 | # Test executing a binary, to make sure that it works (i.e. it is not built 23 | # requiring a newer version of glibc or libstdc++ than what is available in 24 | # this container). 25 | RUN --mount=type=bind,source=toolchain,target=/toolchain \ 26 | mkdir -p $TOOLCHAIN_PREFIX && ARCH=$(uname -m) && \ 27 | tar xf /toolchain/linux-ucrt-$ARCH-toolchain/llvm-mingw-*-$ARCH.tar.xz --strip-components 1 -C $TOOLCHAIN_PREFIX && \ 28 | ANY_ARCH=$(echo $TOOLCHAIN_ARCHS | awk '{print $1}') && \ 29 | $TOOLCHAIN_PREFIX/bin/$ANY_ARCH-w64-mingw32-clang --version 30 | 31 | ENV PATH=$TOOLCHAIN_PREFIX/bin:$PATH 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The llvm-mingw project (the scripts for building and assembling a 2 | toolchain, wrappers for executing tools and testcases) is licensed under 3 | the ISC license. 4 | 5 | This license only covers the components provided by llvm-mingw directly. 6 | The final built toolchain is covered by the licenses of the individual 7 | external projects, primarily LLVM's Apache 2 license with LLVM exceptions. 8 | 9 | The ISC license: 10 | 11 | Permission to use, copy, modify, and/or distribute this software for any 12 | purpose with or without fee is hereby granted, provided that the above 13 | copyright notice and this permission notice appear in all copies. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LLVM MinGW 2 | ========== 3 | 4 | This is a recipe for reproducibly building a 5 | [LLVM](https://llvm.org)/[Clang](https://clang.llvm.org/)/[LLD](https://lld.llvm.org/) 6 | based mingw-w64 toolchain. 7 | 8 | Benefits of a LLVM based MinGW toolchain are: 9 | - Support for targeting ARM/ARM64 (while GCC obviously does support 10 | these architectures, it doesn't support Windows on ARM) 11 | - A single toolchain targeting all four architectures (i686, x86_64, 12 | armv7 and arm64) instead of separate compiler binaries for each 13 | architecture 14 | - Support for generating debug info in PDB format 15 | - Support for Address Sanitizer and Undefined Behaviour Sanitizer 16 | - Since LLVM 16: Support for [Control Flow Guard](https://github.com/mstorsjo/llvm-mingw/issues/301) 17 | (`-mguard=cf` compile and link flags) 18 | 19 | Clang on its own can also be used as compiler in the normal GNU binutils 20 | based environments though, so the main difference lies in replacing 21 | binutils with LLVM based tools. 22 | 23 | Releases 24 | -------- 25 | 26 | The [GitHub Releases](https://github.com/mstorsjo/llvm-mingw/releases) 27 | page contains prebuilt toolchains that can be downloaded and installed 28 | by just unpacking them. 29 | 30 | They come primarily in two different forms; packages named 31 | `llvm-mingw---ubuntu--.tar.xz` 32 | are cross compilers, that can be run on Linux, compiling binaries 33 | for any of the 4 target Windows architectures. Packages named 34 | `llvm-mingw---.zip` are native toolchains that 35 | run on Windows (with binaries in the specified architecture), but 36 | which all can compile binaries for any of the 4 architectures. 37 | 38 | The cross compilers come in versions running on either x86_64 or 39 | aarch64. (They're built on Ubuntu, but hopefully do run on other 40 | contempory distributions as well.) 41 | 42 | There are packages with two different choices of CRT (C runtime) - the 43 | primary target is UCRT (the Universal C Runtime). The UCRT 44 | is available preinstalled since Windows 10, but can be 45 | [installed](https://www.microsoft.com/en-us/download/details.aspx?id=50410) 46 | on top of Vista or newer. The other legacy alternative is `msvcrt`, 47 | which produces binaries for (and uses) msvcrt.dll, which is a 48 | built-in component in all versions of Windows. This allows running 49 | directly out of the box on older versions of Windows too, without 50 | ensuring that the UCRT is installed, but msvcrt.dll is generally 51 | less featureful. Address Sanitizer only works properly with UCRT. 52 | 53 | In addition to the downloadable toolchain packges, there are also 54 | prebuilt docker linux images containing the llvm-mingw toolchain, 55 | available from [Docker Hub](https://hub.docker.com/r/mstorsjo/llvm-mingw/). 56 | 57 | There are also [nightly builds](https://github.com/mstorsjo/llvm-mingw/releases/tag/nightly) 58 | with the very latest versions of LLVM and mingw-w64 from git. 59 | 60 | Building from source 61 | -------------------- 62 | 63 | The toolchain can be compiled for installation in the current Unix 64 | environment, fetching sources as needed: 65 | 66 | ./build-all.sh 67 | 68 | It can also be built, reproducibly, into a Docker image: 69 | 70 | docker build . 71 | 72 | Individual components of the toolchain can be (re)built by running 73 | the standalone shellscripts listed within `build-all.sh`. However, if 74 | the source already is checked out, no effort is made to check out a 75 | different version (if the build scripts have been updated to prefer 76 | a different version) - and likewise, if configure flags in the build-\*.sh 77 | scripts have changed, you might need to wipe the build directory under 78 | each project for the new configure options to be taken into use. 79 | 80 | 81 | Building in MSYS2 82 | ----------------- 83 | 84 | To build in MSYS2, install the following set of packages with `pacman -S --needed`: 85 | 86 | git wget mingw-w64-x86_64-gcc mingw-w64-x86_64-ninja mingw-w64-x86_64-cmake make mingw-w64-x86_64-python3 autoconf libtool 87 | 88 | 89 | Status 90 | ------ 91 | 92 | The toolchain currently does support both C and C++, including support 93 | for exception handling. 94 | 95 | 96 | Known issues 97 | ------------ 98 | 99 | LLD, the LLVM linker, is what causes most of the major differences to the 100 | normal GCC/binutils based MinGW. 101 | 102 | - As this toolchain uses a different CRT and C++ standard library than 103 | most mingw toolchains, it is incompatible with object files and 104 | static libraries built with other toolchains. Mixing DLLs from other 105 | toolchains is supported, but only as long as CRT resources aren't 106 | shared across DLL boundaries (no sharing of file handles etc, and memory 107 | should be freed by the same DLL that allocated it). 108 | - The windres replacement, llvm-rc, isn't very mature and doesn't support 109 | everything that GNU windres does. 110 | - The toolchain defaults to using the Universal CRT and targeting Windows 7. 111 | These defaults can be changed in `build-mingw-w64.sh` though. The Universal 112 | CRT is only available out of the box since Windows 10, but can be 113 | [installed](https://www.microsoft.com/en-us/download/details.aspx?id=50410) 114 | on Vista or newer. For x86, there are also releases that run on 115 | msvcrt.dll. 116 | - The toolchain uses Windows native TLS support, which doesn't work properly 117 | until Windows Vista. This has no effect on code not using thread local 118 | variables. 119 | - The runtime libraries libunwind, libcxxabi and libcxx also assume that the 120 | target is Windows 7 or newer. 121 | - Address sanitizer is only supported on x86. 122 | - LLD doesn't support linker script (in the COFF part of LLD). Linker script can be used for 123 | reprogramming how the linker lays out the output, but is in most cases 124 | in MinGW setups only used for passing lists of object files to link. 125 | Passing lists of files can also be done with response files, which LLD does support. 126 | (This was fixed in qmake in [v5.12.0](https://code.qt.io/cgit/qt/qtbase.git/commit/?id=d92c25b1b4ac0423a824715a08b2db2def4b6e25), to use response 127 | files instead of linker script.) 128 | - Libtool based projects fail to link with llvm-mingw if the project contains 129 | C++. (This often manifests with undefined symbols like `___chkstk_ms`, 130 | `__alloca` or `___divdi3`.) 131 | For such targets, libtool tries to detect which libraries to link 132 | by invoking the compiler with `$CC -v` and picking up the libraries that 133 | are linked by default, and then invoking the linker driver with `-nostdlib` 134 | and specifying the default libraries manually. In doing so, libtool fails 135 | to detect when clang is using compiler_rt instead of libgcc, because 136 | clang refers to it as an absolute path to a static library, instead of 137 | specifying a library path with `-L` and linking the library with `-l`. 138 | Clang is [reluctant to changing this behaviour](https://reviews.llvm.org/D51440). 139 | A [bug](https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27866) has been filed 140 | with libtool, but no fix has been committed, and as libtool files are 141 | shipped with the projects that use them (bundled within the configure 142 | script), one has to update the configure script in each project to avoid 143 | the issue. This can either be done by installing libtool, patching it 144 | and running `autoreconf -fi` in the project, or by manually applying the 145 | fix on the shipped `configure` script. A patched version of libtool is 146 | [shipped in MSYS2](https://github.com/msys2/MINGW-packages/blob/95b093e888/mingw-w64-libtool/0011-Pick-up-clang_rt-static-archives-compiler-internal-l.patch) 147 | at least. 148 | - Libtool, when running on Windows, prefers using linker script over 149 | response files, to pass long lists of object files to the linker driver, 150 | but LLD doesn't support linker script (as described above). This issue 151 | produces errors like `lld-link: error: .libs\libfoobar.la.lnkscript: unknown file type`. 152 | To fix this, the bundled libtool scripts has to be fixed like explained 153 | above, but this fix requires changes both to `configure` and a separate 154 | file named `ltmain.{in,sh}`. A fix for this is also 155 | [shipped in MSYS2](https://github.com/msys2/MINGW-packages/blob/95b093e888/mingw-w64-libtool/0012-Prefer-response-files-over-linker-scripts-for-mingw-.patch). 156 | 157 | Additionally, one may run into other minor differences between GCC and clang. 158 | 159 | PDB support 160 | ----------- 161 | 162 | LLVM does [support](http://blog.llvm.org/2017/08/llvm-on-windows-now-supports-pdb-debug.html) 163 | generating debug info in the PDB format. Since GNU binutils based mingw 164 | environments don't support this, there's no predecent for what command 165 | line parameters to use for this, and llvm-mingw produces debug info in 166 | DWARF format by default. 167 | 168 | To produce debug info in PDB format, you currently need to do the following 169 | changes: 170 | 171 | - Add `-gcodeview` to the compilation commands (e.g. in 172 | `wrappers/clang-target-wrapper.sh`), together with using `-g` as usual to 173 | enable debug info in general. 174 | - Add `-Wl,--pdb=` to linking commands. This creates a PDB file at the same 175 | location as the output EXE/DLL, but with a PDB extension. (By passing 176 | `-Wl,--pdb=module.pdb` one can explicitly specify the name of the output 177 | PDB file.) 178 | 179 | Even though LLVM supports this, there are some caveats with using it when 180 | building in MinGW mode; Microsoft debuggers might have assumptions about 181 | the C++ ABI used, which doesn't hold up with the Itanium ABI used in MinGW. 182 | -------------------------------------------------------------------------------- /build-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | HOST_CLANG= 20 | LLVM_ARGS="" 21 | MINGW_ARGS="" 22 | CFGUARD_ARGS="--enable-cfguard" 23 | HOST_ARGS="" 24 | 25 | while [ $# -gt 0 ]; do 26 | case "$1" in 27 | --enable-asserts) 28 | LLVM_ARGS="$LLVM_ARGS $1" 29 | ;; 30 | --host-clang|--host-clang=*) 31 | HOST_CLANG=${1#--host-clang} 32 | HOST_CLANG=${HOST_CLANG#=} 33 | HOST_CLANG=${HOST_CLANG:-clang} 34 | ;; 35 | --full-llvm) 36 | LLVM_ARGS="$LLVM_ARGS $1" 37 | FULL_LLVM=1 38 | ;; 39 | --disable-dylib) 40 | LLVM_ARGS="$LLVM_ARGS $1" 41 | ;; 42 | --disable-lldb) 43 | LLVM_ARGS="$LLVM_ARGS $1" 44 | NO_LLDB=1 45 | ;; 46 | --disable-lldb-mi) 47 | NO_LLDB_MI=1 48 | ;; 49 | --disable-clang-tools-extra) 50 | LLVM_ARGS="$LLVM_ARGS $1" 51 | ;; 52 | --with-default-msvcrt=*) 53 | MINGW_ARGS="$MINGW_ARGS $1" 54 | ;; 55 | --with-default-win32-winnt=*) 56 | MINGW_ARGS="$MINGW_ARGS $1" 57 | ;; 58 | --enable-cfguard) 59 | CFGUARD_ARGS="--enable-cfguard" 60 | ;; 61 | --disable-cfguard) 62 | CFGUARD_ARGS="--disable-cfguard" 63 | ;; 64 | --no-runtimes) 65 | NO_RUNTIMES=1 66 | ;; 67 | --host=*) 68 | HOST_ARGS="$HOST_ARGS $1" 69 | ;; 70 | --no-tools) 71 | NO_TOOLS=1 72 | ;; 73 | --wipe-runtimes) 74 | WIPE_RUNTIMES=1 75 | ;; 76 | --clean-runtimes) 77 | CLEAN_RUNTIMES=1 78 | ;; 79 | *) 80 | if [ -n "$PREFIX" ]; then 81 | echo Unrecognized parameter $1 82 | exit 1 83 | fi 84 | PREFIX="$1" 85 | ;; 86 | esac 87 | shift 88 | done 89 | if [ -z "$PREFIX" ]; then 90 | echo "$0 [--host-clang[=clang]] [--enable-asserts] [--disable-dylib] [--full-llvm] [--disable-lldb] [--disable-lldb-mi] [--disable-clang-tools-extra] [--host=triple] [--with-default-win32-winnt=0x601] [--with-default-msvcrt=ucrt] [--enable-cfguard|--disable-cfguard] [--no-runtimes] [--no-tools] [--wipe-runtimes] [--clean-runtimes] dest" 91 | exit 1 92 | fi 93 | 94 | for dep in git cmake ${HOST_CLANG}; do 95 | if ! command -v $dep >/dev/null; then 96 | echo "$dep not installed. Please install it and retry" 1>&2 97 | exit 1 98 | fi 99 | done 100 | 101 | if [ -n "${HOST_CLANG}" ] && [ "${CFGUARD_ARGS}" = "--enable-cfguard" ]; then 102 | "${HOST_CLANG}" -c -x c -o - - -Werror -mguard=cf /dev/null 2>/dev/null || CFGUARD_ARGS="--disable-cfguard" 103 | fi 104 | 105 | if [ -z "$NO_TOOLS" ]; then 106 | if [ -z "${HOST_CLANG}" ]; then 107 | ./build-llvm.sh $PREFIX $LLVM_ARGS $HOST_ARGS 108 | if [ -z "$NO_LLDB" ] && [ -z "$NO_LLDB_MI" ]; then 109 | ./build-lldb-mi.sh $PREFIX $HOST_ARGS 110 | fi 111 | if [ -z "$FULL_LLVM" ]; then 112 | ./strip-llvm.sh $PREFIX $HOST_ARGS 113 | fi 114 | fi 115 | ./install-wrappers.sh $PREFIX $HOST_ARGS ${HOST_CLANG:+--host-clang=$HOST_CLANG} 116 | ./build-mingw-w64-tools.sh $PREFIX $HOST_ARGS 117 | fi 118 | if [ -n "$NO_RUNTIMES" ]; then 119 | exit 0 120 | fi 121 | if [ -n "$WIPE_RUNTIMES" ]; then 122 | # Remove the runtime code built previously. 123 | # 124 | # This roughly matches the setup as if --no-runtimes had been passed, 125 | # except that compiler-rt headers are left installed in lib/clang/*/include. 126 | rm -rf $PREFIX/*-w64-mingw32 $PREFIX/lib/clang/*/lib 127 | fi 128 | if [ -n "$CLEAN_RUNTIMES" ]; then 129 | export CLEAN=1 130 | fi 131 | ./build-mingw-w64.sh $PREFIX $MINGW_ARGS $CFGUARD_ARGS 132 | ./build-compiler-rt.sh $PREFIX $CFGUARD_ARGS 133 | ./build-libcxx.sh $PREFIX $CFGUARD_ARGS 134 | ./build-mingw-w64-libraries.sh $PREFIX $CFGUARD_ARGS 135 | ./build-compiler-rt.sh $PREFIX --build-sanitizers # CFGUARD_ARGS intentionally omitted 136 | ./build-openmp.sh $PREFIX $CFGUARD_ARGS 137 | -------------------------------------------------------------------------------- /build-compiler-rt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | SRC_DIR=../lib/builtins 20 | BUILD_SUFFIX= 21 | BUILD_BUILTINS=TRUE 22 | ENABLE_CFGUARD=1 23 | CFGUARD_CFLAGS="-mguard=cf" 24 | 25 | while [ $# -gt 0 ]; do 26 | if [ "$1" = "--build-sanitizers" ]; then 27 | SRC_DIR=.. 28 | BUILD_SUFFIX=-sanitizers 29 | SANITIZERS=1 30 | BUILD_BUILTINS=FALSE 31 | # Override the default cfguard options here; this unfortunately 32 | # also overrides the user option if --enable-cfguard is passed 33 | # before --build-sanitizers (although that combination isn't 34 | # really intended/supported anyway). 35 | CFGUARD_CFLAGS= 36 | ENABLE_CFGUARD= 37 | elif [ "$1" = "--enable-cfguard" ]; then 38 | CFGUARD_CFLAGS="-mguard=cf" 39 | ENABLE_CFGUARD=1 40 | elif [ "$1" = "--disable-cfguard" ]; then 41 | CFGUARD_CFLAGS= 42 | ENABLE_CFGUARD= 43 | else 44 | PREFIX="$1" 45 | fi 46 | shift 47 | done 48 | if [ -z "$PREFIX" ]; then 49 | echo "$0 [--build-sanitizers] [--enable-cfguard|--disable-cfguard] dest" 50 | exit 1 51 | fi 52 | if [ -n "$SANITIZERS" ] && [ -n "$ENABLE_CFGUARD" ]; then 53 | echo "warning: Sanitizers may not work correctly with Control Flow Guard enabled." 1>&2 54 | fi 55 | 56 | mkdir -p "$PREFIX" 57 | PREFIX="$(cd "$PREFIX" && pwd)" 58 | export PATH="$PREFIX/bin:$PATH" 59 | 60 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 61 | 62 | ANY_ARCH=$(echo $ARCHS | awk '{print $1}') 63 | CLANG_RESOURCE_DIR="$("$PREFIX/bin/$ANY_ARCH-w64-mingw32-clang" --print-resource-dir)" 64 | 65 | if [ ! -d llvm-project/compiler-rt ] || [ -n "$SYNC" ]; then 66 | CHECKOUT_ONLY=1 ./build-llvm.sh 67 | fi 68 | 69 | if command -v ninja >/dev/null; then 70 | CMAKE_GENERATOR="Ninja" 71 | else 72 | : ${CORES:=$(nproc 2>/dev/null)} 73 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 74 | : ${CORES:=4} 75 | 76 | case $(uname) in 77 | MINGW*) 78 | CMAKE_GENERATOR="MSYS Makefiles" 79 | ;; 80 | esac 81 | fi 82 | 83 | cd llvm-project/compiler-rt 84 | 85 | INSTALL_PREFIX="$CLANG_RESOURCE_DIR" 86 | 87 | if [ -h "$CLANG_RESOURCE_DIR/include" ]; then 88 | # Symlink to system headers; use a staging directory in case parts 89 | # of the resource dir are immutable 90 | WORKDIR="$(mktemp -d)"; trap "rm -rf $WORKDIR" 0 91 | INSTALL_PREFIX="$WORKDIR/install" 92 | fi 93 | 94 | 95 | for arch in $ARCHS; do 96 | [ -z "$CLEAN" ] || rm -rf build-$arch$BUILD_SUFFIX 97 | mkdir -p build-$arch$BUILD_SUFFIX 98 | cd build-$arch$BUILD_SUFFIX 99 | [ -n "$NO_RECONF" ] || rm -rf CMake* 100 | cmake \ 101 | ${CMAKE_GENERATOR+-G} "$CMAKE_GENERATOR" \ 102 | -DCMAKE_BUILD_TYPE=Release \ 103 | -DCMAKE_INSTALL_PREFIX="$CLANG_RESOURCE_DIR" \ 104 | -DCMAKE_C_COMPILER=$arch-w64-mingw32-clang \ 105 | -DCMAKE_CXX_COMPILER=$arch-w64-mingw32-clang++ \ 106 | -DCMAKE_SYSTEM_NAME=Windows \ 107 | -DCMAKE_AR="$PREFIX/bin/llvm-ar" \ 108 | -DCMAKE_RANLIB="$PREFIX/bin/llvm-ranlib" \ 109 | -DCMAKE_C_COMPILER_WORKS=1 \ 110 | -DCMAKE_CXX_COMPILER_WORKS=1 \ 111 | -DCMAKE_C_COMPILER_TARGET=$arch-w64-windows-gnu \ 112 | -DCOMPILER_RT_DEFAULT_TARGET_ONLY=TRUE \ 113 | -DCOMPILER_RT_USE_BUILTINS_LIBRARY=TRUE \ 114 | -DCOMPILER_RT_BUILD_BUILTINS=$BUILD_BUILTINS \ 115 | -DCOMPILER_RT_EXCLUDE_ATOMIC_BUILTIN=FALSE \ 116 | -DLLVM_CONFIG_PATH="" \ 117 | -DCMAKE_FIND_ROOT_PATH=$PREFIX/$arch-w64-mingw32 \ 118 | -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \ 119 | -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY \ 120 | -DSANITIZER_CXX_ABI=libc++ \ 121 | -DCMAKE_C_FLAGS_INIT="$CFGUARD_CFLAGS" \ 122 | -DCMAKE_CXX_FLAGS_INIT="$CFGUARD_CFLAGS" \ 123 | $SRC_DIR 124 | cmake --build . ${CORES:+-j${CORES}} 125 | 126 | # Skip install on arm64ec, we merge archives instead. 127 | if [ "$arch" = "arm64ec" ]; then 128 | cd .. 129 | continue 130 | fi 131 | 132 | cmake --install . --prefix "$INSTALL_PREFIX" 133 | mkdir -p "$PREFIX/$arch-w64-mingw32/bin" 134 | if [ -n "$SANITIZERS" ]; then 135 | case $arch in 136 | aarch64) 137 | # asan doesn't work on aarch64 or armv7; make this clear by omitting 138 | # the installed files altogether. 139 | rm -f "$INSTALL_PREFIX/lib/windows/libclang_rt.asan"*aarch64* 140 | ;; 141 | armv7) 142 | rm -f "$INSTALL_PREFIX/lib/windows/libclang_rt.asan"*arm* 143 | ;; 144 | *) 145 | mv "$INSTALL_PREFIX/lib/windows/"*.dll "$PREFIX/$arch-w64-mingw32/bin" 146 | ;; 147 | esac 148 | fi 149 | cd .. 150 | done 151 | 152 | # Clang expects the aarch64 compiler-rt name on ARM64EC. While this could be adjusted 153 | # in Clang, the current approach mirrors MSVC, where the core CRT is provided as 154 | # archives containing both EC and native support. Ideally, the LLVM build system would 155 | # handle this automatically, but for now we can merge it here. 156 | for arch in $ARCHS; do 157 | if [ "$arch" = "arm64ec" ]; then 158 | rm -f "$INSTALL_PREFIX/lib/windows/libclang_rt.builtins-aarch64.a" \ 159 | "$INSTALL_PREFIX/lib/windows/libclang_rt.builtins-arm64ec.a" 160 | "$PREFIX/bin/llvm-lib" -machine:arm64ec "-out:$INSTALL_PREFIX/lib/windows/libclang_rt.builtins-aarch64.a" \ 161 | build-aarch64/lib/windows/libclang_rt.builtins-aarch64.a \ 162 | build-arm64ec/lib/windows/libclang_rt.builtins-arm64ec.a 163 | fi 164 | done 165 | 166 | if [ "$INSTALL_PREFIX" != "$CLANG_RESOURCE_DIR" ]; then 167 | # symlink to system headers - skip copy 168 | rm -rf "$INSTALL_PREFIX/include" 169 | 170 | cp -r "$INSTALL_PREFIX/." $CLANG_RESOURCE_DIR 171 | fi 172 | -------------------------------------------------------------------------------- /build-cross-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | while [ $# -gt 0 ]; do 20 | case "$1" in 21 | --with-python) 22 | PYTHON=1 23 | ;; 24 | --disable-lldb) 25 | LLVM_ARGS="$LLVM_ARGS $1" 26 | NO_LLDB=1 27 | ;; 28 | --disable-lldb-mi) 29 | NO_LLDB_MI=1 30 | ;; 31 | --disable-clang-tools-extra) 32 | LLVM_ARGS="$LLVM_ARGS $1" 33 | ;; 34 | --no-llvm-tool-reuse) 35 | LLVM_ARGS="$LLVM_ARGS $1" 36 | ;; 37 | --disable-mingw-w64-tools) 38 | NO_MINGW_W64_TOOLS=1 39 | ;; 40 | --full-llvm) 41 | LLVM_ARGS="$LLVM_ARGS $1" 42 | FULL_LLVM=1 43 | ;; 44 | --disable-make) 45 | NO_MAKE=1 46 | ;; 47 | *) 48 | if [ -z "$NATIVE" ]; then 49 | NATIVE="$1" 50 | elif [ -z "$PREFIX" ]; then 51 | PREFIX="$1" 52 | elif [ -z "$CROSS_ARCH" ]; then 53 | CROSS_ARCH="$1" 54 | else 55 | echo Unrecognized parameter $1 56 | exit 1 57 | fi 58 | ;; 59 | esac 60 | shift 61 | done 62 | if [ -z "$CROSS_ARCH" ]; then 63 | echo $0 native prefix arch [--with-python] [--disable-lldb] [--disable-lldb-mi] [--disable-clang-tool-extra] [--disable-mingw-w64-tools] [--disable-make] 64 | exit 1 65 | fi 66 | 67 | for dep in git curl cmake; do 68 | if ! command -v $dep >/dev/null; then 69 | echo "$dep not installed. Please install it and retry" 1>&2 70 | exit 1 71 | fi 72 | done 73 | 74 | export PATH="$NATIVE/bin:$PATH" 75 | HOST=$CROSS_ARCH-w64-mingw32 76 | 77 | if [ -n "$PYTHON" ]; then 78 | PYTHON_NATIVE_PREFIX="$(cd "$(dirname "$0")" && pwd)/python-native" 79 | [ -d "$PYTHON_NATIVE_PREFIX" ] || rm -rf "$PYTHON_NATIVE_PREFIX" 80 | ./build-python.sh $PYTHON_NATIVE_PREFIX 81 | export PATH="$PYTHON_NATIVE_PREFIX/bin:$PATH" 82 | ./build-python.sh $PREFIX/python --host=$HOST 83 | mkdir -p $PREFIX/bin 84 | cp $PREFIX/python/bin/*.dll $PREFIX/bin 85 | LLVM_ARGS="$LLVM_ARGS --with-python" 86 | fi 87 | 88 | ./build-llvm.sh $PREFIX --host=$HOST $LLVM_ARGS 89 | if [ -z "$NO_LLDB" ] && [ -z "$NO_LLDB_MI" ]; then 90 | ./build-lldb-mi.sh $PREFIX --host=$HOST 91 | fi 92 | if [ -z "$FULL_LLVM" ]; then 93 | ./strip-llvm.sh $PREFIX --host=$HOST 94 | fi 95 | if [ -z "$NO_MINGW_W64_TOOLS" ]; then 96 | ./build-mingw-w64-tools.sh $PREFIX --skip-include-triplet-prefix --host=$HOST 97 | fi 98 | ./install-wrappers.sh $PREFIX --host=$HOST 99 | ./prepare-cross-toolchain.sh $NATIVE $PREFIX $CROSS_ARCH 100 | if [ -z "$NO_MAKE" ]; then 101 | ./build-make.sh $PREFIX --host=$HOST 102 | fi 103 | -------------------------------------------------------------------------------- /build-libcxx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | BUILD_STATIC=ON 20 | BUILD_SHARED=ON 21 | CFGUARD_CFLAGS="-mguard=cf" 22 | 23 | while [ $# -gt 0 ]; do 24 | if [ "$1" = "--disable-shared" ]; then 25 | BUILD_SHARED=OFF 26 | elif [ "$1" = "--enable-shared" ]; then 27 | BUILD_SHARED=ON 28 | elif [ "$1" = "--disable-static" ]; then 29 | BUILD_STATIC=OFF 30 | elif [ "$1" = "--enable-static" ]; then 31 | BUILD_STATIC=ON 32 | elif [ "$1" = "--enable-cfguard" ]; then 33 | CFGUARD_CFLAGS="-mguard=cf" 34 | elif [ "$1" = "--disable-cfguard" ]; then 35 | CFGUARD_CFLAGS= 36 | else 37 | PREFIX="$1" 38 | fi 39 | shift 40 | done 41 | if [ -z "$PREFIX" ]; then 42 | echo "$0 [--disable-shared] [--disable-static] [--enable-cfguard|--disable-cfguard] dest" 43 | exit 1 44 | fi 45 | 46 | mkdir -p "$PREFIX" 47 | PREFIX="$(cd "$PREFIX" && pwd)" 48 | 49 | export PATH="$PREFIX/bin:$PATH" 50 | 51 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 52 | 53 | if [ ! -d llvm-project/libunwind ] || [ -n "$SYNC" ]; then 54 | CHECKOUT_ONLY=1 ./build-llvm.sh 55 | fi 56 | 57 | cd llvm-project 58 | 59 | cd runtimes 60 | 61 | if command -v ninja >/dev/null; then 62 | CMAKE_GENERATOR="Ninja" 63 | else 64 | : ${CORES:=$(nproc 2>/dev/null)} 65 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 66 | : ${CORES:=4} 67 | 68 | case $(uname) in 69 | MINGW*) 70 | CMAKE_GENERATOR="MSYS Makefiles" 71 | ;; 72 | esac 73 | fi 74 | 75 | for arch in $ARCHS; do 76 | [ -z "$CLEAN" ] || rm -rf build-$arch 77 | mkdir -p build-$arch 78 | cd build-$arch 79 | [ -n "$NO_RECONF" ] || rm -rf CMake* 80 | cmake \ 81 | ${CMAKE_GENERATOR+-G} "$CMAKE_GENERATOR" \ 82 | -DCMAKE_BUILD_TYPE=Release \ 83 | -DCMAKE_INSTALL_PREFIX="$PREFIX/$arch-w64-mingw32" \ 84 | -DCMAKE_C_COMPILER=$arch-w64-mingw32-clang \ 85 | -DCMAKE_CXX_COMPILER=$arch-w64-mingw32-clang++ \ 86 | -DCMAKE_CXX_COMPILER_TARGET=$arch-w64-windows-gnu \ 87 | -DCMAKE_SYSTEM_NAME=Windows \ 88 | -DCMAKE_C_COMPILER_WORKS=TRUE \ 89 | -DCMAKE_CXX_COMPILER_WORKS=TRUE \ 90 | -DCMAKE_AR="$PREFIX/bin/llvm-ar" \ 91 | -DCMAKE_RANLIB="$PREFIX/bin/llvm-ranlib" \ 92 | -DLLVM_ENABLE_RUNTIMES="libunwind;libcxxabi;libcxx" \ 93 | -DLIBUNWIND_USE_COMPILER_RT=TRUE \ 94 | -DLIBUNWIND_ENABLE_SHARED=$BUILD_SHARED \ 95 | -DLIBUNWIND_ENABLE_STATIC=$BUILD_STATIC \ 96 | -DLIBCXX_USE_COMPILER_RT=ON \ 97 | -DLIBCXX_ENABLE_SHARED=$BUILD_SHARED \ 98 | -DLIBCXX_ENABLE_STATIC=$BUILD_STATIC \ 99 | -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=TRUE \ 100 | -DLIBCXX_CXX_ABI=libcxxabi \ 101 | -DLIBCXX_LIBDIR_SUFFIX="" \ 102 | -DLIBCXX_INCLUDE_TESTS=FALSE \ 103 | -DLIBCXX_INSTALL_MODULES=ON \ 104 | -DLIBCXX_INSTALL_MODULES_DIR="$PREFIX/share/libc++/v1" \ 105 | -DLIBCXX_ENABLE_ABI_LINKER_SCRIPT=FALSE \ 106 | -DLIBCXXABI_USE_COMPILER_RT=ON \ 107 | -DLIBCXXABI_USE_LLVM_UNWINDER=ON \ 108 | -DLIBCXXABI_ENABLE_SHARED=OFF \ 109 | -DLIBCXXABI_LIBDIR_SUFFIX="" \ 110 | -DCMAKE_C_FLAGS_INIT="$CFGUARD_CFLAGS" \ 111 | -DCMAKE_CXX_FLAGS_INIT="$CFGUARD_CFLAGS" \ 112 | .. 113 | 114 | cmake --build . ${CORES:+-j${CORES}} 115 | cmake --install . 116 | cd .. 117 | done 118 | -------------------------------------------------------------------------------- /build-lldb-mi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2020 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | : ${LLDB_MI_VERSION:=f1fea743bf06a99b6e7f74085bd8c8db47999df5} 20 | BUILDDIR=build 21 | unset HOST 22 | 23 | while [ $# -gt 0 ]; do 24 | case "$1" in 25 | --host=*) 26 | HOST="${1#*=}" 27 | ;; 28 | *) 29 | PREFIX="$1" 30 | ;; 31 | esac 32 | shift 33 | done 34 | if [ -z "$PREFIX" ]; then 35 | echo $0 [--host=] dest 36 | exit 1 37 | fi 38 | 39 | mkdir -p "$PREFIX" 40 | PREFIX="$(cd "$PREFIX" && pwd)" 41 | 42 | if [ ! -d lldb-mi ]; then 43 | git clone https://github.com/lldb-tools/lldb-mi.git 44 | CHECKOUT=1 45 | fi 46 | 47 | if [ -n "$SYNC" ] || [ -n "$CHECKOUT" ]; then 48 | cd lldb-mi 49 | [ -z "$SYNC" ] || git fetch 50 | git checkout $LLDB_MI_VERSION 51 | cd .. 52 | fi 53 | 54 | if command -v ninja >/dev/null; then 55 | CMAKE_GENERATOR="Ninja" 56 | else 57 | : ${CORES:=$(nproc 2>/dev/null)} 58 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 59 | : ${CORES:=4} 60 | 61 | case $(uname) in 62 | MINGW*) 63 | CMAKE_GENERATOR="MSYS Makefiles" 64 | ;; 65 | esac 66 | fi 67 | 68 | export LLVM_DIR="$PREFIX" 69 | 70 | # Try to find/guess the builddir under the llvm buildtree next by. 71 | # If LLVM was built without LLVM_INSTALL_TOOLCHAIN_ONLY, and the LLVM 72 | # installation directory hasn't been stripped, we should point the build there. 73 | # But as this isn't necessarily the case, point to the LLVM build directory 74 | # instead (which hopefully hasn't been removed yet). 75 | LLVM_SRC="$(pwd)/llvm-project/llvm" 76 | if [ -d "$LLVM_SRC" ]; then 77 | SUFFIX=${HOST+-}$HOST 78 | for base in build build-asserts; do 79 | if [ -d "$LLVM_SRC/$base$SUFFIX" ]; then 80 | export LLVM_DIR="$LLVM_SRC/$base$SUFFIX" 81 | break 82 | fi 83 | done 84 | fi 85 | 86 | if [ -n "$HOST" ]; then 87 | BUILDDIR=$BUILDDIR-$HOST 88 | 89 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_C_COMPILER=$HOST-gcc" 90 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_CXX_COMPILER=$HOST-g++" 91 | case $HOST in 92 | *-mingw32) 93 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_SYSTEM_NAME=Windows" 94 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_RC_COMPILER=$HOST-windres" 95 | ;; 96 | *-linux*) 97 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_SYSTEM_NAME=Linux" 98 | ;; 99 | *) 100 | echo "Unrecognized host $HOST" 101 | exit 1 102 | ;; 103 | esac 104 | 105 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_FIND_ROOT_PATH=$LLVM_DIR" 106 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER" 107 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY" 108 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY" 109 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY" 110 | fi 111 | 112 | if [ -n "$MACOS_REDIST" ]; then 113 | : ${MACOS_REDIST_ARCHS:=arm64 x86_64} 114 | : ${MACOS_REDIST_VERSION:=10.12} 115 | ARCH_LIST="" 116 | NATIVE= 117 | for arch in $MACOS_REDIST_ARCHS; do 118 | if [ -n "$ARCH_LIST" ]; then 119 | ARCH_LIST="$ARCH_LIST;" 120 | fi 121 | ARCH_LIST="$ARCH_LIST$arch" 122 | if [ "$(uname -m)" = "$arch" ]; then 123 | NATIVE=1 124 | fi 125 | done 126 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_OSX_ARCHITECTURES=$ARCH_LIST" 127 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_OSX_DEPLOYMENT_TARGET=$MACOS_REDIST_VERSION" 128 | if [ -z "$NATIVE" ]; then 129 | # If we're not building for the native arch, flag to CMake that we're 130 | # cross compiling. 131 | CMAKEFLAGS="$CMAKEFLAGS -DCMAKE_SYSTEM_NAME=Darwin" 132 | fi 133 | fi 134 | 135 | cd lldb-mi 136 | 137 | [ -z "$CLEAN" ] || rm -rf $BUILDDIR 138 | mkdir -p $BUILDDIR 139 | cd $BUILDDIR 140 | [ -n "$NO_RECONF" ] || rm -rf CMake* 141 | cmake \ 142 | ${CMAKE_GENERATOR+-G} "$CMAKE_GENERATOR" \ 143 | -DCMAKE_INSTALL_PREFIX="$PREFIX" \ 144 | -DCMAKE_BUILD_TYPE=Release \ 145 | $CMAKEFLAGS \ 146 | .. 147 | 148 | cmake --build . ${CORES:+-j${CORES}} 149 | cmake --install . --strip 150 | -------------------------------------------------------------------------------- /build-make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | unset HOST 20 | 21 | : ${MAKE_VERSION:=4.4.1} 22 | 23 | while [ $# -gt 0 ]; do 24 | case "$1" in 25 | --host=*) 26 | HOST="${1#*=}" 27 | ;; 28 | *) 29 | PREFIX="$1" 30 | ;; 31 | esac 32 | shift 33 | done 34 | if [ -z "$PREFIX" ]; then 35 | echo $0 [--host=triple] dest 36 | exit 1 37 | fi 38 | 39 | mkdir -p "$PREFIX" 40 | PREFIX="$(cd "$PREFIX" && pwd)" 41 | 42 | : ${CORES:=$(nproc 2>/dev/null)} 43 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 44 | : ${CORES:=4} 45 | 46 | download() { 47 | if command -v curl >/dev/null; then 48 | curl -LO "$1" 49 | else 50 | wget "$1" 51 | fi 52 | } 53 | 54 | if [ ! -d make-$MAKE_VERSION ]; then 55 | download https://ftp.gnu.org/gnu/make/make-$MAKE_VERSION.tar.gz 56 | tar -zxf make-$MAKE_VERSION.tar.gz 57 | fi 58 | 59 | cd make-$MAKE_VERSION 60 | 61 | if [ -n "$HOST" ]; then 62 | CONFIGFLAGS="$CONFIGFLAGS --host=$HOST" 63 | CROSS_NAME=-$HOST 64 | fi 65 | 66 | [ -z "$CLEAN" ] || rm -rf build$CROSS_NAME 67 | mkdir -p build$CROSS_NAME 68 | cd build$CROSS_NAME 69 | ../configure --prefix="$PREFIX" $CONFIGFLAGS --program-prefix=mingw32- --enable-job-server LDFLAGS="-Wl,-s" 70 | make -j$CORES 71 | make install-binPROGRAMS 72 | -------------------------------------------------------------------------------- /build-mingw-w64-libraries.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | USE_CFLAGS="-g -O2 -mguard=cf" 20 | 21 | while [ $# -gt 0 ]; do 22 | case "$1" in 23 | --enable-cfguard) 24 | USE_CFLAGS="-g -O2 -mguard=cf" 25 | ;; 26 | --disable-cfguard) 27 | USE_CFLAGS="-g -O2" 28 | ;; 29 | *) 30 | PREFIX="$1" 31 | ;; 32 | esac 33 | shift 34 | done 35 | if [ -z "$PREFIX" ]; then 36 | echo "$0 [--enable-cfguard|--disable-cfguard] dest" 37 | exit 1 38 | fi 39 | mkdir -p "$PREFIX" 40 | PREFIX="$(cd "$PREFIX" && pwd)" 41 | export PATH="$PREFIX/bin:$PATH" 42 | unset CC 43 | 44 | : ${CORES:=$(nproc 2>/dev/null)} 45 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 46 | : ${CORES:=4} 47 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 48 | 49 | if [ ! -d mingw-w64 ] || [ -n "$SYNC" ]; then 50 | CHECKOUT_ONLY=1 ./build-mingw-w64.sh 51 | fi 52 | 53 | MAKE=make 54 | if command -v gmake >/dev/null; then 55 | MAKE=gmake 56 | fi 57 | 58 | cd mingw-w64/mingw-w64-libraries 59 | for lib in winpthreads winstorecompat; do 60 | cd $lib 61 | for arch in $ARCHS; do 62 | [ -z "$CLEAN" ] || rm -rf build-$arch 63 | mkdir -p build-$arch 64 | cd build-$arch 65 | arch_prefix="$PREFIX/$arch-w64-mingw32" 66 | ../configure --host=$arch-w64-mingw32 --prefix="$arch_prefix" --libdir="$arch_prefix/lib" \ 67 | --enable-silent-rules \ 68 | CFLAGS="$USE_CFLAGS" \ 69 | CXXFLAGS="$USE_CFLAGS" 70 | $MAKE -j$CORES 71 | $MAKE install 72 | cd .. 73 | mkdir -p "$arch_prefix/share/mingw32" 74 | install -m644 COPYING "$arch_prefix/share/mingw32/COPYING.${lib}.txt" 75 | done 76 | cd .. 77 | done 78 | -------------------------------------------------------------------------------- /build-mingw-w64-tools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | unset HOST 20 | 21 | while [ $# -gt 0 ]; do 22 | case "$1" in 23 | --skip-include-triplet-prefix) 24 | SKIP_INCLUDE_TRIPLET_PREFIX=1 25 | ;; 26 | --host=*) 27 | HOST="${1#*=}" 28 | ;; 29 | *) 30 | PREFIX="$1" 31 | ;; 32 | esac 33 | shift 34 | done 35 | if [ -z "$CHECKOUT_ONLY" ]; then 36 | if [ -z "$PREFIX" ]; then 37 | echo $0 [--skip-include-triplet-prefix] [--host=triple] dest 38 | exit 1 39 | fi 40 | 41 | mkdir -p "$PREFIX" 42 | PREFIX="$(cd "$PREFIX" && pwd)" 43 | fi 44 | 45 | if [ ! -d mingw-w64 ] || [ -n "$SYNC" ]; then 46 | CHECKOUT_ONLY=1 ./build-mingw-w64.sh 47 | fi 48 | 49 | cd mingw-w64 50 | 51 | MAKE=make 52 | if command -v gmake >/dev/null; then 53 | MAKE=gmake 54 | fi 55 | 56 | : ${CORES:=$(nproc 2>/dev/null)} 57 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 58 | : ${CORES:=4} 59 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 60 | : ${TARGET_OSES:=${TOOLCHAIN_TARGET_OSES-mingw32 mingw32uwp}} 61 | 62 | if [ -n "$HOST" ]; then 63 | CONFIGFLAGS="$CONFIGFLAGS --host=$HOST" 64 | CROSS_NAME=-$HOST 65 | case $HOST in 66 | *-mingw32) 67 | EXEEXT=.exe 68 | ;; 69 | esac 70 | else 71 | case $(uname) in 72 | MINGW*) 73 | EXEEXT=.exe 74 | ;; 75 | esac 76 | fi 77 | if [ -n "$MACOS_REDIST" ]; then 78 | if [ -z "$CFLAGS" ]; then 79 | CFLAGS="-g -O2" 80 | fi 81 | : ${MACOS_REDIST_ARCHS:=arm64 x86_64} 82 | : ${MACOS_REDIST_VERSION:=10.12} 83 | NONNATIVE_ARCH= 84 | for arch in $MACOS_REDIST_ARCHS; do 85 | CFLAGS="$CFLAGS -arch $arch" 86 | if [ "$(uname -m)" != "$arch" ]; then 87 | case $arch in 88 | arm64) NONNATIVE_ARCH=aarch64 ;; 89 | *) NONNATIVE_ARCH=$arch ;; 90 | esac 91 | fi 92 | done 93 | if [ -n "$NONNATIVE_ARCH" ]; then 94 | # If we're not building for the native arch, flag that we're 95 | # cross compiling. 96 | CONFIGFLAGS="$CONFIGFLAGS --host=$NONNATIVE_ARCH-apple-darwin" 97 | fi 98 | export CFLAGS="$CFLAGS -mmacosx-version-min=$MACOS_REDIST_VERSION" 99 | fi 100 | if [ -n "$SKIP_INCLUDE_TRIPLET_PREFIX" ]; then 101 | INCLUDEDIR="$PREFIX/include" 102 | else 103 | INCLUDEDIR="$PREFIX/generic-w64-mingw32/include" 104 | fi 105 | ANY_ARCH=$(echo $ARCHS | awk '{print $1}') 106 | 107 | CONFIGFLAGS="$CONFIGFLAGS --enable-silent-rules" 108 | 109 | cd mingw-w64-tools/gendef 110 | [ -z "$CLEAN" ] || rm -rf build${CROSS_NAME} 111 | mkdir -p build${CROSS_NAME} 112 | cd build${CROSS_NAME} 113 | ../configure --prefix="$PREFIX" $CONFIGFLAGS 114 | $MAKE -j$CORES 115 | $MAKE install-strip 116 | mkdir -p "$PREFIX/share/gendef" 117 | install -m644 ../COPYING "$PREFIX/share/gendef" 118 | cd ../../widl 119 | [ -z "$CLEAN" ] || rm -rf build${CROSS_NAME} 120 | mkdir -p build${CROSS_NAME} 121 | cd build${CROSS_NAME} 122 | ../configure --prefix="$PREFIX" --target=$ANY_ARCH-w64-mingw32 --with-widl-includedir="$INCLUDEDIR" $CONFIGFLAGS 123 | $MAKE -j$CORES 124 | $MAKE install-strip 125 | mkdir -p "$PREFIX/share/widl" 126 | install -m644 ../../../COPYING "$PREFIX/share/widl" 127 | cd .. 128 | cd "$PREFIX/bin" 129 | # The build above produced $ANY_ARCH-w64-mingw32-widl, add symlinks to it 130 | # with other prefixes. 131 | for arch in $ARCHS; do 132 | for target_os in $TARGET_OSES; do 133 | if [ "$arch" != "$ANY_ARCH" ] || [ "$target_os" != "mingw32" ]; then 134 | ln -sf $ANY_ARCH-w64-mingw32-widl$EXEEXT $arch-w64-$target_os-widl$EXEEXT 135 | fi 136 | done 137 | done 138 | if [ -n "$EXEEXT" ]; then 139 | # In a build of the tools for windows, we also want to provide an 140 | # unprefixed one. If crosscompiling, we know what the native arch is; 141 | # $HOST. If building natively, check the built clang to see what the 142 | # default arch is. 143 | if [ -z "$HOST" ] && [ -f clang$EXEEXT ]; then 144 | HOST=$(./clang -dumpmachine | sed 's/-.*//')-w64-mingw32 145 | fi 146 | if [ -n "$HOST" ]; then 147 | HOST_ARCH="${HOST%%-*}" 148 | # Only install an unprefixed symlink if $HOST is one of the architectures 149 | # we are installing wrappers for. 150 | case $ARCHS in 151 | *$HOST_ARCH*) 152 | ln -sf $HOST-widl$EXEEXT widl$EXEEXT 153 | ;; 154 | esac 155 | fi 156 | fi 157 | -------------------------------------------------------------------------------- /build-mingw-w64.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | : ${DEFAULT_WIN32_WINNT:=0x601} 20 | : ${DEFAULT_MSVCRT:=ucrt} 21 | : ${MINGW_W64_VERSION:=c3b5e71d54aa596bba9fb8ec7c1f9f712e7c616a} 22 | 23 | CFGUARD_FLAGS="--enable-cfguard" 24 | 25 | while [ $# -gt 0 ]; do 26 | case "$1" in 27 | --skip-include-triplet-prefix) 28 | SKIP_INCLUDE_TRIPLET_PREFIX=1 29 | ;; 30 | --with-default-win32-winnt=*) 31 | DEFAULT_WIN32_WINNT="${1#*=}" 32 | ;; 33 | --with-default-msvcrt=*) 34 | DEFAULT_MSVCRT="${1#*=}" 35 | ;; 36 | --enable-cfguard) 37 | CFGUARD_FLAGS="--enable-cfguard" 38 | ;; 39 | --disable-cfguard) 40 | CFGUARD_FLAGS= 41 | ;; 42 | *) 43 | PREFIX="$1" 44 | ;; 45 | esac 46 | shift 47 | done 48 | if [ -z "$CHECKOUT_ONLY" ]; then 49 | if [ -z "$PREFIX" ]; then 50 | echo "$0 [--skip-include-triplet-prefix] [--with-default-win32-winnt=0x601] [--with-default-msvcrt=ucrt] [--enable-cfguard|--disable-cfguard] dest" 51 | exit 1 52 | fi 53 | 54 | mkdir -p "$PREFIX" 55 | PREFIX="$(cd "$PREFIX" && pwd)" 56 | fi 57 | 58 | if [ ! -d mingw-w64 ]; then 59 | git clone https://github.com/mingw-w64/mingw-w64 60 | CHECKOUT=1 61 | fi 62 | 63 | cd mingw-w64 64 | 65 | if [ -n "$SYNC" ] || [ -n "$CHECKOUT" ]; then 66 | [ -z "$SYNC" ] || git fetch 67 | git checkout $MINGW_W64_VERSION 68 | fi 69 | 70 | [ -z "$CHECKOUT_ONLY" ] || exit 0 71 | 72 | MAKE=make 73 | if command -v gmake >/dev/null; then 74 | MAKE=gmake 75 | fi 76 | 77 | case $(uname) in 78 | MINGW*|MSYS*|CYGWIN*) 79 | CRT_CONFIG_FLAGS="--disable-dependency-tracking" 80 | ;; 81 | esac 82 | 83 | export PATH="$PREFIX/bin:$PATH" 84 | 85 | unset CC 86 | 87 | : ${CORES:=$(nproc 2>/dev/null)} 88 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 89 | : ${CORES:=4} 90 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 91 | 92 | if [ -z "$SKIP_INCLUDE_TRIPLET_PREFIX" ]; then 93 | HEADER_ROOT="$PREFIX/generic-w64-mingw32" 94 | else 95 | HEADER_ROOT="$PREFIX" 96 | fi 97 | 98 | cd mingw-w64-headers 99 | [ -z "$CLEAN" ] || rm -rf build 100 | mkdir -p build 101 | cd build 102 | ../configure --prefix="$HEADER_ROOT" \ 103 | --enable-idl --with-default-win32-winnt=$DEFAULT_WIN32_WINNT --with-default-msvcrt=$DEFAULT_MSVCRT INSTALL="install -C" 104 | $MAKE install 105 | cd ../.. 106 | if [ -z "$SKIP_INCLUDE_TRIPLET_PREFIX" ]; then 107 | for arch in $ARCHS; do 108 | mkdir -p "$PREFIX/$arch-w64-mingw32" 109 | if [ ! -e "$PREFIX/$arch-w64-mingw32/include" ]; then 110 | ln -sfn ../generic-w64-mingw32/include "$PREFIX/$arch-w64-mingw32/include" 111 | fi 112 | done 113 | fi 114 | 115 | cd mingw-w64-crt 116 | for arch in $ARCHS; do 117 | [ -z "$CLEAN" ] || rm -rf build-$arch 118 | mkdir -p build-$arch 119 | cd build-$arch 120 | case $arch in 121 | armv7) 122 | FLAGS="--disable-lib32 --disable-lib64 --enable-libarm32" 123 | ;; 124 | aarch64|arm64ec) 125 | FLAGS="--disable-lib32 --disable-lib64 --enable-libarm64" 126 | ;; 127 | i686) 128 | FLAGS="--enable-lib32 --disable-lib64" 129 | ;; 130 | x86_64) 131 | FLAGS="--disable-lib32 --enable-lib64" 132 | ;; 133 | esac 134 | FLAGS="$FLAGS --with-default-msvcrt=$DEFAULT_MSVCRT" 135 | FLAGS="$FLAGS --enable-silent-rules" 136 | ../configure --host=$arch-w64-mingw32 --prefix="$PREFIX/$arch-w64-mingw32" $FLAGS $CFGUARD_FLAGS $CRT_CONFIG_FLAGS 137 | $MAKE -j$CORES 138 | $MAKE install 139 | cd .. 140 | done 141 | cd .. 142 | 143 | for arch in $ARCHS; do 144 | if [ ! -f $PREFIX/$arch-w64-mingw32/lib/libssp.a ]; then 145 | # Create empty dummy archives, to avoid failing when the compiler 146 | # driver adds "-lssp -lssh_nonshared" when linking. 147 | llvm-ar rcs $PREFIX/$arch-w64-mingw32/lib/libssp.a 148 | llvm-ar rcs $PREFIX/$arch-w64-mingw32/lib/libssp_nonshared.a 149 | fi 150 | 151 | mkdir -p "$PREFIX/$arch-w64-mingw32/share/mingw32" 152 | for file in COPYING COPYING.MinGW-w64/COPYING.MinGW-w64.txt COPYING.MinGW-w64-runtime/COPYING.MinGW-w64-runtime.txt; do 153 | install -m644 "$file" "$PREFIX/$arch-w64-mingw32/share/mingw32" 154 | done 155 | done 156 | -------------------------------------------------------------------------------- /build-openmp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2020 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | CFGUARD_CFLAGS="-mguard=cf" 20 | 21 | while [ $# -gt 0 ]; do 22 | case "$1" in 23 | --enable-cfguard) 24 | CFGUARD_CFLAGS="-mguard=cf" 25 | ;; 26 | --disable-cfguard) 27 | CFGUARD_CFLAGS= 28 | ;; 29 | *) 30 | PREFIX="$1" 31 | ;; 32 | esac 33 | shift 34 | done 35 | if [ -z "$PREFIX" ]; then 36 | echo "$0 [--enable-cfguard|--disable-cfguard] dest" 37 | exit 1 38 | fi 39 | 40 | mkdir -p "$PREFIX" 41 | PREFIX="$(cd "$PREFIX" && pwd)" 42 | 43 | export PATH="$PREFIX/bin:$PATH" 44 | 45 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 46 | 47 | if [ ! -d llvm-project/openmp ] || [ -n "$SYNC" ]; then 48 | CHECKOUT_ONLY=1 ./build-llvm.sh 49 | fi 50 | 51 | cd llvm-project/openmp 52 | 53 | if command -v ninja >/dev/null; then 54 | CMAKE_GENERATOR="Ninja" 55 | else 56 | : ${CORES:=$(nproc 2>/dev/null)} 57 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 58 | : ${CORES:=4} 59 | 60 | case $(uname) in 61 | MINGW*) 62 | CMAKE_GENERATOR="MSYS Makefiles" 63 | ;; 64 | esac 65 | fi 66 | 67 | for arch in $ARCHS; do 68 | CMAKEFLAGS="" 69 | case $arch in 70 | x86_64) 71 | CMAKEFLAGS="$CMAKEFLAGS -DLIBOMP_ASMFLAGS=-m64" 72 | ;; 73 | arm64ec) 74 | # Not yet supported 75 | continue 76 | ;; 77 | esac 78 | 79 | [ -z "$CLEAN" ] || rm -rf build-$arch 80 | mkdir -p build-$arch 81 | cd build-$arch 82 | [ -n "$NO_RECONF" ] || rm -rf CMake* 83 | 84 | cmake \ 85 | ${CMAKE_GENERATOR+-G} "$CMAKE_GENERATOR" \ 86 | -DCMAKE_BUILD_TYPE=Release \ 87 | -DCMAKE_INSTALL_PREFIX="$PREFIX/$arch-w64-mingw32" \ 88 | -DCMAKE_C_COMPILER=$arch-w64-mingw32-clang \ 89 | -DCMAKE_CXX_COMPILER=$arch-w64-mingw32-clang++ \ 90 | -DCMAKE_RC_COMPILER=$arch-w64-mingw32-windres \ 91 | -DCMAKE_ASM_MASM_COMPILER=llvm-ml \ 92 | -DCMAKE_SYSTEM_NAME=Windows \ 93 | -DCMAKE_AR="$PREFIX/bin/llvm-ar" \ 94 | -DCMAKE_RANLIB="$PREFIX/bin/llvm-ranlib" \ 95 | -DLIBOMP_ENABLE_SHARED=TRUE \ 96 | -DCMAKE_C_FLAGS_INIT="$CFGUARD_CFLAGS" \ 97 | -DCMAKE_CXX_FLAGS_INIT="$CFGUARD_CFLAGS" \ 98 | $CMAKEFLAGS \ 99 | .. 100 | cmake --build . ${CORES:+-j${CORES}} 101 | cmake --install . 102 | rm -f $PREFIX/$arch-w64-mingw32/bin/*iomp5md* 103 | rm -f $PREFIX/$arch-w64-mingw32/lib/*iomp5md* 104 | cd .. 105 | done 106 | -------------------------------------------------------------------------------- /build-python.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | : ${LIBFFI_VERSION:=v3.4.7} 20 | : ${PYTHON_VERSION:=v3.12.9} 21 | : ${PYTHON_VERSION_MINGW:=1b241aa8572ee8cd4131fffca838b6bbdf5a7b5e} 22 | 23 | unset HOST 24 | 25 | BUILDDIR=build 26 | 27 | while [ $# -gt 0 ]; do 28 | case "$1" in 29 | --host=*) 30 | HOST="${1#*=}" 31 | BUILDDIR=$BUILDDIR-$HOST 32 | ;; 33 | *) 34 | PREFIX="$1" 35 | ;; 36 | esac 37 | shift 38 | done 39 | 40 | if [ -z "$CHECKOUT_ONLY" ]; then 41 | if [ -z "$PREFIX" ]; then 42 | echo $0 --host=triple dest 43 | exit 1 44 | fi 45 | 46 | mkdir -p "$PREFIX" 47 | PREFIX="$(cd "$PREFIX" && pwd)" 48 | fi 49 | 50 | MAKE=make 51 | if command -v gmake >/dev/null; then 52 | MAKE=gmake 53 | fi 54 | 55 | : ${CORES:=$(nproc 2>/dev/null)} 56 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 57 | : ${CORES:=4} 58 | 59 | if [ ! -d libffi ]; then 60 | git clone https://github.com/libffi/libffi.git 61 | CHECKOUT_LIBFFI=1 62 | fi 63 | 64 | if [ -n "$SYNC" ] || [ -n "$CHECKOUT_LIBFFI" ]; then 65 | cd libffi 66 | [ -z "$SYNC" ] || git fetch 67 | git reset --hard 68 | git checkout $LIBFFI_VERSION 69 | autoreconf -vfi 70 | cd .. 71 | fi 72 | 73 | if [ -z "$HOST" ]; then 74 | # Use a separate checkout for python for the native build; 75 | # mingw builds use a separate fork, maintained by msys2 76 | # which doesn't build on regular Unix 77 | if [ ! -d cpython-native ]; then 78 | git clone https://github.com/python/cpython.git cpython-native 79 | CHECKOUT_PYTHON_NATIVE=1 80 | fi 81 | 82 | if [ -n "$SYNC" ] || [ -n "$CHECKOUT_PYTHON_NATIVE" ]; then 83 | cd cpython-native 84 | [ -z "$SYNC" ] || git fetch 85 | git checkout $PYTHON_VERSION 86 | cd .. 87 | fi 88 | 89 | [ -z "$CHECKOUT_ONLY" ] || exit 0 90 | 91 | cd libffi 92 | [ -z "$CLEAN" ] || rm -rf $BUILDDIR 93 | mkdir -p $BUILDDIR 94 | cd $BUILDDIR 95 | ../configure --prefix="$PREFIX" --disable-symvers --disable-docs 96 | $MAKE -j$CORES 97 | $MAKE install 98 | cd ../.. 99 | 100 | cd cpython-native 101 | [ -z "$CLEAN" ] || rm -rf $BUILDDIR 102 | mkdir -p $BUILDDIR 103 | cd $BUILDDIR 104 | ../configure --prefix="$PREFIX" \ 105 | CFLAGS="-I$PREFIX/include" CXXFLAGS="-I$PREFIX/include" LDFLAGS="-L$PREFIX/lib -Wl,-s" \ 106 | --without-ensurepip \ 107 | --disable-test-modules 108 | $MAKE -j$CORES 109 | $MAKE install 110 | exit 0 111 | fi 112 | 113 | # Fetching 114 | if [ ! -d cpython-mingw ]; then 115 | git clone https://github.com/msys2-contrib/cpython-mingw.git 116 | CHECKOUT_PYTHON=1 117 | fi 118 | 119 | if [ -n "$SYNC" ] || [ -n "$CHECKOUT_PYTHON" ]; then 120 | cd cpython-mingw 121 | [ -z "$SYNC" ] || git fetch 122 | git reset --hard 123 | git checkout $PYTHON_VERSION_MINGW 124 | autoreconf -vfi 125 | cd .. 126 | fi 127 | 128 | [ -z "$CHECKOUT_ONLY" ] || exit 0 129 | 130 | cd libffi 131 | [ -z "$CLEAN" ] || rm -rf $BUILDDIR 132 | mkdir -p $BUILDDIR 133 | cd $BUILDDIR 134 | ../configure --prefix="$PREFIX" --host=$HOST --disable-symvers --disable-docs 135 | $MAKE -j$CORES 136 | $MAKE install 137 | cd ../.. 138 | 139 | cd cpython-mingw 140 | [ -z "$CLEAN" ] || rm -rf $BUILDDIR 141 | mkdir -p $BUILDDIR 142 | cd $BUILDDIR 143 | BUILD=$(../config.guess) # Python configure requires build triplet for cross compilation 144 | # Locate the native python3 that we've built before, from the path 145 | NATIVE_PYTHON="$(command -v python3)" 146 | 147 | export CC=$HOST-gcc 148 | export CXX=$HOST-g++ 149 | 150 | ../configure --prefix="$PREFIX" --build=$BUILD --host=$HOST \ 151 | CFLAGS="-I$PREFIX/include" CXXFLAGS="-I$PREFIX/include" LDFLAGS="-L$PREFIX/lib -Wl,-s" \ 152 | PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ 153 | --with-build-python="$NATIVE_PYTHON" \ 154 | --enable-shared \ 155 | --with-system-ffi \ 156 | --without-ensurepip \ 157 | --without-c-locale-coercion \ 158 | --disable-test-modules 159 | 160 | $MAKE -j$CORES 161 | $MAKE install 162 | find $PREFIX/lib/python* -name __pycache__ | xargs rm -rf 163 | 164 | # Provide a versionless executable as well; msys2 does something similar 165 | # (for python3, python3w, python3-config, idle3 and pydoc3) after installing 166 | # a Python version that is supposed to be the primary Python. 167 | cp -a $PREFIX/bin/python3.exe $PREFIX/bin/python.exe 168 | 169 | cd ../.. 170 | -------------------------------------------------------------------------------- /copy-msys-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2023 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | while [ $# -gt 0 ]; do 20 | if [ -z "$PREFIX" ]; then 21 | PREFIX="$1" 22 | elif [ -z "$MSYS_ENV" ]; then 23 | MSYS_ENV="$1" 24 | else 25 | echo Unrecognized parameter $1 26 | exit 1 27 | fi 28 | shift 29 | done 30 | if [ -z "$MSYS_ENV" ]; then 31 | echo $0 prefix msys_env 32 | exit 1 33 | fi 34 | 35 | cd $PREFIX/bin 36 | for i in ld.lld.exe clang-*.exe lldb.exe; do 37 | if [ ! -f "$i" ]; then 38 | continue 39 | fi 40 | for f in $(ldd "$i" | grep /$MSYS_ENV | awk '{print $3}'); do 41 | if [ ! -f "$(basename $f)" ]; then 42 | echo Copying $f 43 | cp $f . 44 | fi 45 | done 46 | done 47 | -------------------------------------------------------------------------------- /extract-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | if [ $# -lt 2 ]; then 18 | echo $0 image dir 19 | echo 20 | echo This extracts \'dir\' from the docker image named \'image\' into the 21 | echo current directory. NOTE: This removes the existing directory named 22 | echo \'dir\' first. 23 | exit 1 24 | fi 25 | 26 | image=$1 27 | dir=$2 28 | 29 | rm -rf $(echo $dir | sed 's,^/,,') 30 | docker run --rm $image tar -cf - $dir | tar -xvf - 31 | -------------------------------------------------------------------------------- /install-wrappers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | unset HOST 20 | unset HOST_CLANG 21 | 22 | while [ $# -gt 0 ]; do 23 | case "$1" in 24 | --host-clang|--host-clang=*) 25 | HOST_CLANG=${1#--host-clang} 26 | HOST_CLANG=${HOST_CLANG#=} 27 | HOST_CLANG=${HOST_CLANG:-clang} 28 | ;; 29 | --host=*) 30 | HOST="${1#*=}" 31 | ;; 32 | *) 33 | PREFIX="$1" 34 | ;; 35 | esac 36 | shift 37 | done 38 | if [ -z "$PREFIX" ]; then 39 | echo $0 [--host=triple] [--host-clang[=clang]] dest 40 | exit 1 41 | fi 42 | mkdir -p "$PREFIX" 43 | PREFIX="$(cd "$PREFIX" && pwd)" 44 | 45 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 46 | : ${TARGET_OSES:=${TOOLCHAIN_TARGET_OSES-mingw32 mingw32uwp}} 47 | 48 | if [ -n "$HOST" ] && [ -z "$CC" ]; then 49 | CC=$HOST-gcc 50 | fi 51 | : ${CC:=cc} 52 | 53 | if [ -n "$HOST" ]; then 54 | case $HOST in 55 | *-mingw32) 56 | EXEEXT=.exe 57 | ;; 58 | esac 59 | else 60 | case $(uname) in 61 | MINGW*) 62 | EXEEXT=.exe 63 | ;; 64 | esac 65 | fi 66 | 67 | if [ -n "${HOST_CLANG}" ]; then 68 | HOST_CLANG_EXE=$(command -v $HOST_CLANG) 69 | HOST_CLANG_VER=$(echo "__clang_major__ __clang_minor__ __clang_patchlevel__" | $HOST_CLANG_EXE -E -P -x c - | xargs printf '%d.%d.%d') 70 | 71 | mkdir -p $PREFIX/bin 72 | 73 | # ex. /usr/lib/llvm-17/lib/clang/17 74 | resdir=$($HOST_CLANG -print-resource-dir) 75 | # ex. /usr/lib/llvm-17 76 | llvmdir=${resdir%/lib/clang/*} 77 | # ex /lib/clang/17 78 | clangres=${resdir#$llvmdir} 79 | 80 | mkdir -p $PREFIX$clangres 81 | 82 | # link the header directory, prevent modification 83 | ln -snf $resdir/include $PREFIX$clangres/include 84 | 85 | # Note: clang will detect the "InstalledDir" based on the path that was used to invoke the tools 86 | # This might still have some hidden effects 87 | printf '#!/bin/sh\nsr=$(dirname "$(dirname "$(readlink -f "$0")")")\nexec %s -resource-dir="$sr"%s --sysroot="$sr" --config-system-dir="$sr"/bin "$@"\n' "$HOST_CLANG_EXE" "$clangres" > $PREFIX/bin/clang 88 | # printf '#!/bin/sh\nsr=$(dirname "$(dirname "$(readlink -f "$0")")")\nexec %s -resource-dir="$sr"%s --sysroot="$sr" "$@"\n' "$(readlink -f "$HOST_CLANG_EXE")" "$clangres" > $PREFIX/bin/clang 89 | chmod 755 $PREFIX/bin/clang 90 | ln -sf clang $PREFIX/bin/clang++ 91 | ln -sf clang $PREFIX/bin/clang-cpp 92 | 93 | echo "Using existing clang $HOST_CLANG_EXE ($HOST_CLANG_VER)" 94 | $PREFIX/bin/clang -v 95 | 96 | # prefer system llvm installation, but search in llvm private paths (eg. debian does not symlink all tools into /usr/bin) 97 | llvmexec="$PATH:$llvmdir/bin" 98 | 99 | for exec in ld.lld llvm-ar llvm-ranlib llvm-nm llvm-objcopy llvm-strip llvm-rc llvm-cvtres \ 100 | llvm-addr2line llvm-dlltool llvm-readelf llvm-size llvm-strings llvm-addr2line llvm-windres llvm-ml llvm-lib; do 101 | execpath=$(PATH=$llvmexec command -v $exec) && ln -sf $execpath $PREFIX/bin/$exec 102 | done 103 | fi 104 | 105 | if [ -n "$MACOS_REDIST" ]; then 106 | : ${MACOS_REDIST_ARCHS:=arm64 x86_64} 107 | : ${MACOS_REDIST_VERSION:=10.12} 108 | for arch in $MACOS_REDIST_ARCHS; do 109 | WRAPPER_FLAGS="$WRAPPER_FLAGS -arch $arch" 110 | done 111 | WRAPPER_FLAGS="$WRAPPER_FLAGS -mmacosx-version-min=$MACOS_REDIST_VERSION" 112 | fi 113 | 114 | if [ -n "$EXEEXT" ]; then 115 | CLANG_MAJOR=$(basename $(echo $PREFIX/lib/clang/* | awk '{print $NF}') | cut -f 1 -d .) 116 | WRAPPER_FLAGS="$WRAPPER_FLAGS -municode -DCLANG=\"clang-$CLANG_MAJOR\"" 117 | WRAPPER_FLAGS="$WRAPPER_FLAGS -DCLANG_SCAN_DEPS=\"clang-scan-deps-real\"" 118 | # The wrappers may use printf, but doesn't use anything that specifically 119 | # needs full ansi compliance - prefer leaner binaries by using the CRT 120 | # implementations. 121 | WRAPPER_FLAGS="$WRAPPER_FLAGS -D__USE_MINGW_ANSI_STDIO=0" 122 | fi 123 | 124 | mkdir -p "$PREFIX/bin" 125 | cp wrappers/*-wrapper.sh "$PREFIX/bin" 126 | cp wrappers/mingw32-common.cfg $PREFIX/bin 127 | for arch in $ARCHS; do 128 | cp wrappers/$arch-w64-windows-gnu.cfg $PREFIX/bin 129 | done 130 | if [ -n "$HOST" ] && [ -n "$EXEEXT" ]; then 131 | # TODO: If building natively on msys, pick up the default HOST value from there. 132 | WRAPPER_FLAGS="$WRAPPER_FLAGS -DDEFAULT_TARGET=\"$HOST\"" 133 | for i in wrappers/*-wrapper.sh; do 134 | cat $i | sed 's/^DEFAULT_TARGET=.*/DEFAULT_TARGET='$HOST/ > "$PREFIX/bin/$(basename $i)" 135 | done 136 | fi 137 | $CC wrappers/clang-target-wrapper.c -o "$PREFIX/bin/clang-target-wrapper$EXEEXT" -O2 -Wl,-s $WRAPPER_FLAGS 138 | $CC wrappers/clang-scan-deps-wrapper.c -o "$PREFIX/bin/clang-scan-deps-wrapper$EXEEXT" -O2 -Wl,-s $WRAPPER_FLAGS 139 | $CC wrappers/llvm-wrapper.c -o "$PREFIX/bin/llvm-wrapper$EXEEXT" -O2 -Wl,-s $WRAPPER_FLAGS 140 | if [ -n "$EXEEXT" ]; then 141 | # For Windows, we should prefer the executable wrapper, which also works 142 | # when invoked from outside of MSYS. 143 | CTW_SUFFIX=$EXEEXT 144 | CTW_LINK_SUFFIX=$EXEEXT 145 | CSDW=clang-scan-deps-wrapper$EXEEXT 146 | else 147 | CTW_SUFFIX=.sh 148 | CSDW=clang-scan-deps 149 | fi 150 | cd "$PREFIX/bin" 151 | for arch in $ARCHS; do 152 | for target_os in $TARGET_OSES; do 153 | for exec in clang clang++ gcc g++ c++ as; do 154 | ln -sf clang-target-wrapper$CTW_SUFFIX $arch-w64-$target_os-$exec$CTW_LINK_SUFFIX 155 | done 156 | ln -sf $CSDW $arch-w64-$target_os-clang-scan-deps$CTW_LINK_SUFFIX 157 | for exec in addr2line ar ranlib nm objcopy readelf size strings strip llvm-ar llvm-ranlib; do 158 | if [ -n "$EXEEXT" ]; then 159 | link_target=llvm-wrapper 160 | else 161 | case $exec in 162 | llvm-*) 163 | link_target=$exec 164 | ;; 165 | *) 166 | link_target=llvm-$exec 167 | ;; 168 | esac 169 | fi 170 | ln -sf $link_target$EXEEXT $arch-w64-$target_os-$exec$EXEEXT || true 171 | done 172 | # windres and dlltool can't use llvm-wrapper, as that loses the original 173 | # target arch prefix. 174 | ln -sf llvm-windres$EXEEXT $arch-w64-$target_os-windres$EXEEXT 175 | ln -sf llvm-dlltool$EXEEXT $arch-w64-$target_os-dlltool$EXEEXT 176 | for exec in ld objdump; do 177 | ln -sf $exec-wrapper.sh $arch-w64-$target_os-$exec 178 | done 179 | done 180 | done 181 | if [ -n "$EXEEXT" ]; then 182 | if [ ! -L clang$EXEEXT ] && [ -f clang$EXEEXT ] && [ ! -f clang-$CLANG_MAJOR$EXEEXT ]; then 183 | mv clang$EXEEXT clang-$CLANG_MAJOR$EXEEXT 184 | fi 185 | if [ ! -L clang-scan-deps$EXEEXT ] && [ -f clang-scan-deps$EXEEXT ] && [ ! -f clang-scan-deps-real$EXEEXT ]; then 186 | mv clang-scan-deps$EXEEXT clang-scan-deps-real$EXEEXT 187 | fi 188 | if [ -z "$HOST" ]; then 189 | HOST=$(./clang-$CLANG_MAJOR -dumpmachine | sed 's/-.*//')-w64-mingw32 190 | fi 191 | HOST_ARCH="${HOST%%-*}" 192 | # Install unprefixed wrappers if $HOST is one of the architectures 193 | # we are installing wrappers for. 194 | case $ARCHS in 195 | *$HOST_ARCH*) 196 | for exec in clang clang++ gcc g++ c++ addr2line ar dlltool ranlib nm objcopy readelf size strings strip windres clang-scan-deps; do 197 | ln -sf $HOST-$exec$EXEEXT $exec$EXEEXT 198 | done 199 | for exec in cc c99 c11; do 200 | ln -sf clang$EXEEXT $exec$EXEEXT 201 | done 202 | for exec in ld objdump; do 203 | ln -sf $HOST-$exec $exec 204 | done 205 | ;; 206 | esac 207 | fi 208 | -------------------------------------------------------------------------------- /prepare-cross-toolchain-unix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2022 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | if [ $# -lt 2 ]; then 20 | echo $0 src dest 21 | exit 1 22 | fi 23 | SRC="$1" 24 | DEST="$2" 25 | 26 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 27 | 28 | CLANG_RESOURCE_DIR="$("$SRC/bin/clang" --print-resource-dir)" 29 | CLANG_VERSION=$(basename "$CLANG_RESOURCE_DIR") 30 | 31 | # Copy the clang resource files (include, lib, share). The clang cross 32 | # build installs the main headers, but since we didn't build the runtimes 33 | # (compiler-rt), we're lacking the files that are installed by them. The 34 | # compiler-rt build primarily installs some libs, but also a few files under 35 | # share, and headers for some of the runtime libraries. 36 | # 37 | # Instead of trying to merge these files on top of the headers installed 38 | # by the clang cross build, just wipe the existing files and copy the whole 39 | # resource directory from the complete toolchain. As long as it's a matching 40 | # version of clang, the headers that were installed by it should be identical. 41 | # 42 | # Alternatively, we could copy the lib and share subdirectories, and 43 | # copy the individual include subdirectories that are missing. 44 | rm -rf $DEST/lib/clang/$CLANG_VERSION 45 | cp -a $CLANG_RESOURCE_DIR $DEST/lib/clang/$CLANG_VERSION 46 | 47 | # Copy all arch-specific subdirectories plus the "generic" one, as is. 48 | for arch in generic $ARCHS; do 49 | rm -rf $DEST/$arch-w64-mingw32 50 | cp -a $SRC/$arch-w64-mingw32 $DEST/$arch-w64-mingw32 51 | done 52 | 53 | # Copy the libc++ module sources 54 | rm -rf $DEST/share/libc++ 55 | cp -a $SRC/share/libc++ $DEST/share 56 | -------------------------------------------------------------------------------- /prepare-cross-toolchain.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | if [ $# -lt 3 ]; then 20 | echo $0 src dest arch 21 | exit 1 22 | fi 23 | SRC="$1" 24 | DEST="$2" 25 | CROSS_ARCH="$3" 26 | 27 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 28 | 29 | CLANG_RESOURCE_DIR="$("$SRC/bin/clang" --print-resource-dir)" 30 | CLANG_VERSION=$(basename "$CLANG_RESOURCE_DIR") 31 | 32 | # If linked to a shared libc++/libunwind, we need to bundle those DLLs 33 | # in the bin directory. For simplicity, copy all runtime DLLs to the 34 | # bin directory - that way, users who have this directory in $PATH 35 | # can run the executables they've built directly without fiddling 36 | # with copying them. 37 | cp $SRC/$CROSS_ARCH-w64-mingw32/bin/*.dll $DEST/bin 38 | 39 | # Copy the clang resource files (include, lib, share). The clang cross 40 | # build installs the main headers, but since we didn't build the runtimes 41 | # (compiler-rt), we're lacking the files that are installed by them. The 42 | # compiler-rt build primarily installs some libs, but also a few files under 43 | # share, and headers for some of the runtime libraries. 44 | # 45 | # Instead of trying to merge these files on top of the headers installed 46 | # by the clang cross build, just wipe the existing files and copy the whole 47 | # resource directory from the complete toolchain. As long as it's a matching 48 | # version of clang, the headers that were installed by it should be identical. 49 | # 50 | # Alternatively, we could copy the lib and share subdirectories, and 51 | # copy the individual include subdirectories that are missing. 52 | rm -rf $DEST/lib/clang/$CLANG_VERSION 53 | cp -a $CLANG_RESOURCE_DIR $DEST/lib/clang/$CLANG_VERSION 54 | 55 | mkdir -p $DEST/include 56 | # Copy over headers and arch specific files, converting a unix style 57 | # install (everything in arch specific subdirectories) into 58 | # what we'd have when built on Windows, as if build-mingw-w64.sh 59 | # was called with --skip-include-triplet-prefit, with all headers 60 | # in $DEST/include, and only keeping the bin and lib directories for the 61 | # individual architectures. 62 | cp -a $SRC/generic-w64-mingw32/include/. $DEST/include 63 | for arch in $ARCHS; do 64 | mkdir -p $DEST/$arch-w64-mingw32 65 | for subdir in bin lib share; do 66 | cp -a $SRC/$arch-w64-mingw32/$subdir $DEST/$arch-w64-mingw32 67 | done 68 | done 69 | 70 | # Copy the libc++ module sources 71 | rm -rf $DEST/share/libc++ 72 | cp -a $SRC/share/libc++ $DEST/share 73 | -------------------------------------------------------------------------------- /release-macos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2022 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -ex 18 | 19 | if [ $# -lt 1 ]; then 20 | echo $0 tag 21 | exit 1 22 | fi 23 | 24 | TAG=$1 25 | 26 | # macOS itself doesn't ship with libzstd; avoid picking up a zstd 27 | # dependency from libraries installed e.g. with homebrew. 28 | export LLVM_CMAKEFLAGS="-DLLVM_ENABLE_ZSTD=OFF" 29 | 30 | RELNAME=llvm-mingw-$TAG-ucrt-macos-universal 31 | DEST=$HOME/$RELNAME 32 | rm -rf $DEST 33 | time CLEAN=1 SYNC=1 MACOS_REDIST=1 ./build-all.sh $DEST 34 | dir=$(pwd) 35 | cd $HOME 36 | TAR=tar 37 | if command -v gtar >/dev/null; then 38 | TAR_FLAGS="--numeric-owner --owner=0 --group=0" 39 | TAR=gtar 40 | fi 41 | $TAR -Jcvf $dir/$RELNAME.tar.xz --format=ustar $TAR_FLAGS $RELNAME 42 | rm -rf $RELNAME 43 | cd $dir 44 | ls -lh $RELNAME.tar.xz 45 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -ex 18 | 19 | if [ $# -lt 1 ]; then 20 | echo $0 tag [nativeonly] 21 | exit 1 22 | fi 23 | 24 | TAG=$1 25 | 26 | if [ "$2" = "nativeonly" ]; then 27 | NATIVEONLY=1 28 | fi 29 | 30 | time docker build -f Dockerfile . -t mstorsjo/llvm-mingw:latest -t mstorsjo/llvm-mingw:$TAG 31 | 32 | DISTRO=ubuntu-24.04-$(uname -m) 33 | docker run --rm mstorsjo/llvm-mingw:latest sh -c "cd /opt && mv llvm-mingw llvm-mingw-$TAG-ucrt-$DISTRO && tar -Jcvf - --format=ustar --numeric-owner --owner=0 --group=0 llvm-mingw-$TAG-ucrt-$DISTRO" > llvm-mingw-$TAG-ucrt-$DISTRO.tar.xz 34 | 35 | if [ -n "$NATIVEONLY" ]; then 36 | exit 0 37 | fi 38 | 39 | time docker build -f Dockerfile.dev . -t mstorsjo/llvm-mingw:dev -t mstorsjo/llvm-mingw:dev-$TAG 40 | 41 | cleanup() { 42 | for i in $temp_images; do 43 | docker rmi --no-prune $i || true 44 | done 45 | } 46 | 47 | trap cleanup EXIT INT TERM 48 | 49 | for arch in i686 x86_64 armv7 aarch64; do 50 | temp=$(uuidgen) 51 | temp_images="$temp_images $temp" 52 | time docker build -f Dockerfile.cross --build-arg BASE=mstorsjo/llvm-mingw:dev --build-arg CROSS_ARCH=$arch --build-arg TAG=$TAG-ucrt- --build-arg WITH_PYTHON=1 -t $temp . 53 | ./extract-docker.sh $temp /llvm-mingw-$TAG-ucrt-$arch.zip 54 | done 55 | 56 | msvcrt_image=llvm-mingw-msvcrt-$(uuidgen) 57 | temp_images="$temp_images $msvcrt_image" 58 | time docker build -f Dockerfile.dev -t $msvcrt_image --build-arg DEFAULT_CRT=msvcrt . 59 | 60 | docker run --rm $msvcrt_image sh -c "cd /opt && mv llvm-mingw llvm-mingw-$TAG-msvcrt-$DISTRO && tar -Jcvf - --format=ustar --numeric-owner --owner=0 --group=0 llvm-mingw-$TAG-msvcrt-$DISTRO" > llvm-mingw-$TAG-msvcrt-$DISTRO.tar.xz 61 | 62 | for arch in i686 x86_64; do 63 | temp=$(uuidgen) 64 | temp_images="$temp_images $temp" 65 | time docker build -f Dockerfile.cross --build-arg BASE=$msvcrt_image --build-arg CROSS_ARCH=$arch --build-arg TAG=$TAG-msvcrt- --build-arg WITH_PYTHON=1 -t $temp . 66 | ./extract-docker.sh $temp /llvm-mingw-$TAG-msvcrt-$arch.zip 67 | done 68 | -------------------------------------------------------------------------------- /run-lldb-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2022 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -ex 18 | 19 | if [ $# -lt 1 ]; then 20 | echo $0 prefix 21 | exit 1 22 | fi 23 | PREFIX="$1" 24 | PREFIX="$(cd "$PREFIX" && pwd)" 25 | export PATH=$PREFIX/bin:$PATH 26 | 27 | # We use tool names with explicit .exe suffixes here, so that it works both 28 | # in msys2 bash and in bash in WSL. 29 | : ${CXX:=clang++.exe} 30 | : ${LLDB:=lldb.exe} 31 | : ${OBJCOPY:=objcopy.exe} 32 | 33 | TARGET=$(clang.exe -dumpmachine) 34 | ARCH="${TARGET%%-*}" 35 | 36 | cd test 37 | 38 | TEST_DIR="$ARCH" 39 | [ -z "$CLEAN" ] || rm -rf $TEST_DIR 40 | 41 | mkdir -p $TEST_DIR 42 | 43 | # Build an executable with DWARF debug info 44 | $CXX hello-exception.cpp -o $TEST_DIR/hello-exception-dwarf.exe -g 45 | 46 | # Build an executable with PDB debug info. Strip out any bundled DWARF debug info. 47 | $CXX hello-exception.cpp -o $TEST_DIR/hello-exception-pdb.exe -g -gcodeview -Wl,--pdb= -Wl,-s 48 | 49 | # Make a DWARF split debug info file with gnu debuglink. 50 | cp $TEST_DIR/hello-exception-dwarf.exe $TEST_DIR/hello-exception-split.exe 51 | $OBJCOPY --only-keep-debug $TEST_DIR/hello-exception-split.exe $TEST_DIR/hello-exception-split.dbg 52 | $OBJCOPY --strip-all $TEST_DIR/hello-exception-split.exe 53 | $OBJCOPY --add-gnu-debuglink=$TEST_DIR/hello-exception-split.dbg $TEST_DIR/hello-exception-split.exe 54 | 55 | for i in libc++ libunwind; do 56 | if [ -f $PREFIX/$ARCH-w64-mingw32/bin/$i.dll ]; then 57 | cp $PREFIX/$ARCH-w64-mingw32/bin/$i.dll $TEST_DIR 58 | fi 59 | done 60 | 61 | 62 | # Test debugging a crashing executable, and check the backtrace of 63 | # the crash. 64 | OUT=lldb-test-out 65 | SCRIPT=lldb-test-script 66 | cat > $SCRIPT < $OUT 2>/dev/null 72 | cat $OUT 73 | grep -q "Access violation" $OUT 74 | if [ "$ARCH" != "armv7" ] || [ "$exe" = "hello-exception-pdb.exe" ]; then 75 | grep -q "volatile int.*NULL.*0x42" $OUT 76 | fi 77 | if [ "$ARCH" != "armv7" ]; then 78 | # armv7 pdb gives "val=". 79 | grep -q "frame #0: .*hello-exception.*.exe.recurse(val=0) at hello-exception.cpp:" $OUT 80 | grep -q "hello-exception.*.exe.recurse(val=10) at hello-exception.cpp:" $OUT 81 | fi 82 | done 83 | 84 | exe=hello-exception-dwarf.exe 85 | if [ "$ARCH" = "armv7" ]; then 86 | # LLDB works better on ARM with PDB than with DWARF. 87 | exe=hello-exception-pdb.exe 88 | fi 89 | 90 | 91 | # Test running into a programmatic breakpoint (__debugbreak), check the 92 | # backtrace from there, and check that we can continue from it. 93 | cat > $SCRIPT < $OUT 2>/dev/null 99 | cat $OUT 100 | grep -q "stop reason = Exception 0x80000003" $OUT 101 | # Not checking that __debugbreak is "frame #0"; on arm/aarch64, the program 102 | # counter points into the __debugbreak function, while on x86, it points to 103 | # the calling recurse function. 104 | grep -q "__debugbreak" $OUT 105 | if [ "$ARCH" != "armv7" ]; then 106 | grep -q "hello-exception.*.exe.recurse(val=10) at hello-exception.cpp:" $OUT 107 | fi 108 | grep -q "exited with status = 0" $OUT 109 | 110 | 111 | # Test setting a breakpoint in LLDB, checking the backtrace when we hit it, 112 | # stepping from the breakpoint, and running to completion. 113 | cat > $SCRIPT < $OUT 2>/dev/null 121 | cat $OUT 122 | grep -q "Breakpoint 1: where = hello-exception.*.exe.done.* at hello-exception.cpp:" $OUT 123 | grep -q "stop reason = breakpoint" $OUT 124 | grep -q "frame #0: .*hello-exception.*.exe.done.* at hello-exception.cpp:" $OUT 125 | if [ "$ARCH" != "armv7" ]; then 126 | grep -q "frame #0: .*hello-exception.*.exe.recurse(val=0) at hello-exception.cpp:" $OUT 127 | grep -q "hello-exception.*.exe.recurse(val=10) at hello-exception.cpp:" $OUT 128 | fi 129 | grep -q "exited with status = 0" $OUT 130 | 131 | rm -f $OUT $SCRIPT 132 | echo All tests succeeded 133 | -------------------------------------------------------------------------------- /run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -ex 18 | 19 | if [ $# -lt 1 ]; then 20 | echo $0 dest 21 | exit 1 22 | fi 23 | PREFIX="$1" 24 | PREFIX="$(cd "$PREFIX" && pwd)" 25 | export PATH=$PREFIX/bin:$PATH 26 | 27 | : ${CORES:=$(nproc 2>/dev/null)} 28 | : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} 29 | : ${CORES:=4} 30 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 31 | 32 | MAKE=make 33 | if command -v gmake >/dev/null; then 34 | MAKE=gmake 35 | fi 36 | 37 | case $(uname -s) in 38 | Darwin) 39 | ;; 40 | *) 41 | # Assume everything except macOS has got GNU make >= 4.0 42 | MAKEOPTS="-O" 43 | esac 44 | 45 | if [ -e /proc/sys/fs/binfmt_misc/WSLInterop ]; then 46 | # Detect running in WSL 47 | export WSL=1 48 | export TOOLEXT=.exe 49 | fi 50 | 51 | cd test 52 | 53 | HAVE_UWP=1 54 | cat< is-ucrt.c 55 | #include 56 | #if !defined(_UCRT) 57 | #error not ucrt 58 | #endif 59 | EOF 60 | ANY_ARCH=$(echo $ARCHS | awk '{print $1}') 61 | if $ANY_ARCH-w64-mingw32-gcc$TOOLEXT -E is-ucrt.c > /dev/null 2>&1; then 62 | IS_UCRT=1 63 | else 64 | # If the default CRT isn't UCRT, we can't build for mingw32uwp. 65 | unset HAVE_UWP 66 | fi 67 | rm -f is-ucrt.c 68 | 69 | if (echo "int main(){}" | $ANY_ARCH-w64-mingw32-gcc$TOOLEXT -x c++ - -o has-cfguard-test.exe -mguard=cf); then 70 | if llvm-readobj$TOOLEXT --coff-load-config has-cfguard-test.exe | grep -q 'CF_INSTRUMENTED (0x100)'; then 71 | HAVE_CFGUARD=1 72 | elif [ -n "$HAVE_CFGUARD" ]; then 73 | echo "error: Toolchain doesn't seem to include Control Flow Guard support." 1>&2 74 | rm -f has-cfguard-test.exe 75 | exit 1 76 | fi 77 | rm -f has-cfguard-test.exe 78 | elif [ -n "$HAVE_CFGUARD" ]; then 79 | echo "error: Toolchain doesn't seem to include Control Flow Guard support." 1>&2 80 | exit 1 81 | fi 82 | 83 | : ${TARGET_OSES:=${TOOLCHAIN_TARGET_OSES-$DEFAULT_OSES}} 84 | 85 | set_native() { 86 | arch="$1" 87 | winbuild="$2" 88 | case $arch in 89 | i686) 90 | NATIVE_X86=1 91 | RUN_I686=true 92 | ;; 93 | x86_64) 94 | NATIVE_X86=1 95 | RUN_I686=true 96 | RUN_X86_64=true 97 | ;; 98 | armv7) 99 | ;; 100 | aarch64) 101 | # Windows/ARM64 can run i686 binaries. Not setting NATIVE_X86 - the 102 | # asan tests don't run correctly when emulated on ARM64. 103 | NATIVE_AARCH64=1 104 | RUN_I686=true 105 | RUN_AARCH64=true 106 | 107 | if [ -n "$winbuild" ] && [ "$winbuild" -ge 22000 ]; then 108 | # Since Windows 11, x86_64 binaries can also be emulated. 109 | RUN_X86_64=true 110 | fi 111 | if [ -n "$winbuild" ] && [ "$winbuild" -lt 26100 ]; then 112 | # Since Windows 11 24H2 armv7 binaries can no longer be 113 | # executed. (It is also possible to be unable to run armv7 114 | # binaries on older OS versions, if the hardware is incapable 115 | # of it, like on Apple Silicon macs.) 116 | NATIVE_ARMV7=1 117 | RUN_ARMV7=true 118 | fi 119 | ;; 120 | esac 121 | } 122 | 123 | # This script can be run in a number of configurations: 124 | # - On Linux, where one possibly can run tests on the local machine with wine 125 | # (if available), and possibly also remotely running tests on a different 126 | # machine with suitable COPY_*/RUN_* variables (wrapping scp/ssh). 127 | # - In WSL, running a native Windows toolchain. 128 | # - In an msys2 shell. 129 | 130 | if [ -z "$RUN_X86_64" ] && [ -z "$RUN_I686" ] && [ -z "$RUN_ARMV7" ] && [ -z "$RUN_AARCH64" ]; then 131 | case $(uname) in 132 | MINGW*|MSYS*|CYGWIN*) 133 | # On Windows/arm64, we may be running x86_64 msys2 emulated, so we 134 | # can't rely on "uname -m" here. But the msys2 "uname" output indicates 135 | # the real host architecture, and the Windows build version. 136 | if [ "$(uname | cut -d - -f 4)" = "ARM64" ]; then 137 | winbuild="$(uname | cut -d - -f 3)" 138 | set_native aarch64 $winbuild 139 | elif [ "$(uname -m)" = "i686" ] && [ "$(uname | cut -d - -f 4)" != "WOW64" ]; then 140 | set_native i686 141 | else 142 | set_native x86_64 143 | fi 144 | ;; 145 | Linux) 146 | if [ -e /proc/sys/fs/binfmt_misc/WSLInterop ]; then 147 | # On WSL, inspect the architecture. 148 | winbuild="$(PATH=$PATH:/mnt/c/Windows/System32 cmd.exe /c ver 2>/dev/null | cut -s -d . -f 3)" 149 | set_native "$(uname -m)" "$winbuild" 150 | elif command -v wine >/dev/null; then 151 | # On Linux, use Wine if available. (On macOS, it's less clear 152 | # what Wine can execute; it's most likely an x86_64 version 153 | # emulated with Rosetta. Thus don't automatically use Wine on 154 | # macOS.) 155 | case $(uname -m) in 156 | x86_64) 157 | # Assume that Wine, if installed, supports both 32 and 64 bit 158 | # binaries. 159 | : ${RUN_X86_64:=wine} 160 | : ${RUN_I686:=wine} 161 | ;; 162 | aarch64) 163 | # Don't assume that the installed Wine can run armv7 binaries 164 | # too. (Versions since Wine 10.2 can, if both an armv7 and 165 | # aarch64 version is installed together.) 166 | : ${RUN_AARCH64:=wine} 167 | ;; 168 | esac 169 | fi 170 | ;; 171 | esac 172 | fi 173 | 174 | 175 | for arch in $ARCHS; do 176 | unset HAVE_ASAN 177 | case $arch in 178 | i686) 179 | RUN="$RUN_I686" 180 | COPY="$COPY_I686" 181 | NATIVE="$NATIVE_X86" 182 | if [ -n "$IS_UCRT" ]; then 183 | HAVE_ASAN=1 184 | fi 185 | ;; 186 | x86_64) 187 | RUN="$RUN_X86_64" 188 | COPY="$COPY_X86_64" 189 | NATIVE="$NATIVE_X86" 190 | if [ -n "$IS_UCRT" ]; then 191 | HAVE_ASAN=1 192 | fi 193 | ;; 194 | armv7) 195 | RUN="$RUN_ARMV7" 196 | COPY="$COPY_ARMV7" 197 | NATIVE="$NATIVE_ARMV7" 198 | ;; 199 | aarch64) 200 | RUN="$RUN_AARCH64" 201 | COPY="$COPY_AARCH64" 202 | NATIVE="$NATIVE_AARCH64" 203 | ;; 204 | esac 205 | 206 | TARGET=all 207 | if [ -n "$RUN" ] && [ "$RUN" != "false" ]; then 208 | TARGET=test 209 | if [ "$RUN" = "true" ]; then 210 | unset RUN 211 | fi 212 | fi 213 | COPYARG="" 214 | if [ -n "$COPY" ]; then 215 | COPYARG="COPY=$COPY" 216 | fi 217 | 218 | TEST_DIR="$arch" 219 | [ -z "$CLEAN" ] || rm -rf $TEST_DIR 220 | mkdir -p $TEST_DIR 221 | cd $TEST_DIR 222 | $MAKE -f ../Makefile ARCH=$arch HAVE_UWP=$HAVE_UWP HAVE_CFGUARD=$HAVE_CFGUARD HAVE_ASAN=$HAVE_ASAN NATIVE=$NATIVE RUNTIMES_SRC=$PREFIX/$arch-w64-mingw32/bin clean 223 | $MAKE -f ../Makefile ARCH=$arch HAVE_UWP=$HAVE_UWP HAVE_CFGUARD=$HAVE_CFGUARD HAVE_ASAN=$HAVE_ASAN NATIVE=$NATIVE RUNTIMES_SRC=$PREFIX/$arch-w64-mingw32/bin RUN="$RUN" $COPYARG $MAKEOPTS -j$CORES $TARGET 224 | cd .. 225 | done 226 | echo All tests succeeded 227 | -------------------------------------------------------------------------------- /strip-llvm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -e 18 | 19 | unset HOST 20 | 21 | while [ $# -gt 0 ]; do 22 | case "$1" in 23 | --host=*) 24 | HOST="${1#*=}" 25 | ;; 26 | *) 27 | PREFIX="$1" 28 | ;; 29 | esac 30 | shift 31 | done 32 | if [ -z "$PREFIX" ]; then 33 | echo $0 [--host=triple] dir 34 | exit 1 35 | fi 36 | cd "$PREFIX" 37 | 38 | if [ -n "$FULL_LLVM" ]; then 39 | exit 0 40 | fi 41 | 42 | if [ -n "$HOST" ]; then 43 | case $HOST in 44 | *-mingw32) 45 | EXEEXT=.exe 46 | ;; 47 | esac 48 | fi 49 | 50 | case $(uname) in 51 | MINGW*) 52 | EXEEXT=.exe 53 | ;; 54 | esac 55 | 56 | cd bin 57 | for i in amdgpu-arch bugpoint c-index-test clang-* clangd clangd-* darwin-debug diagtool dsymutil find-all-symbols git-clang-format hmaptool ld64.lld* llc lldb-* lli llvm-* modularize nvptx-arch obj2yaml opt pp-trace sancov sanstats scan-build scan-view split-file verify-uselistorder wasm-ld yaml2obj libclang.dll *LTO.dll *Remarks.dll *.bat; do 58 | basename=$i 59 | if [ -n "$EXEEXT" ]; then 60 | # Some in the list are expanded globs, some are plain names we list. 61 | basename=${i%$EXEEXT} 62 | i=$basename 63 | if [ -e $basename$EXEEXT ]; then 64 | i=$basename$EXEEXT 65 | fi 66 | fi 67 | # Basename has got $EXEEXT stripped, but any other suffix kept intact. 68 | case $basename in 69 | *.sh) 70 | ;; 71 | clang++|clang-*.*|clang-cpp) 72 | ;; 73 | clang-format|git-clang-format) 74 | ;; 75 | clangd) 76 | ;; 77 | clang-scan-deps) 78 | ;; 79 | clang-tidy) 80 | ;; 81 | clang-target-wrapper*|clang-scan-deps-wrapper*) 82 | ;; 83 | clang-*) 84 | suffix="${basename#*-}" 85 | # Test removing all numbers from the suffix; if it is empty, the suffix 86 | # was a plain number (as if the original name was clang-7); if it wasn't 87 | # empty, remove the tool. 88 | if [ "$(echo $suffix | tr -d '[0-9]')" != "" ]; then 89 | rm -f $i 90 | fi 91 | ;; 92 | llvm-ar|llvm-cvtres|llvm-dlltool|llvm-nm|llvm-objdump|llvm-ranlib|llvm-rc|llvm-readobj|llvm-strings|llvm-pdbutil|llvm-objcopy|llvm-strip|llvm-cov|llvm-profdata|llvm-addr2line|llvm-symbolizer|llvm-wrapper|llvm-windres|llvm-ml|llvm-readelf|llvm-size|llvm-cxxfilt|llvm-lib) 93 | ;; 94 | ld64.lld|wasm-ld) 95 | if [ -e $i ]; then 96 | rm $i 97 | fi 98 | ;; 99 | lldb|lldb-server|lldb-argdumper|lldb-instr|lldb-mi|lldb-vscode|lldb-dap) 100 | ;; 101 | *) 102 | if [ -f $i ]; then 103 | rm $i 104 | elif [ -L $i ] && [ ! -e $(readlink $i) ]; then 105 | # Remove dangling symlinks 106 | rm $i 107 | fi 108 | ;; 109 | esac 110 | done 111 | if [ -n "$EXEEXT" ]; then 112 | # Convert ld.lld from a symlink to a regular file, so we can remove 113 | # the one it points to. On MSYS, and if packaging built toolchains 114 | # in a zip file, symlinks are converted into copies. 115 | if [ -L ld.lld$EXEEXT ]; then 116 | cp ld.lld$EXEEXT tmp 117 | rm ld.lld$EXEEXT 118 | mv tmp ld.lld$EXEEXT 119 | fi 120 | # lld-link isn't used normally, but can be useful for debugging/testing, 121 | # and is kept in unix setups. Removing it when packaging for windows, 122 | # to conserve space. 123 | rm -f lld$EXEEXT lld-link$EXEEXT 124 | # Remove superfluous frontends; these aren't really used. 125 | rm -f clang-cpp* clang++* 126 | fi 127 | cd .. 128 | rm -rf libexec 129 | cd share 130 | cd clang 131 | for i in *; do 132 | case $i in 133 | clang-format*) 134 | ;; 135 | *) 136 | rm -rf $i 137 | ;; 138 | esac 139 | done 140 | cd .. 141 | rm -rf opt-viewer scan-build scan-view 142 | rm -rf man/man1/scan-build* 143 | cd .. 144 | cd include 145 | rm -rf clang clang-c clang-tidy lld llvm llvm-c lldb 146 | cd .. 147 | cd lib 148 | rm -f *.dll.a 149 | rm -f lib*.a 150 | for i in *.so* *.dylib* cmake; do 151 | case $i in 152 | liblldb*|libclang-cpp*|libLLVM*) 153 | ;; 154 | *) 155 | rm -rf $i 156 | ;; 157 | esac 158 | done 159 | cd .. 160 | -------------------------------------------------------------------------------- /test-libcxx-module.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2024 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | set -ex 18 | 19 | if [ $# -lt 1 ]; then 20 | echo $0 prefix 21 | exit 1 22 | fi 23 | PREFIX="$1" 24 | PREFIX="$(cd "$PREFIX" && pwd)" 25 | export PATH=$PREFIX/bin:$PATH 26 | 27 | : ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} 28 | 29 | case $(uname) in 30 | MINGW*|MSYS*|CYGWIN*) 31 | NATIVE=1 32 | ;; 33 | *) 34 | esac 35 | 36 | for arch in $ARCHS; do 37 | # TODO: This should ideally use "$CXX -print-file-name=libc++.modules.json", then parse the json to find the relevant cppm file and include directory. 38 | $arch-w64-mingw32-clang++ -I$PREFIX/share/libc++/v1 -std=gnu++23 -Wno-reserved-module-identifier -x c++-module -fmodule-output=std.pcm -o std.cppm.obj -c $PREFIX/share/libc++/v1/std.cppm 39 | $arch-w64-mingw32-clang++ -I$PREFIX/share/libc++/v1 -std=gnu++23 -Wno-reserved-module-identifier -x c++-module -fmodule-output=std.compat.pcm -fmodule-file=std=std.pcm -o std.compat.cppm.obj -c $PREFIX/share/libc++/v1/std.compat.cppm 40 | $arch-w64-mingw32-clang-scan-deps -format=p1689 -- $arch-w64-mingw32-clang++ -std=c++23 -c test/test-scan-deps.cpp -DEXPECT_$arch 41 | done 42 | 43 | if [ -n "$NATIVE" ]; then 44 | # Test the unprefixed clang-scan-deps wrapper. 45 | clang-scan-deps -format=p1689 -- clang++ -std=c++23 -c test/test-scan-deps.cpp -DEXPECT_$(clang++ -dumpmachine | sed 's/-.*//') 46 | fi 47 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.dll 3 | *.lib 4 | *.dll.a 5 | *.pdb 6 | -------------------------------------------------------------------------------- /test/atomic-helpers.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | 21 | struct large { 22 | int data[20]; 23 | }; 24 | 25 | typedef struct large type; 26 | 27 | _Atomic type value; 28 | 29 | type get(void) { 30 | return atomic_load(&value); 31 | } 32 | 33 | type myValue; 34 | 35 | int lockfree; 36 | 37 | int main(int argc, char* argv[]) { 38 | myValue = get(); 39 | lockfree = atomic_is_lock_free(&value); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /test/autoimport-lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include "autoimport-lib.h" 20 | 21 | int var; 22 | 23 | int array[10]; 24 | 25 | int getVar(void) { 26 | return var; 27 | } 28 | 29 | void setVar(int val) { 30 | var = val; 31 | } 32 | 33 | int getArray(int index) { 34 | return array[index]; 35 | } 36 | 37 | void setArray(int index, int val) { 38 | array[index] = val; 39 | } 40 | -------------------------------------------------------------------------------- /test/autoimport-lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef AUTOIMPORT_LIB_H 20 | #define AUTOIMPORT_LIB_H 21 | 22 | extern int var; 23 | extern int array[10]; 24 | int getVar(void); 25 | void setVar(int val); 26 | int getArray(int index); 27 | void setArray(int index, int val); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /test/autoimport-main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include "autoimport-lib.h" 20 | 21 | int *ptr = &var; 22 | 23 | int *arrayptr = &array[3]; 24 | 25 | int main(int argc, char *argv[]) { 26 | setVar(42); 27 | if (var != 42) return 1; 28 | var++; 29 | if (getVar() != 43) return 1; 30 | (*ptr)++; 31 | if (getVar() != 44) return 1; 32 | 33 | setArray(3, 100); 34 | if (array[3] != 100) return 1; 35 | if (*arrayptr != 100) return 1; 36 | array[3]++; 37 | if (*arrayptr != 101) return 1; 38 | if (getArray(3) != 101) return 1; 39 | (*arrayptr)++; 40 | if (getArray(3) != 102) return 1; 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /test/bufferoverflow.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #if defined(__linux__) || defined(__MINGW32__) 20 | #define _GNU_SOURCE 21 | #endif 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | char buf[10]; 28 | char padding[10]; 29 | 30 | const char *ten_chars = "1234567890"; 31 | int ten = 10; 32 | const char *eleven_chars = "1234567890!"; 33 | int eleven = 11; 34 | 35 | const char *foo = "foo"; 36 | const char *barbar = "barbar"; 37 | const char *barbarr = "barbarr"; 38 | const char *barbarrr = "barbarrr"; 39 | int six = 6; 40 | int seven = 7; 41 | int eight = 8; 42 | 43 | char hash = '#'; 44 | 45 | #if !defined(__GLIBC__) && !defined(__MINGW32__) 46 | #define mempcpy memcpy 47 | #endif 48 | 49 | static void acceptable_use(void) { 50 | memcpy(buf, ten_chars, ten); 51 | memmove(buf, ten_chars, ten); 52 | mempcpy(buf, ten_chars, ten); 53 | memset(buf, hash, ten); 54 | 55 | // Test writing a full buffer without null termination. 56 | strncpy(buf, eleven_chars, ten); 57 | 58 | strcpy(buf, foo); 59 | strcat(buf, barbar); 60 | 61 | strcpy(buf, foo); 62 | // We copy a truncated amount from the source, and fit exactly in the 63 | // buffer. 64 | strncat(buf, barbarrr, six); 65 | } 66 | 67 | int main(int argc, char *argv[]) { 68 | #ifndef _FORTIFY_SOURCE 69 | fprintf(stderr, "NOTE, this is built without _FORTIFY_SOURCE; the " 70 | "checks will fail!\n"); 71 | #endif 72 | if (argc < 2) { 73 | acceptable_use(); 74 | fprintf(stderr, "%s: A test tool for detecting buffer overflows.\n" 75 | "Run this with an integer between 1 and 10 to test " 76 | "various overflows that should be caught.\n", argv[0]); 77 | return 0; 78 | } 79 | switch (atoi(argv[1])) { 80 | default: 81 | case 1: 82 | memcpy(buf, eleven_chars, eleven); 83 | break; 84 | case 2: 85 | memmove(buf, eleven_chars, eleven); 86 | break; 87 | case 3: 88 | mempcpy(buf, eleven_chars, eleven); 89 | break; 90 | case 4: 91 | memset(buf, hash, eleven); 92 | break; 93 | case 5: 94 | // The contents of the string fits in the buffer, but the null 95 | // terminator doesn't. 96 | strcpy(buf, ten_chars); 97 | break; 98 | case 6: 99 | // The contents of the string doesn't fit in the buffer. 100 | strncpy(buf, eleven_chars, eleven); 101 | break; 102 | case 7: 103 | strcpy(buf, foo); 104 | // The contents of the string fits in the buffer, but the null 105 | // terminator doesn't. 106 | strcat(buf, barbarr); 107 | break; 108 | case 8: 109 | strcpy(buf, foo); 110 | // The contents of the string doesn't fit in the buffer. 111 | strcat(buf, barbarrr); 112 | break; 113 | case 9: 114 | strcpy(buf, foo); 115 | // We copy a truncated amount from the source, but the null terminator 116 | // doesn't fit in the buffer. 117 | strncat(buf, barbarrr, seven); 118 | break; 119 | case 10: 120 | strcpy(buf, foo); 121 | // The contents of the string doesn't fit in the buffer. 122 | strncat(buf, barbarrr, eight); 123 | break; 124 | } 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /test/cfguard-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Alvin Wong 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #define WINVER 0x0603 20 | #define _WIN32_WINNT 0x0603 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | __attribute__ (( noinline )) 27 | void nop_sled_target(void) { 28 | __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); 29 | __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); 30 | __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); 31 | __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); 32 | 33 | __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); 34 | __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); 35 | __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); 36 | __asm__("nop"); __asm__("nop"); __asm__("nop"); __asm__("nop"); 37 | 38 | #if defined(__x86_64__) && !defined(__arm64ec__) 39 | // On x86_64 the stack frame has to be aligned to 16 bytes. Since we 40 | // skipped the prologue we need to manually realign it to prevent 41 | // alignment-related crashes when calling puts() or exit(). 42 | __asm__("and $~0xF, %rsp"); 43 | #endif 44 | 45 | puts("Pwned!!!"); 46 | 47 | // We skipped the function prologue with the indirect call. If we let 48 | // the function return normally it will just crash with a segfault, so 49 | // do an exit instead. 50 | exit(2); 51 | } 52 | 53 | __attribute__ (( noinline )) 54 | void normal_function(void) { 55 | puts("Normal function called."); 56 | } 57 | 58 | __attribute__ (( noinline )) 59 | void make_indirect_call(void (*fn_ptr)(void)) { 60 | fn_ptr(); 61 | } 62 | 63 | __attribute__ (( noinline, guard(nocf) )) 64 | void make_indirect_call_nocf(void (*fn_ptr)(void)) { 65 | fn_ptr(); 66 | } 67 | 68 | int check_cfguard_status(void) { 69 | PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY policy; 70 | BOOL result = GetProcessMitigationPolicy(GetCurrentProcess(), 71 | ProcessControlFlowGuardPolicy, 72 | &policy, 73 | sizeof(policy)); 74 | if (!result) 75 | return 0; 76 | return policy.EnableControlFlowGuard; 77 | } 78 | 79 | void *nop_sled_target_ptr = nop_sled_target; 80 | 81 | int main(int argc, char *argv[]) { 82 | if (argc == 2) { 83 | if (strcmp(argv[1], "check_enabled") == 0) { 84 | if (check_cfguard_status()) { 85 | puts("Control Flow Guard is enabled!"); 86 | return 0; 87 | } else { 88 | puts("Control Flow Guard is _not_ enabled!"); 89 | return 1; 90 | } 91 | } 92 | if (strcmp(argv[1], "normal_icall") == 0) { 93 | puts("Performing normal indirect call."); 94 | make_indirect_call(normal_function); 95 | return 0; 96 | } 97 | if (strcmp(argv[1], "invalid_icall") == 0) { 98 | void *target = nop_sled_target_ptr; 99 | target += 16; 100 | puts("Performing invalid indirect call. If CFG is enabled this " 101 | "should crash with exit code 0xc0000409 (-1073740791)..."); 102 | fflush(stdout); 103 | make_indirect_call(target); 104 | puts("Unexpectedly returned from indirect call!"); 105 | return 1; 106 | } 107 | if (strcmp(argv[1], "invalid_icall_nocf") == 0) { 108 | void *target = nop_sled_target_ptr; 109 | target += 16; 110 | puts("Performing invalid indirect call without CFG. You should " 111 | "get an exit code 2..."); 112 | fflush(stdout); 113 | make_indirect_call_nocf(target); 114 | puts("Unexpectedly returned from indirect call!"); 115 | return 1; 116 | } 117 | } 118 | printf("%s ( check_enabled | normal_icall | invalid_icall | invalid_icall_nocf )\n", argv[0]); 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /test/exception-locale.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 SquallATF 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | int main(int argc, char *argv[]) { 23 | try { 24 | std::locale loc("test"); 25 | } catch (std::runtime_error& e) { 26 | std::cerr << "Caught \"" << e.what() << "\"" << std::endl; 27 | std::cerr << "Type " << typeid(e).name() << std::endl; 28 | std::cerr << "Test succeeded." << std::endl; 29 | } catch (...) { 30 | std::cerr << "catch all" << std::endl; 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /test/exception-reduced.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Marc Aldorasi 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | 21 | typedef void (*func_ptr)(int); 22 | struct h { 23 | func_ptr z; 24 | }; 25 | struct c { 26 | h* e; 27 | }; 28 | struct as { 29 | as() { at = static_cast(operator new(sizeof(int))); } 30 | ~as() { operator delete(at); } 31 | int *at; 32 | }; 33 | void am(int) { 34 | static as au; 35 | as av; 36 | throw 0; 37 | } 38 | int main(int argc, char* argv[]) { 39 | h hh{am}; 40 | c *u = new c{&hh}; 41 | try { 42 | u->e->z(0); 43 | } catch (...) { 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /test/global-terminate.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Liu Hao 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | void whoa() { 24 | ::puts("whoa!"); // expected output 25 | ::exit(0); 26 | } 27 | 28 | int main(int argc, char *argv[]) { 29 | ::std::set_terminate(whoa); 30 | throw 42; 31 | } 32 | -------------------------------------------------------------------------------- /test/hello-cpp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | 21 | class Hello { 22 | public: 23 | Hello() { 24 | printf("Hello ctor\n"); 25 | } 26 | ~Hello() { 27 | printf("Hello dtor\n"); 28 | } 29 | }; 30 | 31 | Hello global_h; 32 | 33 | __attribute__((constructor)) static void attr_ctor(void) { 34 | printf("attr_ctor\n"); 35 | } 36 | 37 | __attribute__((destructor)) static void attr_dtor(void) { 38 | printf("attr_dtor\n"); 39 | } 40 | 41 | int main(int argc, char* argv[]) { 42 | std::cout<<"Hello world C++"< 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | class RecurseClass { 26 | public: 27 | RecurseClass(int v) : val(v) { 28 | fprintf(stderr, "ctor %d\n", val); 29 | fflush(stderr); 30 | } 31 | ~RecurseClass() { 32 | fprintf(stderr, "dtor %d\n", val); 33 | fflush(stderr); 34 | } 35 | private: 36 | int val; 37 | }; 38 | 39 | bool crash = false; 40 | bool breakpoint = false; 41 | bool noop = false; 42 | bool do_wait = false; 43 | 44 | void done() { 45 | } 46 | 47 | void recurse(int val) { 48 | RecurseClass obj(val); 49 | if (val == 0) { 50 | if (crash) 51 | *(volatile int*)NULL = 0x42; 52 | #ifdef _WIN32 53 | else if (breakpoint) 54 | __debugbreak(); 55 | #endif 56 | else if (noop) 57 | done(); 58 | else 59 | throw std::exception(); 60 | } else if (val == 5) { 61 | try { 62 | recurse(val - 1); 63 | } catch (std::exception& e) { 64 | fprintf(stderr, "caught exception at %d\n", val); 65 | fflush(stderr); 66 | } 67 | } else { 68 | recurse(val - 1); 69 | } 70 | fprintf(stderr, "finishing function recurse %d\n", val); 71 | fflush(stderr); 72 | } 73 | 74 | int main(int argc, char* argv[]) { 75 | for (int i = 1; i < argc; i++) { 76 | /* These modes are useful for testing backtraces in a debugger. */ 77 | if (!strcmp(argv[i], "-crash")) { 78 | crash = true; 79 | fprintf(stderr, "Crashing instead of throwing an exception\n"); 80 | } else if (!strcmp(argv[i], "-breakpoint")) { 81 | #ifdef _WIN32 82 | breakpoint = true; 83 | fprintf(stderr, "Triggering breakpoint instead of throwing an exception\n"); 84 | #else 85 | fprintf(stderr, "Programmatic breakpoints not supported\n"); 86 | #endif 87 | } else if (!strcmp(argv[i], "-noop")) { 88 | noop = true; 89 | fprintf(stderr, "Calling the function 'done' when recursion stops\n"); 90 | } else if (!strcmp(argv[i], "-wait")) { 91 | do_wait = true; 92 | fprintf(stderr, "Waiting before exiting\n"); 93 | } 94 | } 95 | recurse(10); 96 | if (do_wait) { 97 | fprintf(stderr, "Waiting\n"); 98 | std::this_thread::sleep_for(std::chrono::seconds(10)); 99 | fprintf(stderr, "Exiting\n"); 100 | } 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /test/hello-omp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | int main(int argc, char *argv[]) { 23 | #pragma omp parallel 24 | printf("thread %d, nthreads %d\n", omp_get_thread_num(), 25 | omp_get_num_threads()); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/hello-res-rc.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include "hello-res.h" 20 | 21 | STRINGTABLE { 22 | HELLO_STRING "Hello world" 23 | } 24 | -------------------------------------------------------------------------------- /test/hello-res.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include "hello-res.h" 22 | 23 | int main(int argc, char *argv[]) { 24 | char buf[100]; 25 | if (LoadStringA(GetModuleHandle(NULL), HELLO_STRING, buf, sizeof(buf)) <= 0) { 26 | printf("Unable to load resource string\n"); 27 | return 1; 28 | } 29 | printf("Resource string: %s\n", buf); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /test/hello-res.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef HELLO_RES_H 20 | #define HELLO_RES_H 21 | 22 | #define HELLO_STRING 1 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /test/hello-tls.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #if defined(_MSC_VER) 25 | static __declspec(thread) int tlsvar = 1; 26 | #else 27 | static __thread int tlsvar = 1; 28 | #endif 29 | 30 | static unsigned __stdcall threadfunc(void* arg) { 31 | int id = (int)(intptr_t)arg; 32 | printf("thread %d, tlsvar %p initially %d\n", id, &tlsvar, tlsvar); 33 | tlsvar = id + 100; 34 | for (int i = 0; i < 4; i++) { 35 | printf("thread %d, tlsvar %p %d\n", id, &tlsvar, tlsvar); 36 | tlsvar += 10; 37 | Sleep(500); 38 | } 39 | return 0; 40 | } 41 | 42 | int main(int argc, char* argv[]) { 43 | HANDLE threads[3]; 44 | 45 | for (int i = 0; i < 3; i++) { 46 | printf("mainthread, tlsvar %p %d\n", &tlsvar, tlsvar); 47 | tlsvar += 10; 48 | threads[i] = (HANDLE)_beginthreadex(NULL, 0, threadfunc, (void*)(intptr_t) (i + 1), 0, NULL); 49 | Sleep(350); 50 | } 51 | for (int i = 0; i < 3; i++) { 52 | WaitForSingleObject(threads[i], INFINITE); 53 | CloseHandle(threads[i]); 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /test/hello.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | 21 | int main(int argc, char* argv[]) { 22 | printf("Hello world!\n"); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /test/idltest.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #define COBJMACROS 22 | #include "idltest.h" 23 | 24 | int main(int argc, char *argv[]) { 25 | if (argc <= 1) 26 | return 0; 27 | 28 | ITestClass *obj; 29 | CoInitializeEx(NULL, COINIT_MULTITHREADED); 30 | if (CoCreateInstance(&CLSID_TestClassImplementation, 0, CLSCTX_INPROC, &IID_ITestClass, (void*)&obj)) 31 | return 0; 32 | ITestClass_DoSomething(obj, 0); 33 | ITestClass_Release(obj); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /test/idltest.idl: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | import "unknwn.idl"; 20 | 21 | [ 22 | uuid(73ad110f-de60-4d7a-899a-58f2afc033a7), 23 | ] 24 | interface ITestClass : IUnknown 25 | { 26 | HRESULT DoSomething([in] ULONG param); 27 | } 28 | 29 | cpp_quote("DEFINE_GUID(CLSID_TestClassImplementation, 0x5247bb7c,0x51d6,0x42ce,0xa3,0xd1,0x1c,0xe9,0x65,0xf6,0x93,0x72);") 30 | -------------------------------------------------------------------------------- /test/longjmp-cleanup.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | jmp_buf jmp; 23 | 24 | class RecurseClass { 25 | public: 26 | RecurseClass(int v) : val(v) { 27 | fprintf(stderr, "ctor %d\n", val); 28 | } 29 | ~RecurseClass() { 30 | fprintf(stderr, "dtor %d\n", val); 31 | } 32 | private: 33 | int val; 34 | }; 35 | 36 | void recurse(int val) { 37 | RecurseClass obj(val); 38 | if (val == 0) { 39 | longjmp(jmp, 1); 40 | } 41 | if (val == 5) { 42 | if (!setjmp(jmp)) 43 | recurse(val - 1); 44 | else 45 | fprintf(stderr, "returned from setjmp\n"); 46 | } else { 47 | recurse(val - 1); 48 | } 49 | fprintf(stderr, "finishing function recurse %d\n", val); 50 | } 51 | 52 | int main(int argc, char* argv[]) { 53 | recurse(10); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /test/setjmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | jmp_buf jmp; 25 | 26 | int fibonacci(int val) { 27 | char buf[100]; 28 | if (val <= 1) { 29 | longjmp(jmp, 1); 30 | return val; 31 | } 32 | snprintf(buf, sizeof(buf), "fibonacci(%d)", val); 33 | printf("%s\n", buf); 34 | return fibonacci(val - 1) + fibonacci(val - 2); 35 | } 36 | 37 | double check_d, check_cos; 38 | 39 | int main(int argc, char* argv[]) { 40 | int val = 10, ret; 41 | double val2 = 3.14; 42 | if (argc > 1) 43 | val = atoi(argv[1]); 44 | if (argc > 2) 45 | val2 = atof(argv[2]); 46 | double d = sin(val2); 47 | printf("d = %f\n", d); 48 | printf("cos = %f\n", cos(val2)); 49 | printf("size = %d, %p\n", (int) sizeof(jmp), jmp); 50 | check_d = d; 51 | check_cos = cos(val2); 52 | if ((ret = setjmp(jmp)) != 0) { 53 | printf("setjmp returned %d\n", ret); 54 | printf("d = %f\n", d); 55 | printf("cos = %f\n", cos(val2)); 56 | if (d != check_d || cos(val2) != check_cos) { 57 | printf("local variables were clobbered\n"); 58 | return 1; 59 | } 60 | return 0; 61 | } 62 | printf("fibonacci(%d) = %d\n", val, fibonacci(val)); 63 | return 1; 64 | } 65 | -------------------------------------------------------------------------------- /test/stacksmash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | 21 | __attribute__((noinline)) 22 | void func(char *ptr, int idx) { 23 | ptr[idx] ^= 1; 24 | } 25 | 26 | int main(int argc, char *argv[]) { 27 | char buf[10]; 28 | if (argc > 1) { 29 | fprintf(stderr, "smashing stack\n"); 30 | fflush(stderr); 31 | func(buf, 10); 32 | } else { 33 | func(buf, 9); 34 | fprintf(stderr, "%s: A test tool for detecting stack smashing.\n" 35 | "Run this with a command line argument to trigger an " 36 | "error.\n", argv[0]); 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /test/tchar.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2025 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifdef UNICODE 20 | #define _UNICODE 21 | #endif 22 | 23 | #include 24 | #include 25 | 26 | int _tmain(int argc, TCHAR* argv[]) { 27 | _tprintf(_T("_tprintf\n")); 28 | _ftprintf(stdout, _T("_ftprintf\n")); 29 | 30 | TCHAR buffer[100]; 31 | _stprintf(buffer, _T("foo %d"), 123); 32 | if (_tcscmp(buffer, _T("foo 123"))) { 33 | _tprintf(_T("incorrect _stprintf output\n")); 34 | return 1; 35 | } 36 | _stprintf(buffer, _T("str %s"), _T("arg")); 37 | if (_tcscmp(buffer, _T("str arg"))) { 38 | _tprintf(_T("incorrect _stprintf output for %%s\n")); 39 | return 1; 40 | } 41 | 42 | int val; 43 | if (_stscanf(_T("123"), _T("%d"), &val) != 1 || val != 123) { 44 | _tprintf(_T("incorrect _stscanf output\n")); 45 | return 1; 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /test/test-scan-deps.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | // Test that clang-scan-deps can locate c++ standard library headers 20 | #include 21 | 22 | // Test that we have set the expected architecture defines. 23 | #if defined(__x86_64__) && !defined(__arm64ec__) 24 | #ifndef EXPECT_x86_64 25 | #include 26 | #endif 27 | #elif defined(__i386__) 28 | #ifndef EXPECT_i686 29 | #include 30 | #endif 31 | #elif defined(__aarch64__) 32 | #ifndef EXPECT_aarch64 33 | #include 34 | #endif 35 | #elif defined(__arm__) 36 | #ifndef EXPECT_armv7 37 | #include 38 | #endif 39 | #elif defined(__arm64ec__) 40 | #ifndef EXPECT_arm64ec 41 | #include 42 | #endif 43 | #endif 44 | -------------------------------------------------------------------------------- /test/throwcatch-lib.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include "throwcatch-lib.h" 20 | #include 21 | 22 | void libFunc(int param) { 23 | switch (param) { 24 | case 1: 25 | fprintf(stderr, "throwing FirstException\n"); 26 | fflush(stderr); 27 | throw FirstException("first"); 28 | case 2: 29 | fprintf(stderr, "throwing SecondException\n"); 30 | fflush(stderr); 31 | throw SecondException("second"); 32 | case 3: 33 | fprintf(stderr, "throwing std::exception\n"); 34 | fflush(stderr); 35 | throw std::exception(); 36 | default: 37 | fprintf(stderr, "not throwing\n"); 38 | break; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /test/throwcatch-lib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef THROWCATCH_LIB_H 20 | #define THROWCATCH_LIB_H 21 | 22 | #include 23 | #include 24 | 25 | class FirstException : public std::exception { 26 | public: 27 | FirstException(const char *s) : str(s) {} 28 | 29 | const char *what() const noexcept override { 30 | return str.c_str(); 31 | } 32 | 33 | private: 34 | std::string str; 35 | }; 36 | 37 | class SecondException : public std::exception { 38 | public: 39 | SecondException(const char *s) : str(s) {} 40 | 41 | const char *what() const noexcept override { 42 | return str.c_str(); 43 | } 44 | 45 | private: 46 | std::string str; 47 | }; 48 | 49 | void libFunc(int param); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /test/throwcatch-main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include "throwcatch-lib.h" 20 | #include 21 | #include 22 | 23 | int main(int argc, char* argv[]) { 24 | int ret = 0; 25 | for (int i = 0; i <= 3; i++) { 26 | int caught = 0; 27 | try { 28 | libFunc(i); 29 | } catch (FirstException &e) { 30 | fprintf(stderr, "caught FirstException\n"); 31 | caught = 1; 32 | if (strcmp(e.what(), "first")) { 33 | fprintf(stderr, "unexpected what()\n"); 34 | ret = 1; 35 | } 36 | } catch (SecondException &e) { 37 | fprintf(stderr, "caught SecondException\n"); 38 | caught = 2; 39 | if (strcmp(e.what(), "second")) { 40 | fprintf(stderr, "unexpected what()\n"); 41 | ret = 1; 42 | } 43 | } catch (std::exception &e) { 44 | fprintf(stderr, "caught std::exception\n"); 45 | caught = 3; 46 | } catch (...) { 47 | fprintf(stderr, "caught something else\n"); 48 | caught = -1; 49 | } 50 | if (caught != i) { 51 | fprintf(stderr, "caught unexpected exception!\n"); 52 | ret = 1; 53 | } 54 | } 55 | if (ret) 56 | fprintf(stderr, "got errors\n"); 57 | else 58 | fprintf(stderr, "all ok\n"); 59 | return ret; 60 | } 61 | -------------------------------------------------------------------------------- /test/tlstest-lib.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #define WIN32_LEAN_AND_MEAN 20 | #include 21 | #include 22 | #include 23 | 24 | class Hello { 25 | public: 26 | Hello(const char* s) { 27 | str = s; 28 | thread = GetCurrentThreadId(); 29 | fprintf(stderr, "%s ctor on thread %d\n", str, thread); 30 | } 31 | ~Hello() { 32 | fprintf(stderr, "%s dtor from thread %d, now on %d\n", str, thread, (int) GetCurrentThreadId()); 33 | } 34 | const char* str; 35 | int thread; 36 | }; 37 | 38 | Hello lib_h("lib global"); 39 | static thread_local Hello lib_tls_h("lib global tls"); 40 | 41 | static void lib_atexit(void) { 42 | fprintf(stderr, "lib_atexit\n"); 43 | } 44 | 45 | static class SetAtexit { 46 | public: 47 | SetAtexit() { 48 | atexit(lib_atexit); 49 | } 50 | } sa; 51 | 52 | extern "C" void __declspec(dllexport) func(void) { 53 | fprintf(stderr, "func\n"); 54 | static thread_local Hello h2("lib local tls"); 55 | fprintf(stderr, "func end, thread %d\n", lib_tls_h.thread); 56 | } 57 | -------------------------------------------------------------------------------- /test/tlstest-main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #define WIN32_LEAN_AND_MEAN 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | HANDLE event1, event2, event3; 27 | void (*func)(void); 28 | 29 | class Hello { 30 | public: 31 | Hello(const char* s) { 32 | str = s; 33 | thread = GetCurrentThreadId(); 34 | fprintf(stderr, "%s ctor on thread %d\n", str, thread); 35 | } 36 | ~Hello() { 37 | fprintf(stderr, "%s dtor from thread %d, now on %d\n", str, thread, (int) GetCurrentThreadId()); 38 | } 39 | const char* str; 40 | int thread; 41 | }; 42 | 43 | unsigned __stdcall threadfunc(void *arg) { 44 | HANDLE event = (HANDLE) arg; 45 | int threadId = GetCurrentThreadId(); 46 | fprintf(stderr, "threadfunc thread %d\n", threadId); 47 | static thread_local Hello main_h("main local tls"); 48 | SetEvent(event3); 49 | WaitForSingleObject(event, INFINITE); 50 | fprintf(stderr, "thread %d calling func\n", threadId); 51 | if (func) 52 | func(); 53 | SetEvent(event3); 54 | WaitForSingleObject(event, INFINITE); 55 | 56 | fprintf(stderr, "thread %d finishing\n", threadId); 57 | return 0; 58 | } 59 | 60 | static Hello main_h("main global"); 61 | 62 | static void atexit_func(void) { 63 | fprintf(stderr, "main atexit_func\n"); 64 | } 65 | 66 | int main(int argc, char* argv[]) { 67 | atexit(atexit_func); 68 | fprintf(stderr, "main\n"); 69 | event1 = CreateEvent(NULL, FALSE, FALSE, NULL); 70 | event2 = CreateEvent(NULL, FALSE, FALSE, NULL); 71 | event3 = CreateEvent(NULL, FALSE, FALSE, NULL); 72 | fprintf(stderr, "main, starting thread1\n"); 73 | HANDLE thread1 = (HANDLE)_beginthreadex(NULL, 0, threadfunc, event1, 0, NULL); 74 | WaitForSingleObject(event3, INFINITE); 75 | fprintf(stderr, "main, thread1 started\n"); 76 | fprintf(stderr, "LoadLibrary tlstest-lib.dll\n"); 77 | HMODULE h = LoadLibrary("tlstest-lib.dll"); 78 | fprintf(stderr, "LoadLibrary tlstest-lib.dll ret %p\n", h); 79 | if (!h) { 80 | fprintf(stderr, "Unable to load tlstest-lib.dll\n"); 81 | return 1; 82 | } 83 | func = (void (*)(void)) GetProcAddress(h, "func"); 84 | fprintf(stderr, "main, got func address, calling it\n"); 85 | if (func) 86 | func(); 87 | 88 | fprintf(stderr, "main, starting thread2\n"); 89 | HANDLE thread2 = (HANDLE)_beginthreadex(NULL, 0, threadfunc, event2, 0, NULL); 90 | WaitForSingleObject(event3, INFINITE); 91 | fprintf(stderr, "main, thread2 started\n"); 92 | 93 | SetEvent(event1); 94 | WaitForSingleObject(event3, INFINITE); 95 | fprintf(stderr, "main, thread1 work done\n"); 96 | 97 | SetEvent(event2); 98 | WaitForSingleObject(event3, INFINITE); 99 | fprintf(stderr, "main, thread2 work done\n"); 100 | 101 | SetEvent(event1); 102 | WaitForSingleObject(thread1, INFINITE); 103 | fprintf(stderr, "main, thread1 joined\n"); 104 | 105 | fprintf(stderr, "FreeLibrary\n"); 106 | FreeLibrary(h); 107 | fprintf(stderr, "FreeLibrary done\n"); 108 | 109 | SetEvent(event2); 110 | WaitForSingleObject(thread2, INFINITE); 111 | fprintf(stderr, "main, thread2 joined\n"); 112 | static thread_local Hello main_h("main local tls"); 113 | atexit(atexit_func); 114 | fprintf(stderr, "main done\n"); 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /test/ubsan.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | int32_t var = INT32_MAX; 23 | 24 | int main(int argc, char *argv[]) { 25 | char buf[10]; 26 | if (argc > 1) { 27 | fprintf(stderr, "triggering undefined behaviour\n"); 28 | fflush(stderr); 29 | var++; 30 | } else { 31 | var--; 32 | fprintf(stderr, "%s: A test tool for undefined behaviour sanitizer. \n" 33 | "Run this with a command line argument to trigger " 34 | "undefined behaviour.\n", argv[0]); 35 | } 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/uwp-error.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Steve Lhomme 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | int main(int argc, char *argv[]) { 23 | UINT res = GetOEMCP(); 24 | fprintf(stderr, "Windows OEM CP is %u\n", res); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /wrappers/aarch64-w64-windows-gnu.cfg: -------------------------------------------------------------------------------- 1 | -target aarch64-w64-mingw32 2 | @mingw32-common.cfg 3 | # SEH is the default for aarch64. 4 | -------------------------------------------------------------------------------- /wrappers/arm64ec-w64-windows-gnu.cfg: -------------------------------------------------------------------------------- 1 | -target arm64ec-w64-mingw32 2 | @mingw32-common.cfg 3 | # SEH is the default for arm64ec. 4 | -------------------------------------------------------------------------------- /wrappers/armv7-w64-windows-gnu.cfg: -------------------------------------------------------------------------------- 1 | -target armv7-w64-mingw32 2 | @mingw32-common.cfg 3 | # SEH is the default for armv7. 4 | -------------------------------------------------------------------------------- /wrappers/clang-scan-deps-wrapper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include "native-wrapper.h" 20 | 21 | #ifndef CLANG_SCAN_DEPS 22 | #define CLANG_SCAN_DEPS "clang-scan-deps" 23 | #endif 24 | #ifndef DEFAULT_TARGET 25 | #define DEFAULT_TARGET "x86_64-w64-mingw32" 26 | #endif 27 | 28 | int _tmain(int argc, TCHAR *argv[]) { 29 | const TCHAR *dir; 30 | split_argv(argv[0], &dir, NULL, NULL, NULL); 31 | 32 | int max_arg = argc + 3; 33 | const TCHAR **exec_argv = malloc((max_arg + 1) * sizeof(*exec_argv)); 34 | int arg = 0; 35 | exec_argv[arg++] = concat(dir, _T(CLANG_SCAN_DEPS)); 36 | 37 | // If changing this wrapper, change clang-scan-deps-wrapper.sh accordingly. 38 | int i = 1; 39 | int got_flags = 0; 40 | TCHAR *cmd_exe = NULL; 41 | for (; i < argc; i++) { 42 | if (got_flags) { 43 | cmd_exe = _tcsdup(argv[i]); 44 | exec_argv[arg++] = argv[i]; 45 | i++; 46 | break; 47 | } else if (!_tcscmp(argv[i], _T("--"))) { 48 | got_flags = 1; 49 | exec_argv[arg++] = argv[i]; 50 | } else { 51 | exec_argv[arg++] = argv[i]; 52 | } 53 | } 54 | 55 | if (cmd_exe) { 56 | // If cmd_exe is a - style command, prefer the 57 | // target triple from there, rather than from what we might have 58 | // had in our name. 59 | TCHAR *sep = _tcsrchrs(cmd_exe, '/', '\\'); 60 | if (sep) 61 | cmd_exe = sep + 1; 62 | sep = _tcsrchr(cmd_exe, '.'); 63 | if (sep) 64 | *sep = '\0'; 65 | TCHAR *dash = _tcsrchr(cmd_exe, '-'); 66 | int has_target = 0; 67 | if (dash) { 68 | *dash = '\0'; 69 | const TCHAR *cmd_exe_suffix = dash + 1; 70 | if (!_tcscmp(cmd_exe_suffix, _T("clang")) || 71 | !_tcscmp(cmd_exe_suffix, _T("clang++")) || 72 | !_tcscmp(cmd_exe_suffix, _T("gcc")) || 73 | !_tcscmp(cmd_exe_suffix, _T("g++")) || 74 | !_tcscmp(cmd_exe_suffix, _T("c++")) || 75 | !_tcscmp(cmd_exe_suffix, _T("as")) || 76 | !_tcscmp(cmd_exe_suffix, _T("cc")) || 77 | !_tcscmp(cmd_exe_suffix, _T("c99")) || 78 | !_tcscmp(cmd_exe_suffix, _T("c11"))) { 79 | has_target = 1; 80 | } 81 | } 82 | const TCHAR *target = NULL; 83 | #ifdef _WIN32 84 | // On Windows, we want to set our default target even if no target 85 | // was found in cmd_exe, as we want to support running with a foreign 86 | // clang-scan-deps-real.exe binary, that could have any default. 87 | if (!has_target) 88 | target = _T(DEFAULT_TARGET); 89 | #endif 90 | 91 | if (target) { 92 | // If we did find a cmd_exe and have figured out a target, add 93 | // -target after cmd_exe. 94 | exec_argv[arg++] = _T("-target"); 95 | exec_argv[arg++] = target; 96 | } 97 | } 98 | 99 | for (; i < argc; i++) 100 | exec_argv[arg++] = argv[i]; 101 | 102 | exec_argv[arg] = NULL; 103 | if (arg > max_arg) { 104 | fprintf(stderr, "Too many options added\n"); 105 | abort(); 106 | } 107 | 108 | return run_final(exec_argv[0], exec_argv); 109 | } 110 | -------------------------------------------------------------------------------- /wrappers/clang-target-wrapper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include "native-wrapper.h" 20 | 21 | #ifndef CLANG 22 | #define CLANG "clang" 23 | #endif 24 | #ifndef DEFAULT_TARGET 25 | #define DEFAULT_TARGET "x86_64-w64-mingw32" 26 | #endif 27 | 28 | int _tmain(int argc, TCHAR* argv[]) { 29 | const TCHAR *dir; 30 | const TCHAR *target; 31 | const TCHAR *exe; 32 | split_argv(argv[0], &dir, NULL, &target, &exe); 33 | if (!target) 34 | target = _T(DEFAULT_TARGET); 35 | TCHAR *arch = _tcsdup(target); 36 | TCHAR *dash = _tcschr(arch, '-'); 37 | if (dash) 38 | *dash = '\0'; 39 | TCHAR *target_os = _tcsrchr(target, '-'); 40 | if (target_os) 41 | target_os++; 42 | 43 | // Check if trying to compile Ada; if we try to do this, invoking clang 44 | // would end up invoking -gcc with the same arguments, which ends 45 | // up in an infinite recursion. 46 | for (int i = 1; i < argc - 1; i++) { 47 | if (!_tcscmp(argv[i], _T("-x")) && !_tcscmp(argv[i + 1], _T("ada"))) { 48 | fprintf(stderr, "Ada is not supported\n"); 49 | return 1; 50 | } 51 | } 52 | 53 | int max_arg = argc + 18; 54 | const TCHAR **exec_argv = malloc((max_arg + 1) * sizeof(*exec_argv)); 55 | int arg = 0; 56 | if (getenv("CCACHE")) 57 | exec_argv[arg++] = _T("ccache"); 58 | exec_argv[arg++] = concat(dir, _T(CLANG)); 59 | exec_argv[arg++] = _T("--start-no-unused-arguments"); 60 | 61 | // If changing this wrapper, change clang-target-wrapper.sh accordingly. 62 | if (!_tcscmp(exe, _T("clang++")) || !_tcscmp(exe, _T("g++")) || !_tcscmp(exe, _T("c++"))) 63 | exec_argv[arg++] = _T("--driver-mode=g++"); 64 | else if (!_tcscmp(exe, _T("c99"))) 65 | exec_argv[arg++] = _T("-std=c99"); 66 | else if (!_tcscmp(exe, _T("c11"))) 67 | exec_argv[arg++] = _T("-std=c11"); 68 | 69 | if (target_os && !_tcscmp(target_os, _T("mingw32uwp"))) { 70 | // the UWP target is for Windows 10 71 | exec_argv[arg++] = _T("-D_WIN32_WINNT=0x0A00"); 72 | exec_argv[arg++] = _T("-DWINVER=0x0A00"); 73 | // the UWP target can only use Windows Store APIs 74 | exec_argv[arg++] = _T("-DWINAPI_FAMILY=WINAPI_FAMILY_APP"); 75 | // the Windows Store API only supports Windows Unicode (some rare ANSI ones are available) 76 | exec_argv[arg++] = _T("-DUNICODE"); 77 | // force the Universal C Runtime 78 | exec_argv[arg++] = _T("-D_UCRT"); 79 | } 80 | 81 | exec_argv[arg++] = _T("-target"); 82 | exec_argv[arg++] = target; 83 | exec_argv[arg++] = _T("--end-no-unused-arguments"); 84 | 85 | for (int i = 1; i < argc; i++) 86 | exec_argv[arg++] = argv[i]; 87 | 88 | if (target_os && !_tcscmp(target_os, _T("mingw32uwp"))) { 89 | // Default linker flags; passed after any user specified -l options, 90 | // to let the user specified libraries take precedence over these. 91 | 92 | exec_argv[arg++] = _T("--start-no-unused-arguments"); 93 | // add the minimum runtime to use for UWP targets 94 | exec_argv[arg++] = _T("-Wl,-lwindowsapp"); 95 | // This still requires that the toolchain (in particular, libc++.a) has 96 | // been built targeting UCRT originally. 97 | exec_argv[arg++] = _T("-Wl,-lucrtapp"); 98 | exec_argv[arg++] = _T("--end-no-unused-arguments"); 99 | } 100 | 101 | exec_argv[arg] = NULL; 102 | if (arg > max_arg) { 103 | fprintf(stderr, "Too many options added\n"); 104 | abort(); 105 | } 106 | 107 | return run_final(exec_argv[0], exec_argv); 108 | } 109 | -------------------------------------------------------------------------------- /wrappers/clang-target-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | get_dir() { 18 | target="$1" 19 | while [ -L "$target" ]; do 20 | cd "$(dirname "$target")" 21 | target="$(readlink "$(basename "$target")")" 22 | done 23 | cd "$(dirname "$target")" 24 | pwd 25 | } 26 | 27 | DIR="$(get_dir "$0")" 28 | BASENAME="$(basename "$0")" 29 | TARGET="${BASENAME%-*}" 30 | EXE="${BASENAME##*-}" 31 | DEFAULT_TARGET=x86_64-w64-mingw32 32 | if [ "$TARGET" = "$BASENAME" ]; then 33 | TARGET=$DEFAULT_TARGET 34 | fi 35 | ARCH="${TARGET%%-*}" 36 | TARGET_OS="${TARGET##*-}" 37 | 38 | # Check if trying to compile Ada; if we try to do this, invoking clang 39 | # would end up invoking -gcc with the same arguments, which ends 40 | # up in an infinite recursion. 41 | case "$*" in 42 | *-x\ ada*) 43 | echo "Ada is not supported" >&2 44 | exit 1 45 | ;; 46 | *) 47 | ;; 48 | esac 49 | 50 | # Allow setting e.g. CCACHE=1 to wrap all building in ccache. 51 | if [ -n "$CCACHE" ]; then 52 | CCACHE=ccache 53 | fi 54 | 55 | # If changing this wrapper, change clang-target-wrapper.c accordingly. 56 | CLANG="$DIR/clang" 57 | FLAGS="" 58 | FLAGS="$FLAGS --start-no-unused-arguments" 59 | case $EXE in 60 | clang++|g++|c++) 61 | FLAGS="$FLAGS --driver-mode=g++" 62 | ;; 63 | c99) 64 | FLAGS="$FLAGS -std=c99" 65 | ;; 66 | c11) 67 | FLAGS="$FLAGS -std=c11" 68 | ;; 69 | esac 70 | LINKER_FLAGS="" 71 | case $TARGET_OS in 72 | mingw32uwp) 73 | # the UWP target is for Windows 10 74 | FLAGS="$FLAGS -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00" 75 | # the UWP target can only use Windows Store APIs 76 | FLAGS="$FLAGS -DWINAPI_FAMILY=WINAPI_FAMILY_APP" 77 | # the Windows Store API only supports Windows Unicode (some rare ANSI ones are available) 78 | FLAGS="$FLAGS -DUNICODE" 79 | # Force the Universal C Runtime 80 | FLAGS="$FLAGS -D_UCRT" 81 | 82 | # Default linker flags; passed after any user specified -l options, 83 | # to let the user specified libraries take precedence over these. 84 | 85 | # add the minimum runtime to use for UWP targets 86 | LINKER_FLAGS="$LINKER_FLAGS --start-no-unused-arguments" 87 | LINKER_FLAGS="$LINKER_FLAGS -Wl,-lwindowsapp" 88 | # This still requires that the toolchain (in particular, libc++.a) has 89 | # been built targeting UCRT originally. 90 | LINKER_FLAGS="$LINKER_FLAGS -Wl,-lucrtapp" 91 | LINKER_FLAGS="$LINKER_FLAGS --end-no-unused-arguments" 92 | ;; 93 | esac 94 | 95 | FLAGS="$FLAGS -target $TARGET" 96 | FLAGS="$FLAGS --end-no-unused-arguments" 97 | 98 | $CCACHE "$CLANG" $FLAGS "$@" $LINKER_FLAGS 99 | -------------------------------------------------------------------------------- /wrappers/i686-w64-windows-gnu.cfg: -------------------------------------------------------------------------------- 1 | -target i686-w64-mingw32 2 | @mingw32-common.cfg 3 | # Dwarf is the default for i686. 4 | -------------------------------------------------------------------------------- /wrappers/ld-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | get_dir() { 18 | target="$1" 19 | while [ -L "$target" ]; do 20 | cd "$(dirname "$target")" 21 | target="$(readlink "$(basename "$target")")" 22 | done 23 | cd "$(dirname "$target")" 24 | pwd 25 | } 26 | 27 | DIR="$(get_dir "$0")" 28 | export PATH="$DIR":"$PATH" 29 | 30 | BASENAME="$(basename "$0")" 31 | TARGET="${BASENAME%-*}" 32 | DEFAULT_TARGET=x86_64-w64-mingw32 33 | if [ "$TARGET" = "$BASENAME" ]; then 34 | TARGET=$DEFAULT_TARGET 35 | fi 36 | ARCH="${TARGET%%-*}" 37 | TARGET_OS="${TARGET##*-}" 38 | case $ARCH in 39 | i686) M=i386pe ;; 40 | x86_64) M=i386pep ;; 41 | armv7) M=thumb2pe ;; 42 | aarch64) M=arm64pe ;; 43 | arm64ec) M=arm64ecpe ;; 44 | esac 45 | FLAGS="-m $M" 46 | case $TARGET_OS in 47 | mingw32uwp) 48 | FLAGS="$FLAGS -lwindowsapp -lucrtapp" 49 | ;; 50 | esac 51 | ld.lld $FLAGS "$@" 52 | -------------------------------------------------------------------------------- /wrappers/llvm-wrapper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include "native-wrapper.h" 20 | 21 | int _tmain(int argc, TCHAR* argv[]) { 22 | const TCHAR *dir; 23 | const TCHAR *exe; 24 | const TCHAR *basename, *target; 25 | split_argv(argv[0], &dir, &basename, &target, &exe); 26 | if (_tcsncmp(exe, _T("llvm-"), 5)) 27 | exe = concat(_T("llvm-"), exe); 28 | TCHAR *exe_path = concat(dir, exe); 29 | 30 | return run_final(exe_path, (const TCHAR *const *) argv); 31 | } 32 | -------------------------------------------------------------------------------- /wrappers/mingw32-common.cfg: -------------------------------------------------------------------------------- 1 | -rtlib=compiler-rt 2 | -unwindlib=libunwind 3 | -stdlib=libc++ 4 | -fuse-ld=lld 5 | -------------------------------------------------------------------------------- /wrappers/native-wrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Martin Storsjo 3 | * 4 | * This file is part of llvm-mingw. 5 | * 6 | * Permission to use, copy, modify, and/or distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifdef UNICODE 20 | #define _UNICODE 21 | #endif 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #ifdef _WIN32 29 | #define WIN32_LEAN_AND_MEAN 30 | #include 31 | #include 32 | #include 33 | #define EXECVP_CAST 34 | #else 35 | #include 36 | typedef char TCHAR; 37 | #define _T(x) x 38 | #define _tcsrchr strrchr 39 | #define _tcschr strchr 40 | #define _tcsdup strdup 41 | #define _tcscpy strcpy 42 | #define _tcslen strlen 43 | #define _tcscmp strcmp 44 | #define _tcsncmp strncmp 45 | #define _tperror perror 46 | #define _texecvp execvp 47 | #define _tmain main 48 | #define _ftprintf fprintf 49 | #define _vftprintf vfprintf 50 | #define _tunlink unlink 51 | #define EXECVP_CAST (char **) 52 | #endif 53 | 54 | #ifdef _UNICODE 55 | #define TS "%ls" 56 | #else 57 | #define TS "%s" 58 | #endif 59 | 60 | #ifdef _WIN32 61 | static inline const TCHAR *escape(const TCHAR *str) { 62 | // If we don't need to escape anything, just return the input string 63 | // as is. 64 | if (!_tcschr(str, ' ') && !_tcschr(str, '"')) 65 | return str; 66 | TCHAR *out = malloc((_tcslen(str) * 2 + 3) * sizeof(*out)); 67 | TCHAR *ptr = out; 68 | int i; 69 | *ptr++ = '"'; 70 | for (i = 0; str[i]; i++) { 71 | if (str[i] == '"') { 72 | int j = i - 1; 73 | // Before all double quotes, backslashes need to be escaped, but 74 | // not elsewhere. 75 | while (j >= 0 && str[j--] == '\\') 76 | *ptr++ = '\\'; 77 | // Escape the next double quote. 78 | *ptr++ = '\\'; 79 | } 80 | *ptr++ = str[i]; 81 | } 82 | // Any final backslashes, before the quote around the whole argument, 83 | // need to be doubled. 84 | int j = i - 1; 85 | while (j >= 0 && str[j--] == '\\') 86 | *ptr++ = '\\'; 87 | *ptr++ = '"'; 88 | *ptr++ = '\0'; 89 | return out; 90 | } 91 | 92 | static inline TCHAR *concat(const TCHAR *prefix, const TCHAR *suffix); 93 | 94 | static TCHAR *make_response_file(const TCHAR **argv) { 95 | if (!argv[1]) 96 | return NULL; 97 | TCHAR *temp_path = malloc(MAX_PATH * sizeof(*temp_path)); 98 | if (GetTempPath(MAX_PATH, temp_path) == 0) 99 | return NULL; 100 | TCHAR *rsp_file = malloc(MAX_PATH * sizeof(*rsp_file)); 101 | if (GetTempFileName(temp_path, _T("ctw"), 0, rsp_file) == 0) 102 | return NULL; 103 | 104 | FILE *f = _tfopen(rsp_file, _T("w, ccs=UNICODE")); 105 | for (int i = 1; argv[i]; i++) 106 | _ftprintf(f, _T(TS"\n"), argv[i]); 107 | fclose(f); 108 | argv[1] = escape(concat(_T("@"), rsp_file)); 109 | argv[2] = NULL; 110 | return rsp_file; 111 | } 112 | 113 | static inline int _tspawnvp_escape(int mode, const TCHAR *filename, const TCHAR * const *argv) { 114 | int num_args = 0; 115 | while (argv[num_args]) 116 | num_args++; 117 | const TCHAR **escaped_argv = malloc((num_args + 1) * sizeof(*escaped_argv)); 118 | int total = 0; 119 | for (int i = 0; argv[i]; i++) { 120 | escaped_argv[i] = escape(argv[i]); 121 | total += 1 + _tcslen(escaped_argv[i]); 122 | } 123 | escaped_argv[num_args] = NULL; 124 | const TCHAR *temp_file = NULL; 125 | if (total > 32000) { 126 | // If we are getting close to the limit, write the arguments to 127 | // a temporary response file. 128 | temp_file = make_response_file(escaped_argv); 129 | if (temp_file) 130 | total = _tcslen(escaped_argv[0]) + _tcslen(escaped_argv[1]) + 2; 131 | } 132 | int ret = _tspawnvp(mode, filename, escaped_argv); 133 | if (temp_file) 134 | DeleteFile(temp_file); 135 | return ret; 136 | } 137 | #else 138 | static inline int _tcsicmp(const TCHAR *a, const TCHAR *b) { 139 | while (*a && tolower(*a) == tolower(*b)) { 140 | a++; 141 | b++; 142 | } 143 | return *a - *b; 144 | } 145 | #endif 146 | 147 | static inline TCHAR *concat(const TCHAR *prefix, const TCHAR *suffix) { 148 | int prefixlen = _tcslen(prefix); 149 | int suffixlen = _tcslen(suffix); 150 | TCHAR *buf = malloc((prefixlen + suffixlen + 1) * sizeof(*buf)); 151 | _tcscpy(buf, prefix); 152 | _tcscpy(buf + prefixlen, suffix); 153 | return buf; 154 | } 155 | 156 | static inline TCHAR *_tcsrchrs(const TCHAR *str, TCHAR char1, TCHAR char2) { 157 | TCHAR *ptr1 = _tcsrchr(str, char1); 158 | TCHAR *ptr2 = _tcsrchr(str, char2); 159 | if (!ptr1) 160 | return ptr2; 161 | if (!ptr2) 162 | return ptr1; 163 | if (ptr1 < ptr2) 164 | return ptr2; 165 | return ptr1; 166 | } 167 | 168 | static inline void split_argv(const TCHAR *argv0, const TCHAR **dir_ptr, const TCHAR **basename_ptr, const TCHAR **target_ptr, const TCHAR **exe_ptr) { 169 | const TCHAR *sep = _tcsrchrs(argv0, '/', '\\'); 170 | TCHAR *dir = _tcsdup(_T("")); 171 | const TCHAR *basename = argv0; 172 | if (sep) { 173 | dir = _tcsdup(argv0); 174 | dir[sep + 1 - argv0] = '\0'; 175 | basename = sep + 1; 176 | } 177 | #ifdef _WIN32 178 | TCHAR module_path[8192]; 179 | GetModuleFileName(NULL, module_path, sizeof(module_path)/sizeof(module_path[0])); 180 | // Try to resolve the given tool name into its long form. If the caller 181 | // called us with a short form executable name, e.g. C__~1.EXE instead of 182 | // c++.exe, we need to resolve the original name, so that the wrapper 183 | // can invoke the right tool with the right arguments. 184 | // 185 | // CMake/Ninja generates such tool names when the tools are located in 186 | // a path with spaces. 187 | TCHAR long_path[8192]; 188 | int long_path_ret = GetLongPathName(module_path, long_path, sizeof(long_path)/sizeof(long_path[0])); 189 | if (long_path_ret > 0 && long_path_ret < sizeof(long_path)/sizeof(long_path[0])) { 190 | sep = _tcsrchrs(long_path, '/', '\\'); 191 | if (sep) 192 | basename = _tcsdup(sep + 1); 193 | } 194 | TCHAR *sep2 = _tcsrchr(module_path, '\\'); 195 | if (sep2) { 196 | sep2[1] = '\0'; 197 | dir = _tcsdup(module_path); 198 | } 199 | #endif 200 | basename = _tcsdup(basename); 201 | TCHAR *period = _tcschr(basename, '.'); 202 | if (period) 203 | *period = '\0'; 204 | TCHAR *target = _tcsdup(basename); 205 | TCHAR *dash = _tcsrchr(target, '-'); 206 | const TCHAR *exe = basename; 207 | if (dash) { 208 | *dash = '\0'; 209 | exe = dash + 1; 210 | // Handle [-]llvm- as exe=llvm- 211 | TCHAR *dash2 = _tcsrchr(target, '-'); 212 | if (dash2 && !_tcscmp(dash2, _T("-llvm"))) { 213 | // Found -llvm-; move the llvm- prefix to 214 | // exe. Convert the original dash which we overwrote with '\0' 215 | // back into a dash and split the string at the preceding dash. 216 | *dash = '-'; 217 | *dash2 = '\0'; 218 | exe = dash2 + 1; 219 | } else if (!_tcscmp(target, _T("llvm"))) { 220 | // Found llvm-; don't treat "llvm" as target but move 221 | // it to the exe part. 222 | exe = basename; 223 | target = NULL; 224 | } 225 | } else { 226 | target = NULL; 227 | } 228 | 229 | if (dir_ptr) 230 | *dir_ptr = dir; 231 | if (basename_ptr) 232 | *basename_ptr = basename; 233 | if (target_ptr) 234 | *target_ptr = target; 235 | if (exe_ptr) 236 | *exe_ptr = exe; 237 | } 238 | 239 | static inline int run_final(const TCHAR *executable, const TCHAR *const *argv) { 240 | #ifdef _WIN32 241 | int ret = _tspawnvp_escape(_P_WAIT, executable, argv); 242 | if (ret == -1) { 243 | _tperror(executable); 244 | return 1; 245 | } 246 | return ret; 247 | #else 248 | // On unix, exec() runs the target executable within this same process, 249 | // making the return code propagate implicitly. 250 | // Windows doesn't have such mechanisms, and the exec() family of functions 251 | // makes the calling process exit immediately and always returning 252 | // a zero return. This doesn't work for our case where we need the 253 | // return code propagated. 254 | _texecvp(executable, EXECVP_CAST argv); 255 | 256 | _tperror(executable); 257 | return 1; 258 | #endif 259 | } 260 | -------------------------------------------------------------------------------- /wrappers/objdump-wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2018 Martin Storsjo 4 | # 5 | # Permission to use, copy, modify, and/or distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | get_dir() { 18 | target="$1" 19 | while [ -L "$target" ]; do 20 | cd "$(dirname "$target")" 21 | target="$(readlink "$(basename "$target")")" 22 | done 23 | cd "$(dirname "$target")" 24 | pwd 25 | } 26 | 27 | DIR="$(get_dir "$0")" 28 | export PATH="$DIR":"$PATH" 29 | 30 | if [ "$1" = "-f" ]; then 31 | # libtool can try to run objdump -f and wants to see certain strings in 32 | # the output, to accept it being a windows (import) library 33 | llvm-readobj $2 | while read -r line; do 34 | case $line in 35 | File:*) 36 | file=$(echo $line | awk '{print $2}') 37 | ;; 38 | Format:*) 39 | format=$(echo $line | awk '{print $2}') 40 | case $format in 41 | COFF-i386) 42 | format=pe-i386 43 | ;; 44 | COFF-x86-64) 45 | format=pe-x86-64 46 | ;; 47 | COFF-ARM*) 48 | # This is wrong; modern COFF armv7 isn't pe-arm-wince, and 49 | # arm64 definitely isn't, but libtool wants to see this 50 | # string (or some of the others) in order to accept it. 51 | format=pe-arm-wince 52 | ;; 53 | esac 54 | echo $file: file format $format 55 | ;; 56 | esac 57 | done 58 | else 59 | llvm-objdump "$@" 60 | fi 61 | -------------------------------------------------------------------------------- /wrappers/x86_64-w64-windows-gnu.cfg: -------------------------------------------------------------------------------- 1 | -target x86_64-w64-mingw32 2 | @mingw32-common.cfg 3 | # SEH is the default for x86_64. 4 | --------------------------------------------------------------------------------