How can I set properly the makefile to import some OpenCV lib into the libmat.o?
this is the make file:
# Define a variable for classpath
CLASS_PATH = ../bin
# Debug: -g3=compile with extra debugg infos. -ggdbg3=include things like macro defenitions. -O0=turn off optimizations.
DEBUGFLAGS = -g3 -ggdb3 -O0
CFLAGS = $(DEBUGFLAGS)
# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)
all : libMat.so
# $# matches the target, $< matches the first dependancy
libMat.so : libMat.o
g++ $(CFLAGS) -W -shared -o $# $<
# $# matches the target, $< matches the first dependancy
libMat.o : Mat2Image.cpp Mat2Image.h
g++ $(CFLAGS) -fPIC -I/usr/lib/jvm/jdk1.8.0_111/include -I/usr/lib/jvm/jdk1.8.0_111/include/linux -c $< -o $# -L/usr/local/lib
# $* matches the target filename without the extension
# manually this would be: javah -classpath ../bin HelloJNI
HelloJNI.h : Mat2Image.class
javah -classpath $(CLASS_PATH) $*
clean :
rm -f Mat2Image.h libMat.o libMat.so
i need some OpenCV lib located in /usr/local/lib
for example libopencv_imgproc.so
I think what you want to do is get (e.g.) libopencv_imgproc.so,
located in /usr/local/lib, to be linked with your shared library libMat.so.
The way you are trying to do this in your makefile is by "linking"
libopencv_imgproc.so with the object file libMat.o by the recipe:
libMat.o : Mat2Image.cpp Mat2Image.h
g++ $(CFLAGS) -fPIC -I/usr/lib/jvm/jdk1.8.0_111/include \
-I/usr/lib/jvm/jdk1.8.0_111/include/linux -c $< -o $# \
-L/usr/local/lib
You think that -L/usr/local/lib at the end will in some way let the linker
know you want to link libopencv_imgproc.so and do so.
That won't work for more than one reason:
-L/usr/local/lib will just tell the linker that /usr/local/lib is
a directory where you want it search for libraries that you ask it to
link. It doesn't ask it to link any libraries from there, and if you
don't tell it to, it won't. To tell the linker
to search for libraries in /usr/local/lib and ask it to link
libopencv_imgproc.so you would use:
`-L/usr/local/lib -lopencv_imgproc
But you don't need to tell it to search for libraries in /usr/local/lib,
because that is one of the directories the linker searches for libraries
by default. So -lopencv_imgproc is all you would need.
But more important than that,
g++ $(CFLAGS) -fPIC -I/usr/lib/jvm/jdk1.8.0_111/include \
-I/usr/lib/jvm/jdk1.8.0_111/include/linux -c $< -o $# \
-L/usr/local/lib
is the command that simply compiles libMat.o from Mat2Image.cpp. It
doesn't do any linkage. It is not possible and does not make sense to "link"
anything with an object file. So adding any linkage options to your
compile command is pointless. The compiler will ignore them. This command is
effectively no different from:
g++ $(CFLAGS) -fPIC -I/usr/lib/jvm/jdk1.8.0_111/include \
-I/usr/lib/jvm/jdk1.8.0_111/include/linux -c $< -o $#
and that's what it should be.
The recipe that does your linkage is:
libMat.so : libMat.o
g++ $(CFLAGS) -W -shared -o $# $<
So this is where you have to tell the linker that you want libopencv_imgproc.so
to be linked:
libMat.so : libMat.o
g++ $(CFLAGS) -W -shared -o $# $< -lopencv_imgproc
With this, libMat.so will be linked containing libMat.o and a runtime
dependency on the shared library libopencv_imgproc.so - that is, an
instruction to the runtime loader that it must load libopencv_imgproc.so
into the same process when it loads libMat.so.
Your makefile has various other faults but what I've said is enough to
explain and fix the particular problem I think you're asking about. You
can learn how to write a better makefile, if you want, by searching for tutorials
and ariticles about GNU Make and studying the documentation
I'll just point out one other fault that is serious. Your recipe:
clean:
rm -f Mat2Image.h libMat.o libMat.so
is going to delete the header file Mat2Image.h when you run
make clean. That header file is one of your original source files. It
isn't generated by this makefile - like libMat.o and libMat.so - unless
you've ommitted some bits of the real makefile. So
if you delete it you'll have to recover it from you source-control system; and
if its not under a source-control system, you'll have to rewrite it. So
I think you just want:
clean:
rm -f libMat.o libMat.so
Related
I need to compile fat binary file to be able use it on another linux machine. But there are some libraries missing so as I understand I should compile it with some -shared options. But I don't understand how to configure a Makefile for that. Currently my makefile looks like this:
CC = g++
CC_FLAGS = -std=c++11 -O2 -static -Wall
EXEC = cpp_server
SOURCES = $(wildcard *.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
LIBS = -lpthread -lmicrohttpd -lz
$(EXEC): $(OBJECTS)
$(CC) $(OBJECTS) -o $(EXEC) $(LIBS)
%.o: %.cpp
$(CC) -c $(CC_FLAGS) $< -o $#
clean:
rm -f $(EXEC) $(OBJECTS)
You'll better take advantage of the many built-in rules of GNU make. Run once make -p to learn them. So you should use CXX instead of CC and replace CC_FLAGS with CXXFLAGS.
You may want to build a statically linked executable. Then you should pass -static into your linking command, using LINKFLAGS
So try with
## untested Makefile for GNU make
# variables known to make
CXX= g++
CXXFLAGS= -std=c++11 -O2 -Wall -Wextra
LINKFLAGS= -static
LIBS= -lpthread -lmicrohttpd -lz
# this project needs:
MYEXEC= cpp_server
MYSOURCES= $(wildcard *.cpp)
MYOBJECTS= $(SOURCES:.cpp=.o)
.PHONY: all clean
all: $(MYEXEC)
$(MYEXEC): $(MYOBJECTS)
$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $#
clean:
rm -f $(MYEXEC) $(MYOBJECTS)
AFAIK you don't need anything more in your Makefile (provided you use a GNU make, not e.g. a BSD one). Of course you need appropriate TAB characters in your Makefile (so you need to use some editor able to insert them).
You could want to statically link only -lmicrohttpd (and dynamically link the other libraries; however, you might want to also statically link the C++ standard library, which depends upon the compiler and could change when the compiler changes; linking also the C++ library statically is left as an exercise). You could do that with removing the LINKFLAGS line and using
LIBS= -Bstatic -lmicrohttpd -Bdynamic -lz -lpthread
BTW the -shared linker option is need to build from position-independent code object files a shared library (not to use one). See this and that.
You may want to use make --trace (or remake -x, using remake) to debug your Makefile
If you want to understand what actual files are linked, add -v -Wl,--verbose to LINKFLAGS perhaps by running make 'LINKFLAGS=-v -Wl,--verbose' on your terminal.
You might want to make clean before anything else.
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
I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++. I've been reading up on shared libraries and it seems to be the best solution.
However, as headers/source change frequently, I'm hoping to create a makefile that would automatically generate all the .so files from the headers and source.
To better demonstrate what I'm trying to do, I'll take one of my sub-libraries, Chrono and show how I would do this manually.
I first create the object files like so,
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DateTime.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Schedule.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/Duration.cpp
$ g++ -std=c++11 -fPIC -g -c -Wall ../src/Chrono/cpp/DayCount.cpp
So that I now have DateTime.o, Schedule.o, Duration.o, and DayCount.o in the current directory. I then create the .so file,
$ g++ -shared -Wl,-soname,libChrono.so.1 -o libChrono.so.1.0.1 DateTime.o Schedule.o Duration.o DayCount.o -lc
I then go,
$ rm ./*.o && ldconfig -n ./
So that my working directory now contains, libChrono.so.1.0.1 and the symlink libChrono.so.1.
There are quite a few subdirectories I need to do this for, so you can see that this quickly grows inefficient whenever changes to headers/source are made. I would be grateful if anyone can help me design a makefile that accomplishes all this simply by invoking make.
Thanks!
UPDATE:
Based on goldilock's advice and some digging, I managed to bang together:
CXX=g++
CFLAGS=-std=c++11
TARGET=./lib/libChrono.so.1.0.1
CHRONODIR=./src/Chrono
CHRONOSRC=$(wildcard $(CHRONODIR)/cpp/*.cpp)
CHRONOOBJ=$(join $(addsuffix ../obj/, $(dir $(CHRONOSRC))), $(notdir (CHRONOSRC:.cpp=.o)))
all: $(TARGET)
#true
clean:
#-rm -f $(TARGET) $(CHRONOOBJ)
./lib/libChrono.so.1.0.1: $(CHRONOOBJ)
#echo "======================="
#echo "Creating library file $#"
#echo "======================="
#$(CXX) -shared -Wl,-soname,$(join $(basename $#), .1) -o $# $^ -l
#echo "-- $# file created --"
$(CHRONODIR)/cpp/../obj/%.o : $(CHRONOSRC)
#mkdir -p $(dir $#)
#echo "============="
#echo "Compiling $<"
#$(CXX) $(CFLAGS) -fPIC -g -Wall -c $< -o $#
4 .o files are produced in lib/ but I get multiple definition complaints from ld. Before I was compiling the object files separately, but this unwinds CHRONOOBJ on one line. Any ideas?
Fortunately you included the origin of your problem:
I've been building a C++11 library, and the number of header/source files has grown to the point where compiling programs invoking it, entails passing 20+ .cpp files to g++.
Because this reveals a potential XY problem. The straightforward solution to this is to put object files into an archive (aka. a static library) and use that.
GNU make has an implicit rule for creating C++ .o files. It amounts to this:
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
Meaning, if you make DateTime.o in a directory with a makefile that doesn't redefine this, it will make DateTime.o. You may want to add things to $(CXXFLAGS) however, e.g.:
CXXFLAGS += -Wall -Wextra --std=c++11
If you intend to stick with the shared lib route, -fPIC can go there too. That one line could be your entire makefile.
However, you also want to put these together, so you must first declare all the objects and a rule for combining them:
OBJS = DateTime.o Schedule.o Duration.o
libChrono.a: $(OBJS)
ar crvs $# $^
This last line (see man ar) creates the archive (libChrono.a) containing all the objects in $(OBJS). You can then use this with whatever program by placing it in the same directory (or a directory in the library path) and linking -lChrono. Only the necessary parts will be extracted and compiled in. This saves you having to maintain a shared lib in a system directory.
If you still think you need a shared lib, $# and $^ are automatic variables; you can use similar methodology to create a .so, something along the lines of:
SO_FLAGS = -shared
libChrono.so.1.0.1: $(OBJS)
$(CXX) $(SO_FLAGS) -Wl,-soname,libChrono.so.1 -o $# $^ -lc
If that is your first rule, make will take care of everything: building first the objects and then the library. Notice this one has excluded your normal $(CXXFLAGS) to duplicate exactly the compiler line from the question.
How can I link jsoncpp with a C++ program using g++? I tried:
g++ -o program program.cpp -L/path/to/library/files -ljsoncpp, -ljson, -llibjsoncpp
but g++ keeps saying:
/usr/bin/ld: cannot find -lsomething
You could also try using the new Amalgamated version of jsoncpp, which is new as of version 0.6.0.
The Amalgamated version allows you to use jsoncpp by adding just one directory with a couple of header files and one .cpp file to your project. You then can directly compile jsoncpp into your program with no worries about having to link to any jsoncpp libraries.
Look in /path/to/library/files to see what your *.a file is really named. On my system, I link with:
-ljson_linux-gcc-4.4.3_libmt
Some libraries will create a link from lib<name>.a to lib<name>-<version>.a for you, but I don't think that jsoncpp does this automatically. Therefore, you need to specify the complete name when linking.
You basically need to tell the path and the library.
jsoncpp library has pkg-config and you can use the command
`pkg-config --cflags path/to/jsoncpp/build/pkg-config/jsoncpp.pc`
for the include path and
`pkg-config --libs ../jsoncpp/build/pkg-config/jsoncpp.pc`
for linking (when running the command with g++ use the ). To see the single commands which is -L/libraryPath -ljsoncpp) run the commands above in the terminal without the ``.
It is easier to use this commands in a Makefile. As example my Makefile is:
CXX = g++
CXXFLAGS = -std=c++11
INC_PATH = `pkg-config --cflags ../jsoncpp/build/pkg-config/jsoncpp.pc`
LIBS = `pkg-config --libs ../jsoncpp/build/pkg-config/jsoncpp.pc`
SOURCES := $(wildcard *.cpp)
OBJDIR=obj
OBJECTS := $(patsubst %.cpp,$(OBJDIR)/%.o,$(SOURCES))
DEPENDS := $(patsubst %.cpp,$(OBJDIR)/%.d,$(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: yourProjectExecutableName
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
yourProjectExecutableName: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $# $(LIBS)
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: %.cpp Makefile $(OBJDIR)
$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) -MMD -MP -c $< -o $#
and then in the directory of the file I run make. The final command(s) will be printed out in the Terminal
I'm trying to compile a simple program, with
#include <gtkmm.h>
The path to gtkmm.h is /usr/include/gtkmm-2.4/gtkmm.h. g++ doesn't see this file unless I specifically tell it -I /usr/include/gtkmm-2.4.
My question is, how can I have g++ automatically look recursively through all the directories in /usr/include for all the header files contained therein, and why is this not the default action?
In this case, the correct thing to do is to use pkg-config in your Makefile or buildscripts:
# Makefile
ifeq ($(shell pkg-config --modversion gtkmm-2.4),)
$(error Package gtkmm-2.4 needed to compile)
endif
CXXFLAGS += `pkg-config --cflags gtkmm-2.4`
LDLIBS += `pkg-config --libs gtkmm-2.4`
BINS = program
program_OBJS = a.o b.o c.o
all: $(BINS)
program: $(program_OBJS)
$(CXX) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $#
# this part is actually optional, since it's covered by gmake's implicit rules
%.o: %.cc
$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $< -o $#
If you're missing gtkmm-2.4, this will produce
$ make
Package gtkmm-2.4 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gtkmm-2.4.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gtkmm-2.4' found
Makefile:3: *** Package gtkmm-2.4 needed to compile. Stop.
Otherwise, you'll get all the appropriate paths and libraries sucked in for you, without specifying them all by hand. (Check the output of pkg-config --cflags --libs gtkmm-2.4: that's far more than you want to type by hand, ever.)
I guess you are not using a makefile? The only thing that could be annoying is having to type the long -I option each time you compile your program. A makefile makes it a lot easier.
For example, you could modify the hello world makefile from wikipedia to something like the following:
INC=-I/usr/include/gtkmm-2.4/
helloworld: helloworld.o
g++ -o $# $<
helloworld.o: helloworld.c
g++ $(INC) -c -o $# $<
.PHONY: clean
clean:
rm -f helloworld helloworld.o
You can't. The whole point of include paths is so you can pick and choose what you want and what versions.
What you could do is..
#include <gtkmm-2.4/gtkmm.h>
Which would achieve the same effect.