makefile linking does not work (although no error message) - c++

I am having issue with Makefile that I produced. It consists of one .cpp file with main() inside and I want to create executable from it. While putting in terminal make command I get following:
g++ STutorial.o -o MyExecutable
g++: error: STutorial.o: No such file or directory
g++: fatal error: no input files
While putting first make STutorial.o (.o created) and then make get this:
g++ STutorial.o -o MyExecutable
STutorial.o: In function `main':
STutorial.cpp:(.text+0x47a): undefined reference to `alcOpenDevice'
Firstly, why make does not go from the beginning?
Secondly, why this reference is undefined as if I did not include library, I did that in Makefile aswell as in STutorial.cpp file.
Can you please help me out? I was reading up what could I do wrong and see no clue. (I am beginner and maybe mistake is a rookie one, I apologise in advance but cannot understand it alone)
Makefile:
FLAGS += -std=c++11
CCX=g++
FLAGS +=-c -Wall #for compilation, for warning
FLAGS += -lopenal -lSDL
all: MyExecutable
MyExecutable:
$(CXX) STutorial.o -o MyExecutable
STutorial.o: STutorial.cpp
$(CXX) $(FLAGS) STutorial.cpp

Your makefile should be like this:
CCX=g++
FLAGS +=-c -Wall #for compilation, for warning
LINK_FLAGS += -lopenal -lSDL
all: MyExecutable
MyExecutable: Stutorial.o
$(CXX) STutorial.o -o MyExecutable $(LINK_FLAGS)
STutorial.o: STutorial.cpp
$(CXX) $(FLAGS) STutorial.cpp
Explanation:
Your MyExecutable depends on Stutorial.o which inturn depends on Stutorial.cpp
Now -c flag should be used only with .cpp file to create an object file and not with already created .o file.
Therefore you should have two flags: FLAGS for compiling and LINK_FLAGS for linking libraries during making executable file.

Your executable rule is the issue:
MyExecutable:
$(CXX) STutorial.o -o MyExecutable
It has a target (MyExecutable) and it has a recipe ($(CXX) ...), that all looks good. But what are its prerequisites? MyExecutable does have prerequisites - it needs STutorial.o in order to generate the binary! You need to explicitly tell make about this:
MyExecutable: STutorial.o
$(CXX) STutorial.o -o MyExecutable
Otherwise, you are telling make that you want to build all. all depends on MyExecutable. MyExecutable doesn't depend on anything, so the rule for STutorial.o never gets run.
As for the linker error, you're not linking in the library you need, so you should define something like:
LFLAGS += -lopenal -lSDL
MyExecutable: STutorial.o
$(CXX) STutorial.o $(LFLAGS) -o MyExecutable

You have a few problem in your Makefile starting with:
FLAGS +=-c -Wall #for compilation, for warning
FLAGS += -lopenal -lSDL
You are redefining the FLAGS variable here.
So what you should have is a different variable for your compiler and linker flags:
CFLAGS +=-c -Wall #for compilation, for warning
LDFLAGS += -lopenal -lSDL
Now, for the sake of giving a complete answer, and not solving your immediate problem only I'll try to show how to make the Makefile more flexible:
Start with the sources - you should have a variable for them as well; it's useful when adding/removing source files to/from the project:
SOURCES = STutorial.cpp
define a variable for your object files (this will come in handy at link-time):
OBJ = $(SOURCES:.cpp=.o)
Compile all source files into object files:
.cpp.o:
$(C++) $(CFLAGS) -o $# $<
Link your binary file using the compiled object files:
$(MyExecutable): $(OBJ)
$(C++) $(LDFLAGS) $(OBJ) -o $#
Add a clean command for completeness (removes the binary and object files):
clean:
$(RM) $(EXECUTABLE) $(OBJ)
Now, putting it all together:
CCX=g++
CFLAGS +=-c -Wall -std=c++11#for compilation, for warning
LDFLAGS += -lopenal -lSDL
SOURCES = STutorial.cpp
OBJ = $(SOURCES:.cpp=.o)
all: $(MyExecutable)
$(MyExecutable): $(OBJ)
$(CCX) $(LDFLAGS) $(OBJ) -o $#
.cpp.o:
$(CCx) $(CFLAGS) -o $# $<
clean:
$(RM) $(EXECUTABLE) $(OBJ)
This should allow you to flexibly build, rebuild, clean you project.

This is how you should do:
g++ -std=c++11 -Wall -lopenal -lSDL STutorial.cpp -o MyExecutable

Related

SFML library doesn't link with makefile compilation

I have been trying to link the SFML dlls to my windows C++ project, but I can't get it to work. I always end up with:
fatal error: SFML/System.hpp: No such file or directory
I've tried a bunch of things but nothing changes the issue.
Here is my makefile:
PROGRAM = zero_flip
OBJS = src/main.o src/Math.o src/card.o src/game_board.o src/indicator.o src/ui.o
CXX = g++
CXX_FLAGS = -O0 -g -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable
LIB_DIRS = -L./Resources/libs/
LIBS = -lsfml-system -lsfml-graphics -lsfml-window -lsfml-audio
LNK_FLAGS = $(LIB_DIRS) $(LIBS)
DEPS=$(OBJS:.o=.d)
.PHONY: all clean
all: $(PROGRAM)
-include $(DEPS)
%.o: %.cpp
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $< -o $#
$(PROGRAM): $(OBJS)
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $^ -o $#
clean:
rm -f $(OBJS) $(DEPS) $(PROGRAM) && clear
The "./Resources/libs/" directory contains:
openal32.dll
sfml-audio-2.dll
sfml-audio-d-2.dll
sfml-graphics-2.dll
sfml-graphics-d-2.dll
sfml-system-2.dll
sfml-system-d-2.dll
sfml-window-2.dll
sfml-window-d-2.dll
Can anyone get me unstuck please this is driving me mad.
This is wrong:
%.o: %.cpp
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $< -o $#
This rule says it will compile a source file into an object file, but the recipe actually builds a complete executable: it will compile the source file like xxx.cpp then link it into a program named xxx.o. You need to invoke just the compiler here, not the linker, so you should not have $(LNK_FLAGS) and you need to add the -c option to tell the compiler to stop after compiling and not link.
Then you need to add an -I option to the compile line telling the compiler where to find the header files needed during compilation... in this case SFML/System.hpp.

Makefile not giving the expected compilation results

I am quite new to Make. I am attempting to write a Makefile to build a medium-sized Linux C/C++ application as below.
Making a simple Makefile by having all source files in one location and explicitly listing the source files works ok for me but I would like it to be more generic.
I have all my source files (C and C++) in the src folder in different subdirectories. I have header files inside an inc and inc/common folder, and then libs inside a lib folder.
The Makefile is run on the same level :
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
CXX := /bin/arm-linux-gnueabi-g++
EXE := $(BIN_DIR)/runfile
SRC := $(shell find $(SRC_DIR) -name *.cpp -or -name *.c)
OBJ := $(patsubst $(SRC_DIR)/%,$(OBJ_DIR)/%,$(addsuffix .o,$(basename $(SRC))))
CPPFLAGS := -Iinc -Iinc/common -MMD -MP
CXXFLAGS := -std=c++11 -Wall
LDFLAGS := -Llib
LDLIBS :=
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
I get lots of errors such as below when I run it, including problems opening dependency files. I think i'm almost there, but can't see my error exactly :
compilation terminated.
/bin/arm-linux-gnueabi-g++ -Iinc -Iinc/common -MMD -MP -std=c++11 -Wall -c -o obj/main.d.o
cc -Llib obj/main.d.o -o obj/main.d
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: relocations in generic ELF (EM: 40)
/usr/bin/ld: obj/main.d.o: error adding symbols: file in wrong format
I don't see how the output you show can be generated from the makefile you show here but anyway.
This is not right:
$(OBJ_DIR)/%.o: $(SRC) | $(OBJ_DIR)
A pattern rule is a template that tells make "if you want to build a target that matches this pattern, then you can build it from the prerequisites that match this pattern".
Here you are listing ALL your source files as a prerequisite for EVERY object file. Suppose SRC is set to foo.c bar.c biz.c baz.c, then this expands to:
obj/%.o : foo.c bar.c biz.c baz.c | obj
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
You're telling make that every single .o target depends on ALL the source files, not just the one for that object file. Further, the automatic variable $< always expands to the first prerequisite, which here will always be foo.c. So, you're compiling foo.c four times, creating each of the object files.
The very first important rule when debugging makefiles is to look carefully at the output (command lines) that make prints. If they are not right, then your makefile is not right. If you do that you'll see all the compile lines are compiling the same source, like:
g++ -c foo.c -o obj/foo.o
g++ -c foo.c -o obj/bar.o
g++ -c foo.c -o obj/biz.o
g++ -c foo.c -o obj/baz.o
That clearly cannot work and it's why you get link errors trying to link together all these object files: they all have the same content.
You need this:
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
which tells make how to build an object file from a single source file.
You also need to create the actual output directory that the object file will go into. Just creating $(OBJ_DIR) is not enough, if the object file appears in a subdirectory.

Makefile missing include path Although the path exists and defined

i have make file which i try to make them generic
but it keeps to compline it missing include directory
this is the makefile :
CXX=g++
CPPFAGS= -Wall -O0 -g -std=c++14
INCLUDES = -I/home/vagrant/libuv/include -Isrc
LIBS_DIRS = -L/home/vagrant/libuv/build
LDFLAGS= -lssl -lcrypto
LIB_STATIC = -Wl,--no-as-needed -Bstatic -luv_a -ldl -lpthread
SOURCE = $(wildcard echo.cpp) \
$(wildcard src/*.cpp)
OBJ = $(SOURCE:.cpp=.o)
DEP = $(OBJ:.o=.d)
TARGET = myproj
$(TARGET) : $(OBJ)
$(CXX) $(CPPFLAGS) $(INCLUDES) -o $# $^ $(LIBS_DIRS) $(LDFLAGS) $(LIB_STATIC)
all: $(TARGET)
clean:
rm -f $(OBJ) $(TARGET)
cleandep:
rm -f $(DEP)
.PHONY:all clean cleandep
when i make : make -n :
make -n
g++ -c -o echo.o echo.cpp
g++ -c -o src/base64.o src/base64.cpp
g++ -c -o src/Server.o src/Server.cpp
g++ -c -o src/sha1.o src/sha1.cpp
g++ -c -o src/Client.o src/Client.cpp
g++ -I/home/vagrant/libuv/include -Isrc -o myproj echo.o src/base64.o src/Server.o src/sha1.o src/Client.o -L/home/vagrant/libuv/build -lssl -lcrypto -Wl,--no-as-needed -Bstatic -luv_a -ldl -lpthread
when i invoke make , im getting this error:
make
g++ -c -o echo.o echo.cpp
In file included from src/Server.h:9:0,
from echo.cpp:1:
src/Client.h:6:10: fatal error: uv.h: No such file or directory
#include <uv.h>
^~~~~~
compilation terminated.
make: *** [echo.o] Error 1
but the uv do exist in : /home/vagrant/libuv/include
You have no rule to build your object files: you've only defined a rule to link your object files into a final executable. As mentioned in the comments, adding $(INCLUDES) into that recipe is useless because header file directories are only used during compiling (creating object files) not linking (converting object files and libraries into executables).
Because you haven't defined your own rule to build object files, you're using make's built-in rule. But make's built-in rule doesn't know anything about a variable named INCLUDES, so that variable is not used during compilation. You can easily see this by looking at the compiler commands generated by make.
You need to either (a) create your own rule for compiling object files that uses your personal make variables, or (b) use the normal built-in variables that make expects to be used with its built-in rules.
For (b), as described in the manual, you should take your current CPPFAGS [sic] variable and rename it to CXXFLAGS, take your current INCLUDES variable and rename it CPPFLAGS, take your current LIBS_DIRS variable and rename it LDFLAGS, and take your current LDFLAGS variable and rename it to LDLIBS.
Also just to note, you have DEPS etc. but there is nothing in your makefile that does anything with them or to create them so they're useless.

Confused how my Makefile is remaking object files

My make file is failing to find my include directory when it tries to remake object files. For example, when I call make tests I get the output:
g++ -c -o sdl_class.o sdl_class.cpp
sdl_class.cpp:9:23: fatal error: sdl_class.h: No such file or directory
#include <sdl_class.h>
^
compilation terminated.
make: *** [sdl_class.o] Error 1
My Makefile is this:
#Originally from: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
#But will be heavily modified
IDIR =../include
CC=g++
CFLAGS=-w -I$(IDIR)
#ODIR=obj
LDIR =../lib
LIBS=-lSDL2
_DEPS = sdl_class.h SDL_image.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
OBJ = sdl_class.o tests.o
#OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
%.o: %.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS) $(LIBS)
tests: sdl_class.o tests.o
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f *.o *~ core $(IDIR)/*~
My understanding is that when I call make tests, that it should attempt to remake the sdl_class.o file. This should then call the %.o rule, which should try to make the object file by calling something like:
g++ -c -o sdl_class.o sdl_class.cpp -w -I../include -lSDL2
However, this is not the case as it looks like it is calling $(CC) -c -o $# $< $(CFLAGS) $(LIBS), as you can see from above.
Do I have a fundamental misunderstanding about how make builds its rules? Seems likely, this is my first Makefile. Perhaps I am confused on how compilation works in general, as I'm somewhat new to that as well.
I would say that the problem is that one or more of the files ../include/sdl_class.h or ../include/SDL_image.h does not exist. Because of that, make is deciding that your pattern rule does not match (because not all the prerequisites can be found or made) and it defaults to the built-in rule to create object files from .cpp files.
The built-in rules use the make variables CXX for the C++ compiler and CXXFLAGS for the C++ flags: the CC and CFLAGS variables are used for the C compiler. That's why your settings for CFLAGS are being ignored.
If you run make -d sdl_class.o you'll see which file make is looking for and why it decides to not use your pattern rule.
If you rewrite your rules like this it will work better:
%.o: %.cpp
$(CC) -c -o $# $< $(CFLAGS)
sdl_class.o tests.o: $(DEPS)
because make will now complain that the relevant files can't be found or created.
There are other issues, of course. You shouldn't be passing $(LIBS) to your compile command; that belongs only in your link line. And, you should probably stick to the standard variables CXX for the C++ compiler, CPPFLAGS for preprocessor flags like -I and -D, and CXXFLAGS for C++ compiler flags. Also, linker library flags like -L../lib go in LDFLAGS and linker libraries like -lSDL2 go in LDLIBS.
CC/CCFLAGS are for C compilation. You should use CXX and CXXFLAGS for C++. They are used in built-in rules and in the LINK.cc macro, making the Makefile much simpler, and thus less error prone.
CXXFLAGS = -Wall ...
prog : foo.o bar.o
$(LINK.cc) -o $# $^
see Default linker setting in Makefile for linking C++ object files

How to link multiple .so files in a C++ Makefile

My Makefile looks as follows:
CXX = g++
CXXFLAGS = -g
INCLUDES = -Iinclude/
OBJS = a1.o \
b1.o
LIBPATH= /usr/lib/<arch>
test-app:$(OBJS)
$(CXX) -o $# $(OBJS)
%.o : %.cpp
$(CXX) $(INCLUDES) -c $(CXXFLAGS) $< -o $#
I want to link two files lib1.so and lib2.so present in LIBPATH? Can anyone please help me with the syntax?
The syntax is
test-app:$(OBJS)
$(CXX) -o $# $(OBJS) -Lpath_to_your_lib -lyour_libname
Also you should use pkg-config to find those variables value.
Try this one:
LIBRARIES= -llib1 -llib2
...
test-app:$(OBJS)
$(CXX) -o $# -L$(LIBPATH) $(LIBRARIES) $(OBJS)
Consider that the arguments order are most of times important since the gcc compiler/linker process the files just one time in the given order and if the order was wrong errors like "Symbol not find" and "undefined reference" will be produced.
Though, I strongly recommend CMake since it's syntax is so easier, more dynamic and It supports many build platforms (IDEs, Compilers, Makefiles, etc.)
Update:
This configuration is likely more effective than the above:
SHARED_LIBRARIES= -L/path/to/shared_libs -llib1 -llib2
STATIC_LIBRARIES= -L/path/to/static_libs -llib1 -llib2 -L/another/path/to/static_libs -llib3
...
test-app:$(OBJS)
$(CXX) -o $# $(STATIC_LIBRARIES) $(SHARED_LIBRARIES) $(OBJS)