[Linux]GNU CC (GCC)库文件的一些问题

本文详细介绍了库文件(包括静态库和共享库)的概念、生成及使用方法,并提供了具体的命令示例,帮助读者理解如何在开发环境中正确配置并利用库文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、库文件简介

简单地说,库(Library)就是一组已经写好了的函数和变量、经过编译代码,是为了能够提高开发效率和运行效率而设计 的。库分为静态库(Static Library)和共享库(Shared library)两类。静态库文件的扩展名是.a,共享库文件的扩展名是.so(在CYGWIN环境下,分别叫做.o和.dll)。共享库现在常常被叫做 动态库,是由于很多人借用了MS Windows的DLL(Dynamic Linked Library)这个词。

(1)静态库

静态是指每个用到该库的应用程序都拥有一份自己的库拷贝;应用程序运行的时候,即使将库删除也没有问题,因为应用程序自己已经有了自己的拷贝。

(2)共享库

一个共享库有可能被多个所有应用程序共享。因此,对每个应用程序来说,即使不再使用某个共享库,也不应将其删除。此外,应用程序需要正确的环境变量设置(LD_LIBRARY_PATH),从而找到共享库所在的位置,否则,应用程序运行时会报告找不到这个库。

二、关于使用库的问题

如果库是已经编译好的,那么如何在开发、运行应用程序时使用呢?

头文件和库文件所在的路径,必须通过适当的方式通知给编译器、链接器和相关的应用程序。

对于静态库来说,主要涉及开发工具,如gcc。例如,用gcc编译、链接时,需要通过适当的路径找到头文件和静态库文件;实现的方法有两种:

gcc的命令行参数(-I, -L)
shell的环境变量(C_INCLUDE_PATH, LIBRARY_PATH)

对于共享库来说,程序在运行时,如果用到了动态库,也需要找到对应的动态库文件;实现的方法:

        shell的环境变量(LD_LIBRARY_PATH)

1)        gcc命令行参数(-I, -L)

默认情况下,gcc会自动搜索下面的路径:

对头文件:
/usr/local/include/
/usr/include/
对库文件:
/usr/local/lib/
/usr/lib/

但是由于系统管理员对系统安装路径有不同的配置,或者对于如64位系统等情况,上述路径对于一台具体的计算机来说可能不同。

如果开发者还有自己工程所需的头文件和库文件,就要用gcc的-I和-L来指定对应的路径。如果需要链接库,还要用-l选项。

例如:如果工程涉及到GDBM(GNU DataBase Management)包,需要libgdbm库,而系统中安装GDBM的路径是:

头文件:/opt/gdbm-1.8.3/include
库文件:/opt/gdbm-1.8.3/lib/

那么,gcc的命令参数是:

$gcc … -I/opt/gdbm-1.8.3/include -L/opt/gdbm-1.8.3/lib –lgdbm

注意:为保证兼容性,必须坚决杜绝在C/C++源文件的#include语句中或者其他相关语句中使用上述路径。

2)        shell环境变量(Environmental Variable)

除了用命令行参数,还可以用环境变量来指示gcc搜索适当的路径。而由于Shell的不同,环境变量的设置方法也不同。常用的Shell有Bash, Csh和Tcsh。

(1)Bash

对于Bash来说,除了由系统管理员配置的内容以外,每个用户的用户目录($HOME)下,有一个.bash_profile文件。可在该文件内,增加下面的两个语句来设置GDBM头文件路径的环境变量:

C_INCLUDE_PATH=/opt/gdbm-1.8.3/include
export C_INCLUDE_PATH

类似地,在该文件内用下面的两个语句来设置库文件路径的环境变量:

LIBRARY_PATH=/opt/gdbm-1.8.3/lib
export LIBRARY_PATH

在.bash_profile中有了上述语句以后,就不用再使用-I和-L来搜索特定包的路径了。但是链接库的时候,还是要用-l选项。

$gcc … –lgdbm

在Bash下,要检查有什么样的环境变量,可用env命令。

$env

(2)Csh和Tcsh

如果是Csh或Tcsh,对环境变量的设置方法就不同了。在用户的($HOME)目录下,相关的一些文件如下:

.cshrc        每次进入Csh时的启动(Startup)文件
.tcshrc        每次进入Tcsh时的启动(Startup)文件(在Tcsh下,如果没有这个文件,系统会用.cshrc文件代替)
.login        每次登录Shell时的启动(Startup)文件

在Csh和Tcsh下,分为Shell变量和环境变量;前者是用来设置Shell本身的,而后者则是供其他程序使用的。一般习惯是:Shell变量在.cshrc中定义,而环境变量则在.login文件中定义。

定义Shell变量的方法是在.cshrc或.tcshrc中用set语句:

        set history = 20

定义环境变量的方法是在.login文件中用setenv语句。对于上面关于GDBM的例子:

setenv C_INCLUDE_PATH /opt/gdbm-1.8.3/include
setenv LIBRARY_PATH /opt/gdbm-1.8.3/lib

在Csh和Tcsh下,可以用setenv命令来查看设置了哪些环境变量(如果要看Shell变量,要用set命令)。

注意:

-        设置Shell变量时要用“=”号;
-        设置环境变量时,变量名与实际值(这里是真实路径)之间没有“=”号;
-        不需要export。

3)        使用共享库

使 用共享库的应用程序,要通过环境变量LD_LIBRARY_PATH找到对应的共享库文件。与其他环境变量一样,对LD_LIBRARY_PATH也要根 据shell的种类和库文件的实际路径进行设置。但是,必须注意的是,与一般的环境变量不同,LD_LIBRARY_PATH的值,是已经安装了的所有共 享库的路径,因此,在Bash下,不能简单地用下面的办法:

LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib        错误!
export LD_LIBRARY_PATH

而必须用:

LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

这样,就把其他共享库的路径也一起加入进来了。同样地,在Csh和Tcsh下,

setenv LD_LIBRARY_PATH /opt/gdbm-1.8.3/lib:$LD_LIBRARY_PATH

三、关于库生成的问题

(1)静态库

简单地说,静态库是一个目标文件的简单集合。因此,首先要解决目标文件。

第一步:将各函数代码所在的源文件编译成目录文件。
例如,对于myfunc.c, myproc.c

gcc -c myfunc.c myproc.c

将得到myfunc.o和myproc.o。

第二步:由ar(archive,归档的意思)把多个目标文件集合起来。

$ar -r libmyjob.a myfunc.o myproc.o

通常,静态库的命名方式应遵守libXXXXX.a格式。应用程序在使用静态库的时候,通常只需要把命名中的XXXXX部分传递给gcc即可。例如:

$gcc –o mywork –lmyjob …

意为让gcc(实际上是gcc调用ld)去连接一个名字为libmyjob.a(或者libmyjob.so)的库。如果库的命名不遵循libXXXXX.a的格式就找不到相应文件。

(2)共享库

共享库的构造复杂一些,通常是一个ELF格式的文件。可以有三种方法生成:

$ld -G
$gcc -shared
$libtool

用ld最复杂,用gcc -share就简单的多,但是-share并非在任何平台都可以使用。GNU提供了一个更好的工具libtool,专门用来在各种平台上生成各种库。

用gcc的-shared参数:

        gcc –shared –o libmyjob.so myjob.o

这样,就通过myjob.o生成了共享库文件libmyjob.so。

特别地,在CYGWIN环境下,仍需要输出符合Windows命名的共享库(动态库),即libXXXXX.dll。如:

gcc –shared –o libmyjob.dll myjob.o       

(3)库生成以后的配置

如果要把自己开发的库文件安装到操作系统中,需要有管理员权限:

(a)        把库文件复制到适当的目录:

可以把自己开发的动态连接库放到/usr/local/lib(或者/usr/lib),或放到其他目录,但不论放在那里,都必须与LIBRARY_PATH的值、LD_LIBRARY_PATH的值相一致。

(b)        修改相关的系统配置文件:

修改/etc/ld.so.conf,然后利用/sbin/ldconfig来完成。



原文地址:http://www.linuxdiyf.com/blog/?44739/action_viewspace_itemid_918.html

### 设置 `CC` 变量为 `aarch64-linux-gnu-gcc` 在 Linux x86 系统中编写 Makefile 时,如果需要将 `CC` 变量设置为 `aarch64-linux-gnu-gcc` 进行交叉编译,可以通过直接赋值的方式完成。以下是具体的实现方式以及注意事项。 #### 明确指定 `CC` 变量 在 Makefile 中,可以通过简单的赋值操作来定义 `CC` 变量: ```makefile CC := aarch64-linux-gnu-gcc ``` 这条语句的作用是覆盖默认的 C 编译器(通常是系统自带的 `gcc`),并将其替换为 `aarch64-linux-gnu-gcc` 工具链中的编译器[^2]。 #### 完整的 Makefile 示例 以下是一个完整的 Makefile 示例,展示了如何正确配置 `CC` 和其他必要的变量以支持交叉编译: ```makefile # 指定交叉编译工具链 CC := aarch64-linux-gnu-gcc AR := aarch64-linux-gnu-ar RANLIB := aarch64-linux-gnu-ranlib LDSHARED := aarch64-linux-gnu-gcc -shared -Wl,-soname,libexample.so.1 # 编译标志 CFLAGS := -Wall -O2 # 目标文件和源文件 TARGET := example SRCS := main.c helper.c OBJS := $(SRCS:.c=.o) # 默认目标 all: $(TARGET) # 链接目标 $(TARGET): $(OBJS) $(CC) $(OBJS) -o $@ # 清理生成的文件 clean: rm -f $(OBJS) $(TARGET) ``` 在这个例子中: - `CC`, `AR`, 和 `RANLIB` 被分别设置为对应的交叉编译工具。 - `CFLAGS` 包含了一些常用的编译选项。 - `TARGET` 是最终生成的可执行文件名。 - `SRCS` 列出了所有的源文件,而 `OBJS` 自动推导出相应的目标文件列表[^2]。 #### 处理可能的错误 当尝试使用 `aarch64-linux-gnu-gcc` 作为编译器时,可能会遇到类似以下的错误消息: ``` checking for aarch64-linux-gnu-gcc... no checking for gcc... gcc ``` 这种情况下,通常是因为未安装或未正确配置交叉编译工具链。解决方法包括下载并解压预构建的 Linaro 工具链,或者自行编译适合的工具链版本[^3]。 例如,可以从官方站点获取最新的工具链包: ```bash wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz tar xf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz export PATH=$(pwd)/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin:$PATH ``` 最后一步通过更新环境变量 `PATH` 来确保系统能够找到新安装的 `aarch64-linux-gnu-gcc` 执行程序[^3]。 --- ### 总结说明 通过合理设置 Makefile 中的 `CC` 变量以及其他关联参数,可以轻松切换至基于 ARM 架构的交叉编译流程。同时,务必确认本地环境中已经存在可用的交叉编译工具链,并适当调整路径等相关配置信息以适应实际需求变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值