我正在尝试使用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
编译的程序。事实并非如此。如何抑制这种行为?
答案 0 :(得分:2)
从ctl
创建ctl.c
的“隐式规则”仅在没有明确说明的创建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 {em> 应该如何使用ctl.c
。
答案 1 :(得分:2)
Make 带有很多模式规则,很难使用。
其中一位说了如何从foo
中创建可执行文件foo.c
。这就是你正在发生的事情。
我个人非常不喜欢这些规则,通常使用-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
答案 2 :(得分:0)
通常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