動態庫與靜態庫(一)

靜態庫

獲取第三方靜態庫方法(參考)

以獲取AFNetworking爲例:c++

1.使用cocoaPods安裝AFNetworking,在Podfile文件中target下添加objective-c

#use_frameworks!
pod 'AFNetworking'
複製代碼

注意#use_frameworks!前面的#號不能省略,不然用的就是動態庫macos

2.終端執行安裝命令成功後,打開xcworkspace文件,New Scheme,選中Pods下面的AFNetworking markdown

3.command+B編譯一下,找到變成黑色的libAFNetworking.a文件,右鍵show in Finder架構

4.將Pods目錄下的AFNetworking文件裏的AFNetworking文件拷貝出來備用app

5.將剛纔找到的libAFNetworking.a文件拷貝到備用的AFNetworking文件夾下框架

連接靜態庫

1.準備一個main.m文件,添加代碼以下:測試

#import <Foundation/Foundation.h>
#import <AFNetworking.h>

int main() {
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    NSLog(@"test---%@",manager);
    return 0;
}
複製代碼

2.將AFNetworking文件夾和main.m放到同一個目錄下,例如:ui

圖片.png

3.使用clang命令將main.m文件編譯成main.o文件spa

clang命令參數解釋:
     -x: 指定編譯文件語言類型
     -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
     -F<directory> 在指定目錄尋找framework framework search path
     -framework <framework_name> 指定連接的framework名稱 other link flags -framework AFNetworking
複製代碼

cd到main.m所在目錄,執行下面命令,將main.m編譯成main.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./AFNetworking \
-c main.m -o main.o
複製代碼

main.m編譯成main.o:命令解釋以下:

1. 使用OC
2. 生成的是X86_64_macOS架構的代碼
   Big Sur是:x86_64-apple-macos11.1,以前是:x86_64-apple-macos10.15
3. 使用ARC
4. 使用的SDK的路徑在:
   Big Sur是:/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk
        以前是:/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk
5.指定頭文件路徑
6.輸出目標文件
 
複製代碼

4.連接靜態庫生成可執行文件

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-L./AFNetworking \
-lAFNetworking \
main.o -o main
複製代碼

-lAFNetworking連接的名稱爲libAFNetworking/AFNetworking的動態庫或者靜態庫

查找規則:先找lib+<library_name>的動態庫,找不到,再去找lib+<library_name>的靜態庫,還找不到,就報錯

生成了可執行文件main

雙擊執行: 打印出AFNetworking相關內容,連接成功

使用腳本文件編譯連接

1.建立腳本文件

圖片.png 2.將剛纔使用過的編譯鏈接命令放build.sh文件內:

echo "======將main.m編譯成main.o======start"
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./AFNetworking \
-c main.m -o main.o
echo "======將main.m編譯成main.o======end"

echo "======連接靜態庫生成可執行文件======start"
clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-L./AFNetworking \
-lAFNetworking \
main.o -o main
echo "======連接靜態庫生成可執行文件======end"
複製代碼

3.cd到當前目錄下執行

./build.sh
複製代碼

可能會出現

圖片.png

這時候執行

chmod +x build.sh
複製代碼

以後再次執行

./build.sh
複製代碼

過程以下:

圖片.png 執行結果

圖片.png

靜態庫原理

經過ar命令可以看到libAFNetworking.a這個庫文件是.o文件合集。 接下來經過一個例子連接一個.o文件更名的庫文件

1.準備工程目錄以下:

圖片.png

TestStaticLib文件代碼:

//TestStaticLib.h代碼

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface TestStaticLib : NSObject
-(void)testStaticLib;

@end


//TestStaticLib.m文件代碼

#import "TestStaticLib.h"

@implementation TestStaticLib
-(void)testStaticLib
{
    NSLog(@"---testStaticLib---");
}
@end


NS_ASSUME_NONNULL_END
複製代碼

main.m文件代碼

#import <Foundation/Foundation.h>
#import "TestStaticLib.h"
int main() {
    TestStaticLib *lib = [TestStaticLib new];
    NSLog(@"test---%@",lib);
    return 0;
}
複製代碼

2.cdTestStaticLib.m所在目錄,執行命令:

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 TestStaticLib.m -o TestStaticLib.o
複製代碼

圖片.png 使用file查看文件類型

圖片.png 3.根據庫文件查找規則(先找lib+<library_name>的動態庫,找不到,再去找lib+<library_name>的靜態庫,還找不到,就報錯),將TestStaticLib.o文件進行更名爲libTestStaticLib.dylib

圖片.png 使用file查看文件類型

圖片.png 改了名字,仍是object類型的文件,若是被連接成功併成功執行,也就說明了靜態庫是.o文件的合集。

4.cdmain.m所在目錄,執行命令:

編譯

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./StaticLib \
-c main.m -o main.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./StaticLib \
-lTestStaticLib \
main.o -o main
複製代碼

圖片.png 4.雙擊執行

圖片.png 也可以成功執行

動態庫

獲取第三方動態庫方法(參考)

和獲取靜態庫的方式差很少,區別是將#use_frameworks!中的#號去掉

1.使用cocoPods安裝AFNetworking,在Podfile文件中target下添加

use_frameworks!
pod 'AFNetworking'
複製代碼

2.終端執行安裝命令成功後,打開xcworkspace文件,command+B編譯一下,找到AFNetworking.framework

圖片.png

3.右鍵show in Finder,找到AFNetworkingHeaders

圖片.png

4.將AFNetworking文件更名爲libAFNetworking.dylib,將Headers文件夾命名爲AFNetworking,而後將libAFNetworking.dylib放到AFNetworking文件夾內。

更名緣由:
連接庫查找規則:先找lib+<library_name>的動態庫,找不到,再去找lib+<library_name>的靜態庫,還找不到,就報錯

連接動態庫

rpath、executable_path的使用

主工程連接一個動態庫演示:

1.將連接靜態庫的main.m文件拿過來和該AFNetworking文件夾放到同一目錄下: 圖片.png 2.cd到該目錄下(這裏是連接動態庫),執行下面命令,將main.m編譯成main.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./AFNetworking \
-c main.m -o main.o
複製代碼

3.連接靜態庫生成可執行文件

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-L./AFNetworking \
-lAFNetworking \
main.o -o main
複製代碼

4.點擊生成的可執行文件main,結果以下: 圖片.png

從上面的報錯可知,dyld @rpath/AFNetworking.framework/Versions/A/AFNetworking路徑下找不到庫

使用otool命令查看可執行文件main

otool -l main | grep 'DYLIB' -A 5
複製代碼

圖片.png

分析:這個(LC_LOAD_DYLIB)路徑和報錯提示的一致,接下來須要修改這個路徑。這個路徑是libAFNetworking.dylib提供的,因此要先去修改libAFNetworking.dylib

cd AFNetworking文件夾下,使用otool命令查看可執行文件libAFNetworking.dylib

otool -l libAFNetworking.dylib | grep 'ID' -A 5
複製代碼

圖片.png 可以看到main中的LC_LOAD_DYLIB就是libAFNetworking.dylib中的LC_ID_DYLIB,這個路徑是默認路徑,咱們已經修改了文件目錄,因此如今須要對其進行修改

5.cdAFNetworking文件夾下,使用install_name_tool命令修改路徑。這裏須要用到@rpath,能夠這樣理解,誰要連接動態庫,誰就要提供@rpath,它就是本身所在位置,這裏是main要連接,因此@rpath就表明main所在目錄, 須要修改的路徑就是@rpath/AFNetworking/libAFNetworking.dylib

終端執行:

install_name_tool -id @rpath/AFNetworking/libAFNetworking.dylib libAFNetworking.dylib
複製代碼

再次使用otool命令查看

otool -l libAFNetworking.dylib | grep 'ID' -A 5
複製代碼

圖片.png 已經修改爲功

6.這時候須要從新執行2.3兩步,將剛纔的修改關聯的main上。而後雙擊可執行文件main

圖片.png

發現依舊找不到庫,可是路徑已經修改過了。其實這裏的路徑只有後面的一段,還須要前面的一段拼在一塊兒纔是完整的路徑。這個路徑是存在main中的

7.cdmain所在目錄,使用otool命令查看RPATH

otool -l main | grep 'RPATH' -A 5
複製代碼

圖片.png

並無內容輸出,也就是沒有,如今須要添加,添加命令

install_name_tool -add_rpath @executable_path main
複製代碼

@executable_path提供當前可執行文件main的以前的路徑 再次使用otool命令查看RPATH

圖片.png 已經添加成功了

7.最後雙擊執行可執行文件main 圖片.png 注意點:

  1. 修改庫文件中的LC_ID_DYLIB
  2. 編譯連接生成主工程文件
  3. 修改主工程文件添加LC_LOAD_DYLIB

使用腳本文件編譯連接

對應腳本文件代碼:

#pushd到AFNetworking文件下
pushd ./AFNetworking
echo "======修改動態庫路徑======start"
install_name_tool -id @rpath/AFNetworking/libAFNetworking.dylib libAFNetworking.dylib
echo "======修改動態庫路徑======end"
#回到上一個目錄
popd

echo "======將main.m編譯成main.o======start"
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./AFNetworking \
-c main.m -o main.o
echo "======將main.m編譯成main.o======end"

echo "======連接靜態庫生成可執行文件======start"
clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-L./AFNetworking \
-lAFNetworking \
main.o -o main
echo "======連接靜態庫生成可執行文件======end"

echo "======修改可執行文件main路徑======start"
install_name_tool -add_rpath @executable_path main
echo "======修改可執行文件main路徑======end"

複製代碼

load_path的使用

主工程連接動態庫A,動態庫A連接動態庫B演示:

1.建立工程目錄

圖片.png 2.添加測試文件及代碼 main.m

#import <Foundation/Foundation.h>
#import "myLibA.h"
int main(){
    myLibA *libA = [myLibA new];
    NSLog(@"----libA:%@",libA);
    [libA mylibAClass];
    return 0;
}
複製代碼

myLibA

//myLibA.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface myLibA : NSObject
-(void)mylibAClass;
@end

NS_ASSUME_NONNULL_END

//myLibA.m
#import "myLibA.h"
#import "myLibB.h"
@implementation myLibA
-(void)mylibAClass
{
    NSLog(@"=====MylibAClass");
    myLibB *lib = [myLibB new];
    [lib MylibBClass];
}
@end
複製代碼

myLibB

//myLibB.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface myLibB : NSObject
-(void)MylibBClass;
@end

NS_ASSUME_NONNULL_END

//myLibB.m
#import "myLibB.h"

@implementation myLibB
-(void)MylibBClass
{
    NSLog(@"=====myLibB");
}
@end

複製代碼

3.編譯鏈接myLibB.framework cdmyLibB.framework目錄下,執行

編譯:

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./Headers \
-c myLibB.m -o myLibB.o
複製代碼

連接:

clang -dynamiclib  \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-Xlinker -install_name -Xlinker @rpath/myLibB.framework/myLibB \
myLibB.o -o myLibB
複製代碼
參數解釋:
-Xlinker 傳參數給連接器
複製代碼

4.編譯鏈接myLibA.framework cdmyLibA.framework目錄下,執行 編譯:

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./Headers \
-I./Frameworks/myLibB.framework/Headers \
-c myLibA.m -o myLibA.o
複製代碼

連接:

clang -dynamiclib  \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-Xlinker -install_name -Xlinker @rpath/myLibA.framework/myLibA \
-F./Frameworks \
-framework myLibB \
myLibA.o -o myLibA
複製代碼

這裏留個坑,沒有添加連接myLibB的執行者路徑

5.cdmain.m所在目錄,編譯鏈接main.m 編譯:

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./Frameworks/myLibA.framework/Headers \
-c main.m -o main.o
複製代碼

連接:

clang   \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-F./Frameworks \
-framework myLibA \
main.o -o main
複製代碼

main添加執行者路徑:

install_name_tool -add_rpath @executable_path/Frameworks main
複製代碼

6.雙擊可執行文件main

圖片.png 7.修改myLibALC_RPATH

install_name_tool -add_rpath  @executable_path/Frameworks/myLibA.framework/Frameworks myLibA
複製代碼

圖片.png 8.從新執行第5步後雙擊main 圖片.png 運行成功 @executable_path/Frameworks/myLibA.framework看起來比較長,可用@loader_path代替 第7步可改成

install_name_tool -add_rpath  @loader_path/Frameworks myLibA
複製代碼

使用腳本文件編譯連接

echo '==========處理myLibB==========start'
pushd ./Frameworks/myLibA.framework/Frameworks/myLibB.framework

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./Headers \
-c myLibB.m -o myLibB.o

clang -dynamiclib  \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-Xlinker -install_name -Xlinker @rpath/myLibB.framework/myLibB \
myLibB.o -o myLibB

popd
echo '==========處理myLibB==========end'

echo '==========處理myLibA==========start'
pushd ./Frameworks/myLibA.framework

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./Headers \
-I./Frameworks/myLibB.framework/Headers \
-c myLibA.m -o myLibA.o



clang -dynamiclib  \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-Xlinker -install_name -Xlinker @rpath/myLibA.framework/myLibA \
-F./Frameworks \
-framework myLibB \
myLibA.o -o myLibA

install_name_tool -add_rpath @loader_path/Frameworks myLibA

popd
echo '==========處理myLibB==========end'

echo '==========處理main==========start'
clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./Frameworks/myLibA.framework/Headers \
-c main.m -o main.o

clang   \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-F./Frameworks \
-framework myLibA \
main.o -o main

install_name_tool -add_rpath @executable_path/Frameworks main
echo '==========處理myLibB==========end'

複製代碼

-reexport_framework的使用

基於上個示例,咱們知道它們的連接關係是這樣的:main-myLibA-myLibB,若是main想調用myLibB裏的方法改怎麼辦?只須要如下3步:

  1. 修改main.m的代碼
#import <Foundation/Foundation.h>
#import "myLibA.h"
#import "myLibB.h"
int main(){
    myLibA *libA = [myLibA new];
    NSLog(@"----libA:%@",libA);
    [libA mylibAClass];
    myLibB *libB = [myLibB new];
    NSLog(@"----libB:%@",libB);
    [libB MylibBClass];
    return 0;
}

複製代碼
  1. 將myLibB的符號路徑加入myLibA`,使用

-reexport_framework

cd到myLibA.framework文件夾下,執行

clang -dynamiclib  \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-Xlinker -install_name -Xlinker @rpath/myLibA.framework/myLibA \
-Xlinker -reexport_framework -Xlinker myLibB \
-F./Frameworks \
-framework myLibB \
myLibA.o -o myLibA
複製代碼

圖片.png main會經過LC_REEXPORT_DYLIB找到myLibB 1.將myLibB的頭文件查找路徑告訴編譯器後,生成新的main cdmain所在目錄下執行: 編譯:

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./Frameworks/myLibA.framework/Headers \
-I./Frameworks/myLibA.framework/Frameworks/myLibB.framework/Headers \
-c main.m -o main.o
複製代碼

連接:

clang   \
-target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-F./Frameworks \
-framework myLibA \
main.o -o main
複製代碼

main添加執行者路徑:

install_name_tool -add_rpath @executable_path/Frameworks main
複製代碼

最後查看程序運行結果:

圖片.png

動態庫原理

1.準備工程目錄

圖片.png TestDyLib代碼

//TestDyLib.h代碼

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface TestDyLib : NSObject
-(void)TestDyLib;

@end

//TestDyLib.m代碼

#import "TestDyLib.h"

@implementation TestDyLib
-(void)TestDyLib
{
    NSLog(@"---TestDyLib---");
}
@end

複製代碼

main.m代碼

#import <Foundation/Foundation.h>
#import "TestDyLib.h"
int main() {
    TestDyLib *lib = [TestDyLib new];
    NSLog(@"test---%@",lib);
    return 0;
}
複製代碼

2.cd到TestDyLib.m文件所在目錄,將TestDyLib.m編譯成目標文件:

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-c TestDyLib.m -o TestDyLib.o
複製代碼

3.使用libtoolTestDyLib.o編譯成靜態庫

libtool -static -arch_only x86_64 TestDyLib.o -o libTestDyLib.a
複製代碼
參數解釋:
-static:編譯靜態庫
-arch_only x86_64:架構
複製代碼

4.使用ld連接器將libTestDyLib.a連接成動態庫

ld -dylib -arch x86_64 \
-macosx_version_min 11.1 \
-syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-lsystem -framework Foundation \
libTestDyLib.a -o libTestDyLib.dylib
複製代碼
參數解釋:
-dylib:連接動態庫
-arch_only x86_64:架構
-macosx_version_min 11.1:最小支持版本
syslibroot:使用的SDK路徑
-lsystem:依賴系統框架
複製代碼

5.cdmain.m所在目錄,編譯成目標文件

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./dylib \
-c main.m -o main.o
複製代碼

6.連接生成可執行文件

clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-L./dylib \
-lTestDyLib \
main.o -o main
複製代碼

圖片.png 發現報錯,找不到這個符號。 7.回到dylib目錄下,修改連接器參數,再執行

ld -dylib -arch x86_64 \
-macosx_version_min 11.1 \
-syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-lsystem -framework Foundation \
-all_load
libTestDyLib.a -o libTestDyLib.dylib
複製代碼
參數解釋:
-all_load:告訴編譯器,無論符號有沒有被用到,所有都載入
複製代碼

8.執行第6步,成功生成可執行文件main,雙擊執行

圖片.png 出現這個錯誤就是路徑問題,具體見上面的連接動態庫部分 解決:

  • 修改庫文件中的LC_ID_DYLIB

圖片.png

  • 編譯連接生成主工程文件,執行第五、6兩步

  • 修改主工程文件添加LC_LOAD_DYLIB

圖片.png

  • 雙擊可執行文件main

圖片.png 可以看到,可以將靜態庫連接成動態庫。

結論:動態庫是.o文件連接事後的產物,是連接的最終產物,它比靜態庫要多走一次連接的過程。

使用腳本文件編譯連接

腳本文件代碼:

pushd ./dylib
echo "======TestDyLib編譯成目標文件======start"
clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-c TestDyLib.m -o TestDyLib.o
echo "======TestDyLib編譯成目標文件======end"


echo "======將TestDyLib.o編譯成靜態庫======start"
# Xcode->靜態庫
libtool -static -arch_only x86_64 TestDyLib.o -o libTestDyLib.a
echo "======將TestDyLib.o編譯成靜態庫======end"

echo "======將TestDyLib.a連接成動態庫======start"
ld -dylib -arch x86_64 \
-macosx_version_min 11.1 \
-syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-lsystem -framework Foundation \
-all_load \
libTestDyLib.a -o libTestDyLib.dylib
echo "======將TestDyLib.a連接成動態庫======end"
install_name_tool -id @rpath/dylib/libTestDyLib.dylib libTestDyLib.dylib
popd

echo "======main編譯成目標文件======start"
clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-I./dylib \
-c main.m -o main.o
echo "======main編譯成目標文件======end"

echo "======連接lTestDyLib.dylib======start"
clang -target x86_64-apple-macos11.1 \
-fobjc-arc \
-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk \
-L./dylib \
-lTestDyLib \
main.o -o main
echo "======連接lTestDyLib.dylib======end"
install_name_tool -add_rpath @executable_path main

複製代碼
相關文章
相關標籤/搜索