Linker Configuration
The linker is the final stage of the translation pipeline. It accepts object files (.o or .obj) Generated by the compiler, resolves symbol references (functions and variables), performs Relocation, and generates the final executable or shared library.
In C++23 development, the default system linker is often the bottleneck for build iteration speeds. Replacing legacy linkers (like GNU BFD) with modern asynchronous linkers (LLD or Mold) can reduce Incremental link times by an order of magnitude.
The Landscape of Linkers
Section titled “The Landscape of Linkers”1. GNU ld.bfd
Section titled “1. GNU ld.bfd”- Status: Legacy Default.
- Platform: Linux/GNU.
- Characteristics: Extremely stable but single-threaded and slow. It uses low-memory algorithms designed for hardware from the 1990s.
2. GNU gold
Section titled “2. GNU gold”- Status: Maintenance Mode / Deprecated.
- Platform: Linux (ELF only).
- Characteristics: The first mainstream linker designed for C++. It introduced multithreading but has largely been superseded by LLD.
3. LLVM LLD
Section titled “3. LLVM LLD”- Status: Industry Standard Best Practice.
- Platform: Cross-Platform (ELF, COFF, Mach-O, Wasm).
- Characteristics:
- Drop-in replacement for system linkers.
- Highly parallelized.
- 2x-10x faster than BFD.
- Required for correct Cross-Compilation with Clang.
4. Mold
Section titled “4. Mold”- Status: High-Performance / Bleeding Edge.
- Platform: Linux (ELF), partial macOS/Windows support.
- Characteristics: Designed to utilize all available CPU cores and IO bandwidth. It aims to make linking as fast as file copying (
cp). It is significantly faster than LLD on large projects.
5. MSVC link.exe
Section titled “5. MSVC link.exe”- Status: Windows Default.
- Platform: Windows (COFF).
- Characteristics: Tightly integrated with PDB generation and Incremental Linking. While LLD (
lld-link) is faster,link.exeis required for certain “Edit and Continue” debugging features in Visual Studio.
Linker Comparison Matrix
Section titled “Linker Comparison Matrix”| Feature | GNU ld.bfd | GNU gold | LLVM LLD | Mold | MSVC link.exe |
|---|---|---|---|---|---|
| ELF support | Yes | Yes | Yes | Yes | No (COFF only) |
| COFF support | No | No | Yes (lld-link) | Partial | Yes |
| Mach-O support | No | No | Yes (ld64.lld) | Partial | No |
| Wasm support | No | No | Yes (wasm-ld) | No | No |
| Multithreading | No | Limited | Yes (highly parallel) | Yes (fully parallel) | Yes |
| Incremental linking | No | No | No | No | Yes |
| LTO support | Via GCC plugin | Via GCC plugin | Native | Via Clang/GCC plugin | Via MSVC LTCG |
| Linker scripts | Full | Full | ELF: Full, COFF: No | Full | No |
| ThinLTO | No | No | Yes | No | No |
| Typical speed vs BFD | 1x | 2-5x | 5-10x | 10-50x | N/A |
| Memory usage | Low | Medium | Medium | High | Medium |
| Symbol versioning | Yes | Yes | Yes | Yes | N/A |
| Cross-platform | No | No | Yes | No | No |
CMake Configuration Strategy
Section titled “CMake Configuration Strategy”Configuring the linker requires instructing the compiler driver (e.g., clang++ or g++) to invoke A specific underlying binary.
Modern CMake (Version 3.29+)
Section titled “Modern CMake (Version 3.29+)”CMake 3.29 introduced a generic abstraction for selecting linkers, removing the need for Compiler-specific flag handling.
cmake_minimum_required(VERSION 3.29)project(HighPerfCpp)add_executable(app main.cpp)# Select linker by type# Options: LLD, MOLD, APPLE_CLASSIC, MSVC, GNU, GOLDset_property(TARGET app PROPERTY LINKER_TYPE LLD)Legacy CMake (Pre-3.29)
Section titled “Legacy CMake (Pre-3.29)”For older CMake versions, linker flags must be manually injected.
# Check if using Clang or GCCif (CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") include(CheckCXXCompilerFlag) # Attempt to use Mold check_cxx_compiler_flag("-fuse-ld=mold" HAVE_MOLD) if (HAVE_MOLD) add_link_options("-fuse-ld=mold") else() # Fallback to LLD check_cxx_compiler_flag("-fuse-ld=lld" HAVE_LLD) if (HAVE_LLD) add_link_options("-fuse-ld=lld") endif() endif()endif()Link Time Optimization (LTO)
Section titled “Link Time Optimization (LTO)”Link Time Optimization (also known as IPO - Interprocedural Optimization) allows the compiler to Perform optimizations across translation unit boundaries. Instead of generating machine code in the .o files, the compiler generates intermediate bitcode (IR). The linker then merges all IR and runs The optimizer on the entire program at once.
Benefits
Section titled “Benefits”- Inlining: Functions defined in
math.cppcan be inlined intomain.cpp. - Dead Code Elimination: Unused parts of libraries can be aggressively stripped.
- Build Time: Link time increases drastically (often becoming single-threaded).
- Memory: High RAM usage during linking.
Enabling LTO in CMake
Section titled “Enabling LTO in CMake”CMake provides a portable abstraction for enabling LTO.
include(CheckIPOSupported)check_ipo_supported(RESULT result OUTPUT output)if(result) set_property(TARGET app PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)else() message(WARNING "IPO is not supported: ${output}")endif()ThinLTO (Clang/LLVM)
Section titled “ThinLTO (Clang/LLVM)”Standard LTO is monolithic. Clang supports ThinLTO, which parallelizes the LTO process, offering Similar runtime performance with significantly faster build times. To force ThinLTO specifically when using Clang:
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-flto=thin) add_link_options(-flto=thin)endif()LTO and Symbol Visibility
Section titled “LTO and Symbol Visibility”When using LTO with shared libraries, ensure that symbols intended for export are marked with Visible visibility. LTO can inline and eliminate symbols more aggressively, potentially removing Symbols that would otherwise be exported:
# Ensure public API symbols are preserved when building a shared library with LTOset_target_properties(MyLib PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON)Symbol Stripping
Section titled “Symbol Stripping”For release builds, removing debug symbols reduces binary size significantly.
Linux/macOS
Section titled “Linux/macOS”The strip utility removes symbols.
if (UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")endif()Windows (MSVC)
Section titled “Windows (MSVC)”Windows separates debug symbols into a .pdb file. The executable is stripped by default in Release Mode.
Section titled “Windows separates debug symbols into a .pdb file. The executable is stripped by default in Release Mode.”Verification
Section titled “Verification”To verify which linker is being used, inspect the verbose output of the build system.
- Configure CMake with Verbose Output:
Terminal window cmake -S . -B build -DCMAKE_VERBOSE_MAKEFILE=ON - Build and Inspect:
Terminal window cmake --build build - Analyze the Link Command: Look for the final linking step in the log.
- LLD: Will show
-fuse-ld=lldor direct calls told.lld. - Mold: Will show
-fuse-ld=moldor direct calls tomold. - BFD: invoked as just
ld(checkld --versionto confirm).
ELF Verification (Linux)
Section titled “ELF Verification (Linux)”Use readelf to check the .comment section of the resulting binary, which often contains the Linker signature.
readelf -p .comment build/appTarget Output (Example):
String dump of section '.comment': [ 0] Linker: LLD 16.0.0 [ 1c] clang version 16.0.0Linker Internals: How the Linker Works
Section titled “Linker Internals: How the Linker Works”Understanding what the linker actually does at the binary level is critical for diagnosing obscure Build failures and optimizing binary output.
Symbol Resolution
Section titled “Symbol Resolution”The linker maintains a global symbol table with three categories:
- Defined symbols: Functions and variables that are defined (have a body) in one or more object files.
- Undefined symbols: Symbols that are referenced but not defined in the current object file. These must be resolved by finding a matching definition in another object file or library.
- Common symbols: Tentative definitions (e.g.,
int x;at file scope withoutexternor an initializer). The linker allocates space for the largest definition and merges them. The resolution algorithm processes object files in the order they appear on the command line. When The linker encounters an object file, it adds all defined symbols to its table and records all Undefined symbols. If a subsequent object file or library provides a definition for a Previously-undefined symbol, the reference is patched. This ordering dependency is the root cause of the classic “undefined reference” error when linking Against static libraries. If libraryAdepends on libraryB``Amust appear beforeBon the Command line.
# WRONG order -- linker processes B first, finds no undefined symbols,# discards B's object files, then processes A and fails on unresolved refstarget_link_libraries(app PRIVATE B A)# CORRECT order -- A's undefined symbols are recorded, then resolved by Btarget_link_libraries(app PRIVATE A B)Modern CMake with target_link_libraries generally handles this correctly for targets within the Same build, but when consuming pre-built static libraries from external sources, the ordering still Matters because CMake respects the order you specify.
Relocation
Section titled “Relocation”Once all symbols are resolved, the linker performs relocation: patching placeholder addresses in Machine code with the final virtual addresses of symbols. Consider this C++ code compiled to x86_64:
extern int counter;int* get_counter() { return &counter; }The compiler emits a call to get_counter that returns a placeholder address. The linker must:
- Determine the final virtual address of
counter(defined in some other object file). - Patch the
leaormovinstruction inget_counterwith the actual address. - If the relocation target is in a shared library loaded at a dynamic base address, generate a PLT/GOT entry so the loader can resolve it at runtime. Relocation types on x86_64 ELF include: | Relocation Type | Description | Example Use | | :----------------------- | :----------------------------------------- | :------------------------------------ | |
R_X86_64_64| Absolute 64-bit address | Global variable access | |R_X86_64_PC32| 32-bit PC-relative | Near call/jump | |R_X86_64_PLT32| 32-bit PC-relative through PLT | External function call | |R_X86_64_GOTPCRELX| Optimized GOT access (lazy binding bypass) | Frequently called external function | |R_X86_64_REX_GOTPCRELX| REX-prefixed GOT access | RIP-relative GOT access in large code |
Static vs Dynamic Linking
Section titled “Static vs Dynamic Linking”The choice between static and dynamic linking has profound implications for deployment, security, And startup performance. Static Linking embeds all library code into the final executable:
# Force static linking of specific librariestarget_link_options(app PRIVATE -static-libgcc -static-libstdc++)Advantages:
- No external dependencies at runtime (simplifies deployment).
- The linker can perform whole-program optimization (dead code elimination across library boundaries).
- Slightly faster startup (no dynamic loader work). Disadvantages:
- Larger binary size (all library code is included, even unused portions of archive members).
- No shared memory between processes using the same library.
- Security patches require recompilation and redistribution. Dynamic Linking loads library code at runtime:
# Explicitly link shared librarytarget_link_libraries(app PRIVATE /usr/lib/libssl.so)The linker records the library dependency (DT_NEEDED) in the ELF dynamic section. At runtime, the Dynamic loader (ld.so) maps the shared library into the process address space and resolves Symbols.
Lazy Binding vs RELRO
Section titled “Lazy Binding vs RELRO”By default, ELF uses lazy binding (PLT stubs): function calls to shared libraries go through a Procedure Linkage Table (PLT). On first call, the dynamic loader resolves the actual address and Patches the GOT entry. Subsequent calls go directly through the GOT. This is a security risk: an attacker who overwrites the GOT before resolution can redirect Execution. RELRO (RELocation Read-Only) mitigates this:
# Full RELRO: makes the entire GOT read-only after resolutiontarget_link_options(app PRIVATE -Wl,-z,relro,-z,now)# Partial RELRO (default on many distros): only .init_array is read-onlytarget_link_options(app PRIVATE -Wl,-z,relro)- Partial RELRO:
.got.pltremains writable. The PLT stubs can still be exploited. - Full RELRO (
-z,now): All symbols are resolved at load time (no lazy binding), and the entire GOT is made read-only. This defeats GOT overwrite attacks at the cost of slightly slower startup. Best practice: Always use-Wl,-z,relro,-z,nowfor production builds.
Linker Scripts
Section titled “Linker Scripts”The linker’s behavior can be controlled programmatically via linker scripts (.ld files). These Define:
- Memory regions for embedded targets.
- Custom section ordering.
- Symbol assignments at link time.
Basic Linker Script Syntax
Section titled “Basic Linker Script Syntax”/* minimal.ld -- Place .text at 0x10000, .data after it */ENTRY(_start)SECTIONS{ . = 0x10000; .text : { *(.text*) } .rodata : { *(.rodata*) } .data : { *(.data*) } .bss : { *(.bss*) *(COMMON) }}# Use a custom linker scripttarget_link_options(firmware PRIVATE -T${CMAKE_SOURCE_DIR}/minimal.ld)Section Merging: Proof of Ordering
Section titled “Section Merging: Proof of Ordering”The linker processes input sections from all object files and merges them into output sections According to the linker script. The merging algorithm is deterministic:
- The linker reads each input object file in command-line order.
- For each object file, it extracts sections matching the patterns in the linker script.
- Sections are concatenated in the order they are encountered. Theorem: The order of input object files on the link command line determines the order of Functions in the
.textsection of the final binary. Proof: Consider two object files,a.oandb.oEach containing a.textsection. The linker Script contains.text : { *(.text*) }. The*(.text*)pattern matches all.textsections from All input files. The linker iterates over input files in command-line order. For each file, it Appends the matched sections to the output.textsection. Therefore,a.o’s.textprecedesb.o’s.textin the output if and only ifa.oprecedesb.oon the command line. This ordering matters for cache locality: placing frequently-called functions adjacent to each other Improves instruction cache hit rates.
Custom Section Markers
Section titled “Custom Section Markers”Linker scripts can define symbols that mark the boundaries of custom sections. This enables Compile-time registration patterns:
SECTIONS{ . = 0x8000; .text : { *(.text*) } /* Custom section for init functions */ .init_array : { __init_array_start = .; KEEP(*(.init_array*)) __init_array_end = .; }}// Source code references the linker-defined symbolsextern "C" { extern void (*__init_array_start[])(); extern void (*__init_array_end[])();}// Call all init functions at startupfor (auto* fn = __init_array_start; fn != __init_array_end; ++fn) { (*fn)();}Linker Script for Embedded (STM32)
Section titled “Linker Script for Embedded (STM32)”A realistic embedded linker script defines memory regions and places sections within them:
MEMORY{ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K}ENTRY(Reset_Handler)SECTIONS{ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) . = ALIGN(4); } > FLASH .text : { . = ALIGN(4); *(.text*) *(.rodata*) . = ALIGN(4); _etext = .; } > FLASH _sidata = LOADADDR(.data); .data : { . = ALIGN(4); _sdata = .; *(.data*) . = ALIGN(4); _edata = .; } > RAM AT > FLASH .bss : { . = ALIGN(4); _sbss = .; *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; } > RAM}Linker scripts are essential for bare-metal and embedded development where you control the entire Memory layout. On hosted platforms, they are occasionally used to:
- Enforce specific section ordering for cache locality.
- Define link-time symbols (e.g.,
__start_custom_sectionand__stop_custom_sectionmarkers). - Implement custom allocator regions.
Symbol Versioning
Section titled “Symbol Versioning”Symbol versioning is a mechanism that allows a shared library to expose multiple versions of the Same symbol. This is critical for backward compatibility when the implementation of a function Changes but its signature does not.
GNU Symbol Versioning
Section titled “GNU Symbol Versioning”#include <stdio.h>__asm__(".symver old_printf,printf@GLIBC_2.2.5");__asm__(".symver new_printf,printf@@GLIBC_2.17");void old_printf(const char* s) { puts("[legacy]"); puts(s); }void new_printf(const char* s) { puts("[modern]"); puts(s); }The @@ (double at-sign) denotes the default version. The @ (single at-sign) denotes a Non-default version. Binaries compiled against older glibc versions will resolve to the @GLIBC_2.2.5 version, while newer binaries resolve to @@GLIBC_2.17. Symbol versioning is the mechanism that allows libstdc++.so.6 to maintain backward compatibility Across GCC releases. The .so version number never changes (it stays at .6), but individual Symbols within the library are versioned:
nm -D /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX# Contains entries like:# _ZNSt6vectorIiSaIiEE9push_backERKi@@GLIBCXX_3.4.21# _ZNSt6vectorIiSaIiEE9push_backERKi@GLIBCXX_3.4Inspecting Symbol Versions
Section titled “Inspecting Symbol Versions”# Show symbol versions in a shared libraryobjdump -T /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep -A1 GLIBCXX# Show which version a binary requiresreadelf -V /usr/bin/myappThe -Wl, Flag Mechanism
Section titled “The -Wl, Flag Mechanism”The -Wl, prefix passes flags from the compiler driver to the linker. The comma separates Individual linker arguments. This is necessary because the compiler driver controls the linking Phase and does not pass unrecognized flags to the linker.
# Pass -z relro and -z now to the linkerclang++ main.cpp -Wl,-z,relro,-z,now# Pass a linker script and --gc-sectionsclang++ main.cpp -Wl,-T,memory.ld,--gc-sections# Pass a library search pathclang++ main.cpp -Wl,-L,/custom/lib/path# Set the output format (ELF32 vs ELF64)clang++ main.cpp -Wl,-m,elf_x86_64In CMake, use target_link_options to pass these flags:
target_link_options(app PRIVATE "LINKER:-z,relro" "LINKER:-z,now" "LINKER:-T,${CMAKE_SOURCE_DIR}/memory.ld" "LINKER:--gc-sections")The LINKER: prefix in CMake 3.13+ automatically adds the -Wl, wrapper, improving portability.
Section titled “The LINKER: prefix in CMake 3.13+ automatically adds the -Wl, wrapper, improving portability.”Common Linker Errors and Their Causes
Section titled “Common Linker Errors and Their Causes””undefined reference to symbol”
Section titled “”undefined reference to symbol””The linker could not find a definition for the referenced symbol. Common causes:
- Missing source file in the build (forgot to add a
.cpptoCMakeLists.txt). - Wrong link order for static libraries.
- Conditional compilation excluded the definition (
#ifdefguard not met). - Name mangling mismatch (linking C++ code against a C library without
extern "C").
// Correct: tells the compiler to use C linkage (no mangling)extern "C" { void c_library_function(int arg);}“multiple definition of symbol”
Section titled ““multiple definition of symbol””Two or more translation units define the same symbol with external linkage. Common causes:
- A function definition in a header file without
inline. - A global variable defined in a header file (not
inlineorconstexprin C++17+). - The same source file compiled twice and linked.
”relocation truncated to fit”
Section titled “”relocation truncated to fit””A relocation requires more bits than the instruction encoding provides. Common on 32-bit x86 when The code model is small (default) but the binary exceeds 2GB.
# Use the large code model if you have enormous binariesclang++ -mcmodel=large ...Common Pitfalls
Section titled “Common Pitfalls”- Forgetting
-Wl,-z,relro,-z,nowon production builds. This leaves the GOT writable, exposing your binary to GOT overwrite attacks. - Mixing static and dynamic C++ runtime libraries. On Linux, if one library links
libstdc++statically and another dynamically, you get two copies of the C++ runtime with separate global state. This causes crashes indynamic_cast``typeidAnd exception handling. Use-static-libgcc -static-libstdc++consistently or not at all. - Not specifying
CMAKE_EXE_LINKER_FLAGScorrectly for LLD. On some systems,lldis installed asld.lldbut not in the PATH. UseCMAKE_LINKERto specify the absolute path. - Enabling LTO without cleaning the build directory. LTO generates
.ofiles containing LLVM bitcode instead of machine code. Mixing LTO and non-LTO object files from a previous build causes cryptic linker errors. Always do a clean build when toggling LTO. - Using
-fuse-ld=moldon CI where mold is not installed. The build will silently fall back to the default linker. Usecheck_cxx_compiler_flagto verify availability, or install mold as a build dependency. - Linker script errors with
-Wl,--gc-sections. If your linker script does not useKEEP()for sections that must not be garbage-collected (like interrupt vector tables), the linker may remove them. Always useKEEP(*(.isr_vector))or equivalent for critical sections. - Circular dependencies between static libraries. If library
Adepends onBandBdepends onAThe linker cannot resolve symbols in a single pass. Solutions: (1) merge the libraries, (2) use--start-group/--end-groupto enable multiple passes, or (3) refactor to eliminate the circular dependency.
See Also
Section titled “See Also”- Installing a Compiler — Compiler selection affects linker choice
- Cross-compilation Toolchains — Cross-linker considerations
- Language Standard and ABI Compatibility — ABI constraints on linking
Appendix: Linker Script Reference
Section titled “Appendix: Linker Script Reference”Memory Region Definitions
Section titled “Memory Region Definitions”Linker scripts can define memory regions with specific attributes. This is used in embedded systems Where different memory types (flash, RAM, registers) have different access permissions:
MEMORY{ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K CCM (rw) : ORIGIN = 0x10000000, LENGTH = 64K}The attributes in parentheses control what can be placed in each region:
r— readablew— writablex— executable
Section Placement with KEEP
Section titled “Section Placement with KEEP”By default, the linker’s garbage collector (--gc-sections) removes unreferenced sections. The KEEP() directive prevents specific sections from being collected:
SECTIONS{ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) KEEP(*(.isr_vector.*)) } > FLASH}PROVIDE and ASSERT
Section titled “PROVIDE and ASSERT”PROVIDE defines a symbol only if it is not already defined by the application:
PROVIDE(__stack_start = ORIGIN(RAM) + LENGTH(RAM));ASSERT evaluates an expression at link time and errors if it fails:
ASSERT(. <= ORIGIN(FLASH) + LENGTH(FLASH), "Flash overflow")ASSERT(. <= ORIGIN(RAM) + LENGTH(RAM), "RAM overflow")PHDRS: Program Header Control
Section titled “PHDRS: Program Header Control”For ELF binaries, the linker script can control which sections are mapped into which program Segments (PT_LOAD, PT_NOTE, etc.):
PHDRS{ text PT_LOAD FLAGS(7); /* Read + Write + Execute (for self-modifying code) */ rodata PT_LOAD FLAGS(4); /* Read only */ data PT_LOAD FLAGS(6); /* Read + Write */}SECTIONS{ .text : { *(.text*) } :text .rodata : { *(.rodata*) } :rodata .data : { *(.data*) } :data .bss : { *(.bss*) *(COMMON) } :data}Output Section Types
Section titled “Output Section Types”The linker supports several output section types beyond the default loadable section:
SECTIONS{ /DISCARD/ : { *(.comment) *(.note*) *(.eh_frame*) } .noinit (NOLOAD) : { *(.noinit) }}/DISCARD/: Sections listed here are not included in the output binary.NOLOAD: The section is allocated space but not loaded into memory at runtime. Useful for zero-initialized regions in embedded systems.
Appendix: Linker Flag Quick Reference
Section titled “Appendix: Linker Flag Quick Reference”GNU/LLD Linker Flags
Section titled “GNU/LLD Linker Flags”| Flag | Purpose |
|---|---|
-z relro | Partial RELRO (read-only relocations) |
-z now | Full RELRO (no lazy binding) |
-z noexecstack | Make the stack non-executable |
-z defs | Require all symbols to be resolved at link time |
-z origin | Allow $ORIGIN in RPATH |
--gc-sections | Remove unreferenced sections |
--as-needed | Only link libraries that are actually used |
--no-as-needed | Link all specified libraries (legacy behavior) |
--whole-archive | Force include all symbols from a static lib |
--no-whole-archive | Revert to default selective inclusion |
-rpath /path | Set runtime library search path |
-rpath-link /path | Set link-time only search path |
--build-id=sha1 | Embed a build ID for crash reporting |
-Map=output.map | Generate a linker map file |
--print-map | Print the link map to stdout |
In CMake
Section titled “In CMake”target_link_options(app PRIVATE "LINKER:-z,relro" "LINKER:-z,now" "LINKER:--gc-sections" "LINKER:--as-needed" "LINKER:-rpath,$ORIGIN/../lib" "LINKER:-Map,${CMAKE_BINARY_DIR}/app.map")Summary
Section titled “Summary”This topic covers the core concepts of linker configuration, including underlying theory, practical implementation, and key applications. Key concepts include:
- command-line fundamentals
- file permissions and ownership
- process management
- shell scripting with bash
- package management Understanding these concepts thoroughly is essential for both examinations and practical programming, and requires both theoretical knowledge and hands-on practice.
Worked Examples
Section titled “Worked Examples”Worked examples demonstrating the application of key concepts are covered in the detailed sub-pages linked above.