如何确保使用多个 MAKE 目标的 Makefile 中的正确设置来编译目标文件
我有一个小项目,它从相同的源文件构建多个目标。目标需要使用不同的编译标志构建源文件。这实际上是在 cygwin 上,所以我将使用它作为具体示例,尽管我认为这是一个普遍问题。
因此,这将是一个示例 Makefile:
a: CFLAGS =
a: a.o c.o
b: CFLAGS = -mno-cygwin
b: b.o c.o
原则上,构建 a 将在未设置 CFLAGS 的情况下进行编译,而构建 b 将在 CFLAGS 设置为 -mno-cygwin 的情况下进行编译。但前提是 co 尚不存在。
因此,
> make a b
在原始目录中执行操作将首先使用空 CFLAGS 编译 ac 和 cc。然后它将尝试使用 CFLAGS=-mno-cygwin 构建 b。但由于 co 已经存在,因此不会重新编译 cc,从而导致链接器错误,因为目标文件需要具有相同的此标志设置。
同样,cygwin-flag 只是一个具体的例子,我正在寻找一种通用的解决方案。
我尝试的是引入一个额外的目标来检查当前的 CFLAGS,并在不匹配时删除所有目标文件:
ARCH = `echo $(CFLAGS)`
checkTarget:
-@if test "`cat .arch`" != "$(ARCH)"; then \
rm *.o; \
/bin/echo -n $(ARCH) > .arch; \
fi
插入此目标作为两个目标的依赖项可确保在需要时重新编译所有目标文件。
a: CFLAGS =
a: checkTarget a.o c.o
b: CFLAGS = -mno-cygwin
b: checkTarget b.o c.o
然而,这会重新编译每个目标文件,这是不必要的,并且在较大的项目中会成为一个问题。
有更好的方法吗?
编辑: 在对单个答案的评论中包含一个提示,即您可以使目标文件依赖于 CFLAGS 的内容。我不知道如何做到这一点,除了将它们放入临时文件并与以前的文件进行比较,然后将其复制到依赖文件上。难道就没有更好的办法了吗?
I have a small project that builds a number of targets from the same source files. The targets require building the source files with different compile flags. This is actually on cygwin so I'll use that as the concrete example although I suppose this is a generic problem.
So this would be an example Makefile:
a: CFLAGS =
a: a.o c.o
b: CFLAGS = -mno-cygwin
b: b.o c.o
This works in principle, building a will compile with CFLAGS unset, and building b will compile with CFLAGS set to -mno-cygwin. But only if c.o does not already exist.
So doing
> make a b
in a virgin directory will first compile a.c and c.c using an empty CFLAGS. Then it will try to build b using CFLAGS=-mno-cygwin. But since c.o already exists it will not recompile c.c resulting in linker errors since object files need to have the same setting of this flag.
Again, the cygwin-flag is just one concrete example, and I am looking for a generic solution.
What I have tried is to introduce an extra target checking the current CFLAGS and remove all object files if it does not match:
ARCH = `echo $(CFLAGS)`
checkTarget:
-@if test "`cat .arch`" != "$(ARCH)"; then \
rm *.o; \
/bin/echo -n $(ARCH) > .arch; \
fi
Inserting this target as a dependency for the two targets ensures that all object files are recompiled if required.
a: CFLAGS =
a: checkTarget a.o c.o
b: CFLAGS = -mno-cygwin
b: checkTarget b.o c.o
This however recompiles every object file, which is unnecessary, and becomes a problem in a larger project.
Is there a better way to do this?
EDIT:
In the comments to the single answer included a hint that you could make the object files depend on the content of the CFLAGS. I can't figure out how to do that, except cat'ing them to a temporary file and compare to the previous ones and then copy that over a depending file. Is there no better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里我们需要的是
co
的两个(或更多)版本,使用不同的标志进行编译并链接到不同的可执行文件中。您可以使用像c_for_a.o
这样的人为文件名来完成此操作,但将它们保存在不同的目录for_a/
和for_b/
中会更整洁:(如果不清楚,我可以填写 Makefile 的其余部分。)
编辑:
如果您不想保留多个
co
,有时您必须重新编译co。checkTarget
的想法可能有一个小的改进。当您构建像
b
这样的目标,并且co
已经存在时,co
是否是使用CFLAGS 适合于
b
,并且您使用checkTarget
来记录该信息。 但是您并不关心使用了什么CFLAGS
,只关心它们是否是b
的CFLAGS
。因此,您不必在checkTarget
文件中记录任何内容,只需在构建新目标时更新它即可:What we need here is two (or more) versions of
c.o
, compiled with different flags and to be linked into different executables. You could do this with contrived filenames likec_for_a.o
, but it's tidier to keep them in different directories,for_a/
andfor_b/
:(If this isn't clear I can fill in the rest of the Makefile.)
EDIT:
If you don't want to keep multiple
c.o
's, you will have to recompile c.o sometimes. There is a small improvement possible on thecheckTarget
idea.When you are building a target like
b
, andc.o
already exists, it matters whether thatc.o
was built with theCFLAGS
suited tob
, and you usecheckTarget
to record that information. But you don't care whatCFLAGS
were used, only whether they wereb
'sCFLAGS
. So you don't have to record anything in thecheckTarget
file, just update it when you build a new target:尽管有一些关于如何执行我最初要求的建议 这里(正如slowdog所指出的),我决定采取< a href="https://stackoverflow.com/users/128940/beta">Beta 的 different-names-schema 更进一步,将各种变体的所有对象放入 Beta 在回答 这个问题。
本质上,这使我的 Makefile 看起来像:
所以第一部分命名一个用于“a”的目标文件的子目录,并通过转换源文件名并添加子目录前缀在该目录中创建目标文件列表。
然后遵循这些对象文件的默认规则(为了更好的措施而引入依赖项生成)。
接下来的两个是确保子目录存在,并且包含依赖关系信息。
最后,链接规则对子目录本身具有额外的依赖性,以确保在子目录不存在时创建它。
在我的示例中,可以通过交换所有 a 来重复此块。因此,如果我能弄清楚如何将这个块打包成可以参数化的更通用的东西,我会很高兴。
Although there where some suggestions on how to do what I initially asked for here (as pointed to by slowdog), I took the decision to take Beta's different-names-schema one step further and put all objects for the various variants in subdirectories following the description in Beta's second suggestion in his answer to this question.
In essence that made my Makefile look like:
So the first part names a subdirectory to be used for object files of 'a' and creates a list of object files in that directory by converting the source filenames and adding the subdirectory prefix.
Then follows the default rule for those object files (with dependency generation thrown in for good measure).
Next two are ensuring that the subdirectory exists, and that the dependency information is included.
Finally the link rule with an extra dependency on the subdirectory itself to ensure that it is created if it does not exist.
This block can be repeated for b, in my example, by exchanging all a's. So if I only could figure out how to package this block into something more general that can be parameterized I would be happy.