仅当源文件比编译的程序更新时才运行编译脚本

仅当源文件比编译的程序更新时才运行编译脚本

我想做的是创建一个 bash 脚本,仅当源代码发生更改时,该脚本才会运行另一个 bash 脚本来编译某些程序。到目前为止,我有一种方法可以获取自 J2000 纪元以来每个文件的时间戳(以秒为单位):

#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)

#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")

和一个安装脚本

./make_common_lib.bsh build
./make_common_lib.bsh install

我想弄清楚如何创建一个 if 状态(在半伪代码中)

if [any of $sourceTimes>$exeTimes];
then  #run make_common_lib.bsh script
else  #Do nothing
fi

到目前为止,我最好的猜测是以某种方式使用read,但我不确定如何同时索引这两个变量。

如果有一个非常简单的方法来做到这一点,我很抱歉,因为我对 bash 脚本非常陌生,但到目前为止,我的谷歌搜索都没有真正返回任何有用的东西。

更多信息:

时间戳变量的格式如下

1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069

答案1

您的构建脚本方法

如果您想保留“bash 构建方法”,那么您最好touch lastbuild在运行构建脚本并完成构建时“触摸”文件 ( )。此外,构建脚本可以查找由 touch 生成的文件(如果不存在,则假设需要构建),或者如果存在,则使用find查看是否存在任何新文件:

find . -name "*.[ch]" -newer lastbuild

然后构建该输出是否为 1 行或多行(可以使用类似的方法进行检查wc -l)。

使用 Make 代替

这最好通过像 Makefile 这样的东西来管理(专门用于执行这种依赖性检查)。

default: all

all: dependency1.o dependency2.o

dependency1.o: dependency1.c
    ./make_common_lib.bsh build

dependency2.o: dependency2.c
    ./make_common_lib.bsh build

install: 
    ./make_common_lib.bsh install

创建一个虚拟的“构建”脚本:

$ cat make_common_lib.bsh 
#! /bin/sh

echo "Build $1"

我们现在可以运行 make:

$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build

您还可以将 替换为将发出构建等的./make_common_lib.bsh build命令:./make_common_lib.bsh builddependency1.o

dependency1.o: dependency1.c
    gcc -c dependency1.c

Makefile 还允许符号替换,因此您可以在 Makefile 的前面声明编译器和编译器标志:

CC=/usr/bin/gcc
CFLAGS=-O2 -Wall

然后在您的规则中引用它们:

dependency1.o: dependency1.c
    $(CC) $(CFLAGS) -c dependency1.c

请注意,依赖项声明后缩进的行必须以制表符开头,而不是空格。

缩短依赖规则列表

OP 询问是否可以采用更短的方式来声明所有依赖项。使用 GNU make 的一些技巧是可能的(注意并非所有这些都适用于 vanilla make)。

您可以进行变量替换。鉴于声明:

SRCS=dependency1.c dependency2.c dependency3.c

然后,您可以使用变量替换创建对象规则:

OBJS=$(SRCS:.c=.o)

这会将所有.c' 替换为.o' 。实际上给出了以下形式的一行:

OBJS=dependency1.o dependency2.o dependency3.o

$<然后,您可以使用特殊变量和进一步缩短“编译命令” $@

.c.o:
    $(CC) $(CFLAGS) -c $<  -o $@

$<代表 GNU make 术语中的先决条件(或我所说的依赖项)和$@目标,因此它最终会发出:

/usr/bin/gcc -Wall -O2 -c dependency1.c  -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c  -o dependency2.o
.
.
.

将所有这些放在一起,使用链接选项和链接和编译可执行文件的命令$(TARGET)

# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib

# declare all the sources
SRCS=dependency1.c dependency2.c

# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)

# Target executable name:
TARGET=myexefile

default: all

all: $(TARGET)
    @echo Target has been built

$(TARGET): $(OBJS) 
    $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)

.c.o:
    $(CC) $(CFLAGS) -c $<  -o $@

install:
    ./make_common_lib.bsh install

请注意,您可以使用 GNU make 做很多事情,这里有详细记录GNU 制作手册

相关内容