C++_Compilation_Linking - RicoJia/notes GitHub Wiki
========================================================================
========================================================================
- symbol: During compilation, any non-static global variables? and functions will generate symbols in object files.
- So linker can decide different modules (shared libs, executables, object files) share the same variables or funcs.
- e.g, a.o and b.o will both have a symbol for shared_var, and their symbols will contain the same address after linker's resolution
//A.c extern int shared_var; //B.c int shared_var
- Some functions/classes in the shared lib can be linked to outside applications.
- Nice explaination
- static lib can call a shared lib's function, but that will be linked during linking.
- fvisibility = hidden doesn't apply to static lib as it has static linkage, and static linkage has public visibility
-
types of lib files
- .o files can be used as a "library"
- Others can use it to link against their programs
gcc -g -o output test.c libtest.o
.so
- aka
dll
on windows,.dylib
for macOS - loads in runtime
- compile needs
-fPIC
and-shared
flags - link needs flag
-L
, meaning "look in the current directory" -
-ltest
meanslibtest
-
-lc
meanslibc
, where holds printf, malloc, etc
-
- See
SEARCH_DIR
for default librariesld --verbose | grep SEARCH_DIR
-
ld --verbose
ld is link editor that generates object files. - You will see something like
/usr/lib
-
-
.so
has smaller code size- Because it's loaded at runtime, the other programs don't need to have this code during compile time
- So this gives better modularity for bug fixes as well
- If you don't use
.so
, then you use.a
(static library)
.a
- static library will be part of your program
- static library is made by
ar (archive)
, having the files all bundled upar rcs libtest.a littest1.o libtest2.o ...
- r means replacing other files with the same name in the archive
- c means to create if it's not there yet
- s means to generate index for the library
- linking looks the same as shared lib, you need
-ltest
- But this lib will be stuffed into your binary
- Then you don't need the library anymore
-
static lib
- what happens in linking:
- is just a lib file, archived with a collection of object files (.o), just like a tar/zip file.
- so they're not linked. linker will still need to link them, but it will be easier for them.
- So yes, a static lib can work with shared lib, and final linking will be done by making the executable
-
when you see
‘SomeClass’ declared with greater visibility than the type of its field ‘SomeClass::member’ [-Wattributes]”
- that means your code (visible to other modules) are using a shared' libs code that's not visible to other modules. 1. Make sure that code is truly visible to other modules 2. if not, try
-fvisibility=hidden
, the shared_lib must have this flag too.
- that means your code (visible to other modules) are using a shared' libs code that's not visible to other modules. 1. Make sure that code is truly visible to other modules 2. if not, try
========================================================================
========================================================================
- extern "C"
-
Summary
- tells the compiler go outside my scope, the variable is defined somewhere, but the compiler doesn't need to know where it is at the moment.
- not definition
- The .o files will be linked together, this happens at that stage.
-
first make the
.o
from c, then link it to c++ -
Uses
- Canonical Use 1, in a header file
//h file extern int i; //extern means it's defined somewhere else. // source_1.cpp int i = 3; //sournce_2.cpp int main(){ cout <<i; }
- Canonical Use 2: in two source files, which are linked thru a header file
// source_1.cpp int i = 3; // sournce_2.cpp extern i; cout <<i;
- This was done in linking.
- ** If you can't find i, you will get undefined reference.**
- Multiple definition is not allowed, you can define i only once
- Edge Use 3: **extern tell the compiler to go outside the current scope.
**
//source.cpp int a = 9; { extern int a; printf("%d", a); }
- extends variable visibility, only for declaring, not for defining.
#include "def.h" // has int i = 3; in its extern int i; int main (){ i = 1; }
- Exception is function declared with an initial value
extern int i = 1; int main(){ i = 3; }
- extends variable visibility, only for declaring, not for defining.
-
-
Header and multiple definitions
-
a cpp file will become an
.o
file, which will become a translational unit of itself. To make a final executable, multiple translational units will be linked together. -
if two
cpp
files include the same header file, the include guard will prevent each single cpp file from including the the header file twice, but it doesn't do anything for linking.- In hfile,
void foo()
will be linked twice, that's multiple definition error - In hfile,
inline void foo()
will be copied to the two translational units. - This is one definition rule: (ODR)
- In hfile,
-
class member functions inside the function body, with the declaration, then compiler will see it as inline functions, which is okay. Also, you can declare your enum class with its definition as well.
// header.hpp class Foo(){ // this is ok void foo(){ } }
-
-
The multiple Definition Error
- check include guard
- check if your binary and you lib have included the same files together.
- For libs that must have an
cpp, or cu
, it's okay to have function definitions in.hpp
files, but this case will introduce "multiple definitions" error.
// a.hpp #ifndef __A__ //include guard will prevent multiple inclusion in a cpp file, but will not protect its functions will be included, and potentially defined in different translational units (e.g, lib src files and user src file) #define __A__ void Foo(){} #endif //b.hpp #include "a.hpp" //lib.cpp #include "b.hpp" //user.cpp, using lib #include "b.cpp"
- To solve this issue, you can 1. define hpp functions, variables in a src, or 2. declare a function as static (so the functions defined in header will be only visible to the current transaltional unit)