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在一行上展开。有任何想法吗?
幸运的是,您包含了问题的根源:
我一直在构建一个 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)以从问题中完全复制编译器行。