bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 'How makefiles are remade'


From: Jim
Subject: Re: 'How makefiles are remade'
Date: Wed, 21 Apr 2004 02:43:11 -0700
User-agent: Mozilla Thunderbird 0.5 (Windows/20040207)

Paul D. Smith wrote:


Yes it is, if you write it correctly.

(sorry, this is such an attacking statement...)
The correct way being that a makefile includes one and only one other makefile? I mean sure, if the documentation didn't say if ANY change, then the make is restrated (one would assume that to imply at the end of the rule which generates a changed makefile - and maybe that's my error - but then I still have to submit this as a documentation bug, that it is unclear that make lacks the functionatilty to cleanly reload product include files) And yes, when building a project and spontanseously having .d files populating the direcotyr, these being included, I would not assume that these should be done... but again, that would typically be under the section of "Updating goal targets..." when producing object and as a by product the dependancies thereof. but when in the "Updating makefiles...." section (as indicated when running with a -d option) I would think that it would be reasonable to restart the make at the end of each target which causes an include to change.

  j> and what you're really saying is that only the LAST included file
  j> can be re-loaded, since ALL includes are read before their
  j> dependancies are even checked.

Well, your second statement is true: all includes (that exist) _ARE_
read in first, then make tries to create any included files that were
read (or failed to be read), and if any changed it re-execs itself.

  j> And THAT is not at all what the documentation indicates, it says -

j> " if any have actually been changed, make starts with a clean slate and j> reads all the makefiles over agai"

  j> if ANY changed, clean all, and reload all again...

Yes, exactly.


Consider this makefile; it works exactly as you expect (IIUC).  The
warning statements prove that make is re-execing at every step:


  $(warning Reading makefile)

  include first.mk

  all:: ; @echo "MAIN"

  first.mk:
        @echo 'include second.mk' > $@
        @echo 'all:: ; @echo FIRST' >> $@
        @echo 'first.mk: second.mk' >> $@
        @echo 'second.mk:' >> $@
        @echo ' @echo "all:: ; @echo SECOND" >> $$@' >> $@

  clean: ; rm -f *.mk


Okay. That $(warning reading Makefile) gave me a good idea... There was definatly some question of order... it seems the last included is the first checked, unless that depends on the first included....

some later run... TICKS starts at XIV (14)

Makefile:1: Reading makefile
ticks:1: reading ticks
x:1: reading x TICKS=XIV
y:1: reading y
# everything exists at the moment

Makefile:30: making ticks
#yeah something changed, and ticks has to be updated... new value
# will be XV(15) (value at start shown above is XIV(14) )

Makefile:45: making x
#hmm no reload there, therefore TICKS will still be the old value...

x:4: making y with TICKS=XIII
#yeah ticks is definatly not current, having just been remade
# X creates Y with value loaded in last passes X product (not this one)

Makefile:1: Reading makefile
# ahh SO there are times when it really does restart....

ticks:1: reading ticks
x:1: reading x
y:1: reading y
#yeah, okay so everything's current, no updates needed...

Final result in Y is : XIII
# ooo XIII, that would make this 2 steps behind...

In all these examples where all the data is static it's hard to see when it fails, and it needs to be at least 2 levels to really demonstrate the problem.

Maybe you could chalk this up to a documentation bug, it says whenever ANY included makefile is read, it reloads, the above trace indicates that two rules to generate makefiles were performed before reloading...


Note that in the last @echo line, you have to make sure a TAB character
is inserted in the string that is echoed.

Yes, it's gross, but it does work as you expect.  Here's a sample run:

  temp$ make
  makefile:1: Reading makefile
  makefile:3: first.mk: No such file or directory
  makefile:1: Reading makefile
  first.mk:1: second.mk: No such file or directory
  makefile:1: Reading makefile
  SECOND
  FIRST
  MAIN

  temp$ make
  makefile:1: Reading makefile
  SECOND
  FIRST
  MAIN


I still think you may find using $(eval ...) to be overall simpler.



#include <stdio.h>

int main( int argc, char **argv )
{
        int n;
   int iscmd = 0;
   char cmd[8192];
        if( argc < 2 )
        {
                printf( "usage: echoto [-x] <output> <command line.....>\n" );
                printf( "usage:    c : prefix with a tab character..\n" );
                return 1;
        }
        n = 1;
        while( argv[n][0] == '-' )
        {
                int c = 1;
      while( argv[n] && argv[n][c] ) switch( argv[n][c] )
                {
                case 'c':
                case 'C':
                        iscmd = 1;
         c++;
         break;
                default:
                        printf( "Unknown option: %c\n", argv[n][c] );
         c++;
         break;
                }
      n++;
        }
        {
      int ofs = 0;
                FILE *out = fopen( argv[n], "at+" );
                if( !out )
                        out =fopen( argv[n], "wt" );
                if( !out )
                {
                        printf( "echoto: Failed to open %s for output\n", 
argv[n] );
                        return 1;
                }
                if( iscmd )
         fprintf( out, "\t" );
                for( n++; n < argc; n++ )
                {
                        fprintf( out, "%s ", argv[n] );
                }
      fprintf( out, "\n" );
                fclose( out );
        }
   return 0;
}


$(warning Reading makefile)

ifdef __LINUX__
EXEC:=$(QUIET)exec
else
EXIT:=$(QUIET)exit
endif

# need this if $(REMAKE) cause /bin/false deletes this...
.PRECIOUS: x y 

MAKEFILE=$(word 1,$(MAKEFILE_LIST))

#$(warning remake will be: $(MAKE) -s -C $(CURDIR) -f $(MAKEFILE) 
$(MAKECMDGOALS))
define REMAKE 
        @--$(QUIETCMD)$(MAKE) -s -C $(CURDIR) -f $(MAKEFILE) $(MAKECMDGOALS)
        @/bin/false
endef

.PHONY: fakeall all

fakeall: all ticks x

#fakeall:echoto
#echoto: echoto.c
#       @gcc -o $@ $<
include ticks

#.PHONY:ticks
ticks: Makefile bob dillon
        $(warning making ticks)
        @echo $$(warning reading ticks $$(TICKS))>ticks
        @echo TICKS=$(patsubst %ILI,%L,$(patsubst %XXXXIX,%IL,$(patsubst 
%IXI,%X,$(patsubst %VIV,%IX,$(patsubst %IVI,%V,$(patsubst 
%IIII,%IV,$(TICKS)I))))))>>ticks
        @echo Prior Ticks : $(TICKS)

#       $(REMAKE)



include x

bob dillon: 
        @echo . >$@;

x:ticks Makefile bob dillon 
        $(warning making x)
        @echo $$(warning reading x $$(TICKS))>x
        @echo include y >>x
        @echo y: $@ $? >>x
        @echoto -c x $$(warning making y $(TICKS)) 
        @echoto -c x @echo $$$$(warning reading y) \>y
        @echoto -c x @echo fakeall: \>\>y 
        @echoto -c x @./echoto -c y @echo hey we made it:$(TICKS)

#       @echo ' $$(REMAKE)' >>x
#       $(REMAKE)


Makefile: ;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]