通常如果我想编译一个名为number_input.c
的C程序,我会输入
cc -o number_input number_input.c
我想使用我的mac终端创建一个脚本,这样我就不必输入那个额外的单词。最初我这样做是为了节省自己1秒钟的节目,但具有讽刺意味的是,我花了2个多小时试图让这个工作起作用。
a= echo "$1" | rev | cut -c3- | rev
echo $a
cc -o $a $1
echo $1
这是我的输出:
number_input
clang:错误:没有输入文件 number_input.c
我可以说正确输入了名称,但由于某些原因,cc
命令没有考虑$1
的值?我假设$1
不是直接转换成字符串或类似的东西,但我不确定。
答案 0 :(得分:5)
您的错误在第一行,因为您没有为a
分配任何内容:
a=$(echo "$1" | rev | cut -c3- | rev)
可以解决问题(对于行为良好的文件名,至少,因为你的脚本中缺少引号)。 a
之后的空格表示您为其分配空字符串,然后运行管道中的命令。
而不是全力以赴地翻转两次,只需用${1%??}
删除最后两个字符:
cc -o "${1%??}" "$1"
答案 1 :(得分:1)
执行此操作的最常用工具是make
。它从运行目录中名为Makefile
的文件中读取配方,并执行任何必要的任务。它足够聪明,可以检查文件时间戳,以检测是否需要重新编译项目的哪些部分或哪些部分。这是一个Makefile示例:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := number_input
.PHONY: all clean
all: $(PROGS)
clean:
rm -f $(PROGS)
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
请注意,Makefile
中的缩进必须使用制表符,而不是空格。如果您复制上述内容并粘贴到文件,则需要运行sed -e 's|^ *|\t|' -i Makefile
来修复缩进。
前三行命名编译器使用的名称,编译器选项和链接选项。您的特定用例不需要-lm
链接选项;我刚刚将其包含在内,因为您迟早会想要使用<math.h>
,然后您需要包含-lm
链接选项。
PROGS
行命名您的程序。您可以指定多个,只需用空格分隔。
.PHONY:
行告诉make
目标all
和clean
是“假的”,他们不会生成该名称的文件。
作为all
中的第一个食谱的Makefile
食谱是您运行make
时所遵循的默认食谱。这个告诉我应该构建PROGS
中列出的所有程序。
clean
配方(运行make clean
)从目录中删除所有临时文件和编译文件 - 基本上清理它。
最后的食谱很棘手。它表示PROGS
中列出的所有文件都是根据具有相同名称和.c
后缀的文件构建的。 $^
引用.c
文件名,$@
引用文件名,不带后缀。
如果此Makefile
用于通过电子邮件向教师返回练习,我还会添加新的.PHONY
目标tarball
:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := number_input
TAR := $(notdir $(CURDIR)).tar
.PHONY: all clean tarball
all: $(PROGS)
clean:
rm -f $(PROGS)
tarball: clean
rm -f ../$(TAR)
tar -cf ../$(TAR) $(notdir $(CURDIR))/
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
如果make
在上次编译number_input
之后被修改,或者number_input.c
尚不存在,则运行number_input
将编译number_input
。
运行make TAR=myname-ex01.tar tarball
从当前目录中删除已编译的文件,然后在父目录中创建当前目录(及其子目录,如果有)的tarball为myname-ex01.tar
。如果只运行make tarball
,则tar文件名将与当前目录的名称相同,但后缀为.tar
。
我希望你能明白为什么写Makefile
是如此有用。