Skip to content

Commit 4091898

Browse files
authored
Merge pull request #4665 from the-horo/compiler-rt
Implement clang resource directory logic
2 parents b259906 + 704350a commit 4091898

File tree

5 files changed

+231
-78
lines changed

5 files changed

+231
-78
lines changed

.github/workflows/main.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ jobs:
4040
- job_name: Linux aarch64
4141
os: ubuntu-22.04-arm
4242
arch: aarch64
43-
base_cmake_flags: >-
44-
-DCOMPILER_RT_LIBDIR_OS=aarch64-unknown-linux-gnu
4543
extra_cmake_flags: >-
4644
-DCMAKE_C_COMPILER=clang
4745
-DCMAKE_CXX_COMPILER=clang++
@@ -56,7 +54,6 @@ jobs:
5654
container_image: alpine:3.21
5755
arch: x86_64
5856
base_cmake_flags: >-
59-
-DCOMPILER_RT_LIBDIR_OS=linux
6057
-DLDC_INSTALL_LLVM_RUNTIME_LIBS_ARCH=x86_64
6158
-DLLVM_IS_SHARED=OFF
6259
-DLDC_ENABLE_PLUGINS=OFF
@@ -265,7 +262,6 @@ jobs:
265262
arch: aarch64
266263
android_x86_arch: x86_64
267264
extra_cmake_flags: >-
268-
-DCOMPILER_RT_LIBDIR_OS=linux
269265
-DLDC_INSTALL_LLVM_RUNTIME_LIBS_ARCH=aarch64-android
270266
271267
name: ${{ matrix.job_name }}

CMakeLists.txt

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -805,14 +805,8 @@ endif()
805805
# LLVM_LIBRARY_DIRS/clang/<version>/lib/<OS>/ , for example
806806
# LLVM_LIBRARY_DIRS/clang/4.0.0/lib/darwin/ , but we allow the user to specify
807807
# another directory.
808-
set(COMPILER_RT_BASE_DIR "${LLVM_LIBRARY_DIRS}" CACHE PATH "Base path of compiler-rt libraries. If they in are /usr/lib/clang/17/lib/linux/libclang_rt* you should set this value to /usr/lib")
809-
# If it's different than the default it will need to be added to the config files
810-
if(COMPILER_RT_BASE_DIR STREQUAL LLVM_LIBRARY_DIRS)
811-
set(WANT_COMPILER_RT_LIBDIR_CONFIG FALSE)
812-
else()
813-
set(WANT_COMPILER_RT_LIBDIR_CONFIG TRUE)
814-
endif()
815-
set(COMPILER_RT_LIBDIR "${COMPILER_RT_BASE_DIR}/clang")
808+
set(COMPILER_RT_BASE_DIR "${LLVM_LIBRARY_DIRS}/clang" CACHE PATH "Base path of compiler-rt libraries. If they in are /usr/lib/clang/17/lib/linux/libclang_rt* you should set this value to /usr/lib/clang")
809+
set(COMPILER_RT_LIBDIR "${COMPILER_RT_BASE_DIR}")
816810
if(LDC_LLVM_VER LESS 1600)
817811
set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/${LLVM_VERSION_BASE_STRING}")
818812
else()
@@ -821,13 +815,25 @@ endif()
821815
set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/lib")
822816
if(APPLE)
823817
set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/darwin")
818+
elseif(ANDROID)
819+
set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/linux")
824820
elseif(UNIX)
825-
set(COMPILER_RT_LIBDIR_OS_DEFAULT "x86_64-unknown-linux-gnu")
821+
set(COMPILER_RT_LIBDIR_OS_DEFAULT "${LLVM_HOST_TARGET}") # default when building compiler-rt alongside LLVM
822+
if(NOT EXISTS "${COMPILER_RT_LIBDIR}/${COMPILER_RT_LIBDIR_OS_DEFAULT}")
823+
# default when building compiler-rt separately: OS name alone in lowercase
824+
string(TOLOWER "${CMAKE_SYSTEM_NAME}" lowercase_CMAKE_SYSTEM_NAME)
825+
if(EXISTS "${COMPILER_RT_LIBDIR}/${lowercase_CMAKE_SYSTEM_NAME}")
826+
set(COMPILER_RT_LIBDIR_OS_DEFAULT "${lowercase_CMAKE_SYSTEM_NAME}")
827+
endif()
828+
endif()
826829
set(COMPILER_RT_LIBDIR_OS "${COMPILER_RT_LIBDIR_OS_DEFAULT}" CACHE STRING "Non-Mac Posix: OS used as directory name for the compiler-rt source libraries, e.g., 'freebsd'.")
827830
set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/${COMPILER_RT_LIBDIR_OS}")
828831
elseif(WIN32)
829832
set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/windows")
830833
endif()
834+
if(NOT EXISTS "${COMPILER_RT_LIBDIR}")
835+
message(WARNING "Expected compiler-rt directory '${COMPILER_RT_LIBDIR}' does not exist. To include PGO and sanitizers support, COMPILER_RT_BASE_DIR and/or COMPILER_RT_LIBDIR_OS might need to be set explicitly. See docs/compiler_rt.md.")
836+
endif()
831837
if(LLVM_IS_SHARED)
832838
set(LDC_INSTALL_LLVM_RUNTIME_LIBS_DEFAULT OFF)
833839
else()
@@ -847,9 +853,6 @@ message(STATUS "-- Including LLVM compiler-rt libraries (LDC_INSTALL_LLVM_RUNTIM
847853
if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
848854
# Locate LLVM sanitizer runtime libraries, and copy them to our lib folder
849855

850-
# No need to add another libdir, the default ldc one will have the libraries
851-
set(WANT_COMPILER_RT_LIBDIR_CONFIG FALSE)
852-
853856
if(APPLE)
854857
copy_compilerrt_lib("libclang_rt.asan_osx_dynamic.dylib" "libldc_rt.asan.dylib" TRUE)
855858
copy_compilerrt_lib("libclang_rt.lsan_osx_dynamic.dylib" "libldc_rt.lsan.dylib" TRUE)
@@ -894,9 +897,16 @@ if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
894897
endif()
895898
endif()
896899

897-
if(WANT_COMPILER_RT_LIBDIR_CONFIG)
898-
message(STATUS "Adding ${COMPILER_RT_LIBDIR} to libdir in configuration files")
899-
set(OPTIONAL_COMPILER_RT_DIR "\n \"${COMPILER_RT_LIBDIR}\",")
900+
# If everything else if insufficient, the user can specify
901+
# -DCOMPILER_RT_LIBDIR_CONFIG to embed an arbitrary value.
902+
if(NOT DEFINED COMPILER_RT_LIBDIR_CONFIG)
903+
if(NOT LDC_INSTALL_LLVM_RUNTIME_LIBS)
904+
set(COMPILER_RT_LIBDIR_CONFIG "${COMPILER_RT_LIBDIR}")
905+
endif()
906+
endif()
907+
if(DEFINED COMPILER_RT_LIBDIR_CONFIG)
908+
message(STATUS "Adding ${COMPILER_RT_LIBDIR_CONFIG} to lib-dirs in configuration file")
909+
set(OPTIONAL_COMPILER_RT_DIR "\n \"${COMPILER_RT_LIBDIR_CONFIG}\", // compiler-rt directory")
900910
endif()
901911

902912
#

cmake/Modules/FindLLVM.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ else()
142142
llvm_set(INCLUDE_DIRS includedir true)
143143
llvm_set(ROOT_DIR prefix true)
144144
llvm_set(ENABLE_ASSERTIONS assertion-mode)
145+
llvm_set(HOST_TARGET host-target)
145146

146147
# The LLVM version string _may_ contain a git/svn suffix, so match only the x.y.z part
147148
string(REGEX MATCH "^[0-9]+[.][0-9]+[.][0-9]+" LLVM_VERSION_BASE_STRING "${LLVM_VERSION_STRING}")

docs/compiler_rt.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Configuring LDC to use compiler-rt libraries
2+
3+
LDC provides some functionalities like PGO, sanitizers and fuzzing, which require the presence of some libraries that are part of the compiler-rt LLVM sub-project.
4+
This document aims to describe how to tell LDC the locations of these libraries, based on your installation method.
5+
It is meant mostly for people using LDC through a Linux package manager or manually building it, which includes package maintainers.
6+
7+
## Using the prebuilt packages or [dlang.org/install.sh](https://dlang.org/install.sh)
8+
9+
The tarballs at https://github.com/ldc-developers/ldc/releases come with the compiler-rt libraries and you don't need to do any configuration.
10+
The dlang.org install.sh script also uses these tarballs so the same things applies to it.
11+
12+
## Using a Linux distribution's package manager
13+
14+
Given a survey of the available options at the time of writing,
15+
most distributions don't add a dependency on compiler-rt nor do they configure LDC to find them when installed manually,
16+
therefore, it is needed to do both of these steps manually.
17+
18+
### Installing compiler-rt
19+
20+
The name of the actual package varies quite a lot across distributions but you can usually find it be searching for `compiler-rt` or `libclang`.
21+
Below you will find a list of popular Linux distributions and the name of the `compiler-rt` package:
22+
23+
- Debian/Ubuntu: `libclang-rt-dev`
24+
- Fedora: `compiler-rt`
25+
- Arch: `compiler-rt`
26+
- Gentoo: `compiler-rt-sanitizers`
27+
28+
### Adding the compiler-rt path to ldc2.conf
29+
30+
After you've installed the packages chances are that the libraries still won't be found because the path differs from what LDC expects.
31+
To solve this you need to first determine the path of the libraries.
32+
Again, this path depends on distribution but it is easy to find if you use your package manager to list the contents of the `compiler-rt` package installed in the previous step.
33+
34+
Usually the path has the form: `<some_directory>/lib/clang/<major_version>/lib/linux/`.
35+
Where `<major_version>` is a number like 18, 17, etc.
36+
`linux` may be, instead, a target triple like `x86_64-redhat-linux-gnu`.
37+
If the directory you found contains a bunch of `libclang_rt.*` files then you've found the right path, if not, try again.
38+
39+
For simplicity, below you can find the paths of some Linux distributions.
40+
Remember to adapt them to the appropriate version of the package you have installed.
41+
42+
- Debian/Ubuntu: `/usr/lib/llvm-<major_version>/lib/clang/<major_version>/lib/linux/`
43+
- Fedora: `/usr/lib/clang/<major_version>/lib/x86_64-redhat-linux-gnu/`
44+
- Arch: `/usr/lib/clang/<major_version>/lib/linux/`
45+
- Gentoo: `/usr/lib/clang/<major_version>/lib/linux/`
46+
47+
You now need to edit the ldc2 configuration file.
48+
Since you're installing ldc2 through your package manager the config file is probably in `/etc/ldc2.conf`.
49+
If it's not there it should be in `../etc/ldc2.conf` relative to the directory of the ldc2 executable.
50+
51+
Use your favorite text editor to edit the file and jump to the `lib-dirs = ` snippet.
52+
53+
On recent versions you should see:
54+
```
55+
lib-dirs = [
56+
"/usr/lib",
57+
"/usr/lib/clang/17/lib/linux", // compiler-rt directory
58+
];
59+
```
60+
You should edit the line with the `compiler-rt directory` comment and put the path you determined above in there.
61+
62+
On older versions you wouldn't have the second entry so you would only see:
63+
```
64+
lib-dirs = [
65+
"/usr/lib",
66+
];
67+
```
68+
69+
In that case just add another line with the path surrounded by `"`.
70+
71+
In the end, you should have:
72+
```
73+
lib-dirs = [
74+
"/usr/lib",
75+
"YOUR_PATH_HERE", // compiler-rt directory
76+
];
77+
```
78+
With or without the `compiler-rt` comment.
79+
80+
## Building from source
81+
82+
When building from source you can pass a number of options to cmake related to compiler-rt libraries.
83+
84+
### `COMPILER_RT_BASE_DIR`
85+
86+
This option tells cmake a path that will be transformed, assuming standard layout, in the final compiler-rt directory.
87+
If you are using a distribution tarball for llvm then the default value for this option, `<LLVM_LIB_DIR>/clang`, should be the correct one.
88+
89+
If on Linux and using the llvm provided through your package manager set this option to something like `/usr/lib/clang`.
90+
How to find the correct path is described above, in the Linux section.
91+
92+
### `COMPILER_RT_LIBDIR_OS`
93+
94+
This option only applies to non-Mac Unixes and refers to the final directory name in the full path to the compiler-rt libraries.
95+
96+
If the path is `[...]/clang/<version>/lib/linux` then this value should be `linux`.
97+
If it is `[...]/clang/<version>/lib/x86_64-redhat-linux-gnu` then this value should be `x86_64-redhat-linux-gnu`.
98+
99+
### `LDC_INSTALL_LLVM_RUNTIME_LIBS_ARCH`
100+
101+
The option only applied to non-Mac Unixes and refers to the architecture component in the filename of the libraries.
102+
It only makes sense specifying this if `LDC_INSTALL_LLVM_RUNTIME_LIBS` is set to `ON`, see below.
103+
104+
If the filename of the libraries is `libclang_rt.asan-x86_64.a` then this value should be `x86_64`.
105+
If the filename of the libraries is `libclang_rt.asan.a` then this value should be `""` (empty).
106+
107+
### `LDC_INSTALL_LLVM_RUNTIME_LIBS`
108+
109+
This option tells cmake to copy the library files from the compiler-rt directory specified above to the library directory of ldc2.
110+
If you enable this you don't need to configure anything else, the libraries will be found when you run ldc2.
111+
112+
### `COMPILER_RT_LIBDIR_CONFIG`
113+
114+
The final path that is stored in the configuration file in regards to compiler-rt is `${COMPILER_RT_BASE_DIR}/${LLVM_MAJOR_VERSION}/lib/${COMPILER_RT_LIBDIR_OS}`.
115+
If this setting doesn't match your layout, as a last resort, you can specify your custom path with `-DCOMPILER_RT_LIBDIR_CONFIG` and that unaltered path will be stored in the config.
116+
117+
## Checking that everything works
118+
119+
Try to compile the empty program below with `ldc2 -fprofile-generate -vv sample.d`
120+
```d
121+
void main () {}
122+
```
123+
124+
And check the end of the output:
125+
```
126+
[...]
127+
*** Linking executable ***
128+
Searching profile runtime: /usr/lib/libldc_rt.profile.a
129+
Searching profile runtime: /usr/lib/llvm-17/lib/clang/17/lib/linux/libldc_rt.profile.a
130+
Searching profile runtime: /usr/lib/libldc_rt.profile.a
131+
Searching profile runtime: /usr/lib/llvm-17/lib/libldc_rt.profile.a
132+
Searching profile runtime: /usr/lib/libclang_rt.profile-x86_64.a
133+
Searching profile runtime: /usr/lib/llvm-17/lib/clang/17/lib/linux/libclang_rt.profile-x86_64.a
134+
Found, linking with /usr/lib/llvm-17/lib/clang/17/lib/linux/libclang_rt.profile-x86_64.a
135+
Linking with:
136+
[...]
137+
```
138+
The import line is `Found, linking with ...`.
139+
If you see this it means that you configured LDC correctly and the library was found.
140+
141+
If you're missing that line, like in:
142+
```
143+
*** Linking executable ***
144+
Searching profile runtime: /usr/lib/libldc_rt.profile.a
145+
Searching profile runtime: /usr/lib/libldc_rt.profile.a
146+
Searching profile runtime: /usr/lib/llvm-17/lib/libldc_rt.profile.a
147+
Searching profile runtime: /usr/lib/libclang_rt.profile-x86_64.a
148+
Searching profile runtime: /usr/lib/libclang_rt.profile-x86_64.a
149+
Searching profile runtime: /usr/lib/llvm-17/lib/libclang_rt.profile-x86_64.a
150+
Searching profile runtime: /usr/lib/clang/17.0.6/lib/linux/libclang_rt.profile-x86_64.a
151+
Searching profile runtime: /usr/lib/clang/17.0.6/lib/linux/libclang_rt.profile-x86_64.a
152+
Searching profile runtime: /usr/lib/llvm-17/lib/clang/17.0.6/lib/linux/libclang_rt.profile-x86_64.a
153+
Linking with:
154+
```
155+
You should recheck the paths and make the necessary adjustments in the config file until `ldc2` can find it.

0 commit comments

Comments
 (0)