Makefile构建共享库
Makefile to build shared library
我一直在构建一个C++11
库,并且头文件/源文件的数量已经增长到编译程序调用它的程度,需要将20多个.cpp
文件传递给g++
。我一直在研究共享库,它似乎是最好的解决方案。
然而,由于头/源频繁变化,我希望创建一个makefile
,它将自动从头和源生成所有.so
文件。
为了更好地演示我要做的事情,我将使用我的一个子库Chrono
,并展示我如何手动执行此操作。
我首先像这样创建目标文件,
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DateTime.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Schedule.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Duration.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DayCount.cpp
所以我现在有DateTime.o
, Schedule.o
, Duration.o
和DayCount.o
在当前目录。然后创建.so
文件
$ g++ -shared -Wl,-soname,libChrono.so.1 -o libChrono.so.1.0.1 DateTime.o Schedule.o Duration.o DayCount.o -lc
然后,
$ rm ./*.o && ldconfig -n ./
所以我的工作目录现在包含libChrono.so.1.0.1
和符号链接libChrono.so.1
。
有相当多的子目录我需要这样做,所以你可以看到,无论何时更改头/源,这很快变得低效。如果有人能帮助我设计一个makefile,通过调用make
来完成所有这些,我将不胜感激。
谢谢!
更新:
根据goldilock的建议和一些挖掘,我设法拼凑起来:
CXX=g++
CFLAGS=-std=c++11
TARGET=./lib/libChrono.so.1.0.1
CHRONODIR=./src/Chrono
CHRONOSRC=$(wildcard $(CHRONODIR)/cpp/*.cpp)
CHRONOOBJ=$(join $(addsuffix ../obj/, $(dir $(CHRONOSRC))), $(notdir (CHRONOSRC:.cpp=.o)))
all: $(TARGET)
@true
clean:
@-rm -f $(TARGET) $(CHRONOOBJ)
./lib/libChrono.so.1.0.1: $(CHRONOOBJ)
@echo "======================="
@echo "Creating library file $@"
@echo "======================="
@$(CXX) -shared -Wl,-soname,$(join $(basename $@), .1) -o $@ $^ -l
@echo "-- $@ file created --"
$(CHRONODIR)/cpp/../obj/%.o : $(CHRONOSRC)
@mkdir -p $(dir $@)
@echo "============="
@echo "Compiling $<"
@$(CXX) $(CFLAGS) -fPIC -g -Wall -c $< -o $@
4 .o
文件是在lib/
中产生的,但我从ld
中得到了多个定义投诉。在我单独编译目标文件之前,这将在一行上展开CHRONOOBJ
。什么好主意吗?
幸运的是你包括了问题的根源:
我一直在构建一个c++ 11库,头文件/源文件的数量已经增长到编译程序调用它的程度,需要将20多个.cpp文件传递给c++。
因为这揭示了一个潜在的XY问题。直接的解决方案是将目标文件放入归档文件(也称为。一个静态库)并使用它。
GNU make有一个隐式规则用于创建c++ .o
文件。它相当于:
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
意思是,如果你把make DateTime.o
放在一个没有重新定义这个的makefile的目录中,它将生成DateTime.o
。然而,你可能想在$(CXXFLAGS)
中添加一些东西,例如:
CXXFLAGS += -Wall -Wextra --std=c++11
如果您打算坚持使用共享库路由,-fPIC
也可以去那里。这一行可以是你的整个makefile。
然而,你也想把它们放在一起,所以你必须首先声明所有的对象和一个组合它们的规则:
OBJS = DateTime.o Schedule.o Duration.o
libChrono.a: $(OBJS)
ar crvs $@ $^
最后一行(参见man ar
)创建了包含$(OBJS)
中所有对象的归档文件(libChrono.a)。然后,您可以将它放在相同的目录中(或库路径中的目录)并链接-lChrono
,从而对任何程序使用它。只有必要的部分将被提取和编译。这节省了在系统目录中维护共享库的时间。
如果你仍然认为你需要一个共享库,$@
和$^
是自动变量;您可以使用类似的方法创建.so
,类似于:
SO_FLAGS = -shared
libChrono.so.1.0.1: $(OBJS)
$(CXX) $(SO_FLAGS) -Wl,-soname,libChrono.so.1 -o $@ $^ -lc
如果这是你的第一条规则,make
将照顾一切:首先构建对象,然后是库。请注意,这个问题已经排除了正常的$(CXXFLAGS)
,以完全复制问题中的编译器行。
- 为什么构建目录中新构建的共享库与安装目录中的副本具有不同的依赖项集?
- 在OSX上使用CMake将Adobe的XMP工具包构建为共享库的最简单方法是什么?
- 用于构建 cuda .so 文件(共享库)的生成文件
- 为 Python 构建共享库C++时出现分段错误
- 如何使用 CMake 在 android 构建上编译和共享两个 c++ 库
- 如何在 Linux 中构建共享库时使未定义引用的链接器失败
- 如何使用 cmake 在代码中包含、构建和调试共享库 (.so)?
- 如何防止 CMake 在构建时(而不是在安装时)为共享库创建符号链接?
- 从单个.cpp构建共享对象
- 使用 pybind11 构建库,链接其他共享库
- 从静态库构建共享库
- 使用 Makefile 构建共享库
- 我可以在Embarcadero C 建造者中为Android(*.so)构建共享库
- 构建本身是共享_ptr类型的模板容器
- 尝试与从 CUDA 对象构建的共享库链接时未定义的符号
- setuptools:从C++代码构建共享库,然后构建链接到共享库的 Cython 包装器
- 构建共享对象 - 使用 Ninja 编译适用于 OSX 和 Windows 上的 Ubuntu Crush
- 使用boost :: python手动构建共享对象
- 在我的CMake项目中使用静态构建而不是OpenCV的共享构建
- Qt保持构建共享构建无论我选择什么选项