2014-08-28 66 views
1

我的項目有一個有幾百個文件的組(組織成兩個深度的幾個子組)。該組中的文件本身經常被合理地改變。我希望這些文件被包含在某些目標中,但不包括其他文件。包括/不包括整個組從目標

在Xcode 3.x中,每次更改組後,我只需在組本身上獲取信息,轉到「目標」選項卡,然後(重新)選擇我想要的目標。 (實際上,這是對2010年的一個幾乎相同的問題的回答,Xcode — groups and targets。)

在Xcode 5中,如果您選擇了一個組,則等效的File Inspector面板沒有「目標成員」部分,即使選擇一個組與選擇其所有文件相同,如果您選擇多個文件,目標成員資格複選框也會被禁用)。

那麼,這個功能還在嗎,但隱藏在某個地方,我一直無法找到它?

如果不是,顯然還有其他方法可以做我想做的事情 - 腳本Xcode,解析.pbxproj文件,或將組抽象爲子項目或完全獨立的項目,構建靜態庫等。但是,我'我喜歡能夠在這裏使用Xcode,就像我在3.x中所做的那樣,而不是必須與之對抗。


事實上,腳本Xcode中似乎並沒有工作。任何嘗試獲取構建階段的構建文件都會失敗,並帶有一個通用的-10000錯誤。例如:

tell application "Xcode" 
    set theproject to project "SampleProject" 
    set thetarget to target "SampleTarget" of theproject 
    set thephase to build phase "Compile Sources" of thetarget 
    build files of phase 
end tell 

...上最後一行失敗:

error "Xcode got an error: AppleEvent handler failed." number -10000 

回答

1

這裏是我結束了黑客利用,我倒是顯然還是欣賞更好的解決方案。

#!/usr/bin/env python3 

import os 
import plistlib 
import sys 

pbxproj = os.path.join(sys.argv[1], 'project.pbxproj') 
groupname = sys.argv[2] 
extensions = 'm mm c cc cpp'.split() 

with open(pbxproj, 'rb') as f: 
    p = plistlib.load(f) 

objs = p['objects'] 

groupid, group = next((k, v) for k, v in objs.items() 
         if v.get('path') == groupname) 

def descendants(id): 
    obj = objs[id] 
    if obj['isa'] == 'PBXFileReference': 
     yield (id, obj) 
    for child in obj.get('children', []): 
     yield from descendants(child) 

mdict = {id: obj for id, obj in descendants(group_id) 
     if os.path.splitext(obj['path'])[-1] in extensions} 

proj_id, proj = next((k, v) for k, v in objs.items() 
        if v['isa'] == 'PBXProject') 

for target_id in proj['targets']: 
    target = objs[target_id] 
    phase_ids = target['buildPhases'] 
    phases = [(phase_id, objs[phase_id]) for phase_id in phase_ids] 
    phase_id, phase = next((phase_id, phase) 
          for phase_id, phase in phases 
          if phase['isa'] == 'PBXSourcesBuildPhase') 
    fileref_ids = [i 
        for i, buildfile_id in enumerate(phase['files']) 
        if objs[buildfile_id]['fileRef'] in mdict] 
    fileref_ids.sort(reverse=True) 
    for i in fileref_ids: 
     del phase['files'][i] 

with open(pbxproj + '.new', 'wb') as f: 
    plistlib.dump(p, f) 
os.rename(pbxproj, pbxproj + '.bak') 
os.rename(pbxproj + '.new', pbxproj)