`-l`(小写的”L”)标志在gcc/g++中的含义是:

huangapple go评论126阅读模式
英文:

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:

  1. https://en.cppreference.com/w/c/numeric/math
  2. https://stackoverflow.com/a/12165016/4561887

But I need more detail than that:

  1. 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?

  2. 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?

  3. Why -lpthread vs -pthread? I've seen both before and don't understand the difference.

  4. Are -l includes linking to static .a libraries, or to runtime .so libraries? Where do these libraries exist in your filesystem?

  5. How does this relate to the output of sudo ldconfig -v which I see here?

  6. 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:

  1. https://en.cppreference.com/w/c/numeric/math
  2. https://stackoverflow.com/a/12165016/4561887

But I need more detail than that:

  1. 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?

  2. 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?

  3. Why -lpthread vs -pthread? I've seen both before and don't understand the difference.

  4. Are -l includes linking to static .a libraries, or to runtime .so libraries? Where do these libraries exist in your filesystem?

  5. How does this relate to the output of sudo ldconfig -v which I see here?

  6. 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++编译器标志等”

以下是一些关键要点:

  1. 如我在问题底部弄清楚的那样,-l 大概代表 'l' 库。这些标志显然直接传递给 gcc/g++ld 链接器。查看 ld --help。标志 -lmylibraryname 告诉链接器查找名为 libmylibraryname.a 的文件(如果是静态 .a _存档_库),或者以 lib 为前缀的类似名称(如果是动态 .so _共享对象_库)。如果找到这样的库,通常在 /usr/lib(通常是系统库)或 /usr/local/lib(通常是用户安装的库)中,那么链接就成功。

  2. 头文件也会自动搜索 /usr/include/usr/local/include

  3. 基于上述命名,-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
  1. -lgtest 起作用,因为在我上面的链接中遵循了相同的命名约定,/usr/local/lib/libgtest.a 存在。

  2. 关于 -lpthread-pthread,以下是我在上面答案中的个人备注:

    1. 通过google搜索 g++ "-lpthread" vs "-pthread" 可以找到答案:在编译时“-pthread”与“-lpthread”的区别,其中提到 -lpthread-pthread 之间的区别是历史悠久的,所以在今天的 gcc/g++ 和 clang 编译器上,您应该始终只使用 -pthread 来引入 POSIX 线程。

      -lpthread 库现在似乎是一个空的二进制文件,除了满足仍然必须在某些地方包含该库的古老要求之外,不再执行任何操作。但是,-pthread 为您处理了所有这些,所以只需使用 -pthread,就可以完成!

  3. 你可以添加自己的 -l 标志吗?如何添加?

    可以!首先,使用 gccg++.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:

  1. As I figured out in the bottom of my question, -l presumably means 'l'ibrary. These flags apparently get passed straight through gcc/g++ to the ld linker. See ld --help. The flag -lmylibraryname tells the linker to look for a file named libmylibraryname.a (if a static .a archive library), or a similar name prefixed with lib 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.

  2. Header files are also automatically searched for in /usr/include and /usr/local/include.

  3. Based on the naming above, -lm means there must be a file named libm.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
    
  4. -lgtest works because a file named libgtest.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.

  5. 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!

  6. > 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 with lib.

  7. sudo ldconfig -v shows dynamic libraries only, which are loaded and available for run-time linking now (I think).

  8. > Can you add your own -l flags? How?

    Yes! First, build .c/.cpp files into .o files using gcc or g++, then use ar to convert the output .o files into archive .a static library files. Then, copy your .a files into /usr/local/lib via sudo 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 ldld.gold,还有 musl 和 glibc 项目的 ld.so

链接器使用以下搜索路径来查找所需的共享库:

  1. 由 -rpath-link 选项指定的任何目录。
  2. 由 -rpath 选项指定的任何目录。-rpath 和 -rpath-link 之间的区别在于,-rpath 选项指定的目录包含在可执行文件中并在运行时使用,而 -rpath-link 选项仅在链接时有效。按照这种方式搜索 -rpath 仅由本机链接器和使用 --with-sysroot 选项配置的交叉链接器支持。
  3. 在 ELF 系统上,对于本机链接器,如果未使用 -rpath 和 -rpath-link 选项,还会搜索环境变量 "LD_RUN_PATH" 的内容。
  4. 在 SunOS 上,如果未使用 -rpath 选项,则搜索使用 -L 选项指定的任何目录。
  5. 对于 Linux 系统上的本机链接器,如果存在文件 /etc/ld.so.conf,则搜索该文件中的目录列表。注意:如果定义了 "sysroot" 值,该文件的路径将以该值为前缀,然后是链接器配置的 "prefix" 字符串。
  6. 对于 FreeBSD 系统上的本机链接器,由 elf-hints.h 头文件中定义的 "_PATH_ELF_HINTS" 宏指定的任何目录。
  7. 由链接器脚本中的 "SEARCH_DIR" 命令指定的任何目录,包括由 -T 指定的脚本(但不包括 -dT)。
  8. 默认目录,通常是 /lib 和 /usr/lib。
  9. 由插件 LDPT_SET_EXTRA_LIBRARY_PATH 指定的任何目录。
  10. 默认链接器脚本中的 "SEARCH_DIR" 命令指定的任何目录。

man ld.so

如果共享对象依赖关系不包含斜杠,则按以下顺序搜索:

  1. 使用二进制文件中的 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.

huangapple
  • 本文由 发表于 2023年3月12日 07:33:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/75710217.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定