From 9031eb67914b707c8b500cf0c660e5e564ff41c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Sat, 10 Oct 2020 23:57:44 +0300 Subject: [PATCH] Build the OpenMP runtime in docker based builds LLVM's OpenMP implementation only supports Windows on x86, and it requires a MASM-compatible assembler to build it. Build UASM for this purpose, for now. (UASM isn't available packaged in debian/ubuntu repos.) In the future, llvm-ml should be able to handle it instead, but it's not currently mature enough. Not including it in the regular build-all.sh for now, as UASM isn't generally available. --- Dockerfile | 13 ++++- Dockerfile.dev | 28 ++++++++++ build-openmp.sh | 115 +++++++++++++++++++++++++++++++++++++++ run-tests.sh | 12 +++- test/hello-omp.c | 27 +++++++++ wrappers/uasm-wrapper.sh | 29 ++++++++++ 6 files changed, 222 insertions(+), 2 deletions(-) create mode 100755 build-openmp.sh create mode 100644 test/hello-omp.c create mode 100755 wrappers/uasm-wrapper.sh diff --git a/Dockerfile b/Dockerfile index ce46f39..e637d91 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,8 +19,18 @@ ARG TOOLCHAIN_ARCHS="i686 x86_64 armv7 aarch64" ARG DEFAULT_CRT=ucrt +# Build UASM, for building openmp. In the future, llvm-ml should be able +# to handle it, but it doesn't yet. +RUN git clone https://github.com/Terraspace/UASM && \ + cd UASM && \ + git checkout 16a853bd6de807fe2c42569f8375a029684c0f22 && \ + make -f gccLinux64.mak -j$(nproc) && \ + mkdir -p $TOOLCHAIN_PREFIX/bin && \ + cp GccUnixR/uasm $TOOLCHAIN_PREFIX/bin +COPY wrappers/uasm-wrapper.sh $TOOLCHAIN_PREFIX/bin + # Build everything that uses the llvm monorepo. We need to build the mingw runtime before the compiler-rt/libunwind/libcxxabi/libcxx runtimes. -COPY build-llvm.sh strip-llvm.sh install-wrappers.sh build-mingw-w64.sh build-mingw-w64-tools.sh build-compiler-rt.sh build-mingw-w64-libraries.sh build-libcxx.sh ./ +COPY build-llvm.sh strip-llvm.sh install-wrappers.sh build-mingw-w64.sh build-mingw-w64-tools.sh build-compiler-rt.sh build-mingw-w64-libraries.sh build-libcxx.sh build-openmp.sh ./ COPY wrappers/*.sh wrappers/*.c wrappers/*.h ./wrappers/ RUN ./build-llvm.sh $TOOLCHAIN_PREFIX && \ ./strip-llvm.sh $TOOLCHAIN_PREFIX && \ @@ -31,6 +41,7 @@ RUN ./build-llvm.sh $TOOLCHAIN_PREFIX && \ ./build-mingw-w64-libraries.sh $TOOLCHAIN_PREFIX && \ ./build-libcxx.sh $TOOLCHAIN_PREFIX && \ ./build-compiler-rt.sh $TOOLCHAIN_PREFIX --build-sanitizers && \ + ./build-openmp.sh $TOOLCHAIN_PREFIX && \ rm -rf /build/* # Build libssp diff --git a/Dockerfile.dev b/Dockerfile.dev index d85e1c9..f2fd6cc 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -127,6 +127,34 @@ RUN cd test && \ done; \ done +# Build UASM, for building openmp. In the future, llvm-ml should be able +# to handle it, but it doesn't yet. +RUN git clone https://github.com/Terraspace/UASM && \ + cd UASM && \ + git checkout 16a853bd6de807fe2c42569f8375a029684c0f22 && \ + make -f gccLinux64.mak -j$(nproc) && \ + mkdir -p $TOOLCHAIN_PREFIX/bin && \ + cp GccUnixR/uasm $TOOLCHAIN_PREFIX/bin +COPY wrappers/uasm-wrapper.sh $TOOLCHAIN_PREFIX/bin +# Build OpenMP +COPY build-openmp.sh ./ +RUN ./build-openmp.sh $TOOLCHAIN_PREFIX + +# OpenMP on windows only supports x86. +RUN cd test && \ + for arch in $TOOLCHAIN_ARCHS; do \ + case $arch in \ + i686|x86_64) \ + ;; \ + *) \ + continue \ + ;; \ + esac && \ + for test in hello-omp; do \ + $arch-w64-mingw32-clang $test.c -o $arch/$test.exe -fopenmp=libomp || exit 1; \ + done; \ + done + RUN cd test && \ for arch in $TOOLCHAIN_ARCHS; do \ cp $TOOLCHAIN_PREFIX/$arch-w64-mingw32/bin/*.dll $arch || exit 1; \ diff --git a/build-openmp.sh b/build-openmp.sh new file mode 100755 index 0000000..7cfc89a --- /dev/null +++ b/build-openmp.sh @@ -0,0 +1,115 @@ +#!/bin/sh +# +# Copyright (c) 2020 Martin Storsjo +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +set -e + +PREFIX="$1" +if [ -z "$PREFIX" ]; then + echo $0 dest + exit 1 +fi + +mkdir -p "$PREFIX" +PREFIX="$(cd "$PREFIX" && pwd)" + +export PATH="$PREFIX/bin:$PATH" + +: ${ARCHS:=${TOOLCHAIN_ARCHS-i686 x86_64 armv7 aarch64}} + +if [ ! -d llvm-project/openmp ] || [ -n "$SYNC" ]; then + CHECKOUT_ONLY=1 ./build-llvm.sh +fi + +cd llvm-project/openmp + +if [ -n "$(which ninja)" ]; then + CMAKE_GENERATOR="Ninja" + NINJA=1 + BUILDCMD=ninja +else + : ${CORES:=$(nproc 2>/dev/null)} + : ${CORES:=$(sysctl -n hw.ncpu 2>/dev/null)} + : ${CORES:=4} + + case $(uname) in + MINGW*) + CMAKE_GENERATOR="MSYS Makefiles" + ;; + *) + ;; + esac + BUILDCMD=make +fi + +if [ ! -x "$(which uasm)" ]; then + echo Building the OpenMP runtime requires UASM + exit 1 +fi +UASM=uasm +case $(uname) in +MINGW*|MSYS*) + # On windows, only building with ninja works; building with msys make + # ends up mangling the forward slashes in certain options to UASM. + ;; +*) + # UASM for unix doesn't support options with forward slashes, which CMake + # produces in some places. And ninja on windows can't execute a + # shell script, so this has to be done only on unix. + UASM=uasm-wrapper.sh + ;; +esac + +for arch in $ARCHS; do + CMAKEFLAGS="" + case $arch in + i686) + ;; + x86_64) + CMAKEFLAGS="$CMAKEFLAGS -DLIBOMP_ASMFLAGS=-win64" + ;; + *) + # Not supported + continue + ;; + esac + + [ -z "$CLEAN" ] || rm -rf build-$arch + mkdir -p build-$arch + cd build-$arch + + cmake \ + ${CMAKE_GENERATOR+-G} "$CMAKE_GENERATOR" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$PREFIX/$arch-w64-mingw32" \ + -DCMAKE_C_COMPILER=$arch-w64-mingw32-clang \ + -DCMAKE_CXX_COMPILER=$arch-w64-mingw32-clang++ \ + -DCMAKE_RC_COMPILER=$arch-w64-mingw32-windres \ + -DCMAKE_ASM_MASM_COMPILER=$UASM \ + -DCMAKE_CROSSCOMPILING=TRUE \ + -DCMAKE_SYSTEM_NAME=Windows \ + -DCMAKE_C_COMPILER_WORKS=TRUE \ + -DCMAKE_CXX_COMPILER_WORKS=TRUE \ + -DCMAKE_AR="$PREFIX/bin/llvm-ar" \ + -DCMAKE_RANLIB="$PREFIX/bin/llvm-ranlib" \ + -DLIBOMP_ENABLE_SHARED=TRUE \ + $CMAKEFLAGS \ + .. + $BUILDCMD ${CORES+-j$CORES} + $BUILDCMD install + rm -f $PREFIX/$arch-w64-mingw32/bin/*iomp5md* + rm -f $PREFIX/$arch-w64-mingw32/lib/*iomp5md* + cd .. +done diff --git a/run-tests.sh b/run-tests.sh index 95ad63b..42a5fcc 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -69,6 +69,7 @@ TESTS_CPP_DLL="tlstest-lib" TESTS_SSP="stacksmash" TESTS_ASAN="stacksmash" TESTS_UBSAN="ubsan" +TESTS_OMP="hello-omp" TESTS_UWP="uwp-error" TESTS_IDL="idltest" TESTS_OTHER_TARGETS="hello" @@ -196,12 +197,21 @@ for arch in $ARCHS; do $arch-w64-mingw32-clang $test.c -o $TEST_DIR/$test.exe -fsanitize=undefined TESTS_EXTRA="$TESTS_EXTRA $test" done + for test in $TESTS_OMP; do + case $arch in + # OpenMP on windows only supports x86. + i686|x86_64) ;; + *) continue ;; + esac + $arch-w64-mingw32-clang $test.c -o $TEST_DIR/$test.exe -fopenmp=libomp + TESTS_EXTRA="$TESTS_EXTRA $test" + done DLL="$TESTS_C_DLL $TESTS_CPP_DLL" compiler_rt_arch=$arch if [ "$arch" = "i686" ]; then compiler_rt_arch=i386 fi - for i in libc++ libunwind libssp-0 libclang_rt.asan_dynamic-$compiler_rt_arch; do + for i in libc++ libunwind libssp-0 libclang_rt.asan_dynamic-$compiler_rt_arch libomp; do if [ -f $PREFIX/$arch-w64-mingw32/bin/$i.dll ]; then cp $PREFIX/$arch-w64-mingw32/bin/$i.dll $TEST_DIR DLL="$DLL $i" diff --git a/test/hello-omp.c b/test/hello-omp.c new file mode 100644 index 0000000..24695df --- /dev/null +++ b/test/hello-omp.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020 Martin Storsjo + * + * This file is part of llvm-mingw. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +int main(int argc, char *argv[]) { +#pragma omp parallel + printf("thread %d, nthreads %d\n", omp_get_thread_num(), + omp_get_num_threads()); + return 0; +} diff --git a/wrappers/uasm-wrapper.sh b/wrappers/uasm-wrapper.sh new file mode 100755 index 0000000..d69e8b5 --- /dev/null +++ b/wrappers/uasm-wrapper.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Copyright (c) 2020 Martin Storsjo +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ARGS="" +while [ $# -gt 0 ]; do + a="$1" + case $a in + /safeseh|/coff|/c|/Fo) + a="-${a#/}" + ;; + esac + ARGS="$ARGS $a" + shift +done + +uasm $ARGS