Reputation: 1794
I've added AddressSanitizer flag as follow:
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
Everything builds and runs fine when using Unix Makefiles
.
The problem comes when generating the Xcode project, it just doesn't want to link because it cannot find the ASan library.
I already found two solutions, but decided not to use them because they cannot be automated using just CMake:
-Wl,-undefined,dynamic_lookup
to the linked flags, so it skips linking to dynamic libraries. libclang_rt.asan_osx_dynamic.dylib
directly.So what's the problem with these two solutions?
DYLD_INSERT_LIBRARIES
environment variable pointing to libclang_rt.asan_osx_dynamic.dylib
.Additionally as another solution, I tried enabling Address Sanitizer flag from the Xcode target scheme but interestingly it didn't detect the issues I added, so I didn't list this as a solution because it failed my test.
Any help will be much appreciated.
Upvotes: 100
Views: 113572
Reputation: 91
I made it work for Xcode without hardcoding -fsanitize=address
. One may work normally in Xcode without sanitizers and when necessary enable them in Scheme settings without re-running CMake.
I copy asan libs to the following folder and that's it.
set (XCODE_DEVELOPER_TOOLCHAINS_ROOT
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain")
# Here is detection for iOS/MacOS, but other platforms also can be added here like tvos, watchos, xros
if (IOS)
set (PLATFORM_SUFFIX "ios")
else ()
set (PLATFORM_SUFFIX "osx")
endif ()
file (GLOB_RECURSE _asan_libs "${XCODE_DEVELOPER_TOOLCHAINS_ROOT}/*/libclang_rt.*an_${PLATFORM_SUFFIX}*_dynamic.dylib")
foreach (_asan_lib ${_asan_libs})
file (RELATIVE_PATH _asan_relative_to_toolchain "${XCODE_DEVELOPER_TOOLCHAINS_ROOT}/usr/" "${_asan_lib}")
configure_file ("${_asan_lib}" "${CMAKE_BINARY_DIR}/../${_asan_relative_to_toolchain}" COPYONLY)
endforeach ()
Also here I answered how to make it work with ccache: https://stackoverflow.com/a/77547119/5517503
Here is demo project https://github.com/Hsilgos/xcode-ccache-demo
Upvotes: 0
Reputation: 53173
The idea of this solution is to pass -fsanitize=address
to the compiler and linker flags.
If you would like to enable this for all your targets at the same time, you can use add_compile_options and add_link_options. This makes sense if you have multiple, potentially a large of, targets.
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
Alternatively, you can also use target_compile_options and target_link_options to set these for a particular target. This might make more sense if you do not want this to apply to all the targets.
target_compile_options(asan-target PRIVATE -fsanitize=address)
target_link_options(asan-target PRIVATE -fsanitize=address)
Upvotes: 112
Reputation: 3381
I propose create your own Asan profile.
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(isMultiConfig)
if(NOT "Asan" IN_LIST CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Asan)
endif()
else()
set(allowedBuildTypes Asan Debug Release RelWithDebInfo MinSizeRel)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowedBuildTypes}")
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE IN_LIST allowedBuildTypes)
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
endif()
endif()
set(CMAKE_C_FLAGS_ASAN
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C compiler for Asan build type or configuration." FORCE)
set(CMAKE_CXX_FLAGS_ASAN
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C++ compiler for Asan build type or configuration." FORCE)
set(CMAKE_EXE_LINKER_FLAGS_ASAN
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
"Linker flags to be used to create executables for Asan build type." FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_ASAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
"Linker lags to be used to create shared libraries for Asan build type." FORCE)
Notes:
AddressSanitizer (ASan) for Windows with MSVC is under experimental stage thus I didn't provided the MSVC way here.
CMAKE_BUILD_TYPE
isn't used by multi-configuration generators (Xcode, Visual Studio, etc), thus I provided an example to check this first.
The default value for CMAKE_BUILD_TYPE
is an empty string. And user can set CMAKE_BUILD_TYPE
to any value at the cmake command line. Therefore, we check both cases, and make sure that we are dealing with a known build type (if provided).
There is also CMAKE_MODULE_LINKER_FLAGS
you may want to configure.
Usage:
$ cmake \
-DCMAKE_BUILD_TYPE=Asan \
...
...
Upvotes: 28
Reputation: 2141
First ensure with debug info, such as setting passing CMAKE_BUILD_TYPE
to Debug
-g
flag for GCC/Clang.
Then, if your target is an executable or an shared library, then you may set those cmake variables:
CMAKE_EXE_LINKER_FLAGS
CMAKE_EXE_LINKER_FLAGS_DEBUG
CMAKE_SHARED_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS_DEBUG
i.e. When your target is an executable:
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
When your target is an shared library:
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
However, when your executable relies on an static library and you'd like to use asan to check your static library, then you have to set like this:
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
Upvotes: 5
Reputation: 16197
The simplest solution that I currently found is
cmake -DCMAKE_BUILD_TYPE=ASAN .
I prefer this option since it expresses the intent (run sanitizers) rather than modifies a number of flags.
I do not know when this option was added. I also cannot find any documentation to it.
Upvotes: -3
Reputation: 387
cmake 3.13
introduce configuration for xcode schema
in CMake
cmake_minimum_required(VERSION 3.13)
set(CMAKE_XCODE_GENERATE_SCHEME ON)
set(CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER ON)
set(CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN ON)
When Build
xcodebuild -enableAddressSanitizer YES
Upvotes: 14
Reputation: 643
You need to provide the flag(s) to the linker too. I'm doing it like this:
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
Upvotes: 46