多项目 cmake 不工作
Multi-Project cmake not working
我的情况
我正在尝试使用 cmake
设置项目结构和构建脚本,但出现错误
我的应用程序无法找到我尝试包含的头文件。
我希望有人能指导我解决这个问题。
当前项目
该项目只是一个示例,简化为一个应用程序和一个库项目。目标是
有多个客户端和多个库(有些相互依赖)。
clients/Desktop
例如是一个使用 core/
库的应用程序。
该图显示了项目结构(来自 Visual Studio Code explorer 的屏幕截图)
在包含文件夹中有一个像项目一样命名的文件夹是将包含从 Core.h
至 Core/Core.h
。或者至少这是计划。也许这就是问题所在?
好的,现在是代码:
clients\Desktop\src\main.cpp
:
#include "Core/Core.h"
#include <iostream>
int main(int argc, char* argv[]) {
ProjectStructure::Core::Example ex;
ex.sayHello();
}
Core\include\Core\Core.h
:
#ifndef PROJECTSTRUCTURE_CORE_CORE_H
#define PROJECTSTRUCTURE_CORE_CORE_H
#include <iostream>
namespace ProjectStructure {
namespace Core {
class Example {
public:
void sayHello();
};
} // namespace Core
} // namespace ProjectStructure
#endif
Core\src\Core.cpp
:
#include "Core/Core.h"
namespace ProjectStructure {
namespace Core {
void Example::sayHello() {
std::cout << "Hello world.";
}
} // namespace Core
} // namespace ProjectStructure
clients\Desktop\include\CMakeLists.txt
:
ADD_SUBDIRECTORY("Desktop")
clients\Desktop\src\CMakeLists.txt
:
SET(APP_HEADERS
)
SET(APP_SOURCES
"main.cpp"
)
# Make executable
ADD_EXECUTABLE("${PROJECT_NAME}" "${APP_SOURCES}")
TARGET_LINK_LIBRARIES("${PROJECT_NAME}" "Core")
clients\Desktop\CMakeLists.txt
:
# Version check
cmake_minimum_required(VERSION 3.5)
# Project
PROJECT("Desktop" CXX)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include")
ADD_SUBDIRECTORY("include")
ADD_SUBDIRECTORY("src")
ADD_SUBDIRECTORY("test")
clients\CMakeLists.txt
:
# Executables
ADD_SUBDIRECTORY("${PROJECTSTRUCTURE_CLIENTS_DIR}/Desktop")
Core\include\CMakeLists.txt
:
ADD_SUBDIRECTORY("Core")
Core\src\CMakeLists.txt
:
SET(LIB_HEADERS
"../include/Core/Core.h"
)
SET(LIB_SOURCES
"Core.cpp"
)
# Make library
ADD_LIBRARY("${PROJECT_NAME}" STATIC "${LIB_SOURCES}")
SET_TARGET_PROPERTIES("${PROJECT_NAME}" PROPERTIES
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}"
)
INSTALL(TARGETS "${PROJECT_NAME}"
EXPORT "${PROJECT_NAME}Targets"
ARCHIVE DESTINATION lib COMPONENT libs
RUNTIME DESTINATION bin COMPONENT libs
LIBRARY DESTINATION lib COMPONENT libs
PUBLIC_HEADER DESTINATION include/${PROJECT_NAME} COMPONENT devel
INCLUDES DESTINATION include
)
Core\CMakeLists.txt
:
# Version check
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
# Project
PROJECT("Core" CXX)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include")
ADD_SUBDIRECTORY("include")
ADD_SUBDIRECTORY("src")
ADD_SUBDIRECTORY("test")
最后但同样重要的是顶级 CMakeLists.txt
:
# Version check
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
# Project
PROJECT("ProjectStructure" CXX)
# Status
MESSAGE(STATUS "Cmake running...")
MESSAGE(STATUS "System: ${CMAKE_SYSTEM}")
MESSAGE(STATUS "System: ${CMAKE_SYSTEM_PROCESSOR}")
MESSAGE(STATUS "Cmake-Version: ${CMAKE_VERSION}")
MESSAGE(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER}")
# Project structure
SET(CMAKE_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/include")
SET(CMAKE_BINARY_DIR "${CMAKE_SOURCE_DIR}/build")
SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
SET(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
SET(PROJECTSTRUCTURE_CLIENTS_DIR "${CMAKE_SOURCE_DIR}/clients")
# Prohibit in source builds
IF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
MESSAGE(SEND_ERROR "In-source builds are not allowed. Remove generated files.")
ENDIF()
# Output settings
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(CMAKE_COLOR_MAKEFILE ON)
# Build mode
SET(CMAKE_BUILD_TYPE Debug) # Dev
#SET(CMAKE_BUILD_TYPE RelWithDebInfo) # Test
#SET(CMAKE_BUILD_TYPE Release) # Release
# Used features
SET(CMAKE_CXX_STANDARD 14) # -std=c++14
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
# Compiler flags
SET(CMAKE_CXX_FLAGS "-Wall -Wextra")
SET(CMAKE_CXX_FLAGS_DEBUG "-g3 -O0") # Dev
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3") # Test
SET(CMAKE_CXX_FLAGS_RELEASE "-O3") # Release
# Libraries
ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
# Executables
ADD_SUBDIRECTORY("${PROJECTSTRUCTURE_CLIENTS_DIR}")
我正在使用以下命令使用源代码外构建:
cd build
cmake .. -G "MSYS Makefiles"
然后 运行 使用:
make
注意:真实项目还包含文档目录和其他一些东西。
还有 .gitignore
和 .travis.yml
之类的文件(但这是我必须开始工作的下一件事)。
问题:
cmake
命令有效,但 make
命令告诉我包含的文件 (Core.h
) 可以
找不到。
我认为问题出在安装库的部分。但我无法找到
正确的方法。我在这里发布的解决方案只是我尝试过的众多解决方案中的一个。
其他问题:
1. 标有 A 的 CMakeLists 是空的。他们刚刚添加的地方,以便每个目录
有一个 CMakeLists 文件。我应该删除它们吗?
2. 我想在我的项目中使用 google-test/mock 对每个项目进行测试
project/test
文件夹。我足以在顶层 CMakeLists 中包含 google 测试来完成这个
工作还是我必须将它包含在每个子项目中?
3. 列出源文件或自动加载它们是好的做法吗?我觉得上市
即使工作更多,它们也会更好。我认为这在重新加载时对 cmake
也有好处
该项目。测试也是如此吗?我正在考虑为每个来源制作一个测试文件
文件。
这似乎不是安装部分的问题。我认为您添加包含目录的方式有问题。 :)
当你使用 INCLUDE_DIRECTORIES 时,你说 cmake 应该为这个 CMakeLists 中的文件的编译器添加适当的标志。但不在父 CMakeLists 中添加的文件中。我认为堆栈是这种情况的一个很好的类比。 (https://cmake.org/cmake/help/v3.5/command/include_directories.html)
请注意,您在 ./CMakeLists.txt
中添加了 ./Core/CMakeLists.txt
:ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
,稍后添加客户端子目录时,./Core/include
不再使用。
恕我直言,最优雅的解决方案是使用
TARGET_INCLUDE_DIRECTORIES(Core PUBLIC pathToCoresHeaders)
代替。如果您决定使用它,TARGET_LINK_LIBRARIES("${PROJECT_NAME}" "Core")
行将为桌面可执行文件添加正确的包含路径。
AD1。是的,我认为你应该删除它们。您可以将 CMakeLists.txt 保留在 test
的目录中,因为 UT 通常需要多一个目标。
AD2。我建议在您开始定义自己的目标之前将它添加到顶级目录中,并且 link 您的测试执行程序使用 gtest
和 gtest_main
,这应该注册 gtest 的包含路径。
AD3。我在 cmake 中列出了我所有的文件。我宁愿在构建结束时看到有关丢失文件的错误,也不愿看到未解析的外部符号。但它不是非黑即白的 (Specify source files globally with GLOB?)。你应该自己做决定并承担后果。
PS1。我建议在一些类似 unix 的系统上额外测试你的构建,因为 Windows 对大小写不敏感太自由了。
我会做一些更改来改进您的构建系统。
./Core/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
PROJECT(Core CXX)
SET(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include)
SET(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
SET(LIB_HEADERS
${INCLUDE_DIRS}/Core/Core.h
)
SET(LIB_SOURCES
${SOURCE_DIR}/Core.cpp
)
# Make library
ADD_LIBRARY("${PROJECT_NAME}" STATIC ${LIB_SOURCES} ${LIB_HEADERS})
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME}
PUBLIC ${INCLUDE_DIRS}
)
SET_TARGET_PROPERTIES("${PROJECT_NAME}" PROPERTIES
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}"
)
INSTALL(TARGETS "${PROJECT_NAME}"
EXPORT "${PROJECT_NAME}Targets"
ARCHIVE DESTINATION lib COMPONENT libs
RUNTIME DESTINATION bin COMPONENT libs
LIBRARY DESTINATION lib COMPONENT libs
PUBLIC_HEADER DESTINATION include/${PROJECT_NAME} COMPONENT devel
INCLUDES DESTINATION include
)
ADD_SUBDIRECTORY(test)
./clients/Desktop/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project("Desktop" CXX)
SET(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
SET(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
SET(APP_HEADERS
)
SET(APP_SOURCES
${SOURCE_DIR}/main.cpp
)
# Make executable
ADD_EXECUTABLE(${PROJECT_NAME} ${APP_SOURCES} ${APP_HEADERS})
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} PRIVATE ${INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} Core)
add_subdirectory(test)
我的情况
我正在尝试使用 cmake
设置项目结构和构建脚本,但出现错误
我的应用程序无法找到我尝试包含的头文件。
我希望有人能指导我解决这个问题。
当前项目
该项目只是一个示例,简化为一个应用程序和一个库项目。目标是 有多个客户端和多个库(有些相互依赖)。
clients/Desktop
例如是一个使用 core/
库的应用程序。
该图显示了项目结构(来自 Visual Studio Code explorer 的屏幕截图)
在包含文件夹中有一个像项目一样命名的文件夹是将包含从 Core.h
至 Core/Core.h
。或者至少这是计划。也许这就是问题所在?
好的,现在是代码:
clients\Desktop\src\main.cpp
:
#include "Core/Core.h"
#include <iostream>
int main(int argc, char* argv[]) {
ProjectStructure::Core::Example ex;
ex.sayHello();
}
Core\include\Core\Core.h
:
#ifndef PROJECTSTRUCTURE_CORE_CORE_H
#define PROJECTSTRUCTURE_CORE_CORE_H
#include <iostream>
namespace ProjectStructure {
namespace Core {
class Example {
public:
void sayHello();
};
} // namespace Core
} // namespace ProjectStructure
#endif
Core\src\Core.cpp
:
#include "Core/Core.h"
namespace ProjectStructure {
namespace Core {
void Example::sayHello() {
std::cout << "Hello world.";
}
} // namespace Core
} // namespace ProjectStructure
clients\Desktop\include\CMakeLists.txt
:
ADD_SUBDIRECTORY("Desktop")
clients\Desktop\src\CMakeLists.txt
:
SET(APP_HEADERS
)
SET(APP_SOURCES
"main.cpp"
)
# Make executable
ADD_EXECUTABLE("${PROJECT_NAME}" "${APP_SOURCES}")
TARGET_LINK_LIBRARIES("${PROJECT_NAME}" "Core")
clients\Desktop\CMakeLists.txt
:
# Version check
cmake_minimum_required(VERSION 3.5)
# Project
PROJECT("Desktop" CXX)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include")
ADD_SUBDIRECTORY("include")
ADD_SUBDIRECTORY("src")
ADD_SUBDIRECTORY("test")
clients\CMakeLists.txt
:
# Executables
ADD_SUBDIRECTORY("${PROJECTSTRUCTURE_CLIENTS_DIR}/Desktop")
Core\include\CMakeLists.txt
:
ADD_SUBDIRECTORY("Core")
Core\src\CMakeLists.txt
:
SET(LIB_HEADERS
"../include/Core/Core.h"
)
SET(LIB_SOURCES
"Core.cpp"
)
# Make library
ADD_LIBRARY("${PROJECT_NAME}" STATIC "${LIB_SOURCES}")
SET_TARGET_PROPERTIES("${PROJECT_NAME}" PROPERTIES
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}"
)
INSTALL(TARGETS "${PROJECT_NAME}"
EXPORT "${PROJECT_NAME}Targets"
ARCHIVE DESTINATION lib COMPONENT libs
RUNTIME DESTINATION bin COMPONENT libs
LIBRARY DESTINATION lib COMPONENT libs
PUBLIC_HEADER DESTINATION include/${PROJECT_NAME} COMPONENT devel
INCLUDES DESTINATION include
)
Core\CMakeLists.txt
:
# Version check
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
# Project
PROJECT("Core" CXX)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include")
ADD_SUBDIRECTORY("include")
ADD_SUBDIRECTORY("src")
ADD_SUBDIRECTORY("test")
最后但同样重要的是顶级 CMakeLists.txt
:
# Version check
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
# Project
PROJECT("ProjectStructure" CXX)
# Status
MESSAGE(STATUS "Cmake running...")
MESSAGE(STATUS "System: ${CMAKE_SYSTEM}")
MESSAGE(STATUS "System: ${CMAKE_SYSTEM_PROCESSOR}")
MESSAGE(STATUS "Cmake-Version: ${CMAKE_VERSION}")
MESSAGE(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER}")
# Project structure
SET(CMAKE_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/include")
SET(CMAKE_BINARY_DIR "${CMAKE_SOURCE_DIR}/build")
SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
SET(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
SET(PROJECTSTRUCTURE_CLIENTS_DIR "${CMAKE_SOURCE_DIR}/clients")
# Prohibit in source builds
IF("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
MESSAGE(SEND_ERROR "In-source builds are not allowed. Remove generated files.")
ENDIF()
# Output settings
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(CMAKE_COLOR_MAKEFILE ON)
# Build mode
SET(CMAKE_BUILD_TYPE Debug) # Dev
#SET(CMAKE_BUILD_TYPE RelWithDebInfo) # Test
#SET(CMAKE_BUILD_TYPE Release) # Release
# Used features
SET(CMAKE_CXX_STANDARD 14) # -std=c++14
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
# Compiler flags
SET(CMAKE_CXX_FLAGS "-Wall -Wextra")
SET(CMAKE_CXX_FLAGS_DEBUG "-g3 -O0") # Dev
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3") # Test
SET(CMAKE_CXX_FLAGS_RELEASE "-O3") # Release
# Libraries
ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
# Executables
ADD_SUBDIRECTORY("${PROJECTSTRUCTURE_CLIENTS_DIR}")
我正在使用以下命令使用源代码外构建:
cd build
cmake .. -G "MSYS Makefiles"
然后 运行 使用:
make
注意:真实项目还包含文档目录和其他一些东西。
还有 .gitignore
和 .travis.yml
之类的文件(但这是我必须开始工作的下一件事)。
问题:
cmake
命令有效,但 make
命令告诉我包含的文件 (Core.h
) 可以
找不到。
我认为问题出在安装库的部分。但我无法找到
正确的方法。我在这里发布的解决方案只是我尝试过的众多解决方案中的一个。
其他问题:
1. 标有 A 的 CMakeLists 是空的。他们刚刚添加的地方,以便每个目录 有一个 CMakeLists 文件。我应该删除它们吗?
2. 我想在我的项目中使用 google-test/mock 对每个项目进行测试
project/test
文件夹。我足以在顶层 CMakeLists 中包含 google 测试来完成这个
工作还是我必须将它包含在每个子项目中?
3. 列出源文件或自动加载它们是好的做法吗?我觉得上市
即使工作更多,它们也会更好。我认为这在重新加载时对 cmake
也有好处
该项目。测试也是如此吗?我正在考虑为每个来源制作一个测试文件
文件。
这似乎不是安装部分的问题。我认为您添加包含目录的方式有问题。 :)
当你使用 INCLUDE_DIRECTORIES 时,你说 cmake 应该为这个 CMakeLists 中的文件的编译器添加适当的标志。但不在父 CMakeLists 中添加的文件中。我认为堆栈是这种情况的一个很好的类比。 (https://cmake.org/cmake/help/v3.5/command/include_directories.html)
请注意,您在 ./CMakeLists.txt
中添加了 ./Core/CMakeLists.txt
:ADD_SUBDIRECTORY("${CMAKE_SOURCE_DIR}/core")
,稍后添加客户端子目录时,./Core/include
不再使用。
恕我直言,最优雅的解决方案是使用
TARGET_INCLUDE_DIRECTORIES(Core PUBLIC pathToCoresHeaders)
代替。如果您决定使用它,TARGET_LINK_LIBRARIES("${PROJECT_NAME}" "Core")
行将为桌面可执行文件添加正确的包含路径。
AD1。是的,我认为你应该删除它们。您可以将 CMakeLists.txt 保留在 test
的目录中,因为 UT 通常需要多一个目标。
AD2。我建议在您开始定义自己的目标之前将它添加到顶级目录中,并且 link 您的测试执行程序使用 gtest
和 gtest_main
,这应该注册 gtest 的包含路径。
AD3。我在 cmake 中列出了我所有的文件。我宁愿在构建结束时看到有关丢失文件的错误,也不愿看到未解析的外部符号。但它不是非黑即白的 (Specify source files globally with GLOB?)。你应该自己做决定并承担后果。
PS1。我建议在一些类似 unix 的系统上额外测试你的构建,因为 Windows 对大小写不敏感太自由了。
我会做一些更改来改进您的构建系统。
./Core/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
PROJECT(Core CXX)
SET(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include)
SET(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
SET(LIB_HEADERS
${INCLUDE_DIRS}/Core/Core.h
)
SET(LIB_SOURCES
${SOURCE_DIR}/Core.cpp
)
# Make library
ADD_LIBRARY("${PROJECT_NAME}" STATIC ${LIB_SOURCES} ${LIB_HEADERS})
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME}
PUBLIC ${INCLUDE_DIRS}
)
SET_TARGET_PROPERTIES("${PROJECT_NAME}" PROPERTIES
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}"
)
INSTALL(TARGETS "${PROJECT_NAME}"
EXPORT "${PROJECT_NAME}Targets"
ARCHIVE DESTINATION lib COMPONENT libs
RUNTIME DESTINATION bin COMPONENT libs
LIBRARY DESTINATION lib COMPONENT libs
PUBLIC_HEADER DESTINATION include/${PROJECT_NAME} COMPONENT devel
INCLUDES DESTINATION include
)
ADD_SUBDIRECTORY(test)
./clients/Desktop/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project("Desktop" CXX)
SET(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
SET(INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
SET(APP_HEADERS
)
SET(APP_SOURCES
${SOURCE_DIR}/main.cpp
)
# Make executable
ADD_EXECUTABLE(${PROJECT_NAME} ${APP_SOURCES} ${APP_HEADERS})
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} PRIVATE ${INCLUDE_DIR})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} Core)
add_subdirectory(test)