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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 11:39:10  来源:igfitidea点击:

Including header file from static library

cgccstatic-librariesheader-files.a

提问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:

查看您的代码:

  1. 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. -lfoo
    

    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.

    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. -lfoo
    
  2. 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_
    

    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 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.
    
  1. 如果你的头文件在./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
    
  2. 你的头卫有问题。您最初有(但已更新问题,因此不再存在此错字):

    #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 compiling test.c, why wasn't it necessary when compiling foo/foo.c?
  • 如果-Ifoo编译时需要test.c,为什么编译时不需要foo/foo.c

Good question!

好问题!

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