For this reason I downloaded the C++ library VTK and made a local build in the build subdirectory on a OSX environment.
I would like to compile a project using this library (particularly I am using the class vtkSmartPointer) with Makefile.
Consider for example the following source code:
#include<iostream>
#include<vtkSmartPointer.h>
#include<vtkCallbackCommand.h>
int main()
{
vtkSmartPointer<vtkCallbackCommand> keypressCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
std::cout<<"hello world\n";
return 0;
}
For the Makefile I started from the second answer in this post to which I aded VTK library path:
CXX = g++
# OpenCV trunk
CXXFLAGS = -std=c++11 \
-I ../VTK/Common/Core/ -I ../VTK/build/Common/Core/ -I ../VTK/build/Utilities/KWIML/ \
-I ../VTK/Utilities/KWIML/ \
-L../VTK/build/lib \
-lvtkCommon -lvtkFiltering -lvtkImaging -lvtkGraphics -lvtkGenericFiltering -lvtkIO
SOURCES := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(SOURCES))
DEPENDS := $(patsubst %.cpp,%.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: parking
clean:
$(RM) $(OBJECTS) $(DEPENDS) parking
# Linking the executable from the object files
parking: $(OBJECTS)
$(CXX) $(WARNING) $(CXXFLAGS) $^ -o $#
-include $(DEPENDS)
%.o: %.cpp Makefile
$(CXX) $(WARNING) $(CXXFLAGS) -MMD -MP -c $< -o $#
My environment variable DYLD_LIBRARY_PATH has the value ../cmake_bin_dir/instDir/lib:../VTK/build/lib/.
When I try to compile running make, I get the following error:
ld: library not found for -lvtkCommon
clang: error: linker command failed with exit code 1 (use -v to see invocation)
What part of the Makefile or program or step in the process is not correct?
Thank you in advance.
The current VTK library does not contain libVtkCommon.so (see package contents section https://www.archlinux.org/packages/community/x86_64/vtk/). Are you looking for libVtkCommonCore.so? If that is the case you have to change -lvtkCommon to -lvtkCommonCore in your Makefile. The same seems to be the case for some of the other included libraries.
Related
Makefiles are quite confusing to me. I am attempting to "make" my project that I have worked on in Windows. The confusing part is actually constructing the make file from scratch. I would am trying to also link to the SDL2 library, and that is in a '.a' format.
Here is my code for the make file so far, I have tried multiple versions, and this is the latest:
CXX = gcc
OUT = Engine
SRC =Software-Rendering/src/
SDL_INCLUDE_DIR =Software-Rendering/lib/SDL2/include/SDL/
LIB_DIR =Software-Rendering/lib/SDL2/x86/linuxLib/
SDL = -l${LIB_DIR}libSDL -l${LIB_DIR}/libSDL2main
CPP_FILES =Bitmap.cpp Main.cpp Vector3.cpp Window.cpp
H_FILES =Bitmap.h ErrorReport.h Vector3.h Window.h
O_FILES = Bitmap.o ErrorReport.o Main.o Vector3.o Window.o
all: $(OUT)
$(OUT): $(O_FILES)
$(CXX) -o $# $^ ${SDL}
#Making all of the object files down
$(O_FILES): $(H_FILES)
$(CXX) -c $(CPP_FILES)
#Make sure we can easily clean up the directory
clean:
rm -f Engine ${O_FILES}
clean_obj:
rm -f ${O_FILES}
I decided to put the ".a" files in a special directoy in my project so whenever someone clones my repository on github all of the files for compiling and linking are already there.
Why isn't this working and how can I make it work?
Your library linking directive are wrong -- -l prefixes lib to the name you specify, and then searches through the libdir path set by the -L options. So what you want is something like:
SDL = -L$(LIB_DIR) -lSDL -lSDL2main
You can make it clearer/more standard by using the standard varnames for libraries:
LDFLAGS = -L$(LIB_DIR)
LDLIBS = -lSDL -lSDL2main
$(OUT): $(O_FILES)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
Also, get rid of the explicit command to compile source files -- the default built in rule is fine and easier to use.
I'm trying to link my program with boost libraries using makefile with cygwin. Here is my makefile:
CXX = g++
CXXFLAGS = -Wno-signed-compare -Wall -std=c++11 -funsigned-char -I /cygdrive/e/boost/include/boost-1_55/boost
LNKFLAGS = -L cygdrive/e/boost/lib
SRCDIR = src
OUTDIR = bin
EXEC = $(OUTDIR)/prg
SOURCES = $(wildcard src/*.cpp)
OBJECTS := $(SOURCES:$(SRCDIR)/%.cpp=$(OUTDIR)/%.o)
all: $(EXEC)
$(EXEC): $(OBJECTS)
$(CXX) $(LNKFLAGS) $(OBJECTS) -o $(EXEC) -l boost_thread
$(OBJECTS): $(OUTDIR)/%.o : $(SRCDIR)/%.cpp
mkdir -p $(OUTDIR)
$(CXX) $(CXXFLAGS) -c -O3 $< -o $#
clean:
rm -rf $(OUTDIR)
.PHONY: clean
Result:
$ make
g++ -L cygdrive/e/boost/lib bin/test.o -o bin/prg -l boost_thread
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lboost_thread
What's wrong? What should I specify?
In your Makefile the library search path is relative, but should be absolute in this case.
LNKFLAGS = -L/cygdrive/e/boost/lib
Check if /cygdrive/e/boost/lib really contains Boost libraries built with the GCC toolchain.
libboost_thread.a or libboost_thread.so will work.
Libraries built with the Visual C++ toolchain ending with .lib or .dll will not work.
Check if the filename matches.
-lboost_thread requires that the library is named either libboost_thread.a or libboost_thread.so.
libboost_thread-mt.a or the like will not work.
You may find my answer to a related question helpful.
I have been creating a library. When I compile it as a static library, it works fine. Now I want to turn it into a shared library. The library is created and in the proper place, but when I try to compile the client code, the linking phase says that it can't find the library.
I already tried to rename it to al or dylib but that doesn't help either. When I put the -v flag on the linking, I can see that my library path is there. I also tried different paths. I used a relative path, but even with a full path it doesn't find it.
The Makefile from the library:
.SUFFIXES:
.SUFFIXES: .o .cpp
.SUFFIXES: .o .d
CC := g++
LNK:= g++
CXXFLAGS_RELEASE = -fPIC -shared -O2 -Wall -fmessage-length=0
CXXFLAGS_DEBUG = -fPIC -shared -g -Wall -fmessage-length=0 -D _DEBUG
CXXFLAGS = $(CXXFLAGS_DEBUG)
OBJDIR:= obj
SRCDIR:= src
HDIR:= include
INCLUDE_PATHS:= -Iinclude -Iinclude/interfaces -Iinclude/support
CPP_FILES := propertyfile/propertyfile.cpp \
propertyfile/propertyitem.cpp \
propertyfile/propertyfactory.cpp \
helper/string_helper.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
LIBS:=
TARGET:= libsupport.so
all: $(TARGET)
$(TARGET): $(OBJ)
$(LNK) -o $(TARGET) $(OBJ) -shared
#cp $(TARGET) ../lib
#cp -r include ..
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -c $< -o $# $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -MM -MT $# -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
And here is the Makefile for the application:
.SUFFIXES:
.SUFFIXES: .o .cpp
CC := g++
LD := g++
CXXFLAGS_RELEASE = -O2 -Wall -fmessage-length=0
CXXFLAGS_DEBUG = -g -Wall -fmessage-length=0 -D _DEBUG
CXXFLAGS = $(CXXFLAGS_DEBUG)
OBJDIR:= obj
SRCDIR:= src
INCLUDE_PATHS:= -Iinclude -I../include
LIBS:= -L /cygdrive/d/src/c/lib -lsupport
CPP_FILES := nohupshd.cpp \
daemon.cpp \
task.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
TARGET:= nohupshd
all: $(TARGET)
$(TARGET): $(OBJ)
$(LD) -o $(TARGET) $(OBJ) $(LIBS)
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -c $< -o $# $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -MM -MT $# -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
After some experimenting I found a solution on how to compile a shared library under cygwin.
Apparently the compiler is looking for a DLL file even though it is inside cygwin. so the first step is to add your path, where the library is going to be to the PATH variable.
export PATH=$PATH:/cygdrive/d/src/c/lib
Apparently when linking against a shared library, the linker seems to look for a DLL file by default. I don't know why, because inside cygwin I would expect it to look for a .so file just like on other UNIX systems.
However, there are two solutions to this, which both work.
First, you can create a link to your .so library with the name .dll
ln -s /cygdrive/d/src/lib/libsupport.so libsupport.dll
In this case the makefile doesn't have to be changed and -lsupport will find the library while linking. I prefer this solution.
Second, you can specify the linker option with the full name.
LIBS:= -L /cygdrive/d/src/c/lib -l:libsupport.so
then you don't have to create a link.
So the crucial thing seems to be that the shared library must be in the PATH under cygwin. Using LD_LIBRARY_PATH doesn't help in that case as you can link the executable, but when trying to run it, it will not find it.
ldd nohupshd.exe
libsupport.so => not found
UPDATE: For some reason when I checked with ldd, my library was suddenly gone from the list. I found out that cygwin uses the name to differentiate between MS Windows and Unix shared libraries. So in order to make it work, the name of the library must be cyg.so to make it work, otherwise the exectuable seems to be some Windows build. In this case you don't need to create the link named x.dll as the shared library stays inside the Unix environment.
$(LNK) -o cyg$(TARGET).so $(OBJ) -shared
When using eclipse for debugging, the path to the shared library must also be in the windows path environment variable. Otherwise the debug session immediately terminates without an error.
I've strictly followed this documentation to install and use jsoncpp library in my project : jsoncpp README
But I still have this problem with my compilation:
g++ -W -Wall -Werror -c -o src/ModConnection.o src/ModConnection.cpp
src/ModConnection.cpp:15:23: fatal error: json/json.h: No such file or directory
compilation terminated.
It's happen when I'm trying to use #include <json/json.h>
Here is my Linux MAKEFILE :
CXX = g++
NAME = bin/server
SRCS = ./src/ModConnection.cpp\
./src/unixNetwork.cpp
OBJS = $(SRCS:.cpp=.o)
CXXFLAGS += -W -Wall -Werror
LDFLAGS = -L ./src/jsoncpp-src-0.5.0/buildscons/linux-gcc4.5.1/src/lib_json/libjson_linux-gcc-4.5.1_libmt.a -I src/jsoncpp-src-0.5.0/include
RM = rm -f
$(NAME) : $(OBJS)
$(CXX) $(LDFLAGS) -o $(NAME) $(OBJS)
all : $(NAME)
clean :
$(RM) $(OBJS)
fclean : clean
$(RM) $(NAME)
re : fclean all
.PHONY : all clean fclean re
Thanks for you help.
You're specifying the include directory for jsoncpp in your LDFLAGS variable, but those don't get used until you've already compiled the individual cpp files. You need to put the part -I src/jsoncpp-src-0.5.0/include somewhere in the flags which get added to the compile lines, such as CXXFLAGS.
To expand a bit, you're using implicit Make rules to build your individual .cpp files, then you have a specific target for building your application out of those objects.
See the GNU Make Catalog of Rules for more info, but the one you're using is here:
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c. We encourage you to use the suffix ‘.cc’ for C++ source files instead of ‘.C’.
Edit: Now for your linking errors.
You're getting these problems because the linker can't find the actual implementations of the functions you're calling.
First, your -L directive needs to point to a folder, not a library. -L sets a search path for libraries. It should be set to the folder where the library the jsoncpp build was created. Next, you must link the library itself. That library name is gigantic, but adding -l json_linux-gcc-4.5.1_libmt to LDFLAGS should do the trick. -l (that's lower ell) sets an actual library to link.
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