views:

125

answers:

1

Hi all. I have a make build system that I am trying to decipher that someone else wrote. I am getting an error when I run it on a redhat system, but not when I run it on my solaris system. The versions of gmake are the same major revision (one off on minor revision).

This is for building a C project, and the make system has a global Makefile.global that is inherited by each directory's local Makefile

The Makefile.global has all the targets in it, starting with

 all: $(LIB) $(BIN)

The global file also has the following line

 ifndef INCLUDE_GEN_DEPS
 sinclude $(GEN_DEPS)
 endif

where LIB builds libs and BIN builds binaries.

jumping down the targets I have

 $(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' > [email protected] ; \
      cat [email protected] > $@ ; \
      cat [email protected] | cut -d: -f2 | grep '\.h' | sed 's,\.h,.h :,g' >> $@ ; \
      rm [email protected]
  $(GEN_OBJS) :
       $(CC) $(CFLAGS) $(INCDIRS) -c $(*F).c -lmpi -o $@

I think these are all the relevant targets I need to include to answer my question.

Definitions of those variables:

 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))))

I think this has everything covered you need. Basically self explanatory from the names.

Now as best I can tell, this is generating in /lib/deps a .d file that has the object and source dependencies in it. In other words, for the utilities.a library, I will get a utils.o and utils.c dependency stack, all in the file utils.d

There is some syntax error that is being generated in that file I think, because I get the following error:

 ../lib/deps/util.d:25: *** target pattern contains no '%'. Stop.
 gmake[2]: *** [all] Error 2
 gmake[1]: *** [all] Error 2
 gmake: *** [all] Error 2

I am not sure if my error is in the dependency generation, or some further down part, like the object generation target?

If you need further info, let me know, I will add to post

+1  A: 

Compare what gets written into lib/deps/util.d on your working (Solaris) machine with the non-working (redhat), paying particular attention to line 25. That will probably give you a good hint as to what's going wrong.

If they're identical, the problem is the one-off make minor version.

If thye're different, the problem is probably some difference between the tools being run, or (more likely) different versions of icc installed.

edit

decoding make rule:

$(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' > [email protected] ; \
        cat [email protected] > $@ ; \
        cat [email protected] | cut -d: -f2 | grep '\.h' | sed 's,\.h,.h :,g' >> $@ ; \
        rm [email protected]

This rule makes the dependency files in $(GEN_DEPS), which correspond to all the source files with the .c changed to .d

@set -e; rm -f $@;

Cause any errors to immediately exit this rule with a failure, rather than continuing, and remove the target we're about to regenerate

$(CC) $(CDEP_FLAG) $(CFLAGS) $(INCDIRS) `basename $@ | sed 's/\.d/\.c/' | sed 's,^,$(HOME_SRC)/,'` | sed 's,\(.*\)\.o: ,$(GEN_OBJDIR)/\1.o $@ :,g' > [email protected] ;

Run icc on the .c file corresponding to the .d file we're trying to generate with flags to automatically generate dependencies instead of compiling. The basename $@ | sed 's/\.d/\.c/' | sed 's,^,$(HOME_SRC)/,' clause is translating the .d name back to the .c name.

Pipe the output (which is the depdendency rules) to the sed script sed 's,\(.*\)\.o: ,$(GEN_OBJDIR)/\1.o $@ :,g', which will add the dependency file itself as a something that depends on everything that icc found for the .o (object) file to depend on. Write all of this to a temp file.

cat [email protected] > $@ ;

Copy the temp file to the output dependency file.

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

Append a second copy of the dependencies to the dependency file, modified by a little script which strips off the target and makes the first header into the target. So this is adding an additional set of dependencies for the first header file that appears in the source file.

rm [email protected]

Remove the temp file.

Chris Dodd
I will check that out. I didnt think about the possibility of the compiler generating the dependencies different. I am actually using cc on the solaris system (which is SGI MIPS)
Derek
That's almost certainly the problem then -- different compilers tend to use different flags for generating dependencies and generate them in slightly different ways, which will cause issues with the sed commands in the makefile.
Chris Dodd
Great. I will go check out the differences and see what is going on. What do you think is the best way to resolve this? Have a different set of make rules for each platform? I think we will primarily stick with intel architectures from now on (using icc), but theres always a chance this will have to be ported somewhere else.
Derek
If what icc produces is close enough, you may be able to modify the sed commands to make it work for either compiler. Otherwise you're probably better off moving this action to a separate script and have multiple versions of the script for different platforms.
Chris Dodd