作为一个库的作者,我需要提供什么配置才能让消费者轻松地安装库.

CMakeLists.txt

cmake_minimum_required(VERSION 3.26)
project(mylib C)

set(CMAKE_C_STANDARD 11)

add_library(mylib src/foo.c src/bar.c)
target_compile_features(mylib PRIVATE c_std_11)

target_include_directories(mylib PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

# Config
configure_package_config_file(build/config.cmake
        ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake # cmake-build-debug/
        INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME} NO_SET_AND_CHECK_MACRO) # share/

# Version
write_basic_package_version_file(
        ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
        VERSION 1.0.0
        COMPATIBILITY SameMajorVersion)

# Install Config & Version
install(FILES
        ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake # cmake-build-debug/
        ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake # cmake_build-debug/
        DESTINATION
        ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}) # share/

# Create export set to enable import in other CMake Projects
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets # create export set
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # lib/
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # lib/
        INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # include/
)
# Install Export Set
install(EXPORT ${PROJECT_NAME}-targets
        NAMESPACE mylib::
        DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME})

# Install Headers
install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}) # include/

我的config.cmake

@PACKAGE_INIT@

include(${CMAKE_CURRENT_LIST_DIR}/mylib-targets.cmake)

check_required_components(mylib)

请查看并建议需要更改配置或CMakeLists文件的内容,以获得无缝的消费者体验.

Edit Consumer

cmake_minimum_required(VERSION 3.26)
project(consumer C)

set(CMAKE_C_STANDARD 11)

add_executable(consumer main.c)

find_package(mylib CONFIG REQUIRED)
target_link_libraries(consumer PRIVATE mylib::mylib)

Directory structure

mylib/
|-- CMakeLists.txt (top-level)
|-- src/
|   |-- CMakeLists.txt
|   |-- foo.c
|   |-- bar.c
|-- example/
|   |-- CMakeLists.txt
|   |-- example1.c
|   |-- example2.c

Example/CMakeLists.txt

add_executable(example1 example1.c)
target_link_libraries(example1 PRIVATE mylib)
add_test(NAME TestExample1 COMMAND example1)

add_executable(example2 example2.c)
target_link_libraries(example2 PRIVATE mylib)
add_test(NAME TestExample2 COMMAND example2)

推荐答案

看来你已经做得很好了.它保证是干净的和x平台的.

有一件事你还没有按照Daniel Pfeifer's awesome presentation来做:

在命名空间foo::中导出foo时, 还要创建别名foo::foo.

ADD_LIBRARY(foo::foo别名foo)

这样,当您和您的消费者想要直接从源代码使用您的库时,他们仍然可以使用规范形式的名称空间:

find_package(mylib REQUIRED)
target_link_library(... PRIVATE mylib::mylib)

如果它们覆盖上面pdf中的第34页之类的find_package个API,则如下所示:

### NOTE!!! Hand written && NOT tested
set(as_subproj mylib)

macro(find_package)
    if(NOT "${ARG0}" IN_LIST as_subproj)
        _find_package(${ARGV})
    else()
        add_subdirectory(${ARG0})
    endif()
endmacro()

C++相关问答推荐

Bison解析器转移/减少冲突

C strlen on char array

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

GCC:try 使用—WError或—pedantic using pragmas

我编译了一个新的c程序,并收到以下错误

在编译时参数化类型定义

在C++中通过空指针隐式访问常量变量的值

进程已完成,退出代码为138 Clion

GDB输出ARM助记符

为什么双精度d=flt_max+flt_max;在c语言中得到inf的结果

强制转换变量以在 struct 中蚕食

我在反转双向链表时遇到问题

使用ld将目标文件链接到C标准库

Valgrind正在使用一个Fexecve电话报告不可能发生的事情

区分MySQL C界面中的文本和BLOB字段

Matlab/Octave对conv2函数使用哪种方法?

在列表中查找素数

malloc:损坏的顶部大小无法找出问题

窗口消息处理函数以某种方式更改了应保持不变的 int 变量的值

我们可以在不违反标准的情况下向标准函数声明添加属性吗?