Set rpath on openmp executables
authorJon Chesterfield <jonathanchesterfield@gmail.com>
Mon, 31 Jan 2022 16:01:04 +0000 (16:01 +0000)
committerJon Chesterfield <jonathanchesterfield@gmail.com>
Mon, 31 Jan 2022 16:01:08 +0000 (16:01 +0000)
Openmp executables need to find libomp and libomptarget at runtime.
This currently requires LD_LIBRARY_PATH or the user to specify rpath. Change
that to set the expected location of the openmp libraries in the install tree.

Whether rpath means rpath or runpath is system dependent. The attached test
shows that the Wl,--disable-new-dtags control interacts correctly with this feature.

The implicit rpath field is appended to any user specified ones which is ideal.

Reviewed By: jhuber6

Differential Revision: https://reviews.llvm.org/D118493

clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/lib/Driver/ToolChains/CommonArgs.h
clang/test/OpenMP/Inputs/libomp.a [new file with mode: 0644]
clang/test/OpenMP/implicit_rpath.c [new file with mode: 0644]
openmp/libomptarget/test/lit.cfg

index d3b309d..3ece854 100644 (file)
@@ -3894,6 +3894,11 @@ def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>
   HelpText<"Add -rpath with architecture-specific resource directory to the linker flags">;
 def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Flags<[NoArgumentUnused]>,
   HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags">;
+defm openmp_implicit_rpath: BoolFOption<"openmp-implicit-rpath",
+  LangOpts<"OpenMP">,
+  DefaultTrue,
+  PosFlag<SetTrue, [], "Set rpath on OpenMP executables">,
+  NegFlag<SetFalse>>;
 def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>,
         Group<Link_Group>;
 def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[CC1Option, NoXarchOption]>,
index 1d30090..87f1c8d 100644 (file)
@@ -645,6 +645,22 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
                          /*IsLTO=*/true);
 }
 
+void tools::addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
+                                          const ArgList &Args,
+                                          ArgStringList &CmdArgs) {
+
+  if (Args.hasFlag(options::OPT_fopenmp_implicit_rpath,
+                   options::OPT_fno_openmp_implicit_rpath, true)) {
+    // Default to clang lib / lib64 folder, i.e. the same location as device
+    // runtime
+    SmallString<256> DefaultLibPath =
+        llvm::sys::path::parent_path(TC.getDriver().Dir);
+    llvm::sys::path::append(DefaultLibPath, Twine("lib") + CLANG_LIBDIR_SUFFIX);
+    CmdArgs.push_back("-rpath");
+    CmdArgs.push_back(Args.MakeArgString(DefaultLibPath));
+  }
+}
+
 void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
                                  ArgStringList &CmdArgs) {
   // Enable -frtlib-add-rpath by default for the case of VE.
@@ -702,6 +718,9 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
 
   addArchSpecificRPath(TC, Args, CmdArgs);
 
+  if (RTKind == Driver::OMPRT_OMP)
+    addOpenMPRuntimeSpecificRPath(TC, Args, CmdArgs);
+
   return true;
 }
 
index 00291a3..646fa76 100644 (file)
@@ -106,6 +106,9 @@ void AddAssemblerKPIC(const ToolChain &ToolChain,
                       const llvm::opt::ArgList &Args,
                       llvm::opt::ArgStringList &CmdArgs);
 
+void addOpenMPRuntimeSpecificRPath(const ToolChain &TC,
+                                   const llvm::opt::ArgList &Args,
+                                   llvm::opt::ArgStringList &CmdArgs);
 void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args,
                           llvm::opt::ArgStringList &CmdArgs);
 /// Returns true, if an OpenMP runtime has been added.
diff --git a/clang/test/OpenMP/Inputs/libomp.a b/clang/test/OpenMP/Inputs/libomp.a
new file mode 100644 (file)
index 0000000..8b277f0
--- /dev/null
@@ -0,0 +1 @@
+!<arch>
diff --git a/clang/test/OpenMP/implicit_rpath.c b/clang/test/OpenMP/implicit_rpath.c
new file mode 100644 (file)
index 0000000..d5d6954
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: %clang -fopenmp %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-DEFAULT
+// RUN: %clang -fopenmp -fopenmp-implicit-rpath %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-EXPLICIT
+// RUN: %clang -fopenmp -fno-openmp-implicit-rpath %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-DISABLED
+
+// RUN: %clang -fopenmp -Wl,--disable-new-dtags %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-DEFAULT-RPATH
+// RUN: %clang -fopenmp -fopenmp-implicit-rpath -Wl,--disable-new-dtags %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-EXPLICIT-RPATH
+// RUN: %clang -fopenmp -fno-openmp-implicit-rpath -Wl,--disable-new-dtags %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-DISABLED-RPATH
+
+// RUN: %clang -fopenmp -Wl,--enable-new-dtags %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-DEFAULT-RUNPATH
+// RUN: %clang -fopenmp -fopenmp-implicit-rpath -Wl,--enable-new-dtags %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-EXPLICIT-RUNPATH
+// RUN: %clang -fopenmp -fno-openmp-implicit-rpath -Wl,--enable-new-dtags %s -L%S/Inputs -o %t && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-DISABLED-RUNPATH
+
+// RUN: %clang -Wl,-rpath=early -fopenmp %s -L%S/Inputs -o %t -Wl,-rpath=late && llvm-readelf --dynamic-table %t | FileCheck %s --check-prefixes=CHECK-COMPOSABLE
+
+// CHECK-DEFAULT:      ({{R|RUN}}PATH) Library {{r|run}}path: [{{.*}}llvm{{.*}}lib{{.*}}]
+// CHECK-EXPLICIT:     ({{R|RUN}}PATH) Library {{r|run}}path: [{{.*}}llvm{{.*}}lib{{.*}}]
+// CHECK-DISABLED-NOT: ({{R|RUN}}PATH)
+
+// CHECK-DEFAULT-RPATH:      (RPATH) Library rpath: [{{.*}}llvm{{.*}}lib{{.*}}]
+// CHECK-EXPLICIT-RPATH:     (RPATH) Library rpath: [{{.*}}llvm{{.*}}lib{{.*}}]
+// CHECK-DISABLED-RPATH-NOT: (RPATH)
+
+// CHECK-DEFAULT-RUNPATH:      (RUNPATH) Library runpath: [{{.*}}llvm{{.*}}lib{{.*}}]
+// CHECK-EXPLICIT-RUNPATH:     (RUNPATH) Library runpath: [{{.*}}llvm{{.*}}lib{{.*}}]
+// CHECK-DISABLED-RUNPATH-NOT: (RUNPATH)
+
+// CHECK-COMPOSABLE: ({{R|RUN}}PATH) Library {{r|run}}path: [early:late:{{.*}}llvm{{.*}}lib{{.*}}]
+
+int main() {}
index c21dccc..353466b 100644 (file)
@@ -84,6 +84,8 @@ if supports_unified_shared_memory:
    config.available_features.add('unified_shared_memory')
 
 # Setup environment to find dynamic library at runtime
+# Disable the implicit path to increase certainty over which library is picked up
+config.test_flags += " -fno-openmp-implicit-rpath"
 if config.operating_system == 'Windows':
     append_dynamic_library_path('PATH', config.library_dir, ";")
     append_dynamic_library_path('PATH', config.omp_host_rtl_directory, ";")