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
Related
I'm really struggling in understanding why the following makefile won't work:
all: buildFolders main.out
mv main.out build/
-echo "File compiled"
buildFolders:
mkdir -p build src
cp *.c src/
%.s: %.c
gcc -S $< -o $#
%.out: src/%.s
gcc $< -o $#
It is executed in a folder containing only the makefile and a main.c file. It should build the src and build folder, copy the main.c in the src folder and then start compiling the main.out. Unfortunately it throws the error "no rule to make target 'main.out'". Since I have the %.out that matches 'main.out' I don't see why it gives me that error. Instead it should look for the src/main.s file, create it and then use it to generate the main.out.
What am I doing wrong? Thanks
You have a number of problems.
First, listing prerequisites in order doesn't create a dependency relationship. If, for example, you ever wanted to enable parallel builds then this:
all: buildFolders main.out
doesn't force the buildFolders target to be built before main.out. These two targets both must be built before all but this doesn't tell make that there's any relationship between buildFolders and main.out. If buildFolders must be completed before main.out can be built then main.out must list buildFolders as a prerequisite.
Second, you haven't told make how to build a file src/main.c. It's built as a side-effect of the buildFolders target, but make can't know that. You need to explain to make that this file can exist. I recommend adding a rule:
src/%.c: %.c
mkdir -p src
cp $< $#
and removing the buildFolders target altogether.
However, I really question why you want to do this anyway. What's the point of copying the source files in the current directory to some sub-directory to build them? It's dangerous and confusing to have multiple copies of source files lying around because they can get out of sync with each other, then you're building older versions and you spend hours trying to understand why something doesn't work. It's a really bad idea.
I was given a makefile that looks like this, and told not to change it.
all: clean flex scanner.lex bison -d parser.ypp g++ -std=c++11 -o hw2 *.c *.cpp clean: rm -f lex.yy.c rm -f parser.tab.*pp rm -f hw2
I am trying to run this makefile in a folder with files named: scanner.lex, parser.ypp, output.hpp and output.cpp
I copied it to a file like this:
all:
clean flex scanner.lex bison -d parser.ypp g++ -std=c++11 -o hw2 *.c *.cpp
clean:
rm -f lex.yy.c rm -f parser.tab.*pp rm -f hw2
When I run the make command in my terminal I get an error:
clean flex scanner.lex bison -d parser.ypp g++ -std=c++11 -o hw2 *.c *.cpp
/bin/sh: clean: command not found
make: *** [all] Error 127
Am I doing something wrong? Again, I was given this line and told not to change it.
Thanks a lot.
Line breaks are essential in most computer environments. If you were given a Makefile without the line breaks and you try to cut it randomly you will have difficulties before if finally works. Try this, maybe:
all: clean
flex scanner.lex
bison -d parser.ypp
g++ -std=c++11 -o hw2 *.c *.cpp
clean:
rm -f lex.yy.c
rm -f parser.tab.*pp
rm -f hw2
And use tabs to indent the indented lines, not spaces.
Explanations: all and clean are what is called a target in make parlance. They are the names of the things you want make to do. clean to delete some files, all to do everything else. The
target: prerequisite1 prerequisite2...
recipe1
recipe2
...
template is the basic make template. It means that target depends on prerequisite1, prerequisite2 and that in order to build it make shall pass recipe1 to the shell for execution, then recipe2...
Note that this Makefile is poorly written. As all and clean are not real file names they should be declared as phony, such that, if a file with that name exists make does the job anyway. As is, it wouldn't. Give it a try:
$ make all
$ touch clean
$ make clean
make: 'clean' is up to date.
See? Because a file named clean exists you cannot make clean anymore, make considers that there is nothing to do for clean. Add this at the beginning of your Makefile:
.PHONY: all clean
A second issue is that make works by comparing last modification times of targets and prerequisites to decide if targets must be rebuilt or not. With your Makefile make will always recompile everything, even if the inputs did not change and the outputs are up-to-date. This is a waste. A better (but untested) Makefile would be something like:
.PHONY: all clean
CFILES := $(filter-out lex.yy.c,$(wildcard *.c))
CPPFILES := $(filter-out parser.tab.cpp,$(wildcard *.cpp))
all: hw2
hw2: lex.yy.c parser.tab.cpp $(CFILES) $(CPPFILES)
g++ -std=c++11 -o $# $^
lex.yy.c: scanner.lex
flex $<
parser.tab.cpp: parser.ypp
bison -d $<
clean:
rm -f lex.yy.c
rm -f parser.tab.*pp
rm -f hw2
Understanding it and why it is better is left as an exercise.
All I want to do is gather source files from different source directories into one folder and then do the build of those make files. After a make clean I have to run make command twice to do the build.
So first I run make clean, then i run make, which throws an error saying no -o files found. But when iIrun the make again, the build goes through and generates the build files.
My makefile looks like below
.PHONY: dirs all clean
all: dirs $(OBJ_DIR) $(OBJ_FILES)
"$(CC) -rvn fLib.a $(OBJ_FILES)
# clean build target. Remove all files without reporting errors in case they don't exist.
clean:
#rm -rf fLib.a $(OBJ_DIR)
# Build target for creating flat header file folder for SharedTrackerAPI (FLAT_INC_DIR)
# due to too long paths in Windows 7 build
dirs:
#echo 'Making flat source and header folders.'
#mkdir -p $(OBJ_DIR)
#for f in $(SRC_FILES); do cp $$f $(OBJ_DIR); done
#mkdir -p $(FLAT_INC_DIR)
#OLD_CWD=$(CURDIR)
#cd $(FLAT_INC_DIR)
#find $(STA_RADAR_TRACKER_IFACE) -name '*.h' | xargs -i cp -l {} $(FLAT_INC_DIR)
#cd $(OLD_CWD)
$(OBJ_DIR)/%.o: $(OBJ_DIR)/%.cpp
"$(TASKING_CTC_BIN)"/cctc.exe $(CXXFLAGS) -c -o $# $< $(CC_INCLUDE_PATH)
What am I doing wrong that I have to run make twice after a make clean.
The problem is that although dirs will place the source files in the flat source directory, Make doesn't know that. Before it executes the dirs rule, it has already determined that it knows no way to build the object files.
The quick and dirty solution is to tell Make "trust me, it'll be fine"; one way to do that is to modify the object rule like this:
$(OBJ_DIR)/%.o:
"$(TASKING_CTC_BIN)"/cctc.exe $(CXXFLAGS) -c -o $# $(OBJ_DIR)/$*.cpp $(CC_INCLUDE_PATH)
If you stop there, you will have a working solution.
If you want a more clean, efficient and flexible makefile, you must rethink the approach to finding source files. I see no good reason to use the flat source file approach, but if you really want to use it, here is a good way:
vpath %.cpp $(dir $(SRC_FILES))
$(OBJ_DIR)/%.cpp: %.cpp
#cp $< $#
Now you can get rid of dir and use your unmodified object rule:
$(OBJ_DIR)/%.o: $(OBJ_DIR)/%.cpp
"$(TASKING_CTC_BIN)"/cctc.exe $(CXXFLAGS) -c -o $# $< $(CC_INCLUDE_PATH)
How to handle the header files (FLAT_INC_DIR) is up to you, but I recommend vpath again.
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 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).