修正PackageApplication -o參數(shù)不能指定相對目錄的問題

PackageApplication是舊版本Xcode提供的導(dǎo)出IPA的腳本。
新版本的Xcode已經(jīng)廢棄了,取而代之是建議使用xcodebuild archive。

最近,在使用archive的時(shí)候,卻遇到了個(gè)小問題,每次archive都要全部編譯一次代碼。而xcodebuild build命令則是默認(rèn)增量編譯的。于是,重新拿起PackageApplication。卻發(fā)現(xiàn),這貨的-o參數(shù)竟然不能支持相對目錄。
只好認(rèn)真讀一下這個(gè)腳本了。
發(fā)現(xiàn)問題在于:它先創(chuàng)建了一個(gè)臨時(shí)目錄,把文件拷貝過去,然后cd到那個(gè)臨時(shí)目錄再執(zhí)行zip命令壓縮,于是,我們給的-o參數(shù),如果是相對目錄的話,就變成是相對這個(gè)臨時(shí)目錄了。
找到問題的原因,修改一下就很簡單了。在cd之前,先用abs_path獲取這個(gè)相對目錄的絕對路徑就好了。


附上修改后的全部腳本內(nèi)容

#!/usr/bin/perl
#
#    PackageApplication
#    
#    Copyright (c) 2009-2012 Apple Inc.  All rights reserved.
#
#    Package an iPhone Application into an .ipa wrapper
#

use Pod::Usage;
use Getopt::Long;
use File::Temp qw/ tempdir :POSIX /;
use File::Basename;
use File::Path qw/ remove_tree /;
use Cwd qw/ chdir /;
use Cwd qw/ abs_path/;

print "\n\n\nwarning: PackageApplication is deprecated, use `xcodebuild -exportArchive` instead.\n\n\n";

$|=1;   # don't buffer stdout

my $program = $0;

my %opt = ();
GetOptions ( \%opt,
             "sign|s=s",
             "embed|e=s",
             "output|o=s",
             "symbols=s",
             "verbose|v!",
             "help|h|?",
             "man",
             "plugin=s@" => \@plugins,
             ) or pod2usage(2);

pod2usage(2) if $opt{help};
pod2usage(-exitstatus => 0, -verbose => 2) if $opt{man};

fatal("An application was not specified.") unless $ARGV[0];
my $origApp = shift @ARGV;
fatal("Specified application doesn't exist or isn't a bundle directory : '$origApp'") unless -d $origApp;

if ( $opt{verbose} ) {
    print "Packaging application: '$origApp'\n";
    print "Arguments: ";
    while( ($key,$value) = each %opt)
    {
        print "$key=$value  ";
    }
    print "\n";
    print "Environment variables:\n";
    while( ($key,$value) = each %ENV)
    {
        print "$key = $value\n";
    }
    print "\n";
}

# check any plugins that might be specified 
foreach $plugin (@plugins) {
    print "Plugin: '$plugin'\n" if $opt{verbose};
    fatal("Specified plugin doesn't exist or isn't a bundle directory : '$plugin'") unless -d $plugin;
}

# setup the output name if it isn't specified

# setup the output if it isn't specified 
if ( !defined($opt{output})  ) {
    $opt{output} = dirname($origApp).'/'.basename($origApp, ".app")."\.ipa";
}
$opt{output} = abs_path($opt{output});
print "Output directory: '$opt{output}'\n" if $opt{verbose};
# Make sure we have a temp dir to work with
my $tmpDir = tempdir( CLEANUP => !defined($opt{verbose}) );
print "Temporary Directory: '$tmpDir'  (will NOT be deleted on exit when verbose set)\n" if $opt{verbose};


################## Start Packaging #####################

### Step One : Make a copy of the application (and any plugins)
my $appName = basename($origApp);
chomp $appName;
my $destAppDir = "$tmpDir/Payload";
my $destApp = "$destAppDir/$appName";

mkdir $destAppDir;
fatal("Unable to create directory : '$destAppDir'") unless -d $destAppDir;

runCmd("/bin/cp", "-Rp", $origApp, $destAppDir);
fatal("Unable to copy application '$origApp' into '$destAppDir'") unless -e $destApp;

foreach $plugin (@plugins) {
    my $pluginName = basename($plugin);
    chomp $pluginName;
    my $destPlugin = "$destAppDir/$pluginName";
    
    my $result = runCmd("/usr/bin/codesign", "--verify", "-vvvv", , $plugin );
    if ( $result !~ /valid on disk/ ) {
        fatal("Codesign check fails : $result\n");
    }
    
    runCmd("/bin/cp", "-Rp", $plugin, $destAppDir);
    fatal("Unable to copy application '$plugin' into '$destAppDir'") unless -e $destPlugin;
}

if ( $opt{symbols} ) {
    my $destSymbols = "$tmpDir/Symbols";
    runCmd("/bin/cp", "-Rp", $opt{symbols}, $destSymbols);
    fatal("Unable to copy symbols '$opt{symbols}' into '$destSymbols'") unless -e $destSymbols;
}

### Step Two : recode sign it if necessary

if ( $opt{verbose} ) {
    print "### Checking original app\n";
    my $result = runCmd("/usr/bin/codesign", "--verify", "-vvvv", , $origApp );
    if ( $result !~ /valid on disk/ ) {
        print "Codesign check fails : $result\n";
    }
    print "Done checking the original app\n";
}


if ( defined $opt{sign} ) {
    if ( $opt{embed} ) {
        print "### Embedding '$opt{embed}'\n" if $opt{verbose};
        runCmd("/bin/rm", "-rf", "$destApp/embedded.mobileprovision" );
        fatal("Unable to remove '$destApp/embedded.mobileprovision'\n") if ( -e "$destApp/embedded.mobileprovision" );
        runCmd("/bin/cp", "-rp", $opt{embed}, "$destApp/embedded.mobileprovision");
        fatal("Unable to copy '$opt{embed}' to '$destApp/embedded.mobileprovision'\n") unless ( -e "$destApp/embedded.mobileprovision" );
    }

    my $entitlements_plist = File::Temp::tempnam($tmpDir, "entitlements_plist");

    # If re-signing with a distribution profile and get-task-allow is
    # true, the app store will reject the submission. Setting
    # get-task-allow to false here.
    if ( $opt{sign} =~ /^i(Phone|OS) Distribution/ ) {
        my $entitlements_raw = File::Temp::tempnam($tmpDir, "entitlements_raw");
        runCmd("/usr/bin/codesign", "-d", "--entitlements", $entitlements_raw, $destApp);
        $? == 0 or fatal("Failed to read entitlements from '$destApp'");
        if ( -e $entitlements_raw ) {
            $plist = read_raw_entitlements($entitlements_raw);
            unlink($entitlements_raw) or fatal("Cannot delete '$entitlements_raw': $!");

            open(my $ofh, '>', $entitlements_plist) or fatal("Cannot open '$entitlements_plist': $!");
            print $ofh $plist or fatal("Cannot write entitlements to '$entitlements_plist': $!");
            close($ofh) or fatal("Cannot close file handle for '$entitlements_plist': $!");

            runCmd('/usr/libexec/PlistBuddy', '-c', 'Set :get-task-allow NO', $entitlements_plist);
            # PlistBuddy will fail if get-task-allow doesn't exist. That's okay.
            runCmd('/usr/bin/plutil', '-lint', $entitlements_plist);
            $? == 0 or fatal("Invalid plist at '$entitlements_plist'");
        }
    }

    my @codesign_args = ("/usr/bin/codesign", "--force", "--preserve-metadata=identifier,entitlements,resource-rules",
                         "--sign", $opt{sign},
                         "--resource-rules=$destApp/ResourceRules.plist");

    if ( -e $entitlements_plist ) {
        push(@codesign_args, '--entitlements');
        push(@codesign_args, $entitlements_plist);
    }

    push(@codesign_args, $destApp);
    
    print "### Codesigning '$opt{embed}' with '$opt{sign}'\n" if $opt{verbose};
    my $codesign_output = runCmd(@codesign_args);
    $? == 0 or fatal("@codesign_args failed with error " . ($? >> 8) . ". Output: $codesign_output");

    if ( -e $entitlements_plist ) {
        unlink($entitlements_plist) or fatal("Cannot delete '$entitlements_plist': $!");
    }
}

### Step Three : zip up the package
remove_tree("$opt{output}");
fatal("Unable to remove older '$opt{output}'") if ( -e "$opt{output}" );

chdir $tmpDir;
if($opt{verbose}) {
    runCmd("/usr/bin/zip", "--symlinks", "--verbose", "--recurse-paths", "$opt{output}", ".");
} else {
    runCmd("/usr/bin/zip", "--symlinks", "--quiet", "--recurse-paths", "$opt{output}", ".");
}

fatal("Unable to create '$opt{output}'") if ( ! -e "$opt{output}" );

print "Results at '$opt{output}' \n" if $opt{verbose};

################## Finished ############################

exit 0;

########################################################

sub fatal {
    my ($msg) = @_;
    
    print STDERR "error: $msg\n";
    
    exit 1;
}

use POSIX qw(:sys_wait_h);

sub runCmd {
    my (@cmds) = @_;
    
    my $output = ();
    if ( $opt{verbose} ) {
        my $_cmd = join(" ", @cmds);
        print "+ $_cmd\n" ;
    }
    my $program = shift @cmds;
    
    my ($readme, $writeme);
    pipe $readme, $writeme;
    my $pid = fork;
    defined $pid or die "cannot fork: $!";
    if ( $pid == 0 ) {
        # child
        open(STDOUT, ">&=", $writeme) or die "can't redirect STDOUT: $!";
        open(STDERR, ">&=", $writeme) or die "can't redirect STDERR: $!";
        close $readme;
        exec($program, @cmds) or die "can't run $program: $!";
    }

    close $writeme;
    while(<$readme>) {
        $output .= $_;
    }
    close $readme;
    
    my $waitpid_ret;
    do { $waitpid_ret = waitpid($pid, 0); } while ( $waitpid_ret == 0 );
    $waitpid_ret == $pid or die "waitpid returned $waitpid_ret: $!";
    my $return_code = $? >> 8;
    
    $opt{verbose} and print "Program $program returned $return_code : [$output]\n";

# Let clients handle error checking.
#    $return_code == 0 or fatal("Program $program failed with return code $return_code.");
    
    return $output;
}

# Param: path to codesign --entitlements output file. Returns xml plist in a string.
sub read_raw_entitlements {
    my $entitlements_raw = shift;

    open(my $ifh, '<', $entitlements_raw) or fatal("Cannot open '$entitlements_raw': $!");

    read($ifh, my $format_tag, 4) or fatal("Cannot read format tag from '$entitlements_raw': $!");
    $format_tag = unpack('H*', $format_tag);
    my $expected_format_tag = 'fade7171';
    $format_tag eq $expected_format_tag
        or fatal("Format tag '0x$format_tag' does not match '0x$expected_format_tag'.");

    read($ifh, my $plist_size, 4) or fatal("Cannot read plist size from '$entitlements_raw': $!");
    $plist_size = unpack('L>', $plist_size);
    read($ifh, my $plist, $plist_size) or fatal("Cannot read $plist_size bytes of plist data from '$entitlements_raw': $!");

    close($ifh) or fatal("Cannot close file handle for '$entitlements_raw': $!");

    return $plist;
}

__END__
=head1 NAME

PackageApplication - prepare an application for submission to AppStore or installation by iTunes.

=head1 SYNOPSIS

PackageApplication [-s signature] application [-o output_directory] [-verbose] [-plugin plugin] || -man || -help 

Options:

    -s <signature>  certificate name to resign application before packaging
    -o              specify output filename
    -plugin         specify an optional plugin
    -help           brief help message
    -man            full documentation
    -v[erbose]      provide details during operation


=head1 OPTIONS

=over 8

=item B<-s>

Optional codesigning certificate identity common name.  If provided, the application is will be re-codesigned prior to packaging.

=item B<-o>

Optional output filename.  The packaged application will be written to this location.

=item B<-plugin>

Specify optional plugin.  The packaged application will include the specified plugin(s).

=item B<-help>

Print a brief help message and exits.

=item B<-man>

Prints the manual page and exits.

=item B<-verbose>

Provides additional details during the packaging.

=back

=head1 DESCRIPTION

This program will package the specified application for submission to the AppStore or installation by iTunes.

=cut

最后貼個(gè)Github鏈接
https://github.com/dourgulf/PackageApplication

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,673評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,668評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,004評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評(píng)論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,173評(píng)論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,705評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,426評(píng)論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,656評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,833評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評(píng)論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,371評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,621評(píng)論 2 380

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

  • 本文始發(fā)于我的博文詳解Shell腳本實(shí)現(xiàn)iOS自動(dòng)化編譯打包提交,現(xiàn)轉(zhuǎn)發(fā)至此。 目錄 前言 Shell腳本涉及的工...
    zackzheng閱讀 44,544評(píng)論 95 173
  • Ubuntu的發(fā)音 Ubuntu,源于非洲祖魯人和科薩人的語言,發(fā)作 oo-boon-too 的音。了解發(fā)音是有意...
    螢火蟲de夢閱讀 99,458評(píng)論 9 467
  • 1.Xcode IDE概覽 說明:從左到右,依次是“導(dǎo)航窗格(Navigator)->邊列(Gutter)->焦點(diǎn)...
    小地閱讀 5,380評(píng)論 0 9
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯(cuò)誤還是無法避免 以后資料會(huì)慢慢更新 大...
    數(shù)據(jù)革命閱讀 12,202評(píng)論 2 33
  • 要不是因?yàn)檫h(yuǎn)房親戚家沒有直達(dá)的火車,綠皮車我是很少坐的,一個(gè)是因?yàn)槁僖粋€(gè)車上人太雜,鬧哄哄的。中秋節(jié)的第一天,...
    邊思文閱讀 358評(píng)論 0 0