Ld:Troubleshooting
ld 사용중 발생할 수 있는 문제점에 대한 정리.
undefined reference to 'xxx'
컴파일까지는 잘되는데 링크를 하면 아래와 같은 링크에러가 발생된다.
.a
파일을 같이 link할 때, -l
(라이브러리) 뿐만 아니라, 직접 lib(어쩌구저쩌구).a
라는 형태로도 링크가 가능하다. 굳이 -L(path)
-l(라이브러리)
식으로 할 필요가 없는 것이다. 즉,
와 같은 방식으로도 적용할 수 있다.
링크할 때 적어넣는 순서를 바꿔서 해결할 수 있다. 링크할 때 심볼을 찾는 과정에서 순서를 맞추어야 하는 것이 있는 듯 하다.
아래와 같은 방법으로도 해결할 수 있다.
-Xlinker
는 뒤에 옵션을 링커(ld)에 넘기라는 옵션이다. 링커옵션인 --start-group
와 --end-group
는 아래와 같은 역할을 한다.
Why is My Global or Static Constructor not Called
- Stackoverflow: Global variable has multiple copies on Windows and a single on Linux when compiled in both exec and shared libaray
- Stackoverflow: OSX: How do I convert a static library to a dynamic one?
- [추천] Ns-3_Application_Note_-_linker-problems.pdf
정적링크시 전역변수가 호출되지 않는 현상에 대하여 설명한다.
Recall that a static linker’s purpose is to look through a compilation unit for symbols marked as unresolved and then copy code from a library to define the symbol. Consider what happens if your program does not directly reference any symbol in a compilation unit contained in a given library. The linker never sees an unresolved reference to code in that object file and so it assumes that no code from that particular compilation unit is used, and therefore will ignore any global or static constructors in that file as well. In order to ensure that the global or static constructors of a compilation unit are called, you must directly reference some symbol in the compilation unit object file defining the global constructor. Note that this is a reference to an object file used to build the library, not a symbol in the library file. This means that you must have knowledge of the files that were used to build the library to make this work. For example, consider a situation where you have a static library called libnode.a; and that library is made from a number of object files.
해결방법은, --whole-archive
옵션을 사용하면 된다.
undefined hidden symbol '__init_array_end'
아래와 같은 링크 오류가 발생될 수 있다.
/usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): In function `__libc_csu_init':
(.text+0xd): undefined reference to `__init_array_end'
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): relocation R_X86_64_PC32 against undefined hidden symbol `__init_array_end' can not be used when making a shared object
/usr/bin/ld: final link failed: Bad value
collect2: ld returned 1 exit status
make: *** [libKeynect.so] Error 1
이 경우, -Wl,--whole-archive
와 -Wl,--no-whole-archive
사이에 정적 라이브러리 플래그를 추가하면 된다.
Static library into the shared library
- Stackoverflow: Link a static library to a shared one during build?
- Stackoverflow: how to link static library into dynamic library in gcc
- Stackoverflow: how to disable C++ dead code stripping in xcode
GCC의 --whole-archive
옵션을 사용하면 된다.
clang을 위한 -Wl,-all_load
옵션도 존재한다.
LD_LIBRARY_PATH 환경변수 설정이 안될 경우
Note: You can only set this environment variable inside an interactive shell.
[ie a terminal ] Since Ubuntu 9.04 Jaunty Jackalope, LD_LIBRARY_PATH cannot be set in $HOME/.profile,
/etc/profile, nor /etc/environment files. You must use /etc/ld.so.conf.d/*.conf configuration files.
See Launchpad bug #366728 for more information.
How to fix it:
Make a file with the .conf extension here
Add the paths to it as two lines
Save and exit. Check with ls -l that the file has the same ownership and permissions as others in the directory, they should be:
Then run
This doesn't set the env variable, but includes the libraries appropriately so CUDA works
Direct access to weak symbols
ld: warning: direct access in function {A} from file {B} to global weak symbol {C} from file {D} means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings.
라이브러리를 찾을 수 없지만 패키지로는 설치되어 있다고 출력될 때
Advanced Package Tool#라이브러리를 찾을 수 없지만 패키지로는 설치되어 있다고 출력될 때