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:
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 $@ $^
$(CC) $(CC_FLAGS) -c -o $@ $<
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()'
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
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
asio is dependent on the Posix threads library,
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)
Download the source tarball e.g
asio-1.10.8.tar.bz2, from its
Sourceforge page and
extract the package directory, e.g.
cd into the the package directory and run:
$ autoreconf -i $ ./configure
./configure will indicate dependancies or other requirements
that your system does not satisfy. Fix and repeat until success. Then run
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
project/dependencies/asio and build your program
project/cpp/cpp_client with a makefile like this:
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
that's provided in
/asio-package-dir/src/examples/cpp11/chat. Put just
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
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
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
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/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
oblige the linker to find any other library that
in turn depends on. So if your linkage now fails with undefined references
libv4l2 to symbols in some other library
libfoo, you need to
LDLIBS := -lv4l2 -lfoo
and, if necessary, tell the linker where to find
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
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.
-lasio is needed because this library - untypically in general, but not
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
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
make;make install procedure, and setting up the preprocessor
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 -
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
/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.exe. The linker will make it executable when it creates it.