-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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 CMake options to build using sanitizers #1053
Changes from 9 commits
d3196e4
1c7f4de
349492b
cfe3a54
6ad84d4
233d0d4
014a61a
9eaf635
79ee5cc
001e97c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,53 @@ | |
cmake_minimum_required(VERSION 2.8.11) | ||
project(firestore C CXX) | ||
|
||
option(ASAN "Build with Address sanitizer (mutually exculsive with TSAN)" OFF) | ||
# TODO(varconst): msan | ||
# Memory sanitizer is more complicated: | ||
# - it requires all dependencies to be compiled with msan enabled (see | ||
# https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo); | ||
# - AppleClang doesn't support it. | ||
option(TSAN "Build with Thread sanitizer (mutually exculsive with ASAN)" OFF) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Conventionally these kinds of options are There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. I like that this prefix makes them grouped together in the cache. |
||
option(UBSAN "Build with Undefined behavior sanitizer" OFF) | ||
|
||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cmake/CompilerSetup.cmake defines CLANG and GNU with these values, so you could simplify to just (Note that the include of CompilerSetup is below.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I can't move There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could also factor out compiler detection from An extension of that would be to move this setup into there too since this is largely compiler setup stuff anyway, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It seems to me that it's the least intrusive way, I can do it in one of the follow-ups. |
||
set(HAVE_SANITIZERS 1) | ||
endif() | ||
if(ASAN OR TSAN OR UBSAN) | ||
set(USE_SANITIZERS 1) | ||
endif() | ||
|
||
if (NOT HAVE_SANITIZERS AND USE_SANITIZERS) | ||
message(FATAL_ERROR "Only Clang and GCC support sanitizers.") | ||
endif() | ||
|
||
function(add_to_compile_and_link_flags flag) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you make this a macro instead of a function you can avoid the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) | ||
set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} ${flag}" PARENT_SCOPE) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Elsehwere I've seen this specified as CMAKE_EXE_FLAGS since we only need to specify these extra flags during compilation and final linking into our tests. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, it looks like I'm using a non-existent CMake variable. Changed to The build actually works without specifying the linker flag at all. If linking is invoked via the frontend call (e.g., via |
||
endfunction() | ||
|
||
if (HAVE_SANITIZERS AND USE_SANITIZERS) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic seems more complicated than it needs to be. It seems like you could just have
This eliminates There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. The intention behind those named variables was to make things clearer, but I think the shorter version is at least as readable. |
||
if ((ASAN AND TSAN) OR (UBSAN AND TSAN)) | ||
message(FATAL_ERROR "You cannot combine sanitizers except asan and ubsan.") | ||
endif() | ||
|
||
# Recommended to "get nicer stack traces in error messages" | ||
# TODO(varconst): double-check that tsan actually needs this flag (it's | ||
# explicitly recommended in the docs for asan and ubsan) | ||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer") | ||
|
||
if (TSAN) | ||
add_to_compile_and_link_flags("-fsanitize=thread") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't tsan also need us to specify There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, apparently not. The most relevant thing I could find is this thread, which doesn't contain a definitive answer, but has this quote from the Clang docs:
I couldn't find the same stated explicitly for GCC. However, the wiki page for TSan only has the following instructions:
(Let me know if you think |
||
else() | ||
if (ASAN) | ||
add_to_compile_and_link_flags("-fsanitize=address") | ||
endif() | ||
if (UBSAN) | ||
add_to_compile_and_link_flags("-fsanitize=undefined") | ||
endif() | ||
endif() | ||
endif() | ||
|
||
set(FIREBASE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/..) | ||
|
||
# CMAKE_INSTALL_PREFIX should be passed in to this build so that it can find | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All your changes here might make more sense in cmake/CompilerOptions.cmake, though they would then apply across all of the repo. (As long as everything defaults to off, maybe that's ok?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm okay with that, let's postpone until the next round of review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better not to hide the options we support since this file serves as documentation for people trying to figure out how to configure this build to their purposes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wilhuff Do you think that it would be worthwhile to have these options in the Firebase build as well? If that were the case, I thought about splitting the sanitizer logic from here into
./cmake/Sanitizers.cmake
and including that in both projects. It's a good point that it would make these options non-obvious, so perhaps it would be okay to have the declaration of sanitizer options twice, once for each project. What do you think?