0

我有一个 make build 系统,我正试图破译别人写的。当我在 redhat 系统上运行它时出现错误,但在我的 solaris 系统上运行它时却没有。gmake 的版本是相同的主要版本(次要版本关闭)。

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

Makefile.global 包含所有目标,从

 all: $(LIB) $(BIN)

全局文件也有以下行

 ifndef INCLUDE_GEN_DEPS
 sinclude $(GEN_DEPS)
 endif

其中 LIB 构建库,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

我不确定我的错误是在依赖项生成中,还是在更底层的部分,比如对象生成目标?

如果您需要更多信息,请告诉我,我将添加到帖子中

4

1 回答 1

1

比较在您的工作(Solaris)机器上写入 lib/deps/util.d 的内容与非工作(redhat)机器上写入的内容,特别注意第 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_SRC)/,' 子句将 .d 名称转换回 .c 名称。

将输出(即依赖规则)通过管道传输到 sed 脚本sed 's,\(.*\)\.o: ,$(GEN_OBJDIR)/\1.o $@ :,g',该脚本会将依赖文件本身添加为依赖于 icc 找到的.o(对象)文件所依赖的所有内容的东西。将所有这些写入临时文件。

cat $@.tmp > $@ ;

将临时文件复制到输出依赖文件。

cat $@.tmp | cut -d: -f2 | grep '\.h' | sed 's,\.h,.h :,g' >> $@ ;

将依赖项的第二个副本附加到依赖项文件中,由一个小脚本修改,该脚本剥离目标并使第一个标头成为目标。因此,这是为源文件中出现的第一个头文件添加一组额外的依赖项。

rm $@.tmp

删除临时文件。

于 2010-05-26T18:55:44.647 回答