编译时已通过-L指定库路径,为何运行仍需设置LD_LIBRARY_PATH?
-L at Compile Time and LD_LIBRARY_PATH at Runtime Great question—this is a super common point of confusion when working with shared libraries on Linux-like systems. Let’s break down what’s happening in both stages to clear up why these steps feel redundant but are actually serving very different purposes.
1. Compile/Link Stage: What -L Does
When you use -L/lib1 -L/lib2 in your Makefile, you’re talking to the static linker (ld) during the build process. Here’s what it actually does:
- It tells the linker where to look for shared library files (like
libfoo.so) to resolve symbols your code references. For example, if your model calls a functionbar()fromlibfoo.so, the linker needs to find that library to confirmbar()exists and hook up the reference. - Crucially, the
-Lflag only affects the build process. By default, the linker does not hardcode these library paths into the final executable. It just checks that the libraries exist and have the required symbols, then moves on.
The reason it doesn’t hardcode the paths is portability: your development environment might have libraries in /lib1, but a production server or another user’s machine might store them in /opt/libs or somewhere else. Hardcoding paths would break the executable when moved to a different system.
2. Runtime Stage: Why LD_LIBRARY_PATH Is Required
When you run the executable, the dynamic linker (ld.so/ld-linux.so) takes over. Its job is to load all the required shared libraries into memory so the program can execute. By default, the dynamic linker only searches a set of system-wide default paths:
- Standard system directories like
/lib,/usr/lib,/usr/local/lib - Paths listed in
/etc/ld.so.conf(and files in/etc/ld.so.conf.d/)
If your libraries are in non-standard paths like /lib1 or /lib2, the dynamic linker has no way to find them unless you explicitly tell it. That’s where LD_LIBRARY_PATH comes in: it’s an environment variable that adds extra directories to the dynamic linker’s search list.
Fixing the "Redundancy"
If you want to avoid setting LD_LIBRARY_PATH every time, you can hardcode the library paths into the executable at build time using the -rpath linker flag. Add this to your Makefile’s compile command:
-Wl,-rpath=/lib1:/lib2
The -Wl, part passes the -rpath=/lib1:/lib2 argument directly to the linker. This adds the paths to the executable’s RPATH section, so the dynamic linker will automatically check those locations at runtime without needing LD_LIBRARY_PATH.
Just keep in mind: -rpath makes the paths permanent. If you move the libraries to a new location later, the executable will fail to find them unless you recompile with the updated -rpath or override it with LD_LIBRARY_PATH (which takes precedence over RPATH in most cases).
内容的提问来源于stack exchange,提问作者Luke Davis

