Arks
Arks

Reputation: 659

Make ignores the rule when run for the first time

SO

I can't find out why these lines are not called for the first time I run 'make' but are called the next time:

sb_path = sb
sb_src := $(sb_path)/src
sb_build := $(sb_path)/build
ifndef DO_NOT_GENERATE_COMMIT_INFO
commit_sb: | $(sb_bin)
        @$(sb_build)/generate-commit-info $(sb_path)

$(sb_src)/last_git_commit_info.h: | commit_sb ;
endif

I'm just curious because there is no file generate-commit-info file and make crashes when I call it for the second time, but it compiles my program ok for the first try.

I use script on my local machine to copy sources over ssh to another machine and to run compile.sh script there:

...
scp -r $sbfolder/build $sbfolder/Makefile "$buildserver:$root/$curdate"
check_retcode
scp -r $sbfolder/sb/Makefile "$buildserver:$root/$curdate/sb/"
...
ssh $buildserver "$root/compile.sh $curdate $debug"

compile.sh:

# fix Makefile: we don't have git installed here
#DO_NOT_GENERATE_COMMIT_INFO=true

#now we can compile sb
curdir="/home/tmp/kamyshev/sb_new/$1"
cd $curdir
check_retcode
t_path=$curdir
debug=$2
config=RELEASE
if [[ debug -eq 1 ]]; then
        config=DEBUG
fi
echo "building sb... CONFIG=$config"
make -j2 CONFIG=$config
check_retcode

As you see DO_NOT_GENERATE_COMMIT_INFO=true is commented out. So I just don't see a reason why the code is not run when I call a make or the script for the first time (either from the remote script or myselft from command line).

Do you have any clues?

UPDATE on Etan Reisner comment:

commit_sb target is checked, it does not exist, so it's rule is being run and it updates last_git_commit_info.h. Thus it forces to update the .h file. It also gives me a .PHONY target commit_sb so I could do it directly by calling make commit_sb.

The generate-commit-info also creates a file in a $(sb_bin) folder.

My another guess is that you are talking about a better way to organize this code. I can update last_git_commit_info.h directly with a such rule:

commit_sb $(sb_src)/last_git_commit_info.h: FORCE | $(sb_bin)
    @$(sb_build)/generate-commit-info $(sb_path)

FORCE:

Upvotes: 1

Views: 139

Answers (1)

Arks
Arks

Reputation: 659

Thanks to the commenters on my question I've done some additional research: I've tried to make a minimal complete example. And this led me to the answer.

My code generates dependency files (look at -MMD command in SB_CXXFLAGS):

# just example - in real Makefile these are calculated on the fly
sb_deps := file1.d file2.d [...]

# rules with dependances of .o files against .h files
-include $(sb_deps)

SB_CXXFLAGS = $(CXXFLAGS) [...] -MMD
# compile and generate dependency info;
$(sb_obj)/%.o:$(sb_src)/%.cpp
    $(CXX) $(SB_CXXFLAGS) $< -o $@

And when I run make for the first time there no *.d files, so no *.cpp depends on last_git_commit_info.h file and the rule is not applied. On the subsequent runs the dependency rule appears in one of *.d files, the rule is executed and I get the error.

UPDATE: This does not concern the question directly, but this is the better way to write these rules:

ifndef DO_NOT_GENERATE_COMMIT_INFO
commit_sb $(sb_src)/last_git_commit_info.h: FORCE | $(sb_bin)
    @$(sb_build)/generate-commit-info $(sb_path)

FORCE:
endif

Upvotes: 2

Related Questions