extra CFLAGs with Makefile - gcc

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)

Related

Can't use LAPACK in makefile

I have program (in fortran) where I'm using three custom modules, which make use of LAPACK. Until now I've compiled my program using the following shell script:
filestring="main"
gfortran -c mod_exp.f90 mod_genmat.f90 mod_print.f90 $filestring.f90
gfortran mod_exp.o mod_genmat.o mod_print.o $filestring.o -llapack -lblas
rm mod_exp.o mod_genmat.o mod_print.o $filestring.o exponentiate.mod genmat.mod printing.mod printing_subrtns.mod
mv a.out $filestring
Since I've been using more and more modules and different programs using them, I've decided to start using makefiles. Following a tutorial, I managed to write the following:
FC = gfortran
FFLAGS = -Wall -Wextra -llapack -lblas #-fopenmp
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ)
clean:
#rm -f *.o *.mod main
However, when executing make, it says that the LAPACK functions are not recognized. One such mistake is the following:
/usr/bin/ld: mod_exp.o: in function `__exponentiate_MOD_diagun':
mod_exp.f90:(.text+0x37f): undefined reference to `zgees_'
...
collect2: error: ld returned 1 exit status
One possible mistake I've seen is that I need to specify the location of the libraries. However, it would seem strange since I didn't need to do it before; also, I don't know how to find it.
Please show the link command that make invoked, that caused the error to be generated.
I'm confident that if you cut and paste that exact command line to your shell prompt, you will get the same error you see when make runs it. So the problem is not make, but your link command.
The problem is that you have put the libraries before the objects in the link line. Libraries should come at the end, after the objects, else when the linker examines the libraries it doesn't know what symbols will need to be included (because no objects have been parsed yet to see what symbols are missing).
This is why LDLIBS is traditionally a separate variable:
FC = gfortran
FFLAGS = -Wall -Wextra #-fopenmp
LDLIBS = -llapack -lblas
SOURCES = mod_print.f90 mod_genmat.f90 mod_exp.f90 main.f90
OBJ = ${SOURCES:.f90=.o} #substitute .f90 with .o
%.o : %.f90 #creation of all *.o files DEPENDS on *.f90
$(FC) $(FFLAGS) -c -O $< -o $#
main: $(OBJ)
$(FC) $(FFLAGS) -o $# $(OBJ) $(LDLIBS)

How to link libs once only in GCC?

Pardon my question, I am a beginner to GCC. I have a framework project that holds source code for multiple subcomponents.
The structure is below:
Framework/
makefile //Master makefile in root
Component1/
src/
bin/
makefile
Component2/
src/
bin/
makefile
...
...
...
ComponentN/
src/
bin/
makefile
Now each makefiles in ComponentN/ each of directories will compile the code in its respective src/ and output .o to bin/ directory.
The root makefile however searches all the .o files recursively and links them all into one executable named 'framework'
Problem:
For code dependencies like glib,gdbus,gio I have to link them once when creating .o objects, in each of the component projects.
Plus I have to link the dependencies again when linking all the .o into one executable at root level.
Why do I have to do it twice? I am interested in understanding the internal mechanics.
As per request I am putting in makefile of the individual component libs that products *.o files
CC = gcc
CFLAGS = -g3
LIBS = `pkg-config --cflags --libs glib-2.0`
BINDIR = bin
OUTOBJ = $(addprefix $(BINDIR)/, objex.o)
$(BINDIR)/%.o : %.c
$(CC) -c $< $(CFLAGS) -o $# $(LIBS)
all: $(OUTOBJ)
$(OUTOBJ): | $(BINDIR)
$(BINDIR):
mkdir $(BINDIR)
.PHONY: clean
clean:
rm bin/*
Object files (.o) are created by compilation commands, e.g.
gcc -c -o foo.o foo.c ...
g++ -c -o baz.o baz.cpp ...
-c means compile; don't link. No linkage happens in the creation of
object files by the compiler. Any linkage options that you add to a compilation
command, e.g.
gcc -c -o foo.o foo.c -L/my/libs -lbar -lgum
are simply ignored.
Linkage options are acted on by a linkage command, which creates a program, or shared/dynamic
library, by linking together object files and libraries, e.g.
gcc -o prog foo.o baz.o -L/my/libs -lbar -lgum
gcc -shared -o libfoobaz.so foo.o baz.o -L/my/libs -lbar -lgum
So:
For code dependencies like glib,gdbus,gio I have to link them once when creating .o objects, in each of the component projects.
No you don't, and you can't.
Later
With sight of the problem makefile it is quite clear how to eliminate
the $(LIBS) reference from the compilation recipe, and what has been stopping you. The makefile defines:
LIBS = `pkg-config --cflags --libs glib-2.0`
which is a mistake. That makes $(LIBS) expand to the standard output of the
command:
pkg-config --cflags --libs glib-2.0
which is a single string containing both the compilation options required
for compiling source that #include-s the glib-2.0 API (on account of --cflags)
and also the linkage options required for linking a program or shared library
against libglib-2.0 (on account of --libs). On my system that is:
$ pkg-config --cflags --libs glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0
of which the compilation options alone would be output by:
$ pkg-config --cflags glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
and the linkage options alone would be output by:
$ pkg-config --libs glib-2.0
-lglib-2.0
But because both sets of options are available only together through the expansion
of $(LIBS) you cannot successfully compile without passing the
linkage option -lglib-2.0, which is redundant and ignored.
As your make tool is evidently GNU Make, the makefile (which BTW is not that bad!) would be better written as:
Makefile
CC := gcc
CFLAGS := -g3 $(shell pkg-config --cflags glib-2.0)
BINDIR := bin
SRCS := objex.c
OUTOBJ := $(addprefix $(BINDIR)/, $(SRCS:.c=.o))
.PHONY: all clean
all: $(OUTOBJ)
$(BINDIR)/%.o : %.c
$(CC) -c $< $(CFLAGS) -o $#
$(OUTOBJ): | $(BINDIR)
$(BINDIR):
mkdir -p $(BINDIR)
clean:
$(RM) $(OUTOBJ)
which dispenses with LIBS and runs from scratch like:
$ make
mkdir -p bin
gcc -c objex.c -g3 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -o bin/objex.o
Note a few other improvements:-
The use of immediate expansion (:=) wherever applicable in preference to unnecessary
recursive expansion (=). See 6.2 The Two Flavors of Variables
The use of direct shell substitution by make - $(shell command) - in preference to backtick-expansion in
recipe execution. See 8.13 The shell Function.
all, like clean is a phony target
and you need to tell make that it is, to avoid the booby-trap in which something creates a file called all in
the project directory without you noticing and make mysteriously stops detecting any work for it to do.
With your clean receipe:
clean:
rm bin/*
make clean will fail if ever run except following a successful build. The recipe
is replaced with $(RM) $(OUTOBJ), using GNU Make's predefined delete macro, which
won't fail.
Finally, remember that your linkage recipe, wherever it is, does need the library options for glib-2.0,
which you should provide in its makefile with:
LIBS := $(shell pkg-config --libs glib-2.0) # ...and any more library options required
for use in a recipe similar to:
prog: $(OBJS)
$(CC) -o $# $(LDFLAGS) $^ $(LIBS)
[1] Strictly, preprocessor options should appear in the definition of CPPFLAGS
(C PreProcessor Flags), not to be confused with CXXFLAGS (C++ compilation options).
[2] Strictly, linkage options other than libraries should appear in the definition
of LDFLAGS.

Multiple compilers in one Makefile

I found this question here, which does exactly what I want. However, being new to makefiles, I am having a hard time seeing how to implement the second answer in my current setup.
I have a simple makefile for which I would like to use different compilers when compiling for Linux or cross-compiling for Windows. As presented, the file below works. To make for Linux I just type make, and for windows I type make os=win. In the interest of learning how makefiles work a little better, I would like to be able to implement the linked answer in the current Makefile so that I can make for windows just by typing make win or make cross as presented in the linked question.
Could someone help me understand how the structure presented in the linked answer could be implemented in the specific case I have here? Presumably there is a more elegant way than having native: and cross: targets and replicating almost the entirety of the code across both.
Any suggestions for cleaning up the Makefile in general are also welcome.
ifeq ($(os),win)
CC=x86_64-w64-mingw32-gcc
OUT=cusum.exe
else
CC=gcc
OUT=cusum
endif
CFLAGS=-D_GNU_SOURCE -O3 -Wall -Wextra -lm --static
DEPS=bessel.h detector.h io.h stepfit.h lmmin_int64.h utils.h
ODIR=obj
_OBJ=main.o bessel.o detector.o io.o lmmin_int64.o stepfit.o utils.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
LIBS=-lm
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$(OUT): $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(OUT) $(ODIR)/*.o *~ core $(INCDIR)/*~
You only have to introduce an upper-level target. Target-specific variables are inherited by their prerequisites, so you don't have to change all the targets.
However, you cannot update the content of targets or prerequisites using this method so you can't remove the assignment of OUT. This means you can't get rid of the OS variable assignment.
One simple way to do it is to use recusive invocations of make. Write your makefile normally:
O = o
E =
CC = gcc
OUT = cusum$E
CFLAGS = -D_GNU_SOURCE -O3 -Wall -Wextra -lm --static
DEPS = bessel.h detector.h io.h stepfit.h lmmin_int64.h utils.h
ODIR = obj
_OBJ = main.$O bessel.$O detector.$O io.$O lmmin_int64.$O stepfit.$O utils.$O
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
LIBS = -lm
$(ODIR)/%.$O: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$(OUT): $(OBJ)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -rf $(OUT)* obj wobj *~ core $(INCDIR)/*~
Then add a target that recursively invokes make overriding the relevant variables (be sure to put it at the end or at least after the $(OUT) target):
win:
$(MAKE) CC=x86_64-w64-mingw32-gcc E=.exe O=obj ODIR=wobj
Now you can run make win and it will recursively invoke make overriding the appropriate variables.

makefile for openmp by g++ ---- It is not working

I want to use a makefile for my code which is going to use openmp. My source files are compiled and linked without any error. But when I run it, it uses just one processor, even though I adjust their number by for instance export OMP_NUM_THREADS=2.
The makefile is shown in the following. I would be grateful if somebody could please help me.
Best
CPP_FILES := $(wildcard src/*.cpp)
OBJ_FILES := $(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
CC = g++
DEBUG = -g
INTEL=icc
ifeq ($(notdir $(CC)),$(INTEL))
CCFLAGS=-openmp -lm -lstdc++
else
CCFLAGS=-fopenmp -lm -lstdc++
endif
LD_FLAGS :=-fopenmp -Wall $(DEBUG)
#CC_FLAGS := -Wall -c $(DEBUG)
MAIN: $(OBJ_FILES)
$(CC) $(LD_FLAGS) -o $# $^
obj/%.o: src/%.cpp
$(CC) $(CC_FLAGS) -c -o $# $<
.PHONY: clean
clean:
rm -f $(OBJ_FILES) *.o
Your defined variable CCFLAGS doesn't match the variable you're using CC_FLAGS in the actual compilation rules. When you clean up and run make do the compilation lines actually show the flags you set being passed? I'd expect they shouldn't, unless the code you have here isn't a direct copy of what you're running.
For ease of debugging, could you copy and paste a terminal transcript showing the compilation and linking happening?

Multiple targets and libraries in 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)

Resources