[SOLVED] created symlinks from /usr/lib/lib/* to /usr/lib*
[UPDATE 3] NEW VERSION:
Ok, I think I fixed something
use find / -name "libboost_system.*"
outout was
/usr/include/boost/lib/libboost_system.so
/usr/include/boost/lib/libboost_system.a
/usr/include/boost/lib/libboost_system.so.1.46.1
/usr/lib/lib/libboost_system.so
/usr/lib/lib/libboost_system.a
/usr/lib/lib/libboost_system.so.1.46.1
/usr/local/include/boost_1_46_1/bin.v2/libs/system/build/gcc-4.4.3/release/link-static/threading-multi/libboost_system.a
/usr/local/include/boost_1_46_1/bin.v2/libs/system/build/gcc-4.4.3/release/threading-multi/libboost_system.so.1.46.1
/usr/local/lib/libboost_system.so
/usr/local/lib/libboost_system.a
/usr/local/lib/libboost_system.so.1.46.1
/root/tmp/boost_1_46_1/bin.v2/libs/system/build/gcc-4.4.3/release/link-static/threading-multi/libboost_system.a
/root/tmp/boost_1_46_1/bin.v2/libs/system/build/gcc-4.4.3/release/threading-multi/libboost_system.so.1.46.1
why are these files in /usr/lib/lib ? and is it a problem ?
and the ls -l /usr/lib/lib | grep boost_system
ls -l /usr/lib/lib | grep boost_system
-rw-r--r-- 1 root root 21574 2011-05-09 15:15 libboost_system.a
lrwxrwxrwx 1 root root 25 2011-05-09 15:15 libboost_system.so -> libboost_system.so.1.46.1
-rwxr-xr-x 1 root root 20053 2011-05-09 15:15 libboost_system.so.1.46.1
atm my makefile looks like
LIBPATH=-I/usr/local/include/cpp-netlib
LIBS=$(LIBPATH) -lboost_system -lboost_filesystem -lboost_thread -lpthread
LD=g++ -g
CPP=g++ -c -g $(LIBS)
P=.
OBJ=$(P)/tmp/main.o $(P)/tmp/CLink.o $(P)/tmp/CFetcher.o
main: $(OBJ); $(LD) $(OBJ) $(LIBS) -o $#
$(P)/tmp/CLink.o: $(P)/src/CLink.cpp $(P)/include/CLink.h; $(CPP) -c $< -o $#
$(P)/tmp/CFetcher.o: $(P)/src/CFetcher.cpp $(P)/include/CFetcher.h; $(CPP) -c $< -o $#
$(P)/tmp/main.o: $(P)/src/main.cpp $(P)/include/CLink.h $(P)/include/CFetcher.h ; $(CPP) -c $< -o $#
all:
touch $(P)/tmp/*.o;
touch main;
rm -f $(P)/tmp/*.o;
rm -f main;
make main;
The Compiler output is lie
g++ -c -g -I/usr/local/include/cpp-netlib -lboost_system -lboost_filesystem -lboost_thread -lpthread -c src/main.cpp -o tmp/main.o
g++ -c -g -I/usr/local/include/cpp-netlib -lboost_system -lboost_filesystem -lboost_thread -lpthread -c src/CLink.cpp -o tmp/CLink.o
g++ -c -g -I/usr/local/include/cpp-netlib -lboost_system -lboost_filesystem -lboost_thread -lpthread -c src/CFetcher.cpp -o tmp/CFetcher.o
g++ -g ./tmp/main.o ./tmp/CLink.o ./tmp/CFetcher.o -I/usr/local/include/cpp-netlib -lboost_system -lboost_filesystem -lboost_thread -lpthread -o main
So for me all looks nice but when i try to run the program
./main
./main: error while loading shared libraries: libboost_system.so.1.46.1: cannot open shared object file: No such file or directory
The -l flags must come after the source files on linker command-line.
Yes, that means you'll have to split the LD definition to LD and LIBS, put all the -L and -l flags in the later and change the link command to:
$(LD) $(OBJ) $(LIBS) -o $#
The library (.so (dynamic) or .a (static)) files have to be the same version as the headers. While there are boost 1.46.1 headers installed in /usr/local/include/boost_1_46_1/, the corresponding library files don't seem to be installed at all. The only installed libraries are version 1.40.0 in /usr/lib, so the linker finds those (/usr/lib would be searched by default even if you didn't include the -L/usr/lib flag), but they don't contain the symbols expected by 1.46.1.
Note that when linking against shared library (using shared libraries is strongly recommended in Linux), the linker looks for the file with .so extension, but that is usually symlink to a file with added version suffix and the linker reads it and records the target name in the binary. That way programs compiled against the .1.40 will continue to work when 1.46 is installed, because the libboost*.so.1.40.0 may (and have to) stay around after the .so is redirected to the 1.46.1 version.
It should be even possible to install like:
/usr/local/lib/boost_1_46_1/libboost_system-mt.so -> /usr/local/lib/libboost_system-mt.so.1.46
/usr/local/lib/libboost_system-mt.so.1.46 -> /usr/local/lib/libboost_system-mt.so.1.46.1
/usr/local/lib/libboost_system-mt.so.1.46.1
and compile using -L/usr/local/lib/boost_1_46_1, though I currently can't find any package that would do it to confirm this. This way you could have development files for multiple versions installed and switch between them using explicit -I and -L flags while dynamic linker would still find the runtime files, for which it only looks in /usr/local/lib, /usr/lib and /lib (it can be configured in /etc/ld.so.conf, but that's the default).
Execute your application with strace. This will show the location were you app is looking for your boost libs. In my case an app was looking in /usr/lib/x86_64-linux-gnu for boost libs where the actual location was /usr/lib/lib. A simple export statement adding the paths for the boost shared libs in my case LD_LIBRARY_PATH=/usr/lib/lib worked a treat.
output from strace
open("/usr/lib/x86_64-linux-gnu/libboost_system.so.1.46.1", O_RDONLY) = -1 ENOENT (No such file or directory)
exit_group(127) = ?
Related
I'm currently developing a C++ application which will reference multiple *.so libraries, each containing code for different machines - written in C.
I also have one shared object containing code from a custom namespace Utilities, which (as the name implies) contains basic utilities useful for the application (written in C++, like the rest of the application).
Currently, utilities.so is the only (custom) library referenced by the application.
The application compiles and links just fine, however executing it on the target hardware display the following error: bin/updater_v4test: error while loading shared libraries: ../../../bin/device_modules/utilities.so.1.0.0: cannot open shared object file: No such file or directory
When calling LDD on said application, the following output is shown: ../../../bin/device_modules/utilities.so.1.0.0 => not found
I've written a script which (upon make exiting without errors) collects all SOs and pushes them in to the /lib/ directory on the target hardware; meaning that upon each successful build of the application (whether in part or entirely), the updated files are pushed to the correct directory on the target hardware.
In an attempt to mimic other libraries I've used (e.g. zlib), I've attempted to create a symlink to the library file, with no luck (utilities.so.1.0.0 is the symlink, utilities.so is the actual SO).
utilities.so.1.0.0 --> utilities.so
At the moment I'm at a loss, and I can't waste much more time in trying to figure this out myself.
Below is an excerpt from the utilities Makefile:
include ../../common/user.mk
LIB_DIR=../../../libs/lib/powerpc-linux-gnu
CFLAGS=-Wall -ggdb -I../../libs/include -I../../common -lpthread -lddc -std=c++0x -I../../libs/include/zlib
LDFLAGS=../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../libs/include/minizip/.libs/libminizip.so.1.0.0 \
-L ../../libs/lib \
-L ../../libs/lib/powerpc-linux-gnu \
-Wl,-rpath-link,../../libs/lib/powerpc-linux-gnu \
-lrt -lddc -lpthread -shared
BIN_DIR=../bin
CANONICAL_BIN_DIR := $(shell readlink -f $(BIN_DIR))
CANONICAL_CUR_DIR := $(shell readlink -f "./")
COMP_OBJECTS := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(wildcard *.cpp))
all: objects utilities.so
-cp --parents utilities.so $(GLOBAL_BIN_LIB)
-ln -s utilities.so utilities.so.1.0.0
-mv utilities.so.1.0.0 $(GLOBAL_BIN_LIB)
# -cp --parents *.h $(GLOBAL_HEADER_DIR)
-rm -f utilities.so
-rm -f *.o
for header in $(wildcard *.h); do \
echo $$header; \
ln -s $(CANONICAL_CUR_DIR)/$$header $(GLOBAL_HEADER_DIR)/$$header; \
done;
#printf "########## BUILT $^ ##########\n\n"
utilities.so: $(OBJECTS)
${CXX} $^ -o $# ${LDFLAGS}
objects: $(COMP_OBJECTS)
${CXX} -c $^ ${CFLAGS}
And now an excerpt from the application Makefile.
Here I've added a reference to the library in the linker flags, the header files are all included in from one directory.
include ../../../common/user.mk
LIB_DIR=../../../libs/lib/powerpc-linux-gnu
CFLAGS=-Wall -ggdb -I../../../libs/include -I${COMMON_DIR} -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I${HEADER_DIR}
LDFLAGS=../../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../../libs/include/minizip/.libs/libminizip.so.1.0.0 ../../../bin/device_modules/utilities.so.1.0.0 \
-L ../../../libs/lib \
-L ../../../libs/lib/powerpc-linux-gnu \
-Wl,-rpath-link,../../../libs/lib/powerpc-linux-gnu \
-lrt -lddc -lpthread -L ${SO_DIR}
BIN_DIR=../bin
CANONICAL_BIN_DIR := $(shell readlink -f $(BIN_DIR))
CANONICAL_CUR_DIR := $(shell readlink -f "./")
all: test_update.bin
-cp --parents test_update.bin $(BIN_DIR)
-ln -s $(CANONICAL_BIN_DIR)/test_update.bin $(GLOBAL_BIN_APP)/test_update.bin
-rm -f *.bin
#printf "########## BUILT $^ ##########\n\n"
test_update.bin: main.o updaterdelegate.o commonfunctions.o tinyxml.o
${CXX} $^ -o $# ${LDFLAGS}
####################
# Required Files #
####################
main.o: Main.cpp
${CXX} -c $^ -o $# ${CFLAGS}
updaterdelegate.o: UpdaterDelegate.cpp
${CXX} -c $^ -o $# ${CFLAGS}
commonfunctions.o: $(shell python -c "import os.path; print os.path.relpath('${IMPL_CMN_FUNC}'.replace('\"', ''), '${CANONICAL_CUR_DIR}'.replace('\"', ''))")
${CXX} -c $^ -o $# ${CFLAGS}
tinyxml.o: $(shell python -c "import os.path; print os.path.relpath('${IMPL_TXML}'.replace('\"', ''), '${CANONICAL_CUR_DIR}'.replace('\"', ''))")
${CXX} -c $^ -o $# ${CFLAGS}
####################
# /Required Files #
####################
Just for gits and shiggles, I'll add the build output of the utilities.so and application.
utilities.so:
(Clean ommitted)
=============== CLEAN COMPLETE... BUILDING... ===============
make: Entering directory `~/_workspace/upv4/common/utils'
powerpc-linux-gnu-g++ -c ArgumentHandling.cpp Extensions.cpp Logging.cpp -Wall -ggdb -I../../libs/include -I../../common -lpthread -lddc -std=c++0x -I../../libs/include/zlib
ArgumentHandling.cpp: In member function ‘void Utilities::ArgumentHandler::freeMemory()’:
ArgumentHandling.cpp:136: warning: deleting ‘void*’ is undefined
powerpc-linux-gnu-g++ ArgumentHandling.o Extensions.o Logging.o -o utilities.so ../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../libs/include/minizip/.libs/libminizip.so.1.0.0 -L ../../libs/lib -L ../../libs/lib/powerpc-linux-gnu -Wl,-rpath-link,../../libs/lib/powerpc-linux-gnu -lrt -lddc -lpthread -shared
cp --parents utilities.so """~/_workspace/upv4""/bin/device_modules"
ln -s utilities.so utilities.so.1.0.0
mv utilities.so.1.0.0 """~/_workspace/upv4""/bin/device_modules"
rm -f utilities.so
rm -f *.o
for header in ArgumentHandling.h Enumerations.h Extensions.h Logging.h; do \
echo $header; \
ln -s ~/_workspace/upv4/common/utils/$header """"~/_workspace/upv4""/bin/device_modules"/headers"/$header; \
done;
ArgumentHandling.h
Enumerations.h
Extensions.h
Logging.h
########## BUILT objects utilities.so ##########
make: Leaving directory `~/_workspace/upv4/common/utils'
=============== BUILD COMPLETE... PARSING... ===============
========== Warnings ==========
Total: 1
ArgumentHandling.cpp:136: warning: deleting ‘void*’ is undefined
========== Errors ==========
Total: 0
test_update.bin:
(Clean ommitted)
=============== CLEAN COMPLETE... BUILDING... ===============
make: Entering directory `~/_workspace/_workspace/upv4/test/app/src'
powerpc-linux-gnu-g++ -c Main.cpp -o main.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c UpdaterDelegate.cpp -o updaterdelegate.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c ../../../common/commonFunctions.cpp -o commonfunctions.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c ../../../common/xmlreader/tinyxml2.cpp -o tinyxml.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ main.o updaterdelegate.o commonfunctions.o tinyxml.o -o test_update.bin ../../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../../libs/include/minizip/.libs/libminizip.so.1.0.0 ../../../bin/device_modules/utilities.so.1.0.0 -L ../../../libs/lib -L ../../../libs/lib/powerpc-linux-gnu -Wl,-rpath-link,../../../libs/lib/powerpc-linux-gnu -lrt -lddc -lpthread -L """"~/_workspace/_workspace/upv4""/bin/device_modules""
cp --parents test_update.bin ../bin
ln -s ~/_workspace/_workspace/upv4/test/app/bin/test_update.bin """~/_workspace/_workspace/upv4""/bin"/test_update.bin
ln: failed to create symbolic link `~/_workspace/_workspace/upv4/bin/test_update.bin': File exists
make: [all] Error 1 (ignored)
rm -f *.bin
########## BUILT test_update.bin ##########
make: Leaving directory `~/_workspace/_workspace/upv4/test/app/src'
=============== BUILD COMPLETE... PARSING... ===============
========== Warnings ==========
Total: 0
========== Errors ==========
Total: 0
The build script is custom, I built it myself to rid myself of the entire make output when I don't need it, and it parses out all the errors and warnings.
Due to the issue, I have turned make output back on.
Did I miss something during compilation/linking of the library, or is something going wrong during the linking of the application?
I'm inclined to say it's during compilation/linking of the library - although I don't know what exactly is going wrong, as everything is compiling and linking just fine.
Why is the application looking for the .so file in a path it can't possibly have?
I also made sure that the .so files are found with the $PATH variable, so the application should be able to find them.
The system normally searches for shared objects in a fixed set of directories. You can handle around this by defining the environment variable LD_LIBRARY_PATH and adding the directory where you install the shared libraries into.
Or you can add those libraries to some of the standard libraries directories and execute ldconfig -a to update the cache of shared libraries.
See ldconfig(8), for more info.
edit
There are two mechanisms to load a shared object.
The first is the normal library loading mechanism, that specifies what has to be loaded at start executable time, and implies linking your executable with the shared objects. This is what you do in your Makefile. You specify the shared executables, and the ld.so.xxx shared object (which is linked to your application when you are dynamically linking it) loads and follows all the unresolved identifiers to find a place for them in the virtual address space. The ld.so.xxx object uses the /etc/ld.so.cache file, that is just a hash table with the directories and shared executables available to be loaded this way. That file is indexed by what is called the soname (which is something useful to allow different versions of the same library to coexist in the same system) and normally maps to the last versioned shared found in the list of directories listed in the file /etc/ld.so.conf (this is static information to accelerate the process of loading libraries and is generated at each boot of the system). If the shared was found at link time (this mechanism is not used by ld, but only to load the libraries at program start time) to have a soname, then that soname is searched in the /etc/ld.so.cache to find the final file that has to be loaded. This cache is built on each boot of the system, so you don't have to cope with that, but only if you don't want to reboot and you install a new library for system use. It is important to note that shared objects must be given sonames for this to work, and that the list of directories in the file /etc/ld.so.conf are the only directories used to search for files. This means that for a standard library to be usable, you need to put it in one of this directories (or add the directory to the list in /etc/ld.so.conf) and then execute ldconfig -a to rebuild the cache and let it include a reference for the file under that soname.
The other way it to add to the list of search places a list in the form of a PATH variable. The variable is LD_LIBRARY_PATH so, in case you have your shared objects in ${HOME}/libs, you can add this line to your .profile:
export LD_LIBRARY_PATH=${HOME}/libs
or
setenv LD_LIBRARY_PATH ${HOME}/libs
this allows your library to live outside of the standard directories, but think twice, as this is a far less efficient way to load a file (as it involves processing a list of directories to look for the final shared objects, while the previous approach is direct, you ask for the file matching the soname that ld.so.xxx asks for, only one search, only one step)
The second is to use a library function dlopen(3) that allow you to load a shared object and do some housekeeping before calling anything inside. The dl library allows you to search for a symbol in the shared executable and then decide if you interpret it as data or a jump target. dlopen() just opens and loads into the virtual address space a shared object. It resolves the dependencies (if requested to) and is the more flexible way (but it is also nontransparent) to load unknown code for execution. This is the way plugins normally work. You decide in a config file, or dynamically what to load, and then you load it. The program doesn't have to know previously the symbol table of what you are dealing with and you are free to implement whatever you want in the module you are loading.
All of these methods work with ELF binaries, so you have a lot of freedom, but also a lot of complexity on it.
more...
As i've seen from your compilation:
you are including -l in the compile only commands, the libraries are only needed if you are linking an executable, don't put libraries in the compile phase.
for a library to be searched and selected by the linker, it has to be named as lib<name>.so (without the version info at the end) so this means that you normally find three names for a standard library (let me use the math library -lm as an example):
/usr/lib/libm.so.3.2.8 # this is the ELF file with the library contents.
/usr/lib/libm.so.3 -> libm.so.3.2.8 # this is the soname used to create the library.
/usr/lib/libm.so -> libm.so.3 # this is the actual file the ld(1) program searches for when using -lm.
those links have to be created, as the system normally doesn't. This is part of the installation procedure for a shared library. The soname link allows you to have different versions of a library and detect which one of them will be used at runtime (all must be compatible so you can interchange, when you make an incompatible modification, then you have to change the soname, so the system doesn't get confused on loading)
It is very important to know that the ld(1) program only selects a library if it is called lib<name>.so, with no version info. Indeed, the compiler first searchs for lib<name>.so, then for lib<name>.a, then it complains.
It is very important to put -L places to search for libraries before any -l option that will use those directories in the linking parameters.
You only need to run ldconfig -a and install the library in a system directory if you are not going to use the LD_LIBRARY_PATH mechanism. (this mechanism doesn't work for root account, for obvious reasons :))
Expecting this added comments give some light to the process.
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
I have the following files in my proj2 directories and need to compile them together to have one executable file.
proj2/main.cpp
proj2/model/Player.cpp
proj2/model/gameBoard.cpp
proj2/controller/TTTController.cpp
proj2/Makefile
I'm using the following command inside my makefile, but it is not working.
all:
g++ /project2_p1/main.cpp /project2_p1/controller/TTTController.cpp /model/gameBoard.cpp /model/Player.cpp -o ttt
clean:
-rm ttt
Can anybody help me please.Thank you
I strongly recommend you start learning make as it is one of the fundamental tools that programmers use. And, if you can learn C++, you can definitely learn make.
In your project you have source files buried in their own subdirectories so in order to find them all you can use the $(shell find...) command. Same with any header files in your project.
By making all: the direct target it gets executed unconditionally and you lose the benefits of using make - only compile when you change something.
Having said that the basic template I am providing here could be improved to recompile only those source files that have changed but that's an exercise for the reader.
I think this should work in your case:
# set non-optional compiler flags here
CXXFLAGS += -std=c++11 -Wall -Wextra -pedantic-errors
# set non-optional preprocessor flags here
# eg. project specific include directories
CPPFLAGS +=
# find cpp files in subdirectories
SOURCES := $(shell find . -name '*.cpp')
# find headers
HEADERS := $(shell find . -name '*.h')
OUTPUT := ttt
# Everything depends on the output
all: $(OUTPUT)
# The output depends on sources and headers
$(OUTPUT): $(SOURCES) $(HEADERS)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(OUTPUT) $(SOURCES)
clean:
$(RM) $(OUTPUT)
thats my minGW project's makefile codes:
hepsi: derle calistir
Nesneler := ./lib/Hata.o ./lib/Hatalar.o ./lib/Dugum.o ./lib/ListeGezici.o ./lib/BagilListe.o
derle:
g++ -I ./include/ -o ./lib/Hata.o -c ./src/Hata.cpp
g++ -I ./include/ -o ./lib/Hatalar.o -c ./src/Hatalar.cpp
g++ -I ./include/ -o ./lib/Dugum.o -c ./src/Dugum.cpp
g++ -I ./include/ -o ./lib/ListeGezici.o -c ./src/ListeGezici.cpp
g++ -I ./include/ -o ./lib/BagilListe.o -c ./src/BagilListe.cpp
g++ -I ./include/ -o ./bin/test $(Nesneler) ./src/test.cpp
calistir:
./bin/test
In your project I think this will work;
all: compile run
Objects := ./lib/Player.o ./lib/gameBoard.o ./lib/TTTController.o
compile:
g++ -I ./include/ -o ./lib/Player.o -c ./model/Player.cpp
g++ -I ./include/ -o ./lib/gameBoard.o -c ./model/gameBoard.cpp
g++ -I ./include/ -o ./lib/TTTController.o -c .controller/TTTController.cpp
g++ -I ./include/ -o ./bin/main $(Objects) ./main.cpp
run:
./bin/main
lib folder contains .o files. You can chance it if you want.
include folder refers your header .h or .hpp files. You can change every one of them according to your headers location.
bin folder contains your .exe file called main.exe. You can change or remove it like that
run:
./main
I hope it'll work.
#Galik has right. if you want to learn C++, you should definitely learn make.
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 *~
I'm having trouble getting a sample program to link correctly (in this case against the ICU library). When I do 'make', everything builds fine. But when I run it, it says it can't find one of the .so's. I double checked they're all installed in /usr/local/lib. What I discovered was it was looking in /usr/lib. If I symlink from there to there actual location, it works.
Why is my LIBPATHS being ignored or not used?
Here is the Makefile
CC = g++
INCPATHS = -I/usr/local/include
CFLAGS = -c -Wall $(INCPATHS)
LIBPATHS = -L/usr/local/lib/
LIBS = $(LIBPATHS) -licuio -licui18n -licuuc -licuio -licudata
EXECUTABLE = prog
print_linking = echo -e "\033[32m" "Linking: $<" "\033[39m"
print_compiling = echo -e "\033[33m" "Compiling: $<" "\033[39m"
print_cleaning = echo -e "\033[31m" "Cleaning: `pwd`" "\033[39m"
all: main
# [target]: [dependencies]
# <tab> system command
main: main.o
#$(print_linking)
#$(CC) -o $(EXECUTABLE) main.o $(LIBS) >> /dev/null
main.o: main.cpp
#$(print_compiling)
#$(CC) $(CFLAGS) main.cpp
clean:
#$(print_cleaning)
#rm -rf *.o *~ $(EXECUTABLE)
Your LIBPATHS tells the linker where to find the library when linking to resolve symbols.
At runtime, you need to tell the loader where to find the library. It doesn't know about what happened at compile time. You can use the LD_LIBRARY_PATH variable as mentioned above, or check into /etc/ld.so.conf and it's friends.
The path to the dynamic libraries isn't stored in the executable by default. You can either:
use LD_LIBRARY_PATH at runtime to give a path where to search for dynamic libraries
use -Wl,-Rpath at link time to store a path in the executable
One solution is to add /usr/local/lib to the environment variable LD_LIBRARY_PATH.
You can do this in your .profile or .cshrc
You can also get the linker to store the full path to the library in the executable.
Both solutions have different tradeoffs with respect to using the execultable by different users and/or on different machines.