Eth*_*gue 14 c gcc header-files static-libraries .a
我正在进行C静态库和程序的测试设置.库代码位于我项目的子目录'foo'中,包含以下文件:
富/ foo.c的:
#include <stdio.h>
void foo(void) {
printf("something");
}
Run Code Online (Sandbox Code Playgroud)
富/ foo.h中:
#ifndef foo_h__
#define foo_h__
extern void foo(void);
#endif
Run Code Online (Sandbox Code Playgroud)
我的程序代码如下:
test.c的:
#include "foo.h"
int main() {
foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我有一个名为"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
Run Code Online (Sandbox Code Playgroud)
但是当我运行build时,它会给我以下错误:
test.c:1:17: fatal error: foo.h: No such file or directory
#include "foo.h"
^
Compilation terminated
Run Code Online (Sandbox Code Playgroud)
但是,当我省略#include行时,它确实有效,但我更喜欢在静态库中使用头文件.我做错了什么,我该如何解决?
Jon*_*ler 28
标头不存储在库中.标题与库分开存储.库包含目标文件; 标头不是目标文件.默认情况下,在Unix系统中标准的头被保存在/usr/include-你会发现正常/usr/include/stdio.h和/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>和许多其他头了.
看看你的代码:
如果你的头文件在./foo/foo.h,那么你需要写:
#include "foo/foo.h"
Run Code Online (Sandbox Code Playgroud)
或者,如果继续使用#include "foo.h",则需要在编译器命令行中使用参数指定在哪里查找标头:
gcc -Ifoo -o test test.c -L. -lfoo
Run Code Online (Sandbox Code Playgroud)
我故意排除了-static; 只有在静态库和共享库之间做出选择时才有必要,但是你只有libfoo.a,所以链接器无论如何都会使用它.
请注意,问题是编译错误,而不是链接错误.如果将程序构建分为两个步骤,这将更加清晰:(1)创建test.o和(2)链接程序:
gcc -c -Ifoo test.c
gcc -o test test.o -L. -lfoo
Run Code Online (Sandbox Code Playgroud)你的头部防守有问题.你最初有(但已经更新了问题所以这个错字不再存在):
#ifndef foo_h__
#define foo_h_
Run Code Online (Sandbox Code Playgroud)
你需要:
#ifndef foo_h__
#define foo_h__
Run Code Online (Sandbox Code Playgroud)
两个行中的宏名称必须相同.请注意,在这种情况下,拼写错误几乎是无害的 - 但在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.
Run Code Online (Sandbox Code Playgroud)你可能合理地想知道:
-Ifoo在编译时需要,编译test.c时为什么不需要foo/foo.c?好问题!
foo/foo.cfoo/foo.c,它会在foo目录中查找包含在内的标题#include "foo.h".foo/foo.c应包括在内foo.h; 这是非常重要的,因为编译器提供了确保一致性所必需的交叉检查.如果您已编写#include "foo.h",则编译将按所述方式工作.如果你写了(in foo/foo.c)#include "foo/foo.h",那么创建命令行foo.o就需要了,-I.所以可以找到标题.