我想做的是创建一个 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 build
dependency1.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 制作手册。