Read a variable from Makefile, in a Makefile - c

The tree of my work folder:
.
|-- work_folder1
| |-- some.c file
| |-- Makefile B
|
|-- some.c file
|-- Makefile A
My makefile A call 'all' rule in Makefile B. The 'all' rule of Makefile B makes one .o file named 'B.o' [$(NAME) variable] and copy it on work folder (cp ../). The Makefile A compile .c file and link them with the 'B.o'. But if i decide to change the name of 'B.o' in Makefile B, for example 'my_B.o', Makefile A cannot compile cause 'B.o' dosen't exist anymore.
How can I, from Makefile A, read the $(NAME) variable of Makefile B?

You can add a special .PHONY rule in your Makefile B so that it outputs the name you want.
In Makefile B
.PHONY: get_names
get_names:
#echo "B.o"
In Makefile A
B_Files:=$(shell $(MAKE) -C work_folder_B get_names)
# You can use $(B_Files) that will contain `B.o`.
Note the use of := in Makefile A so that you run make to get the names only once.

I found it ! Many thanks to Didier !
In my Makefile B:
$(NAME): my_B.o
PHONY: get_name
get_name:
#echo $(NAME)
In my Makefile A:
B_Files:=$(shell make -s -C work_folder_B get_name)

Related

Makefile: Rule dependent on directory of target

I am trying to create a Makefile to create object files in a directory based on the source file. For example I have DirA/file.c and DirB/file.c and I want to create a recipe for creating DirA/file.o and DirB/file.o.
rootdir/
|-- Makefile
|-- DirA
| |-- source.c
| +-- source.o
+-- DirB
|-- file.c
+-- file.o
I would assume the recipe would be similar to the following:
MAKEFLAGS += --no-builtin-rules
DirA_Files=$(wildcard DirA/*.c)
DirB_Files=$(wildcard DirB/*.c)
.PHONY: all a_files b_files
all: a_files b_files
#echo Done with all!
#echo built $(patsubst %.c,%.o,$(DirA_Files)) $(patsubst %.c,%.o,$(DirB_Files))
a_files: $(patsubst %.c,%.o,$(DirA_Files))
b_files: $(patsubst %.c,%.o,$(DirB_Files))
DirA/%.o DirB/%.o : DirA/%.c DirB/%.c
# Complex recipe that I'd rather not state twice in the Makefile
#echo "Building $# because $? changed"
#touch $#
But I do not want the object files in DirA to be dependent on the source files of DirB, which is what the above recipe implies.
I have also tried
DirA/%.o : DirA/%.c
DirB/%.o : DirB/%.c
DirA/%.o DirB/%.o :
# Complex recipe that I'd rather not state twice in the Makefile
#echo "Building $# because $? changed"
#touch $#
But then the $? variable is always blank.
How could I create a single recipe that would also allow me to build a_files and b_files independently
You can't combine pattern rules quite that easily. But this situation is what defined recipes were made for:
define complex-rule
# Complex recipe that I'd rather not state twice in the Makefile
#echo "Building $# because $? changed"
#touch $#
endef
DirA/%.o : DirA/%.c
$(complex-rule)
DirB/%.o : DirB/%.c
$(complex-rule)
related info:
DirA_Files := $(wildcard DirA/*.c)
DirB_Files := $(wildcard DirB/*.c)
$(info DirA_Files: $(DirA_Files))
$(info DirB_Files: $(DirB_Files))
aobj := $(patsubst %.c,%.o,$(DirA_Files))
bobj := $(patsubst %.c,%.o,$(DirB_Files))
$(info aobj: $(aobj))
$(info bobj: $(bobj))
all: $(aobj) $(bobj)
#echo Done with all!

Makefile implicit rules with different directories

I am following the manual in order to learn more about Makefiles, so I decided to code along and apply this example ( https://www.gnu.org/software/make/manual/make.html#Letting-make-Deduce-the-Recipes ) to the Makefile of my project.
The problem is that I have a seperate directory for the object files that will be generated, as far as my understanding goes the implicit rules will only look for the corresponding .c files in the same directory as the object file.
My makefile looks like this:
objects = $(addprefix objs/, main.o interface.o \
build.o requests.o parse.o configure.o)
output: $(objects)
gcc -o output $(objects)
objs/main.o: interface.h build.h requests.h parse.h configure.h
objs/interface.o: interface.h
objs/build.o: build.h
objs/requests.o: requests.h
objs/parse.o: parse.h
objs/configure.o: configure.h
.PHONY: clean
clean:
rm output $(objects)
My object files are supposed to go to the objs/ directory the source code files are located in the root directory of the project, like this:
objs/
*.c
*.h
How can I still use implicit rules without having to compile object files into the source file directory?
You just have to define your own implicit rule, since the built-in rules won't do that for you.
Try:
obj/%.o : %.c
$(COMPILE.c) $(OUTPUT_OPTION) $<

Makefile for potentially large project with automatic target creation

Let's say I have a C project. There are several files:
/myproject/makefile
/myproject/src
/myproject/build
/myproject/src/baseHeader.h
/myproject/src/module1/module1.h
/myproject/src/module1/module1_a.c
/myproject/src/module1/module1_b.c
/myproject/src/main.c
I want make to search in src for all *.h files which are not on the first depth level i.e. make should look for *.h files in
/myproject/src/module1/
so it will not use
/myproject/src/baseHeader.h
Then for every found .h make should create target with the basename of .h i.e. for
/myproject/src/module1/module1.h
it should be
./build/module1.o: ./src/module1/module1_a.c ./src/module1/module1_b.c ./src/module1/module1.h $(OTHER_DEPS) | $(OPTIONAL_DEPS)
$(CC) -c $< -o $#
also it should create target for every .c file in /myproject/src/ dir without going recursive in this example only main.c will be found and target should look like
./build/main.o: ./src/main.c $(OTHER_DEPS) | $(OPTIONAL_DEPS)
How this can be done?
Could someone provide me with the link to example if exists?
I'm asking for this because after a day of trying I think it's better to forget about make and use bash scripts instead...
This can be done but it is not trivial. One way to do it is to build a list of all of the .h files recursively in the src directory and its subdirectories, then remove from that list the .h files in the src directory.
We can search the src directory and all subdirectories for .h files with $(wildcard src/**/*.h)) and only the src directory for .h files with $(wildcard src/*.h). These can be combined with the filter-out function to produce a list containing only the .h files in subdirectories of src/ like
MODULES := $(filter-out $(wildcard src/*.h),$(wildcard src/**/*.h))
This will produce a list like
/myproject/src/module1/module1.h
/myproject/src/module2/module2.h
/myproject/src/module3/module3.h
We could remove the directory structure with
INCLUDES := $(notdir MODULES)
which will produce
module1.h
module2.h
module3.h
We can convert these into object files for the modules with
OBJDIR = build
OBJS := $(addprefix $(OBJDIR)/, $(patsubst %.h,%.o, $(INCLUDES)))
Then we define an empty target rule to create all these
.PHONY: modules
modules: $(OBJS)
And the implicit rule to create the objects
$(OBJDIR)/%.o: $(dir $(findstring %.h, $MODULES))*.c %.h $(OTHER_DEPS) | $(OPTIONAL_DEPS)
$(CC) -c $? -o $#
EDIT: Its not particularly advisable to use wildcards in prerequisite lists but it is the best solution I have for now.
To compile a target for every .c file in src without searching recursively we take a similar approach starting off.
SRCS := $(wildcard src/*.c)
will find all out the .c files in the top level src directory. We can compile targets for these with
$(SRCS:%.c=$(OBJDIR)/%.o): %.c $(OTHER_DEPS) | $(OPTIONAL_DEPS)

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.

Compile and link when dependent header file changed in other directory

I have 3 questions about compiling and linking my project in fewer steps...
First, my project looks like: ( I use Watcom C to compile//link my project )
Directory 'MyProject' contains 3 sub directories for different modules and some files:
directory 'A' ( a.h and a.c included )
directory 'B' ( b.h and b.c included )
directory 'C' ( c.h and c.c included )
my.c and my.h
my.lnk
makefile
And within each sub directory there is one corresponding makefile...
[Q1] Assume I update a.h in directory A and a.h is referenced by b.c in directory B, then my original steps will be:
compile in directory A ( obj and lib generated...)
compile in directory B ( obj and lib generated...)
back to directory MyProject then compile and link
Can I just take one step to cover above ?
[Q2] If I want to ignore all existing obj/lib and rebuild all, how to do it ?
I know this takes time but sometimes "kill and rebuild" will be better...
[Q3] If my.h is updated and it is referenced by a.c,b.c, and c.c...
Can I just take one step to cover above ?
[My makefile in sub directory looks like]
INCLUDE1 = -ic:\watcom\h
OBJECTS1 = a.obj
CFLAGS = -zq -mf -oxsbl $(INCLUDE1)
DEST = a.exe
COMPILER = wpp386
.erase # special cmd, tell wmake to "erase" target if make is not successful
.cpp.obj: .AUTODEPEND
$(COMPILER) $(CFLAGS) $<
$(DEST) : $(OBJECTS1) makefile
[My makefile in main directory looks like]
INCLUDE1 = -i=c:\myproj\my -i=c:\watcom\h
OBJECTS1 = my.obj
CFLAGS = -zq -fp6 -mf -6r -s -oxsbl $(INCLUDE1)
DEST = my.exe
COMPILER = wpp386
LINKER = wlink
LNK_FILE = my.lnk
.erase # special cmd, tell wmake to "erase" target if make is not successful
.cpp.obj: .AUTODEPEND
$(COMPILER) $(CFLAGS) $<
$(DEST) : $(OBJECTS1) makefile my.lnk
$(LINKER) #$(LNK_FILE)
[Update 1]
I use wpp386 as compiler and it is watcom c++ tool.
To build the target I use one batch file to compile cpp file:
#echo off
del a1.lib
del *.err
wmake -h
wlib -q a1.lib + a.obj
del *.obj
I can successfully compile cpp file and everything is fine.
In directory B, I use the same way(batch file+makefile) to compile b.cpp
To sum up my project works and the reason why I ask is to find "faster compiling/linking sequence" if I just update some header file...
I tried add the command ehco hello to the rule $(DEST) and found it was ok. Then use echo $(MAKE) and got:
...
echo C:\WATCOM\BINW\WMAKE.EXE
C:\WATCOM\BINW\WMAKE.EXE
...
Thanks !
I'm not familiar with your compiler, so I can't see how these makefiles work, so we'll have to take this one step at a time.
1) when you go into a subdirectory A, what command do you use to build the targets? Does it work? How about in subdirectory B?
2) In the main makefile, can you add a command, like echo hello to the $(DEST) rule? If that works, try echo $(MAKE).
EDIT:
Non-GNU versions of Make are troublesome, but we'll see what we can do.
Try editing the makefile in subdir A:
INCLUDE1 = -ic:\watcom\h
OBJECTS1 = a.obj
CFLAGS = -zq -mf -oxsbl $(INCLUDE1)
DEST = a1.lib # NOTE THIS CHANGE
COMPILER = wpp386
.erase # special cmd, tell wmake to "erase" target if make is not successful
.cpp.obj: .AUTODEPEND
$(COMPILER) $(CFLAGS) $<
$(DEST) : $(OBJECTS1) makefile
wlib -q $# + $(OBJECTS1)
del $(OBJECTS1)
Instead of the batch file, just run make -h. This should rebuild the library (if the library needs rebuilding). If it works, try moving up into MyProject and running make -h -C A. This should execute the makefile in A and rebuild the library there (unless WMAKE has some other syntax).
If that works, try making the same changes in B, then editing the $(DEST) rule in the main makefile:
$(DEST) : $(OBJECTS1) makefile my.lnk
$(MAKE) -h -C A
$(MAKE) -h -C B
$(LINKER) #$(LNK_FILE)
Cross your fingers and run make -h. This should rebuild both libraries, compile, link, and solve Q1...

Resources