英文:
Meaning of `-l` (lowercase "L") flags in gcc/g++
问题
What is the meaning of -l
(lowercase "L") flags passed to gcc/g++? And where can I find documentation or tutorials on it?
I've tried searching man gcc
and man ld
for -l
, but that has thousands of matches.
Example of a -l
flag:
in this:
gcc -Wall -Wextra -Werror -O3 -std=c17 hello_world_extra_basic.c -o bin/a -lm && bin/a
-lm
says to include the math library (static .a or dynamic .so?--I don't know) so you can use functions like sin()
from math.h
.
See:
But I need more detail than that:
-
What does calling
-lgtest
or-lm
really do? I can clearly manually pass the-I
include directories, and.a
static prebuilt files myself, for instance, like this from my answer here:# to manually build "googletest/googletest/samples/sample1_unittest.cc" time ( \ time g++ -Wall -Wextra -Werror -O3 -std=c++17 -pthread \ -I"googletest/googletest/include" -I"googletest/googlemock/include" \ googletest/googletest/samples/sample1_unittest.cc \ googletest/googletest/samples/sample1.cc \ bin/libgtest.a bin/libgtest_main.a \ -o bin/a \ && time bin/a \ )
What does
-lgtest
do instead, and what has to be in-place for this to work? -
Why
-l
? Is that part of what must be present in the name? Does "l" mean something like 'linker'? Do these flags go to the compiler or the linker? -
Why
-lpthread
vs-pthread
? I've seen both before and don't understand the difference. -
Are
-l
includes linking to static.a
libraries, or to runtime.so
libraries? Where do these libraries exist in your filesystem? -
How does this relate to the output of
sudo ldconfig -v
which I see here? -
Can you add your own
-l
flags? How?
Update: searching ld --help
shows this, so l
must stand for 'library,' but is that static or dynamic?:
-l LIBNAME, --library LIBNAME Search for library LIBNAME
英文:
What is the meaning of -l
(lowercase "L") flags passed to gcc/g++? And where can I find documentation or tutorials on it?
I've tried searching man gcc
and man ld
for -l
, but that has thousands of matches.
Example of a -l
flag:
in this:
gcc -Wall -Wextra -Werror -O3 -std=c17 hello_world_extra_basic.c -o bin/a -lm && bin/a
-lm
says to include the math library (static .a or dynamic .so?--I don't know) so you can use functions like sin()
from math.h
.
See:
But I need more detail than that:
-
What does calling
-lgtest
or-lm
really do? I can clearly manually pass the-I
include directories, and.a
static prebuilt files myself, for instance, like this from my answer here:# to manually build "googletest/googletest/samples/sample1_unittest.cc" time ( \ time g++ -Wall -Wextra -Werror -O3 -std=c++17 -pthread \ -I"googletest/googletest/include" -I"googletest/googlemock/include" \ googletest/googletest/samples/sample1_unittest.cc \ googletest/googletest/samples/sample1.cc \ bin/libgtest.a bin/libgtest_main.a \ -o bin/a \ && time bin/a \ )
What does
-lgtest
do instead, and what has to be in-place for this to work? -
Why
-l
? Is that part of what must be present in the name? Does "l" mean something like 'l'inker? Do these flags go to the compiler or the linker? -
Why
-lpthread
vs-pthread
? I've seen both before and don't understand the difference. -
Are
-l
includes linking to static.a
libraries, or to runtime.so
libraries? Where do these libraries exist in your filesystem? -
How does this relate to the output of
sudo ldconfig -v
which I see here? -
Can you add your own
-l
flags? How?
Update: searching ld --help
shows this, so l
must stand for 'l'ibrary, but is that static or dynamic?:
> -l LIBNAME, --library LIBNAME
> Search for library LIBNAME
答案1
得分: 1
我已经弄清楚得足够好,以至于感到舒适地发布一个答案。我通过大量的试验和错误,几乎已经弄清楚了以下所有内容,正如我在我的答案中所写。
有关完整详情,请参见我的答案末尾的“深入了解”部分:如何在Linux上设置googleTest作为共享库:“进一步了解:关于库的一般信息;调试;gcc/g++编译器标志等”
以下是一些关键要点:
-
如我在问题底部弄清楚的那样,
-l
大概代表 'l' 库。这些标志显然直接传递给gcc
/g++
到ld
链接器。查看ld --help
。标志-lmylibraryname
告诉链接器查找名为libmylibraryname.a
的文件(如果是静态.a
_存档_库),或者以lib
为前缀的类似名称(如果是动态.so
_共享对象_库)。如果找到这样的库,通常在/usr/lib
(通常是系统库)或/usr/local/lib
(通常是用户安装的库)中,那么链接就成功。 -
头文件也会自动搜索
/usr/include
和/usr/local/include
。 -
基于上述命名,
-lm
意味着必须存在一个名为libm.a
的文件,可能在某个地方的/usr/lib
。确实,find /usr/lib -path "*libm.*"
找到以下内容:
$ find /usr/lib -path "*libm.*"
/usr/lib/x86_64-linux-gnu/libm.so
/usr/lib/x86_64-linux-gnu/libm.a
/usr/lib/x86_64-linux-gnu/libm.so.6
/usr/lib/i386-linux-gnu/libm.so.6
-
-lgtest
起作用,因为在我上面的链接中遵循了相同的命名约定,/usr/local/lib/libgtest.a
存在。 -
关于
-lpthread
与-pthread
,以下是我在上面答案中的个人备注:-
通过google搜索
g++ "-lpthread" vs "-pthread"
可以找到答案:在编译时“-pthread”与“-lpthread”的区别,其中提到-lpthread
和-pthread
之间的区别是历史悠久的,所以在今天的 gcc/g++ 和 clang 编译器上,您应该始终只使用-pthread
来引入 POSIX 线程。-lpthread
库现在似乎是一个空的二进制文件,除了满足仍然必须在某些地方包含该库的古老要求之外,不再执行任何操作。但是,-pthread
为您处理了所有这些,所以只需使用-pthread
,就可以完成!
-
-
你可以添加自己的
-l
标志吗?如何添加?可以!首先,使用
gcc
或g++
将.c
/.cpp 文件构建为.o
文件,然后使用ar
将输出的.o
文件转换为存档的.a
静态库文件。然后,通过sudo cp -i -t /usr/local/lib lib/libgtest.a lib/libgtest_main.a lib/libgmock.a lib/libgmock_main.a
或类似方式将您的.a
文件复制到/usr/local/lib
。有关手动构建.o
和.a
文件的详细信息,请参见我的答案:如何使用gcc/g++或clang构建和使用googletest (gtest)和googlemock (gmock)?。
我认为这就涵盖了所有内容。
英文:
I got it figured out well enough to feel comfortable posting an answer. I figured out almost all of the following through extensive trial and error as I wrote my answer here.
For full details, see the "Going further" section at the end of my answer here: How to set up googleTest as a shared library on Linux: "Going further: general information about libraries; debugging; gcc/g++ compiler flags; etc."
Here are some of the salient points:
-
As I figured out in the bottom of my question,
-l
presumably means 'l'ibrary. These flags apparently get passed straight throughgcc
/g++
to theld
linker. Seeld --help
. The flag-lmylibraryname
tells the linker to look for a file namedlibmylibraryname.a
(if a static.a
archive library), or a similar name prefixed withlib
if a dynamic.so
shared object libary. If such a library is found, generally in/usr/lib
(usually for system libraries), or/usr/local/lib
(usually for user-installed libraries), then the linking is successful. -
Header files are also automatically searched for in
/usr/include
and/usr/local/include
. -
Based on the naming above,
-lm
means there must be a file namedlibm.a
, for instance, probably in/usr/lib
somewhere. Sure enough,find /usr/lib -path "*libm.*"
finds the following:$ find /usr/lib -path "*libm.*" /usr/lib/x86_64-linux-gnu/libm.so /usr/lib/x86_64-linux-gnu/libm.a /usr/lib/x86_64-linux-gnu/libm.so.6 /usr/lib/i386-linux-gnu/libm.so.6
-
-lgtest
works because a file namedlibgtest.a
(following that same naming conventino described above) exists at/usr/local/lib/libgtest.a
, now that I've followed my own instructions at the link above. -
Regarding
-lpthread
vs-pthread
, here are my own notes from my answer above:> 1. A google search for
g++ "-lpthread" vs "-pthread"
reveals this answer: Difference between-pthread
and-lpthread
while compiling, which says that the difference between-lpthread
and-pthread
is historical, so on today's gcc/g++ and clang compilers, you should always just use-pthread
to bring in POSIX threads.
>
> The-lpthread
library is now an empty binary apparently and doesn't do anything except satisfy ancient requirements where that library must still be included in some places. But,-pthread
handles that all for you, so just use-pthread
alone and be done! -
> Are
-l
includes linking to static.a
libraries, or to runtime.so
libraries? Where do these libraries exist in your filesystem?Answer: either.
They are usually found in
/usr/lib
(system-installed libraries) or/usr/local/lib
(user-installed libraries), and their file names must begin withlib
. -
sudo ldconfig -v
shows dynamic libraries only, which are loaded and available for run-time linking now (I think). -
> Can you add your own
-l
flags? How?Yes! First, build .c/.cpp files into .o files using
gcc
org++
, then usear
to convert the output .o files into archive .a static library files. Then, copy your .a files into/usr/local/lib
viasudo cp -i -t /usr/local/lib lib/libgtest.a lib/libgtest_main.a lib/libgmock.a lib/libgmock_main.a
, or similar. For full details on building the .o and .a files manually, see my answer here: How do I build and use googletest (gtest) and googlemock (gmock) with gcc/g++ or clang?.
I think that covers it.
答案2
得分: 0
What is the meaning of -l (lowercase "L") flags passed to gcc/g++?
用于链接库。
And where can I find documentation or tutorials on it?
在本地可以使用 man gcc
,在线文档在 https://gcc.gnu.org/onlinedocs。不过关于教程,我不太清楚。
What does calling -lgtest or -lm really do?
从 https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Link-Options.html#Link-Options 可以找到:
-llibrary
-l library链接时搜索名为 library 的库。第二个选项将库作为单独的参数,这只是为了符合 POSIX 标准,不建议使用。
-l 选项直接传递给链接器。具体细节请参考你的链接器文档。以下是针对 GNU 链接器的一般描述。
链接器会在一组标准目录中搜索库。搜索的目录包括一些标准的系统目录以及你用 -L 指定的目录。
静态库是一组目标文件的归档文件,通常具有像 liblibrary.a 这样的文件名。某些目标还支持共享库,通常具有像 liblibrary.so 这样的名称。如果同时找到静态库和共享库,除非使用 -static 选项,否则链接器会首选与共享库链接。
在命令中写入此选项的位置会产生差异;链接器按照它们的指定顺序搜索和处理库和目标文件。因此,“foo.o -lz bar.o”将在文件 foo.o 之后但在 bar.o 之前搜索库 'z'。如果 bar.o 引用 'z' 中的函数,这些函数可能不会加载。
Why -l? Is that part of what must be present in the name? Does "l" mean something like 'l'inker?
这个选项的名字是 "library" 中 "l" 的缩写。
Do these flags go to the compiler or the linker?
两者都会使用这些选项。
"Compiler" 有两个含义。编译器本质上是将一种语言翻译为另一种语言的工具。但我们称之为 "GCC 编译器" 的实际上是 "GCC 编译器集合",包含用于编译的多个程序。GCC 编译器包括预处理器 (cpp)、编译器 (cc1) 和链接器 (ld)。链接器是编译器工具链的一部分。例如,可以使用 gcc -print-prog-name=cc1
查看编译器集合中的编译器。
Why -lpthread vs -pthread?
https://stackoverflow.com/questions/23250863/difference-between-pthread-and-lpthread-while-compiling . 而且正如你在最新的系统上发现的那样,libpthread.so
是空的。不过,为了确保可移植性,至少在一段时间内最好使用 -pthread
。
Are -l includes linking to static .a libraries, or to runtime .so libraries?
两者都可以。.so
通常优先于 .a
,除非使用 -static
标志,此时会优先使用 .a
。
Where do these libraries exist in your filesystem?
注意:共享库需要两次。首先,在编译器的一部分,由链接器 ld
查找(但实际上 https://stackoverflow.com/questions/42017681/do-shared-libraries-so-files-need-to-present-or-specified-at-link-time)。然后,在执行库时,由 ld.so
动态链接器/加载器查找。这两者是不同的程序,它们都有不同的实现 - 例如 GNU ld
和 ld.gold,还有 musl 和 glibc 项目的 ld.so
。
链接器使用以下搜索路径来查找所需的共享库:
- 由 -rpath-link 选项指定的任何目录。
- 由 -rpath 选项指定的任何目录。-rpath 和 -rpath-link 之间的区别在于,-rpath 选项指定的目录包含在可执行文件中并在运行时使用,而 -rpath-link 选项仅在链接时有效。按照这种方式搜索 -rpath 仅由本机链接器和使用 --with-sysroot 选项配置的交叉链接器支持。
- 在 ELF 系统上,对于本机链接器,如果未使用 -rpath 和 -rpath-link 选项,还会搜索环境变量 "LD_RUN_PATH" 的内容。
- 在 SunOS 上,如果未使用 -rpath 选项,则搜索使用 -L 选项指定的任何目录。
- 对于 Linux 系统上的本机链接器,如果存在文件 /etc/ld.so.conf,则搜索该文件中的目录列表。注意:如果定义了 "sysroot" 值,该文件的路径将以该值为前缀,然后是链接器配置的 "prefix" 字符串。
- 对于 FreeBSD 系统上的本机链接器,由 elf-hints.h 头文件中定义的 "_PATH_ELF_HINTS" 宏指定的任何目录。
- 由链接器脚本中的 "SEARCH_DIR" 命令指定的任何目录,包括由 -T 指定的脚本(但不包括 -dT)。
- 默认目录,通常是 /lib 和 /usr/lib。
- 由插件 LDPT_SET_EXTRA_LIBRARY_PATH 指定的任何目录。
- 默认链接器脚本中的 "SEARCH_DIR" 命令指定的任何目录。
从 man ld.so
:
如果共享对象依赖关系不包含斜杠,则按以下顺序搜索:
- 使用二进制文件中的 DT_RPATH 动态部分属性中指定的目录(如果存在),并且 DT_RUNPATH
英文:
> What is the meaning of -l (lowercase "L") flags passed to gcc/g++?
To link with a library.
> And where can I find documentation or tutorials on it?
Locally in man gcc
, online at https://gcc.gnu.org/onlinedocs . No idea about tutorials.
> What does calling -lgtest or -lm really do?
From https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Link-Options.html#Link-Options :
> -llibrary
> -l library
>
> Search the library named library when linking. (The second alternative
> with the library as a separate argument is only for POSIX compliance
> and is not recommended.)
>
> The -l option is passed directly to the linker by GCC. Refer to your
> linker documentation for exact details. The general description below
> applies to the GNU linker.
>
> The linker searches a standard list of directories for the library.
> The directories searched include several standard system directories
> plus any that you specify with -L.
>
> Static libraries are archives of object files, and have file names
> like liblibrary.a. Some targets also support shared libraries, which
> typically have names like liblibrary.so. If both static and shared
> libraries are found, the linker gives preference to linking with the
> shared library unless the -static option is used.
>
> It makes a difference where in the command you write this option; the
> linker searches and processes libraries and object files in the order
> they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after
> file foo.o but before bar.o. If bar.o refers to functions in ‘z’,
> those functions may not be loaded.
> Why -l? Is that part of what must be present in the name? Does "l" mean something like 'l'inker?
Shortcut from the word "l"ibrary.
> Do these flags go to the compiler or the linker?
Both.
Compiler like means two things. Compiler literally is a translator which translates one language to another. But we call "GCC compiler" what really is "GCC Compiler Collection" - a set of many programs used to compile. GCC compiler includes preprocessor (cpp), compiler (cc1) and linker (ld). Linker is part of the compiler (toolchain). See for example gcc -print-prog-name=cc1
.
> Why -lpthread vs -pthread?
https://stackoverflow.com/questions/23250863/difference-between-pthread-and-lpthread-while-compiling . And as you found out on newest systems, libpthread.so
is empty. Still, for portability, at least for some time prefer to use -pthread
.
> Are -l includes linking to static .a libraries, or to runtime .so libraries?
Both. .so
is preferred over .a
, unless -static
flag is given, in which case .a
is preferred over .so
.
> Where do these libraries exist in your filesystem?
Note: shared libraries are like needed twice. First, by linker ld
as part of the compiler (but really https://stackoverflow.com/questions/42017681/do-shared-libraries-so-files-need-to-present-or-specified-at-link-time) and then by the ld.so
dynamic linker/loader when executing the library. These are different programs and both have different implementations - there are for example GNU ld
and ld.gold, there are ld.so
from musl and glibc projects.
> The linker uses the following search paths to locate required shared
> libraries:
>
> 1. Any directories specified by -rpath-link options.
>
> 2. Any directories specified by -rpath options. The difference between -rpath and -rpath-link is that directories specified by -rpath
>
> options are included in the executable and used at runtime, whereas the -rpath-link option is only effective at link time.
> Searching
> -rpath in this way is only supported by native linkers and cross linkers which have been configured with the --with-sysroot
> option.
>
> 3. On an ELF system, for native linkers, if the -rpath and -rpath-link options were not used, search the contents of the environment
> variable "LD_RUN_PATH".
>
> 4. On SunOS, if the -rpath option was not used, search any directories specified using -L options.
>
> 5. For a native linker, search the contents of the environment variable "LD_LIBRARY_PATH".
>
> 6. For a native ELF linker, the directories in "DT_RUNPATH" or "DT_RPATH" of a shared library are searched for shared libraries
> needed by
> it. The "DT_RPATH" entries are ignored if "DT_RUNPATH" entries exist.
>
> 7. For a linker for a Linux system, if the file /etc/ld.so.conf exists, the list of directories found in that file. Note: the path to
> this
> file is prefixed with the "sysroot" value, if that is defined, and then any "prefix" string if the linker was configured with the
> --prefix=<path> option.
>
> 8. For a native linker on a FreeBSD system, any directories specified by the "_PATH_ELF_HINTS" macro defined in the elf-hints.h
> header
> file.
>
> 9. Any directories specified by a "SEARCH_DIR" command in a linker script given on the command line, including scripts specified by -T
> (but
> not -dT).
>
> 10. The default directories, normally /lib and /usr/lib.
>
> 11. Any directories specified by a plugin LDPT_SET_EXTRA_LIBRARY_PATH
>
> 12. Any directories specified by a "SEARCH_DIR" command in a default linker script.
From man ld.so
:
> If a shared object dependency does not contain a slash, then it is
> searched for in the following order:
>
> (1) Using the directories specified in the DT_RPATH dynamic
> section attribute of the binary if present and DT_RUNPATH attribute
> does not exist.
> Use of DT_RPATH is deprecated.
>
> (2) Using the environment variable LD_LIBRARY_PATH, unless the
> executable is being run in secure-execution mode (see below), in which
> case this
> variable is ignored.
>
> (3) Using the directories specified in the DT_RUNPATH dynamic
> section attribute of the binary if present. Such directories are
> searched only
> to find those objects required by DT_NEEDED (direct dependencies) entries and do not apply to those objects' children,
> which must them‐
> selves have their own DT_RUNPATH entries. This is unlike DT_RPATH, which is applied to searches for all children in the
> dependency tree.
>
> (4) From the cache file /etc/ld.so.cache, which contains a
> compiled list of candidate shared objects previously found in the
> augmented library
> path. If, however, the binary was linked with the -z nodeflib linker option, shared objects in the default paths are
> skipped. Shared ob‐
> jects installed in hardware capability directories (see below) are preferred to other shared objects.
>
> (5) In the default path /lib, and then /usr/lib. (On some 64-bit
> architectures, the default paths for 64-bit shared objects are
> /lib64, and
> then /usr/lib64.) If the binary was linked with the -z nodeflib linker option, this step is skipped.
> How does this relate to the output of sudo ldconfig -v which I see here?
ld.so
searches the cache created by ldconfig
. The output of ldconfig
shows the content of that cache. See man ldconfig
.
> Can you add your own -l flags? How?
You can type -lanything
. You can also create a shared library or a static library named libanything.so
and add it to compiler linker search paths.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论