Automatically collect and output all C++ dependencies - c++

Problem
I need my code to compile on a machine that cannot leverage apt-get to install nonstandard C++ libraries but my C++ program has a single #include for an external library that I must use. That library includes many headers and other libraries, meaning that my makefile has many -l and -I to /usr/include/... and /usr/lib/... pointing to my apt-get installed libraries.
What I want
Rather than manually going through and grabbing all of these libraries so that I can include them in my project directory, I am hoping there is a command or flag for make or g++ that will dump all the libraries and headers into a directory for me.
Progress
This and this have helped because adding the -MMD flag to my g++ compile command will dump out a list of about 100 header file locations. But I would like g++ to go one step further and actually do the work of gathering them all together for me, if that feature exists.

Related

How to compile with c++ <execution> standard library

The issue
I am trying to use the execution policies in the standard algorithm library. However, when I try to compile I get the following error message
c:\mingw\lib\gcc\mingw32\9.2.0\include\c++\pstl\parallel_backend_tbb.h:19:10: fatal error: tbb/blocked_range.h: No such file or directory
After looking at various other related questions such as this or this, I understand that the execution library depends upon a software called tbb. Moreover in order to compile code which uses <execution> one has to manually link to tbb. My issue is precisely with how to download and link tbb to a script that uses <execution>.
I believe I have some serious gaps in my understanding in terms of how one downloads the correct files and then links to them. I will first make a list with my understanding of the linking process and then I will explain what I have tried to fix the issue. I have chosen this format so that it is faster for the one to answer my question to point at the issue at fault. I will attempt to keep this as concise as possible.
My understanding
Code is organized in header and cpp files, where the former usually only contain the interface to the software and the later the implementation
The cpp files can be pre-compiled and grouped into a single library file
For a user to then use the library, they have to #include the header/s in their script and also tell the compiler where the header files as well as the library file, are located
This can be done with the -I for the headers and -L, -l for the library file
-L provides the location of the library files, the -l specifies which libraries to use
What I tried
The script I try to compile is:
#include <execution>
int main() {
std::execution::par;
return 0;
}
with
g++ script.cpp -o out -I C:(path to the headers) -L C:(path to the library) -l (name of library) -std=c++17
I should also mention I am trying to do this on Windows 10
1st attempt
I had a particularly hard time understanding where to find the header and library files for tbb.
In the Intel getting started with TBB webpage, this github repository is listed as "TBB being available at". As I am used to header-only libraries I thought everything would be in the include directory but no .dll files where there. It is now my understanding that I have to compile the DLLs myself for my specific system which makes sense. I followed the following process using cmake:
# Do our experiments in /tmp
cd /tmp
# Clone oneTBB repository
git clone https://github.com/oneapi-src/oneTBB.git
cd oneTBB
# Create binary directory for out-of-source build
mkdir build && cd build
# Configure: customize CMAKE_INSTALL_PREFIX and disable TBB_TEST to avoid tests build
cmake -DCMAKE_INSTALL_PREFIX=/tmp/my_installed_onetbb -DTBB_TEST=OFF ..
# Build
cmake --build
# Install
cmake --install .
# Well done! Your installed oneTBB is in /tmp/my_installed_onetbb
However at the cmake --build step, cmake does not accept the command but requests more options. One of them is the dir option, which for which I made another directory and supplied it but then the error message Error: could not load cache printed out.
In any case, some files had been created so I searched for the .dll file but could not find it.
2nd attempt
I downloaded the Intel oneAPI Base Toolkit as is suggested here. After the installation at ../Program Files (x86)/Intel/oneAPI I found the specific tbb tool at C:\Program Files (x86)\Intel\oneAPI\tbb and I used this address for the -I and -L flags but initial error message persists.
I also copied the directory C:\Program Files (x86)\Intel\oneAPI\tbb\2021.6.0 to the local directory of the script so I could link with -flag tbb\2021.6.0 but no luck
Many thanks
Yes you were correct.
By using the package mingw-w64-tbb. You can use -ltbb12 instead of -ltbb. As the library files are related to ltbb12.
For using -ltbb option, you should set the Intel oneAPI environment. It can be used by downloading Intel oneAPI Base Toolkit.You can set the environment by sourcing setvars.sh file using the below command.
source /opt/intel/oneapi/setvars.sh

Some doubts about libraries

Say, I want to write a program in C++ in Linux and I need some specific libraries. There are 2 ways of getting these libraries:
Using the command line--> apt-get install library
Downloading and extracting a .zip or .tar file from their website.
Now my questions are:
For the first method I have seen libraries being downloaded with apt-get install library and apt-get install library-dev. I know dev means development or developer, but what is the difference between installing the dev and not installing the dev? What does dev do, exactly?
For the second method, do I need to build the libraries using a compiler? Because I have seen tutorials doing it but the OS used was usually Windows, do I only have to build them on Windows and not Linux?
Also, say I can only use the 2nd method for a certain library and not the first one. After extracting, what am I supposed to do? Is there any default way of installing a library manually or is each library different?
Finally, when I use the first method where is the library installed to? Is it /usr/local/lib, /usr/lib or /usr/include? Because when I have to link to these libraries in the Linker's settings I only write their name, not the path so I assume there is already a default path for libraries to be in.
One last question: Is there any default way of installing and using libraries in general or does that depend on what I want to do, programming language, etc...?
The second method is very broad because it depends entirely on the how the project is designed including the build system used etc. Things get a little more conformant when you use a distribution's managed packages.
If you want to develop a program that uses the library you need the library-dev package that usually contains the C/C++/etc.. header files.
Many development package conform to a standard tool that helps your build system find the libraries header and binary files.
For example libcurl uses the pkg-config system so its compiler components can be found from the command line like this:
pkg-config libcurl --libs # print the library link flags
You can then add that to your Makefile (or whatever build system you use):
program:
g++ -o program program.cpp $(shell pkg-config libcurl --libs)
The $(shell pkg-config libcurl --libs) part adds the correct compiler flags to link with the library.
Not all dev packaged use pkg-config. Some come with their own tools (like mysql_config) while others let you guess and try to figure it all out for yourself (looking at you libclang).

How to add gsl to MinGW?

I use TextPad and MinGW. I compile with TextPad so I don't know how to use gcc ect. comands.
I got my library from here ftp://ftp.gnu.org/gnu/gsl/gsl-1.9.tar.gz and I have no idea what to do with it. In my MinGW folder there are bin, include and lib folders of course but I have no idea what to copy where.
And I don't know how to find out where MinGW searches for these libraries.
It would seem reasonable to copy .h , .a and .dll files where such files already are. It doesn't help that supposedly the same gsl are different from source to source and some include .dll and some don't.
I suppose the biggest problem is how do I tell MinGW where to search, since I found gsl that is already compiled and I could supposedly already use.
Assuming you have MSYS accompanied with MinGW, you can simply do:
./configure
make
make install
after
tar xzf gsl-1.9.tar.gz
cd gsl...
It will install gsl to the default directories. You may have to use -I/usr/local/include -L/usr/local/lib on the command line when compiling your program using gcc, because MinGW gcc does not recognize those standard locations.

add armadillo libraries to g++ compiler in linux

I am trying to install a C++ library (armadillo) in a unix cluster where I do not have root permissions.
I managed to compile the C++ libraries without user permissions by running the following make command:
make install DESTDIR=my_usr_dir
But then in the armadillo readme file it says:
where "my_usr_dir" is for storing C++ headers and library files. Make sure your C++ compiler is configured to use the sub-directories present within this directory.
The compiler the armadillo uses to install the libraries is gcc-4.8.1. I am not sure where the compiler was installed but it's loaded when I start my session in the unix cluster.
After installing armadillo I am trying to compile open source code that uses the armadillo libraries. This open source code also has a makefile.
However, when I go to the open source code and I type in:
make
it calls g++. How can I make sure g++ will recognize the armadillo libraries previously installed in my_usr_dir?
Currently I get the following error if I go to src and then type make:
opencode.cpp:28:21: fatal error: armadillo: No such file or directory
#include <armadillo>
^
compilation terminated.
make: *** [mmcollapse] Error 1
you can use
alias gcc="gcc -I./my_usr_dir/include -L./my_usr_dir/lib"
and so on in your .bashrc file. In that way, whenever you invoke gcc on the command line, the flags will be added before every other argument you enter on the command line
I think the readme file refers to the usage of the library headers and library files from applications. For those to be useful, the compiler/linker/loader (usually all driven by the "compiler") have to know where to find them. The compiler always looks in some default directories, such as /usr/include (for headers) and /usr/lib/ (for libraries), but they require root permission to write into. However, you can tell the compiler with the flag -Idirectory to search in directory directory for headers. For libraries use -l and -L (check the manual page of your compiler). You may also need to consider the LD_LIBRARY_PATH and LD_RUN_PATH environment variables, if you're using dynamic linking (shared object files).
This question looks similar to
How to specify non-default shared-library path in GCC Linux? Getting "error while loading shared libraries" when running
If you dont want to change the .bashrc
use -rpath as suggested in the post above.
gcc XXX.c -o xxx.out -Lmy_usr_dir -lXX -Wl,-rpath=my_usr_dir
-L is for static linking
-rpath for adding the directory to the linker search path
more on -rpath here
I don't understand -Wl,-rpath -Wl,
Dont bother to upvote the answer because this is really not an answer. I would have commented but i could not locate the add comment for your post.

How to use SOCI C++ Database library?

I'm trying to implement soci in my program but I don't know how. I'm using C++ on Linux, on a project using netbeans. I have followed the steps in: http://soci.sourceforge.net/doc/structure.html to install it, and I tried to copy the files soci.h from /src/core and soci-mysql.h from /src/backends/mysql in my project but it gives a compilation error (these files include other soci files, but it's illogical to copy all files into the directory...). I have read the guide several time but I don't understand what I'm doing wrong. The examples only include these files.
Thanks.
Edit: I have given more information in a comment below the answer. I don't know what steps I have to follow to implement soci.
The relevant bit on that page is
When the configure script is run without parameters, the remaining part of the process will use /usr/local/include/soci as a default destination for SOCI header files and /usr/local/lib as a default destination for library files
Now /usr/local/include ought to be in your default include path (e.g. try something like gcc -c -v -x c++ /dev/null -o /dev/null to see the list your install uses) and so you can include these using
#include <soci/soci.h>
#include <soci/soci-mysql.h>
You then need to add the libraries to your link step. It looks like you'll have both static and shared versions of the libraries. You'll need to add -lsoci_core -lsoci_mysql to your link step; however if that doesn't work then you'll also need to specify /usr/local/lib as a search directory i.e. -L/usr/local/lib -lsoci_core -lsoci_mysql. (Again it's probably there already but you can see using gcc -print-search-dirs.) However, the issue then is that if you're using the shared version and /usr/local/lib isn't in your distributions library search path (see /etc/ld.so.conf and/or /etc/ld.so.conf.d/*) then it won't be able to find the shared library at runtime. You'll need to either hard-code in the path to the library with the linker switch -rpath or add /usr/local/lib to the system-wide search path as before or in your environment (variable LD_LIBRARY_PATH). I'm not sure what the best way to do this is - I'd suggest -rpath to avoid modifying the system in general, although if you're building a lot of libraries into /usr/local/lib it might make sense to add it.
I got the same doesn't load backend error on my C++ program when I execute session sql("mysql://db=...)
I found a solution (at least on my Ubuntu 11.04). Just do:
sudo -i ln -s /usr/lib/libsoci_mysql-gcc-3_0-3.0.0.so /usr/lib/libsoci_mysql.so
It seem that the SOCI library search for the file /usr/lib/libsoci_mysql.so that is not in the system, buy if you make a link to the library /usr/lib/libsoci_mysql-gcc-3_0-3.0.0.so that it's in the system it works (I think debian/ubuntu makes a file name change from the original name, but it have side effects because the SOCI library search inside for the original name).
I found the error using the bash environment variable LD_DEBUG=files and running my C++ binary.
Hope it helps.