makefile静态编译
‘壹’ 如何编译静态链接的程序,通过./configure 把参数-static传入Makefile。
./configure LDFLAGS=-static
‘贰’ makefile如何链接静态库
makefile 里面写法,同你的编译器 如何链接静态库的方法有关。例如:指定库名
VC++ 用 编译选项 /MT 链接 LIBCMT.LIB 就是 链接静态库。
-----
unix/linux makefile 里面,例如
LIBS = libmine.a -lpthread 这里写你要链接的静态库库名
CXXFILES = pthreads.cpp 程序名字们
CXXFLAGS = -O3 -o prog -rdynamic -D_GNU_SOURCE -L./libmine 编译选项
LIBS = libmine.a -lpthread 库名
all:
$(CXX) $(CXXFILES) $(LIBS) $(CXXFLAGS)
clean:
rm -f prog *.o
‘叁’ 如何用vs和makefile文件进行编译
运行cmd.exe (or command.com in win9x)->进到vc/bin目录->运行vc-vars32.bat->进到makefile 所在的目录->nmake /f makefile
从sourceforge上下载下来的libjpeg源代码中有一个makefile.vc的文件,可以通过nmake /f makefile.vc [nodebug=1]来编译libjpeg,但是只能编译静态库,如果需要编译dll以便在emacs等程序中使用的话,需要修改makefile.vc和jmorecfg.h文件。在makefile.vc文件中添加编译dll规则:
以下内容为程序代码:
libjpeg.lib: $(LIBOBJECTS) $(RM) libjpeg.lib lib -out:libjpeg.lib $(LIBOBJECTS) #
添加以下这行 libjpeg.dll: $(LIBOBJECTS) $(RM) libjpeg.dll link -dll -out:libjpeg.dll $(LIBOBJECTS) 在jmorecfg.h中添加#define _WIN32_#define JPEG_DLL 然后nmake /f makefile.vc nodebug=1就可以编译了。
将makefile复制为一个.mak文件,然后用VC打开即可!
.mak 就是一个makefile
可以指定怎样编译(命令行,必须先设置VC命令行环境)
vcvars32.bat可设置环境,在vc98/bin下 nmake /f XXXX.mak
如果有一个makefile就只要nmake就可以了。
‘肆’ 现在go可以静态编译一个程序么
第一步:all.bash
% cd $GOROOT/src
% ./all.bash
第一步有些突兀,因为 all.bash 仅仅调用了其它两个 shell 脚本;make.bash 和 run.bash。如果你在使用 Windows 或 Plan 9,过程是一样的,只是脚本扩展名变成了.bat 或.rc。对于本文中的其它脚本,请根据你的系统适当改动。
第二步:make.bash
. ./make.bash --no-banner
main.bash 来源于 all.bash,因此调用退出将正确终止便宜进程。main.bash 有三个主要工作,第一个是验证编译 Go 的环境是否完整。完整性检查在过去几年中建立,它通常尝试避免使用已知的破损工具或必然失败的环境进行编译。
第三步. cmd/dist
gcc -O2 -Wall -Werror -ggdb -o cmd/dist/dist -Icmd/dist cmd/dist/*.c
一旦可用性检查完毕,make.bash 将编译产生 cmd/dist,cmd/dist取代了之前存在于Go 1 之前的Makefile 编译系统。cmd/dist用来管理少量的pkg/runtime的代码生成。cmd/dist 是C语言编写的程序,能够充分利用系统C编译器和头文件来处理大部分主机系统平台的检测。cmd/dist通常用来检测主机的操作系统和体系结构,即环境变量$GOHOSTOS和$GOHOSTARCH .如果是交叉编译的话,变量 $GOOS和$GOARCH可能会由于你的设置而不同。事实上,Go 通常用作跨平台编译器,只不过多数情况下,主机和目标系统一致而已。接下来,make.bash 调用cmd/dist 的引导参数的支持库、 lib9、 libbio 和 libmach,使用编译器套件,然后用自己的编译器进行编译。这些工具也是用 C 语言写的中,但是由系统 C 编译器编译产生。
echo "# Building compilers and Go bootstrap tool for host, $GOHOSTOS/$GOHOSTARCH."
buildall="-a"
if [ "$1" = "--no-clean" ]; then
buildall=""
fi
./cmd/dist/dist bootstrap $buildall -v # builds go_bootstrap
使用的编译器套件 cmd/dist 编译产生一个版本的gotool,go_bootstrap。但go_bootstrap并不是完整得gotool,比方说 pkg/net 就是孤立的,避免了依赖于 cgo。要编译的文件的列表以及它们的依赖项,是由cmd/dist编译的 ,所以十分谨慎地避免引入新的生成依赖项 到 cmd/go。
第四步:go_bootstrap
现在, go_bootstrap 编译完成了,make.bash 的最后一部就是使用 go_bootstrap 完成 Go 标准库的编译,包括整套 gotool 的替换版。
echo "# Building packages and commands for $GOOS/$GOARCH."
"$GOTOOLDIR"/go_bootstrap install -gcflags "$GO_GCFLAGS" \
-ldflags "$GO_LDFLAGS" -v std
第五步:run.bash
现在,make.bash 完成了,运行回到了 all.bash,它将引用 run.bash。run.bash 的工作是编译和测试标准库,运行时以及语言测试套件。
bash run.bash --no-rebuild
使用 --no-rebuild 标识是因为 make.bash 和 run.bash 可能都调用了 go install -a std,这样可以避免重复,--no-rebuild 跳过了第二个 go install。
# allow all.bash to avoid double-build of everything
rebuild=true
if [ "$1" = "--no-rebuild" ]; then
shift
else
echo '# Building packages and commands.'
time go install -a -v std
echo
fi
第六步:go test -a std
echo '# Testing packages.'
time go test std -short -timeout=$(expr 120 \* $timeout_scale)s
echo
下一步 run.bash z则是对标准库中的所有包进行单元测试,这是使用 testing 包编写的。由于 $GOPATH 和 $GOROOT 中的代码存在于同一个命名空间中,我们不能使用 go test,这可能会测试 $GOPATH 中的所有包,所以将创建别名std来标识标准库中的包。由于有些测试需要很长时间,或耗用大量内存,测试将会通过 -short 标识将其过滤。
第七步 runtime 和 cgo 测试
run.bash的下一节将运行大量对cgo支持的平台测试,运行一些季春测试,编译 Go 附带的一些杂项程序。随着时间的推移,这份杂项程序列表已经变长了,当它们发现自己并不包含在编译过程中时,沉默将不可避免的被打破。
第八步: go run test
(xcd ../test
unset GOMAXPROCS
time go run run.go
) || exit $?
run.bash的倒数第二步调用了$GOROOT目录下test文件夹中的编译器和运行时测试。这其中有描述编译器和运行时本身的低层级测试。而子目录 test/bugs 及 test/fixedbugs 中的测试对已知问题和已解决问题进行特别的测试。所有测试的测试驱动器是 $GOROOT/test/run.go,该程序很小,它调用test文件夹中的每个.go 文件。有些 .go 文件在首行上描述了预期的运行结果,例如,程序失败或是放出特定的输出队列。
第九步go tool api
echo '# Checking API compatibility.'
go tool api -c $GOROOT/api/go1.txt,$GOROOT/api/go1.1.txt \
-next $GOROOT/api/next.txt -except $GOROOT/api/except.txt
run.bash的最后一部将调用API工具,API工具的作用是执行 Go 1 约定;导出的符号,常数,函数,变量,类型和方法组成2012年确认的 Go 1 API。Go 1 写在 api/go1.txt 文件,而 Go 1.1 则写在 api/go1.1.txt文件中。另一个额外的文件,api/next.txt 描述了G 1.1自后添加到标准库和运行时中的符号。当 Go 1.2 发布时,这个文件将会成为 Go 1.2 的约定,另一个新的 next.txt 文件也将被创建。这里还有一个小文件,except.txt,它包括 Go 1 约定中被批准的扩展。对文件的增添总是小心翼翼的。
‘伍’ 在VC里如何用Makefile文件编译
运行cmd.exe (or command.com in win9x)->进到vc/bin目录->运行vc-vars32.bat->进到makefile 所在的目录->nmake /f makefile
从sourceforge上下载下来的libjpeg源代码中有一个makefile.vc的文件,可以通过nmake /f makefile.vc [nodebug=1]来编译libjpeg,但是只能编译静态库,如果需要编译dll以便在emacs等程序中使用的话,需要修改makefile.vc和jmorecfg.h文件。在makefile.vc文件中添加编译dll规则:
以下内容为程序代码:
libjpeg.lib: $(LIBOBJECTS) $(RM) libjpeg.lib lib -out:libjpeg.lib $(LIBOBJECTS) #
添加以下这行 libjpeg.dll: $(LIBOBJECTS) $(RM) libjpeg.dll link -dll -out:libjpeg.dll $(LIBOBJECTS) 在jmorecfg.h中添加#define _WIN32_#define JPEG_DLL 然后nmake /f makefile.vc nodebug=1就可以编译了。
将makefile复制为一个.mak文件,然后用VC打开即可!
.mak 就是一个makefile
可以指定怎样编译(命令行,必须先设置VC命令行环境)
vcvars32.bat可设置环境,在vc98/bin下 nmake /f XXXX.mak
如果有一个makefile就只要nmake就可以了。
‘陆’ makefile的选项CFLAGS,CPPFLAGS,LDFLAGS和LIBS的区别
Linux内核的配置系统由三个部分组成,分别是:Makefile:分布在 Linux 内核源代码中的 Makefile,定义 Linux 内核的编译规则; 配置文件(config.in):给用户提供配置选择的功能; 配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释)和配置用户界面(提供基于字符界面、基于 Ncurses 图形界面以及基于 Xwindows 图形界面的用户配置界面,各自对应于 Make config、Make menuconfig 和 make xconfig)。这些配置工具都是使用脚本语言,如 Tcl/TK、Perl 编写的(也包含一些用 C 编写的代码)。本文并不是对配置系统本身进行分析,而是介绍如何使用配置系统。所以,除非是配置系统的维护者,一般的内核开发者无须了解它们的原理,只需要知道如何编写 Makefile 和配置文件就可以。所以,在本文中,我们只对 Makefile 和配置文件进行讨论。另外,凡是涉及到与具体 CPU 体系结构相关的内容,我们都以 ARM 为例,这样不仅可以将讨论的问题明确化,而且对内容本身不产生影响。2. Makefile2.1 Makefile 概述Makefile 的作用是根据配置的情况,构造出需要编译的源文件列表,然后分别编译,并把目标代码链接到一起,最终形成 Linux 内核二进制文件。由于 Linux 内核源代码是按照树形结构组织的,所以 Makefile 也被分布在目录树中。Linux 内核中的 Makefile 以及与 Makefile 直接相关的文件有:Makefile:顶层 Makefile,是整个内核配置、编译的总体控制文件。 .config:内核配置文件,包含由用户选择的配置选项,用来存放内核配置后的结果(如 make config)。 arch/*/Makefile:位于各种 CPU 体系目录下的 Makefile,如 arch/arm/Makefile,是针对特定平台的 Makefile。 各个子目录下的 Makefile:比如 drivers/Makefile,负责所在子目录下源代码的管理。 Rules.make:规则文件,被所有的 Makefile 使用。 用户通过 make config 配置后,产生了 .config。顶层 Makefile 读入 .config 中的配置选择。顶层 Makefile 有两个主要的任务:产生 vmlinux 文件和内核模块(mole)。为了达到此目的,顶层 Makefile 递归的进入到内核的各个子目录中,分别调用位于这些子目录中的 Makefile。至于到底进入哪些子目录,取决于内核的配置。在顶层 Makefile 中,有一句:include arch/$(ARCH)/Makefile,包含了特定 CPU 体系结构下的 Makefile,这个 Makefile 中包含了平台相关的信息。位于各个子目录下的 Makefile 同样也根据 .config 给出的配置信息,构造出当前配置下需要的源文件列表,并在文件的最后有 include $(TOPDIR)/Rules.make。Rules.make 文件起着非常重要的作用,它定义了所有 Makefile 共用的编译规则。比如,如果需要将本目录下所有的 c 程序编译成汇编代码,需要在 Makefile 中有以下的编译规则:%.s: %.c$(CC) $(CFLAGS) -S $< -o $@有很多子目录下都有同样的要求,就需要在各自的 Makefile 中包含此编译规则,这会比较麻烦。而 Linux 内核中则把此类的编译规则统一放置到 Rules.make 中,并在各自的 Makefile 中包含进了 Rules.make(include Rules.make),这样就避免了在多个 Makefile 中重复同样的规则。对于上面的例子,在 Rules.make 中对应的规则为:%.s: %.c$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F)) $(CFLAGS_$@) -S $< -o [email protected] Makefile 中的变量顶层 Makefile 定义并向环境中输出了许多变量,为各个子目录下的 Makefile 传递一些信息。有些变量,比如 SUBDIRS,不仅在顶层 Makefile 中定义并且赋初值,而且在 arch/*/Makefile 还作了扩充。常用的变量有以下几类:1) 版本信息版本信息有:VERSION,PATCHLEVEL, SUBLEVEL, EXTRAVERSION,KERNELRELEASE。版本信息定义了当前内核的版本,比如 VERSION=2,PATCHLEVEL=4,SUBLEVEL=18,EXATAVERSION=-rmk7,它们共同构成内核的发行版本KERNELRELEASE:2.4.18-rmk72) CPU 体系结构:ARCH在顶层 Makefile 的开头,用 ARCH 定义目标 CPU 的体系结构,比如 ARCH:=arm 等。许多子目录的 Makefile 中,要根据 ARCH 的定义选择编译源文件的列表。3) 路径信息:TOPDIR, SUBDIRSTOPDIR 定义了 Linux 内核源代码所在的根目录。例如,各个子目录下的 Makefile 通过 $(TOPDIR)/Rules.make 就可以找到 Rules.make 的位置。SUBDIRS 定义了一个目录列表,在编译内核或模块时,顶层 Makefile 就是根据 SUBDIRS 来决定进入哪些子目录。SUBDIRS 的值取决于内核的配置,在顶层 Makefile 中 SUBDIRS 赋值为 kernel drivers mm fs net ipc lib;根据内核的配置情况,在 arch/*/Makefile 中扩充了 SUBDIRS 的值,参见4)中的例子。4) 内核组成信息:HEAD, CORE_FILES, NETWORKS, DRIVERS, LIBSLinux 内核文件 vmlinux 是由以下规则产生的:vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o --start-group $(CORE_FILES) $(DRIVERS) $(NETWORKS) $(LIBS) --end-group -o vmlinux可以看出,vmlinux 是由 HEAD、main.o、version.o、CORE_FILES、DRIVERS、NETWORKS 和 LIBS 组成的。这些变量(如 HEAD)都是用来定义连接生成 vmlinux 的目标文件和库文件列表。其中,HEAD在arch/*/Makefile 中定义,用来确定被最先链接进 vmlinux 的文件列表。比如,对于 ARM 系列的 CPU,HEAD 定义为: HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o表明 head-$(PROCESSOR).o 和 init_task.o 需要最先被链接到 vmlinux 中。PROCESSOR 为 armv 或 armo,取决于目标 CPU。 CORE_FILES,NETWORK,DRIVERS 和 LIBS 在顶层 Makefile 中定义,并且由 arch/*/Makefile 根据需要进行扩充。 CORE_FILES 对应着内核的核心文件,有 kernel/kernel.o,mm/mm.o,fs/fs.o,ipc/ipc.o,可以看出,这些是组成内核最为重要的文件。同时,arch/arm/Makefile 对 CORE_FILES 进行了扩充:# arch/arm/Makefile# If we have a machine-specific directory, then include it in the build.MACHDIR := arch/arm/mach-$(MACHINE)ifeq ($(MACHDIR),$(wildcard $(MACHDIR)))SUBDIRS += $(MACHDIR)CORE_FILES := $(MACHDIR)/$(MACHINE).o $(CORE_FILES)endifHEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.oSUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpeCORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)LIBS := arch/arm/lib/lib.a $(LIBS)5) 编译信息:CPP, CC, AS, LD, AR,CFLAGS,LINKFLAGS在 Rules.make 中定义的是编译的通用规则,具体到特定的场合,需要明确给出编译环境,编译环境就是在以上的变量中定义的。针对交叉编译的要求,定义了 CROSS_COMPILE。比如:CROSS_COMPILE = arm-linux-CC = $(CROSS_COMPILE)gccLD = $(CROSS_COMPILE)ld......CROSS_COMPILE 定义了交叉编译器前缀 arm-linux-,表明所有的交叉编译工具都是以 arm-linux- 开头的,所以在各个交叉编译器工具之前,都加入了 $(CROSS_COMPILE),以组成一个完整的交叉编译工具文件名,比如 arm-linux-gcc。CFLAGS 定义了传递给 C 编译器的参数。LINKFLAGS 是链接生成 vmlinux 时,由链接器使用的参数。LINKFLAGS 在 arm/*/Makefile 中定义,比如:# arch/arm/MakefileLINKFLAGS :=-p -X -T arch/arm/vmlinux.lds6) 配置变量CONFIG_*.config 文件中有许多的配置变量等式,用来说明用户配置的结果。例如 CONFIG_MODULES=y 表明用户选择了 Linux 内核的模块功能。.config 被顶层 Makefile 包含后,就形成许多的配置变量,每个配置变量具有确定的值:y 表示本编译选项对应的内核代码被静态编译进 Linux 内核;m 表示本编译选项对应的内核代码被编译成模块;n 表示不选择此编译选项;如果根本就没有选择,那么配置变量的值为空。2.3 Rules.make 变量前面讲过,Rules.make 是编译规则文件,所有的 Makefile 中都会包括 Rules.make。Rules.make 文件定义了许多变量,最为重要是那些编译、链接列表变量。O_OBJS,L_OBJS,OX_OBJS,LX_OBJS:本目录下需要编译进 Linux 内核 vmlinux 的目标文件列表,其中 OX_OBJS 和 LX_OBJS 中的 "X" 表明目标文件使用了 EXPORT_SYMBOL 输出符号。M_OBJS,MX_OBJS:本目录下需要被编译成可装载模块的目标文件列表。同样,MX_OBJS 中的 "X" 表明目标文件使用了 EXPORT_SYMBOL 输出符号。O_TARGET,L_TARGET:每个子目录下都有一个 O_TARGET 或 L_TARGET,Rules.make 首先从源代码编译生成 O_OBJS 和 OX_OBJS 中所有的目标文件,然后使用 $(LD) -r 把它们链接成一个 O_TARGET 或 L_TARGET。O_TARGET 以 .o 结尾,而 L_TARGET 以 .a 结尾。
‘柒’ 我写了个Makefile文件 指定调用我自己编译的静态库 怎么每次系统都从/usr/lib下面查找
你在makefile中指定所链接库的位置了么??
在你的makefile中写编译规则的地方加上 -L/home/zhangcl/lib 就好了
‘捌’ makefile 生成动态库和静态库的区别
生成
动态库
的时候要注意,编译生成目标文件的时候加上-fPIC参数,生成位置无关的可重定位代码,然后链接的时候加上-shared生成动态共享库。比如一个hello.c,生成静态库:
1
2
gcc -o hello.o -c hello.c
ar rcs libhello.a hello.o
生成动态库的命令:
1
2
gcc -fPIC hello.o -c hello.c
gcc -shared -o libhelllo.so hello.o
还有一个区别是:静态库参与链接过程,而动态库不链接到可执行文件中,
可执行程序
在运行的时候,对应的动态库也要加载到内存中,否则可执行程序运行不了。
‘玖’ 多级目录makefile,静态库
在lib 目录下编译需要生成动态库的文件,生成动态库,并安装到系统的标准库中,供
程序调用。具体步骤如下:
(1) 编写Makefile.am 文件
AUTOMAKE_OPTIONS=foreign
lib_LTLIBRARIES=libhello.la
libhello_la_SOURCES=test.c
这里lib_LTLIBRARIES 的意思是生成的动态库,然后指定动态库依赖的源文件
test.c ,若有多个源文件用空格隔开。
(2) 在lib 目录下,用命令autoscan 产生configure.scan 文件,并改名为configure.in。 这
里需加上宏AC_PROG_LIBTOOL,表示利用libtool 来自动生成动态库
#configure.in
# Process this file with autoconf to proce a configure script.
AC_PREREQ(2.59)
AC_INIT(hello,1.0, [[email protected]])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([test.c])
#AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_PROG_LIBTOOL
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
(3) 执行命令aclocal、libtoolize -f -c 、autoconf、automake --add-missing、./configure、
make、make install 将动态库安装到系统的标准库中,以供调用(一般为/usr/local/lib)。
注:libtoolize 提供了一种标准的方式来将libtool 支持加入一个软件包,而GNU libtool 是
一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中。
4. 生成src 目录下的hello 可执行文件
(1) 编写src/Makefile.am 文件
AUTOMAKE_OPTIONS=foreign
INCLUDES= -I../include
bin_PROGRAMS=hello
hello_SOURCES=hello.c
hello_LDADD=-lhello
-ldir 指定编译时搜索库的路径。与静态库不同的是,创建动态库时不用指定库路
径,编译器自动在标准库中查找libhello.so 文件。
(2) 执行autoscan 生成configure.scan 文件,将它重命名为configure.in 并修改其内容。
# configure.in
# Process this file with autoconf to proce a configure script.
AC_PREREQ(2.59)
AC_INIT(hello,1.0, [[email protected]])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([hello.c])
#AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
(3) 在src 目录下编译并生成目标文件,执行命令aclocal、libtoolize -f -c 、autoconf、
automake --add-missing、./configure、make,此时你一定会觉得,成功近在咫尺了。再
执行目标文件./hello,结果却在你的意料之外:
./hello: error while loading shared libraries: libhello.so.0 : cannot open shared object file:
No such file or directory
在执行目标文件的时候,Shell 找不到共享库的位置,需要我们手工载入库路径。
5. shell 搜索动态库路径位置的两种方法
(1) 使用命令导入动态库的路径,命令如下:
export LD_LIBRARY_PATH=dir (如/usr/local/lib)
(2) 修改/etc/ld.so.conf 文件,加入搜索路径,修改后用ldconfig 命令载入修改。
将自己可能存放库文件的路径都加入到/etc/ld.so.conf 中是明智的选择 ^_^。添加
方法也极其简单,将库文件的绝对路径直接写进去就OK 了,一行一个。例如:
/usr/local/lib
/usr/lib
/lib
需要注意的是:这种搜索路径的设置方式对于程序连接时的库(包括共享库和静态
库)的定位已经足够了,但是对于使用了共享库的程序的执行还是不够的。这是 因为
为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所
以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。/etc/ld.so.cache 是一个非
文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由
/sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的(ldconfig 命令
要以 root 权限执行)。因此,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中
进行了库搜索路径的设置之后,还必须要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache
文件之后才可以。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf 列出的路径下的库
文件 缓存到/etc/ld.so.cache 以供使用。因此当安装完一些库文件,(例如刚安装好glib),
或者修改ld.so.conf 增加新的库路径后,需要运行一下/sbin/ldconfig 使所有的库文件都
被缓存到ld.so.cache 中,如果没做,即使库文件明明就在/usr/lib 下的,也是不会被使
用的,结果编译过程中报错,缺少xxx 库,去查看发现明明就在那放着,搞的想大骂
computer 蠢猪一个^_^。极力推荐使用这种方法!
利用gcc 创建和使用动态库
1. 用下面的命令将mylib.c 程序创建成一个动态库:
gcc –fPIC –o mylib.o –c mylib.c
gcc –shared –o libtt.so mylib.o
-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),
则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的
任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不
是固定的。
-shared 作用于链接阶段,实际传递给链接器ld,让其添加作为共享库所需要的额外描
述信息,去除共享库所不需的信息。
也可以直接使用下面一条命令:
gcc –fPIC –shared –o libtt.so mylib.c
2. 将动态库拷贝到linux 的标准库中,usr/local/lib 或者/usr/lib 或者/lib:
cp libttt.so /usr/local/lib
3. 编译src 目录下的源程序时,指定动态库文件的目录,调用动态库中的函数
gcc –o test test.c /usr/lib/libttt.so
4. 设置shell 动态库搜索路径,运行生成的可执行文件。