静态库和动态库的构建和链接
现有C++工程目录结构如下:
 
 add.h
int add(int a, int b);
 
add.cpp
#include "add.h"
int add(int a, int b)
{
    return a+b;
}
 
main.cpp
#include <iostream>
#include "add.h"
int main()
{
	std::cout << add(1, 2) << std::endl;
	return 0;
}
 
静态库的构建和链接
一个可以构建静态库的Makefile:
compile_flags := -g -O3 -std=c++11 -I ./
linking_flags := -l add -L ./
add.o : add.cpp
	@g++ -c $^ -o $@ $(compile_flags)
libadd.a : add.o
	@ar -r $@ $^
static_lib : libadd.a
main.o : main.cpp
	@g++ -c $^ -o $@ $(compile_flags)
use_add : main.o
	@g++ $^ -o $@ $(linking_flags)
all : static_lib use_add
clean :
	@rm -rf *.o *.a *.so use_add
 
执行make all命令即可在当前目录下生成静态库libadd.a和可执行文件use_add。
 通过ldd use_add命令查看可执行程序依赖的动态链接库,打印如下:
linux-vdso.so.1 (0x00007ffdf311f000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fcf0fce3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcf0faf1000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fcf0f9a2000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcf0feff000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fcf0f987000)
 
动态库的构建和链接
一个可以构建动态库的Makefile:
compile_flags := -g -O3 -w -fPIC -I ./
linking_flags := -l add -L ./ -Wl,-rpath=./
add.o : add.cpp
	@g++ -c $^ -o $@ $(compile_flags)
libadd.so : add.o
	@g++ -shared $^ -o $@
dynamic_lib : libadd.so
main.o : main.cpp
	@g++ -c $^ -o $@ $(compile_flags)
use_add : main.o 
	@g++ $^ -o $@ $(linking_flags)
all : dynamic_lib use_add
clean :
	@rm -rf *.o *.a *.so use_add
 
执行make all命令即可在当前目录下生成静态库libadd.so和可执行文件use_add。
 通过ldd use_add命令查看可执行程序依赖的动态链接库,打印如下:
linux-vdso.so.1 (0x00007ffd9dbc7000)
libadd.so => ./libadd.so (0x00007fc2e382d000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc2e3618000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc2e3426000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc2e32d7000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc2e3839000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc2e32bc000)
 
发现比链接静态库时多了一个libadd.so依赖库。
工程实践
包含子目录的工程
现有C++工程目录结构如下:
 
 add.h和add.cpp同上。
 subtract.h
int subtract(int a, int b);
 
subtract.cpp
#include "subtract.h"
int subtract(int a, int b)
{
    return a-b;
}
 
main.cpp
#include <iostream>
#include "add.h"
#include "subtract.h"
int main()
{
	std::cout << add(1, 2) << std::endl;
	std::cout << subtract(1, 2) << std::endl;
	return 0;
}
 
静态库的构建和链接
一个可以构建静态库的Makefile:(通过源文件构建可执行文件)
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -std=c++11 -I ./include
linking_flags := -l static -L ./
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
libstatic.a : $(lib_objs)
	ar -r $@ $^
static_lib : libstatic.a
main.o : main.cpp 
	g++ -c $^ -o $@ $(compile_flags)
test : main.o $(lib_objs)
	g++ $^ -o $@ 
all : static_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
或者(通过链接静态库构建可执行文件)
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -std=c++11 -I ./include
linking_flags := -l static -L ./
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
libstatic.a : $(lib_objs)
	ar -r $@ $^
static_lib : libstatic.a
main.o : main.cpp 
	g++ -c $^ -o $@ $(compile_flags)
test : main.o
	g++ $^ -o $@ $(linking_flags)
all : static_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
动态库的构建和链接
一个可以构建动态库的Makefile:(通过源文件构建可执行文件)
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -w -fPIC  -I ./include
linking_flags := -l dynamic -L ./ -Wl,-rpath=./
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
libdynamic.so : $(lib_objs)
	g++ -shared $^ -o $@
dynamic_lib : libdynamic.so
main.o : main.cpp 
	g++ -c $^ -o $@ $(compile_flags)
test : main.o $(lib_objs)
	g++ $^ -o $@ 
all : dynamic_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
或者(通过链接静态库构建可执行文件)
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -w -fPIC  -I ./include
linking_flags := -l dynamic -L ./ -Wl,-rpath=./
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
libdynamic.so : $(lib_objs)
	g++ -shared $^ -o $@
dynamic_lib : libdynamic.so
main.o : main.cpp 
	g++ -c $^ -o $@ $(compile_flags)
test : main.o 
	g++ $^ -o $@ $(linking_flags)
all : dynamic_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
既构建库又链接库的工程
现有C++工程目录结构如下:
 
 其中libadd.a和libadd.so可以通过上面的方法生成。
- 构建静态库(libstatic.a)并链接静态库(libadd.a):
Makefile会优先链接动态库,因此可以移除libadd.so来确保链接到libadd.a。 
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -std=c++11 -I ./include
linking_flags := -l static -L ./ -l add -L ./lib
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
libstatic.a : $(lib_objs) 
	ar -r $@ $^ 
static_lib : libstatic.a
main.o : main.cpp
	g++ -c $^ -o $@ $(compile_flags) 
test : main.o 
	g++ $^ -o $@ $(linking_flags)
all : static_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
- 构建动态库(libdynamic.so)并链接静态库(libadd.a):
 
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -w -fPIC  -I ./include
linking_flags := -l add -L lib -l dynamic -L ./ -Wl,-rpath=./
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
libdynamic.so : $(lib_objs)
	g++ -shared $^ -o $@
dynamic_lib : libdynamic.so
main.o : main.cpp
	g++ -c $^ -o $@ $(compile_flags) 
test : main.o 
	g++ $^ -o $@ $(linking_flags)
all : dynamic_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
- 构建静态库(libstatic.a)并链接动态库(libadd.so):
Makefile写法同1。 - 构建动态库(libdynamic.so)并链接动态库(libadd.so):
 
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -std=c++11 -I ./include
linking_flags := -l dynamic -L ./ -l add -L ./lib
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
libdynamic.so : $(lib_objs)
	g++ -shared $^ -o $@
dynamic_lib : libdynamic.so
main.o : main.cpp
	g++ -c $^ -o $@ $(compile_flags) 
test : main.o 
	g++ $^ -o $@ $(linking_flags)
all : dynamic_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
通过ldd命令查看依赖库,可以看到除了系统库外还需依赖libdynamic.so和libadd.so:
linux-vdso.so.1 (0x00007fff42cc6000)
libdynamic.so => ./libdynamic.so (0x00007f7d8b239000)
libadd.so => ./libadd.so (0x00007f7d8b234000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f7d8b01f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7d8ae2d000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7d8acde000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7d8b245000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f7d8acc3000)
 
- 把静态库libadd.a以及source合为另一个大的静态库:
先通过ar -x 命令将libadd.a解压为add.o,目前LZ尚未发现其他便捷做法。 
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -std=c++11 -I ./include
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
	ar -x lib/libadd.a
libstatic.a : $(lib_objs) add.o
	ar -r $@ $^ 
static_lib : libstatic.a
main.o : main.cpp
	g++ -c $^ -o $@ $(compile_flags) 
test : main.o libstatic.a
	g++ $^ -o $@ 
all : static_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
- 把静态库libadd.a以及source合为另一个大的动态库:
先通过ar -x 命令将libadd.a解压为add.o,目前LZ尚未发现其他便捷做法。 
lib_srcs := $(shell find ./source -name "*.cpp")
lib_objs := $(lib_srcs:.cpp=.o)
compile_flags := -g -O3 -w -fPIC  -I ./include
linking_flags := -l dynamic -L ./ -Wl,-rpath=./
source/%.o : source/%.cpp
	g++ -c $^ -o $@ $(compile_flags)
	ar -x lib/libadd.a
libdynamic.so : $(lib_objs) add.o
	g++ -shared $^ -o $@
dynamic_lib : libdynamic.so
main.o : main.cpp
	g++ -c $^ -o $@ $(compile_flags) 
test : main.o 
	g++ $^ -o $@ $(linking_flags)
all : dynamic_lib test
clean :
	rm -rf *.o source/*.o *.a *.so test
 
另外,linux系统下无法将动态库合入动态库或者静态库当中。
 欢迎阅读LZ的其他博文:CMake静态库动态库的构建和链接之工程实用篇

















