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.
Related
What's a good way to find the necessary libraries needed to link against when making a toy executable to play around with another library?
I'll get the appropriate compile command from the compile_commands.json file (generated by CMake), but I still have to manually figure out which libraries I need the executable to link to.
For example: if I have a file called main.cpp:
#include <some_cool_library.hpp>
#include <iostream>
int main() {
some_cool_library::some_cool_type obj{"35"};
return 0;
}
I'll grab the appropriate compile command from the compile_commands.json file that was generated in the project that utilized some_cool_library.hpp (this is so I can pass the correct -I flag(s) to compiler without having to think at all).
Then I'll compile it (making the appropriate compile command modifications):
/usr/bin/clang++ -DBOOST_ALL_NO_LIB -DBOOST_ASIO_HAS_STD_CHRONO -DHAS_ZLIB -DWEBSOCKETPP_STRICT_MASKING -I<some-dir0> -I<some-dir1> -I<some-dir2> -isystem /usr/local/include -Wall -Wno-invalid-partial-specialization -O3 -DNDEBUG -pthread -std=gnu++17 -o prog /home/user/main.cpp && ./prog
Lastly I'll get some output that spits back a bunch of linker errors where I have to manually inspect each one and link the appropriate library. Is there a better way to find these libraries?
The standard way to learn how to use a library is to read that library's documentation.
In some cases, pkg-config can be used to get the necessary compiler and linker flags. This is not guaranteed to work, but there is a reasonable chance of it working if CMake seems to automagically handle the library as a dependency.
I have wrapped my C++ header file in an extern "C" block to allow calling C++ functions from C. I have included the proper header files in the proper places. It works if I do something like the following:
g++ -c cpp_src.cc
gcc -c c_src.c
gcc -o c_exe c_src.o cpp_src.o -lstdc++
But if I remove the -lstdc++ from the last line, I get a bunch of errors. Because of reasons beyond my control, I cannot add the -lstdc++ flag. Is there a way to get the above to work without -lstdc++? What exactly is lstdc++, as in how does the gcc use it while linking with g++ compiled code?
Also, cpp_src.cc uses STL, if that makes a difference.
If you really need to have an object file that you can link with gcc without using -lstdc++, you can do an incremental link of your C++ object file with -lstdc++ and then use the result of that on your gcc link line. Something like:
ld -i -static cpp_src.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -lstdc++ -o cpp_withstdlib.o
This will link your C++ object file with the standard C++ library and produce a new object file (cpp_withstdlib.o) that contains all the standard C++ library stuff you need, so can be linked on the gcc command line without needing -lstdc++
The tricky part is the -L option -- you need to figure out where g++ has stashed its standard library, as it generally doesn't put it in the standard /usr/lib location. The above is for an Ubuntu 14.04 machine. On most Linux machines, you can find it with locate libstdc++.a
You're generally just better off using g++ to link C++ code, as it knows all the right paths and won't make little mistakes that result in a binary that superficially appears to work, but is actually incorrect.
Using Josh's suggestion, you can do:
ld -i -static cpp_src.o `g++ -print-file-name=libstdc++.a` -o cpp_withstdlib.o
which is a bit cleaner, and could readily be done in a Makefile.
-lstdc++ causes the linker to link to libstdc++, which is gcc's implementation of the C++ standard library. If your code uses any symbols from the standard library (it uses the standard library, and not all code is inlined from headers), it must link libstdc++ (or whichever standard library implementation you use).
You can avoid the standard library, or you can link against the system standard library, or you can statically link a copy of the standard library into your program.
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.
I'm playing around with a toolchain that seems to wrap gcc (qcc), but also uses g++ for a few things. This caused a bit of confusion when I couldn't link libs I built with g++ using g(q)cc even though it was for the same architecture (due to missing lib errors). After a bit more research, I found that g++ is basically gcc with a few default flags and a slightly different interpretation mechanism for file extensions (there may be other differences I've glanced over). I'd like to know exactly which flags can be passed to gcc to amount to the equivalent g++ call. For instance:
g++ -g -c hello.cpp // I know at the very least that this links in stl
gcc -g -c -??? // I want the exact same result as I got with g++... what flags do I use?
The way the tool chain is set up makes it sort of difficult to simply replace the gcc calls with g++. It'd be much easier to know which flags I need to pass.
The differences between using gcc vs. g++ to compile C++ code is that (a) g++ compiles files with the .c, .h, and .i extensions as C++ instead of C, and that (b) it automatically links with the C++ standard library (-lstdc++). See the man page.
So assuming that you're not compiling .c, .h., or .i files as C++, all you need to do to make gcc act like g++ is add the -lstdc++ command line option to your linker flags. If you are compiling those other files as C++, you can add -x c++, but I'd advise you instead to rename them to use .cc or .ii files (.h can stay that way, if you're using precompiled headers).
My requirement is to work on some interface .h files. Right now I have .h and .cpp/.cc files in my project.
I need to compile it into shared 64-bit linux compatible library (*.so), using NetBeans/ Eclipse on Linux Fedora.
Since the GCC C++ ABI conventions did slightly change (in particular because of C++ standard libraries evolution, or name mangling convention) from one GCC version to the next (e.g. from g++-4.4 to g++-4.6) your shared library may be dependent upon the version of g++ used to build it
(In practice, the changes are often small inside g++, so you might be non affected)
If you want a symbol to be publicly accessible with dlsym you should preferably declare it extern "C" in your header files (otherwise you should mangle its name).
Regarding how to make a shared library, read documentation like Program Library Howto.
See also this question
And I suggest building your shared libraries with ordinary command-line tools (eg Makefile-s). Don't depend upon a complex IDE like NetBeans/ Eclipse to build them (they are invoking command-line utilities anyway).
If you are compiling a library from the 3 C++ source files called a.cc, b.cc, and c.cc respectively;
g++ -fpic -Wall -c a.cc
g++ -fpic -Wall -c b.cc
g++ -fpic -Wall -c c.cc
g++ -shared -Wl,-soname,libmylib.so.0 -o libmylib.so.0.0.0 a.o b.o c.o
Then you install the library using ldconfig, see man 8 ldconfig
you can then compile the program that uses the libary as follows (but be sure to prefix extern "C" before the class declarations in the header files included in the source code using the library.)
g++ -o myprog main.cc -lmylib
I have tried these compile options with my own sample code, and have been successful.
Basically What is covered in Shared Libraries applies to C++, just replace gcc with g++.
The theory behind all of this is;
Libraries are loaded dynamically when the program is first loaded, as can be confirmed by doing a system call trace on a running program, e.g. strace -o trace.txt ls which will dump a list of the system calls that the program made during execution into a file called trace.txt. At the top of the file you will see that the program (in this case ls) had indeed mmapped all the library's into memory.
Since libraries are loaded dynamically, it is unknown at link time where the library code will exist in the program's virtual address space during run time. Therefore library code must be compiled using position independent code - Hence the -fpic option which tells the translation stage to generate assembly code that has been coded with position independent code in mind. If you tell gcc/g++ to stop after the translation stage, with the -S (upper case S) option, and then look at resulting '.s' file, once with the -fpic option, and once without, you will see the difference (i.e. the dynamic code has #GOTPCREL and #PLT, at least on x86_64).
The linker, of course must be told to link all the ELF relocatatable object types into executable code suitable for use as a Linux shared library.