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

Add detection for custom Linker #232

Merged
merged 10 commits into from
Aug 8, 2023
9 changes: 8 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,11 @@ services:
build:
context: .
dockerfile: ./docker/Dockerfile.arm-bare-metal
target: build
target: build
build-gcc-with-custom-linker:
build:
context: .
dockerfile: ./docker/Dockerfile
args:
compiler: gcc
target: build-with-custom-linker
14 changes: 14 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ RUN setup-cpp --compiler $compiler --llvm true --cmake true --doxygen true --nin
COPY ./docker/entrypoint.sh /docker-entrypoint.sh
ENTRYPOINT [ "/docker-entrypoint.sh" ]

FROM setup AS setup-custom-linker

# install linker
RUN apt-get update && apt-get install -y \
binutils \
mold \
lld \
&& rm -rf /var/lib/apt/lists/*

FROM setup AS build
COPY . /home/project_options
Expand All @@ -30,3 +38,9 @@ WORKDIR /home/project_options
RUN git submodule update --init
CMD ["/bin/bash", "-c", "task myproj:test"]


FROM setup-custom-linker AS build-with-custom-linker
COPY . /home/project_options
WORKDIR /home/project_options
RUN git submodule update --init
CMD ["/bin/bash", "-c", "task myproj:build"]
4 changes: 4 additions & 0 deletions docker/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ tasks:
- docker-compose up --build test-gcc
- docker-compose down

gcc.custom-linker:
- docker-compose up --build build-gcc-with-custom-linker
- docker-compose down

llvm:
- docker-compose up --build build-llvm
- docker-compose up --build test-llvm
Expand Down
118 changes: 116 additions & 2 deletions src/Linker.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
include_guard()

# Test linker option support
function(test_linker_option output_linker_test linker)
set(output_linker_test OFF PARENT_SCOPE)
if(NOT "${linker}" STREQUAL "")
include(CheckCXXCompilerFlag)

set(_linker_flag "-fuse-ld=${linker}")

check_cxx_compiler_flag(${_linker_flag} _cxx_supports_linker)
if("${_cxx_supports_linker}" STREQUAL "1")
set(${output_linker_test} ON PARENT_SCOPE)
else()
set(${output_linker_test} OFF PARENT_SCOPE)
endif()
endif()
endfunction()

# Set the linker to use for the linking phase
macro(configure_linker _project_name _linker)
if(NOT "${_linker}" STREQUAL "")
Expand All @@ -8,8 +25,8 @@ macro(configure_linker _project_name _linker)

set(_linker_flag "-fuse-ld=${_linker}")

check_cxx_compiler_flag(${_linker_flag} _cxx_supports_linker)
if("${_cxx_supports_linker}" STREQUAL "1")
test_linker_option(_cxx_supports_linker ${_linker})
if(_cxx_supports_linker)
message(TRACE "Using ${_linker} as the linker for ${_project_name}")
target_link_options(${_project_name} INTERFACE ${_linker_flag})
else()
Expand All @@ -19,3 +36,100 @@ macro(configure_linker _project_name _linker)
endif()
endif()
endmacro()

#[[.rst:

``find_linker``
===============

Find a linker prefering the linkers in this order: sold, mold, lld, gold, the system linker

Output variables:

- ``LINKER``: the linker to use

]]
function(find_linker LINKER)
find_sold(_PROGRAM_sold)
if(_PROGRAM_sold)
set(${LINKER} "sold" PARENT_SCOPE)
return()
endif()

find_mold(_PROGRAM_mold)
if(_PROGRAM_mold)
set(${LINKER} "mold" PARENT_SCOPE)
return()
endif()

find_lld(_PROGRAM_lld)
if(_PROGRAM_lld)
set(${LINKER} "lld" PARENT_SCOPE)
return()
endif()

find_gold(_PROGRAM_gold)
if(_PROGRAM_gold)
set(${LINKER} "gold" PARENT_SCOPE)
return()
endif()

# else, use the default linker
set(${LINKER} "" PARENT_SCOPE)
endfunction()

function(find_sold PROGRAM_sold)
if(UNIX AND NOT WIN32)
find_program(_PROGRAM_sold NAMES "sold")
if(EXISTS ${_PROGRAM_sold})
test_linker_option(SUPPORTS_SOLD "sold")
if(SUPPORTS_SOLD)
set(${PROGRAM_sold} ${_PROGRAM_sold} PARENT_SCOPE)
return()
endif()
endif()
endif()
set(${PROGRAM_sold} OFF PARENT_SCOPE)
endfunction()

function(find_mold PROGRAM_mold)
if(UNIX AND NOT WIN32)
find_program(_PROGRAM_MOLD NAMES "mold")
if(EXISTS ${_PROGRAM_MOLD})
test_linker_option(SUPPORTS_MOLD "mold")
if(SUPPORTS_MOLD)
set(${PROGRAM_mold} ${_PROGRAM_MOLD} PARENT_SCOPE)
return()
endif()
endif()
endif()
set(${PROGRAM_mold} OFF PARENT_SCOPE)
endfunction()

function(find_lld PROGRAM_lld)
if((CMAKE_CXX_COMPILER_ID MATCHES ".*Clang.*"))
find_program(_PROGRAM_LLD NAMES "lld")
if(EXISTS ${_PROGRAM_LLD})
test_linker_option(SUPPORTS_LLD "lld")
if(SUPPORTS_LLD)
set(${PROGRAM_lld} ${_PROGRAM_LLD} PARENT_SCOPE)
return()
endif()
endif()
endif()
set(${PROGRAM_lld} OFF PARENT_SCOPE)
endfunction()

function(find_gold PROGRAM_gold)
if((CMAKE_CXX_COMPILER_ID MATCHES ".*GNU.*") AND NOT WIN32)
find_program(_PROGRAM_GOLD NAMES "gold")
if(EXISTS ${_PROGRAM_GOLD})
test_linker_option(SUPPORTS_GOLD "gold")
if(SUPPORTS_GOLD)
set(${PROGRAM_gold} ${_PROGRAM_GOLD} PARENT_SCOPE)
return()
endif()
endif()
endif()
set(${PROGRAM_gold} OFF PARENT_SCOPE)
endfunction()
55 changes: 53 additions & 2 deletions src/Sanitizers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ function(

if(${ENABLE_SANITIZER_ADDRESS})
list(APPEND SANITIZERS "address")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL
8
)
list(APPEND SANITIZERS "pointer-compare" "pointer-subtract")
message(
STATUS
"To enable invalid pointer pairs detection, add detect_invalid_pointer_pairs=2 to the environment variable ASAN_OPTIONS."
"To enable invalid pointer pairs detection, add detect_invalid_pointer_pairs=2 to the environment variable ASAN_OPTIONS."
)
endif()
endif()
Expand Down Expand Up @@ -91,3 +93,52 @@ function(
endif()

endfunction()

# detect sanitizers support for compiler
function(
check_sanitizers_support
ENABLE_SANITIZER_ADDRESS
ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
ENABLE_SANITIZER_LEAK
ENABLE_SANITIZER_THREAD
ENABLE_SANITIZER_MEMORY
)
set(SANITIZERS "")
if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
list(APPEND SANITIZERS "address")
list(APPEND SANITIZERS "undefined")
list(APPEND SANITIZERS "leak")
list(APPEND SANITIZERS "thread")
list(APPEND SANITIZERS "memory")
elseif(MSVC)
# or it is MSVC and has run vcvarsall
string(FIND "$ENV{PATH}" "$ENV{VSINSTALLDIR}" index_of_vs_install_dir)
if("${index_of_vs_install_dir}" STREQUAL "-1")
list(APPEND SANITIZERS "address")
endif()
endif()

list(JOIN SANITIZERS "," LIST_OF_SANITIZERS)

if(LIST_OF_SANITIZERS)
if(NOT "${LIST_OF_SANITIZERS}" STREQUAL "")
if("address" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_ADDRESS} "ENABLE_SANITIZER_ADDRESS" PARENT_SCOPE)
endif()
if("undefined" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_UNDEFINED_BEHAVIOR} "ENABLE_SANITIZER_UNDEFINED_BEHAVIOR"
PARENT_SCOPE
)
endif()
if("leak" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_LEAK} "ENABLE_SANITIZER_LEAK" PARENT_SCOPE)
endif()
if("thread" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_THREAD} "ENABLE_SANITIZER_THREAD" PARENT_SCOPE)
endif()
if("memory" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_MEMORY} "ENABLE_SANITIZER_MEMORY" PARENT_SCOPE)
endif()
endif()
endif()
endfunction()
45 changes: 0 additions & 45 deletions src/Utilities.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -124,48 +124,3 @@ function(detect_architecture arch)
set(${arch} x64 PARENT_SCOPE)
endif()
endfunction()

# detect sanitizers support for compiler
function(check_sanitizers_support
ENABLE_SANITIZER_ADDRESS
ENABLE_SANITIZER_UNDEFINED_BEHAVIOR
ENABLE_SANITIZER_LEAK
ENABLE_SANITIZER_THREAD
ENABLE_SANITIZER_MEMORY)
set(SANITIZERS "")
if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
list(APPEND SANITIZERS "address")
list(APPEND SANITIZERS "undefined")
list(APPEND SANITIZERS "leak")
list(APPEND SANITIZERS "thread")
list(APPEND SANITIZERS "memory")
elseif(MSVC)
# or it is MSVC and has run vcvarsall
string(FIND "$ENV{PATH}" "$ENV{VSINSTALLDIR}" index_of_vs_install_dir)
if("${index_of_vs_install_dir}" STREQUAL "-1")
list(APPEND SANITIZERS "address")
endif()
endif()

list(JOIN SANITIZERS "," LIST_OF_SANITIZERS)

if(LIST_OF_SANITIZERS)
if(NOT "${LIST_OF_SANITIZERS}" STREQUAL "")
if("address" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_ADDRESS} "ENABLE_SANITIZER_ADDRESS" PARENT_SCOPE)
endif()
if("undefined" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_UNDEFINED_BEHAVIOR} "ENABLE_SANITIZER_UNDEFINED_BEHAVIOR" PARENT_SCOPE)
endif()
if("leak" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_LEAK} "ENABLE_SANITIZER_LEAK" PARENT_SCOPE)
endif()
if("thread" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_THREAD} "ENABLE_SANITIZER_THREAD" PARENT_SCOPE)
endif()
if("memory" IN_LIST SANITIZERS)
set(${ENABLE_SANITIZER_MEMORY} "ENABLE_SANITIZER_MEMORY" PARENT_SCOPE)
endif()
endif()
endif()
endfunction()
7 changes: 7 additions & 0 deletions tests/myproj/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ check_sanitizers_support(ENABLE_SANITIZER_ADDRESS
ENABLE_SANITIZER_THREAD
ENABLE_SANITIZER_MEMORY)

# Detect custom linker
if(NOT MSVC)
find_linker(LINKER)
#message(STATUS "Detect Linker: ${LINKER}")
endif()

# Initialize project_options
# uncomment the options to enable them
project_options(
Expand Down Expand Up @@ -66,6 +72,7 @@ project_options(
# ${ENABLE_SANITIZER_THREAD}
# ${ENABLE_SANITIZER_MEMORY}
# CLANG_WARNINGS "-Weverything"
LINKER "${LINKER}"
)
# NOTE: project_options and project_warnings are defined inside project_options

Expand Down