静态库和动态库的构建和链接
现有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静态库动态库的构建和链接之工程实用篇