Makefile problems with gcc flags (file not recognized; shared libraries) - gcc

I'm a little confused now. I'm trying to get the Makefile work but it breaks. I Hope someone can help me with this bad and frustrating time-killer.
I've written a small and lightweight part of a Compiler.
The project has the following structure:
/Compiler.cpp
/Makefile
/Buffer/
/Buffer/Makefile
/Scanner/
/Scanner/Makefile
/SymTable/
/SymTable/Makefile
When I'm compiling Buffer, Scanner and SymTable manual (changing the directory and typing 'make mode=release' it's no problem and each shared-library is compiled). But when I run the Makefile from within where the 'Master Makefile' /Makefile is, it fails and the terminal prints something like:
Buffer/libBuffer.so: file not recognized: File format not recognized
collect2: ld returned 1 exit status
make: \*** [Compiler] Error 1
Here is the listing of the Makefile of /Buffer/Makefile (the same for Scanner and SymTable):
CXX = g++
ifeq ($(mode),release)
CXXFLAGS = -g -fPIC -O3 -ffunction-sections -march=native
else
mode = debug
CXXFLAGS = -g3
endif
MODUL = Buffer
COMPONENTS = Buffer.h
MK_LIBRARY = lib$(MODUL).so
all: $(MK_LIBRARY)
$(MK_LIBRARY): $(COMPONENTS)
$(CXX) $(CXXFLAGS) -shared -o $# $^
clean:
rm -f $(MK_LIBRARY)
.PHONY: all
.PHONY: clean
The 'Master Makefile' looks like:
CXX = g++
ifeq ($(mode),release)
CXXFLAGS = -g -O3 -ffunction-sections -fwhole-program -march=native
else
mode = debug
CXXFLAGS = -g3
endif
TARGET = Compiler
COMPONENTS = $(TARGET)
DIRS = Buffer Scanner SymTable
MAKE = make
MFLAGS = mode=$(mode)
all: $(COMPONENTS)
$(TARGET): Compiler.cpp libBuffer.so libScanner.so libSymTable.so
$(CXX) $(CXXFLAGS) -IBuffer -IScanner -ISymTable \
-LBuffer -LScanner -LSymTable \
-lBuffer -lScanner -lSymTable -o $# Compiler.cpp
libBuffer.so: force_look
cd Buffer; $(MAKE) $(MFLAGS)
libScanner.so: force_look
cd Scanner; $(MAKE) $(MFLAGS)
libSymTable.so: force_look
cd SymTable; $(MAKE) $(MFLAGS)
clean:
rm -f $(COMPONENTS)
#for d in $(DIRS); do (cd $$d; $(MAKE) clean ); done
check:
#for d in $(DIRS); do (cd $$d; $(MAKE) check ); done
force_look:
true
.PHONY: all
.PHONY: clean
.PHONY: check
I hope some has an answer for me! Thanks!

There's something very weird about this part:
MODUL = Buffer
COMPONENTS = Buffer.h
MK_LIBRARY = lib$(MODUL).so
$(MK_LIBRARY): $(COMPONENTS)
$(CXX) $(CXXFLAGS) -shared -o $# $^
This rule tries to build libBuffer.so out of Buffer.h, the header file. How can this possibly work, without the definitions of the things in Buffer.cc? I would do it this way:
lib%.so: %.o
$(CXX) $(CXXFLAGS) -shared -o $# $^
EDIT:
You have the definitions of Buffer in Buffer.h? All right, you have more than one problem, and the only way to solve them is to do what almost always works: retreat to a simpler problem and solve that first. Can you make Buffer.o? And can you then link that into your executable (bypassing libBuffer.so)? And if not, can you write a "HelloWorld" in Buffer/, and link Buffer.o into that?

Related

Make object file not being created

I am trying to write a Makefile since it's a good skill to have and all the times I've worked with them it all just seems like black magic to me.
The Makefile is shall mix C source and unit test in C++. I've looked at some examples and tried reading some guides but I am not getting it to work properly and most examples seems quite simple and doesn't really do what I would like to do.
This is the folder structure:
project
src
inc
unit_test
out
Here is my Makefile so far.
CXX = g++
CXXFLAGS = -g -c -I$(INC_DIR)
CC = gcc
CFLAGS = -g -c -Wall -Wextra -Wpedantic -I$(INC_DIR)
LIBS = -lcppunit
OUT_DIR = out
INC_DIR = inc
CPP_SRCS = $(wildcard unit_test/*.cpp)
CPP_OBJS = $(CPP_SRCS:unit_test/%.cpp=$(OUT_DIR)/%.o)
C_SRCS = $(wildcard src/*.c)
C_OBJS = $(C_SRCS:src/%.c=$(OUTDIR)/%.o)
BIN = $(OUT_DIR)/a.out
.PHONY: all run build clean
test:
#echo C_SRCS $(C_SRCS)
#echo C_OBJS $(C_OBJS)
#echo CPP_SRCS $(CPP_SRCS)
#echo CPP_OBJS $(CPP_OBJS)
all: run
run: build
./$(BIN)
build: $(BIN)
clean:
rm -f $(CPP_OBJS)
rm -f $(C_OBJS)
rm -f $(BIN)
$(BIN): $(C_OBJS) $(CPP_OBJS)
$(CXX) $(C_OBJS) $(CPP_OBJS) -o $# $(LIBS)
#echo "Build successful!"
$(CPP_OBJS): $(OUT_DIR)/%.o: unit_test/%.cpp
mkdir -p $(OUT_DIR)
#echo Compiling $<
$(CXX) $< $(CXXFLAGS) -o $#
$(C_OBJS): $(OUT_DIR)/%.o: src/%.c
#echo Compiling $<
$(CC) $< $(CFLAGS) -o $#
Here is the output of 'make test' which will describe my problem at this point in time.
C_SRCS src/add.c
C_OBJS /add.o
CPP_SRCS unit_test/Main.cpp unit_test/Tester.cpp
CPP_OBJS out/Main.o out/Tester.o
Why am I not getting the object file out/add.o when I am doing exactly the same for the the src folder as for the unit_test folder? What am I missing? It's not that obvious to me.

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)

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?

Makefile that rebuilds all if compiled with dif flags

So I am having a little bit of a tough time trying to figure out how to make my Makefile so that when I do make and it compiles a release version then later on do a make debug it compiles a debug version with the new -DDEBUG and -g set on gcc if the files have not been updated.
For example:
main.cpp is edited
run make
compiles main.cpp
run make debug
main.cpp is not recompiled because there were no changes even though the flags for compilation differ
Note I don't want to have to do a clean each time either because I dont want to have to recompile files if I do 2 makes in a row so setting clean as a dependency is not going to be a valid answer here
You may like to compile object files into a different directory depending on the build mode, e.g.:
# default mode, override with `make BUILD=release`
BUILD := debug
obj_dir := ${BUILD}
CFLAGS.debug := -g -O0
CFLAGS.release := -g -O3 -march=native -DNDEBUG
all : ${obj_dir}/test
# Example executable
${obj_dir}/test : ${obj_dir}/test.o
test.c :
echo "int main() { return 0; }" > $#
# Generic rules
${obj_dir} :
mkdir $#
${obj_dir}/%.o : %.c Makefile | ${obj_dir} # Also recompile when Makefile changes.
${CC} -c -o $# ${CPPFLAGS} ${CFLAGS} ${CFLAGS.${BUILD}} -MD -MP $<
${obj_dir}/% : Makefile | ${obj_dir} # Also re-link when Makefile changes.
${CC} -o $# ${LDFLAGS} $(filter-out Makefile,$^) ${LDLIBS}
clean :
rm -rf ${obj_dir}
-include $(wildcard ${obj_dir}/*.d)
${obj_dir}/*.d : ;
.PHONY: all clean
(Bonus feature: automatic dependency generation).
Usage:
[max#localhost:~/tmp] $ make
mkdir debug
echo "int main() { return 0; }" > test.c
cc -c -o debug/test.o -g -O0 -MD -MP test.c
cc -o debug/test debug/test.o
[max#localhost:~/tmp] $ make
make: Nothing to be done for 'all'.
[max#localhost:~/tmp] $ make BUILD=release
mkdir release
cc -c -o release/test.o -g -O3 -march=native -DNDEBUG -MD -MP test.c
cc -o release/test release/test.o
[max#localhost:~/tmp] $ make BUILD=release
make: Nothing to be done for 'all'.
First of all, you should not run make debug - that would mean, you want to build a different target (debug). But you don't, you want to build the same target, just with different options. That's what you do, you run a different option, a variable value
>make DEBUG=Y
When you run
>make
you also pass that variable really, just with the empty string as value.
Now, in order for this to work as you want in the Makefile, you would want to make it as if DEBUG was a prerequisite file, with recipes like this:
foobar.o: foobar.c DEBUG
gcc $(if $(DEBUG), -DDEBUG -g) -c $< -o $#
Of course, normally this won't work, because DEBUG is a variable, not a file. So you need a hack, that I call "dependable variables". It is basically a way to declare a variable to behave like a file. I describe this technique in one of my other answers:
How do I add a debug option to Makefile
I once did something like this, it looked like that (boiled down to the minimum):
EXE := a.out
SRC := $(wildcard *.c)
ifneq ($(MAKECMDGOALS),debug)
OBJ := $(SRC:.c=.o)
else
OBJ := $(SRC:.c=-d.o)
endif
.PHONY: all debug
all: $(EXE)
debug: CFLAGS += -g -DDEBUG
debug: $(EXE)
$(EXE): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
%.o %-d.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
The trick is to use two separate list of object files, and select one depending of the target.

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.

Resources