Skip to content

Commit

Permalink
[CMake] Support per-target linker flags (#68393)
Browse files Browse the repository at this point in the history
`CMAKE_{C/CXX}_FLAGS` affects all targets in LLVM. This can
be undesirable in situations, like the case of enabling thinLTO,
where `-flto` is added to every source file. In reality, we only 
care about optimizing a select few of binaries, such as clang or lld,
that dominate the compilation pipeline. Auxiliary binaries in a 
distribution and not on the critical path can be kept non-optimized. 
This PR adds support of per-target linker flags, which can solve the
thinLTO problem by negating the effects of LTO via targeted linker 
flags on the targets. The example of negating thinLTO 
above can be done by doing the following:

```
set(LLVM_llvm-dwarfdump_LINKER_FLAGS "-Wl,--lto-O0" CACHE STRING "Custom linker flags to llvm-dwarfdump")
set(LLVM_lldb_LINKER_FLAGS "-Wl,--lto-O0" CACHE STRING "Custom linker flags to lldb")
```

There's other applications where this could be used (e.g. avoid
optimizing host tools for build speed improvement etc.). 
I've generalized this so that users can apply their desired flags to
targets that are generated by `llvm_add_library` or
`add_llvm_executable`.

Internally, our toolchain builds were on average 1.4x faster when
selectively choosing the binaries that we want optimized.
  • Loading branch information
thevinster committed Oct 17, 2023
1 parent fc5d815 commit e90ec58
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 0 deletions.
11 changes: 11 additions & 0 deletions llvm/cmake/modules/AddLLVM.cmake
Expand Up @@ -726,6 +726,8 @@ function(llvm_add_library name)
endforeach()
endif()

add_custom_linker_flags(${name})

if(ARG_SHARED OR ARG_MODULE)
llvm_externalize_debuginfo(${name})
llvm_codesign(${name} ENTITLEMENTS ${ARG_ENTITLEMENTS} BUNDLE_PATH ${ARG_BUNDLE_PATH})
Expand Down Expand Up @@ -1019,6 +1021,8 @@ macro(add_llvm_executable name)
endforeach()
endif( LLVM_COMMON_DEPENDS )

add_custom_linker_flags(${name})

if(NOT ARG_IGNORE_EXTERNALIZE_DEBUGINFO)
llvm_externalize_debuginfo(${name})
endif()
Expand Down Expand Up @@ -1524,6 +1528,13 @@ macro(add_llvm_tool_subdirectory name)
add_llvm_external_project(${name})
endmacro(add_llvm_tool_subdirectory)

macro(add_custom_linker_flags name)
if (LLVM_${name}_LINKER_FLAGS)
message(STATUS "Applying ${LLVM_${name}_LINKER_FLAGS} to ${name}")
target_link_options(${name} PRIVATE ${LLVM_${name}_LINKER_FLAGS})
endif()
endmacro()

function(get_project_name_from_src_var var output)
string(REGEX MATCH "LLVM_EXTERNAL_(.*)_SOURCE_DIR"
MACHED_TOOL "${var}")
Expand Down
3 changes: 3 additions & 0 deletions llvm/docs/CMake.rst
Expand Up @@ -428,6 +428,9 @@ enabled sub-projects. Nearly all of these variable names begin with
$CMAKE_INSTALL_PREFIX/Toolchains containing an xctoolchain directory which can
be used to override the default system tools.

**LLVM_<target>_LINKER_FLAGS**:STRING
Defines the set of linker flags that should be applied to a <target>.

**LLVM_DEFAULT_TARGET_TRIPLE**:STRING
LLVM target to use for code generation when no target is explicitly specified.
It defaults to "host", meaning that it shall pick the architecture
Expand Down

0 comments on commit e90ec58

Please sign in to comment.