C++: get Boost working; questions on include path and linking library - c++

I was trying to use Boost.Tokenizer library. In my PROG.cpp, I have the following:
#include <boost/tokenizer.hpp>
And my Makefile was initially something like
CXX = g++-4.8
CXXFLAGS = ## some irrelevant flags
LDFLAGS = ## some irrelevant flags
SOURCES = PROG.cpp
OBJECTS = $(SOURCES:.cpp=.o)
TARGETS = PROG
$(TARGETS) : $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
## other targets
It won't compile, since boost/tokenizer.hpp cannot be found:
fatal error: boost/tokenizer.hpp: No such file or directory
Then I manually added the boost include path to CXXFLAGS:
-I/opt/local/include/
(which is the path from MacPorts.)
Then I tried to include the Tokenizer library, but in /opt/local/lib/ I have libboost_atomic-mt.dylib, libboost_chrono-mt.dylib, etc., but nothing like tokenizer. I was rather confused at the time. I supposed that still wouldn't work since the library was not linked against. Surprisingly, the program built, linked, and ran perfectly.
So I'm really confused now. Here are some questions:
(1) I did not link against boost explicitly, so boost is treated like standard library by the linker?
(2) If boost is treated like standard, why the headers are not standard?
(3) Why there are libboost_atomic-mt.dylib, libboost_chrono-mt.dylib, etc. but not tokenizer? Which dynamic library does tokenizer belong to?
I'm not very familiar with g++ linking mechanism; speaking of boost, this is my very first program with boost. So I'd really appreciate detailed explanation. Thanks in advance!
For reference, this is what I extracted by gcc -print-search-dirs:
install: /usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/
programs: =/usr/gcc-4.8.0/libexec/gcc/x86_64-apple-darwin12.3.0/4.8.0/:/usr/gcc-4.8.0/libexec/gcc/x86_64-apple-darwin12.3.0/4.8.0/:/usr/gcc-4.8.0/libexec/gcc/x86_64-apple-darwin12.3.0/:/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/:/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/:/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/../../../../x86_64-apple-darwin12.3.0/bin/x86_64-apple-darwin12.3.0/4.8.0/:/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/../../../../x86_64-apple-darwin12.3.0/bin/
libraries: =/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/:/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/../../../../x86_64-apple-darwin12.3.0/lib/x86_64-apple-darwin12.3.0/4.8.0/:/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/../../../../x86_64-apple-darwin12.3.0/lib/:/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/../../../x86_64-apple-darwin12.3.0/4.8.0/:/usr/gcc-4.8.0/lib/gcc/x86_64-apple-darwin12.3.0/4.8.0/../../../:/lib/x86_64-apple-darwin12.3.0/4.8.0/:/lib/:/usr/lib/x86_64-apple-darwin12.3.0/4.8.0/:/usr/lib/

Most of the boost libraries, are just header files, if you look in the .hpp files you will not see just the declaration of the classes, like you would expect in a header file, but actually the entire implementation. This is why for 90% of the boost libraries, you don't need to worry about linking, only inclusion.
However for a few libraries, serialiser, a few others, there is just too much polluting code for the header inclusion method to be reasonable. I'm sure there is a better, more rigid definition about when the implementation is included in the header and when it isn't.
http://www.boost.org/boost-build2/doc/html/bbv2/faq/header-only-libraries.html
Here is another question about it:
Why are not all boost libraries header-only?
p.s.
Generally it is better to keep the boost library separate and in your makefile do something like:
For compilation:
CXXFLAGS += -I/path/to/boost/include
For Linking:
LDPATH += -L/path/to/boost/lib
This makes it easier to upgrade your boost version as you just have to change the path in one place.

Related

Compiling standalone ASIO with Makefile on Linux

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.

Makefile Dependencies, What Should Be a Dependency?

I have a conceptual question regarding makefile dependencies and this is because I see inconsistency online about this.
Let's say I have the following files:
main.cpp uses-> my_math.cpp and my_strings.cpp
my_math.cpp uses-> my_math.h
my_strings.cpp uses-> my_strings.h
If I have a makefile, with the general outlay of:
program: $(all_objs)
g++ $(all_objs) -o program
main.o: ...
.......
my_math.o: ...
.......
my_strings.o: ...
.......
I don't know what should go into each dependency. Like, math.o #includes my_math.h and my_strings.h, does that mean that main.cpp needs to recompile if I change my_math.h? But why? It uses it like a library, right? It doesn't need to recompile main.cpp or does it?
As in, should the result for main.o be:
1) main.o: main.cpp
gcc -c main.cpp
2) main.o: main.cpp my_strings.cpp my_strings.h my_math.cpp my_math.h
gcc -c main.cpp
3) main.o: main.cpp my_strings.cpp my_strings.h my_math.cpp my_math.h
gcc -c main.cpp my_strings.cpp my_math.cpp
I'm a bit lost on dependencies and how linking works.
Any help would be appreciated! Thank you!
The dependencies are everything whose change requires recompiling the source code. That includes not only your #include-d headers, but also the indirectly included system headers, and even (in principle) the compiler and build chain itself (when you upgrade your C++ compiler, you should recompile all your software). If some of your C++ code is generated from some source (e.g. by tools like GNU bison or Qt moc, or by your own script), both the sources and the generating tools are dependencies. Read also about package managers.
Practically speaking, the GCC compiler is able to output most make dependencies, notably with -M and related processor options. Read also about auto dependencies generation. See also this.
(in practice, you generally don't code in your Makefile some explicit dependency on the compiler itself; but you should not forget to make clean when the compiler has been upgraded)
Unless your main.cpp is including my_strings.cpp (which is not conventional and is very bad taste), your make rule won't have a dependency from my_strings.cpp to main.o. But probably your main.cpp is #include-ing (directly or indirectly) my_strings.h so main.o should depend not only on main.cpp but also on my_strings.h
As a rule of thumb, your object file my_strings.o depends on the source file my_strings.cpp and all the header files which are directly or indirectly #include-d in it. Your main program executable depends on all its object files and the libraries you are linking into it. Order of program arguments to g++ matters a lot.
It uses it like a library, right?
From what you are showing, you don't have any own libraries (but you probably use the standard C++ library, and perhaps some other system libraries). On Linux these are lib*.a files (static libraries) or lib*.so files (shared libraries). A library is an organized agglomeration of object code -and sometimes other resources.
I'm a bit lost on dependencies and how linking works.
Understand the difference between source code files, object files (they contain relocation information) and executables (on Linux, object files and executable files and shared libraries are using the ELF format). Read also about the role of compilers, linkers (the g++ program can run both) & build automation (for which you are using make).
Read Program Library HowTo and much more about translation units and linkers (& name mangling), notably Levine's book on Linkers & loaders.
See also this & that & this (examples about Makefile for C++ programs).
BTW, you should use g++ (not gcc) when compiling C++ code. There are significant differences (even if gcc is sometimes able to compile C++ or Fortran code, you'll mostly use gcc to compile C code). And (assuming you use specifically GNU make) your Makefile should mention $(CXX) (not g++). You need to understand the builtin rules of make (run once make -p to get them) and you'll better take advantage of them (e.g. use $(COMPILE.cc) or $(COMPILE.cpp) etc...). You certainly should pass -Wall -Wextra (to get all warnings, and even more), and -g (to get debugging information) to g++. Practically speaking, you should set your CXXFLAGS variable in your Makefile.
Take time to carefully read GNU make documentation and Invoking GCC.
Look into the Makefile-s of existing free software projects. For various reasons, some projects are generating their Makefile-s with tools like autoconf or cmake. But most simple projects don't need that generality, and you should be able to write your own Makefile for your C++ projects. Of course, take inspiration from existing code.
If you have
main.cpp uses-> my_math.cpp and my_strings.cpp
my_math.cpp uses-> my_math.h
my_strings.cpp uses-> my_strings.h
The purpose of Make is to maintain dependency between modules in two different ways, by building .o files and by linking .o files.
you can picture it as a dependency tree where main.o is the root
main.o
/ \
my_math.o my_strings.o
for each .o there is also a dependency tree with regard to source files e.g.
main.o my_math.o my_strings.o
/ \ / \ / \
main.cpp main.h my_math.cpp my_math.h my_strings.cpp my_strings.h
So when make builds, it sets up a dependency tree with main.o at its root and then tries to build all .o files needed for main. When all .o files have been built they are linked.
By following the dependency tree Make ensures that main will be linked/built when one of the dependent modules is changed.
However if you have used something like say a constant from one of the included headers #define MAXSTRING 32 you are no longer merely dependent on the .o file, you are then dependent on the header content so you need to make sure that main.o is built if the header is changed since linking is then not enough so you add the .h in the dependency
main.o
/ | \
my_math.o my_strings.o my_strings.h
Of course there are ways to make the header more robust to avoid that dependency but is another question.
Your cpp files do not depend on other cpp files in terms of compilation. Simple cpp file should only depend on h files.
In your question you say main.cpp depends on my_math.cpp and my_strings.cpp, but I think it is not true. I can guess you have #includes there and these are your dependecies.
Generally speaking dependencies for cpp files are all #included h files.
Usually there are no dependencies between cpp files. You just generate o files by compiling them. Then your final binary depends on all o files.

How to use a library with headers and .so files?

I'm new to C and wanted to use a library (MLT Multimedia Framework)
I've built it and it produced the following directories: include lib share
Inside lib there are .so .a .la files
Inside include there are .h files
Now, I'm instructed to do this:
#include <framework/mlt.h> which is inside include/mlt/framework/
Questions:
Why I do I need to place the header file that contains only function prototypes? Where are the real functions then? are they linked someway to the ones included in lib directory?
Where to place my own files and how to compile it?
How to learn more about the topics:
Dynamic/Static libraries
Building / making / installing
How to use any C library
If you don't have the function prototypes, how would the compiler know what functions exist in the library? Short answer is: It doesn't. Longer answer: The compiler doesn't care about library files, static (files ending in .a) or shared (files ending in .so), all it cares about is the current translation unit. It's up to the linker to handle resolving undefined references.
When you use libraries, you include the header files that contain the needed declarations (structures, classes, types, function prototypes) into the source file. The source file plus all included header files forms the translation unit that the compiler uses to generate code. If there are undefined references (for example a call to a function in the library) the compiler adds special information about that to the generated object file. The linker then looks through all object files, and if it finds an unresolved reference it tries to find it in the other object files and the provided libraries. If all definitions are resolved the linker generates the final executable, otherwise it will report the unresolved definitions as errors.
To answer your other questions:
Where to place my own files and how to compile it?
This is two questions, the answer to the first one (about placement of your files) is that it doesn't really matter. For small project with only a few source and header files, it's common to place all files in a common project directory.
The second question, about compiling, there are different ways to do it too. If there are only one or two source files you could use the compiler frontend (e.g. gcc) to compile and link and generate your executable all in one go:
$ gcc -Wall -g source1.c source2.c -o your_program_name
The above command takes two source files, compiles and links them into the program your_program_name.
If you need to use a library, there are one or two things that you need to add to the above command line:
You need to tell the linker to link with the library, this is done with e.g. the -l (lower case L) option:
$ gcc -Wall -g source1.c source2.c -o your_program_name -lthe_library
It's important to note that the_library is the base name of the library. If the library file is named libthe_library.so then only the_library part is needed, the linker will add the other parts automatically.
If the library is not in a standard location, then you need to tell the compiler and linker where the library file are. This is done with the -I (capital i) option to tell the preprocessor where the header files are, and the -L (capital l) where the linker files are.
Something like
$ gcc -Wall -g -Ilocation/of/headers source1.c source2.c -o your_program_name -Llocation/of/libraries -lthe_library
If you have more than a couple of source files, it's common to use so called makefiles that lists all source files, their dependencies, compiler and linker flags, and contain rules on how to build object files and link the final program. Such a makefile could look like
CFLAGS = -Wall -g
LDFLAGS = -g
SOURCES = source1.c source2.c
OBJECTS = $(SOURCES:.c=.o)
TARGET = your_program_name
.PHONY: all
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(LD) $(LDFLAGS) $^ -o $#
%.o: %.c
$(CC) $(CFLAGS) $< -c -o $#
The above makefile should do just about the same as the previous command line. The big difference is that it's much easier to add more source files, add special rules for special files, and most importantly, the make program will handle dependencies so that if one source file haven't been modified since last build then it won't be compiled. The last bit will make big projects with many source files build much quicker when only one or a few source files has been modified.
How to learn more about the topics [...]
By going to your favorite search engine, and looking for those topics there. I also recommend e.g. Wikipedia.
Of course, if you use an Integrated Development Environment (a.k.a. an IDE) then you don't have to compile from the command line, or to make your own makefiles, the IDE will handle all that for you. It will also have dialogs for the project settings where you can enter include paths and library paths, and what libraries to link with.
Why I do I need to place the header file that contains only function prototypes?
So as to satisfy your compiler for declaration of those functions or declaration of classes. As C++ is static type checking language, they must know the type of objects which they will be using.
Where to place my own files and how to compile it?
You can place you code anywhere in you filesystem; only make sure to include .h files in includes path and lib while compiling. Usually you need to modify your path.
You can check about building on this link:
https://en.wikipedia.org/wiki/GNU_build_system
Check the README file that came with the code. It should tell you how to install it into the system properly. Usually there is an install build target which installs the resulting files into the proper directories.
The usual sequence of commands to build and install most products is:
$ ./configure
$ make
$ sudo make install

Build CUDA and C++ using Autotools

I'm setting up Autotools for a large scientific code written primarily in C++, but also some CUDA. I've found an example for compiling & linking CUDA code to C code within Autotools, but I cannot duplicate that success with C++ code. I've heard that this is much easier with CMake, but we're committed to Autotools, unfortunately.
In our old hand-written Makefile, we simply use a make rule to compile 'cuda_kernels.cu' into 'cuda_kernels.o' using nvcc, and add cuda_kernels.o to the list of objects to be compiled into the final binary. Nice, simple, and it works.
The basic strategy with Autotools, on the other hand, seems to be to use Libtool to compile the .cu files into a 'libcudafiles.la', and then link the rest of the code against that library. However, this fails upon linking, with a whole bunch of "undefined reference to ..." statements coming from the linker. This seems like it might be a name-mangling issue with g++ vs. the nvcc compiler (which would explain why it works with C code), but I'm not sure what to do at this point.
All .cpp and .cu files are in the top/src directory, and all the compilation is done in the top/obj directory. Here's the relevant details of obj/Makefile.am:
cuda_kernals.cu.o:
$(NVCC) -gencode=arch=compute_20,code=sm_20 -o $# -c $<
libcudafiles_la_LINK= $(LIBTOOL) --mode=link $(CXX) -o $# $(CUDA_LDFLAGS) $(CUDA_LIBS)
noinst_LTLIBRARIES = libcudafiles.la
libcudafiles_la_SOURCES = ../src/cuda_kernels.cu
___bin_main_LDADD += libcudafiles.la
___bin_main_LDFLAGS += -static
For reference, the example which I managed to get working on our GPU cluster is available at clusterchimps.org.
Any help is appreciated!
libtool in conjunction with automake currently generates foo.lo (libtool-object metadata) files, the non-PIC (static) object foo.o, and the PIC object .libs/foo.o.
For consistent .lo files, I'd use a rule like:
.cu.lo:
$(LIBTOOL) --tag=CC --mode=compile $(NVCC) [options...] -c $<
I have no idea if, or how, -PIC flags are handled by nvcc. More options here. I don't know what calls you are making from the program, but are you forward declaring CUDA code with C linkage? e.g.,
extern "C" void cudamain (....);
It seems others have run up against the libtool problem. At worst, you might need a 'script' solution that mimics the .lo syntax and file locations, as described on the clusterchimps site.

how to makefile with iostream, string and ifstream library

I'm trying to build a makefile for an application that use the lib string iostream and fstream.that's what I did up to now
CPP = gcc
LIB_DIR = ./incl
PROGRAMS = test
PROGS_O = action_rec.o
CPPFLAGS = -I$(LIB_DIR) -pg -g
VPATH = ./src/
OBJFILES = $(VPATH)$(patsubst %.cpp,%.o,$(wildcard *.cpp))
LIBS = -02 -liostream -lfstream -lstdlib -lstring
when I try to use my makefile I get as result that everything that need the lib string fstream and iostream was not declared, while everything that need the lib stdlib works properly.
can someone tell me why?
thank you
Try taking all the -lstring -stdlib -liostream -lfstream out and see if it fixes it.
And compile with g++ so it finds other things it needs to link C++ code.
There are two separate issues here.
The C++ side:
Don't use the gcc binary for compiling C++ code - use g++ instead. This will pull in all the required standard include paths and libraries automagically.
The Makefile side:
Your Makefile has a number of issues:
Don't set CPP to a compiler; this variable defines the preprocessor to use. Use CXX to define the compiler - it most likely happens to be defined to g++ anyway.
Don't create programs with the name test. This happens to clash with a standard Unix program (/usr/bin/test) and if you don't pay attention you might end up calling the wrong program.
Don't pass -02 as the linker flags via LIBS. This switch is a) wrongly worded (it should be -O2, the letter O not a zero) and b) it's a compiler flag, so it should be part of CXXFLAGS.
Chances are that you don't need a Makefile at all. The make program comes with default Makefiles so often you can just create a main.cpp file and then run
make main
This will automatically compile and link main.cpp into a main executable. In your case, something like
CXXFLAGS="-I./incl -pg -g -O2" make main
Might be sufficient.
The obvious problem is that you're linking with gcc rather than g++.
gcc doesn't link against the C++ standard library. You can add it
manually, but the simplest is simply to use g++ for everything (unless
you have actual C code; g++ will compiler files ending in .c as
C++).
LIBS = -02 -liostream -lfstream -lstdlib -lstring can be simplified a lot. Just use LIBS = -O2 (I think you meant -O2 rather than -02.) In fact, you really shouldn't be passing a -O flag to the link stage at all. Optimization is a compile-time option, not a link-time option.