I would like to modify a Makefile command:
-rm -f $(OBJS)
-rm -f $(OBJS:.o=.mod)
The first removes all filenames.o and the second removes all filenames.mod. However, I would like to
modify the second such that I get: mod_filenames.mod, i.e., add the string "mod_".
I tried: -rm -f mod_$(OBJS:.o=.mod), but this only affected the first file in the list. But I'm jet guessing here. If anyone could suggest a wide site where such programming is explained, I would grateful.
GNU Make Manual.
There is also GNU Make Unleased book and GNU Make Standard Library.
See 8.3 Functions for File Names of the manual, you can use $(addprefix ...) (there are other ways) to get:
-rm -f $(OBJS)
-rm -f $(addprefix mod_,$(OBJS:.o=.mod))
It would be even better to use $(RM) (it's usually rm -f):
-$(RM) $(OBJS)
-$(RM) $(addprefix mod_,$(OBJS:.o=.mod))
The GNU make manual describes all these things.
You can use patterns to get what you want:
-rm -f $(OBJS:%.o=mod_%.mod)
Writing $(OBJS:.o=.mod) is just shorthand for $(OBJS:%.o=%.mod).
Related
when I try to do make for the makefile it shows me (makefile error missing separator. stop)
my make file is
PROGS = $(patsubst %.c,%,$(SRCS))
all: $(PROGS)
%: %.c
arm-linux-gnueabihf-gcc --static $< -o $#
clean:
rm -f $(PROGS)
I try to use the following command but I could not solve my problem
cat -e -t -v Makefile
SRCS^I=^I$(wildcard^I*.c)^I$
PROGS^I=^I$(patsubst^I%.c,%,$(SRCS))$
all:^I$(PROGS)^I$
%:^I%.c^I$
arm-linux-gnueabihf-gcc^I--static^I$<^I-o^I$#^I$
clean:^I$
rm^I-f^I$(PROGS)^I$ ```
Crazy. You have TAB characters in all the places you don't need them, and you don't have TAB characters in any of the (two) places you must have them. I don't know how you managed that.
In your makefile above the places you MUST have TAB chars are the recipe lines. In other words, your makefile should look like this from cat -e -t -v Makefile:
SRCS = $(wildcard *.c)$
PROGS = $(patsubst %.c,%,$(SRCS))$
all: $(PROGS)$
%: %.c$
^Iarm-linux-gnueabihf-gcc --static $< -o $#$
clean:$
^Irm -f $(PROGS)$
As for configuring your text editor, there are a ton of text editors out there, even on Ubuntu, and we have no idea which one you are using.
I recommend you use a programmer's editor, which has a special mode that understands makefile syntax.
I've seen a few approaches to making output directories in Make.
These include making all directories ahead of time outside of any rule, and
making an object's destination directory as part of the object's rule.
Both of these approaches involve making directories that likely already exist.
Am I missing any gotchas or drawbacks that explain why I haven't seen the below approach?
.SECONDEXPANSION:
$(OBJDIR)%.o: %.c | $$(#D)/
# Compile command
.PRECIOUS: %/
%/:
# mkdir Command
make is very good at dealing with files. make is not very good at dealing with directories.
So treating directories as implementation detail internal to the target rule makes sense, because then make never has to consider the directory at all:
MKDIR_P = mkdir -p
$(objdir)%.o: %.c
#$(MKDIR_P) $(#D)
$(COMPILE.c) -o $# -c $<
Note that the processing and IO required for the mkdir -p can be neglected next to the processing and IO required for the compilation.
The problem with directories is that (contrary to any other target) you don't care for their timestamp, you only need them to exist. Many Makefiles get directories somehow wrong, and creating them over and over again is what you observe, so make will never detect "Nothing to be done for ...".
In fact, the only thing you need for correct handling of directories with GNU make is an "order only dependency", like shown in your example. The trailing slash normally isn't needed (you seem to use it in order to have a pattern rule, I'm not sure whether this works), and you don't need .PRECIOUS either. Your trick with .SECONDEXPANSION looks quite neat, I guess this will work, given the pattern rule indeed works that way (didn't try).
For an alternative, most Makefiles that handle directories correctly take a simpler approach by concatenating all needed output directories for a rule in a single variable and use this variable as a target for another rule, e.g. like in this simplified example:
MODULES:=src/main
OBJDIR?=obj
OBJS:=$(addprefix $(OBJDIR)/,$(addsuffix .c,$(MODULES)))
DIRS:=$(sort $(addprefix $(OBJDIR)/,$(dir $(OBJS))))
TARGET:= myprogram
all: $(TARGET)
myprogram: $(OBJS)
$(CC) -o$# $^
$(DIRS):
mkdir -p $(DIRS)
$(OBJDIR)/%.o: %.c Makefile | $(DIRS)
$(CC) -c -o$# $<
clean:
rm -fr $(OBJDIR)
.PHONY: all clean
I'm searching for a way to simplify the way I work on projects. so i was wondering, is there a way to use a Makefile to generate and update a .tar.gz file of the entire project?
edit
i'm working on C solutions
Err... something like this?
project.tar.gz: $(FILELIST)
tar uzf $# $^
Rough, untested, about as precise as your question. Adjust to unvoiced requirements as appropriate. ;-)
Here is a simple and clean makefile example can be used.Simply add the directory or file names you want to tar to FILES_TO_TAR
HEADERS = header.h
FILES_TO_TAR = README.txt main.c header.h
default:
gcc main.c $(HEADERS) -o output_name
clean:
-rm -f *.o
cleanall:
-rm -f *.o
-rm -f output_name
cleanandtar:
-rm -f *.o
-rm -f output_name
tar -zcvf YOUR_TAR_NAME.tar.gz $(FILES_TO_TAR)
I would suggest that you also compress using the maximum compression setting for the final release (assuming that you’re publishing). On a modern computer it shouldn’t take that much more and it’s easy to set via the -9 flag
the makefile below processes files matching the patterncontent/%.md and outputs the targets in the html directory. Source files are named with the convention of putting a leading number in front of them, like content/01.index.md or content/O2.second-page.md and so on. I would like to remove the leading 0x. number sequence in the target file. For instance, content/01.index.html would generate html/index.html.
How can I do this?
Thanks
MD_FILES = $(shell find content/ -type f -name '*.md')
HTML_FILES = $(patsubst content/%.md, html/%.html, $(MD_FILES))
all: $(HTML_FILES) html/static
html/%.html : content/%.md
mkdir -p $(#D)
python generator/generate.py $< $#
.PHONY: html/static
html/static :
rsync -rupE generator/static html/
.PHONY: clean
clean:
rm -fr html
Replace:
html/%.html : content/%.md
mkdir -p $(#D)
python generator/generate.py $< $#
with:
html/%.html : content/%.md
mkdir -p $(#D)
file='$(#F)'; python generator/generate.py $< "$(#D)/${file#*.}"
Unfortunately, I can't think of a good way of doing that in make itself. I can think of one way but it isn't as simple as that escaping and it isn't safe for files with spaces (not that that matters much here since make already can't handle those).
IMHO, it is a bad idea to use find or wildcards to list files in makefiles. This is because developers have temporary or debugging files sometimes. It is best to list files explicitly. This way, it forces the developer to think about their intent.
If you agree to list files explicitly, then in this case it is best to list the target files, rather than source files, and here is your answer:
HTML_FILES := html/index.html html/second-page.html
.SECONDEXPANSION:
$(HTML_FILES): html/%.html : $$(wildcard content/*.$$*.md)
(put recipe here, using $# and $<)
I'm using GNU Make to build three different editions of a static html document.
I use Less as a CSS preprocessor.
My directory structure looks like this:
Makefile
160x600/style.less
300x250/style.less
728x90/style.less
This is my Makefile:
LESSC=lessc -x # use -x for debugging
.PHONY: all clean
all: 160x600 300x250 728x90
%.css: %.less
$(LESSC) $< > $#
160x600: 160x600/style.css
300x250: 300x250/style.css
728x90: 728x90/style.css
clean:
rm -f 160x600/*.css
rm -f 300x250/*.css
rm -f 728x90/*.css
This way, I can use make 160x600 to build style.css from style.less.
But I don't want to explicitly list a target rule for each directory. Instead, I tried adding this rule instead of the three directory specific ones:
%: %/style.css
But that does not work. I assume it's clear from that example what my goal is. Is there a way to accept any directory as a target, so that I just have to list the directory names in the all: rule?
use static pattern rule:
res_dirs = 160x600 300x250 728x90
$(res_dirs): %: %/style.css