【问题标题】:Extending a simple makefile to support different implicit compiler flags扩展一个简单的 makefile 以支持不同的隐式编译器标志
【发布时间】:2012-11-29 00:03:31
【问题描述】:

我一直在使用一个相当简单的生成文件。我用 .cc 文件列表定义了 OBJS。我设置了依赖项并包含标志并将所有这些附加到 $CXXFLAGS。它看起来像这样:

SRCS = file1.cc file2.cc file3.cc
OBJS = $(SRCS:.cc=.o)
CXXFLAGS=some flags
CXXFLAGS+=some include dirs
$(mylib.so): $OBJS
    $CXX -shared -o $@ $^

mylib.so 使用 CXXFLAGS(隐式)并且一切都构建得很好。

我最近需要 mylib_1.so 和 mylib_2.so,除了 mylib.so。每个 .so 都依赖于所有相同的 .cc 文件,但编译器标志都不同(包括包含目录)。

如何获取它以便可以根据目标 .so 设置编译器标志?我遇到的问题是,如果我多次设置 CXXFLAGS ,它就会被覆盖。这几乎就像我需要一个 if/else 情况。

我尝试设置三个不同的标志,$CXXFLAGS1、$CXXFLAGS2、$CXXFLAGS3,并使用行中的那些

$(mylib1.so): $OBJS
    $CXX $(CXXFLAGS1) -shared -o $@ $^

但这不起作用。

我如何完成我想做的事情?有 3 个单独的 makefile 会更好吗?我确实找到了让它工作的方法。我可以停止使用 $OBJS 并为每个源文件明确地拼出标志,但这在缩放到大小方面似乎是一个可怕的想法。

【问题讨论】:

  • 我应该注意到,在任何给定的构建中,只会创建三个 .so 中的一个。我不需要同时构建所有 3 个

标签: c++ makefile gnu-make


【解决方案1】:

您的示例中的 CXXFLAGS1 仅在创建 .so 文件的阶段使用,not 用于编译实际的 C++ 源代码(我假设这是您正在尝试做的事情)。

为实现上述目的,请考虑让 Makefile 为 3 个不同的目标调用自身 3 次,并将 CXXFLAGS(具有不同值)作为 MAKEFLAGS 的一部分或在命令行中传递。

更新:这是一个例子

全部:构建-lib1 构建-lib2 构建-lib3 构建-lib1: $(MAKE) $(MAKEFLAGS) CXXFLAGS="$(CXXFLAGS1)" lib1.so 构建-lib2: $(MAKE) $(MAKEFLAGS) CXXFLAGS="$(CXXFLAGS2)" lib2.so 构建-lib3: $(MAKE) $(MAKEFLAGS) CXXFLAGS="$(CXXFLAGS3)" lib3.so $(lib1.so): $OBJS $(CXX) -共享 -o $@ $^ ETC...

【讨论】:

  • 我的目标是避免在外面设置标志
  • 标志不会设置在外部 - 它们将在您的 Makefile 中,但此 Makefile 将在其自身上调用 make,有效地在该调用的命令行上传递 CXXFLAGS="$(CXXFLAGS1)"。
  • 哦,我想我明白你在说什么了。如果我将 $CXX $(CXXFLAGS1) -shared -o $@ $^ 更改为 $CXX CXXFLAGS="$(CXXFLAGS1)" -shared -o $@ $^ 它应该可以工作吗?
  • 不,这不是我说的。我的意思是:你有一个调用 3 个较低级别目标的顶级目标,例如“build-lib1”、“build-lib2”和“build-lib3”。目标“build-lib1”是假的,它的命令是:$(MAKE) $(MAKEFLAGS) CXXFLAGS="$(CXXFLAGS1)" lib1.so。其他 2 个目标也一样...
  • 行得通!但我意识到我的要求并不完全清楚。我想要基于构建(build-lib1、build-lib2 等)的不同目标文件。所以我正在改变 OBJS = $(SRCS:.cc=.o) --> OBJS1 = $(SRCS:.cc=1.o), OBJS2=$(SRCS:.cc=2.o)....但是,我仍在使用相同的源文件(file1.cc、file2.cc 等)。如何根据我选择的构建获得不同的目标文件名,以查看相同的源文件? make 抱怨它找不到 file11.cc 这对某些隐含规则有意义吗?
【解决方案2】:

Makefile 可以有target-specific variable values。比如:

$(mylib1.so): CXXFLAGS += -lib1flags
$(mylib2.so): CXXFLAGS += -lib2flags
$(mylib3.so): CXXFLAGS += -lib3flags

根据文档,标志将传播到先决条件目标。

目标特定变量还有一个特殊的特性:当 您定义了一个特定于目标的变量,该变量值也在其中 此目标的所有先决条件及其所有 先决条件等(除非这些先决条件覆盖该变量 具有自己的目标特定变量值)。因此,例如,一个 像这样的声明:

 prog : CFLAGS = -g
 prog : prog.o foo.o bar.o

将在 prog 的配方中将 CFLAGS 设置为“-g”,但它也会设置 在创建 prog.o、foo.o 和 bar.o 的配方中将 CFLAGS 设置为“-g”, 以及任何创建其先决条件的配方。

【讨论】:

  • 但相同的.o 文件需要采用不同的CXXFLAGS,具体取决于正在构建的最终目标。
  • 这是否意味着我可以执行以下操作:$(mylib.so): $OBJS CXXFLAGS += -lib1flags ?
【解决方案3】:

我会通过递归调用来做到这一点。我会使用两个makefile:

Makefile:

全部:mylib1.so mylib2.so SRCS := file1.cc file2.cc file3.cc mylib1.so: $(SRCS) 测试-d mylib1 || mkdir mylib1 $(MAKE) -f ../lib.mak -C mylib1 目标=mylib1.so CXXFLAGS=-DMYLIB=1 cp mylib1/mylib1.so mylib1.so mylib2.so: $(SRCS) 测试-d mylib2 || mkdir mylib2 $(MAKE) -f ../lib.mak -C mylib2 TARGET=mylib2.so CXXFLAGS=-DMYLIB=2 cp mylib2/mylib2.so mylib2.so

lib.mak,同一目录下:

VPATH = .. SRCS := file1.cc file2.cc file3.cc OBJS := $(SRCS:.cc=.o) $(目标): $(OBJS) $(CXX) -共享 -o $@ $^

第二个makefile实际上构建了库,但只使用了一组CXXFLAGS。主 makefile 使用单独的 CXXFLAGS 和在单独的目录中为每个版本调用第一个 makefile。 VPATH 使编译不在同一目录中的源文件变得更加容易。

我通过试运行测试了此设置,

测试-d mylib1 || mkdir mylib1 make -f ../lib.mak -C mylib1 TARGET=mylib1.so CXXFLAGS=-DMYLIB=1 make[1]: 进入目录`/home/depp/Maketest2/mylib1' g++ -DMYLIB=1 -c -o file1.o ../file1.cc g++ -DMYLIB=1 -c -o file2.o ../file2.cc g++ -DMYLIB=1 -c -o file3.o ../file3.cc g++ -shared -o mylib1.so file1.o file2.o file3.o make[1]: 离开目录`/home/depp/Maketest2/mylib1' cp mylib1/mylib1.so mylib1.so 测试-d mylib2 || mkdir mylib2 make -f ../lib.mak -C mylib2 TARGET=mylib2.so CXXFLAGS=-DMYLIB=2 make[1]: 进入目录`/home/depp/Maketest2/mylib2' g++ -DMYLIB=2 -c -o file1.o ../file1.cc g++ -DMYLIB=2 -c -o file2.o ../file2.cc g++ -DMYLIB=2 -c -o file3.o ../file3.cc g++ -shared -o mylib2.so file1.o file2.o file3.o make[1]: 离开目录`/home/depp/Maketest2/mylib2' cp mylib2/mylib2.so mylib2.so

【讨论】:

  • 如果我的要求是我只想在任何给定时间构建一个.so,你还会这样做吗?我将调用 make mylib1.so 或 make mylib2.so..etc。
  • @user1054424:是的,这样就可以了。 mylib1.somylib2.so 都是主 makefile 中的目标,因此您可以正常制作其中一个。
  • 这是否意味着每次添加新的源文件时都需要将其添加到 lib.mak 和 Makefile 中?
  • @user1054424:你可以这样做。或者您可以将变量定义放在单独的 makefile 中,include 将 makefile 与其他两个 makefile 分开。或者您可以使用SRCS := $(wildcard *.cc),如果您同意的话。或者您甚至可以从主 makefile 中完全消除它。很多选择。
  • 有没有办法从一个makefile中完成这个?如果可能的话,那将是理想的..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 2021-12-10
  • 2013-03-09
  • 1970-01-01
  • 2011-04-27
相关资源
最近更新 更多