Makefile file function demo errors - linux

I was trying to get the result of file function in makefile for my demo with a small makefile as:
CMD = cat
OBJECTS = Makefile Makefile-filter-func
program : $(OBJECTS)
$(file >$#.in) $(foreach O,$^,$(file >>$#.in,$O))
#echo The file has been created.
all :
$(CMD) $(CMDFLAGS) #$#.in
#echo The file contents are printed.
#rm $#.in
#echo The file removed.
I want to see the file the file name using ls command but this makefile has following error:
Makefile-file-func:7: *** recipe commences before first target. Stop.
where am I getting wrong.

A pointer to the answer can be found in the source code of make (version 3.82), in the file read.c:
989 /* This line starts with a tab but was not caught above because there
990 was no preceding target, and the line might have been usable as a
991 variable definition. But now we know it is definitely lossage. */
992 if (line[0] == cmd_prefix)
993 O (fatal, fstart, _("recipe commences before first target"));
With this information, it is possible to reproduce your issue by inserting spaces at the right spot. In the code below, ~ denotes a space and <TAB> denotes a TAB:
program : $(OBJECTS)
~~~~~~~~$(file >$#.in) $(foreach O,$^,$(file >>$#.in,$O))
<TAB> #echo The file has been created.
Since the spaces and tabs get lost in your question, it is a bit hard to see if this is exactly your case as well though.
Note that recipes are normally supposed to start with a TAB.

Related

What does "-" symbol do in -$(VARIABLE) type of makefile commands?

In one of the makefiles that i came across, i found something like below in a recipe part of a rule.
-$(RM) $#
Here RM variable is equal to rm Unix command. (it is set in the top part of the code)
I know that here $# represent the target. And without the - symbol, above command removes that target file (maybe still with - symbol it still deletes it). But what is the use of - here?

Makefile rule with percent symbol is not evaluated

I'm trying to port linux kernel's kconfig util to my product
while compiling I got next error:
make[6]: *** No rule to make target `zconf.tab.c', needed by `zconf.tab.o'. Stop.
I found next rule in Makefile.lib for this file
$(obj)/%: $(src)/%_shipped
$(call cmd,shipped)
It looks ok for me and it just works in kernel but not in my product.
Then I added another rule right after previous one.
$(obj)/%c: $(src)/%c_shipped
$(call cmd,shipped)
And now it works just fine.
Can someone explain me what's wrong with original rule?
In my case obj=. and src=. (both = dot). Current dir contains appropriate *_shipped file.
My guess is that $(obj)/%: $(src)/%_shipped qualifies as a match-anything pattern rule. (The manual doesn't mention how targets and prerequisites with with directory components are handled, but it would make sense.)
Note the following in the manual:
A non-terminal match-anything rule cannot apply to a file name that indicates a specific type of data. A file name indicates a specific type of data if some non-match-anything implicit rule target matches it.
Since there are already built-in implicit rules for creating .c files (using parser generators for example), the match-anything rule is never considered.
The reason the error doesn't happen for the kernel makefiles is that they run make with -r, which eliminates built-in implicit rules. It's done in the top-level makefile by setting the MAKEFLAGS variable:
# Do not use make's built-in rules and variables
# (this increases performance and avoids hard-to-debug behaviour);
MAKEFLAGS += -rR
As a simple experiment, I created a file test.c_foo and the following makefile:
MAKEFLAGS += -r
%: %_foo
#echo building
make test.c without the first line gives
make: *** No rule to make target 'test.c'. Stop.
With the first line, it prints "building" instead.

Makefile:124: *** unterminated call to function `foreach': missing `)'. Stop

I am creating Makefile and it gives me following error
Makefile:124: *** unterminated call to function `foreach': missing `)'. Stop.
The Makefile around line 124 is
.PHONY: popiso
popiso: isolinux_cfg $(foreach x,$(_$(country)_pops_roles), pop_iso_$(x)) $(isomedia)
#echo $#
#echo
#echo allhostname $(allhostname)
#echo
#echo
#echo allnetwork_setup $(allnetwork_setup)
#sudo cp $(addsuffix .ks.cfg,$(allhostname)) $(isomedia)
#sudo cp isolinux.cfg $(isomedia)/isolinux/
#echo ready to make iso
$(_$(country)_pops_roles) gets expanded correctly and it calls pop_iso_XXXX 4 times as it suppose to.
And then it gives above mentioned error.
I'm using RHEL6 - 64bit machine
I'm not that deep into Makefile/Gmake, and so I'm not sure what's the issue.
$ make -v
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for x86_64-redhat-linux-gnu
Hemanshu
Edit: Remake version: run using 'remake all -X'
This is how the main line expands
popiso: isolinux_cfg pop_iso_loc2_role1 pop_iso_loc2_role2 pop_iso_loc1_role1 pop_iso_loc1_role2 /raw/ops-xxxx/media
It makes first 5 targets successfully and then stops as follow
end pop_iso_loc1_role2
/raw/patel/xxxx-build-test/build-tools/ks/Makefile:166 Successfully remade target file `pop_iso_loc1_role2'.
<- (/raw/patel/xxxx-build-test/build-tools/ks/Makefile:166)
pop_iso_loc1_role2
remake<19>
-> (/raw/patel/xxxx-build-test/build-tools/ks/Makefile:119)
/raw/ops-xxxx/media:
remake<20>
/raw/patel/xxxx-build-test/build-tools/ks/Makefile:124 Must remake target `popiso'.
Makefile:125: *** unterminated call to function `foreach': missing `)'. Stop.
***Entering debugger because we encountered a fatal error.
** Exiting the debugger will exit make with exit code 2.
popiso
remake<21>
then for testing purpose I removed sixth target '/raw/ops-xxxx/media' but error still says the same
You say that "it calls pop_iso_XXXX 4 times as it suppose to".
That proves that the problem is not in this foreach(). If it were, I would expect that the foreach would not get expanded at all.
The following brief, standalone Makefile, works correctly and gives the expected results without errors:
_a_pops_roles=foo bar
country=a
popiso: $(foreach x, $(_$(country)_pops_roles), pop_iso_$(x))
pop_iso_foo:
echo 1
pop_iso_bar:
echo 2
This usage is identical to what you have.
Look for other foreach loops in your Makefile, where the problem actually is.
For example: you have another call on the same line to $(isomedia). If this macro expands out to a foreach, and it has a syntax error, this would be reported as an error on this line even though the typo is somewhere else.
You can't always trust line numbers.

What does this bash script command mean (sed - e)?

I'm totally new to bash scripting but i want to solve this problem..
the command is:
objfil=`echo ${srcfil} | sed -e "s,c$,o,"`
the idea about the bash script program is to check for the source files, and check if there is an adjacent object file in the OBJ directory, if so, the rest of the program runs smoothly, if not, the iteration terminates and skips the current source file, and moves on to the next one.. it works with .c files but not on the headers, since the object filenames depend on .c files.. i want to write this command so it checks the object files not just the .c but the .h files too.. but without skipping them. i know i have to do something else too, but i need to understand what this line of command does exactly to move on. Thanks. (Sorry for my english)
UPDATE:
if test -r ${curOBJdir}/${objfil}
then
cp -v ${srcfil} ./SAVEDSRC/${srcfil}
fdone="NO"
linenums=ALL
else
fdone="YES"
err="${curOBJdir}/${objfil} is missing - ${srcfil} skipped)"
echo ${err}
echo ${err} >>${log}
fi
while test ${fdone} == "NO"
do
#rest of code ...
here is the rest of the program.. i tried to comment out the "test" part to ignore the comparison just because i only want my script to work on .h files, but without checking the e.g abc.h files has an abc.o file.. (the object file generation is needed because the end of the script there's a comparison between the hexdump of the original and modified object files). The whole script is for changing the basic types with typedefs like int to sint32_t for example.
This concrete command will substitute all c's right before line-end to o:
srcfill=abcd.c
objfil=`echo ${srcfil} | sed -e "s,c$,o,"`
echo $objfil
Output:
abcd.o
P.S. It uses a different match/replace separator: default is / but it uses ,.

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

Resources