包括静态库中的头文件 [英] Including header file from static library

查看:365
本文介绍了包括静态库中的头文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试C静态库和程序. 库代码位于我项目的子目录"foo"中,包含以下文件:

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:

foo/foo.c:

#include <stdio.h>
void foo(void) {
    printf("something");
}

foo/foo.h:

#ifndef foo_h__
#define foo_h__
extern void foo(void);
#endif

我的程序代码如下:

test.c:

#include "foo.h"
int main() {
    foo();
    return 0;
}

我有一个名为"build"的构建脚本,其中包含以下内容:

I have a build script, called 'build', which contains the following:

内部版本:

#!/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

但是当我运行build时,它给了我以下错误:

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

但是,当我省略#include行时,它确实可以工作,但是如果可以在我的静态库中使用头文件,我会更喜欢.我在做什么错了,我该如何解决?

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?

推荐答案

标头未存储在库中.标头与库分开存储.库包含目标文件;标头不是目标文件.默认情况下,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>和许多其他标头中的功能相对应的功能.

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.h and /usr/include/string.h and /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/include for headers and /usr/local/lib for 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.

查看您的代码:

  1. 如果头文件位于./foo/foo.h中,则需要编写:

#include "foo/foo.h"

或者,如果您继续使用#include "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. -lfoo

我故意排除了-static;仅当在静态库和共享库之间进行选择时才有必要,但是您只有libfoo.a,因此链接器仍将使用该库.

I deliberately excluded the -static; it's only necessary when there's a choice between a static and a shared library, but you only have libfoo.a, so the linker will use that anyway.

请注意,问题是编译错误,而不是链接错误.如果将程序构建分为两个步骤,这将更加清楚:(1)创建test.o和(2)链接程序:

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.o and (2) link program:

gcc -c -Ifoo test.c
gcc -o test test.o -L. -lfoo

  • 您的页眉防护出现故障.您原来有(但是已经更新了问题,所以不再存在此错字):

  • Your 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_
    

    您需要:

    #ifndef foo_h__
    #define foo_h__
    

    两行中的宏名称必须相同.请注意,在这种情况下,拼写错误几乎是无害的-但是在Mac OS X上,clang(伪装为gcc)确实对此提供了警告(尽管我在进行任何编译之前就已经发现了它).在某些其他情况下,您将无法获得标头保护程序旨在提供的保护.

    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 as gcc) 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.
    

  • 您可能会合理地想知道:

    You might legitimately wonder:

    • 如果在编译test.c时需要-Ifoo,为什么在编译foo/foo.c时没有必要?
    • If I need -Ifoo when compiling test.c, why wasn't it necessary when compiling foo/foo.c?

    好问题!

    1. 这不会损害foo/foo.c
    2. 的编译
    3. GCC在找到翻译单元源代码的目录中查找标头(因此,编译foo/foo.c时,它在foo目录中查找反而包含为#include "foo.h"的标头.
    4. 源文件foo/foo.c也应该包含foo.h;这样做非常重要,因为这就是编译器提供必要的交叉检查以确保一致性的方式.如果您编写了#include "foo.h",则编译将按照说明进行.如果您(在foo/foo.c中)编写了#include "foo/foo.h",则用于创建foo.o的命令行将需要-I.,以便可以找到标头.
    1. It would not have hurt the compilation of foo/foo.c
    2. 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 in foo directory for headers included as #include "foo.h" anyway.
    3. The source file foo/foo.c should have included foo.h too; 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 (in foo/foo.c) #include "foo/foo.h", then the command line for creating foo.o would have needed -I. so the header could be found.

    这篇关于包括静态库中的头文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆