make file for Gtk - makefile

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.

Related

Why does undefined reference disappear after adding a .cpp file with empty main function when building shared library

I have makefile that builds shared library libsimpletron.so:
#shell
MKDIR_P = mkdir -p
#compiler
CC = g++
#cpp flags
FLAGS = -std=c++1z
CPPFLAGS = -fPIC -Wall -Wextra
LDFLAGS = -shared
#directories
INC_DIR = ../inc
LIB_DIR = ../lib
BIN_DIR = ../bin
OBJ_DIR = ./obj
ALG_DIR = ./algebra
SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo $(INC_DIR)/*.h)
_OBJECTS = $(SOURCES:.cpp=.o)
OBJECTS = $(patsubst %,$(OBJ_DIR)/%,$(_OBJECTS))
ALGEBRA = $(LIB_DIR)/libalgebra.so
TARGET = $(LIB_DIR)/libsimpletron.so
.PHONY: directories
all : directories $(ALGEBRA) $(TARGET)
directories: $(OBJ_DIR) $(BIN_DIR) $(LIB_DIR)
$(OBJ_DIR):
$(MKDIR_P) $(OBJ_DIR)
$(BIN_DIR):
$(MKDIR_P) $(BIN_DIR)
$(LIB_DIR):
$(MKDIR_P) $(LIB_DIR)
$(ALGEBRA):
$(MAKE) -C $(ALG_DIR)
$(OBJ_DIR)/%.o: %.cpp $(HEADERS)
$(CC) -c $(FLAGS) $(CPPFLAGS) -o $# $<
$(TARGET) : $(OBJECTS)
$(CC) $(LDFLAGS) -o $# $^
.PHONY: clean
clean:
rm -f $(OBJ_DIR)/*.o
make command builds library successfully (I think) :
g++ -c -std=c++1z -fPIC -Wall -Wextra -o obj/builder.o builder.cpp
...similar lines for each .cpp file...
g++ -shared -o ../lib/libsimpletron.so obj/builder.o obj/gradient_trainer.o obj/layer.o obj/neuron.o obj/perceptron.o obj/simpletron.o obj/trainer.o
Then I am trying to use this library. I compile my test xor as follows:
#compiler
CC = g++
#cpp flags
FLAGS = -std=c++1z
PUGI = -l pugixml
#directories
LIB_DIR = /home/lrdprdx/Projects/SimplePerceptron/lib
SIMPLETRON = -lsimpletron
ALGEBRA = -lalgebra
XOR = xor
SOURCE = xor.cpp
#config file
CONFIG = config.xml
$(XOR) : $(SOURCE) $(CONFIG)
$(CC) $(FLAGS) -L$(LIB_DIR) $(SIMPLETRON) $(ALGEBRA) $(PUGI) -o $(XOR) $(SOURCE)
But when I try to compile this I get errors of undefined reference to .... OK, though I do not understand why those errors exist, I found that adding a .cpp file with an empty main function to the directory with other .cpp files fixes all the stuff:
//empty.cpp
int main()
{
return 0;
}
And after rebuild the shared library I make and execute xor successfully.
The question is: what is going on here?
I doubt that adding the extra file really fixed anything. Most likely some other side-effect helped.
Your problem is that your link line is incorrect. GCC, like most UNIX linkers, is a single-pass linker. That means it only walks all the libraries one time looking for unresolved symbols. And that means that the order of the arguments to the linker is critically important: you have to ensure that if item A references symbols in item B, that A comes before B on the link line.
In your example, you are putting all your libraries first, and your source files last. So, when make starts looking at your libraries it hasn't seen your sources yet, and there are no symbols it needs to link. By the time it compiles your sources, there are no libraries left to resolve symbols from.
Your link line should be arranged with sources and object files first, then libraries (in referencer ... referencee order):
$(CC) $(FLAGS) $(SOURCE) -L$(LIB_DIR) $(SIMPLETRON) $(ALGEBRA) $(PUGI) -o $(XOR)

How to rename various file extensions to .o in makefile?

Hi I have this makefile:
CC = gcc
AS = nasm
CFLAGS = -ffreestanding -Wall -Wextra -std=c11 -m32 -nostdlib -nostdinc -fno-stack-protector
LDFLAGS = -m elf_i386 -T link.ld
ASFLAGS = -f elf32
SOURCES = $(wildcard src/*.c wildcard src/*.s)
OBJECTS = $(SOURCES:.[s|o]=.o)
INCLUDEPATH = -I inc src/include
OBJDIR = bin/obj
SRCDIR = src/
all: build
build:
ld $(LDFLAGS) $(OBJECTS) -o bin/kernel.bin
iso: build
cp bin/kernel.bin XeonOS/boot
grub-mkrescue -o XeonOS.iso XeonOS/
run: iso
quemu-system-i386 -m 512M -cdrom XeonOS.iso
clean:
rm -rf bin/*.o bin/kernel.bin
%.o: $(SRCDIR)%.c
$(CC) $(INCLUDEPATH) $(CFLAGS) $< -o $(OBJDIR)/$(OBJECTS)
%.o: $(SRCDIR)%.s
$(AS) $(ASFLAGS) $< -o $(OBJDIR)/$(OBJECTS)
And when i execute the command make run i get the following error:
ld -m elf_i386 -T link.ld src/kernel_c.c src/kernel_asm.s -o bin/kernel.bin
ld:src/kernel_c.c: file format not recognized; treating as linker script
Because the kernel_c.c and kernel_asm.s didn' change their extension to .o. How can i change the extension of both .s and .c to .o at the same time?
By the way, I will have another problem, the value of the OBJECTS variable contains the src/ directory but the object files are stored in the bin/obj folder, How can i change that?
When I had this problem last month I just did this:
SOURCES_C := $(wildcard src/*.c)
SOURCES_S := $(wildcard src/*.s)
OBJECTS := $(SOURCES_C:%.c=%.o) \
$(SOURCES_S:%.s=%.o)
I haven't looked at this too deeply but, as far as I know, that's your best bet.
Finally I used the #LightnessRacesinOrbit advice and also used patsubsr so the code is now working:
CC = gcc
AS = nasm
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector -nostartfiles -nodefaultlibs -Wall -Wextra -Werror
LDFLAGS = -m elf_i386 -T link.ld
ASFLAGS = -f elf32
C_SOURCES = $(wildcard src/*.c)
C_OBJECTS = $(patsubst %.c,%.o, $(notdir $(C_SOURCES) ))
ASM_SOURCES = $(wildcard src/*.s)
ASM_OBJECTS = $(patsubst %.s,%.o, $(notdir $(ASM_SOURCES) ))
INCLUDEPATH = -I src/include
OBJDIR = bin/obj
SRCDIR = src/
.PHONY: build
all: build
build: $(C_OBJECTS) $(ASM_OBJECTS)
ld $(LDFLAGS) $(OBJDIR)/$(ASM_OBJECTS) $(OBJDIR)/$(C_OBJECTS) -o bin/kernel.bin
iso: build
cp bin/kernel.bin XeonOS/boot
grub-mkrescue -o XeonOS.iso XeonOS/
run: iso
bochs -f bochsconfig.cfg -q
clean:
rm -rf XeonOS/boot/kernel.bin
rm -rf bin/obj/*.o bin/kernel.bin
%.o: $(SRCDIR)%.c
$(CC) $(INCLUDEPATH) $(CFLAGS) $< -o $(OBJDIR)/$#
%.o: $(SRCDIR)%.s
$(AS) $(ASFLAGS) $< -o $(OBJDIR)/$#

CPPUTestMakeFile Help linking

I am trying to make a makefile, which can make an exe for CppUTest. It can not find the headers, what have I done wrong? First time making a makefile, not 100% sure what I'm doing.
#The compiler to use
CC = g++
LINK = -g -pedantic -Wall -lstdc++ -lpthread -ldl -lm -Wl,-rpath,.
COMPILE = -g -O3 -D_THREAD_SAFE -pedantic -Wall -c -Wno-deprecated
#Name of the EXE file to create.
EXE = ./Tests
SRCS = $(shell ls *.cpp)
OBJS = $(subst .cpp,.o,$(SRCS))
#Extra flags to give to the C compiler.
CFLAGS =
#Libraries to include
LIBS= -lCppUTestExt -lCppUTest -lm
#Extra flags to give to the C++ compiler.
CXXFLAGS = -I/home/mg/DS-5-Workspace/Tests/include
#Extra flags to give to compilers when they are supposed to invoke the linker, ‘ld’,
#such as -L. Libraries (-lfoo) should be added to the LDLIBS variable
#instead.
LDFLAGS = -L/home/mg/DS-5-Workspace/Tests/cpputest/lib
#Extra flags to give to the C preprocessor and programs that use it (the C and
#Fortran compilers).
CPPFLAGS =
.SUFFIXES: .o .cpp
.cpp.o:
$(CC) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $(COMPILE) $(LIBS) $<
all: $(OBJS)
$(CC) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $(LIBS) $(OBJS) -o $(EXE) $(LINK)
-include depend.mak
depend:
g++ -MM $(SRCS) > depend.mak
#static:
#ar -crvs $(a) $(OBJS)
#shared: $(OBJS)
#$(CC) -shared -Wl,-soname -lc -o $(so) $(OBJS)
clean:
rm -rf $(OBJS) depend.mak $(EXE) $(so) $(a)
I have the following error:
error: CppUTest/CommandLineTestRunner.h: No such file or directory
Well, you're mixing up a lot of things.
Let's clean this up and keep only what is needed :
EXE := Tests
SRC_DIR := .
OBJ_DIR := obj
SRC := $(wildcard $(SRC_DIR)/*.cpp)
OBJ := $(SRC:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
CPPFLAGS := -I/home/mg/DS-5-Workspace/Tests/include
CPPFLAGS += -MMD -MP -D_THREAD_SAFE
CXXFLAGS := -W -Wall -Wno-deprecated -pedantic -O3 -g
LDFLAGS := -L/home/mg/DS-5-Workspace/Tests/cpputest/lib
LDFLAGS += -Wl,-rpath,.
LDLIBS := -lCppUTestExt -lCppUTest -lm -lstdc++ -lpthread -ldl
.PHONY: all clean fclean re
all: $(EXE)
clean:
$(RM) -f -r $(OBJ_DIR)
fclean: clean
$(RM) -f $(EXE)
re: fclean all
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
# %.a: $(OBJ)
# $(AR) crvs $# $^
# ranlib $#
# %.so: CXXFLAGS += -fPIC
# %.so: $(OBJ)
# $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR):
#mkdir -p $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
-include $(OBJ:.o=.d)
Some explanations :
Avoid the $(shell ...) function, because it'll be executed each time the variable is called if assigned with the = operator instead of := operator.
$(CC) is a built-in variable containing cc or gcc (should be equivalent). Use the built-in $(CXX) to use g++.
-g, -pedantic, -O3, -Wno-deprecated and -Wall are compiler flags, they should be in the CFLAGS (for C) or CXXFLAGS (for C++) built-in variables.
-I <path> and -D_THREAD_SAFE are preprocessor flag, thus should be in the CPPFLAGS built-in variable.
-MMD -MP will auto-generate dependency files (.d extension) for each .o file. You can read more here.
.cpp.o: is a suffix rule, and suffix rules are the old-fashioned way of defining implicit rules for make. You should just rely upon these implicit rules make already know about or make your own the modern way.
You don't need to define .SUFFIXES: by yourself for such widely used targets. The variable SUFFIXES is defined to the default list of suffixes before make reads any makefiles. Make 3.82 defines these suffixes by default :
.SUFFIXES: .out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el
If you have any questions, go on.

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)

My Makefile is trying to compile a non-exsistent/made up filename

This is my VERY FIRST Makefile and so I have cut and paste junk I have found all over the web. My directory structure is pretty flat and was not thought out for Makefiles. It is:
Project/
Project/Control
Project/NodeMgmt
Project/Common
Project/Interfaces
I am writing a Makefile for Control and would like it to standalone inside Control. It needs to include compile and include from Common & Interfaces. Here's my Makefile:
CC = g++
CFLAGS = -Wall -c
INCLUDES = -I/usr/local/include -I/SuperCool/Ion-1.0.0-snapshot-1/include -I/SuperCool/FastrakSDK-4.0.1-snapshot-1/include/Fastrak/Engine/Core/CoreIpc -I/Projects/Common -I/Projects/Interfaces -I/Projects/NodeMgmt -I/Projects/Controller
LFLAGS = -L/usr/local/lib -L/SuperCool/FastrakSDK-4.0.1-snapshot-1/lib
LIBS = -lCoreIpc4 -lIonOs
VPATH = ../Interfaces/
VPATH = ../Common/
VPATH = ../NodeMgmt/
SRCS = *.cc
OBJS = $(SRCS:.cc=.o)
MAIN = controller
.PHONY: clean
all: $(MAIN)
#echo Built Controller
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS) $(LFLAGS) $(LIBS)
.cc.o:
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
clean:
$(RM) *.o $(MAIN)
It's compiling the first .cc file it finds "-c Controller.cc -o *.o" which make sense but that's all it's compiling and I get a *.o output file, not a Controller.o file. It does not compile any other files.
Here's one problem:
SRCS = *.cc
Make doesn't understand wildcards without the wildcard function:
SRCS = $(wildcard *.cc)
That should get it working; we can make minor improvements later.

Resources