我有一个项目,我需要以相同的方式处理许多文件。我的 GNUMakefile 看起来像这样:
$(SOURCES) = file1.a file2.a file3.a ... fileN.a
$(TARGETS) = $(SOURCES:.a=.b)
%.b: %.a
build-tool $?
all: $(TARGETS)
Run Code Online (Sandbox Code Playgroud)
这个 makefilebuild-tool为每个目标执行,这很慢。所以我希望它只执行build-tool一次并列出所有更新的先决条件。
我尝试添加以下规则:
$(TARGETS): $(SOURCES)
Run Code Online (Sandbox Code Playgroud)
它有助于第一次构建这样的:
$ make all
build-tool file1.a file2.a ... fileN.a
Run Code Online (Sandbox Code Playgroud)
但是在随后的构建build-tool中执行的次数与我拥有的目标一样多:
$ touch file1.a && make all
build-tool file1.a
build-tool file1.a
...
build-tool file1.a
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我将 recipe 更改为build-tool $@它会在所有情况下使用所有先决条件执行一次 build-tool,这也是不可取的。
是否有一些方法可以为所有目标只执行一次配方,即在第一次构建时使用所有先决条件,并且只在后续构建中修改?
我知道我可以使用$@makefile 中目标内的自动变量来检索当前目标的名称。现在我想知道是否有可能有一个看起来像这样的 makefile:...
$@:
g++ $@ && ./a.out
Run Code Online (Sandbox Code Playgroud)
这个想法是打字make test.cpp应该g++ test.cpp && ./a.out在应该运行的地方make main.cpp运行g++ main.cpp && ./a.out。
我看到通配符可能与我的问题密切相关。但是,像这样的makefile:
*.cpp:
g++ $@ && ./a.out
Run Code Online (Sandbox Code Playgroud)
确实创建了适当的目标,但是make test.cpp使用这样的 makefile运行会产生make: >>test.cpp<< is already up-to-date- 没有进行编译。
鉴于master.makefile调用子makefile,例如:
downloads:
make -f downloads.makefile
Run Code Online (Sandbox Code Playgroud)
还有一个子makefile,downloads.makefile例如:
download: clean
curl -o ./data/<itemname>.png 'http://www.mysite.com/<itemname>.png'
echo "downloaded <itemname>: Done!"
Run Code Online (Sandbox Code Playgroud)
如何itemname在我的主文件中设置一个全局变量,可用于我的子制作文件?
注意:我的项目实际上更复杂,有 12 个不同的子 makefile,它们应该重用来自主文件的相同参数/变量。masterfile 应该分配值,而 sub-makefile 应该检索我放置的变量的值<itemname>。
我想根据当前目录中的默认 makefile 是否包含某个目标在 shell 中运行某些操作。
#!/bin/sh
make -q some_target
if test $? -le 1 ; then
true # do something
else
false # do something else
fi
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为如果目标不存在,GNU make 会返回错误代码 2,否则返回 0 或 1。问题是没有以这种方式记录。这是男人的一部分:
-q, --question
``Question mode''. Do not run any commands, or print anything;
just return an exit status that is zero if the specified targets
are already up to date, nonzero otherwise.
Run Code Online (Sandbox Code Playgroud)
仅区分零/非零。这样做的正确方法是什么?
是否可以“安全地”扩展 makefile 中的变量,转义 makefile 认为特殊的所有字符?
例如,假设一个变量被用作目标:
${external_chaos}:
dd if=/dev/zero of=${external_chaos}
Run Code Online (Sandbox Code Playgroud)
(例如故意的戏剧)
如果external_chaos包含空格、;、#、:、,或其他 makefile 重要字符,那么整个规则就会混乱。
我想象的解决方案是一些应该执行此操作的 Make 内置函数,例如${escape external_chaos}(想象中的奢侈品)。
${value external_chaos} 不这样做。
我在一个文件夹中有一个 GNUMakeFile(具有该名称),还有一个run.bat写入标准输出的批处理文件。
如何从 GNUMakeFile 调用该批处理文件?
我试过了,@CALL run.bat但似乎不支持 CALL 命令。
cmd run.bat 只是将 cwgwin 终端置于一种“混合 DOS 状态”。
是否有输出“预处理”makefile 的-E选项,相当于 GCC 的选项?
我有一个项目由几十个模块的层次结构组成,每个模块都有自己的 makefile。构建是从主生成文件调用的。该主 makefile 包含包含、变量定义、命令行选项因变量等。
所以,本质上,我正在寻找处理过的 makefile,包括所有替换。
%.c和*.cmakefile 中有什么区别。例如我们可能有:
vpath %.c $(BASE_DIR)platform/$(TARGET)
Run Code Online (Sandbox Code Playgroud)
和
Files += $(wildcard *.c)
Run Code Online (Sandbox Code Playgroud)
两者都包含某个目录中以 .c 结尾的所有文件。但是我们什么时候使用%.c,*.c什么时候使用?换句话说,为什么我不能使用
vpath *.c $(BASE_DIR)platform/$(TARGET)
Run Code Online (Sandbox Code Playgroud)
代替
vpath %.c $(BASE_DIR)platform/$(TARGET)
Run Code Online (Sandbox Code Playgroud)
?
谢谢你。
Gnu Makefile 显示了两个用于立即扩展的符号,如下所示:
immediate := immediate
immediate ::= immediate
Run Code Online (Sandbox Code Playgroud)
这两者有区别吗?
参考:gnu makefile 手册第 3.7 节
试图找到在makefile. 底部显示了我的简单makefile.
线条 $(info aaa)打印aaa良好。但是线 echo 'aaa'会产生错误*** missing separator
是否可以使用 echo in 打印信息makefile?
CC=gcc
CFLAGS=-I.
DEPS = f1.h,hellomake.h
echo 'aaa'
$(info aaa)
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
hellomake: hellomake.o hellofunc.o f1.o
gcc -o hellomake hellomake.o hellofunc.o f1.o -I.
Run Code Online (Sandbox Code Playgroud)