C语言 包含静态库中的头文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27660713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Including header file from static library
提问by Ethan McTague
I am making a test setup of a C static library and program. The library code, located in a subdirectory 'foo' of my project, contains the following files:
我正在对 C 静态库和程序进行测试设置。库代码位于我的项目的子目录 'foo' 中,包含以下文件:
foo/foo.c:
foo/foo.c:
#include <stdio.h>
void foo(void) {
printf("something");
}
foo/foo.h:
foo/foo.h:
#ifndef foo_h__
#define foo_h__
extern void foo(void);
#endif
My progam code is as follows:
我的程序代码如下:
test.c:
测试.c:
#include "foo.h"
int main() {
foo();
return 0;
}
I have a build script, called 'build', which contains the following:
我有一个名为“build”的构建脚本,其中包含以下内容:
build:
建造:
#!/bin/bash
gcc -c -Wall -Werror foo/foo.c
ar rcs libfoo.a foo.o
gcc -static -o test test.c libfoo.a # I have also tried -L. -lfoo
But when I run build, it gives me the following error:
但是当我运行构建时,它给了我以下错误:
test.c:1:17: fatal error: foo.h: No such file or directory
#include "foo.h"
^
Compilation terminated
It does, however, work when I omit the #include line, but I would prefer if I could use header files in my static libraries. What am I doing wrong, and how can I fix it?
但是,当我省略 #include 行时,它确实可以工作,但我更愿意在我的静态库中使用头文件。我做错了什么,我该如何解决?
回答by Jonathan Leffler
Headers are not stored in libraries. Headers are stored separately from libraries. Libraries contain object files; headers are not object files. By default, standard headers on a Unix system are stored in /usr/include— you'll normally find /usr/include/stdio.hand /usr/include/string.hand /usr/include/stdlib.h, for example. By default, libraries are stored in /usr/lib(but you may also find some in /lib). Often, compilers are configured to look in some other places too. One common alternative location is under /usr/local, so /usr/local/includefor headers and /usr/local/libfor libraries. Note, too, that a single library may have many headers defining the services. The default library is an example. It has the functions corresponding to those found in <stdio.h>, <string.h>, <stdlib.h>and many other headers too.
标头不存储在库中。标头与库分开存储。库包含目标文件;头文件不是目标文件。默认情况下,Unix 系统上的标准头文件存储在/usr/include-例如,您通常会找到/usr/include/stdio.hand/usr/include/string.h和/usr/include/stdlib.h。默认情况下,库存储在/usr/lib(但您也可以在 中找到一些/lib)。通常,编译器也被配置为查看其他一些地方。一个常见的替代位置是在 下/usr/local,因此/usr/local/include对于标题和/usr/local/lib库。还要注意,单个库可能有许多定义服务的头文件。默认库就是一个例子。它有着与那些中发现的功能<stdio.h>,<string.h>,<stdlib.h>和许多其他头了。
Looking at your code:
查看您的代码:
If your header file is in
./foo/foo.h, then you need to write:#include "foo/foo.h"Or if you continue to use
#include "foo.h", you need to specify where to find the header on the compiler command line with the argument:gcc -Ifoo -o test test.c -L. -lfooI deliberately excluded the
-static; it's only necessary when there's a choice between a static and a shared library, but you only havelibfoo.a, so the linker will use that anyway.Note that the problem is a compilation error, not a linking error. This would be clearer if you split the program building into two steps: (1) create
test.oand (2) link program:gcc -c -Ifoo test.c gcc -o test test.o -L. -lfooYour header guard is faulty. You originally had (but have updated the question so this typo is no longer present):
#ifndef foo_h__ #define foo_h_You need:
#ifndef foo_h__ #define foo_h__The macro names must be the same in both lines. Note that in this case, the misspelling is mostly harmless — but on Mac OS X,
clang(masquerading asgcc) did give a warning about it (though I'd spotted it before I did any compilation). In some other cases, you wouldn't get the protection that the header guards are designed to provide../foo/foo.h:1:9: warning: 'foo_h__' is used as a header guard here, followed by #define of a different macro [-Wheader-guard] #ifndef foo_h__ ^~~~~~~ ./foo/foo.h:2:9: note: 'foo_h_' is defined here; did you mean 'foo_h__'? #define foo_h_ ^~~~~~ foo_h__ 1 warning generated.
如果你的头文件在
./foo/foo.h,那么你需要写:#include "foo/foo.h"或者,如果继续使用
#include "foo.h",则需要使用参数在编译器命令行上指定在哪里可以找到头文件:gcc -Ifoo -o test test.c -L. -lfoo我故意排除了
-static; 仅当在静态库和共享库之间进行选择时才有必要,但您只有libfoo.a,因此链接器无论如何都会使用它。请注意,问题是编译错误,而不是链接错误。如果将程序构建分为两个步骤,这会更清楚:(1)创建
test.o和(2)链接程序:gcc -c -Ifoo test.c gcc -o test test.o -L. -lfoo你的头卫有问题。您最初有(但已更新问题,因此不再存在此错字):
#ifndef foo_h__ #define foo_h_你需要:
#ifndef foo_h__ #define foo_h__两行中的宏名称必须相同。请注意,在这种情况下,拼写错误大多是无害的——但在 Mac OS X 上,
clang(伪装为gcc)确实发出了警告(尽管我在进行任何编译之前就发现了它)。在其他一些情况下,您将无法获得头部防护设计提供的保护。./foo/foo.h:1:9: warning: 'foo_h__' is used as a header guard here, followed by #define of a different macro [-Wheader-guard] #ifndef foo_h__ ^~~~~~~ ./foo/foo.h:2:9: note: 'foo_h_' is defined here; did you mean 'foo_h__'? #define foo_h_ ^~~~~~ foo_h__ 1 warning generated.
You might legitimately wonder:
你可能想知道:
- If I need
-Ifoowhen compilingtest.c, why wasn't it necessary when compilingfoo/foo.c?
- 如果
-Ifoo编译时需要test.c,为什么编译时不需要foo/foo.c?
Good question!
好问题!
- It would not have hurt the compilation of
foo/foo.c - GCC looks for headers in the directory where the source code of the translation unit is found (so, when compiling
foo/foo.c, it looks infoodirectory for headers included as#include "foo.h"anyway. - The source file
foo/foo.cshould have includedfoo.htoo; it is very important that it does as that is how the compiler provides the cross-checking necessary to ensure consistency. If you had written#include "foo.h", the compilation would work as described. If you wrote (infoo/foo.c)#include "foo/foo.h", then the command line for creatingfoo.owould have needed-I.so the header could be found.
- 它不会伤害编译
foo/foo.c - GCC 在找到翻译单元源代码的目录中查找头文件(因此,在编译时
foo/foo.c,它会在foo目录中查找包含的头文件#include "foo.h"。 - 源文件也
foo/foo.c应该包含在内foo.h;这样做非常重要,因为这是编译器提供确保一致性所需的交叉检查的方式。如果您编写了#include "foo.h",则编译将按描述进行。如果您编写 (infoo/foo.c)#include "foo/foo.h",则foo.o需要用于创建的命令行,-I.以便可以找到标题。

