我的情况
我正在尝试使用cmake
设置项目结构和构建脚本,但出现错误
我的应用程序找不到我尝试包含的头文件。
我希望有人可以指导我解决这个问题。
当前的项目
该项目只是一个示例,简化为一个应用程序和一个库项目。目标是
有多个客户端和一个以上的库(某些依赖于彼此)。clients/Desktop
例如是使用core/
库的应用程序。
该图显示了项目结构(Visual Studio Code Explorer的屏幕截图)
在include文件夹中有一个类似于项目的文件夹,用于更改Core.h
中的includes
到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
文件夹。我足以在顶级CMakeList中包含google test来做到这一点工作还是我必须将其包含在每个子项目中?
3.列出源文件或自动加载它们是一种好习惯吗?我认为清单
即使需要更多工作,它们也会更好。我认为这在重新加载时对于
cmake
也具有优势该项目。测试也是如此吗?我正在考虑为每个来源制作一个测试文件
文件。
最佳答案
这似乎不是安装部分的问题。我认为添加包含目录的方式存在问题。 :)
当您使用INCLUDE_DIRECTORIES时,您说cmake应该为此CMakeLists中的文件的编译器添加适当的标志。但是不在父CMakeList中添加的文件中。我认为堆栈是这种情况的一个很好的类比。 (https://cmake.org/cmake/help/v3.5/command/include_directories.html)
请注意,您在./Core/CMakeLists.txt
:./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。我建议您在开始定义自己的目标之前,将其添加到顶级目录中,并将测试执行程序与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)
关于c++ - 多项目CMake不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36816839/