I try to setup a target in MakeFile to call 2 targets in the same Makefile.
build: copy
copy2
copy:
cp dir/* ${DIR}
copy2:
cp dir2/* ${DIR}
But when I run make in shell, I see it only execute the first target and it said
make: copy2: No such file or directory make: *** [build] Error 1
I basically change copy2 to same as copy to debug. But I don't see why Make can't find the 2nd target 'copy2'?
Can you please tell me what am I missing?
The copy2 on line 2 is a command that make will try to execute. Presumably that command doesn't exist on your system, so make throws the error "copy2" - command not found.
Do this instead:
build: target1 target2:
echo Both targets have been run!
target1:
echo Running target 1
target2:
echo Running target 2
Output:
echo Running target 1
Running target 1
echo Running target 2
Running target 2
echo Both target2 have been run!
Both target2 have been run!
Related
I am trying to create a Makefile target which will call itself with different options.
# Include config.mk which sets design-specific variables
`include $(CONFIG)
# This command runs the script once with current options
$(LOG_DIR)/compare.log: $(RESULTS_DIR)/final.bin
tclsh $(UTILS_DIR)/script.tcl | tee $#
# Alias for above command
compare: $(LOG_DIR)/compare.log
# This command runs make once for each config file
.PHONY: compare_all
compare_all:
for config in designs/*/config.mk; do \
$(MAKE) CONFIG=$$config compare; \
done
$(UTILS_DIR)/compare_all.py
The problem is that the compare_all target works as expected, but it always thinks that the sub-make targets are out-of-date.
When I run, for example
make CONFIG=designs/a/config.mk compare
make CONFIG=designs/b/config.mk compare
make CONFIG=designs/c/config.mk compare
I get:
make: Nothing to be done for 'compare'.
make: Nothing to be done for 'compare'.
make: Nothing to be done for 'compare'.
But when I run make compare_all -n, I get
tclsh utils/script.tcl | tee logs/a/compare.log
tclsh utils/script.tcl | tee logs/b/compare.log
tclsh utils/script.tcl | tee logs/c/compare.log
showing that it's going to rebuild all designs even though they're already up-to-date.
I have the following lines in my makefile:
.PHONY : clean
clean:
#echo "Running Clean"
$(shell if [ -e exe ]; then rm exe; else echo "no files"; fi)
When I run:
make clean
I get the following output on the shell
Running Clean
no files
make: no: Command not found
Makefile:22: recipe for target 'clean' failed
make: *** [clean] Error 127
Any suggestions?
The problem is the use of $(shell ...). What you want is:
.PHONY : clean
clean:
#echo "Running Clean"
#if [ -e exe ]; then rm exe; else echo "no files"; fi
As far as an explanation of what's going wrong -- when you first run the clean target, make will expand all make variables and functions in the recipes before it starts running them -- because $(shell ...) only has one $, this is considered a make function. Make runs the command, which outputs no files to stdout, and replaces the call with that string, and then starts executing the recipes... So now make sees the following:
clean:
#echo "Running Clean"
no files
When it tries to run no files, due to the lack of a #, it echos the line to the screen, and then passes the command to the shell. Because the shell doesn't recognize the keyword no it outputs the error you're seeing. Make itself then fails because the shell returned an error.
Hey all I'm the same guy who asked this question but I found an answer right after I posted this, I think I'll leave this up (unless this is against stackoverflow etiquette) in case someone else has the same problems. My solution was echoing the string to stdout.
$(shell if [ -e exe ]; then rm exe; else echo "no files" >&2; fi)
I am new to makefile.
All I want is, when a specific C file will be changed, I want to run one command. And finally from one folder, any of the C file will be changed then I want to run the same command with that filename.
.e.g.
ceedling test:filename
I have simple file called unittest.mk. I am not sure the following approach is correct or not.
I am ruinning the following command to run this file.
make -f unittest.mk StartUnitTest
Here is the unittest.mk file:
TEST_OBJS += \
D:\ModApp\Apps\Paymark\ModApp_Paymark\build\test\out\test_txn_admin.o
D:\ModApp\Apps\Paymark\ModApp_Paymark\build\test\out\test_txn_admin.o: D:\ModApp\Apps\Paymark\ModApp_Paymark\test\test_txn_admin.c
echo $(*F)
echo $#
echo $<
StartUnitTest:
#echo Start Unit Test
$(TEST_OBJS)
#echo End Unit Test
When I run this file, it is giving the following error.
Start Unit Test
D:\ModApp\Apps\Paymark\ModApp_Paymark\build\test\out\test_txn_admin.o
D:\ModApp\Apps\Paymark\ModApp_Paymark\build\test\out\test_txn_admin.o
process_begin: CreateProcess(D:\ModApp\Apps\Paymark\ModApp_Paymark\build\test\out\test_txn_admin.o, D:\ModApp\Apps\Paymark\ModApp_Paymark\build\test\out\test_txn_admin.o, ...) failed.
make (e=193): Error 193
make: *** [StartUnitTest] Error 193
Finally once this will work, actually I want a target pattern with % as the following:
D:\ModApp\Apps\Paymark\ModApp_Paymark\build\test\out\%.o: D:\ModApp\Apps\Paymark\ModApp_Paymark\test\%.c
echo $(*F)
echo $#
echo $<
I have found the issue. I have changed the target "StartUnitTest" to the following and it is working now. Removed the echo messages.
StartUnitTest: $(TEST_OBJS)
Thank you MadScientist. the "make -d" does helped me to find the issue.
I wanted to write some Makefile for testing C code via Unity test framework.
However when I want to test it I get the message make: *** No rule to make target 'unity_build/results/test_unity_dumb_example.unity_res', needed by 'unity_test'. Stop. . I can not figure out what is wrong because there is the rule for files that match the pattern: $(UNITY_PATHR)%.unity_res:.
Here is beginning of my Makefile:
UNITY_PATHU = ${UNITY_INSTALL_DIR}/
UNITY_PATHS = src/
UNITY_PATHS += src/unity_dumb_example/
UNITY_PATHT = unity_test/
UNITY_PATHB = unity_build/
UNITY_PATHD = unity_build/depends/
UNITY_PATHO = unity_build/objs/
UNITY_PATHR = unity_build/results/
UNITY_BUILD_PATHS = $(UNITY_PATHB) $(UNITY_PATHD) $(UNITY_PATHO) $(UNITY_PATHR)
# Tell compiler where to look for all test files
UNITY_SRCT = $(wildcard $(UNITY_PATHT)*.c)
UNITY_COMPILER=gcc -c
UNITY_LINKER=gcc
UNITY_DEPEND=gcc -MM -MG -MF
UNITY_CFLAGS=-I. -I$(UNITY_PATHU) -I$(UNITY_PATHS) -DTEST
UNITY_RESULTS = $(patsubst $(UNITY_PATHT)test_%.c,$(UNITY_PATHR)test_%.unity_res,$(UNITY_SRCT))
unity_test: $(UNITY_BUILD_PATHS) $(UNITY_RESULTS)
#echo "-----------------------\nIGNORES:\n-----------------------"
#echo `grep -s IGNORE $(UNITY_PATHR)*.unity_res`
#echo "-----------------------\nFAILURES:\n----------------------"
#echo `grep -s FAIL $(UNITY_PATHR)*.unity_res`
#echo "\nDONE"
$(UNITY_PATHR)%.unity_res: $(UNITY_PATHB)%.out
./$< > $# 2>&1
In GNU make manual I have read
The target is a pattern for matching file names; the ‘%’
matches any nonempty substring, while other characters match only themselves.
I do not understand why make complains because there is no misspell.
EDIT:
After full clean the output is as follows:
mkdir -p unity_build/
mkdir -p unity_build/depends/
mkdir -p unity_build/objs/
mkdir -p unity_build/results/
make: *** No rule to make target 'unity_build/results/test_unity_dumb_example.unity_res', needed by 'unity_test'. Stop.
All the needed paths exist.
When I run make in debug mode -d I can see that make is trying pattern rule with stem test_test_unity_dumb_example instead of test_unity_dumb_example, for example:
Trying pattern rule with stem 'test_test_unity_dumb_example'
test_test_ was my mistake but I have fixed it. I still can't make it work.
When I run with -p I can find something like this in the output:
# Implicit Rules
unity_build/results/%.unity_res: unity_build/%.out
# recipe to execute (from 'Makefile.unity', line 30):
./$< > $# 2>&1
SOLVED
The problem was with the prerequisite of the prerequisite of the $(UNITY_PATHB)%.out. Precisely, path to one crucial source file was ${UNITY_INSTALL_DIR}/src instead of ${UNITY_INSTALL_DIR}/ .
However I still find it weird that make was complaining about the rule to target that is 2 level above the target that could not be built.
It is hard to believe, but it seems to me that the common Makefile idiom "> $#" is wrong. In particular, a target whose rule has a command that fails but uses this redirection will fail the first time around but not subsequent times. This is because even though the command fails, the redirection "succeeds" in the sense of creating an up-to-date (albeit zero-length) target.
It seems to me that the correct thing to do is to redirect to a temporary and on success rename this temporary to the target.
Here's and example Makefile:
bad-target:
command-that-will-fail > $#
good-target:
command-that-will-fail > $#.tmp || ( rm $#.tmp; false )
mv $#.tmp $#
clean:
rm -f bad-target good-target
And here's a sequence of commands illustrating the problem and its solution:
$ make clean
rm -f bad-target good-target
$ make bad-target
command-that-will-fail > bad-target
/bin/sh: command-that-will-fail: not found
make: *** [bad-target] Error 127
$ make bad-target
make: `bad-target' is up to date.
$ make good-target
command-that-will-fail > good-target.tmp || ( rm good-target.tmp; false )
/bin/sh: command-that-will-fail: not found
make: *** [good-target] Error 1
$ make good-target
command-that-will-fail > good-target.tmp || ( rm good-target.tmp; false )
/bin/sh: command-that-will-fail: not found
make: *** [good-target] Error 1
If you're using GNU make, you may also add the .DELETE_ON_ERROR special target to your makefile. This will cause make to delete the output file if there is an error during execution of the commands for that file:
all: foo.o
foo.o:
echo bogus! > $#
exit 1
.DELETE_ON_ERROR:
Here's an example of this makefile in action:
$ gmake
echo bogus! > foo.o
exit 1
gmake: *** [foo.o] Error 1
gmake: *** Deleting file `foo.o'
This is easier to use than your version, since you need not modify every rule in the makefile.
Perhaps this is an obvious solution, but many common commands provide a -o flag or similar. So instead of output redirection, you should use the rule:
target: target.dep
some_command target.dep -o $#
If the command fails, the output file will not be created. I haven't had many occasions to use output redirection in makefiles.
Yes, this is definitely something to bear in mind.
But sometimes you're OK with the command failing and you don't want to retry it, because the error would only repeat itself.
In that case leaving an empty result is OK. Just don't make subsequent processing count on there being meaningful content in that file.