用gcc生成静态和动态链接库的示例

照着https://www.cnblogs.com/oxspirt/p/7344371.html这篇文章做了一个小实验,以下是我的笔记整理。关于动态库还有一些疑惑,再次也记录一下。
gcc几个参数的功能:
-I dir :将目录dir添加到要搜索头文件的目录列表中,且搜索顺序优先于系统库。(在你使用 #include “file” 的时候, gcc/g++ 会先在当前目录查找你所制定的头文件, 如果没有找到, 他回到默认的头文件目录找, 如果使用 -I 制定了目录,他会先在你所指定的目录查找, 然后再按常规的顺序去找。对于 #include, gcc/g++ 会到 -I 制定的目录查找, 查找不到, 然后将到系统的默认的头文件目录查找 。此时如果找不到头文件会在编译期报错)
-Ldir :增加该目录到能够被-l搜索到的列表中。(Add directory dir to the list of directories to be searched for -l.指定编译的时候,搜索库的路径。比如你自己的库,可以用它指定目录,不然编译器将只在标准库的目录找。这个dir就是目录的名称。)
-l library:链接时搜索名为library的库。(如果没有找到该名称的库则会在链接时报错。注意不是编译时了,这是已经通过了编译,在链接阶段找函数实现时,发现找不到)

示例

三个程序放在文件夹~/testso中
程序1: hello.h

#ifndef HELLO_H 
#define HELLO_H 
    void hello(const char *name); 
#endif

程序2:hello.c

#include <stdio.h> 
void hello(const char *name) { 
    printf("Hello %s!\n", name); 
}

程序3:main.c

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

问题的提出

注意:这个时候,我们编译好的hello.o是无法通过gcc –o 编译的,这个道理非常简单,
hello.c是一个没有main函数的.c程序,因此不够成一个完整的程序,如果使用gcc –o 编译并连接它,GCC将报错(undefined reference to `main’)。
==无论静态库,还是动态库,都是由.o文件创建的。==因此,我们必须将源程序hello.c通过gcc先编译成.o文件。
这个时候我们有三种思路:
1) 通过编译多个源文件,直接将目标代码合成一个.o文件。
2) 通过创建静态链接库libmyhello.a,使得main函数调用hello函数时可调用静态链接库。
3) 通过创建动态链接库libmyhello.so,使得main函数调用hello函数时可调用静态链接库。

思路一:编译多个源文件

[root@192 testso]# gcc -c hello.c
[root@192 testso]# gcc -c main.c
[root@192 testso]# gcc -o hello hello.o main.o
[root@192 testso]# ls
hello hello.c hello.h hello.o main.c main.o
[root@192 testso]# ./hello
hello everyone!
gcc -c 代表汇编生成.o文件后就停止,不进行最后一步的链接。

思路二:静态链接库

[root@192 testso]# ls
hello.c hello.h main.c
[root@192 testso]# gcc -c hello.c
[root@192 testso]# ar rcs libmyhello.a hello.o
[root@192 testso]# ls //可以看到这里我们的静态库已经制作完毕
hello.c hello.h hello.o libmyhello.a main.c
//-L.代表着我们对于myhello的搜索位置是当前目录,也就是我们libmyhello.a的位置是当前目录,如果将其移动到其他的目录中,这个-L<dir>应该随之修改。
[root@192 testso]# gcc -o hello main.c -static -L. -lmyhello
[root@192 testso]# ./hello
hello everyone!
我在运行 gcc -o hello main.c -static -L. -lmyhello这个命令时报错:/usr/bin/ld: 找不到 -lc,原因是在新版本的linux 系统下安装 glibc-devel、glibc和gcc-c++时,都不会安装libc.a. 只安装libc.so. 所以当使用-static时,libc.a不能使用。只能报找不到libc了。解决方式:安装 glibc-static sudo yum install glibc-static(参考https://blog.csdn.net/whatday/article/details/99421837)

思路三、动态链接库(共享函数库)

[root@192 testso]# ls
hello.c hello.h main.c
[root@192 testso]# gcc -shared -fPIC -c hello.c
[root@192 testso]# ls
hello.c hello.h hello.o main.c
[root@192 testso]# gcc -shared -fPIC -o libmyhello.so hello.o
[root@192 testso]# ls
hello.c hello.h hello.o libmyhello.so main.c
[root@192 testso]# gcc -o hello main.c -L. -lmyhello
./hello
./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

错误提示,找不到动态库文件libmyhello.so。程序在运行时,会查找需要的动态库文件,顺序参考后文介绍。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。有多种方法可以解决,(这里我试了三种方式,从头到尾做了一遍,才能够正常运行程序,目前也不太理解
(1)我们将文件 libmyhello.so复制到目录/usr/lib中,再试试。
$ sudo mv libmyhello.so /usr/lib
(2)既然连接器会搜寻LD_LIBRARY_PATH所指定的目录,那么我们可以将这个环境变量设置成当前目录:
export LD_LIBRARY_PATH=$(pwd)
(3)sudo ldconfig ~/testso
注: 当用户在某个目录下面创建或拷贝了一个动态链接库,若想使其被系统共享,可以执行一下”ldconfig 目录名”这个命令。此命令的功能在于让ldconfig将指定目录下的动态链接库被系统共享起来,意即:在缓存文件/etc/ld.so.cache中追加进指定目录下的共享库.本例让系统共享了~/tests目录下的动态链接库。

搜索路径

目前还不太懂,先记下来把,日后再看。

静态库链接时搜索路径顺序:

ld会去找GCC命令中的参数-L
再找gcc的环境变量LIBRARY_PATH
再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态链接时、执行时搜索路径顺序:

编译目标代码时指定的动态库搜索路径;
环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
配置文件/etc/ld.so.conf中指定的动态库搜索路径;
默认的动态库搜索路径/lib;
默认的动态库搜索路径/usr/lib。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,我来为你简单介绍一下如何设置编译生成执行文件、使用 CMake 进行构建、以及如何进行静态链接和动态链接。 1. 主函数编译生成执行文件 在主函数编写完成后,使用命令行编译工具或者集成开发环境(IDE)进行编译生成可执行文件。以 gcc 编译器为例,编译命令如下: ``` gcc main.c -o main ``` 其中 main.c 是主函数源代码文件,main生成的可执行文件名。 2. 使用 CMake 进行构建 使用 CMake 进行构建可以提高开发效率,方便在不同的平台和编译器上进行编译和构建。在项目根目录下创建 CMakeLists.txt 文件,并在其中定义项目名称、源代码文件、可执行文件等信息。示例 CMakeLists.txt 文件如下: ``` cmake_minimum_required(VERSION 3.0) project(my_project) add_executable(my_project main.c) ``` 其中,cmake_minimum_required 表示 CMake 的最低版本要求,project 定义项目名称,add_executable 定义可执行文件名和源代码文件。 3. 静态链接和动态链接 静态链接和动态链接都是将库中的代码和数据与可执行文件关联起来。静态链接是将库代码和数据复制到可执行文件中,而动态链接是在程序运行时动态加载库。 静态链接可以通过在编译时使用 -static 选项来进行,示例编译命令如下: ``` gcc main.c -static -o main ``` 动态链接可以通过在编译时不使用 -static 选项来进行,示例编译命令如下: ``` gcc main.c -o main ``` 以上是简单的设置方法,具体设置还需要根据不同的编译器和操作系统进行调整。希望这些信息对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值