C++ 如何使cmake在子文件夹中查找共享库

C++ 如何使cmake在子文件夹中查找共享库,c++,cmake,shared-libraries,C++,Cmake,Shared Libraries,我正在努力学习如何创建共享库。下面的方法似乎有效(如果你对这种方法有一些反馈,请发表评论,我基本上不知道我在做什么) 在我的库项目中,我将头文件放在名为“include”的文件夹中,将源文件放在“src”中 我的库的CMakeLists.txt: cmake_minimum_required(VERSION 2.4.0) project(mycustomlib) # Find source files file(GLOB SOURCES src/*.cpp) # Include heade

我正在努力学习如何创建共享库。下面的方法似乎有效(如果你对这种方法有一些反馈,请发表评论,我基本上不知道我在做什么)

在我的库项目中,我将头文件放在名为“include”的文件夹中,将源文件放在“src”中

我的库的CMakeLists.txt:

cmake_minimum_required(VERSION 2.4.0)

project(mycustomlib)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Include header files
include_directories(include)

# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})

# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib)

# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include)
cmake_minimum_required(VERSION 2.4.0)

project(myprogram)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})

# Find and link library
find_library(MYCUSTOMLIB mycustomlib)
target_link_libraries(${PROJECT_NAME} ${MYCUSTOMLIB})
cmake_minimum_required(VERSION 2.4.0)

project(mycustomlib)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Include header files
include_directories(include)

# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})

# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})

# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
cmake_minimum_required(VERSION 2.4.0)

project(myprogram)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})

# Find and link library
find_library(MYCUSTOMLIB mycustomlib/mycustomlib)
target_link_libraries(${PROJECT_NAME} ${MYCUSTOMLIB})
我的应用程序的CMakeLists.txt:

cmake_minimum_required(VERSION 2.4.0)

project(mycustomlib)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Include header files
include_directories(include)

# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})

# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib)

# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include)
cmake_minimum_required(VERSION 2.4.0)

project(myprogram)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})

# Find and link library
find_library(MYCUSTOMLIB mycustomlib)
target_link_libraries(${PROJECT_NAME} ${MYCUSTOMLIB})
cmake_minimum_required(VERSION 2.4.0)

project(mycustomlib)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Include header files
include_directories(include)

# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})

# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})

# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
cmake_minimum_required(VERSION 2.4.0)

project(myprogram)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})

# Find and link library
find_library(MYCUSTOMLIB mycustomlib/mycustomlib)
target_link_libraries(${PROJECT_NAME} ${MYCUSTOMLIB})
这是在工作。问题是,我想将标题和库都放入子文件夹(具体来说:
/usr/local/include/mycustomlib/
用于标题,而
/usr/local/lib/mycustomlib/
用于库)

这就是我的尝试:

我的库的新CMakeLists.txt:

cmake_minimum_required(VERSION 2.4.0)

project(mycustomlib)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Include header files
include_directories(include)

# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})

# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib)

# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include)
cmake_minimum_required(VERSION 2.4.0)

project(myprogram)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})

# Find and link library
find_library(MYCUSTOMLIB mycustomlib)
target_link_libraries(${PROJECT_NAME} ${MYCUSTOMLIB})
cmake_minimum_required(VERSION 2.4.0)

project(mycustomlib)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Include header files
include_directories(include)

# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})

# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})

# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
cmake_minimum_required(VERSION 2.4.0)

project(myprogram)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})

# Find and link library
find_library(MYCUSTOMLIB mycustomlib/mycustomlib)
target_link_libraries(${PROJECT_NAME} ${MYCUSTOMLIB})
我的应用程序的新CMakeLists.txt:

cmake_minimum_required(VERSION 2.4.0)

project(mycustomlib)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Include header files
include_directories(include)

# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})

# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib)

# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include)
cmake_minimum_required(VERSION 2.4.0)

project(myprogram)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})

# Find and link library
find_library(MYCUSTOMLIB mycustomlib)
target_link_libraries(${PROJECT_NAME} ${MYCUSTOMLIB})
cmake_minimum_required(VERSION 2.4.0)

project(mycustomlib)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Include header files
include_directories(include)

# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})

# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})

# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
cmake_minimum_required(VERSION 2.4.0)

project(myprogram)

# Find source files
file(GLOB SOURCES src/*.cpp)

# Create executable
add_executable(${PROJECT_NAME} ${SOURCES})

# Find and link library
find_library(MYCUSTOMLIB mycustomlib/mycustomlib)
target_link_libraries(${PROJECT_NAME} ${MYCUSTOMLIB})
这是不起作用的。现在,我被迫指定库的.so文件,如下所示:

find_库(MYCUSTOMLIB-MYCUSTOMLIB/libmycustomlib.so)


怎么会呢?

我会先处理您的实际问题,然后再提供其他意见。从技术上讲,您要求CMake查找一个名为
mycustomlib/mycustomlib
的库,但您真正想说的是您想要查找
mycustomlib
,它可以在名为
mycustomlib
的子目录中找到。在第二种情况下,调用
find_library()
以实现此目的的两种替代方法是:

find_library(MYCUSTOMLIB mycustomlib PATH_SUFFIXES mycustomlib)
find_library(MYCUSTOMLIB mycustomlib PATHS /usr/local/lib/mycustomlib)
target_include_directories(${PROJECT_NAME} PUBLIC include)
后者对库的安装位置做了更多的假设,因此我倾向于第一种选择。第一个选项假设CMake已经在/usr/local/lib中找到了库,这似乎是您的问题。通过修改和,可以影响CMake查找库的位置。我希望上述任何一种选择都能让你的第二个案例奏效

现在来看其他观察结果。您已经在每个
CMakeLists.txt
文件的第一行请求了一个非常旧的最低CMake版本。你可能想至少考虑一下这个2.8(个人建议,我更喜欢3.2或更晚,但是这取决于你的项目需要支持什么)。 您已经使用文件全局绑定来获取源和头的列表。这是不可靠的,通常应该避免(参见对此的讨论)。为了简单起见,您将看到许多示例代码使用此方法,但不建议将其用于实际项目(甚至包括CMake文档)。如果需要健壮的构建,请分别明确列出源文件和头文件

如果您愿意要求CMake 2.8.11或更高版本(现在应该是这样),而不是调用
include_directories()
,这会使所有内容都选择您指定的标题搜索路径,您应该更愿意将搜索路径要求附加到需要它的目标。你和我一起做这件事。上述代码的等效代码为:

find_library(MYCUSTOMLIB mycustomlib PATH_SUFFIXES mycustomlib)
find_library(MYCUSTOMLIB mycustomlib PATHS /usr/local/lib/mycustomlib)
target_include_directories(${PROJECT_NAME} PUBLIC include)
随着项目规模和复杂性的增加,这可以更好地控制目标间的依赖关系。关于这个话题的更深入的讨论,请参阅,也许也可以(披露:我写了这两篇文章)

您的库和程序是否完全独立于源代码存储库?它们可以在同一个项目中建造吗?您可以在一个
CMakeLists.txt
文件中构建多个目标。项目名称不必与任何目标的名称有任何关系(在简单的示例中,您经常会看到
project\u name
变量重复用于目标名称,这是不幸的,因为它表明两者之间存在关系,但对于除简单项目外的所有项目,情况并非如此)。如果它们在同一个存储库中,那么将它们构建在一起将是一个简单得多的构建,因为您不必安装库来查找并链接可执行文件

如果它们必须在单独的项目中构建,那么应用程序项目的以下内容应该可以帮助您实现:

cmake_minimum_required(VERSION 2.8.11)
project(myprogram)

# List your program's sources here explicitly
add_executable(myprogram src/foo.cpp src/bar.cpp)

# Find and link library
find_library(MYCUSTOMLIB mycustomlib PATH_SUFFIXES mycustomlib)
target_link_libraries(myprogram PUBLIC ${MYCUSTOMLIB})

# Find library's headers and add it as a search path.
# Provide the name of one header file you know should
# be present in mycustomlib's include dir.
find_path(MCL_HEADER_PATH mycustomlib.h PATH_SUFFIXES mycustomlib)
target_include_directories(myprogram PUBLIC ${MCL_HEADER_PATH})
对于额外的点,您可以通过检查公共路径前缀来确认头路径与库位于同一区域,或者您可以直接派生 通过假定目录结构,从MYCUSTOMLIB路径获取MCL_头_路径。这两种方法都有优点和缺点。如果您想探索后者,命令将是您的朋友


希望这能为您指明正确的方向。

谢谢!如何包含标题子目录?这就是
target\u include\u directories()
的作用。在上面,我展示了在构建
${PROJECT\u NAME}
目标时如何将
include
目录添加到头搜索路径。如果您要添加的目录被指定为相对路径,那么CMake文档实际上不会说明它们与构建相关的内容(它们只提到它们与安装相关的内容)。您可能需要进行实验,以了解行为是什么。如果您没有获得预期的行为,请尝试
${CMAKE\u CURRENT\u SOURCE\u DIR}/include
,而不仅仅是
include
。好的,我猜该命令是针对我的库的CMakeLists.txt的。但我仍然不明白如何在我的应用程序的CMakeLists.txt.Answer中指定库头子目录,更新后的答案演示了一种将库头目录添加到程序头搜索路径的方法。太棒了,谢谢!但愿我能投超过1票。