在CMake中添加多个可执行文件


70

我在C ++项目中的代码组织如下

  • 我有几个.cpp.h文件,其中包含我的班
  • 我有几个.cxx文件必须针对这些.cpp文件和一些外部库进行编译。

现在,每个.cxx文件都有一个main()方法,因此我需要为每个文件添加与文件名称相同的不同可执行文件。

同样,这些.cxx文件可能不会链接到相同的外部库。

我想用CMake编写这个版本,我是一个新手,我该如何处理?

Answers:


107

我的建议是分两个阶段解决此问题:

  1. 使用.cpp和从和.h文件构建库add_library
  2. 遍历所有.cxx文件,并使用add_executable和从每个文件创建可执行文件foreach

建立图书馆

这可能很简单

file( GLOB LIB_SOURCES lib/*.cpp )
file( GLOB LIB_HEADERS lib/*.h )
add_library( YourLib ${LIB_SOURCES} ${LIB_HEADERS} )

生成所有可执行文件

只需遍历所有.cpp文件并创建单独的可执行文件即可。

# If necessary, use the RELATIVE flag, otherwise each source file may be listed 
# with full pathname. RELATIVE may makes it easier to extract an executable name
# automatically.
# file( GLOB APP_SOURCES RELATIVE app/*.cxx )
file( GLOB APP_SOURCES app/*.cxx )
foreach( testsourcefile ${APP_SOURCES} )
    # I used a simple string replace, to cut off .cpp.
    string( REPLACE ".cpp" "" testname ${testsourcefile} )
    add_executable( ${testname} ${testsourcefile} )
    # Make sure YourLib is linked to each app
    target_link_libraries( ${testname} YourLib )
endforeach( testsourcefile ${APP_SOURCES} )

一些警告:

  • file( GLOB )通常不建议这样做,因为如果添加新文件,CMake不会自动重建。我在这里使用它是因为我不知道您的源文件。
  • 在某些情况下,可能会找到具有完整路径名的源文件。如有必要,请将RELATIVE标志用于find( GLOB ... )
  • 手动设置源文件需要更改CMakeLists.txt,这会触发重建。请参阅此问题以了解球形的(缺点)优点。
  • 我使用生成了测试名string( REPLACE ... )。我本可以将get_filename_componentNAME_WE标志一起使用。

关于“常规” CMake信息,我建议您阅读一些关于stackoverflow的广泛的“ CMake概述”问题。例如:


+1个不错的答案。这些可执行文件是否都将构建在同一个顶级build/目录中,还是会尊重基础源代码树的目录结构?另请参阅此问题
TemplateRex 2013年

我尚未对其进行测试,但是假设它将在类似于source-dir的目录结构中生成可执行文件。无耻插头:看看stackoverflow.com/questions/13556885如何修改输出路径...
安德烈

3
如果您使用的是更新的cmake(我发现的最早的版本是3.0.2),则可以使用get_filename_component(testname ${testsourcefile} NAME_WE)而不是使用获取文件名string(REPLACE...。这样做的好处是,它还将删除路径的其余部分,如果您EXECUTABLE_OUTPUT_PATH用于设置二进制文件的存放位置,这将很方便。
Alex

@André有什么替代的替代品file( GLOB APP_SOURCES app/*.cxx )
ywiyogo

1
在使用它之前,我不得不进行了大量修改。我的配置如下:file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) foreach( sourcefile ${APP_SOURCES} ) file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${sourcefile}) string( REPLACE ".cpp" "" file ${filename} ) add_executable( ${file} ${sourcefile} ) target_link_libraries( ${file} ndn-cxx boost_system ) endforeach( sourcefile ${APP_SOURCES} )
rafee

0

CMakeLists.txt适用于我的OpenCV项目,
假设*.cpp文件与以下文件位于同一目录中CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(opencv LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(OpenCV REQUIRED)
include_directories( ${OpenCV_INCLUDE_DIRS} )

file( GLOB APP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp )
foreach( sourcefile ${APP_SOURCES} )
    file(RELATIVE_PATH filename ${CMAKE_CURRENT_SOURCE_DIR} ${sourcefile})
    string( REPLACE ".cpp" "" file ${filename} )
    add_executable( ${file} ${sourcefile} )
    target_link_libraries( ${file} ${OpenCV_LIBS} )
endforeach( sourcefile ${APP_SOURCES} )

0

在组织带有多个示例文件的OpenGL项目时,我发现自己处在类似的情况下,其中每个文件都包含一个主要方法。

下面的设置将为每个c / cpp文件生成一个单独的可执行文件,并将所需的依赖项复制到目标bin文件夹中。

资料夹结构

my-project
│── ch01_01.c
│── ch02_01.cpp
│── CMakeLists.txt
│── Resources
│   │── Libraries
│   │   │── glew
│   │   │   │── bin
│   │   │   │── include
│   │   │   │── lib
│   │   │── glfw    
│   │   │   │── include 
│   │   │   │── lib 

CMakeLists.txt

cmake_minimum_required (VERSION 3.9)

project ("my-project")

include_directories(Resources/Libraries/glew/include
                    Resources/Libraries/glfw/include)

link_directories(Resources/Libraries/glew/lib
                 Resources/Libraries/glfw/lib)

link_libraries(opengl32.lib
               glew32.lib
               glfw3.lib)

set(CMAKE_EXE_LINKER_FLAGS "/NODEFAULTLIB:MSVCRT")

file(GLOB SOURCE_FILES *.c *.cpp)

foreach(SOURCE_PATH ${SOURCE_FILES})

    get_filename_component(EXECUTABLE_NAME ${SOURCE_PATH} NAME_WE)

    add_executable(${EXECUTABLE_NAME} ${SOURCE_PATH})

    # Copy required DLLs to the target folder
    add_custom_command(TARGET ${EXECUTABLE_NAME} POST_BUILD
                       COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/Resources/Libraries/glew/bin/glew32.dll" 
                                                                     "${CMAKE_BINARY_DIR}/glew32.dll")

endforeach(SOURCE_PATH ${SOURCE_FILES})

可选步骤

在Visual Studio中

  • 在“开始”窗口中使用“打开本地文件夹”选项打开项目

  • 添加新文件时,您可以:

    • 取消询问对话框自动 add_executable进入CMakeLists.txt
    • 通过取消选中“为文件夹视图中的文件操作启用自动CMake脚本修改功能”来禁用此行为 Tools > Options > CMake

由于新添加的文件不会自动更改,因为CMakeLists.txt从未更改,因此只需重新生成缓存,如下所示:

  • Project > CMake Cache (x64-Debug) > Delete Cache
  • Project > Generate Cache for my-project

现在,您可以简单地右键单击给定的c / cpp文件并Set as Startup Item使用进行调试F5

环境

  • cmake版本3.18.20081302-MSVC_2
  • Microsoft Visual Studio Community 2019版本16.8.3
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.