【问题标题】:CMake target_include_directories relative to parent directory? [duplicate]CMake target_include_directories 相对于父目录? [复制]
【发布时间】:2021-09-27 19:14:12
【问题描述】:

如何将lib0 路径添加到lib1,以便从header1.h 可以#include <header0.h>

|   CMakeLists.txt
+---lib0
|       CMakeLists.txt
|       header0.c
|       header0.h
+---lib1
|       CMakeLists.txt
|       header1.c
|       header1.h
\---main
        CMakeLists.txt
        main.c

CMakeLists.txt

cmake_minimum_required(VERSION 3.19)
project(c_multilib C)

foreach (sub "lib0" "lib1" "main")
    add_subdirectory("${sub}")
endforeach ()

lib0/CMakeLists.txt

add_library(lib0 "header0.h" "header0.c")

set_target_properties(lib0 PROPERTIES LINKER_LANGUAGE C)

include(GenerateExportHeader)
set(_generated_export_header "${CMAKE_CURRENT_SOURCE_DIR}/lib0_export.h")
generate_export_header(lib0 EXPORT_FILE_NAME "${_generated_export_header}")

target_include_directories(lib0
        INTERFACE
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
        "$<INSTALL_INTERFACE:include>"
)

install(FILES "header0.h" "${_generated_export_header}" DESTINATION "include")

lib0/header0.h

#ifndef C_MULTILIB_HEADER0_H
#define C_MULTILIB_HEADER0_H

#include "lib0_export.h"

int LIB0_EXPORT sum(int, int);

#endif /* C_MULTILIB_HEADER0_H */

lib0/header0.c

#include "header0.h"

int sum(int a, int b) {return a+b;}

lib1/CMakeLists.txt

add_library(lib1 "header1.h" "header1.c")

set_target_properties(lib1 PROPERTIES LINKER_LANGUAGE C)

include(GenerateExportHeader)
set(_generated_export_header "${CMAKE_CURRENT_SOURCE_DIR}/lib1_export.h")
generate_export_header(lib1 EXPORT_FILE_NAME "${_generated_export_header}")

target_include_directories(lib1
        INTERFACE
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
        "$<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}/lib0>"
        "$<INSTALL_INTERFACE:include>"
)

install(FILES "header1.h" "${_generated_export_header}" DESTINATION "include")

lib1/header1.h

#ifndef C_MULTILIB_HEADER1_H
#define C_MULTILIB_HEADER1_H

#include <header0.h>
#include "lib1_export.h"

int LIB1_EXPORT add1(int);

#endif /* C_MULTILIB_HEADER1_H */

lib1/header1.c

#include <header1.h>

int add1(int a) {return sum(a, 1);}

main/CMakeLists.txt

add_executable("main" "main.c")

target_link_libraries("main" "lib0" "lib1")
target_include_directories(
        "main"
        INTERFACE
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
        "$<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}/lib0>"
        "$<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}/lib1>"
        "$<INSTALL_INTERFACE:include>"
)

main/main.c

#include <header0.h>
#include <header1.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    printf("sum(1,5) =\t%d\n"
                   "add1(5) =\t%d\n", sum(1,5), add1(6));
    return EXIT_SUCCESS;
}

尝试:

# lib1/CMakeLists.txt

target_include_directories(
    lib1
    INTERFACE
    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
    #"$<BUILD_INTERFACE:lib0>"
    #"$<BUILD_INTERFACE:../../lib0>"
    #"$<BUILD_INTERFACE:${${PROJECT_NAME}_SOURCE_DIR}/src/lib0>"
    "$<INSTALL_INTERFACE:include>"
)

install(FILES "header1.h" DESTINATION "include")

错误范围:

致命错误 C1083:无法打开包含文件:'header0.h':没有这样的文件或目录

到:

目标在其 INTERFACE_INCLUDE_DIRECTORIES 中包含相对路径

还给get_target_property(LIB0_INCLUDES "lib0" INCLUDE_DIRECTORIES)

使用不存在的目标“lib0”调用get_target_property()。

【问题讨论】:

  • 您没有提供足够的信息来说明问题所在。请根据 Stack Overflow 指南提供minimal reproducible example。具体来说,请显示 lib1/CMakeLists.txt 文件的其余部分,以及其他 CMake 文件的内容,以便为您如何设置目标 lib0 和 lib1 以及它们的设置顺序提供上下文...
  • @squareskittles 好的,我添加了一个完整的示例。这有点冗长:(
  • 谢谢,还请提供您收到的所提供代码的完整错误,包括周围的日志和编译消息,以便为构建链中发生此错误的where提供上下文.
  • 实际上并不清楚您希望通过您的代码实现什么。例如。假设header0.c includes 标头header0.h,带有该标头的目录应该使用 PRIVATE 或 PUBLIC 关键字添加,但不能使用 INTERFACE 关键字。 (您知道 CMake 中关键字 PUBLIC/PRIVATE/INTERFACE 的含义吗?)。在给定的假设下,lib0 的代码完全是错误的,您需要在编写使用 lib0lib1 的代码之前修复它。
  • 不确定为什么要在可执行文件中使用INTERFACE 包含目录;您不能将可执行文件链接到另一个目标,并且INTERFACE... 属性的全部要点将通过链接目标来使用。这就是为什么我的约定是在设置可执行文件的属性时简单地使用PRIVATE 可见性;这也意味着您无需费心使用生成器表达式来区分构建/安装界面;您只是不为可执行文件提供任何标头; all 已经是你的二进制文件的一部分了。

标签: cmake target cmake-language


【解决方案1】:

src/lib0/CMakeLists.txt 应该是这样的

add_library(lib0 INTERFACE)
target_include_directories(lib0 INTERFACE ${CMAKE_CURRENT_LIST_DIR})

INTERFACE 这个词告诉 Cmake 没有要编译的东西。

src/lib1/CMakeLists.txt 应该是这样的

add_library(lib1 INTERFACE)
target_include_directories(lib1 INTERFACE ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(lib1 INTERFACE lib0)

src/CMakeLists.txt 应该类似于

add_subdirectory(lib0)
add_subdirectory(lib1)
# Assuming that your src target is called my_proj: 
target_link_libraries(my_proj PRIVATE lib0 lib1)

编辑:

如果您将所有包含从 lib1_export... 更改为 header1 并修改以下 3 个 CMakeLists.txt 文件,我可以确认您提供的代码可以编译:

lib0/CMakeLists.txt:

add_library(lib0 header0.c)
target_include_directories(lib0 PUBLIC ${CMAKE_CURRENT_LIST_DIR})

lib1/CMakeLists.txt:

add_library(lib1 header1.c)
target_include_directories(lib1 PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(lib1 PUBLIC lib0)

main/CMakeLists.txt:

add_executable(main main.c)
target_link_libraries(main PRIVATE lib0 lib1)

我不清楚你想用生成器表达式(尖括号)实现什么。如果您解释了您要完成的工作,那么我们可以建议适当的修复。

【讨论】:

  • 我已经更新了问题。但最初的问题显示了相同的解决方案。这个建议的解决方案不起作用,因为我已经这样做了。它不适用于尖括号。
  • 所以你想要生成器表达式(尖括号)?或者你只是插入它来试图让它编译?
  • 为什么要创建lib0 作为 INTERFACE 库?源文件header0.c 绝对是该库的一部分,因此该库不是只有标题的库,正如 INTERFACE 关键字所暗示的那样。
  • 删除所有INTERFACE 行并像你说的那样替换它给我留下c-multilib\main\main.c(1): fatal error C1083: Cannot open include file: 'header0.h': No such file or directory
  • 实际上用细齿梳子梳理了一下,效果很好。我认为这是 add_library(lib1 "header1.c")add_library(lib1 "header1.c" "header1.h")
猜你喜欢
  • 1970-01-01
  • 2011-10-25
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 2021-04-17
  • 1970-01-01
  • 2014-12-02
相关资源
最近更新 更多