I am trying to cross-compile the mosquitto example program. At first I compiled the mosquitto example on Host PC, it worked well. The makefile is as following:
CFLAGS=-Wall -ggdb -I../../lib -I../../lib/cpp
LDFLAGS=-L../../lib ../../lib/cpp/libmosquittopp.so.1 ../../lib/libmosquitto.so.1
.PHONY: all clean
all : mqtt_temperature_conversion
mqtt_temperature_conversion : main.o temperature_conversion.o
${CXX} $^ -o $# ${LDFLAGS}
main.o : main.cpp
${CXX} -c $^ -o $# ${CFLAGS}
temperature_conversion.o : temperature_conversion.cpp
${CXX} -c $^ -o $# ${CFLAGS}
clean :
-rm -f *.o mqtt_temperature_conversion
Then I add the following lines to cross compile this program:
CXX=arm-unknown-linux-gnueabi-gcc
AR=arm-unknown-linux-gnueabi-ar
AS=arm-unknown-linux-gnueabi-as
LD=arm-unknown-linux-gnueabi-ld
RANLIB=arm-unknown-linux-gnueabi-ranlib
Then it gives a error message:
/home/Tools/tool_chain/bin/../lib/gcc/arm-unknown-linux-
gnueabi/5.4.0/../../../../arm-unknown-linux-gnueabi/bin/ld: main.o:
undefined reference to symbol '_ZdlPv##GLIBCXX_3.4'
/home/Tools/tool_chain/bin/../sysroot/usr/lib/libstdc++.so.6:
error adding symbols: DSO missing from command line
I am very confused. I googled for this error, but none of them seems to be relevant. Cause when I compiled with the host PC compiler, everything works. So it should not be a lib problem.
update:
So I could not figure out what happened, then I made a test project myself. The Makefile is as follows:(I ignored the cross tool chain variabl parts to save some place)
CFLAGS=-Wall -ggdb -I../../lib -I../../lib/cpp
LDFLAGS=-L../../lib ../../lib/cpp/libmosquittopp.so.1 ../../lib/libmosquitto.so.1
mqtt: main.o
${CXX} $^ -o $# ${LDFLAGS}
main.o: main.cpp
${CXX} -c $^ -o $# ${CFLAGS}
And it worked?! I flashed it to the board the executable seems to be correct.
Now I am more confused
LD=arm-unknown-linux-gnueabi-ld
Don't use ld directly, ever. You want to use g++ as the driver that calls your linker, otherwise you will have linker problems.
LD=$(CXX)
Related
I'm trying to get started with the mosquitto MQTT library (c++, raspberry pi). I think I have successfully installed all of the packages I need, and was able to build and execute the included "temperature_conversion" sample without errors. I do receive a bunch of warnings about deprecated functions, but I'm ignoring those as not part of the immediate problem.
Though not a complete newbie, I'm not well experienced with linux development tools and building/linking/MakeFiles. In trying to create my own stand-alone test based on the sample found here:
https://github.com/eclipse/mosquitto/tree/master/examples/temperature_conversion
Output when running 'make' (on my modified version): [edited to include change based on JDAllen's comment]
pi#raspberrypi:~/Documents/c/offgrid $ make
g++ main.o mqtt_manager.o -o offgrid -L/usr/local/lib/libmosquittopp.so.1 /usr/local/lib/libmosquitto.so.1
main.o: In function `main':
/home/pi/Documents/c/offgrid/main.cpp:8: undefined reference to `mosqpp::lib_init()'
/home/pi/Documents/c/offgrid/main.cpp:11: undefined reference to `mosqpp::mosquittopp::loop_forever(int, int)'
.
.
(Similar 'undefined reference' messages omitted for clarity)
.
.
collect2: error: ld returned 1 exit status
Makefile:11: recipe for target 'offgrid' failed
make: *** [offgrid] Error 1
My modified MakeFile: [edited to include change based on JDAllen's comment]
CFLAGS=-Wall -ggdb -I/usr/local/include
LDFLAGS=-L/usr/local/lib/libmosquittopp.so.1 /usr/local/lib/libmosquitto.so.1
.PHONY: all clean
all : offgrid
offgrid : main.o mqtt_manager.o
${CXX} $^ -o $# ${LDFLAGS}
main.o : main.cpp
${CXX} -c $^ -o $# ${CFLAGS}
mqtt_manager.o : mqtt_manager.cpp
${CXX} -c $^ -o $# ${CFLAGS}
clean :
-rm -f *.o offgrid
UNMODIFIED sample application's MakeFile:
CFLAGS=-Wall -ggdb -I../../lib -I../../lib/cpp
LDFLAGS=-L../../lib ../../lib/cpp/libmosquittopp.so.1 ../../lib/libmosquitto.so.1
.PHONY: all clean
all : mqtt_temperature_conversion
mqtt_temperature_conversion : main.o temperature_conversion.o
${CXX} $^ -o $# ${LDFLAGS}
main.o : main.cpp
${CXX} -c $^ -o $# ${CFLAGS}
temperature_conversion.o : temperature_conversion.cpp
${CXX} -c $^ -o $# ${CFLAGS}
clean :
-rm -f *.o mqtt_temperature_conversion
I have verified that /usr/local/include contains mosquittopp.h, and that /usr/local/lib contains libmosquittopp.so.1
Could someone please enlighten me on what I'm missing here? I'm pretty sure I could make it work by copying the /lib directory structure from the example, but I would like to use the ?installed? versions in /usr because that seems like the way one should go about such things.
[EDIT1: I have now verified that copying /lib from the example directory into my own and replacing the first two lines in the Makefile with paths relative to those directories does, indeed, allow my modified code to build without the aforementioned errors. I still want to be able to use the files in /usr/local/lib though - why doesn't this work? What further steps can I take to see where things are going wrong?]
If requested, I can update this with my modified code but unless I've done something stupid, it's a structurally equivalent pared down version of the original example linked above.
Well, I don't completely understand what's going on in the back-end, but I was able to figure out what works based another discussion with the same/similar problem here:
https://www.raspberrypi.org/forums/viewtopic.php?t=254740
In case the above link doesn't work, the following is an excerpt from that discussion:
If you are building some C code as a client you will need "-lmosquitto" at the end of the gcc command.
That says "use the library libmosquitto" which will resolve all those missing symbols.
Note that is a lower case "-l", the upper case "-L" indicates a library search path.
Use "-lmosquittopp" if you are building C++.
You will need to have installed the mosquitto client development library packages: libmosquitto-dev for C and/or libmosquittopp-dev for C++.
After a small amount of trial & error, I ended up with the following Makefile that appears to work just fine:
LDFLAGS=-lmosquittopp
.PHONY: all clean
all : offgrid
offgrid : main.o mqtt_manager.o
${CXX} $^ -o $# ${LDFLAGS}
main.o : main.cpp
${CXX} -c $^ -o $# ${CFLAGS}
mqtt_manager.o : mqtt_manager.cpp
${CXX} -c $^ -o $# ${CFLAGS}
clean :
-rm -f *.o offgrid
I'm trying to create a generic make file so that I can compile my project independently of how many files I add to it and where I decide to put them in the project tree.
In my step by step approach I cam to this makefile which works fine.
CC=g++
OBJECTS=main.o board.o
VPATH=src:\
src/board:\
include/board:\
build:\
bin
boardG : main.o board.o
$(CC) -o bin/boardG build/main.o build/board.o
main.o : main.cpp board.hpp
$(CC) -c -I include $< -o build/$#
board.o : board.cpp board.hpp
$(CC) -c -I include $< -o build/$#
This version will do the job just fine. See output below:
me#01:~/code/projects/boardG$ make
g++ -c -I include src/main.cpp -o build/main.o
g++ -c -I include src/board/board.cpp -o build/board.o
g++ -o bin/boardG build/main.o build/board.o
The problem here is that I will have to create one rule for each .cpp file. Which is precisely what I try to avoid. Hence I tried to adapt the version above using matching patterns like this:
CC=g++
OBJECTS=main.o board.o
VPATH=src:\
src/board:\
include/board:\
build:\
bin
boardG : main.o board.o
$(CC) -o bin/boardG build/main.o build/board.o
%.o : %.cpp %.hpp
$(CC) -c -I include $< -o build/$#
When I run make now I get the follwing output:
me#01:~/code/projects/boardG$ make
g++ -c -o main.o src/main.cpp
src/main.cpp:2:27: fatal error: board/board.hpp: No such file or directory
compilation terminated.
<builtin>: recipe for target 'main.o' failed
make: *** [main.o] Error 1
My project has the follwing structure/files in it.
./bin/
./build/
./include/board/board.hpp
./src/main.cpp
./src/board/board.cpp
./makefile
I'm wondering why make would change the command when using pattern matching? Or, and probably more accurately, what am I doing wrong that makes make fail?
Just avoid using VPATH when it comes to object files. What's happening is that make is actually using the built-in rule for %.o and not using your rule at all.
If you prefix all your objects with the directory, this should work:
CC=g++
OBJDIR = build
OBJECTS = $(OBJDIR)/main.o $(OBJDIR)/board.o
VPATH = src:\
src/board:\
include/board:\
bin/boardG : $(OBJECTS)
$(CC) -o $# $^
$(OBJDIR)/%.o : %.cpp %.hpp
$(CC) -c -I include $< -o $#
Here is a helpful resource, which more or less exactly describes the problem you've run into.
I'm scanning the web and all my project files for solution but still can't find the answer why my linker won't finish the job. Everything smoothly compiles into .o files, but the last make command fails. And here is the Makefile content:
CXX = g++
CXXFLAGS = -Wall -pedantic -c
OBJS = main.o operacje.o porownaj.o
dzialania: $(OBJS)
$(CXX) $^ -o $#
main.o: main.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $^ -o $#
operacje.o: operacje.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $^ -o $#
porownaj.o: porownaj.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $^ -o $#
clean:
rm -f *o
and again, here is the mistake that pops out:
g++ main.o operacje.o porownaj.o -o dzialania
ld: fatal: file main.o: unknown file type
ld: fatal: file processing errors. No output written to dzialania
*** Error code 1
make: Fatal error: Command failed for target `dzialania'
I'm sure it's some kind of a basic mistake but after staring at the file for a few hours I won't notice it anyway. Maybe some of you folks with notice the bug with a fresh eye.
btw. it's my first post after long-term passive lurking, I hope I did everything right. Thanks in advance!
#edit1 OK, I did all the suggested corrections
#edit2 Seems like the problem is caused by improper module division of my program. I'll rearrange it's structure and let you know if it works then. Thanks for all the support!
#edit3 OK, I changed the structure of my program and everything runs smooth, Thanks again!
Try using $< instead of $^ in your rules to compile main.o, operacje.o, and porownaj.o:
main.o: main.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $< -o $#
operacje.o: operacje.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $< -o $#
porownaj.o: porownaj.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $< -o $#
That will cause make to compile only the corresponding .cpp file. When you use $^ the header files are passed to the g++ command which tells the compiler to create precompiled headers for them - that's what's ending up in main.o instead of the object file for main.cpp.
GNU make variable definitions like CC = g++, or CFLAGS = -Wall -pedantic etc.. should each be on its own line:
CC = g++
CFLAGS = -Wall -pedantic
OBJS = main.o operacje.o porownaj.o
BTW, you probably mean
CXX = g++
CXXFLAGS = -Wall -pedantic
You certainly don't want -c explicitly in your CFLAGS or CXXFLAGS; you really should remove it.
Also, recipes should be after its rule, so you want
dzialania: $(OBJS)
$(LINK.cc) $^ -o $#
operacje.o: operacje.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) -c $< -o $#
The several spaces are actually a single tab character.
Run make -p to understand the rules known by make; see also this answer and that one.
Take time to read GNU make documentation.
so I have this structure:
simpleConnect.cpp (contains main)
Call feature_extract.cpp
feature_extract.cpp (does some things here, returns to simpleConnect)
ThesisHeader.h (has declaration of feature_extract and all the includes etc...)
Now...These files use a library called ARIA (used for mobilerobots) and a set of header files - EIGEN (for matrix manipulations etc)
I used to suggested structure by Aria as follows:
SOURCES=simpleConnect
all: $(SOURCES)
CFLAGS=-fPIC -g -Wall
ARIA_INCLUDE =-I/usr/local/Aria/include
ARIA_LINK=-L/usr/local/Aria/lib -lAria -lpthread -ldl -lrt
%: %.cpp
$(CXX) $(CFLAGS) $(ARIA_INCLUDE) $< -o $# $(ARIA_LINK)
But I'm getting this error at the line where I call the function feature_extract:
undefined reference to 'feature_extract(......)'
collect2: ld reurned 1 exit status
As far as I can understand this is to do with me not telling the compiler that feature_extract is there....because I don't know how...
I tried adding pieces I found online but to no avail, hence I came asking here.
Could anyone be kind enough to modify the makefile so as to include that file to be able to compile?
Thank you for your time,
Patrick
This app needs `feature_extract`.
You're using "SOURCES" for something other than sources.
CFLAGS=-fPIC -g -Wall
ARIA_INCLUDE =-I/usr/local/Aria/include
ARIA_LINK=-L/usr/local/Aria/lib -lAria -lpthread -ldl -lrt
app_name: simpleConnect.cpp feature_extract.cpp
$(CXX) $(CFLAGS) $(ARIA_INCLUDE) $^ -o $# $(ARIA_LINK)
If this works, further refinements are possible.
I managed to solve this problem, thanks to those who helped.
I ended up reading the GNU make manual, which solved my problem.
https://www.gnu.org/software/make/manual/make.pdf
This is the final makefile that ended up working:
CFLAGS=-fPIC -g -Wall
ARIA_INCLUDE =-I/usr/local/Aria/include
ARIA_LINK=-L/usr/local/Aria/lib -lAria -lpthread -ldl -lrt
edit : simpleConnect.o feature_extract.o
$(CXX) $(CFLAGS) $(ARIA_INCLUDE) -o edit simpleConnect.o
feature_extract.o $(ARIA_LINK)
simpleConnect.o : simpleConnect.cpp ThesisHeader.h feature_extract.cpp
$(CXX) $(CFLAGS) $(ARIA_INCLUDE) -c simpleConnect.cpp $(ARIA_LINK)
feature_extract.o : feature_extract.cpp ThesisHeader.h
$(CXX) $(CFLAGS) $(ARIA_INCLUDE) -c feature_extract.cpp $(ARIA_LINK)
clean :
rm edit simpleConnect.o feature_extract.o
This is my makefile:
CFLAGS = -Wall -pedantic -pedantic-errors -g -lSDL -lSDL_image
CC = g++
OBJ = Point.o Personaje.o Juego.o EventHandler.o
all: main
#%.o: %.cpp %.h
# $(CC) -c $(CFLAGS) $<
bin: other $(OBJ)
Point.o: Point.cpp Point.h
$(CC) -c $(CFLAGS) $<
Personaje.o: Personaje.cpp Personaje.h
$(CC) -c $(CFLAGS) $<
Juego.o: Juego.cpp Juego.h
$(CC) -c $(CFLAGS) $<
EventHandler.o: EventHandler.cpp EventHandler.h
$(CC) -c $(CFLAGS) $<
main: $(OBJ)
cd ../vista/; make
cp ../vista/*.o .
rm ../vista/*.o
g++ $(CFLAGS) $(OBJ) Pantalla.o Imagen.o main.cpp -o main
clean:
rm *.o;
rm main
PHONY: main
When I compile with "make" I get the following errors:
EventHandler.cpp:17: undefined reference to `SDL_PollEvent'
Pantalla.o: In function `Pantalla::initialize(int, int, int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
Pantalla.cpp:6: undefined reference to `SDL_Init'
Pantalla.cpp:9: undefined reference to `SDL_SetVideoMode'
Pantalla.cpp:14: undefined reference to `SDL_WM_SetCaption'
and many other errors.
The header of "Pantalla.h" contains this line:
#include "SDL/SDL.h"
And I already installed the SDL packages.
I don't know what I'm doing wrong... please help!
CFLAGS = -Wall -pedantic -pedantic-errors -g -lSDL -lSDL_image
This isn't good. You're mixing compiler flags (warnings and debug) with linker information (which libraries you need to link to). Use two separate variables for that:
CFLAGS = -Wall -pedantic -pedantic-errors -g
LIBS = -lSDL -lSDL_image
Then when you compile (but don't link, i.e. when you generate the .o files), only use $(CFLAGS) (like you have now). But when you do link (to produce the final executable), add the linker directives.
g++ $(CFLAGS) -o main main.cpp $(OBJ) Pantalla.o Imagen.o $(LIBS)
The order you put your objects and libraries is important.
One problem is that you are using exactly the same flags for compilation and linking. The compiler doesn't use libraries; the linker doesn't know about pedantic.
A bigger problem is that your -lSDL -lSDL_image appears too early in the link command, g++ $(CFLAGS) $(OBJ) Pantalla.o Imagen.o main.cpp -o main. The linker won't look into libSDL.a or libSDL_image.a (or their equivalents) because there are no unresolved external references at the point where you specified the search. Put the -lSDL -lSDL_image options just before the -o option.