I created a batch file, for a project I am working on, which works as expected from a command in MINGW64, but not from a command in CMD.
I have the same problem with 'make clean', which, only in CMD prints an error.
make[1]: Entering directory 'C:/Users/src/Probs'
rm -rf ./obj ./mod
process_begin: CreateProcess(NULL, rm -rf ./obj ./mod, ...) failed.
make (e=2): The system cannot find the file specified.
make[1]: *** [makefile:114: clean] Error 2
make[1]: Leaving directory 'C:/Users/src/Probs'
make: *** [makefile:56: clean] Error 2
Would you please comment on that?
When you run your script in command prompt it doesn't recognize the rm command. It doesn't exist on command prompt.
You can change it to use rd instead:
rd /s /q "path"
Or you can install cygwin, which has rm as well as ls etc...
And add "Cygwin\bin" to your Environment Path variable
Related
I'm tyring to exclude test files in my makefile shell command.
When i run the following makefile target,
api-run:
${API_COMPOSE} sh -c "go run -mod=vendor cmd/serverd/*.go"
I get this error
go: cannot run *_test.go files (cmd/serverd/router_test.go)
make: *** [api-run] Error 1
I've tried adjusting the command into
api-run:
${API_COMPOSE} sh -c "for file in \$(ls cmd/serverd/*.go | grep -v _test.go); do go run -mod=vendor \$file; done"
but end up getting this error
sh: 1: Syntax error: "done" unexpected (expecting "do")
make: *** [api-run] Error 2
I'm preparing some latex files and decided to make some makefile to help me to compile and clean de latex files. So I created the following makefile
aula=listaProb
all: compile clean
compile:
pdflatex $(aula).tex
clean:
rm -rf !(makefile|$(aula).tex|$(aula).pdf) -v
But when I execute "make" I get the following mistake
rm -rf !(makefile|listaProb.tex|listaProb.pdf) -v
/bin/sh: 1: Syntax error: "(" unexpected
makefile:8: recipe for target 'clean' failed
make: *** [clean] Error 2
But the command
rm -rf !(makefile|listaProb.tex|listaProb.pdf) -v
works fine on the terminal.
What is wrong? I can't find any mistake :/..
Ps. I use this way to remove the files because I want to delete all but the specified files. It needs the command
shopt -s extglob
before use it. If anyone knows how to do it without use extglob, it would be nice.
Thanks
The problem is recipe commands are passed to /bin/sh which cannot process that syntax. You can change your Makefile to say:
clean:
bash -O extglob -c "rm -rf !(makefile|$(aula).tex|$(aula).pdf) -v"
To force this command to be run in bash with extglob on.
Or define SHELL variable for your make e.g. by running:
make SHELL="/bin/bash -O extglob" clean
Or adding:
SHELL := /bin/bash -O extglob
To your make file. The former option only affects shell invocation of that one command, the latter will apply to all your recipes (commands).
I tried to suppress an error from rm command by writing
Makefile:
...
clean: $(wildcard *.mod)
-rm $^ 2>/dev/null
...
I ran:
$ make clean
rm 2>/dev/null
make: [clean] Error 64 (ignored)
I still had gotten an error.
Anyway, when I tried
$ rm [some non-existent files] 2>/dev/null
on the bash shell, it just works fine.
How can I use 2>/dev/null inside a makefile?
2>dev/null will redirect the error output so you don't see it, it will not prevent the shell to raise the error level. And the - sign in front of your shell command will tell GNU make to continue even if the error level is raised but it will not either prevent the shell to raise it.
What you want is the shell not to raise the error level and this can be done like this :
Unix (credits to this answer)
-rm $^ 2>/dev/null ; true
Windows
-rm $^ 2>NUL || true
or if you don't have rm on Windows
-del /F /Q $^ 2>NUL || true
The message make: [clean] Error 64 (ignored) is being printed by make after it sees that your shell command has failed.
It will therefore not be affected by any redirection that you use in the recipe.
Two fixes:
Use the -f rm flag. rm -f never returns an error.
(Well, hardly ever anyway, and if it does you probably want to know about it!)
Stop the shell command returning an error: simply append || : to the command.
Say what? Well if the rm succeeds your job is done and make is happy. OTOH if rm fails, the shell runs the second command in the or.
: is a shell built-in that always succeeds, and is much preferable to true IMHO.
The first of these is best in this case,
though the second is a general, if somewhat less efficient, pattern.
.PHONY: clean
clean: ; rm -rf *.mod
I have a folder demo and inside that I have made a Makefile and various other files. Now I want to zip this folder for that I have written the following Makefile but it is always giving me error
Makefile-:
all:demo.tgz
demo.tgz:
cd ..
tar -cvzf demo.tgz demo/
error is "demo no file or directory"
can i anyone tell me what is wrong here.....
it is giving me the following error
jatinkhurana#jatinkhurana-HP-ProBook-4430s:~/Mtech1/SoftwareLab/makefile/demo$ make
cd ..
tar -cvzf demo.tgz demo/
tar: demo: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
make: *** [demo.tgz] Error 2
all:demo.tgz
demo.tgz:
( \
cd .. ; \
tar -cvzf demo.tgz demo/ ;\
)
Each line in a recipe will run in own environment. Changing the directory with cd will not change the environment for the next line of you recipe.
Simple pack your commands into braces an add ;\ at the end of each line. This will make it ONE command which runs in one shell environment.
Each line in a make file is run in a separate environment. This means that the cd .. doesn't change the current dir for the following commands. You have to force the commands to run in the same env by combining them.
demo.tgz:
cd .. && tar -cvzf demo.tgz demo/
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.