C++ is a compiled language, which means that the code you write is translated into machine code before it is executed. While compiling a small program is usually quite painless, things can get complicated when the project grows.
Static and dynamic libraries
When you compile a program, you can link it to libraries. There are two types of libraries: static and dynamic.
Static libraries
A static library is a file that contains compiled code that can be linked to a program at compile time. The code from the library is copied into the program, and the program is then compiled into a single executable file.
To create a static library, you can use the ar
command to create an archive of object files.
# Create a static library
ar rcs libmylib.a file1.o file2.o
To check what libraries are linked to a binary, you can use the ldd
command.
Find what libraries are linked statically to a binary
nm -D binary
Dynamic libraries
A dynamic library is a file that contains compiled code that can be linked to a program at run time. The code from the library is not copied into the program; instead, the program is linked to the library at run time.
To create a dynamic library, you can use the gcc
command with the -shared
option.
# Create a dynamic library
gcc -shared -o libmylib.so file1.o file2.o
To check what libraries are linked to a binary, you can use the ldd
command.
# Check what libraries are linked to a binary
ldd binary
Data in Elf files
RPATH
rpath designates the run-time search path hard-coded in an executable file or library. Dynamic linking loaders use the rpath to find required libraries.
# Get rpah of a library
readelf -d bazel-bin/dlinear/libdlinear.so | grep 'R.*PATH'
SONAME
soname is the name of the shared library. It usually considered by other binaries to link against the right version of the shared library at run time.
# Get the SONAME
objdump -p libdlinear.so | grep SONAME
NEEDED
When a binary is linked to any number of shared libraries, they are marked as NEEDED in the binary to ensure they will be loaded at runtime. The NEEDED field is usually taken from the SONAME of the shared library. If the SONAME is not present, the NEEDED field will be the path to the file.
# Get the NEEEDED
objdump -p libdlinear.so | grep NEEDED
Compilation flags
gcc
General flags
-c
: Compile or assemble the source files, but do not link-o
: Place the output into the specified file-L
: Add the directory to the list of directories to be searched for libraries-l
: Link with the library
Preprocessor flags
-I
: Add the directory to the list of directories to be searched for header files-Iquote
: Add the directory to the list of directories to be searched for header files, but only through#include "file"
- This is useful when you want to include a header file from the current directory.
#include <file>
would not work in this case
- This is useful when you want to include a header file from the current directory.
Linker flags
-Wl,-rpath-link=.
: Add the current directory to the link-time search path-Wl,-rpath=.
: Add the current directory to the runtime search path-shared
: Create a shared library-fPIC
: Generate position-independent code- This is required when creating shared libraries
Warning flags
-Wall
: Enable all warnings-Wextra
: Enable extra warnings-Werror
: Treat warnings as errors- This flag will cause the compiler to stop if any warnings are generated
Optimization flags
-O0
: Disable optimization-O1
: Optimize for size-O2
: Optimize for speed-O3
: Optimize for speed and size
Debugging flags
-g
: Generate debugging information
Security flags
-U_FORTIFY_SOURCE
: Disable the fortify source feature- This feature is used to detect some buffer overflow errors when using standard library functions
-fstack-protector
: Enable stack protection- This feature adds a canary value to the stack to detect buffer overflow errors
Dependency flags
-MD
: Generate dependency information-MMD
: Generate dependency information, but do not include system headers-MF <file>
: Write dependency information to the specified file