ccmakevcpkgaddress-sanitizer

Industry practice of address sanitizer with vcpkg


I have authored a library with address sanitizer and "treating warnings as errors" configured in my CMakeLists.txt file

if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.1 AND NOT WIN32) # sanitizer
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-sanitize-recover=all")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined")
    # target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address,undefined -fno-sanitize-recover=all)
    # target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address,undefined)
endif ()


if (CMAKE_COMPILER_IS_GNUCC AND NOT WIN32) # werror
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -ansi")
    # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -ansi -pedantic")
    # target_compile_options(${PROJECT_NAME} PRIVATE -Werror -Wall -ansi)
    # target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -ansi -pedantic)
endif ()

option(BUILD_TESTS "Build Tests" ON) # Tests
if (BUILD_TESTS)
    enable_testing()
    include(CTest)

    add_subdirectory(test)
end if()

If you build your lib as a static lib with asan you need to build everything downstream with asan or at least link the asan libs.

As a result, the consumers of the library are also forced to link sanitizer with their builds.

Question:

As a user I don't want to be enforced the compilation flags but then at the same time I need my library to be perfect and sanitized.

An idea occurred, how can I install the debug the version with sanitization but then release version without.

Attempt 1

# Enable AddressSanitizer for Debug builds
if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WIN32) # sanitizer
    message(STATUS "Applying AddressSanitizer for Debug build")
    target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address,undefined -fno-sanitize-recover=all)
    target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address,undefined)
endif ()

if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND CMAKE_COMPILER_IS_GNUCC AND NOT WIN32) # werror
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -ansi")
    # target_compile_options(${PROJECT_NAME} PRIVATE -Werror -Wall -ansi)
    # target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -ansi -pedantic)
endif ()

Issue

As I consumed this library, and of course applying address sanitizer to my debug build in the consumer (reusing the same code block in my consumer), I still get asan errors. (implying both debug and release versions are applied address sanitizer)

Undefined symbols for architecture x86_64:
  "___asan_init", referenced from:

Solution

  • Based on the comments I have moved my sanitization under the test blocks.

    option(BUILD_TESTS "Build Tests" ON) # Tests
    if (BUILD_TESTS)
    
        if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.1 AND NOT WIN32) # sanitizer
            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-sanitize-recover=all")
            set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined")
            # target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address,undefined -fno-sanitize-recover=all)
            # target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address,undefined)
        endif ()
        
        
        if (CMAKE_COMPILER_IS_GNUCC AND NOT WIN32) # werror
            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -ansi")
            # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -ansi -pedantic")
            # target_compile_options(${PROJECT_NAME} PRIVATE -Werror -Wall -ansi)
            # target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -ansi -pedantic)
        endif ()
    
        enable_testing()
        include(CTest)
    
        add_subdirectory(test)
    end if()
    

    This way both release and debug builds are lightweight free to any dependencies while I can assure quality in my local tests before making it available for delivery via VCPKG etc.