using MAKEFILE to copy files before compilation and delete them after - c

I am trying to copy files befoe compilation (I have two source files with same name so I copy the files to a files with a different name) and delete them at the end of the MAKEFILE.
I am trying to do the folliwng but probably there is mismatch in the execution order.
How can I do it correctly?
all: copy_dup_files $(dst_dir) $(APP_TARGET_LIB) delete_dup_files
copy_dup_files:
#echo "COPYING DUP FILES"
$(shell cp /aaa/hmac.c /aaa/hmac1.c )
$(shell cp /bbb/hmac.c /bbb/hmac2.c )
delete_dup_files:
#echo "DELETING DUP FILES"
$(shell rm /aaa/hmac1.c )
$(shell rm /bbb/hmac2.c )
Thanks

The purpose of $(shell) is to produce an output which Make reads. The recipe lines should not have this construct at all.
# this is evaluated when the Makefile is read
value := $(shell echo "Use the shell to produce a value for a variable")
# this is evaluated when you say "make foo"
foo:
echo 'No $$(shell ...) stuff here'
So, all the $(shell ...) stuff in your attempt gets evaluated when the Makefile is read, but before any actual target is executed.

Your makefile is trying to say /aaa/hmac1.c depends on /aaa/hmac.c.
Thus we have:
/aaa/hmac1.c: /aaa/hmac.c
cp $< $#
/bbb/hmac2.c: /bbb/hmac.c
cp $< $#
/aaa/hmac1.o /bbb/hmac2.o: %.o: %.c
gcc $< -o $#
myprog: /aaa/hmac1.o /bbb/hmac2.o
gcc $^ -o $#
This is clean and parallel safe (a good test of any makefile).
There are innumerable style improvements you could make, like
Get rid of the absolute paths
Use symbolic links instead of copying
Automatic dependency generation (for .h files, etc.)
Don't besmirch the source tree — put all the intermediate files (the .os and the temporary .cs) in their own build folder
&c. &c.

Related

How to modify makefile to compile changed source into object directory except for a list of files

I inherited a makefile that uses GNU Make 3.81. It is overly complicated, IMHO because it does not use patterns. In addition, it does not automatically create an object file directory when needed. I've looked at several examples and read the a GNU makefile manual, but still not seeing something that should be simple. There seem to be many ways recommended, but not clear what to use. I have about 60 c files that need to be compiled into a directory named obj. But, I don't want 6 test programs that have 'main' programs compiled into that directory. They are in a list called OTHERSRCS. I'd like to have the c files less the OTHERSRCS compiled into obj if anything changes in those files. Also, if the obj directory doesn't exist, I'd like to create it. The 'make clean' should remove that directory. I've used ANT with Java and can get the dependencies to work, but I'm not succeeding with this makefile. A simple example would be helpful that used some sort of exclusion along with the pattern for the c files.
In this simple example, the C source files in the current directory
are foo.c, bar.c, atest.c, anothertest.c. We have:
OTHERSRCS := atest.c anothertest.c
Each of the $(OTHERSRCS) is to be separatedly compiled and linked into
a program in current directory. All remaining C source files, whatever
the are, are to be compiled into a directory obj, which shall be
created when required, and the resulting object files all linked into
a program foobar.
Makefile
ALLSRCS := $(wildcard *.c)
OTHERSRCS := atest.c anothertest.c
foobar_SRCS := $(filter-out $(OTHERSRCS),$(ALLSRCS))
foobar_OBJS := $(addprefix obj/,$(foobar_SRCS:.c=.o))
PROGS := foobar atest anothertest
.PHONY: all clean
all : $(PROGS)
obj/%.o: %.c | obj
$(COMPILE.c) $< -o $#
obj:
mkdir -p $#
foobar: $(foobar_OBJS)
$(LINK.o) -o $# $^ $(LDLIBS)
clean:
rm -fr $(PROGS) obj
The default make runs like:
$ make
mkdir -p obj
cc -c foobar.c -o obj/foobar.o
cc -c foo.c -o obj/foo.o
cc -c bar.c -o obj/bar.o
cc -o foobar obj/foobar.o obj/foo.o obj/bar.o
cc atest.c -o atest
cc anothertest.c -o anothertest
and of course make foobar like the first 5 lines of that.
To understand the key details, see 4.3 Types of Prerequisites
and 8.2 Functions for String Substitution and Analysis
in the manual. No recipes need be written for the programs atest and anothertest in this example because they're correctly built by GNU make's default rules.
If you are going to rework your inherited makefile, consider rationalising the source tree, e.g. by at least not having test sources in the same directory as application sources.
Here's my Makefile
This should get you going. I tried to be as descriptive as I could.
Edit:
To exclude a .c file you can change:
SRC = $(shell find $(SRC_DIR) -name '*.c')
to
SRC = $(shell find $(SRC_DIR) -name '*.c' ! -iname 'myFile.c')

Script to compile C code

Usually if I want to compile a C program called number_input.c I would type
cc -o number_input number_input.c
I want to use my mac terminal to make a script so that I don't have to type that extra word. Originally I did this to save myself 1 sec of programming but ironically I've spent over 2 hrs trying to get this to work.
a= echo "$1" | rev | cut -c3- | rev
echo $a
cc -o $a $1
echo $1
This is my output:
number_input
clang: error: no input files
number_input.c
I can tell that the names are being inputted correctly but for some reason the cc command isn't taking in the value of $1? I am assuming that somehow the $1 isn't directly converted into a string or something like that but I am not sure.
Your error is on the first line, since you're not assigning anything to a:
a=$(echo "$1" | rev | cut -c3- | rev)
Would fix the problem (for well-behaved filenames, at least, since you're missing quotes further down in your script). A space after a means you're assigning an empty string to it and then running the commands in the pipeline.
Instead of going to all the effort of reversing the twice, just remove the last two characters with ${1%??}:
cc -o "${1%??}" "$1"
The most common tool to do this is make. It reads the recipes from a file named Makefile in the directory it is run, and performs any tasks necessary. It is smart enough to check the file timestamps to detect if or which parts of your projects need to be re-compiled. Here is an example Makefile:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := number_input
.PHONY: all clean
all: $(PROGS)
clean:
rm -f $(PROGS)
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Note that indentation in a Makefile must use tabs, not spaces. If you copy the above, and paste to a file, you will need to run sed -e 's|^ *|\t|' -i Makefile to fix the indentation.
The first three lines name the compiler used, the compiler options, and the linking options. The -lm linking option is not needed for your particular use case; I just included it because you will sooner or later want to use <math.h>, and then you do need to include the -lm linking option.
The PROGS line names your programs. You can specify more than one, just separate them by spaces.
The .PHONY: line tells make that targets all and clean are "phony", that they do not generate files of that name.
The all recipe, as the first recipe in a Makefile, is the default recipe that is followed, when you run make. This one tells that all programs listed in PROGS should be built.
The clean recipe (run make clean) removes all temporary files and compiled files from the directory -- essentially cleaning it.
The last recipe is a tricky one. It says that all the files listed in PROGS are each built from a file having the same name plus a .c suffix. The $^ refers to the .c file name, and $# to the file name without the suffix.
If this Makefile were used for returning exercises via email to a teacher, I'd also add a new .PHONY target, tarball:
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS := -lm
PROGS := number_input
TAR := $(notdir $(CURDIR)).tar
.PHONY: all clean tarball
all: $(PROGS)
clean:
rm -f $(PROGS)
tarball: clean
rm -f ../$(TAR)
tar -cf ../$(TAR) $(notdir $(CURDIR))/
$(PROGS): %: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $#
Running make will compile number_input, if number_input.c has been modified after the last time number_input was compiled, or if number_input does not exist yet.
Running make TAR=myname-ex01.tar tarball removes the compiled files from the current directory, then creates a tarball of the current directory (and its subdirectories, if any) in the parent directory as myname-ex01.tar. If you run just make tarball, the tar file name will be the same as the name of the current directory, but with a .tar suffix.
I hope you can see why writing a Makefile is so useful.

sample make file for creating more than one exe files with different directory [duplicate]

This question already has answers here:
Building multiple executables with similar rules
(5 answers)
Closed 9 years ago.
I am having a directory called test where make file should be. i am having subdirectory called sub1, sub2, sub3.
test/Makefile
test/sub1
test/sub2
test/sub3
I want to create exe1 by compiling sub1, exe2 by compiling sub2 and exe3 from sub3.
Can i add more than one directory in vpath?? or any other solution
You could simply have a very simple makefile in the test directory, just going into the subdirectories and calling makefiles in them. The subdirectories have makefiles that builds normally, but simply put the executable in the parent directory.
First of all: Yes you could add more than one directory in vpath. Each entry is separated with a colon ':'
vpath %.c test/sub1:test/sub2:test/sub3
But you'll getting into trouble as soon you have the same filename (with different content) in two directories. Consider:
test/Makefile
test/sub1/main.c
test/sub1/foo.c
test/sub1/bar.c
...
test/sub2/main.c
test/sub2/blish.c
test/sub3/blash.c
...
test/sub3/main.c
test/sub3/okEnoughForNow.c
And your makefile containing:
vpath %.c sub1:sub2:sub3
exe1.exe : main.c foo.c bar.c
gcc -o $# $^
exe2.exe : main.c blish.c blash.c
gcc -o $# $^
exe3.exe : main.c okEnoughForNow.c
gcc -o $# $^
The result would be:
gcc -o exe1.exe sub1/main.c sub1/foo.c sub1/bar.c
gcc -o exe2.exe sub1/main.c sub2/blish.c sub2/blash.c
gcc -o exe3.exe sub1/main.c sub3/okEnoughForNow.c
As you can see, all exe's contain sub1/main.c as this is the main.c found first; Its path appears first on the vpath.
Joachim's Approach is definitive a simple, and very common solution. I would choose it as well if the programs in your subfolders are completely unrelated: You could have in each directory a makefile containing something like:
SRC := $(wildcard *.c)
%.exe : $(SRC)
gcc -o $# $^
Assuming, all .c files in each of your sub* shall be part of your program, and there are no subfolders in your sub's. Otherwise you'll need a different approach to scan your .c files, or specify them individually.
In your main makefile you can run for each subfolder a new instance of make, using those makefiles. Which gives you a main Makefile like:
# Get all subfolders name without trailing slash
PROGS := $(patsubst %/,%,$(wildcard */))
# Each subfolder can be made by calling make in
# that folder. A file prog.exe is created.
.PHONY : $(PROGS)
$(PROGS) :
$(MAKE) -C $# prog.exe
# Now every .exe depends on its subfolder, calls
# Make there - see rule above and copies the
# prog.exe from there into the root, with the name
# of the subfolder. (Alternatively you could use
# mv instead of cp)
%.exe : %
cp $</prog.exe $#
Assuming the name of your .exe is the same as the directory name and all subfolders are containing programs.
However, calling make from a running make instance (recursive make) can cause a real headache as soon as there are any dependencies between the generated files of the subfolders.
Another solution:
A different approach whithout using recursive make is having rules dynamically created. In that case your main Makefile could look like this. (I'm again assuming all subfolders are containing programs, all subfolders are flat, and all .c files in those subfolders are part of your program) This has the advantage that you'll have to maintain just one makefile, and there can be any dependency between the different programs. But still it has the disadvantage that you cannot manage your different programs seperately.
That's the complete makefile:
%.exe :
gcc -o $# $^
PROGS := $(patsubst %/,%,$(wildcard */))
$(foreach P,$(PROGS),$(eval OBJ_$(P) := $(wildcard $(P)/*.c)))
$(foreach P,$(PROGS),$(eval $(P).exe : $(OBJ_$(P))))
.PHONY : all
all : $(addsuffix .exe,$(PROGS)
We're starting with a rule for compiling: Any .exe is generated by invoking gcc having all prerequisites as source files.
%.exe :
gcc -o $# $^
Then, next step is to obtain all "programs" by scanning for all subfolders and stripping off the trailing slash
PROGS := $(patsubst %/,%,$(wildcard */))
The next step is to create for each program a variable containig all Sources. Note the eval function expands, and passes everything to make as it has been written in the Makefile.
$(foreach P,$(PROGS),$(eval SRC_$(P) := $(wildcard $(P)/*.c)))
Thus the line above, with your sub1, sub2 and sub3 will become:
SRC_sub1 := $(wildcard sub1/*.c)
SRC_sub2 := $(wildcard sub2/*.c)
SRC_sub3 := $(wildcard sub3/*.c)
The eval function can even be used to create rules:
$(foreach P,$(PROGS),$(eval $(P).exe : $(SRC_$(P))))
So this will expand to (assuming the file structure in the example above)
sub1.exe : sub1/main.c sub1/foo.c sub1/bar.c
sub2.exe : sub2/main.c sub2/blish.c sub2/blash.c
sub3.exe : sub3/main.c sub3/okEnoughForNow.c
Now we have three rules without a recipe. Make says "if you have a rule without recipe, and an implicit rule that matches can be found, this rule is used with the prerequisites added from the rule that does not have the recipe" Thus, for those 3 rules the implicit rule of %.exe above applies.
Basically that's the trick. For your convenience you can add
.PHONY : all
all : $(addsuffix .exe,$(PROGS))
So make all makes everything.
Extension:
If you'd like to be able to make the .o files seperately as well, you could add one more implicit rule like:
%.o : %.c
gcc -c -o $# $<
and make your programs dependent on the .o rather than on the .c files:
$(foreach P,$(PROGS),$(eval OBJ_$(P) := $(patsubst %.c,%.o,$(wildcard $(P)/*.c))))
$(foreach P,$(PROGS),$(eval $(P).exe : $(OBJ_$(P))))
Then you'll have your .exe dependend on the .o that can be found by changing .c into .o after scanning all sources. Via the implicit rule chain %.o : %.c make will know what to do.

Can I regenerate a makefile for a C project, with correct link order and dependencies?

I have source code I last worked on in the late 90's-2000 and have it all backed up, apart from the makefile (yes berate away, bad backups are almost as good as no backups): so... I am wondering if there is any automated way to generate the makefile or a good way to analyse the dependencies quickly?
Specifically I am looking for:
a tool which could analyse the dependencies and correct the link order for me.
if such does not exist, then advice is greatly appreciated as to how to best approach this problem from someone who has had similar problem(s) in the past
failing either of the above two options, I think the best approach is to create an analysis/make-file creation tool which can automatically generate the dependencies order for linking (I have held off on this approach as time is always in short supply to squeeze in another project).
The reason for this quest for help/advice is that the code-base is 300,000 lines of code (excluding comments) and spans hundreds of C/O files, and as often as I have tried creating a make-file by hand, it frustrates and confounds, hence my last attempt to seek help and ask in here.
For reference: I have tried Cmake, AutoMake, GenMake and similar tools in the past to generate the makefile, all to no avail, as the dependencies are horrendous.
Generic makefile script
As it may be of use to others, here is the makefile I usually use for less convoluted C and C++ projects, as it saves me having to worry about creating a new one every time:
$(VERBOSE).SILENT:
PROGRAMNAME = prog
CC = gcc
CC += -c
CPP = g++
CPP += -c
ASM = nasm
ASM += -f elf -d ELF_TYPE
LD = g++
OBJFILES = $(patsubst %.c,%.o,$(wildcard *.c))
OBJFILES += $(patsubst %.s,%.o,$(wildcard *.s))
OBJFILES += $(patsubst %.cpp,%.o,$(wildcard *.cpp))
all: $(PROGRAMNAME)
clean:
#echo "Cleaning object files"
#echo " rm -f *.o"
rm -f *.o
#echo "Cleaning backups"
#echo " rm -f *~"
rm -f *~
#echo "Removing program file"
#echo " rm -f "$(PROGRAMNAME)
rm -f $(PROGRAMNAME)
%.o: %.s
#echo "Assembling ASMs "$#
#echo " ASM "$<
$(ASM) $<
%.o: %.c
#echo "(C)ompiling "$#
#echo " CC "$<
$(CC) $<
%.o: %.cpp
#echo "(C++)ompiling "$#
#echo " CPP "$<
$(CPP) $<
$(PROGRAMNAME): $(OBJFILES)
#echo "Get ready...."
#echo "Linking "$#
#echo " LD -o "$(PROGRAMNAME)" "$(OBJFILES)
$(LD) -o $(PROGRAMNAME) $(OBJFILES)
#echo "Cry if it worked! Scream swear and cry if it did not..."
strip: $(PROGRAMNAME)
#echo "Stripping "$(PROGRAMNAME)
echo -n "Size of "$(PROGRAMNAME)" before stripping is "
ls -sh $(PROGRAMNAME) | cut -d' ' -f1
#echo " Stripping "$(PROGRAMNAME)
strip $(PROGRAMNAME)
echo -n "Size of "$(PROGRAMNAME)" after stripping is "
ls -sh $(PROGRAMNAME) | cut -d' ' -f1
nothing:
#echo "Nothing to do; see you later - I'm going home!!!"
#echo "Hey, try some of these:"
#echo "make all - this would be the one you want"
#echo "make strip - does not work in the real world, only in computers"
#echo "make clean - will help clean your mind up"
You are looking for the classic Unix tool from MIT, makedepend.
gcc & clang can generate dependencies, see Advanced Auto-Dependency Generation , this won't solve the whole problem but shall help you.
On a linux/unix system:
find . -name "*.c" -print > sources will give you a list of all the sources.
find . -name "*.c" -print|sed s/\.c/\.o > objects should give you a list that you can stick "OBJECTS=" in front of [maybe manually add some linebreaks].
cat sources|xargs gcc -M > myprog.deps should give you a list of header dependencies that you can include myprog.deps in your makefile. [1]
Now all you need is
TARGET = myprog # Whatever you call your program!
OBJECTS = ... # from "objects" file above.
SOURCES = ... # from "sources" file above
INCLUDES = -I subdir1 -I subdir2 ... # include directories used by this product
CFLAGS = ... ${INCLUDES} # Some suitable settings
CC = gcc
LD = ${CC}
LDFLAGS = ... # I don't know what this needs to be - usually nothing complicated.
all: ${TARGET}
clean:
rm -f ${TARGET} ${OBJECTS}
${TARGET}: ${OBJECTS}
${LD} -o $# ${OBJECTS}
.c.o:
${CC} -o $# $<
That should have MOST of the hard work done, unless you have to build internal tools or your many source files don't actually produce one final binary of course - in the latter case, you'll probably have to search for "main" and go through the above steps for each executable - you can still use a top-level Makefile and use include of the intermediate ones.
[1] You could add to the makefile - particularly if your project produces many different executables.
myprog.deps: ${SOURCES}
${CC} -MM ${SOURCES} > myprog.deps
include myprog.deps
Thanks for the great response: concise and very informational. Based on the answers I am now using a mixture of manual effort and GNU AutoMake (the modern successor to makedepend) to try recompiling, and so far seems to be quite effective.
Then shall come the fun and games of porting to OO code in C++...that's a task I would gladly avoid but needs must.
Thanks again!

Why does this makefile not apply includes to all objects?

This makefile does not behave as I expect. I want it to build .o files for each .c file in the current directory and subdirectories, and put them in a static library. However, it stops applying my $(INCS) after the first or second file. When it tries to build the second .o file, I don't see the -I paths in the build line and it complains about not finding a header file therein. Names have been genericized to simplify things. I'm using cygwin on Windows XP. I'm using an ARM cross compiler that is not under the cygwin tree. I based this makefile off an answer here. There are only about two dozen .c files so the overhead of creating the dependency files this way isn't a big deal.
# Project specific options
CC = my-cross-gcc
INCS := -I. -Iinc
INCS += -Imy/inc/path
CFLAGS := -Wall -fPIC -static -cross-compiler-specific-options
OUT := bin/libmylib.a
MKDIR:=mkdir -p
### Generic C makefile items below:
# Add .d to Make's recognized suffixes.
SUFFIXES += .d
NODEPS:=clean
#Find all the C files in this directory, recursively
SOURCES:=$(shell find . -name "*.c")
#These are the dependency files
DEPFILES:=$(patsubst %.c,%.d,$(SOURCES))
OBJS:= $(patsubst %.c,%.o,$(SOURCES))
#Don't create dependencies when we're cleaning, for instance
ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS))))
-include $(DEPFILES)
endif
#This is the rule for creating the dependency files
%.d: %.c
$(CC) $(INCS) $(CFLAGS) -MM -MT '$(patsubst %.c, %.o,$(patsubst %.c,%.o,$<))' $< > $#
#This rule does the compilation
%.o: %.c %.d %.h
$(CC) $(INCS) $(CFLAGS) -o $# -c $<
# Now create a static library
all: $(OBJS)
#$(MKDIR) bin
ar rcsvq $(OUT) $(OBJS)
clean:
rm -rf $(OBJS) $(OUT) $(DEPFILES)
Why does this makefile not apply $(INCS) when building subsequent .o files? How do I fix it? Output resembles this:
$ make all
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o firstfile.o -c firstfile.c
my-cross-gcc -I. -Iinc -Imy/inc/path -<compiler options> -o secondfile.o -c secondfile.c
my-cross-gcc -<compiler flags> -o thirdfile.o -c thirdfile.c
thirdfile.c:23:18: fatal error: myinc.h: No such file or directory
compilation terminated.
When I go to the command line and type in the gcc line to build thirdfile.o and use the -I paths, the object file is successfully built.
There are two different mechanisms for handling header files at work here:
When the compiler is trying to build foo.o from foo.c, and in foo.c it encounters #include "foo.h", it goes looking for foo.h. The -I flags tell it where to look. If it is invoked without the flags it needs to find foo.h, it will complain and die.
When Make is trying to build foo.o, and considering which rule to use, it looks at the prerequisites. The prerequisites for your rule are foo.c foo.d foo.h, so it goes looking for those prerequisites. How is it to know where foo.h is? Note that the compiler flag inside one of its commands is of no use-- it won't make any deductions about that. If it can't find (and doesn't know how to make) a prerequisite, it will reject that rule and look for another one, such as the implicit %.o rule which knows nothing about your $(INCS) variable, and that leads you to the problem described above.
If this is the problem (and you can check by looking at the locations of the headers and doing some experiments) you have a couple of options:
A) You can use the implicit rule, and it's variables. Just add INCS to CFLAGS and you'll probably get the results you want. This tells the compiler what to do, but it still leaves Make in the dark about the dependencies, so you'll probably have to double-check that your dependency handling is correct.
B) You can tell Make where to find the header files:
vpath %.h inc my/inc/path
(You may notice that this is redundant with your INCS variable, and redundancy is bad-- you can eliminate this redundancy, but I urge you to get it working first.)
I'm going to guess that you have files named firstfile.h, secondfile.h, but no file named thirdfile.h?
I would then suppose that make cannot use the rule you gave it because and can't find or build the .h file. So it decides to use the default implicit rule instead.
All I can imagine is that for "thirdfile" your depfile is somehow out-of-date or corrupt. Perhaps it is bad enough that it's confusing make into calling some other default target.

Resources