Makefile 如何确保“make”在删除文件后重建所有对象

Makefile 如何确保“make”在删除文件后重建所有对象,makefile,Makefile,考虑以下Makefile框架: HEADERS := $(shell find . -name "*.h" | sort) SOURCES := $(shell find . -name "*.c" | sort) OBJECTS := $(patsubst %.c, %.o, $(SOURCES)) executable: $(OBJECTS) $(CC) $(CFLAGS) -o $@ $(OBJECTS) %.o: %.c rm -f $@ $(CC) $(CF

考虑以下
Makefile
框架:

HEADERS := $(shell find . -name "*.h" | sort)
SOURCES := $(shell find . -name "*.c" | sort)
OBJECTS := $(patsubst %.c, %.o, $(SOURCES))

executable: $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $(OBJECTS)

%.o: %.c
    rm -f $@
    $(CC) $(CFLAGS) -c -o $@ $< || { rm -f $@; exit 1; }

$(OBJECTS): Makefile $(HEADERS)
HEADERS:=$(shell find.-name“*.h”| sort)
来源:=$(shell find.-name“*.c”| sort)
对象:=$(patsubst%.c、%.o、$(源))
可执行文件:$(对象)
$(CC)$(CFLAGS)-o$@$(对象)
%.o:%.c
rm-f$@
$(CC)$(CFLAGS)-c-o$@$<|${rm-f$@;退出1;}
$(对象):Makefile$(标题)
如果修改了以下任何文件,这些规则可确保重新编译
对象
可执行文件

  • 声明文件(*.h)
  • 实现文件(*.c)
  • Makefile
    本身
这个很好用。它还包括将新源代码文件添加到项目目录的情况(假设新文件不是使用
cp-a
mv
添加的)。没有涉及的情况是删除文件

删除时重新编译很有用,因为它捕获剩余源代码中的剩余部分,并从
可执行文件中删除多余的数据

HEADERS := $(shell find . -name "*.h" | sort)
SOURCES := $(shell find . -name "*.c" | sort)
OBJECTS := $(patsubst %.c, %.o, $(SOURCES))

executable: $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $(OBJECTS)

%.o: %.c
    rm -f $@
    $(CC) $(CFLAGS) -c -o $@ $< || { rm -f $@; exit 1; }

genlist:
    find . -name \*.c -or -name \*.h > listfile

$(OBJECTS): Makefile $(HEADERS) listfile

.PHONY: genlist
从项目中删除源代码文件后,确保
make
命令重建所有对象的简洁高效的方法是什么

答案可以通过
$(shell…

使用任何常见的Linux命令。您可以创建一个列表文件(name
listfile
),其中包含头和
C
源的列表。如果从源代码树中删除文件,则需要重新创建此
listfile
listfile
应该是
Makefile
中的依赖项

HEADERS := $(shell find . -name "*.h" | sort)
SOURCES := $(shell find . -name "*.c" | sort)
OBJECTS := $(patsubst %.c, %.o, $(SOURCES))

executable: $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $(OBJECTS)

%.o: %.c
    rm -f $@
    $(CC) $(CFLAGS) -c -o $@ $< || { rm -f $@; exit 1; }

genlist:
    find . -name \*.c -or -name \*.h > listfile

$(OBJECTS): Makefile $(HEADERS) listfile

.PHONY: genlist
HEADERS:=$(shell find.-name“*.h”| sort)
来源:=$(shell find.-name“*.c”| sort)
对象:=$(patsubst%.c、%.o、$(源))
可执行文件:$(对象)
$(CC)$(CFLAGS)-o$@$(对象)
%.o:%.c
rm-f$@
$(CC)$(CFLAGS)-c-o$@$<|${rm-f$@;退出1;}
基因列表:
找到-name\*.c-或-name\*.h>列表文件
$(对象):Makefile$(标题)listfile
.伪造:基因列表
删除后,应运行
生成genlist

当然,您可以扩展这个想法:您将创建一个列表文件,每个
make
都将生成一个临时列表文件(例如使用
mktemp
),并与“官方”
列表文件进行比较。如果它们不同,则将覆盖“正式”列表文件,并且在删除后不必运行
make genlist

您可以创建一个列表文件(名称
listfile
),其中包含标题列表和
C
源。如果从源代码树中删除文件,则需要重新创建此
listfile
listfile
应该是
Makefile
中的依赖项

HEADERS := $(shell find . -name "*.h" | sort)
SOURCES := $(shell find . -name "*.c" | sort)
OBJECTS := $(patsubst %.c, %.o, $(SOURCES))

executable: $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $(OBJECTS)

%.o: %.c
    rm -f $@
    $(CC) $(CFLAGS) -c -o $@ $< || { rm -f $@; exit 1; }

genlist:
    find . -name \*.c -or -name \*.h > listfile

$(OBJECTS): Makefile $(HEADERS) listfile

.PHONY: genlist
HEADERS:=$(shell find.-name“*.h”| sort)
来源:=$(shell find.-name“*.c”| sort)
对象:=$(patsubst%.c、%.o、$(源))
可执行文件:$(对象)
$(CC)$(CFLAGS)-o$@$(对象)
%.o:%.c
rm-f$@
$(CC)$(CFLAGS)-c-o$@$<|${rm-f$@;退出1;}
基因列表:
找到-name\*.c-或-name\*.h>列表文件
$(对象):Makefile$(标题)listfile
.伪造:基因列表
删除后,应运行
生成genlist


当然,您可以扩展这个想法:您将创建一个列表文件,每个
make
都将生成一个临时列表文件(例如使用
mktemp
),并与“官方”
列表文件进行比较。如果它们不同,则将覆盖“官方”列表文件,并且在删除后不必运行“生成genlist”。

处理此问题的一种方法是使用现代自动生成的依赖项方法,例如。这些方法具有正确处理已删除文件的内置属性

如果您不想这样做,那么您需要做的就是类似于@uzsolt所建议的事情,但是如果您想避免在make发现文件丢失之前显式运行
make genlist
,那么您必须玩一个小把戏:

HEADERS := $(shell find . -name "*.h" | sort)
SOURCES := $(shell find . -name "*.c" | sort)
OBJECTS := $(patsubst %.c, %.o, $(SOURCES))

executable: $(OBJECTS)
        $(CC) $(CFLAGS) -o $@ $(OBJECTS)

%.o: %.c
        rm -f $@
        $(CC) $(CFLAGS) -c -o $@ $< || { rm -f $@; exit 1; }

$(OBJECTS): Makefile $(HEADERS) sourcelist

sourcelist: FORCE
        @for f in $(SOURCES) $(HEADERS); do echo "$$f"; done > $@.tmp
        @[ `comm -23 $@ $@.tmp | wc -l` -eq 0 ] || mv $@.tmp $@

FORCE:
HEADERS:=$(shell find.-name“*.h”| sort)
来源:=$(shell find.-name“*.c”| sort)
对象:=$(patsubst%.c、%.o、$(源))
可执行文件:$(对象)
$(CC)$(CFLAGS)-o$@$(对象)
%.o:%.c
rm-f$@
$(CC)$(CFLAGS)-c-o$@$<|${rm-f$@;退出1;}
$(对象):Makefile$(标题)源列表
来源列表:原力
@对于f,单位为$(来源)$(标题);做回显“$$f”;完成>$@.tmp
@[comm-23$@$@.tmp|wc-l`-eq 0]| mv$@.tmp$@
部队:

这里的想法是将旧列表与新列表进行比较,并且仅当旧列表包含新列表不包含的内容时才修改列表。这确保了除非删除某些内容,
sourcelist
的时间戳不会更改,因此不会强制对象文件过期。

处理此问题的一种方法是使用现代自动生成的依赖项方法,例如。这些方法具有正确处理已删除文件的内置属性

如果您不想这样做,那么您需要做的就是类似于@uzsolt所建议的事情,但是如果您想避免在make发现文件丢失之前显式运行
make genlist
,那么您必须玩一个小把戏:

HEADERS := $(shell find . -name "*.h" | sort)
SOURCES := $(shell find . -name "*.c" | sort)
OBJECTS := $(patsubst %.c, %.o, $(SOURCES))

executable: $(OBJECTS)
        $(CC) $(CFLAGS) -o $@ $(OBJECTS)

%.o: %.c
        rm -f $@
        $(CC) $(CFLAGS) -c -o $@ $< || { rm -f $@; exit 1; }

$(OBJECTS): Makefile $(HEADERS) sourcelist

sourcelist: FORCE
        @for f in $(SOURCES) $(HEADERS); do echo "$$f"; done > $@.tmp
        @[ `comm -23 $@ $@.tmp | wc -l` -eq 0 ] || mv $@.tmp $@

FORCE:
HEADERS:=$(shell find.-name“*.h”| sort)
来源:=$(shell find.-name“*.c”| sort)
对象:=$(patsubst%.c、%.o、$(源))
可执行文件:$(对象)
$(CC)$(CFLAGS)-o$@$(对象)
%.o:%.c
rm-f$@
$(CC)$(CFLAGS)-c-o$@$<|${rm-f$@;退出1;}
$(对象):Makefile$(标题)源列表
来源列表:原力
@对于f,单位为$(来源)$(标题);做回显“$$f”;完成>$@.tmp
@[comm-23$@$@.tmp|wc-l`-eq 0]| mv$@.tmp$@
部队:
这里的想法是将旧列表与新列表进行比较,并且仅当旧列表包含新列表不包含的内容时才修改列表。这就确保了,除非某件事被删除