我不知道很多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) 有没有办法让GNU make打印导致命令失败时执行的目标的"回溯"?我经常处理严重混淆的makefile,同时解决在新系统上构建软件的可移植性问题,看起来这对于make来说应该是一个非常简单的事情,这将极大地帮助调试,但我找不到任何方式来请求它.我希望看到的是:
gcc: error: ...
make[2]: error: gcc ...
make[2]: error building target bar
make[2]: error building dependency bar for target foo
make[1]: error: make -C subdir
make[1]: error building target subdir
make[1]: error building dependency subdir for target all
...
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) 在我得到的开源项目的"./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
有什么方法可以根据具体规则关闭它吗?
我有一个项目涉及子目录与子makefile.我知道我可以使用export命令通过环境将变量从父makefile传递到子makefile.有没有办法将变量从子makefile传递给它的调用makefile?即可以反过来出口工作?我试过这个没有成功.我猜测一旦子make完成它的shell就会被破坏,同时它的环境变量也会被破坏.还有另一种向上传递变量的标准方法吗?
有谁知道如何在食谱上使用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) 后
cd build
cmake -B . -DCMAKE_TOOLCHAIN_FILE=~/vcpkg/scripts/buildsystems/vcpkg.cmake -S ..
Run Code Online (Sandbox Code Playgroud)
好像
cmake --build .
Run Code Online (Sandbox Code Playgroud)
和
make
Run Code Online (Sandbox Code Playgroud)
在 macOS 上执行相同的操作。
那么,我什么时候应该使用其中之一呢?