diff --git a/P/pocl/build_tarballs.jl b/P/pocl/build_tarballs.jl index 5a8e25d5049..523ee0a0a89 100644 --- a/P/pocl/build_tarballs.jl +++ b/P/pocl/build_tarballs.jl @@ -24,7 +24,7 @@ sources = [ #= -POCL wants to be linked against LLVM for run-time code generation, but also generates code +PoCL wants to be linked against LLVM for run-time code generation, but also generates code at compile time using LLVM tools, so we need to carefully select which of the different builds of LLVM we need: @@ -48,18 +48,19 @@ atomic_patch -p1 $WORKSPACE/srcdir/patches/freebsd.patch atomic_patch -p1 $WORKSPACE/srcdir/patches/distro-generic.patch atomic_patch -p1 $WORKSPACE/srcdir/patches/env-override.patch atomic_patch -p1 $WORKSPACE/srcdir/patches/env-override-ld.patch +atomic_patch -p1 $WORKSPACE/srcdir/patches/env-override-args.patch # POCL wants a target sysroot for compiling the host kernellib (for `math.h` etc) -sysroot=/opt/${target}/${target}/sys-root/usr/include +sysroot=/opt/${target}/${target}/sys-root if [[ "${target}" == *apple* ]]; then # XXX: including the sysroot like this doesn't work on Apple, missing definitions like # TARGET_OS_IPHONE. it seems like these headers should be included using -isysroot, # but (a) that doesn't seem to work, and (b) isn't that already done by the cmake # toolchain file? work around the issue by inserting an include for the missing # definitions at the top of the headers included from POCL's kernel library. - sed -i '1s/^/#include \n/' $sysroot/stdio.h + sed -i '1s/^/#include \n/' $sysroot/usr/include/stdio.h fi -sed -i "s|COMMENT \\"Building C to LLVM bitcode \${BC_FILE}\\"|\\"-I$sysroot\\"|" \ +sed -i "s|COMMENT \\"Building C to LLVM bitcode \${BC_FILE}\\"|\\"-I$sysroot/usr/include\\"|" \ cmake/bitcode_rules.cmake CMAKE_FLAGS=() @@ -95,6 +96,29 @@ fi cmake -B build -S . -GNinja ${CMAKE_FLAGS[@]} ninja -C build -j ${nproc} install + +# PoCL uses Clang, which relies on certain system libraries Clang_jll.jl doesn't provide +mkdir -p $prefix/share/lib +if [[ ${target} == *-linux-gnu-* ]]; then + if [[ "${nbits}" == 64 ]]; then + cp -a $sysroot/lib64/libc{.,-}* $prefix/share/lib + cp -a $sysroot/usr/lib64/libm.* $prefix/share/lib + ln -sf libm.so.6 $prefix/share/lib/libm.so + cp -a $sysroot/lib64/libm{.,-}* $prefix/share/lib + cp -a /opt/${target}/${target}/lib64/libgcc_s.* $prefix/share/lib + cp -a /opt/$target/lib/gcc/$target/*/*.{o,a} $prefix/share/lib + else + cp -a $sysroot/lib/libc{.,-}* $prefix/share/lib + cp -a $sysroot/usr/lib/libm.* $prefix/share/lib + ln -sf libm.so.6 $prefix/share/lib/libm.so + cp -a $sysroot/lib/libm{.,-}* $prefix/share/lib + cp -a /opt/${target}/${target}/lib/libgcc_s.* $prefix/share/lib + cp -a /opt/$target/lib/gcc/$target/*/*.{o,a} $prefix/share/lib + fi +elif [[ ${target} == *-linux-musl-* ]]; then + cp -a $sysroot/usr/lib/*.{o,a} $prefix/share/lib + cp -a /opt/$target/lib/gcc/$target/*/*.{o,a} $prefix/share/lib +fi """ # These are the platforms we will build for by default, unless further @@ -206,9 +230,13 @@ init_block = raw""" else error("Unsupported platform") end - ENV["POCL_PATH_LD"] = - generate_wrapper_script("lld", ld_path, - LLD_unified_jll.LIBPATH[], LLD_unified_jll.PATH[]) + ld_wrapper = generate_wrapper_script("lld", ld_path, + LLD_unified_jll.LIBPATH[], + LLD_unified_jll.PATH[]) + ENV["POCL_ARGS_CLANG"] = join([ + "-fuse-ld=lld", "--ld-path=$ld_wrapper", + "-L" * joinpath(artifact_dir, "share", "lib") + ], ";") """ # determine exactly which tarballs we should build diff --git a/P/pocl/bundled/patches/env-override-args.patch b/P/pocl/bundled/patches/env-override-args.patch new file mode 100644 index 00000000000..298d5076e83 --- /dev/null +++ b/P/pocl/bundled/patches/env-override-args.patch @@ -0,0 +1,119 @@ +From 4663081155ce0af4ebacd5a3429eba9449f35b0f Mon Sep 17 00:00:00 2001 +From: Tim Besard +Date: Mon, 21 Oct 2024 09:40:13 +0200 +Subject: [PATCH] Replace POCL_PATH_LD by a more generic POCL_ARGS_CLANG. + +--- + doc/sphinx/source/using.rst | 12 +++++++++++- + lib/CL/pocl_llvm_build.cc | 12 ++++++++---- + lib/CL/pocl_runtime_config.c | 28 ++++++++++++++++++++++++++++ + lib/CL/pocl_runtime_config.h | 3 +++ + 4 files changed, 50 insertions(+), 5 deletions(-) + +diff --git a/doc/sphinx/source/using.rst b/doc/sphinx/source/using.rst +index cdf9b5172..b366e611b 100644 +--- a/doc/sphinx/source/using.rst ++++ b/doc/sphinx/source/using.rst +@@ -311,13 +311,23 @@ pocl. + The following variables are available: + + * **POCL_PATH_CLANG** -- Path to the clang executable. +- * **POCL_PATH_LD** -- Path to the ld executable used by clang. + * **POCL_PATH_LLVM_LINK** -- Path to the llvm-link executable. + * **POCL_PATH_LLVM_OPT** -- Path to the llvm-opt executable. + * **POCL_PATH_LLVM_LLC** -- Path to the llc executable. + * **POCL_PATH_LLVM_SPIRV** -- Path to the llvm-spirv executable. + * **POCL_PATH_SPIRV_LINK** -- Path to the spirv-link executable. + ++- **POCL_ARGS_XXX** ++ ++ String. These variables can be used to pass additional arguments to executables ++ that pocl invokes during compilation, linking, etc. Multiple arguments can be ++ passed by separating them with a semicolon. ++ ++ The following variables are available: ++ ++ * **POCL_ARGS_CLANG** -- Additional arguments to pass to clang. ++ ++ + - **POCL_SIGFPE_HANDLER** + + Defaults to 1. If set to 0, pocl will not install the SIGFPE handler. +diff --git a/lib/CL/pocl_llvm_build.cc b/lib/CL/pocl_llvm_build.cc +index b425d5edc..1892ab13d 100644 +--- a/lib/CL/pocl_llvm_build.cc ++++ b/lib/CL/pocl_llvm_build.cc +@@ -1047,15 +1047,19 @@ int pocl_invoke_clang(cl_device_id Device, const char** Args) { + while (*ArgsEnd++ != nullptr) {} + llvm::SmallVector ArgsArray(Args, ArgsEnd); + +- std::string LDPath; +- if (const char* LDOverride = pocl_get_path("LD", nullptr)) { +- LDPath = "--ld-path=" + std::string(LDOverride); +- ArgsArray.push_back(LDPath.c_str()); ++ int NumExtraArgs; ++ const char *ExtraArgs = pocl_get_args("CLANG", &NumExtraArgs); ++ const char *ExtraArg = ExtraArgs; ++ for (int i = 0; i < NumExtraArgs; ++i) { ++ ArgsArray.push_back(ExtraArg); ++ ExtraArg += strlen(ExtraArg) + 1; + } + + std::unique_ptr C( + TheDriver.BuildCompilation(ArgsArray)); + ++ free((void *)ExtraArgs); ++ + if (C && !C->containsError()) { + SmallVector, 4> FailingCommands; + return TheDriver.ExecuteCompilation(*C, FailingCommands); +diff --git a/lib/CL/pocl_runtime_config.c b/lib/CL/pocl_runtime_config.c +index 3f596549e..4a7e38b54 100644 +--- a/lib/CL/pocl_runtime_config.c ++++ b/lib/CL/pocl_runtime_config.c +@@ -67,3 +67,31 @@ pocl_get_path (const char *name, const char *default_value) + snprintf (key, sizeof (key), "POCL_PATH_%s", name); + return pocl_get_string_option (key, default_value); + } ++ ++/* Returns `n` null-terminated strings representing arguments ++ for an invocation. Can be set using the POCL_ARGS env vars. ++ If the env var is not set, returns NULL and sets `n` to zero. */ ++char * ++pocl_get_args (const char *name, int *n) ++{ ++ char key[256]; ++ snprintf (key, sizeof (key), "POCL_ARGS_%s", name); ++ const char *val = getenv (key); ++ if (val == NULL) ++ { ++ *n = 0; ++ return NULL; ++ } ++ ++ char *args = strdup (val); ++ *n = 1; ++ for (char *p = args; *p; ++p) ++ { ++ if (*p == ';') ++ { ++ *p = 0; ++ ++(*n); ++ } ++ } ++ return args; ++} +diff --git a/lib/CL/pocl_runtime_config.h b/lib/CL/pocl_runtime_config.h +index 3d58a7b9e..6dafd5340 100644 +--- a/lib/CL/pocl_runtime_config.h ++++ b/lib/CL/pocl_runtime_config.h +@@ -43,6 +43,9 @@ const char* pocl_get_string_option(const char *key, const char *default_value); + POCL_EXPORT + const char *pocl_get_path (const char *name, const char *default_value); + ++POCL_EXPORT ++char *pocl_get_args (const char *name, int *n); ++ + #ifdef __cplusplus + } + #endif