Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Build 构建共享库时,是否只需要依赖库的头文件?_Build_Shared Libraries - Fatal编程技术网

Build 构建共享库时,是否只需要依赖库的头文件?

Build 构建共享库时,是否只需要依赖库的头文件?,build,shared-libraries,Build,Shared Libraries,假设一个共享库a依赖于另一个共享库B 在这种情况下,当我构建A时,我是否只需要B的头文件? 因为只有当我构建一些需要A的程序时,B才是必需的。对吗?你能解释一下细节吗?你说得对。这里有一个具体的例子 a.h #ifndef A_H #define A_H extern void aa(void); #endif #ifndef B_H #define B_H extern void bb(void); #endif a.c #include "a.h" #include "b.h"

假设一个共享库a依赖于另一个共享库B

在这种情况下,当我构建A时,我是否只需要B的头文件?
因为只有当我构建一些需要A的程序时,B才是必需的。对吗?你能解释一下细节吗?

你说得对。这里有一个具体的例子

a.h

#ifndef A_H
#define A_H

extern void aa(void);

#endif
#ifndef B_H
#define B_H

extern void bb(void);

#endif
a.c

#include "a.h"
#include "b.h"

void aa(void)
{
    bb();
}
#include "b.h"
#include <stdio.h>

void bb(void)
{
    puts(__func__);
}
#include "a.h"

int main(void)
{
    aa();
    return 0;
}
b.h

#ifndef A_H
#define A_H

extern void aa(void);

#endif
#ifndef B_H
#define B_H

extern void bb(void);

#endif
b.c

#include "a.h"
#include "b.h"

void aa(void)
{
    bb();
}
#include "b.h"
#include <stdio.h>

void bb(void)
{
    puts(__func__);
}
#include "a.h"

int main(void)
{
    aa();
    return 0;
}
我们创建了一个共享库
liba.so
。首先编译一个 对象文件

$ gcc -Wall -Wextra -o a.o -c -fPIC a.c
现在,对象文件
a.o
包含对
bb
的未定义引用:

$ readelf -s a.o

Symbol table '.symtab' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
$ readelf --dyn-syms liba.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
   ...
$ readelf --dyn-syms libb.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    11: 000000000000060a    19 FUNC    GLOBAL DEFAULT   12 bb
链接共享库:

$ gcc -shared -o liba.so a.o
现在,共享库还未定义对
bb
的引用:

$ readelf -s a.o

Symbol table '.symtab' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
$ readelf --dyn-syms liba.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
   ...
$ readelf --dyn-syms libb.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    11: 000000000000060a    19 FUNC    GLOBAL DEFAULT   12 bb
那很好。链接器将创建一个包含未定义引用的共享库

以相同的方式创建另一个共享库
libb.so

$ gcc -Wall -Wextra -o b.o -c -fPIC b.c
$ gcc -shared -o libb.so b.o
此共享库定义了
bb

$ readelf -s a.o

Symbol table '.symtab' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
$ readelf --dyn-syms liba.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
   ...
$ readelf --dyn-syms libb.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    11: 000000000000060a    19 FUNC    GLOBAL DEFAULT   12 bb
接下来尝试制作一个程序:

$ gcc -Wall -Wextra -o main.o -c main.c
$ gcc -o prog main.o
main.o: In function `main':
main.c:(.text+0x5): undefined reference to `aa'
collect2: error: ld returned 1 exit status
当我们既不链接
liba
也不链接
libb
时,就会发生这种情况。链接器将 不创建包含未定义引用的程序。因此:

$ gcc -o prog main.o liba.so
liba.so: undefined reference to `bb'
collect2: error: ld returned 1 exit status
当我们链接到
liba
而不是
libb
时,就会发生这种情况。如果我们与 两者都有,比如:

$ gcc -o prog main.o liba.so libb.so
成功!但是要小心。如果我们交换库的顺序:

$ gcc -o prog main.o libb.so liba.so
liba.so: undefined reference to `bb'
collect2: error: ld returned 1 exit status
联动装置再次失效。而且:

$ gcc -o prog libb.so liba.so main.o
main.o: In function `main':
main.c:(.text+0x5): undefined reference to `aa'
collect2: error: ld returned 1 exit status
链接器需要一个接一个地查看库 依赖于它的库或对象文件。因此必须在
liba
之前链接
main.o
, 必须在
libb
之前链接
liba

还有最后一个障碍

或相当于:

$ gcc -o prog main.o -L. -la -lb
成功链接程序
prog
,但:

$ ./prog
./prog: error while loading shared libraries: liba.so: cannot open shared object file: No such file or directory
它不跑了。因为运行时加载程序仍然不知道在哪里查找
liba
libb

加载程序知道
prog
需要一些名为
liba.so
libb.so
的共享库,因为链接器已经编写了这些库 进入
prog
的信息:

$ readelf -d prog

Dynamic section at offset 0xda8 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [liba.so]
 0x0000000000000001 (NEEDED)             Shared library: [libb.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 ...
就像链接器一样,有。 它将在其中一个默认目录中找到
libc.so.6
(GNUC库)。但是它找不到我已经找到的
liba.so
libb.so
任何一个都有

但是我可以告诉链接器通过链接为加载程序提供缺少的信息 相反,该程序如下所示:

$ gcc -o prog main.o -L. -la -lb -Wl,-rpath=$PWD
使用
-Wl,-rpath=$PWD
,我告诉
gcc
传递(扩展)选项
-rpath=$PWD
连接到链接器,如果我们这样做,我们将看到:

$ readelf -d prog

Dynamic section at offset 0xd98 contains 30 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [liba.so]
 0x0000000000000001 (NEEDED)             Shared library: [libb.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000001d (RUNPATH)            Library runpath: [/home/imk/develop/so/scrap1]
 ...
因此,现在当加载程序加载
prog
时,它将看到
运行路径=/home/imk/developer/So/scrap1
是一个非默认目录,它还应该在其中搜索任何所需的
共享库<代码>程序 然后可以成功加载其所有运行时依赖项:

$ ./prog
bb

你说得对。这里有一个具体的例子

a.h

#ifndef A_H
#define A_H

extern void aa(void);

#endif
#ifndef B_H
#define B_H

extern void bb(void);

#endif
a.c

#include "a.h"
#include "b.h"

void aa(void)
{
    bb();
}
#include "b.h"
#include <stdio.h>

void bb(void)
{
    puts(__func__);
}
#include "a.h"

int main(void)
{
    aa();
    return 0;
}
b.h

#ifndef A_H
#define A_H

extern void aa(void);

#endif
#ifndef B_H
#define B_H

extern void bb(void);

#endif
b.c

#include "a.h"
#include "b.h"

void aa(void)
{
    bb();
}
#include "b.h"
#include <stdio.h>

void bb(void)
{
    puts(__func__);
}
#include "a.h"

int main(void)
{
    aa();
    return 0;
}
我们创建了一个共享库
liba.so
。首先编译一个 对象文件

$ gcc -Wall -Wextra -o a.o -c -fPIC a.c
现在,对象文件
a.o
包含对
bb
的未定义引用:

$ readelf -s a.o

Symbol table '.symtab' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
$ readelf --dyn-syms liba.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
   ...
$ readelf --dyn-syms libb.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    11: 000000000000060a    19 FUNC    GLOBAL DEFAULT   12 bb
链接共享库:

$ gcc -shared -o liba.so a.o
现在,共享库还未定义对
bb
的引用:

$ readelf -s a.o

Symbol table '.symtab' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
$ readelf --dyn-syms liba.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
   ...
$ readelf --dyn-syms libb.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    11: 000000000000060a    19 FUNC    GLOBAL DEFAULT   12 bb
那很好。链接器将创建一个包含未定义引用的共享库

以相同的方式创建另一个共享库
libb.so

$ gcc -Wall -Wextra -o b.o -c -fPIC b.c
$ gcc -shared -o libb.so b.o
此共享库定义了
bb

$ readelf -s a.o

Symbol table '.symtab' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
$ readelf --dyn-syms liba.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND bb
   ...
$ readelf --dyn-syms libb.so

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
    11: 000000000000060a    19 FUNC    GLOBAL DEFAULT   12 bb
接下来尝试制作一个程序:

$ gcc -Wall -Wextra -o main.o -c main.c
$ gcc -o prog main.o
main.o: In function `main':
main.c:(.text+0x5): undefined reference to `aa'
collect2: error: ld returned 1 exit status
当我们既不链接
liba
也不链接
libb
时,就会发生这种情况。链接器将 不创建包含未定义引用的程序。因此:

$ gcc -o prog main.o liba.so
liba.so: undefined reference to `bb'
collect2: error: ld returned 1 exit status
当我们链接到
liba
而不是
libb
时,就会发生这种情况。如果我们与 两者都有,比如:

$ gcc -o prog main.o liba.so libb.so
成功!但是要小心。如果我们交换库的顺序:

$ gcc -o prog main.o libb.so liba.so
liba.so: undefined reference to `bb'
collect2: error: ld returned 1 exit status
联动装置再次失效。而且:

$ gcc -o prog libb.so liba.so main.o
main.o: In function `main':
main.c:(.text+0x5): undefined reference to `aa'
collect2: error: ld returned 1 exit status
链接器需要一个接一个地查看库 依赖于它的库或对象文件。因此必须在
liba
之前链接
main.o
, 必须在
libb
之前链接
liba

还有最后一个障碍

或相当于:

$ gcc -o prog main.o -L. -la -lb
成功链接程序
prog
,但:

$ ./prog
./prog: error while loading shared libraries: liba.so: cannot open shared object file: No such file or directory
它不跑了。因为运行时加载程序仍然不知道在哪里查找
liba
libb

加载程序知道
prog
需要一些名为
liba.so
libb.so
的共享库,因为链接器已经编写了这些库 进入
prog
的信息:

$ readelf -d prog

Dynamic section at offset 0xda8 contains 29 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [liba.so]
 0x0000000000000001 (NEEDED)             Shared library: [libb.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 ...
就像链接器一样,有。 它将在其中一个默认目录中找到
libc.so.6
(GNUC库)。但是它找不到我已经找到的
liba.so
libb.so
任何一个都有

但是我可以告诉链接器通过链接为加载程序提供缺少的信息 相反,该程序如下所示:

$ gcc -o prog main.o -L. -la -lb -Wl,-rpath=$PWD
使用
-Wl,-rpath=$PWD
,我告诉
gcc
传递(扩展)选项
-rpath=$PWD
连接到链接器,如果我们这样做,我们将看到:

$ readelf -d prog

Dynamic section at offset 0xd98 contains 30 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [liba.so]
 0x0000000000000001 (NEEDED)             Shared library: [libb.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000001d (RUNPATH)            Library runpath: [/home/imk/develop/so/scrap1]
 ...
因此,现在当加载程序加载
prog
时,它将看到
运行路径=/home/imk/developer/So/scrap1
是一个非默认目录,它还应该在其中搜索任何所需的
共享库<代码>程序 然后可以成功加载其所有运行时依赖项:

$ ./prog
bb

谢谢你的完美答案:)谢谢你的完美答案:)