Multiple targets and libraries in Makefile - makefile

I have this folder/files structure:
./libs/
helpers.c
helpers.h
./a_app.c
./b_app.c
./c_app.c
Each app depends on helpers lib and GStreamer, so I need to compile helpers.o (inside libs/ folder) and then link each app.
Currently I have this Makefile:
CC = gcc
CFLAGS = -g -Wall -w
LFLAGS = -g -Wall -w -c
CFLAGS += `pkg-config --cflags gstreamer-app-0.10`
LFLAGS += `pkg-config --cflags gstreamer-app-0.10`
LDFLAGS =
LDFLAGS += `pkg-config --libs gstreamer-app-0.10`
all: examples
examples: helpers.o a_app
$(info *** examples ***)
helpers.o:
$(info *** helpers.o ***)
$(CC) $(LFLAGS) libs/helpers.c -o libs/helpers.o $(LDFLAGS)
a_app: a_app.o
$(CC) $(CFLAGS) libs/helpers.o a_app.o -o a_app $(LDFLAGS)
a_app.o: a_app.c
$(info *** a_app.o ***)
$(CC) $(LFLAGS) a_app.c $(LDFLAGS)
While I could add b_appand c_app I'm looking for another (more elegant) way of doing it. Can't I just say that I have a, b and c _app and let Makefile compile them all and link them against GStreamer and helpers?
Also, is there any way to make Makefile compile files without needing to tell it -o name_of_file (and perhaps make it compile them in the folder that they are, because of the helpers library).

Okay, so - as we discussed in the comments, make can figure out how to make the .o files, so those rules are unnecessary. To make a generalized rule for all your *_app files (assuming they all have the same dependency on helpers.h, you can do this:
%_app: %_app.o libs/helpers.o
Make uses the % as a wildcard, and in the rule/dependency line the wildcard will expand to the same thing in the dependencies as it did in the rule. In the actual execution, you can use $* to get the same string. So a single rule for all your *_app executables winds up looking a bit like this:
%_app: %_app.o libs/helpers.o
$(CC) $(CFLAGS) libs/helpers.o $*_app.o -o $*_app $(LDFLAGS)
I was testing this on my machine (hence comments instead of answers, and wound up writing this Makefile:
CC = gcc
CFLAGS = -g -Wall -w
LFLAGS = -g -Wall -w -c
CFLAGS += `pkg-config --cflags gstreamer-app-0.10`
LFLAGS += `pkg-config --cflags gstreamer-app-0.10`
LDFLAGS =
LDFLAGS += `pkg-config --libs gstreamer-app-0.10`
new: clean all
clean:
rm -rf *.o */*.o *_app
all: examples
examples: a_app b_app
%_app: %_app.o libs/helpers.o
$(CC) $(CFLAGS) libs/helpers.o $*_app.o -o $*_app $(LDFLAGS)
Does that all make sense?
EDIT: It occurs to me that GNU Make can run some commands on the command line and store the string for its own purposes.
$(shell ls *_app.c | sed 's/.c//') will expand into all the apps you have in the current directory. so you can say:
examples: $(shell ls *_app.c | sed 's/\.c//')
Or, as I think is a little better:
...
ALLAPPS = $(shell ls *_app.c | sed 's/\.c//')
...
all: $(ALLAPPS)
That way make can be used to make everything, and make ?_app can be used to compile one app at a time.
Super ultra mega double EDIT:
Using a bald % operator as a target will bust up Make's ability to auto generate .o files. Here's the solution we worked out in chat:
CC = gcc
CFLAGS = -g -Wall -w
LFLAGS = -g -Wall -w -c
CFLAGS += $(shell pkg-config --cflags gstreamer-app-0.10)
LFLAGS += $(shell pkg-config --cflags gstreamer-app-0.10)
LDFLAGS =
LDFLAGS += $(shell pkg-config --libs gstreamer-app-0.10)
TARGETS = $(shell ls *.c | sed 's/\.c//')
new: clean all
clean:
rm -rf *.o */*.o *_app
all: examples
examples: $(TARGETS)
.SECONDEXPANSION:
$(TARGETS): libs/helpers.o $$#.o
$(CC) $(CFLAGS) libs/helpers.o $#.o -o $# $(LDFLAGS)

Related

Simplifying a makefile

I have written a scary-looking Makefile by copy/pasting suggestions from Stack Overflow. However, I have read that it might not be necessary to provide explicit compiler invocations so many times (for example, the -O3 flag is everywhere). How can I simplify this Makefile?
CFLAGS = -Weverything -Wno-padded -Wno-unused-parameter -Wno-unused-variable -Wno-sign-conversion
all: fianchetto.o util.o ttable.o movegen.o
clang -O3 $(CFLAGS) -D NDEBUG $^ -o fianchetto
debugf: fianchetto.o ttable.o movegen.o
clang -O3 $(CFLAGS) -g3 $^ -o fianchetto
clean:
rm *.o && rm *.gch & rm fianchetto && rm -rf fianchetto.dSYM
%.o: %.c
clang -O3 -c $(CFLAGS) $< -o $#
fianchetto.o: fianchetto.c
ttable.o: ttable.h ttable.c
movegen.o: movegen.h movegen.c
util.o: util.h util.c
I am mystified by a lot of the syntax, and would appreciate links or explanations of why simplifications work!
CFLAGS and defines (which should be in CPPFLAGS anyway) are useless when linking
You're reinventing make's built-in rules, make will automatically link a target if one of its dependencies is "target.o" (in this case fianchetto: fianchetto.o). Make also knows how to compile C source files (as long as the source and object path match), so your pattern rule is superfluous too.
The object prerequisites aren't necessary as both clang and GCC can generate dependencies for you with the -M set of flags.
Compiling release and debug builds in the same dir makes for a more simple makefile, although you will need to remember to clean the object files when switching.
By default make assigns cc to CC, and cc should be a link to your system's default compiler, so you might not even need the first line below
CC := clang
CPPFLAGS := -MMD -MP
CFLAGS := -Weverything -Wno-padded -Wno-unused-parameter -Wno-unused-variable -Wno-sign-conversion -O3
objs := fianchetto.o util.o ttable.o movegen.o
deps := $(objs:.o=.d)
.PHONY: all debugf clean
all: CPPFLAGS += -DNDEBUG
debugf: CFLAGS += -g3
all debugf: fianchetto
fianchetto: $(objs)
clean: ; $(RM) $(objs) $(deps) fianchetto fianchetto.dSYM
-include $(deps)

make file for Gtk

I have a make file, which creates obj files for all source files and then the executable using those obj files (basically compiling each individual file and then linking all of them together).
CC = gcc
SRC_DIR = src
INC_DIR = inc
OBJ_DIR = obj
CFLAGS = -c -Wall -I$(INC_DIR)
EXE = project
SRCS = $(SRC_DIR)/main.c $(SRC_DIR)/file1.c # and so on...
OBJS = $(OBJ_DIR)/main.o $(OBJ_DIR)/file1.o # and so on...
main : clean build
build: $(OBJS)
$(CC) $(OBJS) -o $(EXE)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
I tried to do the same for gtk+3.0 but haven't been successful as the examples on the web always have been with respect to the example file and not the project as a whole (consisting multiple source files). one such eg:
$ cc `pkg-config --cflags --libs gtk+-3.0` hello.c -o hello
Make file for gtk+ is:
CC = gcc
SRC_DIR = .
INC_DIR = .
OBJ_DIR = Obj
CFLAGS = -Wall -g -o
PACKAGE = `pkg-config --cflags --libs gtk+-3.0`
LIBS = `pkg-config --libs gtk+-3.0`
EXE = Gui
SRCS = $(SRC_DIR)/main.c
OBJS = $(OBJ_DIR)/main.o
main : clean build
build: $(OBJS)
$(CC) $(OBJS) -o $(EXE)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(PACKAGE) $(CFLAGS) $< -o $#
But this doesn't work. It gives errors (undefined reference to 'gtk_init' and other gtk functions)
What modifications should i do?
It should be
LDLIBS = $(shell pkg-config --libs gtk+-3.0)
instead of LIB
Check with make -p your builtin rules.
Look also at this example. See $(LINK.o) variable, etc.
The CFLAGS must have -c or that must be included while compiling. Also, the pkg-config must be included during linking.
After the changes, the make file becomes:
build: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(EXE) $(LIBS)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) ***-c*** -I$(INC_DIR) $< -o $# $(PACKAGE)
The changes run successfully.

extra CFLAGs with Makefile

I'm reading through Foundations of GTK+ and in so doing decided to write a simple makefile that would let me run "make " to compile the example program I'd just written. I also stumbled upon a list of compiler directives here that the Gnome team specified will help moving from GTK2 to GTK3, so I wanted to include those.
I'm a make noob for all intents and purposes, so this is what I came up with:
CC = gcc
CFLAGS += -Wall
GTK_DFLAGS = -DGTK_DISABLE_SINGLE_INCLUDES -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGSEAL_ENABLE
GTK_CFLAGS = $(shell pkg-config --cflags gtk+-3.0)
GTK_LDFLAGS = $(shell pkg-config --libs gtk+-3.0)
%.o: %.c
$(CC) $(CFLAGS) $(GTK_DFLAGS) $(GTK_CFLAGS) -c -o $# $<
%: %.o
$(CC) $(CFLAGS) $(GTK_DFLAGS) $(GTK_CFLAGS) $(GTK_LDFLAGS) -o $# $<
.PHONY: clean
clean:
rm -f *.o *~
And as you might guess, it doesn't work quite right. I know running pkg-config from inside the makefile isn't an ideal solution, but this is for my small-scale learning projects and not for deployment of any sort. That said, the output is weird to me; it seems like make just ignores any variables after CFLAGS.
Something like:
[patrick#blackbox ch2]$ make helloworld
gcc -Wall helloworld.c -o helloworld
helloworld.c:1:21: fatal error: gtk/gtk.h: No such file or directory
#include <gtk/gtk.h>
^
compilation terminated.
<builtin>: recipe for target 'helloworld' failed
make: *** [helloworld] Error 1
If I add have the contents of GTK_DFLAGS simply tacked onto the end of CFLAGS, they appear on the command line, but the pkg-config variables are still missing.
It's obvious to me that I messed something simple up, but after an hour of vaguely worded Googling, I'm fresh out of ideas as to what it is.
Found the answer, and of course the vocabulary I was missing when asking this question/doing earlier searches.
CC = gcc
CFLAGS += -Wall -std=c11
GTK_DFLAGS = -DGTK_DISABLE_SINGLE_INCLUDES -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGSEAL_ENABLE
GTK_CFLAGS := $(shell pkg-config --cflags gtk+-3.0)
GTK_LDFLAGS := $(shell pkg-config --libs gtk+-3.0)
%: %.c
$(CC) $(CFLAGS) $(GTK_DFLAGS) $(GTK_CFLAGS) $(GTK_LDFLAGS) -o $* $*.c
.PHONY: clean
clean:
rm -f *~
This does what I want, which is to compile a single .c file of any name into a program of the same name with the GTK flags I was looking to use.
Thanks to those who contributed!
You need a target for helloworld in your Makefile. Something like this:
helloworld: helloworld.o
$(CC) -o helloworld helloworld.o $(LDFLAGS) $(GTK_LDFLAGS)

Making a better Makefile

so I learned what a Makefile was some time ago, created a template Makefile and all I do is copy and alter the same file for every program I'm doing. I changed it a few times, but it's still a very crude Makefile. How should I improve it? This is an example of my current version:
CC = g++
CFLAGS = -std=gnu++0x -m64 -O3 -Wall
IFLAGS = -I/usr/include/igraph
LFLAGS = -ligraph -lgsl -lgslcblas -lm
DFLAGS = -g -pg
# make all
all: run test
# make a fresh compilation from scratch
fresh: clean test
#makes the final executable binary
run: main.o foo1.o foo2.o
$(CC) $(CFLAGS) $(LFLAGS) $^ -o $#
#makes the test executable with debugging and profiling tags
test: test.o foo1.o foo2.o
$(CC) $(DFLAGS) $(CFLAGS) $(LFLAGS) $^ -o $#
#makes teste.o
teste.o: teste.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#makes main.o
main.o: main.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#file foo1
foo1.o: foo1.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
#file foo2
foo2.o: foo2.cpp
$(CC) $(CFLAGS) $(IFLAGS) -c $^ -o $#
clean: clean-test clean-o clean-annoying
clean-test:
rm test-rfv
clean-o:
rm *.o -rfv
clean-annoying:
rm *~ -rfv
Just by visually comparing with other makefiles I saw around in the web, this seems to be not a very bright Makefile. I don't know how they work, but I can see there's significantly less boilerplate and more generic code in them.
Can this can be made better, safer, and easier to particularize for each project?
You don't want to name specific files in a makefile if you can get away with it, and 99% of the time you can. This page shows how to develop a very general makefile. The following is my own makefile, based on that page's info:
SHELL := bash
PROG := pathed.exe
OUTDIRS := bin/debug bin/rel obj/debug obj/rel
PROG_REL := bin/rel/$(PROG)
PROG_DEBUG := bin/debug/$(PROG)
SRCFILES := $(wildcard src/*.cpp)
OBJFILES_REL := $(patsubst src/%.cpp,obj/rel/%.o,$(SRCFILES))
OBJFILES_DEBUG := $(patsubst src/%.cpp,obj/debug/%.o,$(SRCFILES))
DEPFILES := $(patsubst src/%.cpp,obj/%.d,$(SRCFILES))
CFLAGS := -Iinc -Wall -Wextra -MMD -MP
DBFLAGS := -g
RELFLAGS :=
CC := g++
.PHONY: default all testmake debug release clean dirs
default: debug
all: dirs clean debug release
dirs:
#mkdir -p $(OUTDIRS)
debug: $(PROG_DEBUG)
release: $(PROG_REL)
testmake:
#echo OBJFILES_REL = $(OBJFILES_REL)
#echo OBJFILES_DEBUG = $(OBJFILES_DEBUG)
#echo SRCFILES = $(SRCFILES)
#echo DEPFILES = $(DEPFILES)
clean:
rm -f $(OBJFILES_REL) $(OBJFILES_DEBUG) $(DEPFILES) $(PROG)
$(PROG_REL): $(OBJFILES_REL)
$(CC) $(OBJFILES_REL) -o $(PROG_REL)
strip $(PROG_REL)
#echo "---- created release binary ----"
$(PROG_DEBUG): $(OBJFILES_DEBUG)
$(CC) $(OBJFILES_DEBUG) -o $(PROG_DEBUG)
#echo "---- created debug binary ----"
-include $(DEPFILES)
obj/rel/%.o: src/%.cpp
$(CC) $(RELFLAGS) $(CFLAGS) -MF $(patsubst obj/rel/%.o, obj/%.d,$#) -c $< -o $#
obj/debug/%.o: src/%.cpp
$(CC) $(DBFLAGS) $(CFLAGS) -MF $(patsubst obj/debug/%.o, obj/%.d,$#) -c $< -o $#
Do NOT use CC for the C++ compiler. The standard convention is that CC is the C compiler, CXX is the C++ compiler. CFLAGS are flags for the C compiler, CXXFLAGS are flags for the C++ compiler, and CPPFLAGS are flags for the pre-processor (eg, -I or -D flags). Use LDFLAGS for -L flags to the linker, and LDLIBS (or LOADLIBES) for -l flags.
Using the standard conventions is good not just because it makes things easier for others to understand, but also because it allows you to take advantage of implicit rules. If make needs to make a .o file from a .c file and you have not provided a rule, it will use a standard rule and honor the settings of CC, CFLAGS, and CPPFLAGS. If CC is a C++ compiler, things will probably not work.

How can I configure my makefile for debug and release builds?

I have the following makefile for my project, and I'd like to configure it for release and debug builds. In my code, I have lots of #ifdef DEBUG macros in place, so it's simply a matter of setting this macro and adding the -g3 -gdwarf2 flags to the compilers. How can I do this?
$(CC) = g++ -g3 -gdwarf2
$(cc) = gcc -g3 -gdwarf2
all: executable
executable: CommandParser.tab.o CommandParser.yy.o Command.o
g++ -g -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl
CommandParser.yy.o: CommandParser.l
flex -o CommandParser.yy.c CommandParser.l
gcc -g -c CommandParser.yy.c
CommandParser.tab.o: CommandParser.y
bison -d CommandParser.y
g++ -g -c CommandParser.tab.c
Command.o: Command.cpp
g++ -g -c Command.cpp
clean:
rm -f CommandParser.tab.* CommandParser.yy.* output *.o
Just to clarify, when I say release/debug builds, I want to be able to just type make and get a release build or make debug and get a debug build, without manually commenting out things in the makefile.
You can use Target-specific Variable Values. Example:
CXXFLAGS = -g3 -gdwarf2
CCFLAGS = -g3 -gdwarf2
all: executable
debug: CXXFLAGS += -DDEBUG -g
debug: CCFLAGS += -DDEBUG -g
debug: executable
executable: CommandParser.tab.o CommandParser.yy.o Command.o
$(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl
CommandParser.yy.o: CommandParser.l
flex -o CommandParser.yy.c CommandParser.l
$(CC) -c CommandParser.yy.c
Remember to use $(CXX) or $(CC) in all your compile commands.
Then, 'make debug' will have extra flags like -DDEBUG and -g where as 'make' will not.
On a side note, you can make your Makefile a lot more concise like other posts had suggested.
This question has appeared often when searching for a similar problem, so I feel a fully implemented solution is warranted. Especially since I (and I would assume others) have struggled piecing all the various answers together.
Below is a sample Makefile which supports multiple build types in separate directories. The example illustrated shows debug and release builds.
Supports ...
separate project directories for specific builds
easy selection of a default target build
silent prep target to create directories needed for building the project
build-specific compiler configuration flags
GNU Make's natural method of determining if project requires a rebuild
pattern rules rather than the obsolete suffix rules
#
# Compiler flags
#
CC = gcc
CFLAGS = -Wall -Werror -Wextra
#
# Project files
#
SRCS = file1.c file2.c file3.c file4.c
OBJS = $(SRCS:.c=.o)
EXE = exefile
#
# Debug build settings
#
DBGDIR = debug
DBGEXE = $(DBGDIR)/$(EXE)
DBGOBJS = $(addprefix $(DBGDIR)/, $(OBJS))
DBGCFLAGS = -g -O0 -DDEBUG
#
# Release build settings
#
RELDIR = release
RELEXE = $(RELDIR)/$(EXE)
RELOBJS = $(addprefix $(RELDIR)/, $(OBJS))
RELCFLAGS = -O3 -DNDEBUG
.PHONY: all clean debug prep release remake
# Default build
all: prep release
#
# Debug rules
#
debug: $(DBGEXE)
$(DBGEXE): $(DBGOBJS)
$(CC) $(CFLAGS) $(DBGCFLAGS) -o $(DBGEXE) $^
$(DBGDIR)/%.o: %.c
$(CC) -c $(CFLAGS) $(DBGCFLAGS) -o $# $<
#
# Release rules
#
release: $(RELEXE)
$(RELEXE): $(RELOBJS)
$(CC) $(CFLAGS) $(RELCFLAGS) -o $(RELEXE) $^
$(RELDIR)/%.o: %.c
$(CC) -c $(CFLAGS) $(RELCFLAGS) -o $# $<
#
# Other rules
#
prep:
#mkdir -p $(DBGDIR) $(RELDIR)
remake: clean all
clean:
rm -f $(RELEXE) $(RELOBJS) $(DBGEXE) $(DBGOBJS)
If by configure release/build, you mean you only need one config per makefile, then it is simply a matter and decoupling CC and CFLAGS:
CFLAGS=-DDEBUG
#CFLAGS=-O2 -DNDEBUG
CC=g++ -g3 -gdwarf2 $(CFLAGS)
Depending on whether you can use gnu makefile, you can use conditional to make this a bit fancier, and control it from the command line:
DEBUG ?= 1
ifeq ($(DEBUG), 1)
CFLAGS =-DDEBUG
else
CFLAGS=-DNDEBUG
endif
.o: .c
$(CC) -c $< -o $# $(CFLAGS)
and then use:
make DEBUG=0
make DEBUG=1
If you need to control both configurations at the same time, I think it is better to have build directories, and one build directory / config.
Note that you can also make your Makefile simpler, at the same time:
DEBUG ?= 1
ifeq (DEBUG, 1)
CFLAGS =-g3 -gdwarf2 -DDEBUG
else
CFLAGS=-DNDEBUG
endif
CXX = g++ $(CFLAGS)
CC = gcc $(CFLAGS)
EXECUTABLE = output
OBJECTS = CommandParser.tab.o CommandParser.yy.o Command.o
LIBRARIES = -lfl
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CXX) -o $# $^ $(LIBRARIES)
%.yy.o: %.l
flex -o $*.yy.c $<
$(CC) -c $*.yy.c
%.tab.o: %.y
bison -d $<
$(CXX) -c $*.tab.c
%.o: %.cpp
$(CXX) -c $<
clean:
rm -f $(EXECUTABLE) $(OBJECTS) *.yy.c *.tab.c
Now you don't have to repeat filenames all over the place. Any .l files will get passed through flex and gcc, any .y files will get passed through bison and g++, and any .cpp files through just g++.
Just list the .o files you expect to end up with, and Make will do the work of figuring out which rules can satisfy the needs...
for the record:
$# The name of the target file (the one before the colon)
$< The name of the first (or only) prerequisite file (the first one after the colon)
$^ The names of all the prerequisite files (space separated)
$* The stem (the bit which matches the % wildcard in the rule definition.
you can have a variable
DEBUG = 0
then you can use a conditional statement
ifeq ($(DEBUG),1)
else
endif
Completing the answers from earlier... You need to reference the variables you define info in your commands...
DEBUG ?= 1
ifeq (DEBUG, 1)
CFLAGS =-g3 -gdwarf2 -DDEBUG
else
CFLAGS=-DNDEBUG
endif
CXX = g++ $(CFLAGS)
CC = gcc $(CFLAGS)
all: executable
executable: CommandParser.tab.o CommandParser.yy.o Command.o
$(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl
CommandParser.yy.o: CommandParser.l
flex -o CommandParser.yy.c CommandParser.l
$(CC) -c CommandParser.yy.c
CommandParser.tab.o: CommandParser.y
bison -d CommandParser.y
$(CXX) -c CommandParser.tab.c
Command.o: Command.cpp
$(CXX) -c Command.cpp
clean:
rm -f CommandParser.tab.* CommandParser.yy.* output *.o
You could also add something simple to your Makefile such as
ifeq ($(DEBUG),1)
OPTS = -g
endif
Then compile it for debugging
make DEBUG=1

Resources