"lib" Prefix on Libraries - c++

From http://www.adp-gmbh.ch/cpp/gcc/create_lib.html:
Note: the library must start with the three letters lib and have the suffix .a.
Is this an operating system convention, or a gcc/ar quirk? Xcode seems to be able to create libraries without the prefix. What's it doing differently?

You can name a library whatever you want, but if you want gcc's -l flag to find the right one, you need to name it the way that link describes. For example:
gcc -o myapp myapp.c -lm
Will compile myapp.c, link the resulting object with libm.a, and output an executable called myapp. These days, there might be a more complicated search path involving dynamic library names, etc., but you should get the basic idea from this example.
From the gcc man page:
-l library ...
... surrounds library with lib and .a and searches several directories.

Related

How to add a static library permanently to the Ubuntu system?

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.

link to external library with g++

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.

Linking shared, static, and dynamic library

I built and installed the source code of spidermonkey, I want to link its library and its include folder with my C++ application, so I wrote this command on linux
g++ -I/home/SpiderMonkey/js-1.8.5/js/src/dist/include
-L/home/SpiderMonkey/js1.8.5/js/src/dist/lib -lmozjs185 helloworld.cpp -o
but it gives me undefined reference error, so what is the problem with this command:
the path which the src code was built in is home/SpiderMonkey/js1.8.5/src
and when I installed the src code, its libs and include folder exist now in usr/local/lib and usr/local/include/js respectively, so which path should I use in the command to compile my hellowrorld.cpp.
Also, I found 3 libraries with the same name but with different extension:
libname.so, libname.so.1.0, libname.so.1.0.0 and libname.a
which library should I use and what are the differences?
Put the libraries after your main.cpp on the compilation command. The linker determines which symbols to pull out of those libraries based on the objects it's already seen, left to right.
As for your addendum question:
libname.a is for static linking.
libname.so, libname.so.1.0 and libname.so.1.0.0 are all the same file, just with names that give you an increasing level of version information granularity.
Which to use is beyond the scope of this answer, but you can find plenty of information about that already existing on the web.

How to link to the libabc.a instead of libabc.so?

In the book Autotools: A Practioner's Guide to GNU Autoconf, Automake, and Libtool, chapter 6 (building libraries with libtool), an example of linking library is given.
In the example, a library libjupiter.so is linked to another library libjupcommon.a. The first attempt fails because libjupiter.so needs PIC, but libjupcommon.a is not. The author adds libjupcommon_a_CFLAGS = -fPIC to fix it. It gets much better, but the warning of 'Linking the shared library libjupiter.la against the static library ../common/libjupcommon.a is not portable!' appears.
Therefore the author modifies the Makefile.am's again, using libtool to build libjupcommon.la. The libjupiter links to the libjupcommon.la.
Like this:
noinst_LTLIBRARIES = libjupcommon.la
libjupcommon_la_SOURCES = jupcommon.h print.c
and
...
libjupiter_la_LIBADD = ../common/libjupcommon.la
This time everything's OK.
Now, my problem:
I have a library needs another library, just like libjupiter needs libjupcommon. The difference is my libjupcommon is from another project and installed into the system. It is not a noinst_LTLIBRARIES. Both .so and .a version exist. When I try to link the libjupcommon.la like the example shows, the .so is chosen, but I don't want a dynamic linking relationship. I want to link to the .a, like the example in the book.
Linking to .a explicitly (by using _LIBADD=the .a file) gives a usable library, but the warning of '... not portable' is given.
What's the proper way to achieve linking to the .a in this case?
PS: Download the example from the book's official site. In autotools/book/jupiter-libtool-ch6/common, modify the Makefile.am's noinst_LTLIBRARIES to lib_LTLIBRARIES should be a close mimic to my problem.
There's a couple things you could try. You could try running configure with the --disable-shared option to turn off compilation of shared libs (and add the static lib to libfoo_LIBADD again). You could try adding -static to libfoo_LDFLAGS to get libtool to build it statically (again with the static lib added to libfoo_LIBADD).
EDIT: Since both static and shared libs are needed the above won't work.
Try adding:
AC_CHECK_LIB([abc],[some_function_in_libabc])
to configure.ac.
You can force static linking to one library (while keeping all other links shared) using this construct:
-Wl,-Bstatic -Wl,-whole-archive -Xlinker -l$1 -Wl,-no-whole-archive -Wl,-Bdynamic
Replace $1 above with your library name.
Explanation: Most of the above monstrosity is to get around the fact that libtool will re-arrange the command line arguments, ever so helpfully. Using -Xlinker will force libtool to ignore the -l$1 and not re-arrange it. The -Wl,-Bstatic tells the linker to link all following libraries as static. -Wl,-Bdynamic switches back to dynamic linking for further libraries.

linking problem on linux (can't find the name of the appropriate library)

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.