Makefile 构建共享库

Alm*_*ely 3 c++ linux makefile

我一直在构建一个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
Run Code Online (Sandbox Code Playgroud)

这样我现在在当前目录中有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
Run Code Online (Sandbox Code Playgroud)

那我去,

$ rm ./*.o && ldconfig -n ./
Run Code Online (Sandbox Code Playgroud)

这样我的工作目录现在就包含libChrono.so.1.0.1了 symlink libChrono.so.1

我需要为很多子目录执行此操作,因此您可以看到,每当对标题/源进行更改时,这会迅速变得效率低下。如果有人能帮助我设计一个生成文件,只需调用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 $@
Run Code Online (Sandbox Code Playgroud)

.o生成了4 个文件,lib/但我从ld. 在我单独编译目标文件之前,但这CHRONOOBJ在一行上展开。有任何想法吗?

del*_*ver 5

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

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

因为这揭示了一个潜在的XY 问题。对此的直接解决方案是将目标文件放入存档(又名静态库)中并使用它。

GNU make 有一个创建 C++文件的隐含规则.o。它相当于:

%.o: %.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
Run Code Online (Sandbox Code Playgroud)

意思是,如果您make DateTime.o在一个目录中的 makefile 没有重新定义它,它将 make DateTime.o$(CXXFLAGS)但是,您可能想要添加一些内容,例如:

CXXFLAGS += -Wall -Wextra --std=c++11
Run Code Online (Sandbox Code Playgroud)

如果您打算坚持使用共享库路线,-fPIC也可以去那里。那一行可能是您的整个 makefile。

但是,您还想将它们放在一起,因此您必须首先声明所有对象和组合它们的规则:

OBJS = DateTime.o Schedule.o Duration.o

libChrono.a: $(OBJS)
    ar crvs $@ $^
Run Code Online (Sandbox Code Playgroud)

最后一行(请参阅man ar参考资料)创建了包含$(OBJS). 然后,您可以将它与任何程序一起使用,方法是将其放置在同一目录(或库路径中的目录)中并链接-lChrono. 只有必要的部分将被提取和编译。这使您不必在系统目录中维护共享库。

如果你仍然认为你需要一个共享库,$@并且$^自动变量;您可以使用类似的方法来创建一个.so,类似的东西:

SO_FLAGS = -shared

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

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