Dynamic targets in Makefiles - linux

I'm trying to create a Makefile that has a target per src/ subfolder so that it creates a static lib.
I am currently trying this:
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(INCLUDE) -c -o $# $<
lib%.a: $(patsubst %.cpp, %.o, $(wildcard src/%/*.cpp))
$(AR) rcs $# $^
But this doesn't work, the target matching works, but the dependency tracking doesn't.
If I just leave alone src/%/*.cpp that completes properly to the .cpp files in the proper dir, but the moment I try to use it inside string functions to convert the .cpp to .o the % does not work anymore.

This is tricky because as far as I know you can't use functions like patsubst in the prerequisite list. There is more than one way to do it; this is perhaps the least ugly. Store the path in a variable, then reinvoke make so that you can construct the prerequisite list outside the rule.
ifdef OBJPATH
LIBOBJECTS := $(patsubst %.cc,%.o,$(wildcard src/$(OBJPATH)/*.cc))
lib%.a: $(LIBOBJECTS)
$(AR) rcs $# $^
else
lib%.a: src/%/*.cc
#$(MAKE) -s $# OBJPATH=$*
endif

Related

specifying the filename in a makefile

I'm new to this and trying to create a makefile where I could, for example, run:
make -f mymakefile testfile
and the makefile would find testfile.java (which exists in the directory I'm running from), compile it, and run the code.
Instead, I must be confused with how automatic variables work and after working all afternoon I still get the error:
make: Nothing to be done for `testfile'.
Any help would be appreciated and my code is below:
JC=javac
JVM=java
JFLAGS= -g
RM = rm -f
CFLAGS =
CXX = gcc
NAME = *
.SUFFIXES: .java .class
all: run
NAME:
$(CXX) $(CFLAGS) -o $^ $#
echo $(NAME)
$(NAME).class: $(NAME)
$(JC) $(JFLAGS) $(NAME).java
run: $(NAME).class
$(JVM) $(NAME)
.PHONY: clean
clean:
$(RM) $(NAME).class
I've tried just having it echo 'testfile' to better understand how automatic variables work, but I couldn't get that to work correctly either.
The arguments on the make command line select the targets to build. You can't pass values to variables in the same way you would with a shell script (like you're trying to do with "NAME".)
If you really want to pass a value for a variable, the command would be:
NAME=testfile make -f mymakefile
You can use pattern rules to create rules from arbitrary names. For example:
%.bin : %.cpp
$(CXX) $(CXXFLAGS) -o $# $<
When you call make test.bin, this matches pattern rule %.bin, where % matches test. Then automatic variables $< substitutes the source file and $# substitutes the target file. What actually runs is something like g++ -O3 -o test.bin test.cpp.

Why Makefile detects file even if it does not exist?

Here is my code:
%.o: %.cpp
#mkdir -p bin/obj/$(#D)
ifeq ($(wildcard bin/obj/$#),)
$(CC) -c -o bin/obj/$# $< $(CFLAGS) $(FLAGS)
else
#echo "bin/obj/$# exists"
endif
And I have a problem, when directory obj exists I always get false.
I'm talking about this condition:
($(wildcard bin/obj/$#),)
I don't know how to fix it.
Makefile always prints that file exists even if i remove it from disk.
It works only when I remove obj directory.
How can I fix it?
The trouble is that Make evaluates the conditional before executing the rule, when $# has not been defined (and when the file may not yet have been created). The wildcard statement evaluates to $(wildcard /bin/obj/), which will produce "bin/obj/" if the directory exists, which I suppose it does.
There's more than one way to solve this. The most direct is to put the conditional in the command, so that Make will pass it to the shell:
%.o: %.cpp
#mkdir -p bin/obj/$(#D)
#if [ -e bin/obj/$# ]; then echo it exists; else $(CC) ...; fi

Compiling C++ and C files in one makefile

I have a makefile that looks like this:
CS := a.c b.c
CPPS := foo.cpp bar.cpp
SOURCES := $(CS) $(CPPS)
OBJS := $(CS:%.c=$(OBJSDIR)/%.o) $(CPPS:%.cpp=$(OBJSDIR)/%.o)
I want to create a single rule to compile them all. But the only option I can think of is this:
$(OBJSDIR)/%.o: %.cpp
$(GXX) $(GXXFLAGS) -c $< -o $#
But of course it doesn't work because some of the object files don't have a matching C++ source file.
Any idea?
suppose you have a.cc, b.cc and c.cc, and on the other side, d.c, e.c and f.c
program_objs = a.o b.o c.o d.o e.o f.o
program: $(program_objs)
$(CC) $(LDFLAGS) -o $# $(program_objs)
You don't need anything more, as make will automatically detect which files are c++ and which ones are plain c and will select the proper compiler.
in case you want something special, not included in makefile, you can add some suffixes (file types) with the rule:
.SUFFIXES: .a .b .o
and then use the following rules to compile them to .o
.a.o:
$(COMPILER_A) $(COMPILER_A_FLAGS) -c $# -o $<
.b.o:
$(COMPILER_B) $(COMPILER_B_FLAGS) -c $# -o $<
and let makefile select the proper compiler (the one stored in variables COMPILER_A or COMPILER_B) to do the work.
Of course, you can compile something to a .o file with an explicit rule, as in:
a.o: a.cc
g++ -o a.o -c a.cc
b.o: b.cc
g++ -o b.o -c b.cc
c.o: c.cc
g++ -o c.o -c c.cc
d.o: d.c
gcc -o d.o -c d.c
e.o: e.c
gcc -o e.o -c e.c
f.o: f.c
gcc -o f.o -c f.c
Note #1:
Some sugestions have been made on GNU make % pattern to construct implicit rules for targets. Below is a rewritting of the implicit rules above to do the same thing:
%.o: %.a
$(COMPILER_A) $(COMPILER_A_FLAGS) -c $# -o $<
%.o: %.b
$(COMPILER_B) $(COMPILER_B_FLAGS) -c $# -o $<
As always, $# means the target of the rule and $< (you can use also $* for the file name without any matching suffixes) the left needed file. For a complete list of automatic variables that can be used, I suggest you to read your make manual. Take into account that the old suffix syntax is reversed from the new one (the target suffix appears last in the old syntax, the new syntax being more similar to a normal makefile rule with the target on the left side of the colon)
I want to create a single rule to compile them all.
As Etan Reisner said in the comment section, make already has implicit rules to compile .c and .cpp file, so the real answer to your question is:
Do not write anything to compile your object files.
That said, you should now remove those two variables: $(GXX) and $(GXXFLAGS).
To provide flags to cc or gcc one should use the CFLAGS built-in variable.
To provide flags to g++ one should use the CXXFLAGS built-in variable.
To provide flags to the preprocessor (cpp) one should use the CPPFLAGS variable.
Since you're mixing C and C++ source files, you should use the CXX variable as the linker command.

Makefile target color output

I have written a Makefile which works fine; I do not post it entirely, just the part of it under investigation:
COMPILE_cpp = $(CXX) $(CFLAGS) -o $# -c $< $(MAKEDEP) $(INCLUDES)
%.o : %.cpp ; $(COMPILE_cpp)
.SUFFIXES: .o .cpp
The above code does its duty. Since the build process involves many files I would like to add some color output. I have tried the following
PRINT = #echo -e "\e[1;34mBuilding $<\e[0m"
COMPILE_cpp = $(PRINT) && $(CXX) $(CFLAGS) -o $# -c $< $(MAKEDEP) $(INCLUDES)
%.o : %.cpp ; $(COMPILE_cpp)
.SUFFIXES: .o .cpp
The Makefile still works fine but now I can only see the output of $(PRINT) with the chosen color. The command string $(CXX) $(CFLAGS) -o $# -c $< $(MAKEDEP) $(INCLUDES) is correctly executed but not printed to screen any more; still I can see the eventual warnings and errors.
I would like to avoid using external tools (such as colorgcc or CMake) and hack it with bash script tricks.
Thanks in advance!
EDIT
Just a little add: what about if I want to do something like grep the output of the current built file in order to find strings such as error or warning?
I would like to highlight them, I was thinking about calling a sed on the compiler output to change some words color...
The # symbol at the start of your PRINT definition is suppressing the command printing.
Try this:
%o : %.cpp
$(PRINT)
$(COMPILE_cpp)
where $(COMPILE_cpp) is your first version.
Dont forget the tab character indents recipe commands, not spaces.

Makefiles with source files in different directories

I have a project where the directory structure is like this:
$projectroot
|
+---------------+----------------+
| | |
part1/ part2/ part3/
| | |
+------+-----+ +---+----+ +---+-----+
| | | | | | |
data/ src/ inc/ src/ inc/ src/ inc/
How should I write a makefile that would be in part/src (or wherever really) that could comple/link on the c/c++ source files in part?/src ?
Can I do something like
-I$projectroot/part1/src -I$projectroot/part1/inc -I$projectroot/part2/src ...
If that would work, is there an easier way to do it. I've seen projects where there is a makefile in each of the corresponding part? folders. [in this post I used the question mark like in bash syntax]
The traditional way is to have a Makefile in each of the subdirectories (part1, part2, etc.) allowing you to build them independently. Further, have a Makefile in the root directory of the project which builds everything. The "root" Makefile would look something like the following:
all:
+$(MAKE) -C part1
+$(MAKE) -C part2
+$(MAKE) -C part3
Since each line in a make target is run in its own shell, there is no need to worry about traversing back up the directory tree or to other directories.
I suggest taking a look at the GNU make manual section 5.7; it is very helpful.
If you have code in one subdirectory dependent on code in another subdirectory, you are probably better off with a single makefile at top-level.
See Recursive Make Considered Harmful for the full rationale, but basically you want make to have the full information it needs to decide whether or not a file needs to be rebuilt, and it won't have that if you only tell it about a third of your project.
The link above seems to be not reachable. The same document is reachable here:
aegis.sourceforge.net (archived)
lcgapp.cern.ch
The VPATH option might come in handy, which tells make what directories to look in for source code. You'd still need a -I option for each include path, though. An example:
CXXFLAGS=-Ipart1/inc -Ipart2/inc -Ipart3/inc
VPATH=part1/src:part2/src:part3/src
OutputExecutable: part1api.o part2api.o part3api.o
This will automatically find the matching partXapi.cpp files in any of the VPATH specified directories and compile them. However, this is more useful when your src directory is broken into subdirectories. For what you describe, as others have said, you are probably better off with a makefile for each part, especially if each part can stand alone.
You can add rules to your root Makefile in order to compile the necessary cpp files in other directories. The Makefile example below should be a good start in getting you to where you want to be.
CC=g++
TARGET=cppTest
OTHERDIR=../../someotherpath/in/project/src
SOURCE = cppTest.cpp
SOURCE = $(OTHERDIR)/file.cpp
## End sources definition
INCLUDE = -I./ $(AN_INCLUDE_DIR)
INCLUDE = -I.$(OTHERDIR)/../inc
## end more includes
VPATH=$(OTHERDIR)
OBJ=$(join $(addsuffix ../obj/, $(dir $(SOURCE))), $(notdir $(SOURCE:.cpp=.o)))
## Fix dependency destination to be ../.dep relative to the src dir
DEPENDS=$(join $(addsuffix ../.dep/, $(dir $(SOURCE))), $(notdir $(SOURCE:.cpp=.d)))
## Default rule executed
all: $(TARGET)
#true
## Clean Rule
clean:
#-rm -f $(TARGET) $(OBJ) $(DEPENDS)
## Rule for making the actual target
$(TARGET): $(OBJ)
#echo "============="
#echo "Linking the target $#"
#echo "============="
#$(CC) $(CFLAGS) -o $# $^ $(LIBS)
#echo -- Link finished --
## Generic compilation rule
%.o : %.cpp
#mkdir -p $(dir $#)
#echo "============="
#echo "Compiling $<"
#$(CC) $(CFLAGS) -c $< -o $#
## Rules for object files from cpp files
## Object file for each file is put in obj directory
## one level up from the actual source directory.
../obj/%.o : %.cpp
#mkdir -p $(dir $#)
#echo "============="
#echo "Compiling $<"
#$(CC) $(CFLAGS) -c $< -o $#
# Rule for "other directory" You will need one per "other" dir
$(OTHERDIR)/../obj/%.o : %.cpp
#mkdir -p $(dir $#)
#echo "============="
#echo "Compiling $<"
#$(CC) $(CFLAGS) -c $< -o $#
## Make dependancy rules
../.dep/%.d: %.cpp
#mkdir -p $(dir $#)
#echo "============="
#echo Building dependencies file for $*.o
#$(SHELL) -ec '$(CC) -M $(CFLAGS) $< | sed "s^$*.o^../obj/$*.o^" > $#'
## Dependency rule for "other" directory
$(OTHERDIR)/../.dep/%.d: %.cpp
#mkdir -p $(dir $#)
#echo "============="
#echo Building dependencies file for $*.o
#$(SHELL) -ec '$(CC) -M $(CFLAGS) $< | sed "s^$*.o^$(OTHERDIR)/../obj/$*.o^" > $#'
## Include the dependency files
-include $(DEPENDS)
If the sources are spread in many folders, and it makes sense to have individual Makefiles then as suggested before, recursive make is a good approach, but for smaller projects I find it easier to list all the source files in the Makefile with their relative path to the Makefile like this:
# common sources
COMMON_SRC := ./main.cpp \
../src1/somefile.cpp \
../src1/somefile2.cpp \
../src2/somefile3.cpp \
I can then set VPATH this way:
VPATH := ../src1:../src2
Then I build the objects:
COMMON_OBJS := $(patsubst %.cpp, $(ObjDir)/%$(ARCH)$(DEBUG).o, $(notdir $(COMMON_SRC)))
Now the rule is simple:
# the "common" object files
$(ObjDir)/%$(ARCH)$(DEBUG).o : %.cpp Makefile
#echo creating $# ...
$(CXX) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $# $<
And building the output is even easier:
# This will make the cbsdk shared library
$(BinDir)/$(OUTPUTBIN): $(COMMON_OBJS)
#echo building output ...
$(CXX) -o $(BinDir)/$(OUTPUTBIN) $(COMMON_OBJS) $(LFLAGS)
One can even make the VPATH generation automated by:
VPATH := $(dir $(COMMON_SRC))
Or using the fact that sort removes duplicates (although it should not matter):
VPATH := $(sort $(dir $(COMMON_SRC)))
I think it's better to point out that using Make (recursive or not) is something that usually you may want to avoid, because compared to today tools, it's difficult to learn, maintain and scale.
It's a wonderful tool but it's direct use should be considered obsolete in 2010+.
Unless, of course, you're working in a special environment i.e. with a legacy project etc.
Use an IDE, CMake or, if you're hard cored, the Autotools.
(edited due to downvotes, ty Honza for pointing out)
I was looking for something like this and after some tries and falls i create my own makefile, I know that's not the "idiomatic way" but it's a begining to understand make and this works for me, maybe you could try in your project.
PROJ_NAME=mono
CPP_FILES=$(shell find . -name "*.cpp")
S_OBJ=$(patsubst %.cpp, %.o, $(CPP_FILES))
CXXFLAGS=-c \
-g \
-Wall
all: $(PROJ_NAME)
#echo Running application
#echo
#./$(PROJ_NAME)
$(PROJ_NAME): $(S_OBJ)
#echo Linking objects...
#g++ -o $# $^
%.o: %.cpp %.h
#echo Compiling and generating object $# ...
#g++ $< $(CXXFLAGS) -o $#
main.o: main.cpp
#echo Compiling and generating object $# ...
#g++ $< $(CXXFLAGS)
clean:
#echo Removing secondary things
#rm -r -f objects $(S_OBJ) $(PROJ_NAME)
#echo Done!
I know that's simple and for some people my flags are wrong, but as i said this is my first Makefile to compile my project in multiple dirs and link all of then together to create my bin.
I'm accepting sugestions :D
RC's post was SUPER useful. I never thought about using the $(dir $#) function, but it did exactly what I needed it to do.
In parentDir, have a bunch of directories with source files in them: dirA, dirB, dirC. Various files depend on the object files in other directories, so I wanted to be able to make one file from within one directory, and have it make that dependency by calling the makefile associated with that dependency.
Essentially, I made one Makefile in parentDir that had (among many other things) a generic rule similar to RC's:
%.o : %.cpp
#mkdir -p $(dir $#)
#echo "============="
#echo "Compiling $<"
#$(CC) $(CFLAGS) -c $< -o $#
Each subdirectory included this upper-level makefile in order to inherit this generic rule. In each subdirectory's Makefile, I wrote a custom rule for each file so that I could keep track of everything that each individual file depended on.
Whenever I needed to make a file, I used (essentially) this rule to recursively make any/all dependencies. Perfect!
NOTE: there's a utility called "makepp" that seems to do this very task even more intuitively, but for the sake of portability and not depending on another tool, I chose to do it this way.
Hope this helps!
Recursive Use of Make
all:
+$(MAKE) -C part1
+$(MAKE) -C part2
+$(MAKE) -C part3
This allows for make to split into jobs and use multiple cores
I suggest to use autotools:
//## Place generated object files (.o) into the same directory as their source files, in order to avoid collisions when non-recursive make is used.
AUTOMAKE_OPTIONS = subdir-objects
just including it in Makefile.am with the other quite simple stuff.
Here is the tutorial.

Resources