如何使目标依赖于特定的文件名?
How can I make target depend on specific filename?
我正在尝试使用 Makefile
来管理我的项目中的一些任务(例如打包以供分发)。但是我找不到一种方法来依赖特定的文件名而不是一些自动魔术。参见示例:
+ $ cat Makefile
dist: ctl
echo "package it here"
+ $ tree
.
├── ctl
└── Makefile
0 directories, 2 files
+ $ make
echo "package it here"
package it here
如您所见,这工作正常。但是当我创建文件 ctl.h
和 ctl.c
:
时它停止工作
+ $ touch ctl.{h,c}
+ $ make
cc ctl.c -o ctl
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../lib/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: ctl] Error 1
+ $ tree
.
├── ctl.c
├── ctl.h
└── Makefile
0 directories, 3 files
我的假设是 make
试图变得聪明,并认为 ctl
是从 ctl.c
编译而来的程序。事实并非如此。我怎样才能抑制这种行为?
从 ctl.c
创建 ctl
的 "implicit rule" 仅在没有明确规定的规则创建 ctl
时使用。例如,如果 ctl
应该从源文件 ctlcmd.c
和 common.c
编译,那么写:
ctl: ctlcmd.o common.o
$(CC) $(CFLAGS) -o $@ $^
(.o
文件将使用另一个隐式规则从 .c
文件创建。)
如果ctl
根本不需要重新创建(比如是手写脚本),那么你可以为它写一个虚拟规则,像这样:
# `ctl` is a hand-written file, don't try to recreate it from anything
ctl:
touch ctl
你还应该写一些规则来告诉 Make 应该用ctl.c
做什么。
Make 带有一堆模式规则,它非常努力地使用它们。
其中之一说如何从 foo.c
中创建可执行文件 foo
。这就是发生在你身上的事情。
我个人非常不喜欢这些规则,通常使用 -R
参数禁用它们。
$ ls
ctl ctl.c Makefile
$ make -R
echo "package it here"
package it here
$ make
cc ctl.c -o ctl
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [ctl] Error 1
现在,要求您的用户必须使用某个参数并不好。
一种前进的方式是简单地取消所有隐含规则。
您可以销毁 make 认为应用模式规则的候选文件扩展名列表。
一个简单的 SUFFIXES:
就可以了。
$ ls
ctl ctl.c Makefile
$ cat Makefile
.SUFFIXES:
dist: ctl
echo "package it here"
$ make
echo "package it here"
package it here
通常make
假定所有目标都将创建同名文件。如果在您的示例中没有为 ctl
指定依赖项,make
会尝试猜测依赖项,例如,如果您有一个文件 ctl.c
,它假定它可以从 ctl
构建ctl.c
使用标准规则。
假设您的目标 dist
和 ctl
永远不应构建为文件,您可以通过添加一行
将它们声明为虚假目标
.PHONY: dist ctl
见https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
我正在尝试使用 Makefile
来管理我的项目中的一些任务(例如打包以供分发)。但是我找不到一种方法来依赖特定的文件名而不是一些自动魔术。参见示例:
+ $ cat Makefile
dist: ctl
echo "package it here"
+ $ tree
.
├── ctl
└── Makefile
0 directories, 2 files
+ $ make
echo "package it here"
package it here
如您所见,这工作正常。但是当我创建文件 ctl.h
和 ctl.c
:
+ $ touch ctl.{h,c}
+ $ make
cc ctl.c -o ctl
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../lib/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: ctl] Error 1
+ $ tree
.
├── ctl.c
├── ctl.h
└── Makefile
0 directories, 3 files
我的假设是 make
试图变得聪明,并认为 ctl
是从 ctl.c
编译而来的程序。事实并非如此。我怎样才能抑制这种行为?
从 ctl.c
创建 ctl
的 "implicit rule" 仅在没有明确规定的规则创建 ctl
时使用。例如,如果 ctl
应该从源文件 ctlcmd.c
和 common.c
编译,那么写:
ctl: ctlcmd.o common.o
$(CC) $(CFLAGS) -o $@ $^
(.o
文件将使用另一个隐式规则从 .c
文件创建。)
如果ctl
根本不需要重新创建(比如是手写脚本),那么你可以为它写一个虚拟规则,像这样:
# `ctl` is a hand-written file, don't try to recreate it from anything
ctl:
touch ctl
你还应该写一些规则来告诉 Make 应该用ctl.c
做什么。
Make 带有一堆模式规则,它非常努力地使用它们。
其中之一说如何从 foo.c
中创建可执行文件 foo
。这就是发生在你身上的事情。
我个人非常不喜欢这些规则,通常使用 -R
参数禁用它们。
$ ls
ctl ctl.c Makefile
$ make -R
echo "package it here"
package it here
$ make
cc ctl.c -o ctl
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [ctl] Error 1
现在,要求您的用户必须使用某个参数并不好。
一种前进的方式是简单地取消所有隐含规则。
您可以销毁 make 认为应用模式规则的候选文件扩展名列表。
一个简单的 SUFFIXES:
就可以了。
$ ls
ctl ctl.c Makefile
$ cat Makefile
.SUFFIXES:
dist: ctl
echo "package it here"
$ make
echo "package it here"
package it here
通常make
假定所有目标都将创建同名文件。如果在您的示例中没有为 ctl
指定依赖项,make
会尝试猜测依赖项,例如,如果您有一个文件 ctl.c
,它假定它可以从 ctl
构建ctl.c
使用标准规则。
假设您的目标 dist
和 ctl
永远不应构建为文件,您可以通过添加一行
.PHONY: dist ctl
见https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html