C++ CMake意外地将最后一个文件名前置到foreach中的可执行文件

C++ CMake意外地将最后一个文件名前置到foreach中的可执行文件,c++,cmake,C++,Cmake,我正在尝试为正在进行的库项目创建一个CMakeLists.txt。这是一个相当简单的结构,我已经能够通过以下设置重新创建我遇到的问题的一个简单示例: project ├── CMakeLists.txt ├── include │ ├── doctest.hpp │ └── foo.hpp └── src ├── foo.cpp ├── bar.cpp └── test-main.cpp 使用中提供的示例代码(\uu代替了GIST的/)。C++源代码和标题实际上

我正在尝试为正在进行的库项目创建一个CMakeLists.txt。这是一个相当简单的结构,我已经能够通过以下设置重新创建我遇到的问题的一个简单示例:

project
├── CMakeLists.txt
├── include
│   ├── doctest.hpp
│   └── foo.hpp
└── src
    ├── foo.cpp
    ├── bar.cpp
    └── test-main.cpp
使用中提供的示例代码(
\uu
代替了GIST的
/
)。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_最低要求(3.13版)
项目(foo版本0.0.1)
设置(源文件)
${CMAKE_SOURCE_DIR}/src/foo.cpp
${CMAKE_SOURCE_DIR}/src/bar.cpp
)
设置(头文件)
${CMAKE_SOURCE_DIR}/include/foo.hpp
)
集合(DOCTEST\u INCLUDE\u DIR${CMAKE\u SOURCE\u DIR}/INCLUDE)
添加_库(Doctest导入接口)
目标目录(Doctest接口${Doctest\u include\u DIR})
添加库(测试主对象${CMAKE\u SOURCE\u DIR}/src/test main.cpp)
目标链接库(测试主文档测试)
foreach(src${source\u files})
#去掉前导路径和扩展名,只留下不带扩展名的文件名为${testName}
字符串(正则表达式匹配“^.*/src/(.*)\\.[^.]*$”“${src})
集合(testName${CMAKE\u MATCH\u 1})
消息(状态${testName})
添加_可执行文件(“${testName}”“${src}”$)
目标目录(${testName}PRIVATE${CMAKE\u SOURCE\u DIR}/include)
添加测试(名称${testName}命令${testName})
endforeach()
问题是,虽然
cmake.
运行良好,但
make
也运行良好,而不是像我期望的那样,输出可执行文件是
src/[filenameWithoutExtensionHere]
,它最终是
src/bar.cppfoo
src/bar.cppbar
,显然是在源代码列表中的最终文件名前面加上可执行文件

这是不是因为我在使用
foreach
或调用
add\u executable
时没有意识到什么?
消息(STATUS${testName})
调用打印我所期望的内容,只打印没有路径或扩展名的文件名。我还尝试了在
add_executable
中引用/不引用
${testName}
的各种组合,以及从
add_test
中删除
NAME
命令
,但我不认为这是其中的一部分。这是我第一个使用CMake的项目,我有点不明白为什么会发生这种情况


是什么导致了最终源文件名的前置?如何避免它?

这是由行触发的

string(REGEX MATCH "^.*/src/(.*)\\.[^.]*$" "" ${src})
通过为
指定
,您似乎试图忽略它,因为您只关心捕获组。。。但这似乎有一些非常奇怪和不幸的副作用。您可以使用这个最小的
CMakeLists.txt文件获得相同的效果:

cmake_minimum_required(VERSION 3.13)
add_executable(foo ${CMAKE_SOURCE_DIR}/src/foo.cpp)
set("" some_prefix_)
我猜这会创建一个名称为空字符串的变量,但这会影响结果二进制文件的名称的原因是谁都猜不透的

只要把
dummy
match\u output
或任何东西放进去,问题就解决了:

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

@托马斯:我做了你建议的改变,但我仍然有问题。这可能是CMake的一个变化吗?我目前使用的是3.13.4版<代码>[100%]链接CXX可执行文件/home/nate/test/src/bar.cppfoo[100%]构建目标foo
对不起,我的错误。无论哪种情况,目标名称都是
foo
,这让我很反感,但最终的可执行文件名称仍然很混乱。啊,不用担心。谢谢你的帮助,希望我能尽快解决这个问题:D@Tsyvarev抱歉,似乎没有必要发布示例的源代码,因为它们实际上并不影响建筑,但我应该包含CMakeLists.txt内容。我已经添加了它们。是的,
CMakeLists.txt
就足够了。(正是我在之前的评论中所指的代码,现在被删除为过时代码。)哈!这似乎已经做到了!这是奇怪的,这会影响到一个单独的电话,但感谢整理它!