CMake неожиданно добавляет последний файл к исполняемому файлу в foreach - PullRequest
2 голосов
/ 25 июня 2019

Я пытаюсь создать CMakeLists.txt для библиотечного проекта, над которым я работаю. Это довольно простая структура, и мне удалось воссоздать простой пример проблемы, с которой я сталкиваюсь, с помощью следующей настройки:

project
├── CMakeLists.txt
├── include
│   ├── doctest.hpp
│   └── foo.hpp
└── src
    ├── foo.cpp
    ├── bar.cpp
    └── test-main.cpp

с примером кода, доступным в этом gist (_ заменено на / для gists). Исходники и заголовки C ++ на самом деле не влияют на проблему, поэтому я не включаю их содержимое, но мой файл CMakeLists.txt по сути такой:

cmake_minimum_required(VERSION 3.13)
project(foo VERSION 0.0.1)

set(source_files
        ${CMAKE_SOURCE_DIR}/src/foo.cpp
        ${CMAKE_SOURCE_DIR}/src/bar.cpp
)

set(header_files
        ${CMAKE_SOURCE_DIR}/include/foo.hpp
)

set(DOCTEST_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include)
add_library(Doctest IMPORTED INTERFACE)
target_include_directories(Doctest INTERFACE ${DOCTEST_INCLUDE_DIR})

add_library(test-main OBJECT ${CMAKE_SOURCE_DIR}/src/test-main.cpp)
target_link_libraries(test-main Doctest)

foreach(src ${source_files})
        # Strip off leading path and extension, leaving only filename without extension to be ${testName}
        string(REGEX MATCH "^.*/src/(.*)\\.[^.]*$" "" ${src})
        set(testName ${CMAKE_MATCH_1})
        message(STATUS ${testName})

        add_executable("${testName}" "${src}" $<TARGET_OBJECTS:test-main>)
        target_include_directories(${testName} PRIVATE ${CMAKE_SOURCE_DIR}/include)
        add_test(NAME ${testName} COMMAND ${testName})
endforeach()

Проблема в том, что, хотя cmake . работает нормально, как и make, вместо выходного исполняемого файла, являющегося src/[filenameWithoutExtensionHere], как я и ожидал (из строка 24 в CMakeLists ), он заканчивается как src/bar.cppfoo и src/bar.cppbar, по-видимому, перед конечным именем файла в списке источников перед исполняемым файлом.

Это вызвано чем-то, о чем я не знаю в моем использовании foreach или в моем призвании add_executable? Вызов message(STATUS ${testName}) выводит то, что я ожидал, только имя файла без пути или расширения. Я также пробовал различные комбинации цитирования / не цитирования ${testName} в add_executable, а также удаления NAME и COMMAND из add_test, но я не думаю, что это является частью этого. Это мой первый проект с использованием CMake, и я немного не понимаю, почему это происходит.

Что вызывает предварительное добавление окончательного имени исходного файла и как его избежать?

1 Ответ

1 голос
/ 25 июня 2019

Это вызывается строкой

string(REGEX MATCH "^.*/src/(.*)\\.[^.]*$" "" ${src})

Указывая "" для <output variable>, вы, похоже, пытаетесь игнорировать его, потому что вы заботитесь только о группе захвата ... ноу этого, кажется, есть некоторые очень странные и неудачные побочные эффекты.Вы можете получить тот же эффект с этим минимальным CMakeLists.txt:

cmake_minimum_required(VERSION 3.13)
add_executable(foo ${CMAKE_SOURCE_DIR}/src/foo.cpp)
set("" some_prefix_)

Я предполагаю, что это создает переменную, имя которой является пустой строкой, но почему это повлияет на имя получающегося двоичного файла, никто не знает.

Просто поставьте dummy или match_output или что-то еще, и проблема исчезнет:

string(REGEX MATCH "^.*/src/(.*)\\.[^.]*$" match_output ${src})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...