2014-08-28 69 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)