Trouble compiling/linking C and C++ files - c++

I have tried searching around other questions here on SO, but have still been unable to get my newly created C++ and .h linked to my main C file correctly. My implementation of my loader.cpp and loader.h are based off of this SO question.
My loader.cpp has no main function as I just want to use the C++ functions there. My shift.c file is where my int main() is located. Here is the basic structure of my loader.cpp file.
loader.cpp
#include "loader.h"
...
// Class Declaration
...
// Class implementation
I have been trying to compile with the following.
g++ loader.cpp -o obj -lGLU -lGL -lglut
The error I am getting here is...
(.text+0x20): undefined reference `to main'
So my two questions are, how do I get my cpp file to compile properly, and then what do I need to add to my Makefile to link them properly?
Makefile (for reference)
CC = gcc
CXX = g++
EXE = shift gears
# Main target
all: $(EXE)
CFLG=-O3 -Wall
LIBS=-lglut -lGLU -lGL -lm
CLEAN=rm -f $(EXE) *.o *.a
# Dependencies
gears.o: gears.c
shift.o: shift.c CSCIx229.h
fatal.o: fatal.c CSCIx229.h
loadtexbmp.o: loadtexbmp.c CSCIx229.h
print.o: print.c CSCIx229.h
project.o: project.c CSCIx229.h
errcheck.o: errcheck.c CSCIx229.h
object.o: object.c CSCIx229.h
# Create archive
CSCIx229.a:fatal.o loadtexbmp.o print.o project.o errcheck.o object.o
ar -rcs $# $^
# Compile rules
.c.o:
gcc -c $(CFLG) $<
.cpp.o:
g++ -c $(CFLG) $<
# Link
shift:shift.o CSCIx229.a
gcc -O3 -o $# $^ $(LIBS)
gears:gears.o
gcc -O3 -o $# $^ $(LIBS)
# Clean
clean:
$(CLEAN)

If you want g++ to compile an object module without linking it into a complete program then you must give it the -c option:
g++ -c loader.cpp -o loader.o
Note that that compilation command also assigns a conventional name to the generated object file, and that if you're not linking it into an executable then you don't need to specify libraries to link it to. Your Makefile is already set up for this.
If you add loader.o to the dependencies of CSCIx229.a then that should be enough to persuade make to build it from loader.cpp and to include the object file in your library (which will make it available for linking into your executables). You may also need to add some or all of -lGLU -lGL -lglut to your LIBS variable. It might also be appropriate to add loader.o's dependencies to the makefile if they include more than just loader.cpp itself (e.g. if they include CSCIx229.h).

Add the -c option to compile only. When you are ready to link the final application, then include all the object files and the list of libraries.
g++ -c loader.cpp -o loader.o
g++ loader.o (and the rest of your object files) -lGLU -lGL -lglut
Try adding this to your makefile:
shift:shift.o CSCIx229.a loader.o
gcc -O3 -o $# $^ $(LIBS)

Related

makefile : How to link object files

I have makefile and I need to link two objects into "main" object
They are -> oglinet.o and libshape.o
their path in system -> home/pi/openvg/
Problem :I need to write full path and objects name(home/pi/openvg/libshapes.o) is possible to "make" them as Makefile variable for example home/pi/openvg/libshape.o into $(OBJ1) in makefile rule ?
Tried to make them as variable for example Obj1= /home/pi/openvg/oglinit.o
if I compile that the compilator freeks out.
Working Makefile
#NOT IDEAL MAKEFILE BUT WORKING!!!!!
INCLUDEFLAGS = -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads -I/home/pi/openvg
LIBFLAGS = -L/opt/vc/lib -lbrcmEGL -lbrcmGLESv2 -lbcm_host -lpthread -ljpeg
main:main.cpp
g++ -Wall $(INCLUDEFLAGS) -o main main.cpp $(LIBFLAGS) home/pi/openvg/libshapes.o /home/pi/openvg/oglinit.o
Expectations:
what libshape.o and oglinit.o objects and thei path in system are "stored" in some kind of variable/variables
and if I need I can easily make changes in makefile /
After help of Chriss Dodd (not ideal?) makefile looks like this
INCLUDEFLAGS = -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads -I/home/pi/openvg
LIBFLAGS = -L/opt/vc/lib -lbrcmEGL -lbrcmGLESv2 -lbcm_host -lpthread -ljpeg
OPENVG=/home/pi/openvg
App: main.cpp $(OPENVG)/libshapes.o $(OPENVG)/oglinit.o
g++ -Wall -o $# $^ $(LIBFLAGS) $(INCLUDEFLAGS)
You usually want to make all the object files you're linking dependencies of the target. Then you can just use $^. You also usually want all the libraries after all the object files on the linker command line. With both of those you end up with something like:
OPENVG=/home/pi/openvg
main: main.o $(OPENVG)/libshape.o $(OPENVG)/objinit.o
g++ -Wall -o $# $^ $(LIBFLAGS)

Undefined reference to function when using shared library in Linux

I have some problems to use a custom shared library, since I get undefined reference errors for some functions from two of many other source files.
If I compile the whole project with main file (release:), everything works just fine. But if I create a shared library (lib:) and use this library with the main file (all:), those compile time errors occur.
Here is a snippet of my makefile
release:
$(CC) -Wall -s -w $(INCLUDES) $(LIBRARY) $(SRC) mainfile.cpp $(OCV) $(BOOST) $(GLOG) $(GFLAGS) -o test.exe
lib:
$(CC) -fPIC $(INCLUDES) $(LIBRARY) -c $(SRC) $(OCV) $(BOOST) $(GLOG) $(GFLAGS)
mv *.o obj/
$(CC) -shared -o libOutput.so obj/*.o
all:
$(CC) -Wall -s -w $(INCLUDES) $(LIBRARY) mainfile.cpp -L/path/to/lib/ -lOutput $(OCV) $(BOOST) $(GLOG) $(GFLAGS) -o project.exe
Since there is no error during compilation using the release-option, I'm assuming that there is a linker specific problem.
I inspected the specific object files using GNU Binary Utilities
nm -C obj/specific.o | grep functionName
with no results. I did the same for the shared library, but this time with the following result,
U functionName(std::vector<int>)
which means that the function is unknown.
Do you have any suggestions, how to fix this issue?

makefile linking does not work (although no error message)

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

GCC Shared Library Problems

I'm trying to create a shared library on ubuntu using gcc
I just have one simple class(shared.h and shared.cpp) and one client to use it (main.cpp)
This is my makefile and I'm still not able to to get the program to compile.
all:
#compile object(fPIC: creates position independent code)
gcc -fPIC -Wall -g -c shared.cpp
#compile shared library
gcc -shared -Wl,-soname,libshared.so.1 -o libshared.so.1.0.1 shared.o -lc
#link shared library
gcc -g -o main main.cpp -L. -lshared
I'm confident the first line is correct
I am unsure what "-lc" does. I think it passes something to the linker?
I don't want to install the library, I just want to be able to link it from the current directory. I have tried: export LD_LIBRARY_PATH=.
but it does not seem to make a difference. Everything is in the current directory.
ERROR: /usr/bin/ld: cannot find -lshared
how do I get the compiler to check the current directory for my library?
The problem is not that it's not looking in the directory, the problem is that you've named the library "libshared.so.1.0.1". When you use -lshared, it's looking for a file named 'libshared.so' or 'libshared.a' in the library search path.
Most of the time, when using versioned system libraries, you'll provide a link to the latest one as 'libshared.so', even if you have installed 'libshared.so.1' or 'libshared.so.1.0.1'.
In your case, if you continue to leave the file named 'libshared.so.1.0.1', you'll want to create 2 symbolic links:
libshared.so - So that the library can be found using ld
libshared.so.1 - Since you declared the SO name as libshared.so.1 when building it, you need to provide this link, otherwise, the executable will not be able to find the proper shared library at runtime.
You don't write any dependencies, which is the purpose of Makefile-s. And you probably need to force the run path Perhaps something like
.PHONY: all clean
CXX=g++
CXXFLAGS=-g -Wall
all: main
main: main.o libshared.so
$(LINK.cpp) -o $# $< -Wl,-rpath,. -L. -lshared
libshared.so: shared.pic.o
$(LINK.cpp) -shared -o $^ $<
main.o: main.cc shared.hh
%.pic.o: %.cc
$(CXX) $(CXXFLAGS) -fPIC -c -o $# $<
#
clean:
rm -f *.o *.so main *~

writing a cygwin makefile for ubuntu

I am trying to compile the open-source AAM-library. I have tried in Visual Studio, and although it compiled, it had a run-time error. Now I'm trying to compile it in Ubuntu 11.04 using G++. The only makefile provided is a cygwin makefile. I am trying to use this to compile in Ubuntu. (I have included the makefile below). The problem I am having is near the bottom in the lines:
libaamlibrary.dll.a: $(OBJS)
g++ -fPIC -shared $(OBJS) $(LIBS) -o cygaamlibrary-2.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker libaamlibrary.dll.a
"--enable-auto-image-base" is not a recognised option. I am trying to rewrite these 3 lines to a form that does the same thing but works in Ubuntu, but I am struggling, because I don't really understand what the lines are doing (e.g., I don't understand Xlinker and how it should be used). Any advice would be much appreciated... Here is the full makefile for reference:
CPPFLAGS = -I. -I/home/andrew/MscProject/OpenCV-2.3.0/include/opencv -O2 -Wall -g -MD -fPIC
PROGRAMS = libaamlibrary.dll.a libaamlibrary.a fit build
LIBS = -L/usr/local/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_flann
OBJS = AAM_Util.o VJfacedetect.o AAM_Shape.o AAM_CAM.o AAM_PAW.o AAM_PDM.o AAM_TDM.o AAM_MovieAVI.o AAM_Basic.o AAM_IC.o
all: $(PROGRAMS)
AAM_Util.o: AAM_Util.cpp AAM_Util.h
g++ $(CPPFLAGS) -c -o AAM_Util.o AAM_Util.cpp
AAM_Shape.o: AAM_Shape.cpp AAM_Shape.h
g++ $(CPPFLAGS) -c -o AAM_Shape.o AAM_Shape.cpp
AAM_TDM.o: AAM_TDM.cpp AAM_TDM.h
g++ $(CPPFLAGS) -c -o AAM_TDM.o AAM_TDM.cpp
AAM_PDM.o: AAM_PDM.cpp AAM_PDM.h
g++ $(CPPFLAGS) -c -o AAM_PDM.o AAM_PDM.cpp
AAM_PAW.o: AAM_PAW.cpp AAM_PAW.h
g++ $(CPPFLAGS) -c -o AAM_PAW.o AAM_PAW.cpp
AAM_CAM.o: AAM_CAM.cpp AAM_CAM.h
g++ $(CPPFLAGS) -c -o AAM_CAM.o AAM_CAM.cpp
VJfacedetect.o: VJfacedetect.cpp VJfacedetect.h
g++ $(CPPFLAGS) -c -o VJfacedetect.o VJfacedetect.cpp
AAM_MovieAVI.o: AAM_MovieAVI.cpp AAM_MovieAVI.h
g++ $(CPPFLAGS) -c -o AAM_MovieAVI.o AAM_MovieAVI.cpp
AAM_Basic.o: AAM_Basic.cpp AAM_Basic.h
g++ $(CPPFLAGS) -c -o AAM_Basic.o AAM_Basic.cpp
AAM_IC.o: AAM_IC.cpp AAM_IC.h
g++ $(CPPFLAGS) -c -o AAM_IC.o AAM_IC.cpp
demo_build.o: train.cpp
g++ $(CPPFLAGS) -c -o demo_build.o train.cpp
demo_fit.o: fit.cpp
g++ $(CPPFLAGS) -c -o demo_fit.o fit.cpp
libaamlibrary.a: $(OBJS)
ar cru libaamlibrary.a $(OBJS)
ranlib libaamlibrary.a
libaamlibrary.dll.a: $(OBJS)
g++ -fPIC -shared $(OBJS) $(LIBS) -o cygaamlibrary-2.dll -Wl,--enable-auto-image-base -Xlinker --out-implib -Xlinker libaamlibrary.dll.a
fit: demo_fit.o
g++ -o fit demo_fit.o libaamlibrary.dll.a $(LIBS)
build: demo_build.o
g++ -o build demo_build.o libaamlibrary.dll.a $(LIBS)
clean:
rm -f *.o $(PROGRAMS)
I agree that you should not use a .dll.a or .dll extension (I believe .a and .so are appropriate), but it seems you can't do without libaamlibrary[.dll].a.
Since '--enable-auto-image-base' is prefixed with -Wl, this makes it a linker (ld) option.
I searched 'man ld' and came up with this:
--enable-auto-image-base
Automatically choose the image base for DLLs, unless one is
specified using the "--image-base" argument. By using a hash
generated from the dllname to create unique image bases for each
DLL, in-memory collisions and relocations which can delay program
execution are avoided. [This option is specific to the i386 PE
targeted port of the linker]
What is your platform? It is not available to non i386 architectures as I understand, and maybe not needed? So can you try compiling without it?
By the way I recommend using the excellent Autotools package (automake/autoconf/libtool).
Regarding --out-implib it is also not available on amd64.
--out-implib file
The linker will create the file file which will contain an import
lib corresponding to the DLL the linker is generating. This import
lib (which should be called ".dll.a" or ".a" may be used to link
clients against the generated DLL; this behaviour makes it possible
to skip a separate "dlltool" import library creation step. [This
option is specific to the i386 PE targeted port of the linker]
Sorry but I don't know what an import lib is.
Practical approach: first try building without all the .dll and .dll.a stuff; just remove the lines that refer to such targets.
It seems .dll.a files are static archives containing position-independent code (PIC), which are necessary in advanced linking scenarios, i.e. if you're developing shared libraries yourself. (Even if you want such a thing, you shouldn't call it .dll.a on Linux.)