Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
168 views
in Technique[技术] by (71.8m points)

bash - Using eval in make file

I run a buildroot make and during this build process a text file is created. After this happens another make as part of the build is run. I want to read the contents of the generated file into a variable and use them. This doesn't work as at the start of my buildroot make it sees the file as not existing, so even though it is generated before the code is run make has already decided it doesn't exist.

Format of the file read:

  str1 str2 1.1.0_nightlybuild (1389:1497M@trunk)

I am trying to use eval (this should check the file contents at the time of running). However the problem persists, I do not seem to be able to read from the file after it is created. It seems make might be expanding the variable and so eval does not work.

None of the variables are being set from the file contents. I check and the file has been generated correctly so if I run the make again, when the file has already been generated, everything works fine. Is eval not the correct way to do this?

So the file does not exist at the start of make, comes into existence and then this code is run:

define EXAMPLE
    $(eval s := $(shell cat output/target/version.txt)) 
    $(eval FILENAME_BIN=$(word 1, $(s)).$(word 2, $(s)).$(word 3, $(s)).bin)
    $(eval FILENAME_JFFS2=$(word 1, $(s)).$(word 2, $(s)).$(word 3, $(s)).jffs2)
    mv $(BINARIES_DIR)/$(BOOTIMAGE) $(BINARIES_DIR)/$(FILENAME_BIN)
    mv $(BINARIES_DIR)/$(JFFS2IMAGE) $(BINARIES_DIR)/$(FILENAME_JFFS2)
endef

It does not work, the file is generated and subsequent builds will work, just not the first one where the file does not exist at the start of the process. The first time the files are simply called ...bin and ...jffs2 as the variables read from the file are not populated. When it works the files are called str1.str2.1.1.0_nightlybuild.bin str1.str2. 1.1.0_nightlybuild.jffs2

Here is the real use case makefile http://pastebin.com/6GdKcUg6 TEST_DEFAULT_RENAME is where I am trying to read in a file, I am using buildroot (so a lot of make files), when I hit make during the buildroot process version.txt is created along the way, this code then tries to read this file but it does not work unless version.text is there before I enter the make in the buildroot directory. As you can see I use version.txt elsewhere via cat but that works fine.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I run a buildroot make and during this build process a text file is created. After this happens another make as part of the build is run. I want to read the contents of the generated file into a variable and use them. This doesn't work as at the start of my buildroot make it sees the file as not existing, so even though it is generated before the code is run make has already decided it doesn't exist.

This happens because another make does not know what buildroot make produces, i.e. the dependency information is missing (this is why recursive make is problematic). In other words, another make does not know that buildroot make produces version.txt.

A few solutions come to mind:

  1. Have a shell script that invokes the makefiles in sequence, e.g. make -f buildroot.mk && make -f another.mk. This way another.mk observes all files produced by buildroot.mk.

  2. Invoke buildroot.mk from another.mk during the first phase, before the targets and dependencies are evaluated. E.g.:

    # At the top level, not in a rule.
    $(shell ${MAKE} -f buildroot.mk)
    # now version.txt is available
    version := $(shell cat version.txt)
    
  3. Have another.mk restart itself when buildroot.mk has completed. A more complicated way of doing 1 and 2:

    $ cat buildroot.mk 
    version.txt :
        echo "str1 str2 1.1.0_nightlybuild (1389:1497M@trunk)" > $@
    
    $ cat another.mk
    all :
        @echo "$@ has completed."
    
    ifdef MAKE_RESTARTS
    s := $(shell cat version.txt))
    FILENAME_BIN := $(word 1, $(s)).$(word 2, $(s)).$(word 3, $(s)).bin
    FILENAME_JFFS2 := $(word 1, $(s)).$(word 2, $(s)).$(word 3, $(s)).jffs2
    $(info ${FILENAME_BIN})
    $(info ${FILENAME_JFFS2})
    else
    another.mk : version.txt
        touch $@
    endif
    
    version.txt :
        $(MAKE) -f buildroot.mk
    
    .PHONY: all version.txt
    
    $ make -f another.mk 
    make -f buildroot.mk
    make[1]: Entering directory '~/tmp'
    echo "str1 str2 1.1.0_nightlybuild (1389:1497M@trunk)" > version.txt
    make[1]: Leaving directory '~/tmp'
    touch another.mk
    str1.str2.1.1.0_nightlybuild.bin
    str1.str2.1.1.0_nightlybuild.jffs2
    all has completed.
    
    $ make -f another.mk 
    make -f buildroot.mk
    make[1]: Entering directory '~/tmp'
    make[1]: 'version.txt' is up to date.
    make[1]: Leaving directory '~/tmp'
    touch another.mk
    str1.str2.1.1.0_nightlybuild.bin
    str1.str2.1.1.0_nightlybuild.jffs2
    all has completed.
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...