我正在寻找建议以在递归 makefile 系统中正确处理单独的调试和发布构建子目录,该系统使用 gnumake 手册中记录的 $(SUBDIRS) 目标将 make 目标应用于(源代码)子目录。
具体来说,我对实现“all”、“clean”、“realclean”等目标的可能策略很感兴趣,这些目标要么假设其中一棵树要么应该在两棵树上都工作导致问题。
我们当前的 makefile 使用一个 COMPILETYPE 变量,该变量被设置为 Debug(默认)或 Release('release' 目标),它正确地执行构建,但清理和 make all 仅适用于默认的 Debug 树。传递 COMPILETYPE 变量变得笨拙,因为是否以及如何执行此操作取决于实际目标的值。
看看隐含规则目录,有几个陈述让我想知道:
默认后缀列表为:.out、.a、.ln、.o、.c、.cc、.C、.cpp、.p、.f、.F、.m、.r、.y、.l 、.ym、.lm、.s、.S、.mod、.sym、.def、.h、.info、.dvi、.tex、.texinfo、.texi、.txinfo、.w、.ch .web 、.sh、.elc、.el。下面描述的所有先决条件具有这些后缀之一的隐式规则实际上都是后缀规则。
嗯,不是吗?
$ make -p -f/dev/null | grep '%.o: %\.c$' -A2
%.o: %.c
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
Run Code Online (Sandbox Code Playgroud)
后缀.c在列表中但它被定义为模式规则?
好吧,它还定义了一个后缀规则:
make -p -f/dev/null | grep '^.c.o:' -A5
.c.o:
# Implicit rule search has not been done.
# Modification time never checked.
# File has not been updated.
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
Run Code Online (Sandbox Code Playgroud)
但为什么?
后缀规则在模式规则之后定义。那么模式规则应该优先,对吧?
但既然行动是平等的,那还有什么意义呢?
假设以下文件与 makefile 位于同一目录中:
01.1.dot
01.2.dot
02.1.dot
03.1.dot
03.2.dot
03.3.dot
Run Code Online (Sandbox Code Playgroud)
这意味着我们有 [0-9][0-9].[0-9].dot 形式的文件
此外,makefile 包含以下目标:
%.dot.tex: %.dot
dot2tex <...>
Run Code Online (Sandbox Code Playgroud)
现在我想创建一个依赖于 [0-9][0-9].tex 形式的文件的目标,并且它们还应该依赖于 [0-9][0-9].* 形式的所有文件.dot.tex,使得前两位数字匹配。例如,应make 03.pdf依赖于03.tex、03.1.dot.tex和03.2.dot.tex。03.3.dot.tex我想出了以下几点:
%.pdf: %.tex $(addsuffix .tex,$(wildcard %.*.dot))
@echo $?
pdflatex <...>
Run Code Online (Sandbox Code Playgroud)
但是,通配符函数中不会计算百分比。有人知道如何解决这个问题吗?
我正在编写一个需要定义一些环境变量的 makefile。我正在尝试使用这样的东西来实现这一目标:
define check-var-defined
ifndef $(1)
$(error $(1) is not defined)
endif
endef
$(call check-var-defined,VAR1)
$(call check-var-defined,VAR2)
$(call check-var-defined,VAR3)
rule1:
#stuff
Run Code Online (Sandbox Code Playgroud)
当我运行不带参数的 make 时,我得到:
$ make
Makefile:7: *** VAR1 is not defined. Stop.
Run Code Online (Sandbox Code Playgroud)
但是当我使用指定的 VAR1 运行它时,我得到了同样的错误。
$ make VAR1=hello
Makefile:7: *** VAR1 is not defined. Stop.
Run Code Online (Sandbox Code Playgroud)
有什么想法为什么这行不通吗?我该怎么做才能使这项工作成功?提前致谢。
(请注意,我需要检查运行 makefile 时是否实际定义了变量,因为我需要进一步包含另一个 makefle,并且在执行此操作时需要正确设置变量)。
为什么 RStudio 不在RStudio 的选项卡中显示 的结构Makefile,尤其是特定目标Build?我希望它显示它们并允许人们构建那些特定的目标。RStudio 和 RStudio Server 中是否缺少此功能,或者它在那里,我只需要知道在哪里启用它?
ProjFolder
\
Subfolder
sources.cpp
makefile
makefile
Run Code Online (Sandbox Code Playgroud)
Subfolder应该是一个单独的外部存储库,在检查项目时拉入。当我调用make all顶级 makefile 时,将执行以下配方:
all: $(NAME).elf $(NAME).s19 $(NAME).hex
$(NAME).elf: $(OBJECTS) $(LDSCRIPT) Subfolder/lib.a
make -C CppAudioPeriphs all
@ echo "...linking"
$(CC) $(OBJECTS) Subfolder/lib.a $(LDFLAGS) $(LIBS) -o $@
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,如果Subfolder文件的最终产品lib.a发生更改,Subfolder则会调用 makefile 来重新制作它,然后所有产品都会链接到最终的 Flash 映像中。
问题是顺序。我想总是首先调用子makefile。它知道何时以及如何重制lib.a。然后检查是否lib.a被修改以确定是否重新制作$(NAME).elf。
这是一种解决方案。
.PHONY all $(NAME).elf
Run Code Online (Sandbox Code Playgroud)
这只是指示make无论如何都要重新制作 $(NAME).elf 。我过去曾在小型项目中使用过这种解决方案,但对于当前的项目来说,这是不可接受的。
当 hdr.h 文件更改时,GNU-Make 不会重新编译。如下打印行,即使生成了 main.d 文件,它也没有尝试重新编译。你能指导我为什么会这样吗?
hdr.h
#ifndef __HDR_H__
#define LOOP_CNT 1000
#endif /* __HDR_H__ */
Run Code Online (Sandbox Code Playgroud)
主文件
#include <stdio.h>
#include "hdr.h"
int main(void)
{
int i, sum = 0;
for (i = 0; i < LOOP_CNT; i++) sum += i;
(void)printf("sum = %d\n", sum);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
生成文件
SUFFIXES += .d
.PHONY: clean
OBJECTS = $(patsubst %.c,%.o,$(wildcard *.c))
CC = armcc
LD = armcc
CFLAGS +=
# Default target
all: sum
sum : $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^
$(OBJECTS) …Run Code Online (Sandbox Code Playgroud) 我正在 tasks.json 中配置 VSCode 任务,我需要将 ${workspaceFolder} 传递给“make”命令,但是它需要是正斜杠,而不是反斜杠。
{
"version": "2.0.0",
"echoCommand": true,
"tasks": [
{
"label": "build",
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
},
"command": "make",
"args": [
"APPDIR=\"${workspaceFolder}\""
]
. . .
Run Code Online (Sandbox Code Playgroud)
有没有办法修改 ${workspaceFolder} 以在 Windows 上发出正斜杠?或者,是否有宏这样的东西,我可以在其中搜索和替换?
编辑:我的根本问题是 GNU make 似乎转义了从 APPDIR 传入的反斜杠,例如:C:\somedirectory\someotherdirectory\athirddirectory。我想如果我可以切换到正斜杠,它会解决这个问题。我无法控制,也无法编辑 make 文件。
谢谢
-约翰
我并不总是写 make 文件,但是当我这样做时,我喜欢尝试把它们写好。试图使界面与其他开发人员可能期望的一致总是很困难的。我正在寻找的是所有常见的 make something clean (GNU) make 目标的摘要。
常见的清洁目标有哪些?
每个目标通常什么时候使用?
每个目标与其他目标相比如何?
我曾使用make clean,make clobber和make mrproper之前的系统。那些变得越来越极端;make clean只整理临时文件,make clobber摆脱大部分配置,make mrproper几乎回到刚刚签出的状态。这是正常的秩序吗?应该make mrproper始终删除生成的二进制文件和共享库以进行部署吗?
阅读建议将make distclean事情整理到准备制作分发包的程度。我想这会留下一些自动生成的版本标记文件、文件清单和共享库,但可能会删除您不想存档的临时文件?
make realclean当我在GNU MakeGoals 手册页上看到它时,它对我来说是全新的。正如它列出的那样distclean,clobber我猜它有类似的效果。我是否从未遇到过它,因为它是一个历史文物,或者只是我必须从事的一组项目的特定内容?
抱歉,这有点啰嗦。我找到了将一个目标与另一个目标进行比较的各种问题和答案,但似乎没有一个可以很好地概述。
我正在经历的Makefile文件,我不明白之间的差别--ignore-errors和--keep-going。
有人可以强调两者之间的区别吗?对我来说,两者似乎在发生错误后都会继续。
虽然文档中不清楚,但--ignore-errors可能具有配方级别的范围,如果一个配方行失败,下一个将继续执行。--keep-going可能具有目标级范围,如果任何目标配方失败,配方执行将在那里结束,但仍将尝试创建其他先决条件/目标。这只是一种可能的看法,需要对此进行澄清。
gnu-make ×10
makefile ×7
armcc ×1
c++ ×1
code-cleanup ×1
compilation ×1
gcc ×1
header ×1
mingw ×1
packaging ×1
r ×1
recompile ×1
rstudio ×1
vscode-tasks ×1