forked from omnigroup/OmniGroup
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathListSourceFilesInTarget
More file actions
executable file
·155 lines (128 loc) · 4.65 KB
/
Copy pathListSourceFilesInTarget
File metadata and controls
executable file
·155 lines (128 loc) · 4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/ruby
#
# Copyright 2010-2011 Omni Development, Inc. All rights reserved.
#
# This software may only be used and reproduced according to the
# terms in the file OmniSourceLicense.html, which should be
# distributed with this project and can also be found at
# <http://www.omnigroup.com/developer/sourcecode/sourcelicense/>.
#
# $Id$
require "osx/cocoa"
require 'pathname'
require 'getoptlong'
@@prog = File.basename(__FILE__)
def usage
msg = <<EOS
usage: #{@@prog} [--attribute attr1,attr2] target ext1,ext2 foo.xcodeproj
EOS
STDERR.print msg
exit 1
end
@@RequiredAttributes = []
GetoptLong.new(
[ "--attribute", "-A", GetoptLong::REQUIRED_ARGUMENT ]
).each do |opt,arg|
case opt
when "--attribute"
@@RequiredAttributes << arg
else
usage()
end
end
usage unless ARGV.length == 3
@@TargetName = ARGV[0]
@@Extensions = ARGV[1].split(",").map {|e| ".#{e}"} # We take 'h', but File.extname returns '.h'
@@ProjectFile = Pathname.new(ARGV[2]).realpath.to_s
fail "#{@@prog}: #{@@ProjectFile} is not a directory\n" unless File.directory?(@@ProjectFile)
fail "#{@@prog}: no project file in #{@@ProjectFile}\n" unless File.exists?("#{@@ProjectFile}/project.pbxproj")
@@Project = OSX::NSDictionary.dictionaryWithContentsOfFile("#{@@ProjectFile}/project.pbxproj")
@@Objects = @@Project['objects']
@@Root = @@Objects[@@Project['rootObject']]
fail "#{@@prog}: doesn't look like the pbproj I expect\n" unless @@Root['isa'] == 'PBXProject'
# Build map of object to containing group
@@ContainingGroup = {}
@@Objects.each {|k,v|
if ['PBXGroup', 'PBXVariantGroup'].index(v['isa'])
v['children'].each {|ch|
@@ContainingGroup[ch.to_s] = k;
}
end
}
@@ContainingGroup[@@Root['mainGroup'].to_s] = @@Project['rootObject']
# Build source tree map
@@SourceTrees = {'SOURCE_ROOT' => File.dirname(@@ProjectFile)}
def get(key, *allowedClasses)
obj = @@Objects[key]
fail "No object with id '#{key}'!" unless obj
if allowedClasses
actualClass = obj['isa']
fail "Object '#{key}' is a '#{actualClass}', but expected one of #{allowedClasses.join(", ")}." unless allowedClasses.index(actualClass)
end
obj
end
@@PathCache = {}
def resolvepath(key)
cached = @@PathCache[key]
return cached if cached
obj = get(key, 'PBXFileReference', 'PBXVariantGroup', 'PBXGroup', 'PBXProject', 'PBXReferenceProxy')
return @@SourceTrees['SOURCE_ROOT'] if obj['isa'] == 'PBXProject'
sourceTree = obj['sourceTree']
case sourceTree
when '<group>'
groupID = @@ContainingGroup[key.to_s]
fail "no group contains child ref #{key}, died" unless groupID
base = resolvepath(groupID)
when '<absolute>'
base = '/';
when 'BUILT_PRODUCTS_DIR'
base = ENV['BUILT_PRODUCTS_DIR']
fail "BUILT_PRODUCTS_DIR not specified in environment, but referenced by found file" unless base
else
base = @@SourceTrees[sourceTree.to_s]
fail "Unsupported source tree #{sourceTree}" unless base
end
path = obj['path']
if !path || path == ""
path = base
else
path = "#{base}/#{path}"
end
@@PathCache[key] = path
return path;
end
@@MatchingFiles = []
def do_target(target)
fail "Not a native target" unless target['isa'] == 'PBXNativeTarget'
cwd = Pathname.new(".").realpath
target['buildPhases'].each {|phaseID|
phase = get(phaseID, *%w[PBXCopyFilesBuildPhase PBXFrameworksBuildPhase PBXHeadersBuildPhase PBXResourcesBuildPhase PBXRezBuildPhase PBXShellScriptBuildPhase PBXSourcesBuildPhase])
phase['files'].each {|buildFileID|
buildFile = get(buildFileID, 'PBXBuildFile')
fileRefID = buildFile['fileRef']
#print "file " . $fileRef . "\n";
fileRef = get(fileRefID, 'PBXFileReference', 'PBXVariantGroup', 'PBXReferenceProxy', 'XCVersionGroup')
# Products from other included projects are instances of PBXReferenceProxy (like a .a file generated by a dependency on another project)
next unless %w[PBXFileReference PBXReferenceProxy XCVersionGroup].index(fileRef['isa'])
name = fileRef['name'] || fileRef['path']
ext = File.extname(name) # "foo.h" -> ".h"
next unless @@Extensions.index(ext)
next unless @@RequiredAttributes.all? {|attr|
fileSettings = buildFile['settings']
fileAttributes = (fileSettings && fileSettings['ATTRIBUTES']) || [];
fileAttributes.index(attr)
}
fullpath = resolvepath(fileRefID)
@@MatchingFiles << Pathname.new(fullpath).relative_path_from(cwd).cleanpath().to_s + "\n"
}
}
end
@@Root['targets'].each {|targetID|
target = get(targetID, 'PBXNativeTarget', 'PBXAggregateTarget')
if target['name'] == @@TargetName
do_target(target)
end
}
@@MatchingFiles.sort!
@@MatchingFiles.uniq!
@@MatchingFiles.each {|f| print f }