I have inherited a project file that has a Makefile in it that is doing something I have never seen before--It is injecting a rm command. I cannot find any reason for the rm command, so I am missing something very obvious or very esoteric.
Thanks
The results of running make are:
bison --defines --xml --graph=calc.gv -o calc.c calc.y
Bison flags =
cc -c -o calc.o calc.c
Making BASE = calc
cc -o calc calc.o
Done making BASE
rm calc.c <======== WHERE IS THIS COMING FROM?
The Makefile is:
BASE = calc
BISON = bison
XSLTPROC = xsltproc
all: $(BASE)
%.c %.h %.xml %.gv: %.y
$(BISON) $(BISONFLAGS) --defines --xml --graph=$*.gv -o $*.c $<
#echo "Bison flags = " $(BISONFLAGS)
$(BASE): $(BASE).o
#echo "Making BASE = " $(BASE)
$(CC) $(CFLAGS) -o $# $^
#echo "Done making BASE"
run: $(BASE)
#echo "Type arithmetic expressions. Quit with ctrl-d."
./$<
html: $(BASE).html
%.html: %.xml
$(XSLTPROC) $(XSLTPROCFLAGS) -o $# $$($(BISON) --print-datadir)/xslt/xml2xhtml.xsl $<
CLEANFILES = $(BASE) *.o $(BASE).[ch] $(BASE).output $(BASE).xml $(BASE).html $(BASE).gv
clean:
#echo "Running clean" $(CLEANFILES)
rm -f $(CLEANFILES)
See https://www.gnu.org/software/make/manual/make.html#Chained-Rules:
The second difference is that if make does create b in order to update something else, it deletes b later on after it is no longer needed. Therefore, an intermediate file which did not exist before make also does not exist after make. make reports the deletion to you by printing a rm -f command showing which file it is deleting.
I am trying to analyze the following makefile and reproduce its "behavior" step by step.
Although I type "make all" it seems this makefile skips the "all:" line and jumps straight to "build/*.o" (hence the echo's).
The file and its corresponding output:
TOOLCHAIN ?= arm-none-eabi-
SOURCES = Demo/main.c \
Demo/startup.c \
Demo/Drivers/rpi_gpio.c \
Demo/Drivers/rpi_irq.c \
Source/tasks.c \
Source/list.c \
Source/portable/GCC/RaspberryPi/port.c \
Source/portable/GCC/RaspberryPi/portisr.c \
Source/portable/MemMang/heap_4.c
OBJECTS = $(patsubst %.c,build/%.o,$(SOURCES))
INCDIRS = Source/include Source/portable/GCC/RaspberryPi \
Demo/Drivers Demo/
CFLAGS = -Wall $(addprefix -I ,$(INCDIRS))
CFLAGS += -D RPI2
CFLAGS += -march=armv7-a -mtune=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4
ASFLAGS += -march=armv7-a -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard
LDFLAGS =
.PHONY: all clean
all: $(MOD_NAME)
echo "in all"
$(MOD_NAME): $(OBJECTS)
echo "in mod name"
ld -shared $(LDFLAGS) $< -o $#
build/%.o: %.c
echo -e "\nin build/*.o:*.c\n"
mkdir -p $(dir $#)
$(TOOLCHAIN)gcc -c $(CFLAGS) $< -o $#
build/%.o: %.s
echo -e "in build/*.o:*.s\n"
mkdir -p $(dir $#)
$(TOOLCHAIN)as $(ASFLAGS) $< -o $#
all: kernel7.list kernel7.img kernel7.syms kernel7.hex
echo -e"in kernel all\n"
$(TOOLCHAIN)size kernel7.elf
kernel7.img: kernel7.elf
$(TOOLCHAIN)objcopy kernel7.elf -O binary $#
echo -e "in kernel7.img\n"
kernel7.list: kernel7.elf
echo -e "kernel7.list\n"
$(TOOLCHAIN)objdump -D -S kernel7.elf > $#
kernel7.syms: kernel7.elf
echo -e "kernel7.syms\n"
$(TOOLCHAIN)objdump -t kernel7.elf > $#
kernel7.hex : kernel7.elf
echo -e "kernel7.hex\n"
$(TOOLCHAIN)objcopy kernel7.elf -O ihex $#
kernel7.elf: $(OBJECTS)
echo -e "kernel7.elf\n"
$(TOOLCHAIN)ld $^ -static -Map kernel7.map -o $# -T Demo/raspberrypi.ld
clean:
rm -f $(OBJECTS)
rm -f kernel7.list kernel7.img kernel7.syms
rm -f kernel7.elf kernel7.hex kernel7.map
rm -rf build
echo -e "cleaning \n"
I tried to replicate this behaviour myself with a tiny piece of code. But it doesn't seem to work:
SOURCES = Demo/Drivers/rpi_irq.c \
Demo/Drivers/rpi_gpio.c
OBJECTS = $(patsubst %.c,build/%.o,$(SOURCES))
.PHONY: all clean
all: $(MOD_NAME)
echo "making all"$(SOURCES)
$(MOD_NAME): $(OBJECTS)
echo "MOD_NAME"
build/%.o:%.c
mkdir -p $(dir $#)
arm-none-eabi-gcc -march=armv7-a -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=har $< -o $#
As you can see thanks to the echo's my code just doesn't even build my source code. I'd expect it to go from all->MOD_NAME->build. (This is all the output I get)
So my questions are:
How does the makefile I am analyzing manage to go straight to build/*.o?
Why does my implementation, which I think should do the same doesn't even compile my source code?
The Makefile that you copied contains 2 rules for "all".
The first depends on $(MOD_NAME) which might be empty.
The second rule depends on multiple files "kernel7.*" which themselves depend on "kernel7.elf".
Finally "kernel7.elf" depends on $(OBJECTS).
This last rule is responsible that all your source files will be compiled.
The first rule with $(MOD_NAME) does not need to cause any compilation at all.
In your own Makefile you only have a rule for "all" depending on $(MOD_NAME).
If $(MOD_NAME) is empty in your Makefile as well, you do not have any dependency for "all" at all.
If "all" does not depend on anything, no source files will be compiled.
To solve your problem you need to provide some content for $(MOD_NAME).
all is trying to build $(MOD_NAME), which has dependencies of $(OBJECTS), which it is trying to build.
There are two all's here, which is a problem.
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.
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
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.