iOS SDK 開發(fā) -- 入微三星

入微二星里說了如何通過腳本去打包 Lib遏餐,這里主要說下如何通過腳本打包 Framework历恐。

我們先說下思路:首先需要把 Framework 里的頭文件更新软棺,更新頭文件后再生成一個 framework 包诫欠,這個時候的 framework 是無實際內(nèi)容的艰赞,只有文件結(jié)構(gòu),需要向里面添加對應(yīng)的 Lib 包提佣,最后才可以根據(jù) framework 的頭文件去調(diào)用 Lib 里面的方法了泽艘。

更新頭文件

#!/bin/sh
##############################
# 更新項目里的對外 API 頭文件欲险,并且做 import 形式的轉(zhuǎn)換工作
##############################

echo "\n=================================================="
echo "Action - updateAPIs"

# 引用公共的文件
source Scripts/common.sh

if [ ! $SDK_REPO_DIR ]; then
    echo "SDK_REPO_DIR not exist. Exit.";
    exit 1;
fi

SOURCE_PATH_ROOT="${SDK_REPO_DIR}/sdkSample-lib/Lib/Public"
# 這里可以有SOURCE_PATH_ROOT其它的子目錄

DEST_PATH_ROOT="${SDK_REPO_DIR}/sdkSample-framework/API"
# 這里可以有DEST_PATH_ROOT其它的子目錄

SOURCE_DIRS=($SOURCE_PATH_ROOT)
DEST_DIRS=($DEST_PATH_ROOT)

# 先確認目錄環(huán)境是否正常
existDir() {
    theDir=`ls $1`
    if [ ! theDir ]
    then
        echo -e "$1 does not exist. Not the right path to execute the script."
        exit
    fi
}

existDir $SOURCE_PATH_ROOT
existDir $DEST_PATH_ROOT

src_imports=('#import \"sdkSample.h\"',
        '#import \"SDKConstants.h\"'
    )
dest_imports=('#import <sdkSample\/sdkSample.h>',
        '#import <sdkSample\/SDKConstants.h>'
    )

replace_imports() {
    len_imports="${#src_imports[@]}"
    for i in `seq $len_imports`
    do
        `sed -i "" "s/${src_imports[$i-1]}/${dest_imports[$i-1]}/g" $1`
    done
}

index=0
for dir in "${SOURCE_DIRS[@]}"
do
    for file in $dir/*.h;
    do
        filename=$(basename $file)
        destFile="${DEST_DIRS[$index]}/$filename"
        `cp "$file" "$destFile"`
        replace_imports "$destFile"
    done
    let "index+=1"
done

# Insert all .h imports into sdkSample.h - the only import file for App
sdkSampeFile="$DEST_PATH_ROOT/sdkSample.h"
echo "Insert imports into sdkSample.h - $sdkSampeFile"

sed -i "" '9 a\
    #import <sdkSample\/SDKConstants.h>\
    ' $sdkSampeFile

這是主要是做把 import 的轉(zhuǎn)換的,因為對外的 api 的接口中匹涮,#import "SDKConstants.h" 應(yīng)該轉(zhuǎn)換成 #import <sdkSample/SDKConstants.h>,還有就是將其它需要用到的頭文件導(dǎo)入到sdkSample.h 里面槐壳,目的是只要用戶導(dǎo)入 sdkSample.h 后然低,其頭文件也保證已經(jīng)全部導(dǎo)入,不再需要用戶單獨去做導(dǎo)入工作务唐,而且也提供單獨導(dǎo)入指定頭文件的功能雳攘。

生成 Framework

B388CE0C-546A-42EB-9D38-4C3E24886481.png

在 Framework 根目錄下新建 packageTempFramework.sh 和 Rakefile,前面已經(jīng)有相關(guān)的介紹枫笛,這里面就不多說了吨灭。說下這里面的打包腳本名為什么叫 packageTempFrame,因為生成只是 framework 的文件結(jié)構(gòu)刑巧,還沒有實際內(nèi)容喧兄,上面已經(jīng)提過了。

我們看下 packageTempFramework 的內(nèi)容:

#!/bin/sh

#######################################################
### Package sdkSample.framework folder structure.
#######################################################

echo "\n=================================================="
echo "Action - packageTempFramework"
echo "Current dir - `pwd`"

# 引用公共的文件
if [ ! -f Scripts/common.sh ]; then
    echo "ERROR: not found Scripts/common.h"
    exit 1
fi
source Scripts/common.sh

# 更新 API 文件
source Scripts/updateAPIs.sh

cd $SDK_REPO_DIR/sdkSample-framework

# rake build
rake

if [ $? == 0 ]; then 
    echo "Rake build success"

    # Validdate result of rake    
    if [ ! -d $SDK_FRAMEWORK_STRUCT_DIR ]; then
        echo "The expect rake build outoput dir does not exist - ${SDK_FRAMEWORK_STRUCT_DIR}"
        exit 1
    fi

    # Write version/buildId into framework info.plist
    defaults write $SDK_FRAMEWORK_STRUCT_DIR/Info CFBundleVersion $SDK_BUILDID
    defaults write $SDK_FRAMEWORK_STRUCT_DIR/Info CFBundleShortVersionString $SDK_VERSION
else 
    echo "Rake build failed"
fi

最后會把版本會版本號構(gòu)建號保存到工程的 info.plist 文件中啊楚。

再看下 Rakefile 的內(nèi)容:

##########################
# Rake for build frameowrk structure. Will dist to RootDir/build/sdkSample.framework
##########################

puts "\nAction - sdkSample-framework rake build"

outputFile = ENV['SDK_FRAMEWORK_STRUCT_DIR']

if !outputFile
  outputFile = "../build/sdkSample.framework/"
  puts "WARN - Running rake with no build dependency."
end

puts "Will put dist file into - '#{outputFile}'"


$config = "Release"
def xcodebuild(sdk, archs, iphoneos_deployment_target, products_dir)
  puts $config
  config = $config
  sh "xcodebuild -project 'sdkSample-framework.xcodeproj' -target sdkSample -configuration '#{config}' -sdk '#{sdk}' clean build ARCHS='#{archs}' VALID_ARCHS='#{archs}' IPHONEOS_DEPLOYMENT_TARGET='#{iphoneos_deployment_target}' TARGET_BUILD_DIR='#{products_dir}' BUILT_PRODUCTS_DIR='#{products_dir}' "
end

desc "Build arm"
task :build_arm do
  xcodebuild('iphoneos', 'armv7 armv7s', '7.0', 'build-arm')
end

desc "Build arm64"
task :build_arm64 do
  xcodebuild('iphoneos', 'arm64', '7.0', 'build-arm64')
end

desc "Build i386"
task :build_i386 do
  xcodebuild('iphonesimulator', 'i386', '7.0', 'build-i386')
end

desc "Build x86_64"
task :build_x86_64 do
  xcodebuild('iphonesimulator', 'x86_64', '7.0', 'build-x86_64')
end

desc "Build fat"
task :build_fat => [:build_arm] do
  sh "lipo -create ./build-arm/sdkSample.framework/sdkSample -output ./build-arm/sdkSample.framework/sdkSample"
  sh "mv ./build-arm/sdkSample.framework \"$(dirname #{outputFile})\""
end

desc "Clean"
task :clean do
  Dir["build-*"].each{ |x|
    `rm -r '#{x}'`
  }
end

desc "Clean binary"
task :distclean => [:clean] do
  Dir["build/*.a"].each{ |x|
    `rm -r '#{x}`
  }
end

task :debug => [:distclean, :debug_fat]

task :default => [:distclean, :build_fat, :distclean]

這里和 Lib 打包相似吠冤,就不單獨說了。需要強調(diào)的是恭理,這里只是生成 Framework 的文件結(jié)構(gòu)拯辙。

提供核心打包函數(shù):

FD4100F5-AD36-4B59-BCCA-3EE1503E5A7A.png

新建一個 debugOrReleaseFramework 的腳本,主要提供 Framework 打包的核心功能颜价,把生成的 lib 內(nèi)容復(fù)制到 Framework 的文檔結(jié)構(gòu)里面涯保。這里主要是和 Lib 打包相聯(lián)系的,所以也是需要提供 Debug or release 參數(shù)進行打包的周伦。

腳本內(nèi)容如下:

#! /bin/sh  
##############################
# 執(zhí)行打包 Framework
##############################

# 引用公共的文件
source Scripts/common.sh

if [ ! $SDK_REPO_DIR ]; then
    echo "SDK_REPO_DIR not exist. Exit.";
    exit 1;
fi

# 核心的打包函數(shù)
packageFramework() {
    echo "Action - packageFramework - $1"

    if [ $# -lt 1 ]; then
        echo "At least one param is required - debug/release";
        exitAbnormal
    fi

    if [ ! $1 = debug -a ! $1 = release ]; then
        echo "First param should be debug or release";
        exitAbnormal
    fi

    buildVersion=$1;

    # lib build
    cd $SDK_REPO_DIR
    bash ${SDK_REPO_DIR}/sdkSample-lib/packageLib.sh $buildVersion

    if [ $? != 0 ]; then
        echo "ERROR: packageSdkSampleLib script fail."
        exitAbnormal
    fi

    # Confirm expect output of last step
    if [ ! -f ${SDK_LIB_FILE} ]; then
        echo "Unexpected - expect file does not exist - ${SDK_LIB_FILE}"
        exitAbnormal
    fi

    # Copy lib file into framework struct 
    cp "${SDK_LIB_FILE}" "${SDK_FRAMEWORK_STRUCT_DIR}/sdkSample"
    if [ $? != 0 ]; then
        echo "ERROR: failed to copy sdkSample lib into framework."
        exitAbnormal
    fi

    cd $SDK_REPO_DIR/dist

    if [ $buildVersion = debug ]; then
        zipDir="sdkSample-debug-${SDK_VERSION}b${SDK_BUILDID}"
    else
        zipDir="sdkSample-${SDK_VERSION}"
    fi
    mkdir $zipDir

    cp -r $SDK_FRAMEWORK_STRUCT_DIR ${zipDir}/
    if [ $? != 0 ]; then
        echo "ERROR: failed to copy sdkSample framework into dist."
        exitAbnormal
    fi

} # end of packageFramework

控制打包流程

結(jié)合面兩篇文章(入微一星入微一星)已經(jīng)說完了 Lib 的打包和 Framework 的打包夕春,現(xiàn)在我們需要提供一個統(tǒng)一控制流程的腳本,在根目錄下新建一個 packageFramework.sh:

A44676EE-D0C5-4470-BA16-8A2BC84BA45B.png

內(nèi)容如下:

#!/bin/sh

###################################
# Build sdkSample.framework
# If there is one param - debug/release, will package ther version. Otherwise package both debug and release version.
###################################

echo "\n=================================================="
echo "Action - packageDdkSampleeFramework"
echo "Current dir - `pwd`"

# 引用公共的文件
if [ ! -f Scripts/common.sh ]; then
    echo "ERROR: cannot found the Script/common.h"
    exit 1
fi
source Scripts/common.sh

if [ ! -f Scripts/debugOrReleaseFramework.sh ]; then
echo "ERROR: cannot found the Script/common.h"
exit 1
fi
source Scripts/debugOrReleaseFramework.sh


if [ ! $SDK_REPO_DIR ]; then
    echo "SDK_REPO_DIR not exist. Exit.";
    exit 1;
fi

if [ $# -gt 0 ]; then
    if [ ! $1 = debug -a ! $1 = release ]; then
        echo "First param should be debug/release";
        exit 1;
    fi

    buildVersion=$1
fi

# Prepare
clearAndPrepare

# Confirm the git workspace is clean. 
checkGitWorkspaceClean $SDK_REPO_DIR

# get and set version
updateBuildID
if [ $? != 0 ]; then exitAbnormal; fi
getVersion
if [ $? != 0 ]; then exitAbnormal; fi

# Expect output definitions

PROJECT_NAME="sdkSample-iOS-SDK"
export PROJECT_NAME

SDK_LIB_FILE="${SDK_REPO_DIR}/build/sdkSample-${SDK_VERSION}b${SDK_BUILDID}.a"
export SDK_LIB_FILE

SDK_FRAMEWORK_STRUCT_DIR="${SDK_REPO_DIR}/build/sdkSample.framework"
export SDK_FRAMEWORK_STRUCT_DIR

SDK_DOCS_DIR="${SDK_REPO_DIR}/build/appledoc"
export SDK_DOCS_DIR

echo "\n\n\n ===================== Begin packaging"

cd $SDK_REPO_DIR
bash ${SDK_REPO_DIR}/sdkSample-framework/packageTempFramework.sh
if [ $? != 0 ]; then
    echo "ERROR: packageTempFramework script fail."
    exitAbnormal
fi

# Check expected outout dir exist
if [ ! -d $SDK_FRAMEWORK_STRUCT_DIR ]; then
    echo "ERROR: expect output dir not exist - $SDK_FRAMEWORK_STRUCT_DIR"
    exitAbnormal
fi

# To package debug/release framework zip
cd $SDK_REPO_DIR/sdkSample-lib
if [ $buildVersion ]; then
    packageFramework $buildVersion
else 
    packageFramework debug
    packageFramework release
fi

resetGitworkspace $SDK_REPO_DIR

echo "===================== End packaging \n\n\n "

這里需要注意的是横辆,在打包前需要確保當前 git 倉庫是 clean 的撇他,最后打包完成后,需要把倉庫 reset 下狈蚤,防止污染到原來的代碼困肩。這部分內(nèi)容主要是控制整個打包的流程,也就不多說明了脆侮,直接看腳本和腳本上面的注釋應(yīng)該沒有問題了锌畸。

小結(jié)

SDK 開發(fā)的入微三篇寫到這里已經(jīng)算是寫完了,這三篇文章主要說的是 SDK 的基礎(chǔ)框架的構(gòu)建和通過腳本進行打包靖避,內(nèi)容上沒有過多提及到實際中的 SDK 開發(fā)內(nèi)容潭枣,后面會不定期更新 SDK 開發(fā)的相關(guān)內(nèi)容比默,有興趣的朋友可以關(guān)注下SDK 開發(fā)專題。本來應(yīng)該還有一篇介紹如果通過 appledoc 生成接口文檔的盆犁,這個下次再以擴展形式出了命咐。源碼點這里

關(guān)注公眾號
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谐岁,一起剝皮案震驚了整個濱河市醋奠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伊佃,老刑警劉巖窜司,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異航揉,居然都是意外死亡塞祈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門帅涂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來议薪,“玉大人,你說我怎么就攤上這事漠秋◇厦桑” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵庆锦,是天一觀的道長捅位。 經(jīng)常有香客問我,道長搂抒,這世上最難降的妖魔是什么艇搀? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮求晶,結(jié)果婚禮上焰雕,老公的妹妹穿的比我還像新娘。我一直安慰自己芳杏,他們只是感情好矩屁,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著爵赵,像睡著了一般吝秕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上空幻,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天烁峭,我揣著相機與錄音,去河邊找鬼。 笑死约郁,一個胖子當著我的面吹牛缩挑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鬓梅,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼供置,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了己肮?” 一聲冷哼從身側(cè)響起士袄,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谎僻,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寓辱,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡艘绍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了秫筏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诱鞠。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖这敬,靈堂內(nèi)的尸體忽然破棺而出航夺,到底是詐尸還是另有隱情,我是刑警寧澤崔涂,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布阳掐,位于F島的核電站,受9級特大地震影響冷蚂,放射性物質(zhì)發(fā)生泄漏缭保。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一蝙茶、第九天 我趴在偏房一處隱蔽的房頂上張望艺骂。 院中可真熱鬧,春花似錦隆夯、人聲如沸钳恕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忧额。三九已至,卻和暖如春宦芦,著一層夾襖步出監(jiān)牢的瞬間宙址,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工调卑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抡砂,地道東北人大咱。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像注益,于是被迫代替她去往敵國和親碴巾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容