1#!/bin/bash 2set -x -e -v 3 4# This script is for building a mingw-clang toolchain for use on Linux. 5 6if [[ $# -eq 0 ]]; then 7 echo "Provide either x86 or x64 to specify a toolchain." 8 exit 1; 9elif [ "$1" == "x86" ]; then 10 machine="i686" 11 compiler_rt_machine="i386" 12 crt_flags="--enable-lib32 --disable-lib64" 13 WRAPPER_FLAGS="" 14elif [ "$1" == "x64" ]; then 15 machine="x86_64" 16 compiler_rt_machine="x86_64" 17 crt_flags="--disable-lib32 --enable-lib64" 18 WRAPPER_FLAGS="" 19else 20 echo "Provide either x86 or x64 to specify a toolchain." 21 exit 1; 22fi 23 24TOOLCHAIN_DIR=$MOZ_FETCHES_DIR/llvm-project 25INSTALL_DIR=$TOOLCHAIN_DIR/build/stage4/clang 26CROSS_PREFIX_DIR=$INSTALL_DIR/$machine-w64-mingw32 27 28make_flags="-j$(nproc)" 29 30if [ -d "$MOZ_FETCHES_DIR/binutils/bin" ]; then 31 export PATH="$MOZ_FETCHES_DIR/binutils/bin:$PATH" 32fi 33 34# This is default value of _WIN32_WINNT. Gecko configure script explicitly sets this, 35# so this is not used to build Gecko itself. We default to 0x601, which is Windows 7. 36default_win32_winnt=0x601 37 38cd $GECKO_PATH 39 40patch_file1="$(pwd)/taskcluster/scripts/misc/mingw-winrt.patch" 41patch_file2="$(pwd)/taskcluster/scripts/misc/mingw-dwrite_3.patch" 42patch_file3="$(pwd)/taskcluster/scripts/misc/mingw-unknown.patch" 43 44prepare() { 45 pushd $MOZ_FETCHES_DIR/mingw-w64 46 patch -p1 <$patch_file1 47 patch -p1 <$patch_file2 48 patch -p1 <$patch_file3 49 popd 50} 51 52install_wrappers() { 53 pushd $INSTALL_DIR/bin 54 55 compiler_flags="--sysroot \$DIR/../$machine-w64-mingw32 -rtlib=compiler-rt -stdlib=libc++ -fuse-ld=lld $WRAPPER_FLAGS -fuse-cxa-atexit -Qunused-arguments" 56 57 cat <<EOF >$machine-w64-mingw32-clang 58#!/bin/sh 59DIR="\$(cd "\$(dirname "\$0")" && pwd)" 60\$DIR/clang -target $machine-w64-mingw32 $compiler_flags "\$@" 61EOF 62 chmod +x $machine-w64-mingw32-clang 63 64 cat <<EOF >$machine-w64-mingw32-clang++ 65#!/bin/sh 66DIR="\$(cd "\$(dirname "\$0")" && pwd)" 67\$DIR/clang -target $machine-w64-mingw32 --driver-mode=g++ $compiler_flags "\$@" 68EOF 69 chmod +x $machine-w64-mingw32-clang++ 70 71 CC="$machine-w64-mingw32-clang" 72 CXX="$machine-w64-mingw32-clang++" 73 74 popd 75} 76 77build_mingw() { 78 mkdir mingw-w64-headers 79 pushd mingw-w64-headers 80 $MOZ_FETCHES_DIR/mingw-w64/mingw-w64-headers/configure \ 81 --host=$machine-w64-mingw32 \ 82 --enable-sdk=all \ 83 --enable-idl \ 84 --with-default-msvcrt=ucrt \ 85 --with-default-win32-winnt=$default_win32_winnt \ 86 --prefix=$CROSS_PREFIX_DIR 87 make $make_flags install 88 popd 89 90 mkdir mingw-w64-crt 91 pushd mingw-w64-crt 92 $MOZ_FETCHES_DIR/mingw-w64/mingw-w64-crt/configure \ 93 --host=$machine-w64-mingw32 \ 94 $crt_flags \ 95 --with-default-msvcrt=ucrt \ 96 CC="$CC" \ 97 AR=llvm-ar \ 98 RANLIB=llvm-ranlib \ 99 DLLTOOL=llvm-dlltool \ 100 --prefix=$CROSS_PREFIX_DIR 101 make $make_flags 102 make $make_flags install 103 popd 104 105 mkdir widl 106 pushd widl 107 $MOZ_FETCHES_DIR/mingw-w64/mingw-w64-tools/widl/configure --target=$machine-w64-mingw32 --prefix=$INSTALL_DIR 108 make $make_flags 109 make $make_flags install 110 popd 111} 112 113build_compiler_rt() { 114 CLANG_VERSION=$(basename $(dirname $(dirname $(dirname $($CC --print-libgcc-file-name -rtlib=compiler-rt))))) 115 mkdir compiler-rt 116 pushd compiler-rt 117 cmake \ 118 -DCMAKE_BUILD_TYPE=Release \ 119 -DCMAKE_C_COMPILER=$CC \ 120 -DCMAKE_SYSTEM_NAME=Windows \ 121 -DCMAKE_AR=$INSTALL_DIR/bin/llvm-ar \ 122 -DCMAKE_RANLIB=$INSTALL_DIR/bin/llvm-ranlib \ 123 -DCMAKE_C_COMPILER_WORKS=1 \ 124 -DCMAKE_C_COMPILER_TARGET=$compiler_rt_machine-windows-gnu \ 125 -DCOMPILER_RT_DEFAULT_TARGET_ONLY=TRUE \ 126 $TOOLCHAIN_DIR/compiler-rt/lib/builtins 127 make $make_flags 128 mkdir -p $INSTALL_DIR/lib/clang/$CLANG_VERSION/lib/windows 129 cp lib/windows/libclang_rt.builtins-$compiler_rt_machine.a $INSTALL_DIR/lib/clang/$CLANG_VERSION/lib/windows/ 130 popd 131} 132 133merge_libs() { 134 cat <<EOF |llvm-ar -M 135CREATE tmp.a 136ADDLIB $1 137ADDLIB $2 138SAVE 139END 140EOF 141 llvm-ranlib tmp.a 142 mv tmp.a $1 143} 144 145build_libcxx() { 146 # Below, we specify -g -gcodeview to build static libraries with debug information. 147 # Because we're not distributing these builds, this is fine. If one were to distribute 148 # the builds, perhaps one would want to make those flags conditional or investigation 149 # other options. 150 DEBUG_FLAGS="-g -gcodeview" 151 152 mkdir libunwind 153 pushd libunwind 154 cmake \ 155 -DCMAKE_BUILD_TYPE=Release \ 156 -DCMAKE_INSTALL_PREFIX=$CROSS_PREFIX_DIR \ 157 -DCMAKE_C_COMPILER=$CC \ 158 -DCMAKE_CXX_COMPILER=$CXX \ 159 -DCMAKE_CROSSCOMPILING=TRUE \ 160 -DCMAKE_SYSROOT=$CROSS_PREFIX_DIR \ 161 -DCMAKE_SYSTEM_NAME=Windows \ 162 -DCMAKE_C_COMPILER_WORKS=TRUE \ 163 -DCMAKE_CXX_COMPILER_WORKS=TRUE \ 164 -DLLVM_COMPILER_CHECKED=TRUE \ 165 -DCMAKE_AR=$INSTALL_DIR/bin/llvm-ar \ 166 -DCMAKE_RANLIB=$INSTALL_DIR/bin/llvm-ranlib \ 167 -DLLVM_NO_OLD_LIBSTDCXX=TRUE \ 168 -DCXX_SUPPORTS_CXX11=TRUE \ 169 -DCXX_SUPPORTS_CXX_STD=TRUE \ 170 -DLIBUNWIND_USE_COMPILER_RT=TRUE \ 171 -DLIBUNWIND_ENABLE_THREADS=TRUE \ 172 -DLIBUNWIND_ENABLE_SHARED=FALSE \ 173 -DLIBUNWIND_ENABLE_CROSS_UNWINDING=FALSE \ 174 -DCMAKE_CXX_FLAGS="${DEBUG_FLAGS} -Wno-dll-attribute-on-redeclaration -nostdinc++ -I$TOOLCHAIN_DIR/libcxx/include -DPSAPI_VERSION=2" \ 175 -DCMAKE_C_FLAGS="-Wno-dll-attribute-on-redeclaration" \ 176 $MOZ_FETCHES_DIR/libunwind 177 make $make_flags 178 make $make_flags install 179 popd 180 181 mkdir libcxxabi 182 pushd libcxxabi 183 cmake \ 184 -DCMAKE_BUILD_TYPE=Release \ 185 -DCMAKE_INSTALL_PREFIX=$CROSS_PREFIX_DIR \ 186 -DCMAKE_C_COMPILER=$CC \ 187 -DCMAKE_CXX_COMPILER=$CXX \ 188 -DCMAKE_CROSSCOMPILING=TRUE \ 189 -DCMAKE_SYSTEM_NAME=Windows \ 190 -DCMAKE_C_COMPILER_WORKS=TRUE \ 191 -DCMAKE_CXX_COMPILER_WORKS=TRUE \ 192 -DCMAKE_SYSROOT=$CROSS_PREFIX_DIR \ 193 -DLLVM_COMPILER_CHECKED=TRUE \ 194 -DCMAKE_AR=$INSTALL_DIR/bin/llvm-ar \ 195 -DCMAKE_RANLIB=$INSTALL_DIR/bin/llvm-ranlib \ 196 -DLIBCXXABI_USE_COMPILER_RT=ON \ 197 -DLIBCXXABI_ENABLE_EXCEPTIONS=ON \ 198 -DLIBCXXABI_ENABLE_THREADS=ON \ 199 -DLIBCXXABI_TARGET_TRIPLE=$machine-w64-mingw32 \ 200 -DLIBCXXABI_ENABLE_SHARED=OFF \ 201 -DLIBCXXABI_LIBCXX_INCLUDES=$TOOLCHAIN_DIR/libcxx/include \ 202 -DLLVM_NO_OLD_LIBSTDCXX=TRUE \ 203 -DCXX_SUPPORTS_CXX11=TRUE \ 204 -DCXX_SUPPORTS_CXX_STD=TRUE \ 205 -DCMAKE_CXX_FLAGS="${DEBUG_FLAGS} -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_HAS_THREAD_API_WIN32" \ 206 $TOOLCHAIN_DIR/libcxxabi 207 make $make_flags VERBOSE=1 208 popd 209 210 mkdir libcxx 211 pushd libcxx 212 cmake \ 213 -DCMAKE_BUILD_TYPE=Release \ 214 -DCMAKE_INSTALL_PREFIX=$CROSS_PREFIX_DIR \ 215 -DCMAKE_C_COMPILER=$CC \ 216 -DCMAKE_CXX_COMPILER=$CXX \ 217 -DCMAKE_CROSSCOMPILING=TRUE \ 218 -DCMAKE_SYSTEM_NAME=Windows \ 219 -DCMAKE_C_COMPILER_WORKS=TRUE \ 220 -DCMAKE_CXX_COMPILER_WORKS=TRUE \ 221 -DLLVM_COMPILER_CHECKED=TRUE \ 222 -DCMAKE_AR=$INSTALL_DIR/bin/llvm-ar \ 223 -DCMAKE_RANLIB=$INSTALL_DIR/bin/llvm-ranlib \ 224 -DLIBCXX_USE_COMPILER_RT=ON \ 225 -DLIBCXX_INSTALL_HEADERS=ON \ 226 -DLIBCXX_ENABLE_EXCEPTIONS=ON \ 227 -DLIBCXX_ENABLE_THREADS=ON \ 228 -DLIBCXX_HAS_WIN32_THREAD_API=ON \ 229 -DLIBCXX_ENABLE_MONOTONIC_CLOCK=ON \ 230 -DLIBCXX_ENABLE_SHARED=OFF \ 231 -DLIBCXX_SUPPORTS_STD_EQ_CXX11_FLAG=TRUE \ 232 -DLIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB=TRUE \ 233 -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF \ 234 -DLIBCXX_ENABLE_FILESYSTEM=OFF \ 235 -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=TRUE \ 236 -DLIBCXX_CXX_ABI=libcxxabi \ 237 -DLIBCXX_CXX_ABI_INCLUDE_PATHS=$TOOLCHAIN_DIR/libcxxabi/include \ 238 -DLIBCXX_CXX_ABI_LIBRARY_PATH=../libcxxabi/lib \ 239 -DCMAKE_CXX_FLAGS="${DEBUG_FLAGS} -D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS" \ 240 $TOOLCHAIN_DIR/libcxx 241 make $make_flags VERBOSE=1 242 make $make_flags install 243 244 # libc++.a depends on libunwind.a. Whild linker will automatically link 245 # to libc++.a in C++ mode, it won't pick libunwind.a, requiring caller 246 # to explicitly pass -lunwind. Wo work around that, we merge libunwind.a 247 # into libc++.a. 248 merge_libs $CROSS_PREFIX_DIR/lib/libc++.a $CROSS_PREFIX_DIR/lib/libunwind.a 249 popd 250} 251 252build_libssp() { 253 pushd $MOZ_FETCHES_DIR/gcc-source/ 254 255 # Massage the environment for the build-libssp.sh script 256 mkdir -p ./$machine-w64-mingw32/lib 257 cp $MOZ_FETCHES_DIR/llvm-mingw/libssp-Makefile . 258 sed -i 's/set -e/set -x -e -v/' $MOZ_FETCHES_DIR/llvm-mingw/build-libssp.sh 259 sed -i 's/(CROSS)gcc/(CROSS)clang/' libssp-Makefile 260 sed -i 's/\$(CROSS)ar/llvm-ar/' libssp-Makefile 261 OLDPATH=$PATH 262 PATH=$INSTALL_DIR/clang/bin:$PATH 263 264 # Run the script 265 TOOLCHAIN_ARCHS=$machine $MOZ_FETCHES_DIR/llvm-mingw/build-libssp.sh . 266 267 # Grab the artifacts, cleanup 268 cp $MOZ_FETCHES_DIR/gcc-source/$machine-w64-mingw32/lib/{libssp.a,libssp_nonshared.a} $INSTALL_DIR/$machine-w64-mingw32/lib/ 269 unset TOOLCHAIN_ARCHS 270 PATH=$OLDPATH 271 popd 272} 273 274build_utils() { 275 pushd $INSTALL_DIR/bin/ 276 ln -s llvm-nm $machine-w64-mingw32-nm 277 ln -s llvm-strip $machine-w64-mingw32-strip 278 ln -s llvm-readobj $machine-w64-mingw32-readobj 279 ln -s llvm-objcopy $machine-w64-mingw32-objcopy 280 ./clang $MOZ_FETCHES_DIR/llvm-mingw/wrappers/windres-wrapper.c -O2 -Wl,-s -o $machine-w64-mingw32-windres 281 popd 282} 283 284export PATH=$INSTALL_DIR/bin:$PATH 285 286prepare 287 288# gets a bit too verbose here 289set +x 290 291cd $TOOLCHAIN_DIR 292python3 $GECKO_PATH/build/build-clang/build-clang.py -c $GECKO_PATH/$2 --skip-tar 293 294set -x 295 296pushd $TOOLCHAIN_DIR/build 297 298install_wrappers 299build_mingw 300build_compiler_rt 301build_libcxx 302build_libssp 303build_utils 304 305popd 306 307# Put a tarball in the artifacts dir 308mkdir -p $UPLOAD_DIR 309 310pushd $(dirname $INSTALL_DIR) 311tar caf clangmingw.tar.zst clang 312mv clangmingw.tar.zst $UPLOAD_DIR 313popd 314