我使用的是“ Advanced Linux Programming (2001)” [code]一书中的 Makefile 。我很奇怪看到GNU make确实正确编译了代码,甚至没有在 Makefile 中指定编译器。这就像没有任何食谱烘焙!
这是代码的最小版本:
测试.c
int main(){}
Run Code Online (Sandbox Code Playgroud)
生成文件
all: test
Run Code Online (Sandbox Code Playgroud)
并真正起作用!这是它执行的命令:
cc test.c -o test
Run Code Online (Sandbox Code Playgroud)
我在文档中找不到任何有用的东西。这怎么可能?
PS 额外说明:连语言都没有指定;因为test.c可用,GNUmake使用cc. 如果存在test.cpp或test.cc(当没有时test.c),它使用g++(而不是c++)。
我正在尝试编译一个用 Fortran 编写的程序make(我有一个Makefile,在包含Makefile的目录中,我输入命令$ make target,其中“目标”是我的Makefile 中存在的系统特定的目标规范。正如我对我的目标规范的各种修订进行试验,我在尝试调用 时经常收到各种错误消息make。举几个例子:
make[1]: Entering directory
/bin/sh: line 0: test: too many arguments
./dpp angfrc.f > angfrc.tmp.f
/bin/sh: ./dpp: Permission denied
make[1]: *** [angfrc.o] Error 126
make[1]: Leaving directory
make: *** [cmu60] Error 2
Run Code Online (Sandbox Code Playgroud)
和
make[1]: Entering directory
/bin/sh: line 0: test: too many arguments
./dpp -DSTRESS -DMPI -P -D'pointer=integer'-I/opt/mpich_intel/include angfrc.f > angfrc.tmp.f
/bin/sh: ./dpp: Permission denied
make[1]: *** [angfrc.o] Error 126
make[1]: Leaving …Run Code Online (Sandbox Code Playgroud) 我试图指示 GNU Make 3.81 在命令失败时不要停止(所以我在命令前加上-),但我还想检查下一个命令的退出状态并打印一条信息更丰富的消息。但是我下面的 Makefile 失败了:
$ cat Makefile
all:
-/bin/false
([ $$? -eq 0 ] && echo "success!") || echo "failure!"
$
$ make
/bin/false
make: [all] Error 1 (ignored)
([ $? -eq 0 ] && echo "success!") || echo "failure!"
success!
Run Code Online (Sandbox Code Playgroud)
为什么上面的 Makefile 回显“成功!” 而不是“失败!” ?
更新:
遵循并扩展已接受的答案,以下是它的书写方式:
failure:
@-/bin/false && ([ $$? -eq 0 ] && echo "success!") || echo "failure!"
success:
@-/bin/true && ([ $$? -eq 0 ] && echo "success!") || echo …Run Code Online (Sandbox Code Playgroud) 我想查看一个 makefile 的一个或多个目标的依赖关系。所以我正在寻找一个程序,它可以解析生成文件,然后以某种树状格式(缩进,ascii-art,...)或图形(点,...)表示依赖关系。
有些程序可以针对其他情况执行此操作:
dot图形)的形式显示软件包的依赖关系,gcc -M source_file.c 将 C 源文件的依赖项显示为 make 规则,在网上搜索我发现几乎没有帮助。这让我尝试
make --always-make --silent --dry-run some_target | \
grep --extended-regexp 'Considering target file|Trying rule prerequisite'
Run Code Online (Sandbox Code Playgroud)
但看起来我必须在 perl 或 python 中编写更多解析代码才能将其表示为一个漂亮的树/图。而且我还不知道我是否真的会以这种方式获得完整和正确的图表。
以某种方式限制图形会很好(没有内置规则,只有给定的目标,只有一定的深度),但在大多数情况下,我只是在寻找一种工具,它会给我一些“合理”的依赖关系,人类- 可视格式(就像“类似”下的程序一样)。
make -dnq ...吗?我正在编写一个 Makefile(在 Ubuntu 20.04 上,如果相关的话),并注意到echo. 以这个简单的 Makefile 为例:
test.txt:
@echo -e 'hello\nworld'
@echo -e 'hello\nworld' > test.txt
Run Code Online (Sandbox Code Playgroud)
当我运行时make,我希望在 stdout 上看到与 test.txt 中相同的内容,但事实上我没有。我在标准输出上得到这个:
hello
world
Run Code Online (Sandbox Code Playgroud)
但这在 test.txt 中:
-e hello
world
Run Code Online (Sandbox Code Playgroud)
同时,如果我-e从 Makefile 中的两行中删除,我会在标准输出上得到:
hello\nworld
Run Code Online (Sandbox Code Playgroud)
在 test.txt 中:
hello
world
Run Code Online (Sandbox Code Playgroud)
这让我想知道是否echo检测到重定向并表现出不同的行为,但当我在 shell 中手动运行它时却没有(如我通常期望的那样,/bin/echo -e 'hello\nworld' > test.txt它会在单独的行上产生hello和)。world我什至通过添加一行来确认 Makefile 使用的是 /bin/echo 而不是内置的 shell @echo --version。
这里发生了什么?
我在玩makefile,遇到了%.o或%.c。据我了解,它指定了所有c或o文件。但为什么这项工作:
%.o: %.c
$(CC) -c $^ -o $@
Run Code Online (Sandbox Code Playgroud)
这不起作用
SOURCE := $(wildcard *.c)
$(SOURCE:.c=.o): SOURCE
$(CC) -c $^ -o $@
Run Code Online (Sandbox Code Playgroud)
这两个表达式都指定了所有文件。那么%.o: make 文件中的符号有什么作用呢?
有没有已知的方法可以让 Linuxmake拒绝意外使用 GNU?在 Linux 中编辑或使用其他人的 Makefile 时,在 Makefile 中进行特定扩展?我的意思是,限制 GNU?Makemake按照 POSIX 中指定的方式运行并拒绝任何 GNU?Make 特定扩展?
该.POSIX专项的目标是不够的,按照“ 4.9特别内置目标名(gnu.org) ”。手册页没有提到这个命令行选项。
使用其他make实用程序可能是一种选择。
— 更新 2018-10-19 —
我仍然没有找到我的问题的直接答案,但这里至少有一个关于这个问题的文档,这个文档在我提出这个问题时并不存在: A Tutorial on Portable Makefiles (nullprogram.com)。
我有一个 Makefile,它有一个变量,如果变量未设置或设置但具有空值,则该变量需要具有默认值。
我怎样才能做到这一点?
我需要这个,因为我在 shell 脚本中调用 make 并且 makefile 所需的值可以作为 $1 从 shell 传递。并将其传递给 makefile,我必须将其设置在 bash-script 中。
想法:(不优雅)在 bash 脚本内部,可以检查变量是否已设置但具有空值,在这种情况下可以取消设置。
注意:如果变量未在终端中定义,以下将不起作用,因为它们是在 bash 脚本中设置的。
dSourceP?=$(shell pwd)
Source?=$(notdir $(wildcard $(dSourceP)/*.md))
Run Code Online (Sandbox Code Playgroud)
make all dSourceP="${1}" Source="${2}"
Run Code Online (Sandbox Code Playgroud)
bash ./MyScript.sh
bash ./MyScript.sh /home/nikhil/MyDocs
bash ./MyScript.sh /home/nikhil/MyDocs index.md
Run Code Online (Sandbox Code Playgroud) 目前我正在使用具有如下定义的 Makefile
MYLIB=/.../mylib-1.2.34
Run Code Online (Sandbox Code Playgroud)
问题是这些对于不同的开发人员来说是不同的,每次结帐后都必须重新编辑文件是一种痛苦。
所以我尝试导出一个特定的环境变量,然后做
MYLIBX:=$(MYLIB_ENV)
MYLIBX?=MYLIB
Run Code Online (Sandbox Code Playgroud)
问题是如果 MYLIB_ENV 没有定义,它仍然会创建一个空的 MYLIBX,所以 ?= 不起作用。有没有一种干净的方法来做这个非常基本的事情?
我正在使用多年来开发的一组“丰富”的 make 文件,这些文件可以执行各种操作,例如 make 和相互调用,因此无法深入更改内容。
解决方案
双洗牌。MYLIB 已经定义。
MYLIB_ENV?=MYLIB
MYLIB:=MYLIB_ENV
Run Code Online (Sandbox Code Playgroud) 我想在我的 makefile 中使用来自万维网的文件作为先决条件:
local.dat: http://example.org/example.gz
curl -s $< | gzip -d | transmogrify >$@
Run Code Online (Sandbox Code Playgroud)
如果远程文件比本地文件新,我只想“transmogrify”,就像make正常操作一样。
我不希望保留的高速缓存副本example.gz -文件都很大,而且我不需要原始数据。最好我想完全避免下载文件。目标是使用-jmake 标志并行处理其中的一些。
什么是解决这个问题的干净方法?我可以想到几种方法:
在进一步挖掘之前,我需要一些建议,最好是具体的例子!