Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang][Driver] Add the ability to specify that RPATH should be added by default #115163

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

pawosm-arm
Copy link
Contributor

The -frtlib-add-rpath is very convenient when linking against various runtimes (OpenMP, Fortran, sanitizers), so much so we could argue that this should be a default behavior.

This patch adds the ability to specify (at CMake level) that RPATH should be added by default.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' flang:driver flang Flang issues not falling into any other category labels Nov 6, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Nov 6, 2024

@llvm/pr-subscribers-flang-driver

@llvm/pr-subscribers-clang

Author: Paul Osmialowski (pawosm-arm)

Changes

The -frtlib-add-rpath is very convenient when linking against various runtimes (OpenMP, Fortran, sanitizers), so much so we could argue that this should be a default behavior.

This patch adds the ability to specify (at CMake level) that RPATH should be added by default.


Full diff: https://github.com/llvm/llvm-project/pull/115163.diff

14 Files Affected:

  • (modified) clang/CMakeLists.txt (+2)
  • (modified) clang/include/clang/Config/config.h.cmake (+3)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+4)
  • (modified) clang/test/CMakeLists.txt (+1)
  • (added) clang/test/Driver/arch-specific-libdir-rpath-by-default.c (+105)
  • (modified) clang/test/Driver/arch-specific-libdir-rpath.c (+2)
  • (modified) clang/test/lit.cfg.py (+3)
  • (modified) clang/test/lit.site.cfg.py.in (+1)
  • (modified) flang/test/CMakeLists.txt (+1)
  • (added) flang/test/Driver/arch-specific-libdir-rpath-by-default.f95 (+34)
  • (modified) flang/test/Driver/arch-specific-libdir-rpath.f95 (+2)
  • (modified) flang/test/Driver/linker-flags.f90 (+2-1)
  • (modified) flang/test/lit.cfg.py (+4)
  • (modified) flang/test/lit.site.cfg.py.in (+1)
diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index 27e8095534a65c..fb902cd65a31da 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -216,6 +216,8 @@ endif()
 
 set(ENABLE_LINKER_BUILD_ID OFF CACHE BOOL "pass --build-id to ld")
 
+set(ENABLE_LINKER_RPATH_BY_DEFAULT OFF CACHE BOOL "pass -rpath to the linker by default")
+
 set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL
     "enable x86 relax relocations by default")
 
diff --git a/clang/include/clang/Config/config.h.cmake b/clang/include/clang/Config/config.h.cmake
index 27ed69e21562bf..a7f185d88c68cc 100644
--- a/clang/include/clang/Config/config.h.cmake
+++ b/clang/include/clang/Config/config.h.cmake
@@ -69,6 +69,9 @@
 /* pass --build-id to ld */
 #cmakedefine ENABLE_LINKER_BUILD_ID
 
+/* pass -rpath to the linker by default */
+#cmakedefine ENABLE_LINKER_RPATH_BY_DEFAULT
+
 /* enable x86 relax relocations by default */
 #cmakedefine01 ENABLE_X86_RELAX_RELOCATIONS
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index ca06fb115dfa11..e62f59f56241cd 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1183,7 +1183,11 @@ void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
 void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
                                  ArgStringList &CmdArgs) {
   if (!Args.hasFlag(options::OPT_frtlib_add_rpath,
+#ifdef ENABLE_LINKER_RPATH_BY_DEFAULT
+                    options::OPT_fno_rtlib_add_rpath, true))
+#else
                     options::OPT_fno_rtlib_add_rpath, false))
+#endif
     return;
 
   SmallVector<std::string> CandidateRPaths(TC.getArchSpecificLibPaths());
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index 5369dc92f69e8a..e439e973ce6f81 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -11,6 +11,7 @@ llvm_canonicalize_cmake_booleans(
   CLANG_SPAWN_CC1
   CLANG_ENABLE_CIR
   ENABLE_BACKTRACES
+  ENABLE_LINKER_RPATH_BY_DEFAULT
   LLVM_BUILD_EXAMPLES
   LLVM_BYE_LINK_INTO_TOOLS
   LLVM_ENABLE_PLUGINS
diff --git a/clang/test/Driver/arch-specific-libdir-rpath-by-default.c b/clang/test/Driver/arch-specific-libdir-rpath-by-default.c
new file mode 100644
index 00000000000000..20c3f2fa560905
--- /dev/null
+++ b/clang/test/Driver/arch-specific-libdir-rpath-by-default.c
@@ -0,0 +1,105 @@
+// Test that the driver adds an arch-specific subdirectory in
+// {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath'
+//
+// REQUIRES: enable_rpath_by_default
+//
+// Test the default behavior when neither -frtlib-add-rpath nor
+// -fno-rtlib-add-rpath is specified, which is to add -rpath
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+//
+// Test that -rpath is not added under -fno-rtlib-add-rpath even if other
+// conditions are met.
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -fno-rtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Test that -rpath is added only under the right circumstance even if
+// -frtlib-add-rpath is specified.
+//
+// Add LIBPATH but no RPATH for -fsanitizer=address w/o -shared-libasan
+// RUN: %clang %s -### --target=x86_64-linux -fsanitize=undefined \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Add LIBPATH but no RPATH for -fsanitizer=address w/o -shared-libasan
+// RUN: %clang %s -### --target=x86_64-linux -fsanitize=undefined \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Add LIBPATH, RPATH for -fsanitize=address -shared-libasan
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+//
+// Add LIBPATH, RPATH for -fsanitize=address -shared-libasan on aarch64
+// RUN: %clang %s -### --target=aarch64-linux \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-AARCH64,RPATH-AARCH64 %s
+//
+// Add LIBPATH, RPATH with -fsanitize=address for Android
+// RUN: %clang %s -### --target=x86_64-linux-android -fsanitize=address \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+//
+// Add LIBPATH, RPATH for OpenMP
+// RUN: %clang %s -### --target=x86_64-linux -fopenmp \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+//
+// Add LIBPATH but no RPATH for ubsan (or any other sanitizer)
+// RUN: %clang %s -### -fsanitize=undefined --target=x86_64-linux \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Add LIBPATH but no RPATH if no sanitizer or runtime is specified
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Do not add LIBPATH or RPATH if arch-specific subdir doesn't exist
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -resource-dir=%S/Inputs/resource_dir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,NO-LIBPATH,NO-RPATH %s
+
+// Test that the driver adds an per-target arch-specific subdirectory in
+// {RESOURCE_DIR}/lib/{triple} to the linker search path and to '-rpath'
+//
+// RUN: %clang %s -### 2>&1 --target=x86_64-linux-gnu \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN:     -frtlib-add-rpath \
+// RUN:   | FileCheck --check-prefixes=PERTARGET %s
+
+// RESDIR: "-resource-dir" "[[RESDIR:[^"]*]]"
+//
+// LIBPATH-X86_64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
+// RPATH-X86_64:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
+//
+// NO-LIBPATH-X86_64-NOT: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
+// NO-RPATH-X86_64-NOT:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
+//
+// LIBPATH-AARCH64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)aarch64}}
+// RPATH-AARCH64:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)aarch64}}"
+//
+// NO-LIBPATH-NOT: "-L{{[^"]*Inputs(/|\\\\)resource_dir}}"
+// NO-RPATH-NOT:   "-rpath" {{.*(/|\\\\)Inputs(/|\\\\)resource_dir}}
+
+// PERTARGET: "-resource-dir" "[[PTRESDIR:[^"]*]]"
+// PERTARGET: -L[[PTRESDIR]]{{(/|\\\\)lib(/|\\\\)x86_64-unknown-linux-gnu}}
+// PERTARGET:   "-rpath" "[[PTRESDIR]]{{(/|\\\\)lib(/|\\\\)x86_64-unknown-linux-gnu}}"
diff --git a/clang/test/Driver/arch-specific-libdir-rpath.c b/clang/test/Driver/arch-specific-libdir-rpath.c
index 1e6bbbc5929ac2..ecedb474d7045c 100644
--- a/clang/test/Driver/arch-specific-libdir-rpath.c
+++ b/clang/test/Driver/arch-specific-libdir-rpath.c
@@ -1,6 +1,8 @@
 // Test that the driver adds an arch-specific subdirectory in
 // {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath'
 //
+// UNSUPPORTED: enable_rpath_by_default
+//
 // Test the default behavior when neither -frtlib-add-rpath nor
 // -fno-rtlib-add-rpath is specified, which is to skip -rpath
 // RUN: %clang %s -### --target=x86_64-linux \
diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py
index 4d3469aba4bb8d..07068ab1b09d56 100644
--- a/clang/test/lit.cfg.py
+++ b/clang/test/lit.cfg.py
@@ -328,6 +328,9 @@ def calculate_arch_features(arch_string):
 if config.enable_shared:
     config.available_features.add("enable_shared")
 
+if config.enable_rpath_by_default:
+    config.available_features.add("enable_rpath_by_default")
+
 # Add a vendor-specific feature.
 if config.clang_vendor_uti:
     config.available_features.add("clang-vendor=" + config.clang_vendor_uti)
diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in
index 1cbd876ac5bb93..4630ec53b68daa 100644
--- a/clang/test/lit.site.cfg.py.in
+++ b/clang/test/lit.site.cfg.py.in
@@ -30,6 +30,7 @@ config.clang_staticanalyzer_z3 = @LLVM_WITH_Z3@
 config.clang_enable_cir = @CLANG_ENABLE_CIR@
 config.clang_examples = @CLANG_BUILD_EXAMPLES@
 config.enable_shared = @ENABLE_SHARED@
+config.enable_rpath_by_default = @ENABLE_LINKER_RPATH_BY_DEFAULT@
 config.enable_backtrace = @ENABLE_BACKTRACES@
 config.enable_threads = @LLVM_ENABLE_THREADS@
 config.reverse_iteration = @LLVM_ENABLE_REVERSE_ITERATION@
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index cab214c2ef4c8c..2eccfc7d3ca3af 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -3,6 +3,7 @@
 add_subdirectory(lib)
 
 llvm_canonicalize_cmake_booleans(
+  ENABLE_LINKER_RPATH_BY_DEFAULT
   FLANG_STANDALONE_BUILD
   LLVM_BUILD_EXAMPLES
   LLVM_BYE_LINK_INTO_TOOLS
diff --git a/flang/test/Driver/arch-specific-libdir-rpath-by-default.f95 b/flang/test/Driver/arch-specific-libdir-rpath-by-default.f95
new file mode 100644
index 00000000000000..3630bd8101b8cc
--- /dev/null
+++ b/flang/test/Driver/arch-specific-libdir-rpath-by-default.f95
@@ -0,0 +1,34 @@
+! REQUIRES: x86-registered-target
+! Test that the driver adds an arch-specific subdirectory in
+! {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath'
+!
+! REQUIRES: enable_rpath_by_default
+!
+! Test the default behavior when neither -frtlib-add-rpath nor
+! -fno-rtlib-add-rpath is specified, which is to add -rpath
+! RUN: %flang %s -### --target=x86_64-linux \
+! RUN:     -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir 2>&1 \
+! RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+!
+! Test that -rpath is not added under -fno-rtlib-add-rpath
+! RUN: %flang %s -### --target=x86_64-linux \
+! RUN:     -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir \
+! RUN:     -fno-rtlib-add-rpath 2>&1 \
+! RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+!
+! Test that -rpath is added
+!
+! Add LIBPATH, RPATH for OpenMP
+!
+! RUN: %flang %s -### --target=x86_64-linux -fopenmp \
+! RUN:     -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir \
+! RUN:     -frtlib-add-rpath 2>&1 \
+! RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+!
+!
+! RESDIR: "-resource-dir" "[[RESDIR:[^"]*]]"
+!
+! LIBPATH-X86_64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
+! RPATH-X86_64:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
+!
+! NO-RPATH-X86_64-NOT:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
diff --git a/flang/test/Driver/arch-specific-libdir-rpath.f95 b/flang/test/Driver/arch-specific-libdir-rpath.f95
index 23fb52abfbd574..6e1a8f5212f0b9 100644
--- a/flang/test/Driver/arch-specific-libdir-rpath.f95
+++ b/flang/test/Driver/arch-specific-libdir-rpath.f95
@@ -2,6 +2,8 @@
 ! Test that the driver adds an arch-specific subdirectory in
 ! {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath'
 !
+! UNSUPPORTED: enable_rpath_by_default
+!
 ! Test the default behavior when neither -frtlib-add-rpath nor
 ! -fno-rtlib-add-rpath is specified, which is to skip -rpath
 ! RUN: %flang %s -### --target=x86_64-linux \
diff --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90
index ac9500d7c45cec..c4ee26c5dacab8 100644
--- a/flang/test/Driver/linker-flags.f90
+++ b/flang/test/Driver/linker-flags.f90
@@ -33,7 +33,8 @@
 ! SOLARIS-F128NONE-NOT: FortranFloat128Math
 ! UNIX-F128LIBQUADMATH-SAME: "-lFortranFloat128Math" "--as-needed" "-lquadmath" "--no-as-needed"
 ! SOLARIS-F128LIBQUADMATH-SAME: "-lFortranFloat128Math" "-z" "ignore" "-lquadmath" "-z" "record"
-! UNIX-SAME: "-lFortranRuntime" "-lFortranDecimal" "-lm"
+! UNIX-SAME: "-lFortranRuntime" "-lFortranDecimal"
+! UNIX-SAME: "-lm"
 ! COMPILER-RT: "{{.*}}{{\\|/}}libclang_rt.builtins.a"
 
 ! DARWIN-LABEL:  "{{.*}}ld{{(\.exe)?}}"
diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index f43234fb125b7e..5e61b454832363 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -227,3 +227,7 @@
     )
 else:
     config.substitutions.append(("%f128-lib", "NONE"))
+
+# Pass -rpath to the linker by default.
+if config.enable_rpath_by_default:
+    config.available_features.add("enable_rpath_by_default")
diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in
index d1a0ac763cf8a0..d5ee2a670dc7c2 100644
--- a/flang/test/lit.site.cfg.py.in
+++ b/flang/test/lit.site.cfg.py.in
@@ -26,6 +26,7 @@ config.osx_sysroot = path(r"@CMAKE_OSX_SYSROOT@")
 config.targets_to_build = "@TARGETS_TO_BUILD@"
 config.default_sysroot = "@DEFAULT_SYSROOT@"
 config.have_openmp_rtl = ("@LLVM_TOOL_OPENMP_BUILD@" == "TRUE") or ("openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"))
+config.enable_rpath_by_default = @ENABLE_LINKER_RPATH_BY_DEFAULT@
 if "openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"):
     config.openmp_module_dir = "@CMAKE_BINARY_DIR@/runtimes/runtimes-bins/openmp/runtime/src"
 else:

@llvmbot
Copy link
Collaborator

llvmbot commented Nov 6, 2024

@llvm/pr-subscribers-clang-driver

Author: Paul Osmialowski (pawosm-arm)

Changes

The -frtlib-add-rpath is very convenient when linking against various runtimes (OpenMP, Fortran, sanitizers), so much so we could argue that this should be a default behavior.

This patch adds the ability to specify (at CMake level) that RPATH should be added by default.


Full diff: https://github.com/llvm/llvm-project/pull/115163.diff

14 Files Affected:

  • (modified) clang/CMakeLists.txt (+2)
  • (modified) clang/include/clang/Config/config.h.cmake (+3)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+4)
  • (modified) clang/test/CMakeLists.txt (+1)
  • (added) clang/test/Driver/arch-specific-libdir-rpath-by-default.c (+105)
  • (modified) clang/test/Driver/arch-specific-libdir-rpath.c (+2)
  • (modified) clang/test/lit.cfg.py (+3)
  • (modified) clang/test/lit.site.cfg.py.in (+1)
  • (modified) flang/test/CMakeLists.txt (+1)
  • (added) flang/test/Driver/arch-specific-libdir-rpath-by-default.f95 (+34)
  • (modified) flang/test/Driver/arch-specific-libdir-rpath.f95 (+2)
  • (modified) flang/test/Driver/linker-flags.f90 (+2-1)
  • (modified) flang/test/lit.cfg.py (+4)
  • (modified) flang/test/lit.site.cfg.py.in (+1)
diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt
index 27e8095534a65c..fb902cd65a31da 100644
--- a/clang/CMakeLists.txt
+++ b/clang/CMakeLists.txt
@@ -216,6 +216,8 @@ endif()
 
 set(ENABLE_LINKER_BUILD_ID OFF CACHE BOOL "pass --build-id to ld")
 
+set(ENABLE_LINKER_RPATH_BY_DEFAULT OFF CACHE BOOL "pass -rpath to the linker by default")
+
 set(ENABLE_X86_RELAX_RELOCATIONS ON CACHE BOOL
     "enable x86 relax relocations by default")
 
diff --git a/clang/include/clang/Config/config.h.cmake b/clang/include/clang/Config/config.h.cmake
index 27ed69e21562bf..a7f185d88c68cc 100644
--- a/clang/include/clang/Config/config.h.cmake
+++ b/clang/include/clang/Config/config.h.cmake
@@ -69,6 +69,9 @@
 /* pass --build-id to ld */
 #cmakedefine ENABLE_LINKER_BUILD_ID
 
+/* pass -rpath to the linker by default */
+#cmakedefine ENABLE_LINKER_RPATH_BY_DEFAULT
+
 /* enable x86 relax relocations by default */
 #cmakedefine01 ENABLE_X86_RELAX_RELOCATIONS
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index ca06fb115dfa11..e62f59f56241cd 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1183,7 +1183,11 @@ void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
 void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
                                  ArgStringList &CmdArgs) {
   if (!Args.hasFlag(options::OPT_frtlib_add_rpath,
+#ifdef ENABLE_LINKER_RPATH_BY_DEFAULT
+                    options::OPT_fno_rtlib_add_rpath, true))
+#else
                     options::OPT_fno_rtlib_add_rpath, false))
+#endif
     return;
 
   SmallVector<std::string> CandidateRPaths(TC.getArchSpecificLibPaths());
diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt
index 5369dc92f69e8a..e439e973ce6f81 100644
--- a/clang/test/CMakeLists.txt
+++ b/clang/test/CMakeLists.txt
@@ -11,6 +11,7 @@ llvm_canonicalize_cmake_booleans(
   CLANG_SPAWN_CC1
   CLANG_ENABLE_CIR
   ENABLE_BACKTRACES
+  ENABLE_LINKER_RPATH_BY_DEFAULT
   LLVM_BUILD_EXAMPLES
   LLVM_BYE_LINK_INTO_TOOLS
   LLVM_ENABLE_PLUGINS
diff --git a/clang/test/Driver/arch-specific-libdir-rpath-by-default.c b/clang/test/Driver/arch-specific-libdir-rpath-by-default.c
new file mode 100644
index 00000000000000..20c3f2fa560905
--- /dev/null
+++ b/clang/test/Driver/arch-specific-libdir-rpath-by-default.c
@@ -0,0 +1,105 @@
+// Test that the driver adds an arch-specific subdirectory in
+// {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath'
+//
+// REQUIRES: enable_rpath_by_default
+//
+// Test the default behavior when neither -frtlib-add-rpath nor
+// -fno-rtlib-add-rpath is specified, which is to add -rpath
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+//
+// Test that -rpath is not added under -fno-rtlib-add-rpath even if other
+// conditions are met.
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -fno-rtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Test that -rpath is added only under the right circumstance even if
+// -frtlib-add-rpath is specified.
+//
+// Add LIBPATH but no RPATH for -fsanitizer=address w/o -shared-libasan
+// RUN: %clang %s -### --target=x86_64-linux -fsanitize=undefined \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Add LIBPATH but no RPATH for -fsanitizer=address w/o -shared-libasan
+// RUN: %clang %s -### --target=x86_64-linux -fsanitize=undefined \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Add LIBPATH, RPATH for -fsanitize=address -shared-libasan
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+//
+// Add LIBPATH, RPATH for -fsanitize=address -shared-libasan on aarch64
+// RUN: %clang %s -### --target=aarch64-linux \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-AARCH64,RPATH-AARCH64 %s
+//
+// Add LIBPATH, RPATH with -fsanitize=address for Android
+// RUN: %clang %s -### --target=x86_64-linux-android -fsanitize=address \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+//
+// Add LIBPATH, RPATH for OpenMP
+// RUN: %clang %s -### --target=x86_64-linux -fopenmp \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+//
+// Add LIBPATH but no RPATH for ubsan (or any other sanitizer)
+// RUN: %clang %s -### -fsanitize=undefined --target=x86_64-linux \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Add LIBPATH but no RPATH if no sanitizer or runtime is specified
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+//
+// Do not add LIBPATH or RPATH if arch-specific subdir doesn't exist
+// RUN: %clang %s -### --target=x86_64-linux \
+// RUN:     -resource-dir=%S/Inputs/resource_dir \
+// RUN:     -frtlib-add-rpath 2>&1 \
+// RUN:   | FileCheck --check-prefixes=RESDIR,NO-LIBPATH,NO-RPATH %s
+
+// Test that the driver adds an per-target arch-specific subdirectory in
+// {RESOURCE_DIR}/lib/{triple} to the linker search path and to '-rpath'
+//
+// RUN: %clang %s -### 2>&1 --target=x86_64-linux-gnu \
+// RUN:     -fsanitize=address -shared-libasan \
+// RUN:     -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
+// RUN:     -frtlib-add-rpath \
+// RUN:   | FileCheck --check-prefixes=PERTARGET %s
+
+// RESDIR: "-resource-dir" "[[RESDIR:[^"]*]]"
+//
+// LIBPATH-X86_64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
+// RPATH-X86_64:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
+//
+// NO-LIBPATH-X86_64-NOT: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
+// NO-RPATH-X86_64-NOT:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
+//
+// LIBPATH-AARCH64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)aarch64}}
+// RPATH-AARCH64:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)aarch64}}"
+//
+// NO-LIBPATH-NOT: "-L{{[^"]*Inputs(/|\\\\)resource_dir}}"
+// NO-RPATH-NOT:   "-rpath" {{.*(/|\\\\)Inputs(/|\\\\)resource_dir}}
+
+// PERTARGET: "-resource-dir" "[[PTRESDIR:[^"]*]]"
+// PERTARGET: -L[[PTRESDIR]]{{(/|\\\\)lib(/|\\\\)x86_64-unknown-linux-gnu}}
+// PERTARGET:   "-rpath" "[[PTRESDIR]]{{(/|\\\\)lib(/|\\\\)x86_64-unknown-linux-gnu}}"
diff --git a/clang/test/Driver/arch-specific-libdir-rpath.c b/clang/test/Driver/arch-specific-libdir-rpath.c
index 1e6bbbc5929ac2..ecedb474d7045c 100644
--- a/clang/test/Driver/arch-specific-libdir-rpath.c
+++ b/clang/test/Driver/arch-specific-libdir-rpath.c
@@ -1,6 +1,8 @@
 // Test that the driver adds an arch-specific subdirectory in
 // {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath'
 //
+// UNSUPPORTED: enable_rpath_by_default
+//
 // Test the default behavior when neither -frtlib-add-rpath nor
 // -fno-rtlib-add-rpath is specified, which is to skip -rpath
 // RUN: %clang %s -### --target=x86_64-linux \
diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py
index 4d3469aba4bb8d..07068ab1b09d56 100644
--- a/clang/test/lit.cfg.py
+++ b/clang/test/lit.cfg.py
@@ -328,6 +328,9 @@ def calculate_arch_features(arch_string):
 if config.enable_shared:
     config.available_features.add("enable_shared")
 
+if config.enable_rpath_by_default:
+    config.available_features.add("enable_rpath_by_default")
+
 # Add a vendor-specific feature.
 if config.clang_vendor_uti:
     config.available_features.add("clang-vendor=" + config.clang_vendor_uti)
diff --git a/clang/test/lit.site.cfg.py.in b/clang/test/lit.site.cfg.py.in
index 1cbd876ac5bb93..4630ec53b68daa 100644
--- a/clang/test/lit.site.cfg.py.in
+++ b/clang/test/lit.site.cfg.py.in
@@ -30,6 +30,7 @@ config.clang_staticanalyzer_z3 = @LLVM_WITH_Z3@
 config.clang_enable_cir = @CLANG_ENABLE_CIR@
 config.clang_examples = @CLANG_BUILD_EXAMPLES@
 config.enable_shared = @ENABLE_SHARED@
+config.enable_rpath_by_default = @ENABLE_LINKER_RPATH_BY_DEFAULT@
 config.enable_backtrace = @ENABLE_BACKTRACES@
 config.enable_threads = @LLVM_ENABLE_THREADS@
 config.reverse_iteration = @LLVM_ENABLE_REVERSE_ITERATION@
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index cab214c2ef4c8c..2eccfc7d3ca3af 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -3,6 +3,7 @@
 add_subdirectory(lib)
 
 llvm_canonicalize_cmake_booleans(
+  ENABLE_LINKER_RPATH_BY_DEFAULT
   FLANG_STANDALONE_BUILD
   LLVM_BUILD_EXAMPLES
   LLVM_BYE_LINK_INTO_TOOLS
diff --git a/flang/test/Driver/arch-specific-libdir-rpath-by-default.f95 b/flang/test/Driver/arch-specific-libdir-rpath-by-default.f95
new file mode 100644
index 00000000000000..3630bd8101b8cc
--- /dev/null
+++ b/flang/test/Driver/arch-specific-libdir-rpath-by-default.f95
@@ -0,0 +1,34 @@
+! REQUIRES: x86-registered-target
+! Test that the driver adds an arch-specific subdirectory in
+! {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath'
+!
+! REQUIRES: enable_rpath_by_default
+!
+! Test the default behavior when neither -frtlib-add-rpath nor
+! -fno-rtlib-add-rpath is specified, which is to add -rpath
+! RUN: %flang %s -### --target=x86_64-linux \
+! RUN:     -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir 2>&1 \
+! RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+!
+! Test that -rpath is not added under -fno-rtlib-add-rpath
+! RUN: %flang %s -### --target=x86_64-linux \
+! RUN:     -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir \
+! RUN:     -fno-rtlib-add-rpath 2>&1 \
+! RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,NO-RPATH-X86_64 %s
+!
+! Test that -rpath is added
+!
+! Add LIBPATH, RPATH for OpenMP
+!
+! RUN: %flang %s -### --target=x86_64-linux -fopenmp \
+! RUN:     -resource-dir=%S/../../../clang/test/Driver/Inputs/resource_dir_with_arch_subdir \
+! RUN:     -frtlib-add-rpath 2>&1 \
+! RUN:   | FileCheck --check-prefixes=RESDIR,LIBPATH-X86_64,RPATH-X86_64 %s
+!
+!
+! RESDIR: "-resource-dir" "[[RESDIR:[^"]*]]"
+!
+! LIBPATH-X86_64: -L[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}
+! RPATH-X86_64:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
+!
+! NO-RPATH-X86_64-NOT:   "-rpath" "[[RESDIR]]{{(/|\\\\)lib(/|\\\\)linux(/|\\\\)x86_64}}"
diff --git a/flang/test/Driver/arch-specific-libdir-rpath.f95 b/flang/test/Driver/arch-specific-libdir-rpath.f95
index 23fb52abfbd574..6e1a8f5212f0b9 100644
--- a/flang/test/Driver/arch-specific-libdir-rpath.f95
+++ b/flang/test/Driver/arch-specific-libdir-rpath.f95
@@ -2,6 +2,8 @@
 ! Test that the driver adds an arch-specific subdirectory in
 ! {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath'
 !
+! UNSUPPORTED: enable_rpath_by_default
+!
 ! Test the default behavior when neither -frtlib-add-rpath nor
 ! -fno-rtlib-add-rpath is specified, which is to skip -rpath
 ! RUN: %flang %s -### --target=x86_64-linux \
diff --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90
index ac9500d7c45cec..c4ee26c5dacab8 100644
--- a/flang/test/Driver/linker-flags.f90
+++ b/flang/test/Driver/linker-flags.f90
@@ -33,7 +33,8 @@
 ! SOLARIS-F128NONE-NOT: FortranFloat128Math
 ! UNIX-F128LIBQUADMATH-SAME: "-lFortranFloat128Math" "--as-needed" "-lquadmath" "--no-as-needed"
 ! SOLARIS-F128LIBQUADMATH-SAME: "-lFortranFloat128Math" "-z" "ignore" "-lquadmath" "-z" "record"
-! UNIX-SAME: "-lFortranRuntime" "-lFortranDecimal" "-lm"
+! UNIX-SAME: "-lFortranRuntime" "-lFortranDecimal"
+! UNIX-SAME: "-lm"
 ! COMPILER-RT: "{{.*}}{{\\|/}}libclang_rt.builtins.a"
 
 ! DARWIN-LABEL:  "{{.*}}ld{{(\.exe)?}}"
diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index f43234fb125b7e..5e61b454832363 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -227,3 +227,7 @@
     )
 else:
     config.substitutions.append(("%f128-lib", "NONE"))
+
+# Pass -rpath to the linker by default.
+if config.enable_rpath_by_default:
+    config.available_features.add("enable_rpath_by_default")
diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in
index d1a0ac763cf8a0..d5ee2a670dc7c2 100644
--- a/flang/test/lit.site.cfg.py.in
+++ b/flang/test/lit.site.cfg.py.in
@@ -26,6 +26,7 @@ config.osx_sysroot = path(r"@CMAKE_OSX_SYSROOT@")
 config.targets_to_build = "@TARGETS_TO_BUILD@"
 config.default_sysroot = "@DEFAULT_SYSROOT@"
 config.have_openmp_rtl = ("@LLVM_TOOL_OPENMP_BUILD@" == "TRUE") or ("openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"))
+config.enable_rpath_by_default = @ENABLE_LINKER_RPATH_BY_DEFAULT@
 if "openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"):
     config.openmp_module_dir = "@CMAKE_BINARY_DIR@/runtimes/runtimes-bins/openmp/runtime/src"
 else:

Copy link
Member

@DavidTruby DavidTruby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, and seems useful especially for flang.

… by default

The `-frtlib-add-rpath` is very convenient when linking against
various runtimes (OpenMP, Fortran, sanitizers), so much so we
could argue that this should be a default behavior.

This patch adds the ability to specify (at CMake level) that RPATH
should be added by default.
@MaskRay
Copy link
Member

MaskRay commented Nov 6, 2024

This should use clang configuration file

Copy link
Member

@MaskRay MaskRay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

@MaskRay
Copy link
Member

MaskRay commented Nov 6, 2024

On my phone not easy to comment.
We have NAKed patches to add more clang build variants. Configuration file is designed to customize such default options

@pawosm-arm
Copy link
Contributor Author

We worked out this patch just because we dropped the idea of adding configuration file to our toolchain and for no other reason...

@DavidTruby
Copy link
Member

For what it’s worth, as a user I’m always surprised that this isn’t the default. It’s quite annoying to eg have to set LD_LIBRARY_PATH when using openmp with clang when they’re built alongside each other. Is there a specific reason this isn’t the default or is it just historical?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category flang:driver flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants