如何在一台机器编译带Eigen、PCL等依赖的C++程序并在另一台无对应依赖的同架构同OS机器运行?
Hey there, no need to apologize for asking this—this is a super common deployment scenario, and totally valid! Let’s break down your questions and the standard solutions:
Can I just copy the compiled binary file alone?
Short answer: No, probably not. By default, most C++ compilers link against shared libraries (like .so files for Eigen, PCL, RapidJson). When you run the binary, it looks for these shared libraries in system paths (like /usr/lib or /usr/local/lib). If the target machine doesn’t have these libraries installed, you’ll get errors like error while loading shared libraries: libpcl_common.so.1.8: cannot open shared object file: No such file or directory.
Standard Solutions for Your Scenario
Since your target machines have the same Ubuntu 18.04 version and architecture, you have a few reliable options:
1. Static Compilation (Single Self-Contained Binary)
This approach builds all your dependencies directly into the binary, so you only need to copy that one file to target machines. Here’s how to set it up with CMake:
- Add flags to force static linking: Set
BUILD_SHARED_LIBS=OFFin your CMake configuration, or explicitly specify static versions of your dependencies (e.g.,find_package(Eigen3 REQUIRED NO_MODULE)with static libraries enabled). - Note: PCL can be tricky to statically compile—you’ll need to ensure all its dependencies (like Boost, VTK) are also built as static libraries. You may need to compile PCL from source with static linking enabled if the pre-built packages don’t offer it.
- Pros: Single file to deploy, no extra steps for users. Cons: Binary size will be much larger, and you need to watch for open-source license restrictions (some libraries have specific rules for static linking).
2. Bundle Shared Libraries with Your Binary
If static compilation is too cumbersome, you can package all required shared libraries alongside your binary:
- First, identify all non-system dependencies using
ldd your_compiled_binary. This will list every.sofile your program needs. Ignore system libraries likelibc.so.6orlibstdc++.so.6—Ubuntu 18.04 will have these by default. - Copy all the required third-party
.sofiles into a subfolder (e.g.,./libs/) next to your binary. - To run the program, either:
- Use the
LD_LIBRARY_PATHenvironment variable:LD_LIBRARY_PATH=./libs ./your_binary - Or use
patchelfto modify the binary’srpath(runtime library path) to look in the locallibsfolder:
After this, users can just runpatchelf --set-rpath '$ORIGIN/libs' your_binary./your_binarydirectly without setting environment variables.
- Use the
- Optional: Write a simple shell script (e.g.,
run_program.sh) that wraps the command, so users don’t have to remember theLD_LIBRARY_PATHtrick.
3. Use a Universal Packaging Format (AppImage/Flatpak/Snap)
For a more polished deployment, you can use tools like AppImage, Flatpak, or Snap to package your program and all dependencies into a single, self-contained executable or package:
- AppImage: This is great for simple deployment—you can use tools like
linuxdeployqtto bundle your binary and dependencies into a single AppImage file. Users just need to make it executable (chmod +x your_program.AppImage) and run it. - Flatpak/Snap: These are more heavyweight but offer sandboxing and easier distribution across different Ubuntu versions (though you said target machines are same 18.04, so maybe overkill, but still an option).
Key Notes
- Make sure your build machine and target machines are exactly the same Ubuntu version and architecture—even minor differences in system libraries can cause runtime crashes if you’re using shared libraries.
- Always test the deployed binary on a target machine before distributing it to catch any missing dependencies or compatibility issues.
内容的提问来源于stack exchange,提问作者morsingher

