我正在尝试检查变量是否包含特定字符串。我尝试了此处发布的解决方案:Makefile:包含字符串,但对我来说,它似乎不起作用。
@echo $(findstring 2025, $(basename $(<F)))`
返回2025
,但是:
ifeq ($(findstring 2025, $(basename $(<F))),2025)
@echo $(findstring 2025, $(basename $(<F)))
endif
不返回2025
。为什么?
我正在尝试检查变量是否包含特定字符串。我尝试了此处发布的解决方案:Makefile:包含字符串,但对我来说,它似乎不起作用。
@echo $(findstring 2025, $(basename $(<F)))`
返回2025
,但是:
ifeq ($(findstring 2025, $(basename $(<F))),2025)
@echo $(findstring 2025, $(basename $(<F)))
endif
不返回2025
。为什么?
我已经很久没有使用过 Make 了,我记得有一个技巧可以做到这一点,但我的记忆力不行,而且词汇量太笼统,无法进行搜索……
所以:
SOURCES := $(wildcard */*.org)
JIRAS := $(patsubst %.org,%.jira,$(SOURCES))
.PHONY : all
all : $(JIRAS)
$(JIRAS) : $(SOURCES)
# $< is wrong here, because it will always be the first source
emacs $< --batch -l $(CURDIR)/org2jira -f export-to-jira --kill
正如评论所暗示的,这$<
部分是错误的。我认为有一种方法可以将其拆分为两个规则,然后 Make 会在匹配的文件上成对调用它,但在尝试了一些组合之后,我就是想不起来它是什么。
如果方便的话,所需的代码可以写在 Shell 中:
find . -type f -name '*.org' -exec emacs {} --batch -l $(pwd)/org2jira -f export-to-jira --kill \;
注意:我不关心解决方案是否特定于 GNUMake。
*.d
我已经使用 make(使用)自动生成了依赖文件( ) g++ -MMD
,在这些文件中,我看到创建的规则没有任何配方。此外,从我的测试中,我注意到后续构建(*.d
创建后)仍将使用我自己在 Makefile 中定义的配方:
CPPFLAGS := -Iinclude
CXXFLAGS := -std=c++20 -Wall -Wextra -Werror -MMD
%.o: %.cpp
# recipe below used when building from dependency files!
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o$@ $<
-include $(DEPS_FILES)
文档中是否提到过,带有空配方的规则只会向现有规则添加先决条件?我之所以问这个问题,是因为我注意到它不使用此处定义的隐式规则。
我有一个现有的且可以运行的 Makefile,并且想要添加 MariaDB (mysql.h)。我的问题是:
gcc -o example MariaDBTest.c $(mariadb_config --include --libs)
运行良好。但是我如何/在哪里可以将其插入到我的 Makefile 中:
CC = gcc -Wno-unknown-pragmas -Wall -Wextra
PKGCONFIG = $(shell which pkg-config)
CFLAGS = $(shell $(PKGCONFIG) --cflags gtk+-3.0 --libs) -lbcm2835 -rdynamic -lm
DEPS = LinkedList.h StructDefinitions.h
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
OBJ = reTerminal.c \
Sensors/CpuGpuTemp.c Sensors/ReadSensores.c Sensors/TempSensorExtern.c \
Connectivity/ClientSide.c Connectivity/ServerSide.c \
GUI/MainApp.c GUI/MainAppWindow.c GUI/BasicFrame.c GUI/SimpleFrame.c \
Data/MariaDBTest.c
Main: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
系统:Linux/RasPi5
考虑下面的 Makefile,命令clean
被声明为PHONY
并且有一个备用名称c
。
PHONY 属性是否也适用于make c
或仅适用于make clean
?
.PHONY: clean
clean c:
rm -rf *.o
我可能用错了术语,所以请随时纠正我。我们一段时间以来一直在滥用 make 进行大量构建。99% 的时间都是使用虚假目标。我们有 docker build 项目,我们为每个版本化的 docker 文件调用 docker build。文件结构看起来像这样:
6/Dockerfile
8/Dockerfile
获取项目中的 docker 文件列表很容易。
DOCKERFILES:=$(wildcard */Dockerfile)
目前我们正在使用这种方法来构建docker文件:
.PHONY: all
all: lint init build-images
.PHONY: lint
lint:
$(foreach image, $(DOCKERFILES),$(call dockerLint,$(image),$(_DOCKER_BUILD_ARCH)))
.PHONY: init
init:
$(foreach image, $(DOCKERFILES),$(call initVariablesForImage,$(image)))
.PHONY: build-images
build-images:
$(foreach image, $(DOCKERFILES),$(call dockerBuildPush,$(image),$(_DOCKER_BUILD_ARCH)))
但是,为了更好地理解 make 并避免 foreach,是否可以定义与 Dockerfile 匹配的多个规则并运行相关配方?我使用单个规则取得了一些成功,但一旦我尝试执行多个配方,它就会失败。
.PHONY: test
test: $(DOCKERFILES)
$(DOCKERFILES):*
$(info ***** build $@)
输出结果如下:
***** build 6/Dockerfile
***** build 8/Dockerfile
我预计这种方法是错误的,因为当我尝试引入其他目标时,我会收到覆盖警告或循环引用:
warning: overriding commands for target `8/Dockerfile'
warning: ignoring old commands for target `8/Dockerfile'
...
make: Circular 6/Dockerfile <- 6/Dockerfile dependency dropped.
make: Circular 7/Dockerfile <- 7/Dockerfile dependency dropped.
make: Circular 8/Dockerfile <- 8/Dockerfile dependency dropped.
我想停下来看看我想要实现的目标是否可行。我们现有的方案是可行的,但探索替代方案以查看我们能否提出更清晰的实现方案会更好。
请向我解释一下此行 make 的作用(该subst
部分)?
TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS)):$(USE_GETTEXT_SCHEME)
我认为应该用 \' 替换单引号字符。
我有一个名为的目录markdown
,其中包含.md
文件和其他子目录。我想为每个 md 文件生成一个相应的 html 文件。
该 makefile 可以工作,但是它需要一个单独的构建目录:
SOURCES = $(shell find ./markdown -name "*.md")
HTML = $(patsubst ./markdown/%.md,./build/%.html,$(SOURCES))
all: $(HTML)
build/%.html: markdown/%.md
@echo -e "Convert markdown file [$<] to html [$@]."
我只想在markdown
目录的父级(即项目的根目录)中构建,所以我想要:
./index.html
./foo/bar/hum/another.html
./markdown/index.md
./markdown/foo/bar/hum/another.md
我希望能够删除两个“build/”,因此更改后的行将显示为:
HTML = $(patsubst ./markdown/%.md,./%.html,$(SOURCES))
和
%.html: markdown/%.md
这适用于顶层文件(./markdown/index.md
),但适用于其他任何文件(例如./markdown/foo/bar/hum/another.md
)。为什么会这样?
这是我的 Makefile:
# the issue seems to be the "." in the filename, since
# if NAME = test7 the desired result is achieved!
# although, when I check the [4.9 Special Built-in Target Names][1]
# section of the GNU make command, there is nothing mentioned
# about this?
NAME = .test7
$(NAME):
@echo Making $(NAME)...
@touch $(NAME)
@echo Done.
hello:
@echo Hello :\)
all: $(NAME)
@:
clean fclean:
rm -r $(NAME)
re: fclean all
@:
.PHONY: all clean fclean re
如果我只是简单地第一次运行 make,或者此后多次运行,就会显示以下输出:
Hello :)
即使第一条规则是 $(NAME),它也会被忽略,因为它的值以“.”开头,如 NAME = .test7 ?
这是预期的行为吗?
我找到了GNU make 文档的4.9 特殊内置目标名称部分,但其中没有提到这方面的内容?
但是,如果我有 NAME = test7(开头没有“。”),那么在第一次运行时我将获得预期的结果:
Making .test7...
Done.
经过多次尝试后,只需运行 make,正确的输出如下所示:
make: '.test7' is up to date.
有什么建议吗?也许,修复此 .test7 目标,使其像 NAME = test7 的情况一样运行?
上述问题的解决方案似乎是:
生成文件:
NAME = .test7
.DEFAULT_GOAL := $(NAME)
$(NAME):
@echo Making $(NAME)...
@touch $(NAME)
@echo Done.
hello:
@echo Hello :\)
all: $(NAME)
clean fclean:
rm -r $(NAME)
re: fclean all
@:
.PHONY: all clean fclean re default_target
第一次运行make时将输出:
Making .test7...
Done.
而在后续运行中将输出:
make: '.test7' is up to date.
现在make all将输出:
make: Nothing to be done for 'all'.
感谢所有发表评论的人!:)
我有一个头文件列表,我想使用 Makefile 一次性编译它们。但是,其中一些文件在汇编中具有外部定义的函数。如果是这种情况,则.s
目录中有一个同名(但扩展名为)的文件./asm
。例如,如果./r1.hpp
需要将汇编文件链接到其中,则也会有./asm/r1.s
。因此,我想出了以下 Makefile:
CXXFLAGS := @compile_flags.txt
SRC_FILE:= ./test.cpp
HDR_DIRS:= $(wildcard ./v[0-9]*)
.PHONY: help clean $(HDR_DIRS)
.DEFAULT_GOAL := help
help:
@echo "Please specify a target to run."
%.o: %.s
as $< -o $@
# rule 1
%.out: %.hpp ./asm/%.o $(SRC_FILE)
g++ $(CXXFLAGS) $(SRC_FILE) $(word 2, $^) -o $@ -I. -include $<
# rule 2
%.out: %.hpp $(SRC_FILE)
g++ $(CXXFLAGS) $(SRC_FILE) -o $@ -I. -include $<
$(HDR_DIRS): %:
$(MAKE) $(patsubst %.hpp,%.out,$(wildcard $@/r[0-9]*.hpp))
clean:
@if [ -z "$(DIR)" ]; then \
echo "Error: DIR is not specified. Please set DIR to the target directory."; \
exit 1; \
fi; \
echo "Cleaning files in $(DIR) ..."
@rm -f $(DIR)/*.out $(DIR)/asm/*.o
在这里,如果可能的话,我希望rule1
应用,rule2
如果没有相应的程序集文件(意味着该.s
文件不需要链接它)。但是,rule2
无论我尝试什么,总是被调用。我设法让它工作的唯一方法是将其更改.out
为rule1
,.obj
但我需要相同的扩展名才能进行进一步处理。我还希望将.s
文件作为依赖项进行跟踪,因为它们可以更改,然后需要重新编译文件。
我怎样才能实现这个目标?
注意:我也尝试过使用条件依赖性:
%.out: %.hpp $(wildcard $(patsubst %.hpp,%.s,$(dir $<)asm/$(notdir $<)))
@echo $(word 2, $^)
但是这个通配符总是扩展为空字符串,我不明白为什么。
版本为:
GNU Make 4.4.1.