Question
I am trying to compile a C++ program, and the linker returns this error:
/usr/bin/ld: cannot find -l<nameOfTheLibrary>
In my Makefile, I use g++ and link against a library. The library file is a symbolic link to the real library located in another directory.
Is there a compiler or linker option I need to add so the build can find and link the library correctly?
Short Answer
By the end of this page, you will understand what the -l linker option means, how g++ searches for libraries, why this error happens, and how to fix it using options such as -L, correct library naming, and runtime path settings when needed.
Concept
When you build a C++ program, compilation and linking are two separate steps:
- Compilation turns source files like
.cppinto object files like.o - Linking combines object files and libraries into the final executable
The error:
/usr/bin/ld: cannot find -lfoo
means the linker cannot find a library matching foo in its search paths.
What -lfoo actually means
When you write:
g++ main.cpp -lfoo
g++ passes the request to the linker, which searches for files with names like:
libfoo.solibfoo.a
So -lfoo does not mean “find a file named foo”. It means “find a library named libfoo with a supported extension”.
Why this error happens
Common reasons include:
- The library directory is not in the linker's search path
- The library file name does not follow the expected pattern
- A symbolic link points to a missing target
- You used
-l<fullfilename>instead of the short library name - The library exists only at runtime, not at link time
- You are linking 32-bit code with 64-bit libraries, or vice versa
Why it matters
Understanding library linking is important because real C++ projects often depend on:
- third-party libraries
- custom shared libraries
- system libraries
- build tools such as Make and CMake
If you know how -l, -L, and library naming work, you can diagnose many build problems quickly.
Mental Model
Think of the linker like a librarian.
-lfoomeans: “Please find the book calledlibfoo.”-L/path/to/libsmeans: “Also search this shelf.”- If the shelf is not listed, the librarian only checks the usual shelves.
- If the label is wrong, the book is not found even if it exists.
- If a symbolic link points to nowhere, it is like a catalog card that references a missing book.
So the error means the librarian understood your request, but could not find the library on any known shelf.
Syntax and Examples
The core options for linking libraries with g++ are:
g++ main.cpp -L/path/to/library_directory -lfoo -o my_program
Meaning of each part
-L/path/to/library_directoryadds a directory to the link-time search path-lfoolooks forlibfoo.soorlibfoo.a-o my_programsets the output executable name
Example 1: Linking a custom library
Suppose your library file is:
/opt/mylibs/libmathutils.so
Then use:
g++ main.cpp -L/opt/mylibs -lmathutils -o app
Notice:
- The file is
libmathutils.so - The linker flag is
-lmathutils - You do not write
-llibmathutils.so
Example 2: Static library
If the file is:
/home/user/lib/libparser.a
Then use:
g++ main.cpp -L/home/user/lib -lparser -o app
Example 3: Linking directly to a file
If needed, you can link by exact file path instead of using -l:
g++ main.cpp /opt/mylibs/libmathutils.so -o app
This can help when debugging search path issues.
Example 4: In a Makefile
CXX = g++
CXXFLAGS = -Wall -Wextra -std=c++17
LDFLAGS = -L/opt/mylibs
LDLIBS = -lmathutils
app: main.cpp
$(CXX) $(CXXFLAGS) main.cpp $(LDFLAGS) $(LDLIBS) -o app
This separates:
- compiler options in
CXXFLAGS - linker search paths in
LDFLAGS - libraries in
LDLIBS
Step by Step Execution
Consider this command:
g++ main.cpp -L/home/user/libs -lfoo -o app
Assume /home/user/libs contains libfoo.so.
Step-by-step
1. g++ compiles main.cpp
It first compiles the source code into an object file.
2. g++ invokes the linker
After compilation, g++ calls the linker (ld) behind the scenes.
3. The linker reads -L/home/user/libs
This tells it to also search /home/user/libs for libraries.
4. The linker reads -lfoo
It searches for a matching library file, usually:
libfoo.solibfoo.a
5. If found, it links the library
The executable app is created.
6. If not found, you get the error
/usr/bin/ld: cannot find -lfoo
Trace example with an error
Command:
g++ main.cpp -lfoo -o app
Library location:
/home/user/libs/libfoo.so
What happens:
- The linker checks standard system paths
- It does not check
/home/user/libs - It fails with
cannot find -lfoo
Fixed version
g++ main.cpp -L/home/user/libs -lfoo -o app
Now the library directory is included in the search.
Real World Use Cases
Library linking appears in many real projects.
Using third-party C++ libraries
Examples:
- SQLite wrappers
- OpenSSL
- Boost components
- graphics and game libraries
You often need to add both:
- include paths for headers:
-I... - library paths for linking:
-L...
Building internal shared libraries
A company might have a reusable library like:
/company/libs/libauth.so
Applications link against it with:
-L/company/libs -lauth
Plugin or modular systems
Large applications may separate code into shared libraries so multiple programs can reuse them.
Cross-platform builds
A project might build successfully on one machine because the library is installed system-wide, but fail on another machine where the path must be added manually.
Real Codebase Usage
In real codebases, developers usually organize linking in a structured way instead of placing everything directly in one command.
Common patterns
Use variables in Makefiles
LDFLAGS += -L$(PROJECT_ROOT)/lib
LDLIBS += -lfoo
This keeps build settings reusable.
Separate headers from libraries
Developers often use:
CPPFLAGSfor preprocessor flags like-IincludeLDFLAGSfor linker search paths like-LlibLDLIBSfor actual libraries like-lfoo
Validate library existence
Teams may check whether dependencies are installed before building.
Use pkg-config
For many libraries, developers avoid hardcoding paths and instead use:
g++ main.cpp $(pkg-config --cflags --libs libpng)
This automatically provides the correct include and link flags.
Handle runtime loading too
Even if link time succeeds, a shared library may still fail at runtime unless the system can find it. Common approaches include:
- installing the library in a standard location
- setting
LD_LIBRARY_PATH - embedding an rpath
Example:
g++ main.cpp -L/opt/mylibs -lfoo -Wl,-rpath,/opt/mylibs -o app
That helps the executable find the shared library later when it runs.
Common Mistakes
1. Using the wrong library name with -l
Broken:
g++ main.cpp -llibfoo.so -o app
Correct:
g++ main.cpp -lfoo -o app
The linker adds lib and .so or .a automatically.
2. Forgetting -L for non-standard directories
Broken:
g++ main.cpp -lfoo -o app
If libfoo.so is in /home/user/libs, this fails.
Correct:
g++ main.cpp -L/home/user/libs -lfoo -o app
3. Confusing include paths and library paths
Broken idea:
g++ main.cpp -I/home/user/libs -lfoo -o app
-I is for header files, not libraries.
Correct:
g++ main.cpp -L/home/user/libs -lfoo -o app
4. Broken symbolic link
A symlink may exist, but point to a file that does not exist.
Check with:
ls -l /path/to/libfoo.so
If the target is missing, fix the symlink or point to the real file.
5. Library file has the wrong name
If the file is named:
foo.so
then -lfoo may not find it, because the expected name is usually:
libfoo.so
6. Wrong architecture
A 64-bit program cannot link against a 32-bit library without matching build settings.
Check file type with:
file /path/to/libfoo.so
7. Link order problems
Some libraries depend on others. In many cases, libraries should appear after the object files that use them.
Better:
g++ main.cpp -lfoo -o app
Not usually:
g++ -lfoo main.cpp -o app
For more complex builds, order can matter a lot.
Comparisons
| Concept | Purpose | Example | Common Confusion |
|---|---|---|---|
-I/path | Add header search path | -Iinclude | Does not help find .so or .a files |
-L/path | Add library search path | -L/usr/local/lib | Does not help find header files |
-lfoo | Link library libfoo.so or libfoo.a | -lssl | Do not include lib prefix or file extension |
| Direct file path | Link exact library file | /opt/lib/libfoo.so | Useful for debugging, but less flexible |
LD_LIBRARY_PATH | Runtime shared library search path | export LD_LIBRARY_PATH=/opt/lib | Does not usually fix link-time cannot find -l... |
rpath | Embed runtime library path into executable | -Wl,-rpath,/opt/lib | Helps at runtime, not as a replacement for -L |
-L vs LD_LIBRARY_PATH
-Lhelps the linker during buildLD_LIBRARY_PATHhelps the loader during execution
Symlink vs real file
- A symlink is fine if it points to a valid library file
- A symlink alone is not enough if its directory is not in the search path
Cheat Sheet
# Basic pattern
g++ main.cpp -L/path/to/libs -lfoo -o app
Rules
-lfoosearches forlibfoo.soorlibfoo.a- Use
-L/pathto add non-standard library directories - Use
-I/pathfor headers, not libraries - Do not write
-llibfoo.so - The library directory must be reachable at link time
- Shared libraries may also need runtime search configuration
Useful checks
# Check library files
ls /path/to/libs
# Inspect symbolic link
ls -l /path/to/libs/libfoo.so
# Check architecture
file /path/to/libs/libfoo.so
# Show verbose link command
g++ -v main.cpp -L/path/to/libs -lfoo -o app
Common fixes
# Add library path
g++ main.cpp -L/path/to/libs -lfoo -o app
# Link exact file
g++ main.cpp /path/to/libs/libfoo.so -o app
# Add runtime path too
g++ main.cpp -L/path/to/libs -lfoo -Wl,-rpath,/path/to/libs -o app
Naming reminder
- File:
libmylib.so - Flag:
-lmylib
FAQ
Why does -lfoo look for libfoo.so instead of foo.so?
Because that is the standard Unix linker naming convention for libraries.
Do I need -L if the library is a symbolic link?
Yes, if the symlink is in a non-standard directory. The linker still needs to know which directory to search.
Can I link directly to the .so file instead of using -l?
Yes. You can pass the full path to the library file. This is often useful for debugging.
What is the difference between -L and LD_LIBRARY_PATH?
-L is used at build time by the linker. LD_LIBRARY_PATH is used at runtime by the dynamic loader.
Why does the build succeed on one machine and fail on another?
One machine may have the library installed in a standard system path, while the other does not.
Does -I help fix this error?
No. -I only adds header search paths, not library search paths.
How can I check whether the symlink is broken?
Use:
ls -l /path/to/libfoo.so
Then verify that the target file actually exists.
What if my library file is named incorrectly?
Rename it to the standard form like libfoo.so or link it directly by full path.
Mini Project
Description
Build a small C++ program that uses a custom library stored in a separate directory. This project demonstrates the difference between compilation and linking, how to use -L and -l, and how to organize a simple Makefile correctly.
Goal
Create and link a program against a custom library in a non-standard directory using g++ and a Makefile.
Requirements
- Create a small shared library with one function.
- Place the library in a custom
libdirectory. - Write a program that calls the library function.
- Build the program with
-Land-l. - Ensure the executable can also find the shared library at runtime.
Keep learning
Related questions
Advantages of Brace Initialization in C++
Learn why C++ brace initialization is often clearer and safer than other object initialization styles, with examples and common pitfalls.
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Aggregates, Trivial Types, Trivially Copyable Types, and PODs Explained
Learn what aggregates, trivial types, trivially copyable types, and PODs mean in C++, how they differ, and why they matter.