CMake - 带有示例子目录 运行 的库作为单独的项目

CMake - Library with example subdirectory running as separate project

编辑 2 - 已修复!

问题已通过正确使用 绝对路径 而不是相对路径,并将 add_subdirectory 添加到 example/CMakelists.txt.

来解决

我已经更新了提供的代码(并将离开存储库以防有人想将其用作起点。

编辑:

原文post:

我正在尝试编写一个库,其中包含示例项目,并且可以作为 Git 子模块添加。所需的结构是这样的:

- source
  - MyLib
    lib.cpp
  - CMakelists.txt
- include
  - MyLib
    lib.h
- example
  main.cpp
  CMakelists.txt
CMakelists.txt (main CMake for library)

我要达到什么目的:

我的问题是什么: 我最大的问题是将示例链接到同级文件夹中的库,并确保它可以编译。我设法以我的 IDE 正确理解 #include 语句的方式编写了 CMakelists.txt,但在编译期间找不到函数定义。 请问谁能指点一下吗?

准确的编译错误信息:

C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/10.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lMY_LIB
collect2.exe: error: ld returned 1 exit status
mingw32-make[3]: *** [CMakeFiles\MY_LIB_EXAMPLE.dir\build.make:95: MY_LIB_EXAMPLE.exe] Error 1
mingw32-make[2]: *** [CMakeFiles\Makefile2:82: CMakeFiles/MY_LIB_EXAMPLE.dir/all] Error 2
mingw32-make[1]: *** [CMakeFiles\Makefile2:89: CMakeFiles/MY_LIB_EXAMPLE.dir/rule] Error 2
mingw32-make: *** [Makefile:123: MY_LIB_EXAMPLE] Error 2

CMakelists.txt 个文件 CMakelists.txt:

cmake_minimum_required(VERSION 3.20)
set(CMAKE_CXX_STANDARD 20)
project(MY_LIB)
add_subdirectory(source)

source/CMakelists.txt

add_library(MY_LIB MyLib/library.cpp ../include/MyLib/library.h)

target_include_directories(MY_LIB PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/MyLib)
target_include_directories(MY_LIB PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/source/MyLib)

example/CMakelists.txt

cmake_minimum_required(VERSION 3.20)

set(CMAKE_CXX_STANDARD 20)

#--------------------------------------------------------------------
# Get solution root
#--------------------------------------------------------------------
cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH LIB_PATH)
cmake_path(SET LIB_INCLUDE_PATH "${LIB_PATH}/include")

message(${LIB_PATH})
message(${LIB_INCLUDE_PATH})

#--------------------------------------------------------------------
# Set project name
#--------------------------------------------------------------------
project(MY_LIB_EXAMPLE)

#--------------------------------------------------------------------
# Add source
#--------------------------------------------------------------------
add_executable(MY_LIB_EXAMPLE main.cpp)
add_subdirectory(${LIB_PATH} library-build)

#--------------------------------------------------------------------
# Link libraries
#--------------------------------------------------------------------
target_link_libraries(MY_LIB_EXAMPLE MY_LIB)

#--------------------------------------------------------------------
# Link include directories
#--------------------------------------------------------------------
target_include_directories(MY_LIB_EXAMPLE PUBLIC ${LIB_INCLUDE_PATH})

我用我的设置创建了一个示例存储库https://github.com/jiriKralovec/cmake-library

he example project should be capable of running on its own by loading the CMakelists.txt in the directory, and should be able to use the library

只需添加:

add_subdirectory(./../ some_unique_name_here)

我想我会删除 source/CMakelists.txt 并将其全部写入根目录 CMakelists.txt。使用 ../ 来引用包含目录很奇怪。


我建议做选项 and/or 单元测试:

root CMakeLists.txt:

include(CTest)
add_library(MY_LIB ....)

# one design
if (BUILD_TESTING)
   add_subdirectory(example)
endif()

# another design
add_subdirectory(utilities)

example/CMakeLists.txt:

# if it is something simple, add unit test:
add_executable(MY_LIB_EXAMPLE1 <maybe EXCLUDE_FROM_ALL?> ...)
add_test(NAME MY_LIB_EXAMPLE1 COMMAND MY_LIB_EXAMPLE1)

utilities/CMakeLists.txt:

# if it is a utility, optionally build it
add_executable(MY_LIB_UTILITY_TO_DO_SMTH ...)
option(... BUILD_MY_LIB_UTILITY_TO_DO_SMTH OFF)
if(NOT BUILD_MY_LIB_UTILITY_TO_DO_SMTH)
   set_target_properties(
       MY_LIB_UTILITY_TO_DO_SMTH
       PROPERTIES EXCLUDE_FROM_ALL ON
   )
endif()

不管怎样,做一个 CMake 构建。然后,如果用户想要构建该实用程序,他将执行 cmake --build <builddir> --target MY_LIB_UTILITY_TO_DO_SMTH(或 make MY_LIB_UTILITY_TO_DO_SMTH)。如果想要构建单元测试,你会做cmake ... -D BUILD_TESTING=1

有些人将所有单元测试可执行文件添加为 EXCLUDE_FROM_ALL 并制作特殊 add_custom_target(build_tests) add_target_dependencies(build_tests MY_LIB_EXAMPLE1 etc. etc.) 并在测试前构建该自定义目标。