GCC: Specifying static/dynamic libraries to build against - c++

I have a simple C++ project that is structured as following:
-A base project (ie: contains main() ), and links against everything else
--A few custom libraries that are all built as static libs (ie: .a files)
---One of these static libraries uses features in a shared objective file (ie: a .so file)
So, for example, this is how the project would appear (in a a tree view) at link time, after all the initial compiling has completed:
-myApp (the main application)
--libaudio.a (the audio library I made)
--libnetwork.a (the networking library I made)
--libvideo.a (the video library I made)
--libboost.a (boost library)
Initially, this project build just fine. I just had to make sure I had a simple line in my makefile like this:
LIBS+=audio network video
Recently, I had to change how my audio library works. I now am required to use a third-party library, and all I have is the header file (.h) and the shared object (.so) files. So the new structure at link time looks like so:
-myApp (the main application)
--libaudio.a (the audio library I made)
---libthirdparty.so (contains third-party audio handling functions)
--libnetwork.a (the networking library I made)
--libvideo.a (the video library I made)
--libboost.a (boost library)
This, in effect, means that I have an application with a static library linked in which makes calls to an external shared object. So, I put the header file in the appropriate location so I don't have any build errors when compiling libaudio.a, and put the libthirdparty.so file in a location where the linker searches for all my installed libraries.
At this point, I cannot get the thing to build. It just doesn't see libthirdparty.so file, even though I know it is in a location that the linker searches by default. For some reason, wrapping my libaudio code, as in the example below (borrowed from www.cplusplus.com) fixes the build error:
my_C_CPP_Header.h:
#ifndef MY_C_CPP_HEADER
#define MY_C_CPP_HEADER
/*check if the compiler is of C++*/
#ifdef __cplusplus
extern "C" {
int myOtherCfunc(int arg1, int arg2); /* a C function */
}
#endif
void myCppFunction1(); /* C++ function */
void myCppFunction2(); /* C++ function */
/*check if the compiler is of C++ */
#ifdef __cplusplus
}
#endif
#endif
Now, I have a new problem though. Now that it's building, it no longer statically links in libboost.a, and instead is crashing at startup due to libboost.so not being present. So, somehow this setup breaks how libboost is compiled in if I manage to get it to build at all.
Any suggestions are welcome. Thank you all in advance.

In the end, there was a "LIBPATH=" instead of a "LIBPATH+=" statement overriding the library include paths. Resolved.
Thank you all for your help.

Related

Having target_compile_definitions apply to static library that is linked in

As part of the build process we produce two executables from our source exe1 and exe2. These executables link in a static library which has to have some extra code run in the case of exe2 so the static library has the following code (changed for brevity).
#ifdef _EXE2_
Do certain stuff
#endif
now our CMakeLists.txt defines two targets exe1 and exe2, I tried the following change so that __EXE2_ would get defined only for exe2
target_compile_definitions(exe2 PUBLIC _EXE2_)
however it seems to me that the above line just adds this definition to exe2 and the static lib does not get that definition. Is there a way around this? or do i have to solve this with an exe configuration file. This is c++ code on linux if that helps in any way.
Why would it? The exe depends on the library, not the other way around. Generally, a library has no relation to the modules that include it.
A library is also built once regardless of how many applications include it. That's the whole point of having a library.
If you want you can just add the definitions globally in your main CMakeLists.txt:
add_compile_definitions(_EXE2_)
Note that identifiers beginning with an underscore followed by an uppercase letter are reserved and should not be used.

How to compile a static library with Codelite 11.0.0?

I would like to compile a static library out of all the functions I have written for a C++ project. I am using CodeLite 11.0.0 on Ubuntu 16.04, configured to use GCC as compiler.
I have followed the instructions in CodeLite's tutorial, according to which this should be possible, and changed the project type from Executable to Static Library.
After running the project (CTRL+F5 command), I expected to find a .a file in the /Debug folder, either along with, or in place of the executable file. All I could find, though, was the executable and a number of .o and .o.d files. The same I was finding when the project was set to Executable.
I tried to close and reopen CodeLite, but it did not help. I can't find any official/unofficial example of how to build a static library with CodeLite.
Does anyone know how to set-up CodeLite to produce a .a static library file?
As you've probably discovered, CodeLite allows you to change the type of a
project in the drop-down menu from Settings -> General -> Project type.
Doing so, however, does not change the name of the project target. So, if
you started off your project as an executable myprog - from which, say, the
Debug build generated ./Debug/myprog under the project folder - then
you change the project type to static library and rebuild it, the Debug
build will still generate ./Debug/myprog, but that file will now in fact
be a static library, lacking the customary lib-prefix and .a extension.
To give the output file a conventional static library name -
libmyprog.a - you need to go back into Settings -> General and
change Output File from:
$(IntermediateDirectory)/$(ProjectName)
to:
$(IntermediateDirectory)/lib$(ProjectName).a
Then rebuild the project and it will output a target that is a static
library and looks like one.
Of course, you must make the same changes to the project settings in both
the Debug and Release configurations if you want them both to produce
targets with the same file type and file name.
However...
If this way of converting a program project to a static library project does not
seem very slick, that could be because it is a conversion of very little use.
The static library produced after the conversion will contain exactly the same object
files that the program was built from, including the object file that defines
the main function of the original program. Let's suppose that object file
is main.o, and that it defines 0 or more other functions that the linker can see.
Any other program, newprog, that is linked with the static library must provide
its own main function in a different object file, so in any such linkage one of
two things must happen:-
The linkage of newprog does not need any function defined in libmyprog.a(main.o),
so libmyprog.a(main.o) is not linked and might as well not exist.
The linkage of newprog does need some function, foo, defined in libmyprog.a(main.o),
so libmyprog.a(main.o) is linked; then as well as the definition of foo, the
program links duplicate definitions of main - its own definition plus the
one in libmyprog.a(main.o). Duplicate definitions are an error, so the linkage fails.
Putting a definition of some program's main function into a member of a static
library is pointless, because if that member is ever needed in the linkage of another
program then its linkage will fail.
So converting your program project to a static library project calls for some
refactoring prior to the conversion:-
If any function that you want in the static library is defined in the same source
file as main, then you need to take it out of that source file and define it
is a different one.
After that, remove the source file that defines main from the project.
Lastly, convert and rebuild the project.
You have to do that refactoring to extract from your original program source code
a bunch of source files that are suitable for building into a static library.
Assuming you've done that, the straightforward way to create a static library with
CodeLite is to create a project for that purpose and in the New Project Wizard
choose Library -> Static Library as the project type instead of some kind
of executable.
Then just add either new or existing source files to the static library project
until it contains definitions of all the functions you want the library to
provide. Build, test, debug, edit... until done.

static and dynamic linking using gcc

I've been recently reading about static and dynamic linking and I understood the differences and how to create static and dynamic library and link it to my project
But, a question came to my mind that I couldn't answer or find answer for it as It's a specific question ... when I compile my code on linux using the line
#include <stdio.h>
int main()
{
printf("hello, world!\n");
}
compiling using this command
[root#host ~]# gcc helloworld.c -o helloworld
which type of linking is this??
so the stdio.h is statically or dynamically linked to my project???
Libraries are mostly used as shared resources so, that several different programs can reuse the same pre-compiled code in some manner. Some libraries come as standard libraries which are delivered with the operating system and/or the compiler package. Some libraries come with other third party projects.
When you run just gcc in the manner of your example, you really run a compiler driver which provides you with few compilation-related functions, calling different parts of the compilation process and finally linking your application with a few standard libraries. The type of the libraries is chosen based on the qualifiers you provide. By default it will try to find dynamic (shared) libraries and if missing will attempt for static. Unless you tell it to use static libs only (-static).
When you link to project libraries you tell the gcc/g++ which libraries to use in a manner (-lname). In such a way it will do the same as with the standard libraries, looking for '.so' first and '.a' second, unless -static is used. You can directly specify the path to the full library name as well, actually telling it which library to use. There are several other qualifiers which control the linking process, please look man for 'g++' and 'ld'.
A library must contain real program code and data. The way it is linked to the main executable (and other libraries) is through symbol tables which are parts of the libraries. A symbol table contains entries for global functions an data.
There is a slight difference in the structure of the shared and static libs. The former one is actually a pre-linked object, similar to an executable image with some extra info related to the symbols and relocation (such a library can be loaded at any address in the memory and still should work correctly). The static library is actually an archive of '.o' files, ready for a full-blown linking.
The usual steps to create a library is to compile multiple parts of your program into '.o' files which in turn could be linked in a shared library by 'ld' (or g++) or archived in .a with 'ar'. Afterwards you can use them for linking in a manner described above.
An object file (.o) is created one per a .cpp source file. The source file contains code and can include any number of header files, as 'stdio.h' in your case (or cstdio) or whatever. These files become a part of the source which is insured by the cpp preprocessor. The latter takes care of macros and flattening all the #include hierarchies so that the compiler sees only a single text stream which it converts into '.o'. In general header files should not contain executable code, but declarations and macros, though it is not always true. But it does not matter since they become welded with the main source file.
Hope this would explain it.
which type of linking is this?? so the stdio.h is statically or
dynamically linked to my project???
stdio.h is not linked, it is a header file, and contains code / text, no compiled objects.
The normal link process prefers the '.so' library over the '.a' archive when both are found in the same directory. Your simple command is linking with the .so (if that is in the correct path) or the .a (if that is found in a path with no .so equivalent).
To achieve static linking, you have several choices, including
1) copy the '.a' archive to a directory you create, then specify that
directory (-L)
2) specify the path to the '.a' in the build command. Boost example:
$(CC) $(CC_FLAGS) $< /usr/local/lib/libboost_chrono.a -o $# $(LIB_DIRs) $(LIB_NMs)
I have used both techniques, I find the first easier.
Note that archive code might refer to symbols in another archive. You can command the linker to search a library multiple times.
If you let the build link with the .so, this does not pull in a copy of the entire .so into the build. Instead, the .so (the entire lib) is loaded into memory (if not already there) at run-time, after the program starts. For most applications, this is considered a 'small' start-up performance hit as the program adjusts its memory map (auto-magically behind the scenes) Note that the app itself can control when to load the .so, called dynamic library.
Unrelated:
// If your C++ 'Hello World' has no class ... why bother?
#include <iostream>
class Hello_t {
public:
Hello_t() { std::cout << "\n Hello" << std::flush; }
~Hello_t() { std::cout << "World!" << std::endl; }
void operator() () { std::cout << " C++ "; }
};
int main(int, char**) { Hello_t()(); }

Lesson needed on how to work with files in different projects in C++

I have been able to work in the same project for sometime now, writing and successfully running c++ code. However, I discovered that I am still missing some essentials on how to export my .h files to another project and successfully use them in there.
I created a second project, project B to test the classes I have in project A.
visual c++: #include files from other projects in the same solution
I added the path of the header file in Project A into the Additional Include Directories(C\C++>general and Linker>general) section in the project configuration of Project B. I tried following the tutorials on this page http://msdn.microsoft.com/en-us/library/ms235636.aspx but I still end up with the error below
** LINK : fatal error LNK1104: cannot open file 'C:\Users\LaC\Projects\OSGB\Debug\OSGB.lib**
I would appreciate any help in understanding exactly how this is done so that in future, when I encounter this problem, I can know how to troubleshoot.
The code below is all I am working with.
IN PROJECT A
=============
//Utility.h
class Utility
{
private:
protected:
public:
Utility(void);
~Utility(void);
double square_root (const double);
};
//Utility.cpp
#include "StdAfx.h"
#include "Utility.h"
Utility::Utility(void)
{
//do nothing for now
}
Utility::~Utility(void)
{
//do nothing for now
}
double Utility::square_root (const double)
{
return 0;
}
IN PROJECT B
===============
#include "gtest/gtest.h"
#include "Utility.h"
TEST (SquareRootTest, PositiveNos) {
Utility u;
EXPECT_EQ (50.3321, u.square_root (2533.310224));
}
There are two (general) ways to include files into your project:
Make them a part of your project (adding them from the solution explorer) OR
Import them as a library (static or dynamic linking)
If you make them part of your project, then you have to add the header and the source files in order for the project to compile correctly. However, that's usually not what you want to do, as it defeats the purpose of having external libraries.
The second case is to use the external libraries, which requires that you:
Include the header files which are exported by the library in your C++ properties.
For static linking: you also have to include the *.lib file (the output of building the library) in the Linker properties.
OR
For dynamic linking: see tutorial.
So remember: there are two parts to building a C++ project- compiling and linking.
Compiler Errors:
If you get an error whose code starts with C* (e.g. C1083) and is related to problems header with the files, then check the Properties-> C/C++ -> General -> Additional Include Directories.
Linker Errors:
If you get an error whose code starts with LNK*, then check
Properties -> Linker -> General -> Additional Library Directories (make sure that this points to where the *.lib file is located)
AND
Properties -> Linker -> Input -> Additional Dependencies (make sure that the *.lib file is added here).
If you're dynamically linking, then check that you're correctly referencing the DLL.
So in your case, you have to determine if you're linking statically or dynamically and then make the appropriate references. So ware you getting those header files from a dynamically library or a static library?
When the linker emits unresolved external symbol for a symbol that lives in another library (DLL or shared library), this indicates that you need to link your app to that other library's .lib file. That is most likely what's happening here.
For more information see:
(MSDN) Walkthrough: Creating and Using a Dynamic Link Library (C++)

C++ MinGW shared libraries problem (Windows only,works on Linux)?

Greetings all,
I use MinGW,QT and CMake for my project.
As shown in the figure, my project has two modules.
libRinzoCore.DLL - a shared library which define some abstract classes and interfaces and some core functionality of the application.This module is used to implement dynamic Plugins (which are also shared libraries which automatically loaded by the application) .
Rinzo.exe - the main application.This uses "libRinzoCore" classes.
"libRinzoCore" mainly developed using QT objects and link against the QT library.
"Rinzo.exe" also uses QT library objects,some are not being used in "libRinzoCore".So I have to link QT Library and "libRinzoCore" with this executable.
I can compile "libRinzoCore" without problems and it generated two files "libRinzoCore.DLL" and "libRinzoCore.DLL.a"
But during compiling "Rinzo.exe" it gives the following output :
Linking CXX executable Rinzo.exe
Info: resolving IRzPlugin::staticMetaObject by linking to __imp___ZN9IRzPlugin16staticMetaObjectE (auto-import)
Info: resolving IRzViewerPlugin::staticMetaObject by linking to __imp___ZN15IRzViewerPlugin16staticMetaObjectE (auto-import)
Info: resolving IRzLayeringPlugin::staticMetaObject by linking to __imp___ZN17IRzLayeringPlugin16staticMetaObjectE (auto-import)
C:\MinGW\bin\..\lib\gcc\mingw32\3.4.5\..\..\..\..\mingw32\bin\ld.exe: warning: auto-importing has been activated without --enable-auto-import specified on the command line.
This should work unless it involves constant data structures referencing symbols
from auto-imported DLLs.
[100%] Built target Rinzo
And when executing "Rinzo.exe" it crashes with the message (this is a translation from Japanese error message)
" Application cannot performe
correctly (0xc0000005). Click [OK] to
cancel "
Here are my CMake files for
libRinzoCore :
http://www.keepandshare.com/doc/2199086/rinzocore-txt-august-31-2010-12-10-pm-2k?da=y
Rinzo.exe :
http://www.keepandshare.com/doc/2199085/rinzo-txt-august-31-2010-12-10-pm-5k?da=y
It works fine,If I compile "libRinzoCore" as a static-library.
And works fine on Linux.
Any tips?
On windows you need to declare "export" part of dynamic library to make it work.
#ifdef Q_WS_WIN
#ifdef RINZO_EXPORT
#define RINZO_LIB __declspec(dllexport)
#else
#define RINZO_LIB __declspec(dllimport)
#endif
#else
#define RINZO_LIB
#endif
Then you need to put RINZO_LIB in front of your class declaration inside of lib (only classess you want to "export", use in external code)
class RINZO_LIB YourExportedClass
{
...
}
Last part is to add preprocessor macro while compiling your library. As you can see it's RINZO_EXPORT
Remember, don't add this preprocessor macro, when "importing" (using code outside library).
Also all functions require RINZO_LIB macro to be visible outside library:
RINZO_LIB void yourExportedFunction()
{
...
}