如何使目标取决于特定的文件名?

时间:2019-02-04 17:36:59

标签: c++ c makefile gnu-make automake

我正在尝试使用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.hctl.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编译的程序。事实并非如此。如何抑制这种行为?

3 个答案:

答案 0 :(得分:2)

ctl创建ctl.c的“隐式规则”仅在没有明确说明的创建ctl的规则时使用。例如,如果应该从源文件ctlctlcmd.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通过使用标准规则。

假设目标distctl绝不能构建为文件,则可以通过添加一行来将它们声明为伪目标

.PHONY: dist ctl

请参阅https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html