Ошибка в cmake, программа компилируется без нужных флагов

cmake_minimum_required(VERSION 3.0.0)
project(Tanks VERSION 0.1.0)

option(ENABLE_UNIT_TESTS "Enable unittest" ON)
message(STATUS "Enable testing: ${ENABLE_UNIT_TESTS}")

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
if(NOT SDL2_IMAGE_FOUND)
    message(FATAL_ERROR "SDL2_IMAGE NOT FOUND")
    return()
endif()

if(NOT SDL2_FOUND)
    message(FATAL_ERROR "SDL2 NOT FOUND")
    return()
else()
    include_directories(${SDL2_INCLUDE_DIRS} ${SDL2_IMAGE_INCLUDE_DIRS} headers/)
    file(GLOB SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
    add_executable(main ${SOURCES})
    set_target_properties(main
                          PROPERTIES
                          ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
                          LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
                          RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
                          CMAKE_CXX_STANDARD_REQUIRED ON
                          CMAKE_CXX_STANDARD 17
                          CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -std=c++17"
                          CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -g -fsanitize=address -fsanitize=leak" #<-- Нужный мне флаг! 
                          CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O2"
                         ) #<--Мотни скролбар снизу вправо, коммент выше не помещается
    target_compile_options(main PUBLIC ${CMAKE_CXX_FLAGS_DEBUG}) #<-- Добавляю флаг!
    target_link_libraries(main 
                          ${SDL2_LIBRARIES} 
                          ${SDL2_IMAGE_LIBRARIES})
    message(STATUS "Copy sprites folder")
    file(COPY Sprites DESTINATION .)
    if(ENABLE_UNIT_TESTS)   
        enable_testing()
        add_subdirectory(tests)
    endif()
endif()

Мне нужно собрать программу с флагом санитайзера, прочитал, добавил флаги в cmake, но 0 реакции, хочу разобраться, что же я делаю неверно. Если запустить cmake командой:

cmake .. -DCMAKE_CXX_FLAGS="-fsanitize=address -fsanitize=leak"

То все работает, я вижу вывод санитайзера, но что я прописал в cmake не так - понять не могу


Ответы (1 шт):

Автор решения: Fat-Zer

Различные ошибки, неточности и плохие практики

cmake_minimum_required(VERSION 3.0.0)

3.0.0 — это довольно древняя версия и, если нет особых причин придерживаться какой-либо более старой версии, хорошей практикой будет указывать версию CMake своей системы. В любом случае не стоит указывать ту версию, на которой сборка не тестировалась.

if(NOT SDL2_IMAGE_FOUND)

т.к. find_package вызван с параметром REQUIRED, то эта проверка излишняя.

file(GLOB SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")

Использовать GLOB для получения списка исходников — плохая практика. См. примечание к file(GLOB ...).

set_target_properties(main PROPERTIES
                      ...
                      CMAKE_CXX_STANDARD_REQUIRED ON
                      ...

Свойства с именем CMAKE_CXX_STANDARD_REQUIRED и подобные не существуют. Есть одноимённые переменные СMake, но через set_target_properties их установить нельзя. Список свойств можно посмотреть в man 7 cmake-properties.

Мне бы по дефолту собирать с санитайзером

ИМХО это плохая практика. Санитайзер — тяжёлая и накладная штука и сборка с ним по умолчанию — неожиданный результат обычных действий.


Как бы я это сделал

cmake_minimum_required(VERSION 3.18.5)
project(Tanks VERSION 0.1.0)

option(ENABLE_UNIT_TESTS "Enable unittest" ON)
option(ENABLE_SANITIZER "Pass -fsanitize=address and -fsanitize=leak to compiller" OFF)

message(STATUS "Enable testing: ${ENABLE_UNIT_TESTS}")

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)

include_directories(${SDL2_INCLUDE_DIRS} ${SDL2_IMAGE_INCLUDE_DIRS} headers/)

set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -pedantic")

if(ENABLE_SANITIZER) 
  string(APPEND CMAKE_CXX_FLAGS " -fsanitize=address -fsanitize=leak")
  string(APPEND CMAKE_LINKER_FLAGS " -fsanitize=address -fsanitize=leak")
endif()

string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -pedantic")

# Нет смысла задавать все эти переменные для каждой отдельной цели;
# если они нужны, то лучше сделать их общими
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")

set(SOURCES src/foo.cpp src/bar.cpp
            ...  # и другие исходники
)

add_executable(main ${SOURCES})
target_link_libraries(main 
                      ${SDL2_LIBRARIES} 
                      ${SDL2_IMAGE_LIBRARIES})

message(STATUS "Copy sprites folder")
file(COPY Sprites DESTINATION .)
if(ENABLE_UNIT_TESTS)   
  enable_testing()
  add_subdirectory(tests)
endif()

Соответственно сборка с санитайзером будет выглядеть как

cmake /path/to/build -DENABLE_SANITIZER=ON

Если уж очень хочется включить сборку с санитайзаером по умолчанию, то можно поменять OFF на ON в объяввлении опции ENABLE_SANITIZER.

→ Ссылка