如何为C生成依赖项?(同时..解码此sed/make语句!)
我有一个自制的系统,我正试图破解别人写的。我在redhat系统上运行它时出错,但在solaris系统上运行它时却没有。gmake的版本都是相同的主要版本(一次过的次要版本) 这是用于构建C项目的,make系统有一个全局Makefile.global,由每个目录的本地Makefile继承 Makefile.global包含所有目标,从如何为C生成依赖项?(同时..解码此sed/make语句!),sed,dependencies,makefile,redhat,gnu-make,Sed,Dependencies,Makefile,Redhat,Gnu Make,我有一个自制的系统,我正试图破解别人写的。我在redhat系统上运行它时出错,但在solaris系统上运行它时却没有。gmake的版本都是相同的主要版本(一次过的次要版本) 这是用于构建C项目的,make系统有一个全局Makefile.global,由每个目录的本地Makefile继承 Makefile.global包含所有目标,从 all: $(LIB) $(BIN) 全局文件还有以下行 ifndef INCLUDE_GEN_DEPS sinclude $(GEN_DEPS) end
all: $(LIB) $(BIN)
全局文件还有以下行
ifndef INCLUDE_GEN_DEPS
sinclude $(GEN_DEPS)
endif
其中LIB构建libs,BIN构建二进制文件
跳下我的目标
$(LIB) : $(GEN_LIB)
$(GEN_LIB) : $(GEN_DEPS) $(GEN_OBJS)
$(AR) $(ARFLAGS) $(GEN_LIB) $(GEN_OBJS)
$(GEN_DEPS) :
@set -e; rm -f $@; \
$(CC) $(CDEP_FLAG) $(CFLAGS) $(INCDIRS) `basename $@ | sed 's/\.d/\.c/' | sed 's,^,$(HOME_SRC)/,'` | sed 's,\(.*\)\.o: ,$(GEN_OBJDIR)/\1.o $@ :,g' > $@.tmp ; \
cat $@.tmp > $@ ; \
cat $@.tmp | cut -d: -f2 | grep '\.h' | sed 's,\.h,.h :,g' >> $@ ; \
rm $@.tmp
$(GEN_OBJS) :
$(CC) $(CFLAGS) $(INCDIRS) -c $(*F).c -lmpi -o $@
我想这些都是我回答我的问题需要包括的相关目标
这些变量的定义:
CC = icc
CDEP_FLAG = -M
CFLAGS = various compiler flags ifdef type flags
INCDIRS = include directory where all .h files are
GEN_OBJDIR = /lib/objs
HOME_SRC = .
GEN_LIB = lib/$(LIB)
GEN_DEPDIR=/lib/deps
GEN_DEPS = $(addprefix $(GEN_DEPDIR)/,$(addsuffix .d,$(basename $(OBJS))))
我想这已经涵盖了你需要的一切。从名字来看,基本上是不言自明的
现在,正如我所知,这是在/lib/deps中生成一个.d文件,其中包含对象和源依赖项。换句话说,对于utilities.a库,我将得到一个utils.o和utils.c依赖项堆栈,它们都在utils.d文件中
我认为该文件中生成了一些语法错误,因为我得到了以下错误:
../lib/deps/util.d:25: *** target pattern contains no '%'. Stop.
gmake[2]: *** [all] Error 2
gmake[1]: *** [all] Error 2
gmake: *** [all] Error 2
我不确定我的错误是在依赖项生成中,还是在更深层的部分,比如对象生成目标
如果您需要进一步的信息,请告诉我,我将添加到post中,比较在您的工作(Solaris)计算机和非工作(redhat)计算机上写入lib/deps/util.d的内容,特别注意第25行。这可能会给你一个很好的提示,告诉你哪里出了问题 如果它们是相同的,问题是一次性制作次要版本 如果它们不同,问题可能是正在运行的工具之间存在一些差异,或者(更有可能)安装的icc的不同版本 编辑 解码制定规则:
$(GEN_DEPS) :
@set -e; rm -f $@; \
$(CC) $(CDEP_FLAG) $(CFLAGS) $(INCDIRS) `basename $@ | sed 's/\.d/\.c/' | sed 's,^,$(HOME_SRC)/,'` | sed 's,\(.*\)\.o: ,$(GEN_OBJDIR)/\1.o $@ :,g' > $@.tmp ; \
cat $@.tmp > $@ ; \
cat $@.tmp | cut -d: -f2 | grep '\.h' | sed 's,\.h,.h :,g' >> $@ ; \
rm $@.tmp
此规则使$(GEN_DEPS)
中的依赖项文件与.c
更改为.d
的所有源文件相对应
@set -e; rm -f $@;
使任何错误在发生故障时立即退出此规则,而不是继续,并删除我们将要重新生成的目标
$(CC) $(CDEP_FLAG) $(CFLAGS) $(INCDIRS) `basename $@ | sed 's/\.d/\.c/' | sed 's,^,$(HOME_SRC)/,'` | sed 's,\(.*\)\.o: ,$(GEN_OBJDIR)/\1.o $@ :,g' > $@.tmp ;
在与我们试图生成的.d文件对应的.c文件上运行icc,并使用标志自动生成依赖项,而不是编译。basename$@|sed's/\.d/\.c/'| sed's,^,$(HOME\u SRC)/,'
子句将.d名称转换回.c名称
通过管道将输出(即depdency规则)传输到sed脚本sed,\(.*\\\.o:,$(GEN\u OBJDIR)/\1.o$@:,g'
,该脚本将依赖文件本身添加为依赖于icc找到的.o
(对象)文件所依赖的所有内容的内容。将所有这些写入临时文件
cat $@.tmp > $@ ;
将临时文件复制到输出依赖项文件
cat $@.tmp | cut -d: -f2 | grep '\.h' | sed 's,\.h,.h :,g' >> $@ ;
将依赖项的第二个副本附加到依赖项文件中,通过一个小脚本进行修改,该脚本剥离目标并将第一个头放入目标中。因此,这是为源文件中出现的第一个头文件添加一组附加的依赖项
rm $@.tmp
删除临时文件。您是否尝试过使用
-d
选项运行gmake来查看它在做什么?我会检查一下。我没有考虑编译器生成不同依赖项的可能性。实际上,我在solaris系统上使用cc(即SGI MIPS),这几乎肯定是问题所在——不同的编译器倾向于使用不同的标志来生成依赖项,并以稍微不同的方式生成它们,这将导致makefile.Great中的sed命令出现问题。我会去看看这些差异,看看发生了什么。你认为解决这个问题的最好办法是什么?每个平台有一套不同的制定规则吗?我认为从现在起,我们将主要使用英特尔体系结构(使用icc),但总有可能必须将其移植到其他地方。如果icc生产的产品足够接近,您可以修改sed命令,使其适用于任一编译器。否则,最好将此操作移动到单独的脚本中,并为不同的平台提供多个版本的脚本。
cat $@.tmp > $@ ;