【问题标题】:Makefile to build shared libraryMakefile 构建共享库
【发布时间】:2014-07-18 15:43:23
【问题描述】:

我一直在构建一个 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.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 和符号链接 libChrono.so.1

我需要为很多子目录执行此操作,因此您可以看到,每当对标头/源进行更改时,这很快就会变得低效。如果有人可以帮助我设计一个只需调用 make 即可完成所有这些工作的 makefile,我将不胜感激。

谢谢!

更新:

根据 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 展开为一行。有什么想法吗?

【问题讨论】:

  • '如果有人能帮助我设计一个只需调用 make 即可完成所有这些工作的 makefile,我将不胜感激。' 抱歉,不!像往常一样,SO 不会为您的服务构建代码工厂。既不适用于 c++ 代码,也不适用于 makefile 编码。
  • 你有你需要的命令,只要把它放在makefile中。如果您根本不知道如何制作makefile,那么这个问题就很宽泛了。你可能想search for makefile tutorials

标签: c++ linux makefile


【解决方案1】:

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

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

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

GNU make 有一个 implicit rule 用于创建 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。只有必要的部分将被提取和编译。这使您不必在系统目录中维护一个共享库。

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

SO_FLAGS = -shared

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-27
    • 2017-10-21
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    • 2017-12-27
    相关资源
    最近更新 更多