You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This document compiles the core terms used throughout the project tutorials, grouped by domain, with Chinese and English translations. Its purpose is to ensure consistent terminology across all articles, preventing the same concept from being translated differently in different places.
17
+
This document compiles the core terms used throughout the project tutorials, grouped by domain, with Chinese and English translations. The goal is to ensure consistent terminology across all articles, preventing the same concept from being translated differently in different places.
# Deep Dive into C/C++ Compilation and Linking Part 3: How to Create and Use Static Libraries
15
21
16
-
In the previous blog post, I briefly covered the basic introduction to static and dynamic libraries. I have linked them here:
22
+
In the previous blog post, I briefly touched upon the basic introduction to static and dynamic libraries. I have included the links here:
17
23
18
24
> [Deep Dive into C/C++ Compilation and Linking - CSDN Blog](https://blog.csdn.net/charlie114514191/article/details/152921903)
19
25
>
20
26
> [Deep Dive into C/C++ Compilation and Linking Part 2: Introduction to Dynamic and Static Libraries - CSDN Blog](https://blog.csdn.net/charlie114514191/article/details/154828385)
21
27
22
-
So earlier, we simply explained what the essence of a static library is. Although today, using dynamic libraries for code sharing is a more fundamental strategy, for the sake of completeness—and because I personally like using static libraries to package something that only depends on `C/C++` the most basic runtime (honestly, I have no solid technical reason for this choice; I just don't like feeding a massive chunk of relocatable files directly to the linker)—let's continue.
28
+
So earlier, we briefly covered what the essence of a static library is. Although today, using dynamic libraries for code sharing is a more fundamental strategy, for the sake of completeness—and because I personally like using static libraries to package something that only depends on `C/C++` the most basic runtime (honestly, I have no deep technical reason for this choice; I just don't really like feeding a massive blob of relocatable files directly to the linker)—let's continue.
23
29
24
30
## How Do We Create a Static Library?
25
31
26
32
### `ar` Tool
27
33
28
-
So a natural question arises: we previously learned the fundamental principle of a static library (an organic combination of several relocatable files), but how do we actually create one? The answer is a small yet powerful tool—`ar` (Archiver).
34
+
So a natural question arises: we previously learned the fundamental principle of a static library (an organic combination of several relocatable files), but how do we actually create one? The answer is by using a small yet powerful tool—`ar` (Archiver).
29
35
30
-
Let me briefly introduce `ar`! It is a tool used to create, modify, and extract **archive files**. These archive files typically end with the `.a` extension (where "a" stands for archive), and their most common use case is packaging object files (`.o` files) to create **static libraries**. On Linux, if we are creating a static library (at least a static library) and decide to name it `Charlie`, the generated library will generally be `libCharlie.a`.
36
+
Let me briefly introduce `ar`! It is a tool used to create, modify, and extract **archive files**. These archive files typically end with the `.a` extension (where "a" stands for archive), and their most common use case is packaging object files (`.o` files) to create **static libraries**. On Linux, when we create a static library—assuming we decide to name the library `Charlie`—the generated library will generally be `libCharlie.a`.
31
37
32
-
Some might wonder why it must start with `lib`. Wouldn't generating `Charlie.a` be more intuitive? The core reason is: **this is dictated by the working conventions of the linker when we perform linking later**. Most commonly, when we `gcc/g++` compile and prepare to link objects, we dispatch `ld` to link the target libraries and relocatable files. Generally, upper-level build tools prefer using the `-L` flag to specify the search directory combined with `-l` (a lowercase L) to find the library. For example, when we try to provide the well-known `math` static library to `main.c` at a specified path, we might write something like this:
38
+
Some of you might wonder why it must start with `lib`. Wouldn't generating `Charlie.a` be much more intuitive? The core reason is: **this is dictated by the working conventions of the linker when we perform linking later**. Most commonly, when we `gcc/g++` compile and prepare to link objects, we dispatch `ld` to link the target libraries and relocatable files. Generally, higher-level build tools prefer using the `-L` flag to specify the search directory, combined with `-l` (lowercase L) to find the library. For example, when we try to provide the `math` static library from a known path to `main.c`, we might write something like this:
33
39
34
40
```cpp
35
41
@@ -43,7 +49,7 @@ The linker does not directly look for a file named `math`. Instead, following co
43
49
- The linker automatically prepends the prefix `lib` to this name.
44
50
- Then, depending on the situation (and priority), it appends a suffix like `.a` (static library) or `.so` (dynamic library) to form the complete filename.
45
51
46
-
Therefore, **naming the library file in the `lib<name>.a` format is to proactively cater to the linker's automatic search mechanism**. If the library file is not named in this format, the linker cannot find it via the convenient `-l` option. You would have to link by directly specifying the full path to the library file, which is very cumbersome. Furthermore, this leads to a serious issue that we will revisit when discussing dynamic libraries (for static libraries, it doesn't matter since they get packaged into the target file).
52
+
Therefore, **naming the library file in the `lib<name>.a` format is to proactively cater to the linker's automatic search mechanism**. If the library file is not named in this format, the linker cannot find it via the convenient `-l` option. You would have to rely on the clumsy method of specifying the full path to the library file to link it, which is highly inconvenient. Furthermore, this leads to a severe issue that we will revisit when discussing dynamic libraries (for static libraries, it doesn't matter since they get packaged into the target file anyway).
|**`r`**|**Insert/Replace**: Adds files to the archive. If a file with the same name already exists, it replaces it. |`v` (verbose output) |`ar rv libmy.a file1.o file2.o`|
60
-
|**`t`**|**List**: Displays the list of files contained in the archive. |`v` (verbose output) |`ar t libmy.a`|
66
+
|**`t`**|**List**: Displays the list of files contained in the archive. |`v` (verbose output) |`ar t libmy.a`|
61
67
|**`x`**|**Extract**: Extracts (unpacks) files from the archive. |`v` (verbose output) |`ar xv libmy.a`|
62
68
63
69
> Checking the man page is always a good idea: [ar(1) - Linux man page](https://linux.die.net/man/1/ar)
64
70
65
71
### What About Windows?
66
72
67
-
This is actually handled by the MSVC toolchain. However, few people do this manually on Windows. On Windows, most people delegate this task to the massive IDE: Visual Studio, or like me, use lightweight Visual Studio Code and delegate to CMake. For specific details, you can check the detailed build logs from CMake, but I won't expand on that here for the sake of brevity.
73
+
This is actually handled by the MSVC toolchain. However, few people do this manually on Windows. On Windows, most people delegate this task to the monolithic IDE, Visual Studio, or, like me, use lightweight Visual Studio Code and delegate to CMake. For specific details, you can check the detailed build logs from CMake, but I won't expand on that here for the sake of brevity.
68
74
69
75
## Where Do We Use Static Libraries?
70
76
71
-
I thought about this carefully, combining my shallow engineering experience (which I can honestly say is almost non-existent) with the materials I have read. In fact, today, static libraries can almost entirely be replaced by dynamic libraries. However, in the following scenarios, using static libraries is clearly more appropriate. Of course, I use static libraries more often in embedded systems, so I will frame it this way:
77
+
I thought about this carefully, combining my shallow engineering experience (which I admit is practically non-existent) with the materials I've read. In fact, today, static libraries can almost entirely be replaced by dynamic libraries. However, in the following scenarios, using static libraries is clearly more appropriate. Of course, since I use static libraries more often in embedded systems, I'll frame it this way:
72
78
73
-
-**Simplified distribution:** We only need to distribute a single executable file, without carrying a bunch of `.dll` (Windows) or `.so`/`.dylib` (Linux/macOS) files.
79
+
-**Simplified distribution:** We only need to distribute a single executable file, without carrying around a bunch of `.dll` (Windows) or `.so`/`.dylib` (Linux/macOS) files.
74
80
-**Version locking:** We need to **absolutely guarantee** that our program uses a specific version of a library, free from interference by other versions on the user's system.
75
-
-**Small tools or embedded systems:** In environments with strict limitations on the number of files or dynamic linking support.
81
+
-**Small utilities or embedded systems:** In environments with strict limitations on file count or dynamic linking support.
76
82
77
83
## Conversely, What Are the Reasons Not to Use Static Libraries?
78
84
79
-
Reviewing the previous blog post, we have already explained how static libraries work. So, it is easy to think of the first reason not to use them:
85
+
Reviewing the previous blog post, we already explained how static libraries work. So, it's easy to think of the first reason not to use them:
80
86
81
87
#### Executable Bloat
82
88
83
-
When focusing on **interface reuse**, using static libraries obviously causes the size of all dependent libraries and executables to increase dramatically (executable bloat). Therefore, **for any module whose purpose is to provide functional interfaces to other dependencies and that operates independently, please use a dynamic library**. In this case, keeping only one copy of the code dependency and letting the operating system and loader automatically coordinate all mapped symbol relationships is clearly the better approach.
89
+
When focusing on **interface reuse**, using static libraries obviously causes the size of all dependent libraries and executables to increase dramatically (Executable Bloat). Therefore, **for any module whose purpose is to provide functional interfaces to other dependencies and that stands completely independent, please use a dynamic library**. In this case, keeping only one copy of the code dependency and letting the operating system and loader automatically coordinate all mapped symbol relationships is clearly the better approach.
84
90
85
91
#### Updates Require Recompilation and Redistribution (Hot Reloading Request)
86
92
87
-
In scenarios that prioritize **hot reloading**, using static libraries is clearly inappropriate. For example, when we cannot easily replace the executable file itself but only need to update a sub-dependency (say, a library we use has a vulnerability discovered by an enthusiastic open-source developer who promptly reports it to us)—that is, when we discover a security vulnerability or a bug in the library that needs fixing—with a static library, we must **recompile and redistribute the entire application (static linking makes this code a part of the main body rather than a required dependency)**.
93
+
In scenarios that prioritize **hot reloading**, using static libraries is clearly inappropriate. For example, when we can't easily replace the executable file itself but only need to update a sub-dependency (say, a library we use has a vulnerability discovered by an enthusiastic open-source developer who promptly reports it to us)—meaning we find a security vulnerability or a bug in the library that needs fixing—with a static library, we must **recompile and redistribute the entire application (static linking makes this code a part of the main body rather than a required dependency)**.
88
94
89
95
#### Potential Symbol Collisions and Version Management Issues (Symbol Collisions)
90
96
91
-
If we link **multiple versions** of static libraries or static libraries with **identical symbol names** into the same executable, the compiler/linker will attempt to resolve them, but the risk is very high (if I remember correctly, it drops them randomly based on symbol strength and equality). This is truly dangerous; nobody likes playing a guessing game with their program.
97
+
If we link **multiple versions** of static libraries or libraries with **identical symbol names** into the same executable, the compiler/linker will attempt to resolve them, but the risk is very high (if I remember correctly, it drops them based on symbol strength, or randomly discards them if they are equal). This is truly dangerous—nobody likes playing a guessing game with their program.
0 commit comments