Makefile构建共享库

时间:2014-07-18 15:43:23

标签: c++ linux makefile

我一直在构建一个C++11库,并且头文件/源文件的数量已经增长到编译程序调用它的程度,需要将20多个.cpp文件传递给{{ 1}}。我一直在阅读共享库,它似乎是最好的解决方案。

但是,由于标题/来源经常变化,我希望创建一个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.oSchedule.oDuration.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,我将不胜感激。

谢谢!

更新

基于goldilock的建议和一些挖掘,我设法一起敲打:

make

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。有什么想法吗?

1 个答案:

答案 0 :(得分:4)

幸运的是,你包含了问题的根源:

  

我一直在构建一个C ++ 11库,并且头文件/源文件的数量已经增长到编译程序调用它的程度,需要将20多个.cpp文件传递给g ++。

因为这揭示了潜在的XY problem。对此的直接解决方案是将目标文件放入存档(也称为静态库)并使用它。

GNU make有一个implicit rule用于创建C ++ .o文件。它相当于:

%.o: %.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<

意思是,如果你在一个没有重新定义它的makefile的目录中make DateTime.o,它将生成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的任何程序中。只提取和编译必要的部分。这样可以节省您在系统目录中维护共享库的过程。

如果您仍然认为自己需要共享库,则$@$^automatic variables;您可以使用类似的方法创建.so,类似于:

SO_FLAGS = -shared

libChrono.so.1.0.1: $(OBJS)
    $(CXX) $(SO_FLAGS) -Wl,-soname,libChrono.so.1 -o $@ $^ -lc

如果这是您的第一条规则,make将处理所有事情:首先构建对象,然后构建库。请注意,这个已经排除了您的正常$(CXXFLAGS)以完全复制问题中的编译器行。