我必须在现有的 .html 文件中集成许多 HTML 文件的生成Makefile。问题是 HTML 文件需要驻留在许多不同的目录中。我的想法是写一个隐式规则,将源文件(*.st)转换成对应的html文件
%.html: %.st
$(HPC) -o $@ $<
Run Code Online (Sandbox Code Playgroud)
以及依赖于所有 html 文件的规则
all: $(html)
Run Code Online (Sandbox Code Playgroud)
如果 HTML 文件不在 builddir 中,则make找不到隐式规则:*** No rule to make target. 如果我像这样更改隐式规则
$(rootdir)/build/doc/2009/06/01/%.html: %.st
$(HPC) -o $@ $<
Run Code Online (Sandbox Code Playgroud)
它找到了,但是我必须对项目中的几乎每个文件都有一个隐式规则。根据GNU手册中的隐式规则搜索算法make,规则搜索的工作方式如下:
- 将整个目标名称t拆分为目录部分,称为d,其余部分称为n。例如,如果t是
src/foo.o,则d是src/,而n是foo.o。- 列出其中一个目标与t或n匹配的所有模式规则。如果目标模式包含斜杠,则与t匹配;否则,针对n。
为什么没有找到隐式规则,假设使用 GNU,最优雅的解决方案make是什么?
这是我的精简版Makefile: …
我有一个 makefile,当使用旧版本的 gmake 时,它会出现不明显的故障。我想有一个规则来检查版本至少是 3.82 或更高版本。我已经得到了以下规则,但比较是脆弱的,我真的想要一个允许更高版本的比较:
GMAKE_VERSION := $(shell gmake --version | head -n 1 | sed 's/GNU Make //')
.PHONY: testMake
testMake:
@if [ "$(GMAKE_VERSION)" != "3.82" ]; \
then \
echo >&2 "Unexpected gmakefile version " \
"$(GMAKE_VERSION), expecting 3.82 or later."; \
false; \
fi
Run Code Online (Sandbox Code Playgroud)
什么GNU makefile规则可以保证make的版本至少是v3.82?
我的构建系统坚持在一次调用中对所有目标执行 make,所以我得到:
make clean test clean build
第二次清理只会说“没有为‘清理’做任何事情。” 即使它已添加到 .PHONY 目标。
有什么办法吗?
这是我的makefile:
all: first second
second:
@echo "==Building second=="
first:
@echo "==Building first=="
Run Code Online (Sandbox Code Playgroud)
如果存在名为的目录second,则makefile将完全忽略具有相同名称的规则.如果没有,一切正常.
请注意,无论second文件夹是否为Makefile,都会发生这种情况.
我在组织我的项目时遇到了这个问题:我考虑创建一个通用的Makefile,然后在每个目录中调用Makefile.所以对我来说,规则与文件夹的名称相同是很自然的.
解决方案很简单:更改Makefile中的规则名称...但这种行为似乎很奇怪:你对此有什么想法/见解,还有另一种可能的解决方案吗?
我在Ubuntu 12.04.2 LTS下使用Bash 4.2.25中的GNU Make 3.81.
我有 //here/is$/my/file(注意$)作为文件位置,并在GNUmakefile中指定
OutputFile = //here/is$/my/file
Run Code Online (Sandbox Code Playgroud)
问题是我需要以某种方式逃避$.我试过了\ $没有成功.
有谁知道如何做到这一点?
我想在 Makefile 中执行一个命令,将结果存储到一个变量中并稍后重用该结果。
在 BSD Makefile 中,我可以使用 != 运算符:
PASSWORD != openssl rand -base64 48
Run Code Online (Sandbox Code Playgroud)
在 GNU Makefile 中,我可以使用 shell 函数:
PASSWORD := $(shell openssl rand -base64 48)
Run Code Online (Sandbox Code Playgroud)
有没有办法以与两个 make 兼容的方式编写它?
预期输出
在这两种情况下,命令的结果都分配给 PASSWORD,因此我可以在 Makefile 中重用相同的 PASSWORD 值:
quux:
@echo $(PASSWORD)
@echo $(PASSWORD)
Run Code Online (Sandbox Code Playgroud)
如果我运行make quux,这将输出两次相同的密码。
例如:
$ gmake quux
Y0ZrQQqLF9JK98x9UiIwWwcCN2Cq1wNqzph3ShG1RK0NeqbxWn6p4XB5zgHvfnbY
Y0ZrQQqLF9JK98x9UiIwWwcCN2Cq1wNqzph3ShG1RK0NeqbxWn6p4XB5zgHvfnbY
Run Code Online (Sandbox Code Playgroud)
这与使用反引号运算符不同。在这种情况下,兼容两个make,每次都会运行命令。
在GNU-Make手册中,如何制作读取制作文件 https://www.gnu.org/software/make/manual/make.html#Reading-Makefiles部分说
GNU make在两个不同的阶段完成它的工作.在第一阶段,它读取所有makefile,包括makefile等,并内化所有变量及其值,隐式和显式规则,并构建所有目标及其先决条件的依赖关系图.在第二阶段,make使用这些内部结构来确定需要重建的目标,并调用执行此操作所需的规则.
我无法清楚地了解这两个阶段的差异.可能正在寻找一个有助于理解的例子.是否有任何链接或教程阐明了第一阶段和第二阶段到底发生了什么.
我不知道有什么方法可以在 GNU Make 中以编程方式定义目标。这怎么可能?
有时可以使用替代方法离开。然而,在 Makefile 中以编程方式定义目标的能力对于使用make. 在 FreeBSD 的构建系统或诸如BSD Owl 之类的Makefile 库中可以找到复杂生成规则的示例
shell 脚本和 Makefile 之间的主要区别是:
在 Makefile 中,程序的状态由命令行和文件系统给出,因此可以在作业中断后恢复作业。当然,这需要正确地编写 Makefile,但即使这相当困难,也比使用 shell 脚本实现类似的效果要容易得多。
在 Makefile 中,用建议或钩子装饰一个过程是非常容易的,而这在 shell 脚本中基本上是不可能的。
例如,一个非常简单且有用的模式如下:
build: pre-build
build: do-build
build: post-build
Run Code Online (Sandbox Code Playgroud)
这将build目标呈现为三个目标的组合,一个包含实际指令do-build,另外两个是钩子,在 之前和之后执行do-build。许多为 BSD Make 编写的构建系统都使用这种模式,顺便说一下,它允许以编程方式定义目标,以便可以批量编写:
.for _target in configure build test install
.if !target(${_target})
${_target}: pre-${_target}
${_target}: do-${_target}
${_target}: post-${_target}
.endif
.endfor
Run Code Online (Sandbox Code Playgroud)
.if/.endif块引入的条件使用户能够使用自己对 any 的定义${_target}。
GNU Make 的那个片段的翻译是什么?
在qmake的Makefile中,定义了一系列变量。我想再添加一个,由.pro文件定义。Makefile中的此部分如下所示:
DEL_DIR = rmdir
MOVE = mv -f
CHK_DIR_EXISTS= test -d
MKDIR = mkdir -p
Run Code Online (Sandbox Code Playgroud)
我想补充:
TESTARGS = -xunitxml -o xunitresults.xml
Run Code Online (Sandbox Code Playgroud)
关于原因的一些背景知识:当qmake使用“测试用例”创建Makefile时,它还会使“检查”目标看起来像这样:
check: first
$(TESTRUNNER) ./$(QMAKE_TARGET) $(TESTARGS)
Run Code Online (Sandbox Code Playgroud)
在这里完整记录。
这对于自动单元测试确实非常强大!但是,我想在make文件的其他位置设置“ TESTARGS”。我怎样才能做到这一点?
我最近从Window 7迁移到Windows 10,无法继续使用我的makefile。
我注意到的第一件事是它已开始将Windows文件夹分隔符(反斜杠字符“ \”)视为行继续字符,因此我修改了“ clean”部分,如下所示,改为使用正斜杠“ /”字符:
clean:
del $(ObjDir)/*.o
Run Code Online (Sandbox Code Playgroud)
当我打电话时make -ftest.mak clean,出现以下错误,这表明它现在正试图在MinGw / Cygwin环境中运行:
c:\Test\Source>make -ftest.mak clean
del obj/*.o
/usr/bin/sh: del: command not found
make: *** [clean] Error 127
Run Code Online (Sandbox Code Playgroud)
我的PC上确实有MinGw文件夹(已重命名以停止寻找它),并且在Cmd.exe环境或PATH中看不到任何与“ MingGw”相关的环境变量
我如何才能make工作,这样它就不会尝试sh在Windows下执行?
是否有一些配置参数可以调用它sh而不是cmd.exe?
更新:刚刚尝试运行make -d来记录调试输出。好像它使用我的Git文件夹作为某种根文件夹:
Must remake target `clean'.
del obj/*.o
CreateProcess(NULL,C:/Program Files/Git/usr/bin/sh.exe -c "del obj/*.o",...)
Putting child 0x006e7fc0 (clean) PID 7234712 on the chain.
Run Code Online (Sandbox Code Playgroud)