如何使用 CMake 仅使某些文件可包含在 c 库中?
How can I make only some files includable in c library using CMake?
如果我的库结构是
main.c
CMakeLists.txt
---- lib
---- CMakeLists.txt
-------- include
------------ Node.h
------------ LinkedList.h
------------ Queue.h
-------- src
------------ Node.c
------------ LinkedList.c
------------ Queue.c
我在 lib
文件夹中的 CMakeLists.txt
中的 add_library
代码是
add_library(
lists
lists/src/Node.c
lists/src/LinkedList.c
lists/src/Queue.c
)
target_include_directories(lists PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include}")
我希望能够仅包含 Queue.h
外部库,但 Node.h
& LinkedList.h
仅包含库内。我该如何存档?我尝试的一种方法是将 Node.h
和 LinkedList.h
放在 src 文件夹中,然后将这两个添加到 add_library
中,如下所示
add_library(
lists
lists/src/Node.h
lists/src/Node.c
lists/src/LinkedList.h
lists/src/LinkedList.c
lists/src/Queue.c
)
target_include_directories(lists PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include}")
但是我无法在 Queue.h
中导入 LinkedList.h
。达到此访问级别的理想方式是什么?
如果 Queue.h
包括 LinkedList.h
,包括 Queue.h
在内的所有翻译单元都需要访问 LinkedList.h
,否则它们将无法编译。 (忽略这里的预处理器恶作剧。)如果你不能摆脱包含你就不能实现你的目标。
根据 LinkedList.h
内容的用途,您可以删除包含:
- 如果您仅使用对
LinkedList.h
中定义的类型的引用或指针,您可以将这些类型的前向声明添加到 LinkedList.h
- 如果您当前以引用或指针以外的方式使用
LinkedList.h
中的类型,pimpl idiom 可能会让您摆脱这种用法。
如果这不是一个选项,您可以将那些 header“隐藏”在子目录中,其名称表明 header 不打算直接包含。我已经看到 private
和 impl
被使用了。
示例:
include
--- lists
------ Queue.h
------ private
---------- LinkedList.h
---------- Node.h
Queue.h
...
#include "private/LinkedList.h"
...
使用您的库时,应该很容易确定是否应该包含 header:
#include <lists/Queue.h> // inclusion probably expected
#include <lists/private/Node.h> // probably you're not supposed to include this directly
如果您希望能够通过较短的路径 (#include <LinkedList.h>
) 在库的实现中引用 header,您可以将 include/lists/private
添加为私有包含使缩短的包含路径仅适用于库实现的翻译单元的目录:
target_include_directories(lists
PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
PRIVATE
include/lists/private
)
如果我的库结构是
main.c
CMakeLists.txt
---- lib
---- CMakeLists.txt
-------- include
------------ Node.h
------------ LinkedList.h
------------ Queue.h
-------- src
------------ Node.c
------------ LinkedList.c
------------ Queue.c
我在 lib
文件夹中的 CMakeLists.txt
中的 add_library
代码是
add_library(
lists
lists/src/Node.c
lists/src/LinkedList.c
lists/src/Queue.c
)
target_include_directories(lists PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include}")
我希望能够仅包含 Queue.h
外部库,但 Node.h
& LinkedList.h
仅包含库内。我该如何存档?我尝试的一种方法是将 Node.h
和 LinkedList.h
放在 src 文件夹中,然后将这两个添加到 add_library
中,如下所示
add_library(
lists
lists/src/Node.h
lists/src/Node.c
lists/src/LinkedList.h
lists/src/LinkedList.c
lists/src/Queue.c
)
target_include_directories(lists PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include}")
但是我无法在 Queue.h
中导入 LinkedList.h
。达到此访问级别的理想方式是什么?
如果 Queue.h
包括 LinkedList.h
,包括 Queue.h
在内的所有翻译单元都需要访问 LinkedList.h
,否则它们将无法编译。 (忽略这里的预处理器恶作剧。)如果你不能摆脱包含你就不能实现你的目标。
根据 LinkedList.h
内容的用途,您可以删除包含:
- 如果您仅使用对
LinkedList.h
中定义的类型的引用或指针,您可以将这些类型的前向声明添加到LinkedList.h
- 如果您当前以引用或指针以外的方式使用
LinkedList.h
中的类型,pimpl idiom 可能会让您摆脱这种用法。
如果这不是一个选项,您可以将那些 header“隐藏”在子目录中,其名称表明 header 不打算直接包含。我已经看到 private
和 impl
被使用了。
示例:
include
--- lists
------ Queue.h
------ private
---------- LinkedList.h
---------- Node.h
Queue.h
...
#include "private/LinkedList.h"
...
使用您的库时,应该很容易确定是否应该包含 header:
#include <lists/Queue.h> // inclusion probably expected
#include <lists/private/Node.h> // probably you're not supposed to include this directly
如果您希望能够通过较短的路径 (#include <LinkedList.h>
) 在库的实现中引用 header,您可以将 include/lists/private
添加为私有包含使缩短的包含路径仅适用于库实现的翻译单元的目录:
target_include_directories(lists
PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/include"
PRIVATE
include/lists/private
)