静态库的本质

优质
小牛编辑
130浏览
2023-12-01

验证静态库是.o文件的合集

相关工具介绍

  1. clang命令部分参数描述

     -x: 指定编译文件语言类型
     -target: 指定指令集(-target arm64-apple-ios14.3 真机)
     -g: 生成调试信息
     -c: 生成目标文件,只运行preprocess,compile,assemble,不链接
     -o: 输出文件
     -isysroot: 使用的SDK路径
         1. -I<directory> 在指定目录寻找头文件 (header search path)
         2. -L<dir> 指定库文件路径(.a\.dylib库文件) (library search path)
         3. -l<library_name> 指定链接的库文件名称(.a\.dylib库文件)(other link flags -lAFNetworking)  
         4. -F<directory> 在指定目录寻找framework (framework search path)
         5. -framework <framework_name> 指定链接的framework名称 (other link flags -framework AFNetworking)
    
  2. 在终端中直接进入lldb环境来运行可执行文件: 终端lldb环境运行可执行文件


探究.a静态库

一、准备

  1. OCStaticLib文件夹下准备OCTest.hOCTest.m文件, 代码如下

    • .h文件

        #import <Foundation/Foundation.h>
      
        NS_ASSUME_NONNULL_BEGIN
      
        @interface OCTest : NSObject
      
        - (void)test:(_Nullable id)example;
      
        @end
      
        NS_ASSUME_NONNULL_END
      
    • .m文件

        #import "OCTest.h"
      
        @implementation OCTest
      
        - (void)test:(_Nullable id)example {
            NSLog(@"__TestExample");
        }
      
        @end
      
  2. 外层的test.m文件代码

     #import <Foundation/Foundation.h>
     #import "OCTest.h"
    
     int main() {
         OCTest *test = [OCTest new];
         [test test:nil];
         NSLog(@"testApp ------");
         return 0;
     }
    
  3. 代码说明

    1. 两个简单的Objective-C类文件: .h.m
    2. 定义了一个test:方法, 执行了一条NSLog输出语句
    3. .h文件中对外声明了这个方法
    4. test.m是用于验证能否链接手动修改文件生成的静态库
  4. 目录结构:

     .
     ├── OCStaticLib
     │   ├── OCTest.h
     │   └── OCTest.m
     └── test.m
    

二、生成.o目标文件

  1. 执行clang命令生成目标文件

     clang -x objective-c \
     -target x86_64-apple-macos11.1 \
     -fobjc-arc \
     -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
     -c OCTest.m \
     -o OCTest.o
    
  2. 生成.o文件

     .
     ├── OCTest.h
     ├── OCTest.m
     └── OCTest.o
    

三、手动修改成静态库文件

即然静态库是.o文件的合集, 那么可以理解为一个.o就是一个合集

  1. 在生成的.o文件基础上对齐执行以下两步操作

    1. 去掉.o后缀
    2. 增加lib前缀
    3. 增加.dylib后缀后回车, 再将.dylib后缀去掉回车 *
  2. 通过file命令验证其仍为.o目标文件

     /Users/shenyj/Documents/CodeForTest/staticOCLib/OCStaticLib/libOCTest.o: Mach-O 64-bit object x86_64
    

四、链接这个静态库

  1. 链接 静态库(将.o手动改成静态库文件命名格式的, 我们模拟的静态库) 文件

     clang -x objective-c \
     -target x86_64-apple-macos11.1 \
     -fobjc-arc \
     -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
     -I./OCStaticLib \
     -c test.m \
     -o test.o
    
  2. 执行链接操作后, 并没有出现报错或警告, 并且生成了test.o目标文件

五、生成可执行文件

  1. .o目标文件生成可执行文件

     clang -target x86_64-apple-macos11.1 \
     -fobjc-arc \
     -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
     -L./OCStaticLib \
     -lOCTest \
     test.o -o test
    
    • 这里有个注意点, 在手动修改成静态库文件-步骤1-3中, 先为其增加后缀.dylib确认, 然后在去掉.dylib后缀, 否则在生成可执行文件时可能会报错
    • 原理:

      • Big Sur会保留文件的原始格式
      • 通过修改后缀让系统将原来的.o文件格式(object code)识别成Unix可执行文件
      • 再根据链接静态库的查找规则先找lib+<library_name>的动态库,找不到,再去找lib+<library_name>的静态库,还找不到,就报错, 来找到手动生成的静态库
      ld: library not found for -lOCTest
      clang: error: linker command failed with exit code 1 (use -v to see invocation)
      

六、终端下进入lldb环境, 运行可执行文件

  • 输出结果

      Process 43324 launched: '/Users/shenyj/Documents/CodeForTest/staticOCLib/test' (x86_64)
      2021-01-25 09:11:22.903357+0800 test[43324:1458614] __TestExample
      2021-01-25 09:11:22.903693+0800 test[43324:1458614] testApp ------
      Process 43324 exited with status = 0 (0x00000000)
      (lldb)
    

得出结论

.a静态库就是.o文件的集合