C++如何将多个静态库编译成一个动态库
静态库的使用
首先,定义两个class,分别编译成两个静态库:
第一个class:
foo.h
#ifndef FOO_H
#include <iostream>
#include <string>
class foo
{
private:/* data */std::string m_name;
public:foo(/* args */) {}~foo() {}void setName(const std::string& name);void printName();
};
#endif // !FOO_H
foo.cpp
#include "foo.h"
void foo::setName(const std::string& name) {m_name = name;
}
void foo::printName() {std::cout << m_name << std::endl;
}
第二个class:
bar.h
#ifndef BAR_H
#include<iostream>
#include<string>
class bar
{
private:/* data */std::string m_name;
public:bar(/* args */) {}~bar() {}void setName(const std::string& name);void printName();
};
#endif // !BAR_H
bar.cpp
#include "bar.h"
void bar::setName(const std::string& name) {m_name = name;
}
void bar::printName() {std::cout << m_name << std::endl;
}
Makefile如下:
libFoo:g++ -c -fPIC foo.cpp -o foo.oar rcs libFoo.a foo.o
libBar:g++ -c -fPIC bar.cpp -o bar.oar rcs libBar.a bar.o
注意,这里编译选项需要加上-fPIC,即生成位置无关代码,让编译出的代码不依赖于具体的内存加载地址,ar rcs用于将.o打包为静态库,基于此会生成两个静态库libFoo.a和libBar.a。接着我们写一个主函数通过静态库调用这两个类:
#include<iostream>
#include"foo.h"
#include"bar.h"
int main() {foo ufoo;bar ubar;ufoo.setName("foo");ubar.setName("bar");ufoo.printName();ubar.printName();return 0;
}
对应的Makefile:
static_main: libFoo libBarg++ -c main.cpp -I. -o main.og++ main.o -o static_main -L. -lFoo -lBar
-L包含静态库所在目录,-l包含了需要编译的两个静态库,静态库名字以lib开头才可以简化为-lFoo和-lBar否则的话则需要-l完整的名字。这样就可以生成最后的可执行程序static_main。
多个静态库编译为动态库
下面将两个静态库编译为一个动态库,对应Makefile:
libCombine: libBar libFoog++ -shared -fPIC -o libCombine.so \-L. -Wl,--whole-archive -lFoo -lBar \-Wl,--no-whole-archive
注意编译动态库需要加上-shared选项,同时还有-Wl,--whole-archive和-Wl,--no-whole-archive,两个都不能少,-Wl,--whole-archive表示强制链接器包含后续所有静态库的全部内容(关联参数,默认值包含被引用参数),链接完两个静态库之后,注意在通过-Wl,--no-whole-archive重置链接器行为,避免后续影响其他库。
最后基于动态库我们可以编译我们的可执行程序:
dynamic_main: libCombineg++ -c main.cpp -I. -o main.og++ main.o -o dynamic_main -L. -lCombine