我不知道很多makefile的东西,我一直在倾向于根据需要学习位.
我的makefile最大的失败是我手动列出了所有文件,而这不是一个问题,我当前的项目变得笨拙.我有4个目录,每个目录都有源文件.
如何在不必手动列出的情况下获取所有目标文件列表.
这不起作用,但它显示了我一直在努力做的事情.
VPATH = Lib GameCode Moot/Moot Moot/Impl
OBJS = $(subst .cpp, .o, $(VPATH))
foobar: $(OBJS)
g++ -o $@ $^
%.o: %.cpp
g++ -c $< -o $@ -I Moot
clean:
rm main.o lib.o foo.o foobar
Run Code Online (Sandbox Code Playgroud) 是否有任何类型的if/else语句与GNU make和Berkley make(freeBSD)兼容?
GNU MAKE:
ifeq ($(BUILD_TYPE), debug)
Run Code Online (Sandbox Code Playgroud)
伯克利制造:
.ifdef (BUILD_TYPE)
Run Code Online (Sandbox Code Playgroud) 我有一组我想编译的.cpp文件.这些.cpp文件位于分层目录结构中.我希望相应的.o文件最终都在一个构建文件夹中.
这是我如何让GNU make枚举文件...
SRCS = \
$(wildcard $(CODE)/**/*.cpp) \
$(wildcard $(CODE)/AlgebraLibraries/**/*.cpp) \
$(wildcard $(CODE)/Calculator/Environments/**/*.cpp)
BARE_SRCS = $(notdir $(SRCS))
BARE_OBJS = $(BARE_SRCS:.cpp=.o)
OBJS = $(addprefix $(BUILD)/, $(BARE_OBJS))
Run Code Online (Sandbox Code Playgroud)
完成此操作后,我不知道如何创建将从.cpp文件创建.o文件的规则.直觉上,我想要做的是以下伪代码.
for i=0, N do # <-- a for-loop!
$(OBJS)[i]: $(SRCS)[i] # <-- the rule!
$(CPP) -c $(SRCS)[i] -o $(OBJS)[i] # <-- the recipe
end
Run Code Online (Sandbox Code Playgroud)
当然,这不是有效的GNU make代码,但我相信你理解我正在尝试做的事情.以下方法无效.
%.o: %.cpp
$(CPP) -c $< -o $@
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为GNU make匹配%符号,假设.o文件与.cpp文件并存.
我所知道的所有这些的替代方案,但将非常繁琐,是将所有规则作为明确的规则进行枚举.那是迟钝的!一定有更好的方法.
我一直在研究GNU make生成规则的能力,但如果没有内置逻辑,似乎没有办法做到这一点.如果我可以利用一些流控制语句来生成我想要制定的规则,那将是非常好的.这是否过多地要求GNU-make?
无论如何,有没有办法做我正在尝试用GNU make做的事情?如果是这样,怎么样?
谢谢您的帮助!
在我得到的开源项目的"./configure"中:
user agent OS = Linux
./configure: line 13957: syntax error near unexpected token 0.9.3'
./configure: line 13957: GOBJECT_INTROSPECTION_CHECK(0.9.3)'
make: *** [config.status] Error 2
Run Code Online (Sandbox Code Playgroud)
Ubuntu 12.04软件包"gobject-introspection"和"libgirepository1.0-dev"存在.删除GOBJECT_INTROSPECTION_CHECK行允许configure完成,但项目稍后会失败.
如何干净地完成此配置步骤?谷歌搜索此问题显示针对同一阻塞问题针对众多操作系统项目提出的错误,但通常的答案是"安装gobject-introspection".
GNU Make包含一个称为的特殊目标.DELETE_ON_ERROR。如果您的Makefile中包含此文件,Make将删除其构建序列以非零返回状态完成的任何目标。这很有用,因此在以后的调用中,Make不会假定目标已正确构建。
这是一个虚拟的例子。
.DELETE_ON_ERROR:
out.dat: in.dat
touch out.dat
false
Run Code Online (Sandbox Code Playgroud)
因为false给出的返回值非零,所以构建被视为失败,并且Make删除了out.dat目标。这是广告和预期的行为。但是,当目标是目录时,似乎不会保留此行为。考虑另一个虚拟的例子。
.DELETE_ON_ERROR:
outdir/: in.dat
mkdir outdir/
false
Run Code Online (Sandbox Code Playgroud)
在这种情况下,构建会再次失败,但是Make不会删除outdir目录。有什么方法可以指示Make进行此操作吗?
考虑以下:
%.foo: %.bar
echo $< > $@
Run Code Online (Sandbox Code Playgroud)
假设我们有一个文件1.bar,执行的命令很简单echo 1.bar > 1.foo.但是,当%包含路径而不仅仅是文件名时,它开始变得挑剔.我的问题是我想要添加另一条路径%.bar,模式完全被破坏了.即,当%.bar是nice/path/1.bar,这成为不可能:
%.foo: /project/something/%.bar
echo $< > $@
Run Code Online (Sandbox Code Playgroud)
这将运行,但它执行echo nice/path//project/something/1.bar > 1.foo而不是echo /project/something/nice/path1.bar > 1.foo
这样做的原因在于它的模式规则是如何制作的.来自文档:
当目标模式不包含斜杠(通常不包含斜杠)时,文件名中的目录名将从文件名中删除,然后再与目标前缀和后缀进行比较.[...]仅为了查找要使用的隐式规则而忽略目录,而不是在该规则的应用程序中.因此,'e%t'匹配文件名src/eat,'src/a'作为词干.当先决条件变为文件名时,来自词干的目录将添加到前面,而词干的其余部分将替换为'%'.具有先决条件模式'c%r'的词干'src/a'给出文件名src/car
有什么方法可以根据具体规则关闭它吗?
来自文档:
.ONESHELL
如果.ONESHELL被提到作为目标,那么当构建目标时,配方的所有行将被赋予shell的单个调用,而不是单独调用每行(*note Recipe Execution:Execution.).
所以,一个makefile,如:
.ONESHELL :
all ::
echo 'foo
bar'
Run Code Online (Sandbox Code Playgroud)
跑步,我得到:
$ make
echo 'foo
/bin/sh: 1: Syntax error: Unterminated quoted string
makefile:4: recipe for target 'all' failed
make: [all] Error 2 (ignored)
Run Code Online (Sandbox Code Playgroud)
尝试,几乎相同的makefile,但是如果添加-前缀配方,忽略错误,记录:
要忽略配方行中的错误,请在行的文本开头(在初始选项卡之后)写一个" - ".在将行传递给shell以执行之前,将丢弃" - ".
makefile,如:
.ONESHELL :
all ::
-echo 'foo
bar'
Run Code Online (Sandbox Code Playgroud)
跑步,我得到:
$ make
echo 'foo
/bin/sh: 1: Syntax error: Unterminated quoted string
makefile:4: recipe for target 'all' failed
make: [all] Error 2 …Run Code Online (Sandbox Code Playgroud) 就我而言,我有requirements目标,该目标安装了所需的Python软件包test,并运行了测试,并取决于先前的测试。
安装依赖项是一项很长的操作,我希望仅在requirements.txt更改时才执行。我该如何实现?
这是我现在拥有的Makefile的简化示例:
.PHONY: test requirements
requirements: requirements.txt
pip install -r $<
test: tests/ | requirements
py.test $^
Run Code Online (Sandbox Code Playgroud) 有谁知道如何在食谱上使用here-document重定向?
test:
sh <<EOF
echo I Need This
echo To Work
ls
EOF
Run Code Online (Sandbox Code Playgroud)
我找不到任何解决方案尝试通常的反斜杠方法(基本上以一行中的命令结束).
理由:
我有一组多行配方,我想通过另一个命令代理(例如,sh,docker).
onelinerecipe := echo l1
define twolinerecipe :=
echo l1
echo l2
endef
define threelinerecipe :=
echo l1
echo l2
echo l3
endef
# sh as proxy command and proof of concept
proxy := sh
test1:
$(proxy) <<EOF
$(onelinerecipe)
EOF
test2:
$(proxy) <<EOF
$(twolinerecipe)
EOF
test3:
$(proxy) <<EOF
$(threelinerecipe)
EOF
Run Code Online (Sandbox Code Playgroud)
我希望避免的解决方案:将多行宏转换为单行.
define threelinerecipe :=
echo l1;
echo l2;
echo l3
endef
test3:
$(proxy) <<< "$(strip …Run Code Online (Sandbox Code Playgroud) 通配符函数返回版本3.81中的排序结果,但它在版本4.2中执行此操作.是否有任何编译/运行时开关来控制这个功能?
下面显示了两个版本的GNU make的结果.
$ ls
a.mk a0.svp a1.svp a2.svp a3.svp a4.svp a5.svp a6.svp a7.svp a8.svp a9.svp
$ cat a.mk
SVP_FILES := $(wildcard *.svp)
all:
@echo $(SVP_FILES)
$ make -f a.mk all
a0.svp a1.svp **a2.svp a3.svp a4.svp a5.svp a6.svp a7.svp a8.svp a9.svp**
$ ~/sandbox/bin/make -f a.mk all
a0.svp a1.svp **a6.svp a5.svp a9.svp a4.svp a3.svp a2.svp a7.svp a8.svp**
$make –v | head -n 1
GNU Make 3.81
$ ~/sandbox/bin/make -v | head -n 1
GNU Make 4.2
Run Code Online (Sandbox Code Playgroud)