我想创建一个简单的静态库,并从另一个项目链接到它。有三个源文件(都在同一目录中),可以从中创建库:main1.cpp
,header1.h
和header2.h
。 main1.cpp
包含行#include "header1.h"
,而header1.h
包含行#include "header2.h"
。要创建库,我在add_library(foo STATIC main1.cpp)
文件中使用CMakeLists.txt
。运行cmake
然后make
会按预期创建文件libfoo.a
。
然后我有另一个项目,文件main2.cpp
,其中包含行#include "header1.h"
。在此项目的CMakeLists.txt
文件中,我使用add_executable(bar main2.cpp)
和target_link_libraries(bar foo.a)
创建一个链接到我的静态库的可执行文件。然后我复制foo.a
和header1.h
文件并将它们放在与该项目相同的目录中。
问题是,在编译第二个项目期间,我收到以下错误:
header1.h: fatal error: header2.h: No such file or directory
因此它告诉我header2.h
无法找到,即使它在header1.h
中被引用。但是,我认为foo.a
的内容在构建库时会包含header2.h
的所有内容?当我想构建第二个项目时,我不应该在第一个项目中包含所有头文件吗?
谢谢:)
答案 0 :(得分:4)
简短回答:您将需要所有显示您希望库导出的功能的头文件。换句话说,如果头文件包含仅在库中使用的函数,则不需要公开这些头文件,除非您公开的某些头文件包含该头文件。
库中包含的内容与头文件的内容之间似乎存在一些脱节。为简单起见,我们将头文件的目的限制为具有函数原型(稍后将删除此简化)。头文件的目的是告诉你的新代码(不是库的一部分)函数的样子,如名称,参数和返回类型。当您编译新应用程序时,如果它没有此信息,它将不知道如何处理诸如如何传递参数以及如何处理返回值之类的事情。注意我没有包含头文件说明函数的功能,如函数的机器代码。这是库包含的内容。您需要这两个部分才能正确编译应用程序。
这可以扩展到您在头文件中找到的其他内容,例如结构。关键的想法是您的应用程序仍然需要一些信息,如函数原型和结构定义。
此外,您还需要记住#include
的作用。在其最简单的形式中,它只是抓取指定文件的内容。因此,如果一个头文件包含另一个头文件,则也会抓取第二个头文件的内容。
请注意,无论是静态库还是共享库,这都适用。
下一部分可能不是您想要做的,但它是未来访问者的信息,您自己可能会觉得有用:
现在让我们说header1.h
包含您希望公开的功能,而header2.h
只包含您希望内部的功能。然后,不要让header1.h
包含header2.h
,而应将它们分别包含在源文件中,将它们包装在您可以包含的另一个头文件中,或者header2.h
包括header1.h
依赖关系允许这样做。这样,您只需为您的图书馆用户发送header1.h
。这并不是说它们不能使用header2.h
中的函数,因为它们仍然会被库公开,因为头文件不能控制它,但它会使它们使用起来稍微困难一些。如果你想真正阻止图书馆用户使用你不打算公开的功能,请查看这个SO question。