#pragma once
void myprint();
和#include
#include "myprint.h"
void myprint() {
printf("myprint\n");
}
[test_so_a] :) mkdir so
[test_so_a] :) g++ -fPIC -o myprint.o -c myprint.cc
[test_so_a] :) g++ -shared -o libmyprint.so myprint.o
[test_so_a] :) mv libmyprint.so so/
[test_so_a] :) ls -al ./so/
total 24
drwxrwxr-x 2 pengchen pengchen 4096 Mar 13 19:06 .
drwxrwxr-x 3 pengchen pengchen 4096 Mar 13 19:06 ..
-rwxrwxr-x 1 pengchen pengchen 16208 Mar 13 19:06 libmyprint.so
[test_so_a] :)
#include "myprint.h"
int main() {
myprint();
}
生成可执行文件指令[test_so_a] :) g++ -E main.cc -o main_dynamic.i
[test_so_a] :) g++ -S main_dynamic.i -o main_dynamic.s
[test_so_a] :) g++ -c main_dynamic.s -o main_dynamic.o
[test_so_a] :) g++ -o main_dynamic main_dynamic.o -L ./so/ -lmyprint
[test_so_a] :) echo $LD_LIBRARY_PATH
[test_so_a] :) ./main_dynamic
./main_dynamic: error while loading shared libraries: libmyprint.so: cannot open shared object file: No such file or directory
[test_so_a] :( export LD_LIBRARY_PATH=./so/:${LD_LIBRARY_PATH}
[test_so_a] :) ./main_dynamic
myprint
[test_so_a] :)
这里几个问题?
为什么需要-L以“编译和链接阶段,指定链接器应该搜索哪些目录以找到库文件。”?反正动态库又不放到可执行文件里面?LD_LIBRARY_PATH不就行了?
-L 选项在编译和链接阶段起到了关键作用,确保了链接器能正确解析符号、生成符号表和依赖信息。虽然动态库本身不嵌入到可执行文件中,但这些步骤对于生成一个能够正确运行的可执行文件是不可或缺的。而 LD_LIBRARY_PATH 则是在运行时阶段工作的,保证程序在执行时能找到这些库。两者的作用和使用阶段不同,不能互相替代。
[test_so_a] :) nm -AC main_dynamic.o
main_dynamic.o: U _GLOBAL_OFFSET_TABLE_
main_dynamic.o:0000000000000000 T main
main_dynamic.o: U myprint()
[test_so_a] :) nm -AC main_dynamic
main_dynamic:0000000000004010 B __bss_start
main_dynamic:0000000000004010 b completed.8061
main_dynamic: w __cxa_finalize@@GLIBC_2.2.5
main_dynamic:0000000000004000 D __data_start
main_dynamic:0000000000004000 W data_start
main_dynamic:0000000000001090 t deregister_tm_clones
main_dynamic:0000000000001100 t __do_global_dtors_aux
main_dynamic:0000000000003db0 d __do_global_dtors_aux_fini_array_entry
main_dynamic:0000000000004008 D __dso_handle
main_dynamic:0000000000003db8 d _DYNAMIC
main_dynamic:0000000000004010 D _edata
main_dynamic:0000000000004018 B _end
main_dynamic:00000000000011d8 T _fini
main_dynamic:0000000000001140 t frame_dummy
main_dynamic:0000000000003da8 d __frame_dummy_init_array_entry
main_dynamic:000000000000214c r __FRAME_END__
main_dynamic:0000000000003fb8 d _GLOBAL_OFFSET_TABLE_
main_dynamic: w __gmon_start__
main_dynamic:0000000000002004 r __GNU_EH_FRAME_HDR
main_dynamic:0000000000001000 t _init
main_dynamic:0000000000003db0 d __init_array_end
main_dynamic:0000000000003da8 d __init_array_start
main_dynamic:0000000000002000 R _IO_stdin_used
main_dynamic: w _ITM_deregisterTMCloneTable
main_dynamic: w _ITM_registerTMCloneTable
main_dynamic:00000000000011d0 T __libc_csu_fini
main_dynamic:0000000000001160 T __libc_csu_init
main_dynamic: U __libc_start_main@@GLIBC_2.2.5
main_dynamic:0000000000001149 T main
main_dynamic:00000000000010c0 t register_tm_clones
main_dynamic:0000000000001060 T _start
main_dynamic:0000000000004010 D __TMC_END__
main_dynamic: U myprint()
发现不管是在目标文件还是可执行文件,myprint()都是未解析的符号错误(undefined reference),GPT说对于动态库是正常的。那拿静态库试一下[test_so_a] :) g++ -c myprint.cc -o myprint.o
[test_so_a] :) ar rcs ./a/libmyprint.a myprint.o
[test_so_a] :) g++ -o main_static -L ./a/ -lmyprint
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
[test_so_a] :( g++ -o main_static main_static.o -L ./a/ -lmyprint
[test_so_a] :) ./main_static
myprint
[test_so_a] :) nm -AC main_static.o
main_static.o: U _GLOBAL_OFFSET_TABLE_
main_static.o:0000000000000000 T main
main_static.o: U myprint()
[test_so_a] :) nm -AC main_static
main_static:0000000000004010 B __bss_start
main_static:0000000000004010 b completed.8061
main_static: w __cxa_finalize@@GLIBC_2.2.5
main_static:0000000000004000 D __data_start
main_static:0000000000004000 W data_start
main_static:0000000000001090 t deregister_tm_clones
main_static:0000000000001100 t __do_global_dtors_aux
main_static:0000000000003dc0 d __do_global_dtors_aux_fini_array_entry
main_static:0000000000004008 D __dso_handle
main_static:0000000000003dc8 d _DYNAMIC
main_static:0000000000004010 D _edata
main_static:0000000000004018 B _end
main_static:00000000000011f8 T _fini
main_static:0000000000001140 t frame_dummy
main_static:0000000000003db8 d __frame_dummy_init_array_entry
main_static:000000000000217c r __FRAME_END__
main_static:0000000000003fb8 d _GLOBAL_OFFSET_TABLE_
main_static: w __gmon_start__
main_static:000000000000200c r __GNU_EH_FRAME_HDR
main_static:0000000000001000 t _init
main_static:0000000000003dc0 d __init_array_end
main_static:0000000000003db8 d __init_array_start
main_static:0000000000002000 R _IO_stdin_used
main_static: w _ITM_deregisterTMCloneTable
main_static: w _ITM_registerTMCloneTable
main_static:00000000000011f0 T __libc_csu_fini
main_static:0000000000001180 T __libc_csu_init
main_static: U __libc_start_main@@GLIBC_2.2.5
main_static:0000000000001149 T main
main_static: U puts@@GLIBC_2.2.5
main_static:00000000000010c0 t register_tm_clones
main_static:0000000000001060 T _start
main_static:0000000000004010 D __TMC_END__
main_static:000000000000115d T myprint()
[test_so_a] :)
发现main_static:000000000000115d T myprint()
。[test_so_a] :( g++ -o main_dynamic main_dynamic.o
/usr/bin/ld: main_dynamic.o: in function `main':
main.cc:(.text+0x9): undefined reference to `myprint()'
collect2: error: ld returned 1 exit status
[test_so_a] :( g++ -o main_dynamic main_dynamic.o -L ./so -lmyprint
[test_so_a] :) ldd main_dynamic
linux-vdso.so.1 (0x00007ffdb0769000)
libmyprint.so => ./so/libmyprint.so (0x00007f0a63c44000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0a63a47000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0a63c50000)
[test_so_a] :)
[test_so_a] :) ldconfig -v 2>/dev/null | grep -v ^$'\t'
/usr/lib/x86_64-linux-gnu/libfakeroot:
/usr/local/lib:
/lib/x86_64-linux-gnu:
/lib:
[test_so_a] :) cpp -v /dev/null -o /dev/null
Using built-in specs.
COLLECT_GCC=cpp
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)
COLLECT_GCC_OPTIONS='-E' '-v' '-o' '/dev/null' '-mtune=generic' '-march=x86-64'
/usr/lib/gcc/x86_64-linux-gnu/9/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu /dev/null -o /dev/null -mtune=generic -march=x86-64 -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/9/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include
End of search list.
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-E' '-v' '-o' '/dev/null' '-mtune=generic' '-march=x86-64'
[test_so_a] :)
这里[test_so_a] :) echo $LD_LIBRARY_PATH
[test_so_a] :) ./main_dynamic
./main_dynamic: error while loading shared libraries: libmyprint.so: cannot open shared object file: No such file or directory
[test_so_a] :( export LD_LIBRARY_PATH=./so/:${LD_LIBRARY_PATH}
[test_so_a] :) ./main_dynamic
myprint
[test_so_a] :)
参考https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.htmlYou can specify any number or combination of these options on the command line to search for header files in several directories. The lookup order is as follows:
For the quote form of the include directive, the directory of the current file is searched first.
For the quote form of the include directive, the directories specified by -iquote options are searched in left-to-right order, as they appear on the command line.
Directories specified with -I options are scanned in left-to-right order.
Directories specified with -isystem options are scanned in left-to-right order.
Standard system directories are scanned.
Directories specified with -idirafter options are scanned in left-to-right order.
参考
https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html