I have code that compiles well using the following makefile
all: sample
sample: sample.o mylib.o
g++ -Wall -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -o sample -L/usr/lib sample.o mylib.o -lboost_serialization -lboost_iostreams -lz -I /usr/include/boost
sample.o: sample.cpp
g++ -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -I /usr/include/boost -c -o sample.o sample.cpp
mylib.o: mylib.cc mylib.h
g++ -O3 -ffast-math -funroll-loops -ansi -pedantic-errors -I /usr/include/boost -c -o mylib.o mylib.cc
Now, mylib.cc and mylib.h contains a lot of useful code that I would like to share. However, it depends on Boost which my target audience might not have or know how to install properly.
Is there a way for me to distribute a mylib.o that is static with a mylib.h that my end user can just compile into their own code without needing to install Boost?
ADDITIONAL CLARIFICATION: mylib.h does not contain any BOOST headers, but mylib.cc DOES contain boost headers.
If mylib.h includes Boost header files, those will need to be present in some form on the developer's system. At a minimum, you would have to ship that part of Boost with your code.
However, if you can create a smaller header file that exposes just the pieces of your library and does not include nor reference anything in Boost, then you can. Most of Boost is header-only (the required Boost code will be compiled into your library already).
If you're able to create a "boost-free" header, you can do that.
As soon, as you have any references to boost stuff within the header (which you need to redistribute), you can't.
If your cc file uses boost classes which are not header-only, you need to distribute those files, too - either in sourcecode, or within an object-file - which however can lead to strange behavior, if an user uses another version of the boost library and tries to instantiate classes, which are already defined within your object files.
One possible solution would be to find out, which cc-files of boost are required and compile them within a different namespace, e.g. using -Dboost=my_boost:
g++ -Dboost=my_boost <put additional compiler options here> my_boost_file.cc -c my_boost_file.o
You also should compile your own object file with that define.
Finally create an archive containing all the required object files;
ar rvs my_archive.a mylib.o my_boost_file.o
Related
I have read the explanation on the manual page (https://linux.die.net/man/1/g++) but I still do not understand its use cases. I have seen it used in the example below:
g++ -MM -w --std=c++14 `pkg-config fuse3 --cflags` -fpermissive -I.. hello.cpp > .obj/hello.d
I would like to understand when and why it is used.
The .obj/hello.d file you obtain probably looks like this.
hello.o: hello.cpp something.h stuff.h ...
This is a dependency rule for a makefile.
If your makefile uses something like
-include .obj/*.d
then it will be the same as if you explicitly wrote these dependencies.
If a generic rule knows how to generate a .o from the corresponding .cpp, then it will be triggered everytime one of those automaticaly listed header files is changed.
I am creating a gcc shared library having a static library dependency.
I compile the parts for static library as following:
gcc -c -m64 -O2 -fPIC -std=c99 -Wall ms*.c //there are 10 C files, no warnings
Next I create a static library with:
ar rc static_lib.a ms*.o
Next I compile the parts for my program as following:
g++ -c -m64 -O2 -fPIC -std=c++14 -Wall ab*.cpp //there are 5 C++ files, just -Wunused-variable warnings
Then I create a shared library as following:
g++ -shared -g -Wall ab*.o static_lib.a -o shared_lib.so
in the normal case, this shared_lib.so will be called by a Ruby program using a foreign function interface. There is no problem if I do it on ubuntu or mac(.dylib), but if I try this on debian stretch I get an error related to the static library as if the configurations are not set properly. If I run the application without foreign function interface, such as creating a tester and running with the cpp file main function as following:
> g++ -o library_test ab*.o static_lib.a
> ./library_test
There is no problem!
My question is what kind of configuration for creating a shared library may be missing here to not get that undesirable behaviour. Especially on debian stretch 9.5!
Or is there a way that I can understand if there is a problem in the shared library.
From the comments, you indicate the problem is with a #define. Those are preprocessor directives. Libraries are for the linker.
You might be confused because g++ does include the preprocessor phase, and might call the linker depending on the requested output. Still, g++ follows the C++ language rules.
I want to share my project which was written in C/C++ (Linux environment gcc/g++ compiler) as shared library/static library without actually sharing the source code. So that other users can use my project without actually knowing my source code. Can anyone tell how do I share it as .so/.a format?
Suppose, my project looks like:
main.cpp,
source1.cpp,
source2.cpp,
source3.cpp,
head1.h,
Makefile
How can I share this project by hiding the source code of the files source1.cpp, source2.cpp and source3.cpp and making these as shared library/static library. main.cpp file contains the main() function. What is the detailed procedure?
PS: I am a novice in shared library/static library.
Suppose you have the following source file:
mylib.c:
#include <stdio.h>
void my_print(int i)
{
printf("i=%d\n", i);
}
The public header for this would be:
mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
void my_print(int i);
#endif
You could then build the library like this:
gcc -g -Wall -Wextra -c mylib.c
gcc -g -Wall -Wextra -shared -fPIC -o libmylib.so mylib.o
Then you can distribute libmylib.so and mylib.h to users. Then can then use it in their code like this:
user_prog.c:
#include "mylib.h"
int main()
{
my_print(5);
return 0;
}
They would then put libmylib.so into someplace like /usr/lib or /usr/local/lib, and compile like this:
gcc -g -Wall -Wextra -o user_prog user_prog.c -l mylib
For your particular case, assuming head1.h contains the public interface and source1.cpp source2.cpp source3.cpp the library, you would compile like this:
g++ -g -Wall -Wextra -c source1.cpp
g++ -g -Wall -Wextra -c source2.cpp
g++ -g -Wall -Wextra -c source3.cpp
g++ -g -Wall -Wextra -shared -fPIC -o libmylib.so source1.o source2.o source3.o
You need to create object files from your source files. Then create static and/or shared libraries. You will need to provide a header file for use with your library. And note that your library must NOT contain main().
See detailed instructions for gcc
Ofcourse you can. Simply supply the people with the library file and the header files corresponding to the source files used to build the library.
Problem
Say I've got a Linux executable MAIN that uses an old version of some shared library LIB.so (which it locates using LD_LIBRARY_PATH).
I'd like MAIN to also use my library MYLIB.so, except this uses a newer version of LIB.so.
MAIN and MYLIB.so both use functions that appear in both versions of LIB.so with the same name (but different implementations).
How do I get the application to also load the new version of LIB.so when it loads MYLIB.so?
What doesn't seem to work
I've tried compiling MYLIB.so with an RPATH option pointing to the new version of the library. However, while this correctly identifies the newer library when I run ldd MYLIB.so, when the application runs it only uses the old library implementation.
My compilation (using single file toy implementations for clarity) is as follows:
# compile old library implementation
g++ -c -Wall -Werror -fpic library_old.cpp
g++ -shared -o liblib.so library_old.o
# compile new library implementation
g++ -c -Wall -Werror -fpic library_new.cpp
g++ -shared -o new/liblib.so library_new.o
# compile my library against new liblib
g++ -c -Wall -Werror -fpic my_library.cpp
g++ -L`pwd`/new -shared -Wl,-rpath,`pwd`/new -o libmine.so my_library.o -llib
# compile application against old liblib
g++ -L`pwd` -Wall -Werror -o main main.cpp -llib -lmine
export LD_LIBRARY_PATH=`pwd`
I have been writing a c++ program in Ubuntu and window8 using armadillo. Under Windows8 the program compiles without problems.
The program is just using the linear systems solver.
Under Ubuntu the compiler says
"reference to `wrapper_dgels_' not defined"
The compiler line I use is:
mpic++ -O2 -std=c++11 -Wall -fexceptions -O2 -larmadillo -llapack -lblas program.o
However, right before the error I see:
g++ module_of_the_error.o
Which is something I haven't set.
I am using code blocks in Ubuntu, and I compiled armadillo with all the libraries that cmake asked. (BLAS< LAPACK, OpenBLAS, HDF5, ARPACK, etc)
I have no clue what might be causing the problem, since the exact same code compiles in visual studio.I have tried the compiler line modifications suggested but it does not seem to work.
Any help is appreciated.
This is one trap I fell into myself one time. You will not like the likely cause of your error.
The order of the arguments to the linker matters.
Instead of
mpic++ -O2 -std=c++11 -Wall -fexceptions -O2 -larmadillo -llapack -lblas program.o
try:
mpic++ -O2 -std=c++11 -Wall -fexceptions -O2 program.o -larmadillo -llapack -lblas
I.e., put the object files to be linked into the executable before the libraries.
By the way, at this stage you are only linking files that have already been compiled. It is not necessary to repeat command line options that are only relevant for compiling. So this will be equivalent:
mpic++ program.o -larmadillo -llapack -lblas
Moreover, depending on how you installed Armadillo, you are adding either one or two superfluous libraries in that line. One of the following should be enough:
mpic++ program.o -larmadillo
or
mpic++ program.o -llapack -lblas
EDIT: as the answer by rerx states, the problem is probably just a simple ordering of the switches/arguments supplied to g++. All the -l switches need to be after the -o switch. Or in other words, put the -o switch before any -l switches. For example:
g++ prog.cpp -o prog -O3 -larmadillo
original answer:
Looks like your compiler can't find the Armadillo run-time library. The proper solution is to specify the path for armadillo run-time library using the -L switch. For example, g++ -O2 blah.cpp -o blah -L /usr/local/lib/ -larmadillo
Another possible solution is to define ARMA_DONT_USE_WRAPPER before including the armadillo header, and then directly link with LAPACK and BLAS. For example:
#define ARMA_DONT_USE_WRAPPER
#include <armadillo>
More details are available at the Armadillo frequently asked questions page.