I'm trying to compile a small c++ program that captures an image from a camera using libv4l2 and then sends it over UDP to a separate computer using asio.
The file structure of the project is:
project/
dependencies/
asio/
cpp/
cpp_server/
cpp_client/
Makefile
src/
cpp_client.cpp
ImageClient.cpp
ImageClient.h
ImageProtocol.h
My Makefile for the project is:
CC=g++
CPP_FILES := $(wildcard src/*.cpp)
OBJ_FILES := $(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
LD_FLAGS := -L../../dependencies/asio/asio
INCLUDES := -I../../dependencies/asio/asio/include
CC_FLAGS := -Wall $(INCLUDES) -fpermissive -std=c++14 -DASIO_STANDALONE
client.exe : $(OBJ_FILES)
$(CC) $(LD_FLAGS) -o $# $^
obj/%.o: src/%.cpp
$(CC) $(CC_FLAGS) -c -o $# $<
However, when I try to compile this, my compiler spits on dozens of undefined reference errors for ASIO functions:
cpp_client.cpp:(.text+0x15dc): undefined reference to `asio::error::get_netdb_category()'
cpp_client.cpp:(.text+0x15ec): undefined reference to `asio::error::get_addrinfo_category()'
cpp_client.cpp:(.text+0x15fc): undefined reference to `asio::error::get_misc_category()'
obj/cpp_client.o: In function `asio::error::get_system_category()':
cpp_client.cpp:(.text._ZN4asio5error19get_system_categoryEv[_ZN4asio5error19get_system_categoryEv]+0x8): undefined reference to `asio::system_category()'
obj/cpp_client.o: In function `asio::detail::posix_tss_ptr<asio::detail::call_stack<asio::detail::thread_context, asio::detail::thread_info_base>::context>::posix_tss_ptr()':
cpp_client.cpp:(.text._ZN4asio6detail13posix_tss_ptrINS0_10call_stackINS0_14thread_contextENS0_16thread_info_baseEE7contextEEC2Ev[_ZN4asio6detail13posix_tss_ptrINS0_10call_stackINS0_14thread_contextENS0_16thread_info_baseEE7contextEEC5Ev]+0x20): undefined reference to `asio::detail::posix_tss_ptr_create(unsigned int&)'
obj/cpp_client.o: In function `asio::detail::posix_tss_ptr<asio::detail::call_stack<asio::detail::thread_context, asio::detail::thread_info_base>::context>::~posix_tss_ptr()':
cpp_client.cpp:(.text._ZN4asio6detail13posix_tss_ptrINS0_10call_stackINS0_14thread_contextENS0_16thread_info_baseEE7contextEED2Ev[_ZN4asio6detail13posix_tss_ptrINS0_10call_stackINS0_14thread_contextENS0_16thread_info_baseEE7contextEED5Ev]+0x1c): undefined reference to `pthread_key_delete'
obj/cpp_client.o: In function `asio::detail::posix_global_impl<asio::system_executor::context_impl>::~posix_global_impl()':
cpp_client.cpp:(.text._ZN4asio6detail17posix_global_implINS_15system_executor12context_implEED2Ev[_ZN4asio6detail17posix_global_implINS_15system_executor12context_implEED5Ev]+0x24): undefined reference to `asio::system_executor::context_impl::~context_impl()'
obj/ImageClient.o: In function `ImageClient::ImageClient(FHCamera, unsigned short, std::string const&, unsigned short)':
ImageClient.cpp:(.text+0x898): undefined reference to `asio::io_context::io_context()'
I imagine that the issue is that my Makefile still isn't properly finding ASIO and trying to compile it standalone. That said, I'm not really sure what else to try -- does anyone else have suggestions for what I need to do to get ASIO to compile standalone with a Makefile?
thanks!
The Standalone Asio library is a dependancy of your program. When building
a program, one does not also build the dependancies (unless in exceptional
circumstances). If that were necessary, then building almost any program would
recursively require probhibitively huge amounts of rebuilding dependencies.
If your program has a dependency on a library that is not provided packaged
by the package manager of your Linux distro then you must get the source package
of that library and build and install on your system as per its instructions.
Then you build your own program on the (true) assumption that your system satisfies
the library dependency. You do not repeat the building of the library dependency
in the building of your program.
The standalone moniker might have suggested to you that this library is
meant to be rebuilt in every application that uses it. It's not. It's
standalone asio in the sense that it's not itself dependent on any
boost libaries, unlike boost::asio, from it is derived. Standalone
doesn't even imply that the library does not have dependencies on other
non-boost libraries. E.g. amongst your linkage errors are some that
report undefined references from asio functions to pthread_key_delete,
which means asio is dependent on the Posix threads library, libpthread,
and you're not linking it.
The Standalone Asio library may well be provided by in a development package
by the package manager of your Linux distro. For example, Debian/Ubuntu distros
provide it in libasio-dev and you install it simply with:
sudo apt-get install libasio-dev
Investigate whether your distro does likewise, and if so install the library
with your package manager.
Otherwise you must install the library from source. It is a
GNU autotools source package,
so to build and install it you must have previously installed:
- GCC C++ toolchain
- GNU make
- GNU autotools (autoconf, automake at least)
Then:
Download the source tarball e.g asio-1.10.8.tar.bz2, from its
Sourceforge page and
extract the package directory, e.g. asio-1.10.8
cd into the the package directory and run:
$ autoreconf -i
$ ./configure
Errors from ./configure will indicate dependancies or other requirements
that your system does not satisfy. Fix and repeat until success. Then run
$ make
to build the package. If all is well, as root run:
$ make install
to install the package.
Once you have installed Standalone Asio either from a dev package or from
source, delete project/dependencies/asio and build your program
in project/cpp/cpp_client with a makefile like this:
Makefile
CXX=g++
SRCS := $(wildcard src/*.cpp)
OBJS := $(addprefix obj/,$(notdir $(SRCS:.cpp=.o)))
CXXFLAGS := -pthread
LDFLAGS := -pthread
#LDFLAGS := -L/path/to/your/libv4l2
#LDLIBS := -libv4l2
.PHONY: all clean
CXXFLAGS := -Wall -std=c++14 -DASIO_STANDALONE
all: client
client : $(OBJS)
$(CXX) $(LDFLAGS) -o $# $^ $(LDLIBS)
obj/%.o: src/%.cpp | obj
$(CXX) $(CXXFLAGS) -c -o $# $<
obj:
mkdir -p $#
clean:
rm -f obj/* client
For a rehearsal, I suggest using this makefile first to build the asio chat-client
that's provided in /asio-package-dir/src/examples/cpp11/chat. Put just chat_client.cpp
chat_message.hpp in your src folder for this.
Notice the commented out lines:
#LDFLAGS := -L/path/to/your/libv4l2
#LDLIBS := -lv4l2
You indicated that your program needs to be linked with library libv4l2
but your own makefile does not mention any such linkage. If you do need to
link with it then you must at least inform the linker of that fact by
uncommenting:
LDLIBS := -lv4l2
If you can install dev a package of this library from your package manager, do so. Otherwise
build and install it from source. Debian/Ubuntu does not provide such
a library package, although they do provide libv4l-0, libv4l-dev
and libv4l2rds0. Perhaps you're not precisely sure yet what library you need.
If you install this library from source and decide to install it in
some directory that is not one of the linker's default search paths
(/usr/lib, /usr/local/lib/ etc...) then you will also need to inform
the linker where it is, by uncommenting:
LDFLAGS := -L/path/to/your/libv4l2
Be aware that by adding libv4l2 to the linkage with -lv4l2, you
oblige the linker to find any other library that libv4l2
in turn depends on. So if your linkage now fails with undefined references
from libv4l2 to symbols in some other library libfoo, you need to
extend LDLIBS like:
LDLIBS := -lv4l2 -lfoo
and, if necessary, tell the linker where to find libfoo:
LDFLAGS := -L/path/to/your/libv4l2 -L/path/to/libfoo
And so on until the linkage succeeds.
In this light, you may wonder why the asio library doesn't similarly figure
in the linkage. No linker option -lasio needed? Your own makefile suggests that you
believe the linker needs to be told where to look for such a library, with
its setting:
LD_FLAGS := -L../../dependencies/asio/asio
though having told the linker to look there for libraries, you don't tell it link any
libraries at all.
No -lasio is needed because this library - untypically in general, but not
untypically for boost or boost-ish libraries - is a header only library.
It provides no shared object file libasio.so, nor any object file archive
libasio.a that you must link to get the definitions of functions. Instead,
they are wholly implemented by inline definitions in its header files. Thus,
any of them that you need to call in your program will be compiled straight
into it if you just #include <asio.hpp> in the source(s) file that make
those calls.
As it's a header only library, it is possible to use it to build your own
programs just by extracting the source package, skipping the usual autotools ./configure;
make;make install procedure, and setting up the preprocessor -I options
in your own makefile correctly (in CPPFLAGS - C PreProcessor Flags)
for it to locate the asio headers in, say,
/home/me/downloads/asio/asio-1.10.8. But if you were aiming to achieve
that, you made some mistake(s) en route; and if a package is autotooled -
as asio is - then all bets are off if you try to use it except as provided by the autotools
installation procedure. Installing a library in your system also has
the upside that once you've done it, you can forget about setting up peculiar
compiler and linker options in every project that uses it and the
like of /home/me/downloads/asio/asio-1.10.8 doesn't need become a
fixture of your home directory.
Your makefile and what you say about its problems suggests that you're
trying to use GCC and GNU Make by guesswork, trial and error. Here is
a fairly good starter tutorial in the use of those tools.
For authoritative documentation, here is the GNU Make manual and
here is the GCC manual
Incidentally, in Linux an executable is distinguished simply by its file
attributes and not by having an .exe extension as in Windows, so
your program target can and normally would be called simply client, not client.exe. The linker will make it executable when it creates it.
You are getting errors because on the link step you didn't supply all symbols (global variables or functions) needed to generate the final executable file.
You either need to add the ASIO library to the link step or, as your Makefile suggests by defining the ASIO_STANDALONE macro, need to include ASIO's standalone header in one of your source files to compile it.
Related
I have a project directory structure of:
Root
Source
Common
MyFolder
++ My 3 source files and header
When I am building my project it generates 3 to 4 shared libraries. Lib1 compiled using c++98 and others using c++11. Flags are added in CmakeList.txt which is at root.
I need my 3 source files to be compiled for Lib1 and for other Libs as as well. but here what happens is compiler is first compiling my source file for lib using c++11 and then it is trying to use same .o file for Lib1 as well. So for .o file which is generated using c++11 is throwing exception when same is used for c++98 compiled library.
So how do write this in CmakeList.txt such that compiler rather than trying to use same .o file will compile source file again for Lib1(c++98 compiled library)
Is there any flag I can specify so that it won't take precompiled .o file and will compile it again ?
Here flags are not being overridden for different shared libraries but actually same object file by make file is being used for different flags
This is sort of counter to how makefiles and cmake usually work.
Most users consider it really important that make performs an incremental build.
The usual way with makefiles is to do make clean which is supposed to remove any binaries and object files that were created.
However, sometimes I write cmake scripts that use globbing over the source directory to assemble the project. (That means, it says "just grab all *.cpp files in the /src folder and make an executable from them".) A makefile cannot check what files in a directory, so the make build will be broken after I add a new file, and make clean won't fix it -- the whole makefile will need to be regenerated by cmake.
Usually what I do is, I write a simple bash script, named rebuild.sh or something,
#!/bin/bash
rm -rf build
mkdir build
cd build
cmake ..
make -j3
./tests
And I put that in the root of my repository, and add /build to my .gitignore. I call that when I want to do a full rebuild -- it nukes the build directory, so its foolproof. When I want an incremental rebuild, I just type make again in the /build directory.
The rebuild.sh script can also serve a double purpose if you use travis-ci for continuous integration.
Most build system assume the compiled objects remain the same within the same pass. To avoid shooting your foot I would suggest telling the build system they were actually different objects, while still compiled from same source files.
I'm not familiar with cmake but this is how you do with make:
For example you have a a.cpp which you want to compile 2 times for different compiler options:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf ("Hello %d\n", TOKEN);
return 0;
}
And the Makefile would looks like:
SRC := $(wildcard *.cpp)
OBJ_1 := $(patsubst %.cpp,%_1.o,$(SRC))
OBJ_2 := $(patsubst %.cpp,%_2.o,$(SRC))
all: pass1 pass2
pass1: $(OBJ_1)
gcc -o $# $(OBJ_1) -lstdc++
pass2: $(OBJ_2)
gcc -o $# $(OBJ_2) -lstdc++
%_1.o: %.cpp
gcc -DTOKEN=1 -c $< -o $#
%_2.o: %.cpp
gcc -DTOKEN=2 -c $< -o $#
clean:
rm -f $(OBJ_1) $(OBJ_2)
What I do here is generate two different list of object from the same source files, which you can even do the same for dependency(-MMD -MP flags).
Platforms tested: Linux Mint 17, Ubuntu 14.04
Full example: this repository.
What am I doing and why?
I'm trying to build an R package which wraps a subset of the CAF library using Rcpp and RcppEigen.
I have successfully linked an R package to a system level install of CAF (example here) (Note: ABSEIR no longer uses CAF, 2/5/2015), but I'd like to have a good way to deploy CAF to machines without administrator access, and as a result simplify the installation of other CAF dependent packages (yes, I'm aware that R doesn't directly support linking against other compiled packages, but it seems like others have successfully circumvented this limitation).
What's the problem?
I'm building two shared objects during package compilation in addition to the package shared object (RcppCAF.so): libcaf_core.so and libcaf_io.so. These are successfully compiled and linked, but the package fails to load, claiming:
** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) :
unable to load shared object '/home/grantbrown/R/x86_64-pc-linux-gnu-library/3.2/RcppCAF/libs/RcppCAF.so':
librcaf_core.so: cannot open shared object file: No such file or directory
What have I tried?
In addition to numerous failed Makevars configurations, I've found that
if I manually set LD_LIBRARY_PATH to the folder containing the compiled code, the package will successfully install. Obviously, I'd like to avoid this step by finding a way to tell R where to look for these dependencies. I have attempted to use the inst folder for this purpose to no effect. My Makevars file is as follows:
ROOT_DIR := $(abspath .)
$(info The compilation root directory is: $(ROOT_DIR))
$(info The name of the shared library to be created is: $(SHLIB))
$(info The place R should look for librcaf_core.so is: $(abspath ./libcaf_core))
$(info The place R should look for librcaf_io.so is: $(abspath ./libcaf_io))
SOURCES = $(wildcard ./*.cpp)
SOURCES1 = $(wildcard ./libcaf_core/*.cpp)
SOURCES2 = $(wildcard ./libcaf_io/*.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
OBJECTS1 = $(SOURCES1:.cpp=.o)
OBJECTS2 = $(SOURCES2:.cpp=.o)
PKG_CPPFLAGS+= -std=c++11 -Dlibcaf_core_shared_EXPORTS -Wall -pedantic -pthread -fPIC -O2 -g -fPIC -I../inst -I../inst/libcaf_core -I../inst/libcaf_io
PKG_LIBS += -L$(abspath ./libcaf_core) -lrcaf_core -L$(abspath ./libcaf_io) -lrcaf_io
all: $(SHLIB)
$(SHLIB): $(OBJECTS) libcaf_core/librcaf_core.so libcaf_io/librcaf_io.so
libcaf_core/librcaf_core.so: $(OBJECTS1)
g++ -o libcaf_core/librcaf_core.so $(OBJECTS1) $(PKG_CPPFLAGS) -shared
libcaf_io/librcaf_io.so: $(OBJECTS2)
g++ -o libcaf_io/librcaf_io.so $(OBJECTS2) $(PKG_CPPFLAGS) -shared
There are a lot of threads on StackOverflow and mailing lists which deal with problems loading shared objects, but I couldn't find anyone with precisely the same issue. I've even done similar things in the past with no issues, so I'm having trouble figuring out why R can't find my shared objects. Any suggestions?
Edit
Dirk has suggested compiling to a single shared object, which I'm now working on. In the "Using Makevars" section of "Writing R Extensions", however, it does seems to imply that building dependencies should be possible:
"If you want to create and then link to a library, say using code in a subdirectory, use something like
.PHONY: all mylibs
all: $(SHLIB)
$(SHLIB): mylibs
mylibs:
(cd subdir; make)
"
The easiest approach, which you also seem to have found as per your most recent commit is to just have R 'glue' all object code into a single shared library.
That tends to "just work" but it is a little costly as the library needs to be rebuilt. We could look into packaging CAF as an external library which would make RcppCAF more lightweight.
Gooday everyone
I'm fairly new to ubuntu C programing although I'm
rather experienced in C programing in windows.
I have recently come accross a number of codes written
in 2005 which I'm interested in learning how they work.
Those codes needs BOOST library to compile, however they won't
compile on the newest BOOST version present on my ubuntu 12.04.
I set the gcc compiler on lenient so that it ignores all those error
messages. The code did compile and ran afterwards.
However, when I used GDB debugger to watch how the program flows
I noticed that there are likely errors in the way the program runs
due to using a different BOOST version rather than it's original. Hence
I like to install the BOOST version corresponding to the code I downloaded.
To do that, I installed Ubuntu 5.04 and BOOST 1.33.0 which seemed to have been created in late 2005. I downloaded it
but I didnt found any detailed instruction on how to install it.
Only vague description on using BOOST jam, I played around with BOOST
jam for quite awhile without success.
And this old BOOST does not have installation commands like
"sudo apt-install boost-dev" style option
Thus I like to ask if anyone can give a easy to understand step by step instruction
on how to install the BOOST library downloaded from the above link.
like.....
step1: download boost jam from boost webpage
step2: unpack it in home/boost/ then type make configure
...and so on...
Big thanks for any useful info.
New Contents appended here
in response to the comments given
Hi, I went through the info given by your link and
managed to run the boost library examples given by your link.
That is, I can compile a single cpp file with the command
g++ -I boost_1_33_0 test.cpp -o test
(I'm keeping the boost library and the cpp file to be compiled in the
same folder)
However, the program package I'm interested in is build with make (not cmake).
I have some experience writting cmake files but not make files.
And I do not see any link to boost library command in the make file of the
program package. The readme file only has one sentence that says I
need to have boost installed without explaining what that meant.
I assume it means that either I have to build and do makeinstall the boost or
I could add some lines in the makefile for a link. I thought
maybe you can quickly point out whats missing in the makefile.
The readme file:
To compile, go into the moses directory and do 'make'. You'll need the
latest boost libraries. If compilation still fails for weird reasons,
you could try g++ with the -fpermissive (newer versions reject lots of
code that was ok with older ones). If you are going to be making
changes and recompiling frequently you'll probably want to disable -O3
in the makefile (I use templates liberally, so -O3 really speeds up
the code, but really slows down compilation).
And the makefile:
CC = g++
PROJ_NAME = moses
LINK_FLAGS = -Wall -Iutils/ -Itrees/ -Irewrite -I./ -Imodeling/ -Ifitness/ \
-Ialignment/ -Isim/ -Ilocal/ -O3
COMP_FLAGS = -Wall -Wno-sign-compare -Iutils/ -Itrees/ -Irewrite -I./ \
-Imodeling/ -Ifitness/ -Ialignment/ -Isim/ -Ilocal/ -O3
src := $(wildcard *.cc) $(wildcard utils/*.cc) $(wildcard trees/*.cc) $(wildcard modeling/*.cc) $(wildcard fitness/*.cc) $(wildcard alignment/*.cc) $(wildcard main/*.cc) $(wildcard rewrite/*.cc) $(wildcard sim/*.cc) $(wildcard local/*.cc)
obj := $(patsubst %.cc,%.o,$(src))
all: $(PROJ_NAME)
%.o: %.cc
$(CC) $(COMP_FLAGS) $< -c -o $#
$(PROJ_NAME): $(obj)
$(CC) $(LINK_FLAGS) $^ -o $(PROJ_NAME)
run:
$(PROJ_NAME)
clean:
find -regex ".*~\|.*\.o"|xargs rm -f
rm -f $(PROJ_NAME)
rm -f $(PROJ_NAME).exe*
depend:
makedepend -Y -- $(COMP_FLAGS) -- $(src)
utils/exceptions.o: utils/exceptions.h utils/utils.h
utils/io_util.o: utils/io_util.h utils/tree.h utils/basic_types.h
# ......lots more lines like that.........
I have an old instruction flying around here for Boost 1.34.1, which reads like this (project-specific stuff cut away):
unpack boost sources
cd into tools/jam/src
run ./build.sh to build bjam
cd into the main source directory
tools/jam/src/bin.linux/bjam threading=multi --layout=system --toolset=gcc --without-python variant=release --prefix=/usr/local install
The --without-python was necessary as the target system didn't have Python installed, which caused the build to fail messily.
Obviously you can / need to fiddle with the individual settings (like threading support, release vs. debug variant) to suit your needs, but it should be a good starting point.
If you need ICU support (for Boost.Regex and Boost.Locale), it gets more complicated...
Note that the build process has changed over the years; you shouldn't use the same procedure for more up-to-date boost versions. It's just what I used back then.
Edit:
As for the second part of your question, the Makefile doesn't need to refer to Boost explicitly if boost is installed in the standard system directories.
You do not have to state -I /usr/include for compilation as that is searched automatically; the same goes for -L /usr/lib during linkage.
The fact that the author of the Makefile copied the compiler flags into the linker flags verbatim doesn't really help intuitivity either... ;-)
If you have Boost in a custom directory (either the headers only, or by stating a custom directory in the --prefix option of my build instructions), you need to make the following modifications (look for "boost"):
LINK_FLAGS = -Wall -Iutils/ -Itrees/ -Irewrite -I./ -Imodeling/ -Ifitness/ \
-Ialignment/ -Isim/ -Ilocal/ -L /path/to/boost/libs -O3
COMP_FLAGS = -Wall -Wno-sign-compare -Iutils/ -Itrees/ -Irewrite -I./ \
-Imodeling/ -Ifitness/ -Ialignment/ -Isim/ -Ilocal/ \
-I /path/to/boost/includes -O3
That should do the trick. As the Makefile does not link any of the Boost binaries (e.g. -l boost_program_options or somesuch), it seems that it makes use of the Boost headers only, which would make the -L /path/to/boost/libs part (and, actually, the whole compilation step detailed above) superfluous. You should be able to get away with simply unpacking the sources and giving the header directory as additional include directory using -I /path/to/boost/headers.
I have a Makefile for a c++ Linux project:
MODE ?= dbg
DIR = ../../../../../somdir/$(MODE)
SRC_FILES = a.cpp b.cpp
H_FILES = a.h
LDFLAGS += -L$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
CPPFLAGS = -I$(DIR)/include
LIBRARIES = -lsomeso
ifeq (rel, $(MODE))
CFLAGS = -Wall -g -DNDEBUG
else
CFLAGS = -Wall -ansi -pedantic -Wconversion -g -DDEBUG -D_DEBUG
endif
sample: $(SRC_FILES) $(H_FILES) Makefile
g++ $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LIBRARIES) $(SRC_FILES) -o sample
when i run 'make' it builds the project, with no errors.
but when i run the project it complains that:
error while loading shared libraries: libsomeso.so: cannot open shared object file: No such file or directory
The path that i give in DIR goes to the folder where the shared object is held(relatively to where the makefile is placed), and if it was the wrong path why didn't it complain during the make process.
does someone know what am i missing?
Thanks
Matt
LDFLAGS += -L$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
The above should be:
LDFLAGS += -L$(DIR)/lib/linux -Wl,-R$(DIR)/lib/linux '-Wl,-R$$ORIGIN'
That is, for each non-standard dynamic library location -L a corresponding -Wl,-R should be specified. $ORIGIN is needed to locate dynamic libraries relative to the executable, not sure if you need it here.
People often advise using LD_LIBRARY_PATH. This is a bad advice, in my opinion, because it makes deployment more complicated.
When you run your application, location of libsomeso.so should be in LD_LIBRARY_PATH environment variable. Try running program like this:
LD_LIBRARY_PATH="path_to_libsomeso_so:$LD_LIBRARY_PATH" myprogram
Here path_to_libsomeso_so is full path to a directory where libsomeso.so is located, and myprogram is your program executable. Note, that you should specify path to a directory containing libsomeso.so, not to libsomeso.so file itself.
The trouble is not during compilation time. Everything goes fine. There's a problem at runtime.
Indeed, your program has been linked with a shared object library. Therefore, at runtime, it need to load this shared object file. During compilation, you instructs the compiler where this file was with the -L flag.
For the runtime, you have to set the LD_LIBRARY_PATH environment variable to point to the directory where your libsomeso.so file resides.
Alternatively, you can place this file in one of the standard directory where these shared object files are searched for: /usr/local/lib, /usr/lib, /lib, but this should be what you'll do for the final distributed version of your library.
As told from Maxim Egorushkin, LD_LIBRARY_PATH is a bad choice. Meanwhile, using -L$(your lib path) -l$(your lib name) gcc/g++ argument to link shared library isn't a good choice. Because, after build the exe, you should told exe where the shared library directory is. By default, executable file only search shared library at /usr/lib or /usr/local/lib. Although, you have told makefile where the shared library is when build the executable file. But when you execute this exe file, they are different.
However, link static library don't have such problem.
So, the best way to deal with your problem is change the way you link your custom shared file. Like this:
DYNAMIC_LIB_DIR = ../lib (your lib path ,this is a example)
OBJLIBS = xxx.so (your lib name)
gcc/g++ -o exe_name sourcefile/object_file $(DYNAMIC_LIB_DIR)/$(OBJLIBS)
Refresh that dynamic library cache!
After adding a custom, non-standard library to /usr/local/lib, first check that /usr/local/lib is listed under /etc/ld.so.conf.d/libc.conf.
Then, finish off with a dynamic link library cache refresh:
$ sudo ldconfig
I am running Windows 7 with gcc/g++ under Cygwin. What would be the Makefile format (and extension, I think it's .mk?) for compiling a set of .cpp (C++ source) and .h (header) files into a static library (.dll). Say I have a variable set of files:
file1.cpp
file1.h
file2.cpp
file2.h
file3.cpp
file3.h
....
What would be the makefile format (and extension) for compiling these into a static library? (I'm very new to makefiles) What would be the fastest way to do this?
The extension would be none at all, and the file is called Makefile (or makefile) if you want GNU Make to find it automatically.
GNU Make, at least, lets you rely on certain automatic variables that alone give you control over much of the building process with C/C++ files as input. These variables include CC, CPP, CFLAGS, CPPFLAGS, CXX, CXXFLAGS, and LDFLAGS. These control the switches to the C/C++ preprocessor, compiler, and the linker (the program that in the end assembles your program) that make will use.
GNU Make also includes a lot of implicit rules designed to enable it automatically build programs from C/C++ source code, so you don't [always] have to write your own rules.
For instance, even without a makefile, if you try to run make foobar, GNU Make will attempt to first build foobar.o from foobar.c or foobar.cpp if it finds either, by invoking appropriate compiler, and then will attempt to build foobar by assembling (incl. linking) its parts from system libraries and foobar.o. In short, GNU Make knows how to build the foobar program even without a makefile being present -- thanks to implicit rules. You can see these rules by invoking make with the -p switch.
Some people like to rely on GNU Make's implicit rule database to have lean and short makefiles where only that specific to their project is specified, while some people may go as far as to disable the entire implicit rule database (using the -r switch) and have full control of the building process by specifying everything in their makefile(s). I won't comment on superiority of either strategy, rest assured both do work to some degree.
There are a lot of options you can set when building a dll, but here's a basic command that you could use if you were doing it from the command line:
gcc -shared -o mydll.dll file1.o file2.o file3.o
And here's a makefile (typically called Makefile) that will handle the whole build process:
# You will have to modify this line to list the actual files you use.
# You could set it to use all the "fileN" files that you have,
# but that's dangerous for a beginner.
FILES = file1 file2 file3
OBJECTS = $(addsuffix .o,$(FILES)) # This is "file1.o file2.o..."
# This is the rule it uses to assemble file1.o, file2.o... into mydll.dll
mydll.dll: $(OBJECTS)
gcc -shared $^ -o $# # The whitespace at the beginning of this line is a TAB.
# This is the rule it uses to compile fileN.cpp and fileN.h into fileN.o
$(OBJECTS): %.o : %.cpp %.h
g++ -c $< -o $# # Again, a TAB at the beginning.
Now to build mydll.dll, just type "make".
A couple of notes. If you just type "make" without specifying the makefile or the target (the thing to be built), Make will try to use the default makefile ("GNUMakefile", "makefile" or "Makefile") and the default target (the first one in the makefile, in this case mydll.dll).