I downloaded the FMUSDK and I want to compile the code. Unfortunately the build script is supposed to work with the Visual Studio C compiler, but I can't install/use it on my machine. Thus, I try to modify the script (and some parts of the code) to be able to compile it with the GCC. But I am completely new to compiling complex code (I usually just use gcc *.c -o outfile.exe)
Here is my problem:
In some files there is a library linked with
#pragma comment(lib, "libxml2.lib")
This does not work with GCC.
The lib can be found in ..\shared\parser\libxml2.lib
with headers files in ..\shared\parser\libxml\
I call the build script with
fmusdk\fmu20\src\co_simulation>..\build_fmusim_cs_gcc.bat
The script then looks like this:
set SRC=main.c ..\shared\sim_support.c ..\shared\xmlVersionParser.c ..\shared\parser\XmlParser.cpp ..\shared\parser\XmlElement.cpp ..\shared\parser\XmlParserCApi.cpp
set INC=-I ..\shared\include -I ..\shared -I ..\shared\parser\libxml -I ..\shared\parser
set LIB=-L ..\shared\include -L ..\shared -L ..\shared\parser\libxml -L ..\shared\parser
set OPTIONS=-D FMI_COSIMULATION -D STANDALONE_XML_PARSER -D LIBXML_STATIC -v
g++ %INC% %OPTIONS% %SRC% %LIB% -lxml2 -o fmu20sim_cs.exe
But I get the following error message:
c:/users/<username>/userprograms/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lxml2
I tried to use what I found on http://www.rapidtables.com/code/linux/gcc/gcc-l.htm, but I seems not to work.
Can someone help? What am I doing wrong? Under INC and LIB I put everything that looked helpful, but I have no idea what I am really doing there ...
I have also a logfile with the verbose output of the batch file. But I don't see how to upload it here :(
Best regards,
Martin
libxml2.lib is the example of (quite frequent) messing with library name conventions. Visual Studio uses the convention of adding .lib extension (this would be xml2.lib), GCC uses the convention of adding lib prefix and .a extension to library name (this would be libxml2.a).
According to GCC manual (https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Link-Options.html#Link-Options) you have two options:
Change the library file name to the libxml2.a, because that is the file name GCC is looking for when given the -lxml2 option.
The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a.
Provide the full name of the library file , without -l (e.g. change -lxml2 to libxml2.lib in g++ command line), then the GCC will look for the given name exactly.
A file name that does not end in a special recognized suffix is considered to name an object file or library. (Object files are distinguished from libraries by the linker according to the file contents.) If linking is done, these object files are used as input to the linker.
You should replace -lxml2 by -llibxml2.
Explaination, from Mingw :
Also note that the library names "lib<name>.a" and "lib<name>.lib" are not equivalent; if you have a library named according to the aberrant "lib<name>.lib" convention, it will not be found by an "-l<name>" specification -- if you cannot rename the library, you must use the form "-llib<name>" instead.
Related
Hi everybody I recently created a C++ project in which I put my code into header.h and header.cpp files and successfully create a static library called header.a. Now I put my header.h file into /usr/local/include position of my system and header.a into /usr/local/lib in order to "install" my library into the machine. Now, if I want to use this library, I have to do the following steps:
Suppose I am using a main.cpp program, I include this line at the top of the program:
include <header.h>
Then, I compile with this command:
g++ main.cpp /usr/local/lib/header.a
And all it's ok. But I want to find a way to "store" permanently the header.a library into the system in order to use it like a normal standard C++ header, simplifing the compilation in this way:
g++ main.cpp
Is there a way to do this? Many thanks to all.
You can't, and no system library will be linked automatically without being told to do so.
You can however add the path /usr/local/lib to the default paths for the linker to look for libraries (IIRC it's not in there by default for Ubuntu), which means you only need to add the -l (lower-case L) option to link with the library.
But do note that the library should be having a lib prefix. Like in libheader.a.
Then link with -lheader:
g++ main.cpp -lheader
There also the -L option to add a path to the list of paths that the linker searches, if you have other non-standard paths, of if you can't edit the system configuration to use /usr/local/lib:
g++ main.cpp -L/usr/local/lib -lheader
The library file still needs the lib prefix.
I have 'correctly' installed gsl on mac 10.13.2.
In my c++ program, I am calling like usual, for example:
#include <gsl/gsl_math.h>
However while running the code, it can not find the gsl.
fatal error: 'gsl/gsl_math.h' file not found
I was wondering how to correctly link gsl PATH and libraries.
I have tried,
setting PATH and LD_LIBRARY_PATH in .bash_profile
setting PKG_CONFIG_PATH to .../Gsl2.3/lib/pkgconfig
$which gsl-config returns
/Users/gkdgoutam/Softwares/HEP_Softwares/Install/Gsl2.3/bin/gsl-config
$pkg-config --libs gsl returns
-L/Users/gkdgoutam/Softwares/HEP_Softwares/Install/Gsl2.3/lib -lgsl -lgslcblas -lm
The only solution I can find is to run everytime with gsl linked.
Like:
g++ $(gsl-config --cflags) mycode.cc $(gsl-config --libs) && ./a.out
But I was wondering if the GSL PATH can be set globally so that I can simply run
g++ mycode.cc && ./a.out
This is how c++ code is compiled and built:
COMPILATION
A compilation unit will take each cpp file and work its way through included headers to locate forward declaration of implementations of symbol signatures of used functionality in your code. In your case this involves gsl/gsl.h. If the file cannot be found in the search directories, which you can expand by specifying C_INCLUDE_PATH and or CPLUS_INCLUDE_PATH. If you omit #include <gsl/gsl_math.h>, your code will not compile as there are signatures, which cannot be found for GSL functions, which you use.
LINKING
Once you have compiled all cpp/cc files you need to link the binary, which can be executed. The linking process consists of a search through all symbols in your .o/.obj... files and a matching of the same to what it can find in your object files and the libraries, which you have specified using for example -lgsl. If all goes well, every lookup finds an according binary implementation for your machine's hardware model (i.e. 64bit/32bit ..., Arm, Intel, ... etc). If some are not found you will find linkage errors.
What you are asking is, is there a way that C++ does not work as above? No!
If you leave out #include <gsl/gsl.h> or if said file is not found in your search paths, compilation will not work or. If you omit -lgsl, linking will fail. If you find it annoying to write all the above stuff in the command line, write a Makefile to reduce the building process to ideally a simple command: make.
Don't forget, that if you are linking against the shared library version of GSL, you might need specifying LD_LIBARAY_PATH on Linux and DYLD_LIBRARY_PATH on Macs as well.
TLDR: you cannot ask a c++ compiler / linker to work differently as designed.
I am trying to incorporate a C library into some Rcpp code.
I can use the C library in a C++ program easily. I 'make' the C library, which creates the .a and .dll files in the /lib folder. I can then use the package by including the header in the program and running something like this from command line:
cc myfile.cpp -o myfile -Ipath.to.header path.to.lib.a -lz
This essentially tells the compiler to take the .cpp program, include headers from -I, and to link to two libraries.
Getting this to work with Rcpp shouldn't be overly difficult if I understand makevars correctly (which I unfortunately don't seem to).
I add the library to a folder in my package, and in src I add a makevars and makevars.win that look like this:
PKG_CFLAGS=
# specify header location
PKG_CPPFLAGS=-Ipath.to.lib/include
# specify libs to link to
PKG_LIBS=path.to.lib/lib/file.a -lz
# make library
path.to.lib/lib/file.a:
cd path.to.lib;$(MAKE)
This correctly 'makes' the .a and .dll files for the library, however none of the Rcpp magic runs (i.e. in the build I never see the g++ system call that compiles the files in src), so "no Dll was created".
I am fairly certain this is a problem in my makevars target that makes the library. When I remove that portion from the makevars, and 'make' the library from the command line myself before building the package, I get the proper g++ calls with my -I and -l statements, but I get errors about undefined references.
I notice that the -l statements are only included in the final g++ call where the final .dll is made, but isn't included in the earlier g++ calls where the files with the library headers are compiled.
So I have two problems:
How do I fix my makevars so that it 'makes' the library, but doesn't stop Rcpp from compiling the files in src?
How do I deal with the undefined references? The library is clearly not header-only, so I am guessing it needs the -l statement in the earlier g++ calls, but that may not even be possible.
The best approach is to avoid complicated src/Makevars file altogether.
One easy-ish approach around this: use configure to build your static library, then once you actually build just refer to it in src/Makevars.
I use that scheme in Rblpapi (where we copy an externally supplied library in) and in nloptr where we download nlopt sources and build it 'when needed' (ie when no libnlopt is on the system).
I have an already built library made of this files:
A bunch of headers.
A .so file (libmylib.so).
I want to compile a c++ program (sample.cpp), where I included the headers, and where I need to use the library. This is what I've done, and it's working:
Put the headers in usr/local/include.
Put the .so file in usr/local/lib.
Compile the program in this way: g++ sample.cpp -lmylib.
My question is: why is it not working if I omit -lmylib from the last line?
Is there a way to install the library such that I don't need to put it every time in the g++ command?
Thank you.
What libs are used by default depends on some setting in the compiler/linker,
but it´s not "every lib in usr/local/lib" or any directory, just some specific names
(or even just a single one). Call g++ -v or g++ -dumpspecs to list it (and more stuff)
So, either rebuild your compiler with your own lib list, or specify it manually everytime.
I trying to use a library (http://code.google.com/p/qxmpp/) but I can't find the name of the library to link it to. I want to understand how can you find out the name of the library to use in the linking parameters.
Looks like that is a source archive only -- no binaries included. Have you built the library from it? Where did the build process put it? /usr/lib or /usr/local/lib would be usual suspects, but read the build and install documentation in the package.
Given that the name of the library is libqxmpp.a and (as you mention in a comment) that it's in the usual lib directory (/usr/lib), you can easily deduce the proper options:
gcc and other compilers have an -l switch that finds the library based on the name you give it. By default, it will look in the paths given to GCC at build time (usually /lib and /usr/lib) and any others given to /etc/ld.so.conf. If you add the switch -lX, it will prepend lib to the name and by default append .so and look for any file that looks like libX.so in any of the lib directories it knows about.
Working backwards, we can deduce that invoking gcc with -lqxmpp will look for a file named libqxmpp.so (actually, it looks for a few other names, too.) How do we get it to look for a .a file? Those archives (man ar) are static libraries, so pass the -static switch just before the library:
gcc -o progname your.o program.o files.o -static -lqxmpp
(If you need to link to other libraries, you may need to add -Wl,-dynamic for them if you don't want them statically linked or if static libs aren't available.)
Alternatively, you can do this if you know the full path:
gcc -o progname your.o program.o files.o /usr/lib/libqxmpp.a
... And it works just the same.