gpt4 book ai didi

c++ - Makefile 构建共享库

转载 作者:太空狗 更新时间:2023-10-29 11:44:37 34 4
gpt4 key购买 nike

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

但是,由于 header /源代码经常更改,我希望创建一个 makefile,它会自动从 header 和源代码生成所有 .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.oDayCount.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 和符号链接(symbolic link) libChrono.so.1

我需要为相当多的子目录执行此操作,因此您可以看到,只要对 header /源进行更改,这就会迅速变得低效。如果有人能帮我设计一个 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。有什么想法吗?

最佳答案

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

I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++.

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

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

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

意思是,如果您在一个目录中制作 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) 以完全复制问题中的编译器行。

关于c++ - Makefile 构建共享库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24829006/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com