1. test.m编译链接libAFNetworking.dylib

  1. #import <Foundation/Foundation.h>
  2. #import <AFNetworking.h>
  3. int main(){
  4. AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
  5. NSLog(@"testApp----%@", manager);
  6. return 0;
  7. }

1.1 test.m -> test.o

-I 指定头文件查找路径

image.png

1.2 test.o 链接动态库

-l 指定需要链接的库的名称 -L 指定库所在的路径

image.png

1.3 运行报错:image not found

image.png

2. 链接自定义动态库

2.1 test.m

  1. #import <Foundation/Foundation.h>
  2. #import "TestExample.h"
  3. int main(){
  4. NSLog(@"testApp----");
  5. TestExample *manager = [TestExample new];
  6. [manager lg_test: nil];
  7. return 0;
  8. }

目录结构
image.png

2.2 脚本build.sh

  1. echo "编译test.m --- test.o"
  2. clang -target x86_64-apple-macos10.15 \
  3. -fobjc-arc \
  4. -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
  5. -I./dylib \
  6. -c test.m -o test.o
  7. pushd ./dylib
  8. echo "编译TestExample.m --- TestExample.o"
  9. clang -target x86_64-apple-macos10.15 \
  10. -fobjc-arc \
  11. -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
  12. -c TestExample.m -o TestExample.o
  13. echo "编译TestExample.o --- libTestExample.a"
  14. # Xcode->静态库
  15. libtool -static -arch_only x86_64 TestExample.o -o libTestExample.a
  16. echo "编译TestExample.o --- libTestExample.dylib"
  17. # -dynamiclib: 动态库
  18. # dylib 最终链接产物 -》
  19. ld -dylib -arch x86_64
  20. -macosx_version_min 10.15
  21. -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
  22. -lsystem -framework Foundation \
  23. libTestExample.a -o libTestExample.dylib
  24. popd
  25. echo "链接libTestExample.dylib -- test EXEC"
  26. clang -target x86_64-apple-macos10.15 \
  27. -fobjc-arc \
  28. -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
  29. -L./dylib \
  30. -lTestExample \
  31. test.o -o test

2.3 编译完成后编译,报错undfined

image.png

2.4 查看动态库的导出符号

image.png

2.5 编译器添加参数-all_load

没有导出符号,修改脚本,静态库链接生成动态库的时候给编译器添加参数-all_load
image.png

2.6 重新编译脚本build.sh ,运行 仍然报错 imag not found

image.png

3. 项目工程链接tdb库

image.png

3.1 xcconfig中配置动态库头文件路径

  1. //-I 参数 动态库头文件路径
  2. HEADER_SEARCH_PATHS = $(inherited) ${SRCROOT}/SYCSSColor/Headers
  3. // -F
  4. //FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking"
  5. //-framework
  6. //OTHER_LDFLAGS = $(inherited) -framework "AFNetworking"

3.2 将tdb动态库拖入工程,编译成功

image.png
image.png

3.3 运行时 需要找到符号的真实地址,找不到 会报错

image.png
image.png
**

4. 动态库与framework

4.1 TestExample.m编译生成动态库TestExample

image.png

  1. clang -target x86_64-apple-macos10.15 \
  2. -fobjc-arc \
  3. -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
  4. -c TestExample.m -o TestExample.o
  5. # -dynamiclib: 动态库
  6. ld -dylib -arch x86_64
  7. -macosx_version_min 10.15
  8. -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
  9. -lsystem -framework Foundation \
  10. TestExample.o -o TestExample

4.2 test.m 编译 链接TestExample动态库

  1. clang -target x86_64-apple-macos10.15 \
  2. -fobjc-arc \
  3. -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
  4. -I./Frameworks/TestExample.framework/Headers \
  5. -c test.m -o test.o
  6. clang \
  7. -target x86_64-apple-macos10.15 \
  8. -fobjc-arc \
  9. -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \
  10. -F./Frameworks \
  11. -framework TestExample \
  12. test.o -o test

4.3 报错 image not found

image.png

4.4 查看test的macho中的LC_LOAD_DYLIB(加载的动态库)

  1. //查找macho中的DYLIB,并显示找到符号之后的的三行
  2. otool -l test | grep 'DYLIB' -A 3

image.png

4.5 查看文件类型 file命令

image.png

⚠️ 动态库的路径是保存在动态库自己的macho中的

4.6 查看TestExample保存到Macho中的路径

  1. otool -l TestExample | grep 'ID' -A 5

image.png

4.7 install_name_tool指定动态库的路径

动态库的路径不完整时,可以通过外部的install_name_tool,在外部改变动态库的路径
image.png

  • 修改TestExample动态库的路径(指定绝对路径)

    1. install_name_tool -id /Users/mac/Downloads/动态库/上课代码/动态库与framework/Frameworks/TestExample.framework/TestExample TestExample
  • 重新执行 otool -l TestExample | grep 'ID' -A 5

image.png

  • test.m 重新链接TestExample动态库 ```bash clang -target x86_64-apple-macos10.15 \ -fobjc-arc \ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \ -I./Frameworks/TestExample.framework/Headers \ -c test.m -o test.o

clang \ -target x86_64-apple-macos10.15 \ -fobjc-arc \ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk \ -F./Frameworks \ -framework TestExample \ test.o -o test

otool -l test | grep ‘DYLIB’ -A 3

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1994311/1611715583205-8c17ffb2-50fc-4b92-bb14-ca81af0d92db.png#align=left&display=inline&height=319&originHeight=472&originWidth=907&size=84834&status=done&style=none&width=613)
  2. > ⚠️ 生成动态库的时候,Macho会生成一个name,保存着动态库的路径到LC_ID_DYLIB,可执行文件去链接动态库的时候,动态库会将LC_ID_DYLIB中的name给到可执行文件,保存到可执行文件的Macho LC_LOAD_DYLIB
  3. - 上述从外部修改install_name_tool的方式修改后的是绝对路径,工程修改了存储目录后,会有问题
  4. > install_name_tool可以设置相对路径参数 `@rpath`
  5. > `@rpath(Runpath search Paths)` ,dyld搜索路径,运行`@rpath` 指示 `dyld` 按顺序搜索路径列表,以找到动态库,`@rpath` 保存一个或多个路径变量
  6. - test提供@rpath路径给TestExample
  7. test.m链接TestExample动态库,test提供@rpath路径给TestExample
  8. ```bash
  9. //修改LC_ID_DYLIB
  10. install_name_tool -id @rpath/Frameworks/TestExample.framework/TestExample /Users/mac/Downloads/动态库/上课代码/动态库 与framework/Frameworks/TestExample.framework/TestExample

image.png

  • 然后再test的macho中保存一个@rpath

@rpath使用绝对路径

  1. //往test中添加添加rpath
  2. install_name_tool -add_rpath /Users/mac/Downloads/动态库/上课代码/动态库与framework test

image.png

  • 查看test的macho中的rpath

    1. // -i 大小写不敏感
    2. otool -l test | grep 'rpath' -A 3 -i

    image.png

  • @rpath使用相对路径:

@executable_path 表示可执行程序所在的目录,解析为可执行文件的绝对路径。
@loader_path 表示被加载的Mach-O 所在的目录,每次加载时,都可能被设置为不同的路径,由上层指定

1)@loader_path表示谁来链接动态库,就是谁的目录

  1. install_name_tool -rpath /Users/mac/Downloads/动态库/上课代码/动态库与framework @executable_path test

image.png

  • 运行 test

image.png

  • 补充install_name_tool

image.png

  • xcode中可执行文件的配置文件设置@rpath的路径 LD_RUNPATH_SEARCH_PATHS=$(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'

截屏2021-03-02 下午10.56.13.png
image.png