如何为C生成依赖项?(同时..解码此sed/make语句!)

如何为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

我有一个自制的系统,我正试图破解别人写的。我在redhat系统上运行它时出错,但在solaris系统上运行它时却没有。gmake的版本都是相同的主要版本(一次过的次要版本)

这是用于构建C项目的,make系统有一个全局Makefile.global,由每个目录的本地Makefile继承

Makefile.global包含所有目标,从

 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 > $@ ;