I am trying to make a makefile that will ask the user for the name of the input and append this to create a $$(file).py but when I try and run this with "make do"
I get this error
do :
#echo "What is the name of the file?: "; \
read file; \
touch $$(file).py
Thank you!
Try this way:
.PHONY: do
do:
#echo "What is the name of the file?: "; \
read file && touch "$${file}.py"
.PHONY is to identify that "do" is not a file that make should look for, this will solve your error. [more info]
I made some changes too, by putting together the read and touch I removed weird outputs in between the 2 commands.
Related
I am reading this https://makefiletutorial.com/ makefile tutorial.
With this exmaple:
some_file:
echo "This line will only print once"
touch some_file
This file will make some_file the first time, and the second time notice it’s already made, resulting in make: 'some_file' is up to date.
While with this example:
some_binary: ../headers blah.h
touch some_binary
../headers:
mkdir ../headers
blah.h:
touch ../headers/blah.h
clean:
rm -rf ../headers
rm -f some_binary
Why don't I get 'xxxx' is up to date notice? My output is:
tianhe#tianhe-windy:~/Desktop/learnMake/lala$ make
mkdir ../headers
touch ../headers/blah.h
touch some_binary
tianhe#tianhe-windy:~/Desktop/learnMake/lala$ make
touch ../headers/blah.h
touch some_binary
tianhe#tianhe-windy:~/Desktop/learnMake/lala$
I expect to get xxx is up to date notice the second time I run make, just like the first example.
Very simple: because blah.h is not the same thing as ../headers/blah.h.
So a rule like this:
blah.h:
touch ../headers/blah.h
is wrong: the target tells make "this recipe will create a file named blah.h", but the recipe actually creates a file named ../headers/blah.h.
So the next time make runs, it looks for blah.h again: if it was found then you'd get a message saying that things were up to date. But since it's not found, make will try to make it again because it's clearly not up to date (since it doesn't exist).
I want to run makefile with input variable. What I want is that if I write down the project name, a folder with that name will be created.
So I write read command:
CC = gcc
CFLAGS = -W -Wall
FILE := hi
src = $(wildcard *.c)
OBJ = $(src:.c=.o)
all : $(FILE)
$(FILE) : $(OBJ)
$(CC) $(CFLAGS) -o $# $^
.PHONY: clean
clean :
rm *.o $(FILE)
move :
mkdir -p ../../bin/$(FILE);
mkdir -p ../../exe/$(FILE);
mv *.o ../../bin/$(FILE);
mv $(FILE) ../../exe/$(FILE)
afterclean :
rm ../../bin/$(FILE)/*.o;
rm ../../exe/$(FILE)/$(FILE)
execute :
./../../exe/$(FILE)/$(FILE)
read :
#read -p "Enter : " enter; \
$(FILE) := enter; \
echo $FILE
What I wanna do is if I get FILE name through read I want to change FILE variable, but I can't change it. How can I do that?
Well in short, you cannot easily do that (and you should likely not want to, scroll down for rationale). If you have a closer look at your Makefile you'd notice that you're mixing make and shell syntax... and their contexts.
In your case, it literally passes the following string to shell (value of SHELL, likely defaults to /bin/sh) with -c:
read -p "Enter : " enter; \
hi := enter; \
echo ILE
Which shows the effects of the intermixed syntax. $(FILE) (value hi) and $F (unset -> empty) are make variables substituted by make before invoking shell. (while read into enter variable is not used at all and instead literal string enter is used in attempted make variable assignment inside that running shell.)
If you wanted to run a shell command and assign a value from what it has done / learned to a make variable, you would have to do so using shell function (or generate a (temporary) file you would include, but that's even messier):
FILE := $(shell read -p "Enter: " enter ; echo $${enter})
That however always asks... unless you use conditional assignment (?=) in which case you could choose already from the command line (make FILE=something, at which point we're about to close the circle). I am generally unsure what your intentions were how to tell make when to ask and when to use default value of hi.
That leads me to why this notion sounds suspect to me to start with and why suggestion made by #HolyBlackCat is a superior way of customizing invocation of make.
Also any runtime user interactions generally break automation (which is what we have make for) and also make builds non-reproducible. So, they better are to be avoided.
In other words, if you really had to, I'd say write an interactive_make_call.sh around it for this type of invocation:
#!/bin/bash
read -p "Enter : " enter
make FILE="${enter}" "$#"
Or even:
#!/bin/bash
read -p "Enter : " enter
if [[ -n "${enter}" ]] ; then
make FILE="${enter}" "$#"
else
make "$#"
fi
To fallback on the default value of FILE from the Makefile if you just press enter.
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 have the following Makefile:
cells.csv:
echo cellA > cells.csv
echo cellB >> cells.csv
echo cellC >> cells.csv
echo cellD >> cells.csv
mkdir -p cellA
mkdir -p cellB
mkdir -p cellC
mkdir -p cellD
%/cell_gen: cells.csv
echo '$# generated' > $#
%/cell_gds: %/cell_gen
cat $(#D)/cell_gen > $#
echo $#_GDS >> $#
The idea is to generate 'cells' in two step (called [cell]_gen and [cell]_gds) while the cells list is
not known at the beginning of make.
Here: the target 'cells.csv' is human readable (just echo) , but in
the general case, I expect something complexe, itselft resulting of previous steps ...etc..: not readable.
Each step of 'cell' should be stored in the directory named [cell] .
I don't understand why in this case, if I ask for "make cellA/cell_gds" then it looks like
the steps are all executed: I get the csv file and I get cellA/cell_gds.
...but I can't explain why I don't get cellA/cell_gen ??
... Despite I can see "echo 'cellA/cell_gen generated' > cellA/cell_gen" during make execution , and i really get "cellA/cell_gen generated" instide the cellA/cell_gds
Does anybody knows why there is no file cellA/cell_gen ??
thanks !
The file cellA/cell_gen is an intermediate file; you didn't explicitly ask for it, Make deduced that it was necessary as part of a chain of pattern rules. So by default, Make will delete it once the "real" target, cellA/cell_gds, is complete.
To prevent this, just add the line
.PRECIOUS: %/cell_gen
I'm making a Makefile that moves an output file (foo.o) to a different directory (baz).
The output file moves as desired to the directory. However since make won't recompile the output file if I type make again, mv gets an error when it tries to move the non-existent empty file to the directory baz.
So this is what I have defined in my rule make all after all compilation:
-test -e "foo.o" || mv -f foo.o ../baz
Unfortunately, I'm still getting errors.
Errors in Recipes (from TFM)
To ignore errors in a recipe line, write a - at the beginning of the
line's text (after the initial tab).
So the target would be something like:
moveit:
-mv foo.o ../baz
I notice nobody has actually answered the original question itself yet, specifically how to ignore errors (all the answers are currently concerned with only calling the command if it won't cause an error).
To actually ignore errors, you can simply do:
mv -f foo.o ../baz 2>/dev/null; true
This will redirect stderr output to null, and follow the command with true (which always returns 0, causing make to believe the command succeeded regardless of what actually happened), allowing program flow to continue.
+#[ -d $(dir $#) ] || mkdir -p $(dir $#)
is what I use to silently create a folder if it does not exist. For your problem something like this should work
-#[ -e "foo.o" ] && mv -f foo.o ../baz
-test -e "foo.o" || if [ -f foo.o ]; then mv -f foo.o ../baz; fi;
That should work
Something like
test -e "foo.o" && mv -f foo.o ../baz
should work: the operator should be && instead of ||.
You can experiment with this by trying these commands:
test -e testfile && echo "going to move the file"
test -e testfile || echo "going to move the file"
I faced the same problem and as I am generating files, they always have different time. Workaround is set the same time to the files: touch -d '1 June 2018 11:02' file. In that case, gzip generates the same output and same md5sum. In my scenario, I don't need the time for the files.