从目标中包括/排除整个组 [英] Including/excluding entire groups from targets

查看:23
本文介绍了从目标中包括/排除整个组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目有一个包含数百个文件的组(组织成两个级别深的几十个子组).该组中的文件本身经常被合理地更改.我希望这些文件包含在某些目标中,但不包含在其他目标中.

My project has a group with a few hundred files (organized into a couple dozen subgroups two levels deep). The files in that group are themselves being changed reasonably often. I want those files to be included in some targets, but not others.

在 Xcode 3.x 中,每次更改组后,我只需获取组本身的信息,转到目标"选项卡,然后(重新)选择我想要的目标.(事实上​​,这是对 2010 年几乎相同问题的答案,Xcode — 组和目标.)

In Xcode 3.x, after each change to the group, I would just Get Info on the group itself, go to the Targets tab, and (re-)select the targets I wanted. (This was, in fact, the answer to a nearly-identical question from 2010, Xcode — groups and targets.)

在 Xcode 5 中,如果您选择了一个组,则等效的 File Inspector 面板没有 Target Membership 部分(并且,即使选择一个组与选择其所有文件相同,Target Membership 复选框也被禁用如果您选择多个文件).

In Xcode 5, the equivalent File Inspector panel doesn't have a Target Membership section if you have a group selected (and, even if selecting a group were the same as selecting all of its files, the Target Membership checkboxes are disabled if you select more than one file).

那么,这个功能是否仍然存在,但隐藏在我无法找到的地方?

So, is this functionality still there, but hidden somewhere I haven't been able to find it?

如果没有,显然还有其他方法我可以做我想做的事——脚本 Xcode,解析 .pbxproj 文件,或者将组抽象成一个子项目或一个完全独立的项目,构建一个静态库,等等.但我'我很高兴能够在这里使用 Xcode,就像我在 3.x 中所做的那样,而不必与它作斗争.

If not, obviously there are other ways I can do what I want—script Xcode, parse the .pbxproj file, or abstract the group into a subproject or an entirely separate project that builds a static lib, etc. But I'd love to be able to work with Xcode here, the way I did in 3.x, instead of have to fight against it.

实际上,编写 Xcode 脚本似乎不起作用.任何获取构建阶段的构建文件的尝试都会失败,并出现一般的 -10000 错误.例如:

Actually, scripting Xcode doesn't seem to work. Any attempt to get the build files of a build phase fails with a generic -10000 error. For example:

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

... 在最后一行失败:

… fails on the last line with:

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

推荐答案

这是我最终使用的 hack——显然我仍然希望有更好的解决方案.

Here's the hack I ended up using—I'd obviously still appreciate a better solution.

#!/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)

这篇关于从目标中包括/排除整个组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆