1
1
#include " swift/xcode-autobuilder/XcodeProjectParser.h"
2
2
#include " swift/xcode-autobuilder/XcodeWorkspaceParser.h"
3
+ #include " swift/xcode-autobuilder/CFHelpers.h"
3
4
4
5
#include < iostream>
5
6
#include < filesystem>
@@ -16,31 +17,6 @@ struct TargetData {
16
17
std::string type;
17
18
};
18
19
19
- struct CFKeyValues {
20
- static CFKeyValues fromDictionary (CFDictionaryRef dict) {
21
- auto size = CFDictionaryGetCount (dict);
22
- CFKeyValues ret (size);
23
- CFDictionaryGetKeysAndValues (dict, ret.keys .data (), ret.values .data ());
24
- return ret;
25
- }
26
- explicit CFKeyValues (size_t size) : size(size), keys(size), values(size) {}
27
- size_t size;
28
- std::vector<const void *> keys;
29
- std::vector<const void *> values;
30
- };
31
-
32
- static std::string stringValue (CFDictionaryRef dict, CFStringRef key) {
33
- auto cfValue = (CFStringRef)CFDictionaryGetValue (dict, key);
34
- if (cfValue) {
35
- const int bufferSize = 256 ;
36
- char buf[bufferSize];
37
- if (CFStringGetCString (cfValue, buf, bufferSize, kCFStringEncodingUTF8 )) {
38
- return {buf};
39
- }
40
- }
41
- return {};
42
- }
43
-
44
20
typedef std::unordered_map<std::string, CFDictionaryRef> Targets;
45
21
typedef std::unordered_map<std::string, std::vector<std::string>> Dependencies;
46
22
typedef std::unordered_map<std::string, std::vector<std::pair<std::string, CFDictionaryRef>>>
@@ -57,7 +33,7 @@ static size_t totalFilesCount(const std::string& target,
57
33
}
58
34
59
35
static bool objectIsTarget (CFDictionaryRef object) {
60
- auto isa = (CFStringRef) CFDictionaryGetValue (object, CFSTR (" isa" ));
36
+ auto isa = cf_string_ref ( CFDictionaryGetValue (object, CFSTR (" isa" ) ));
61
37
if (isa) {
62
38
for (auto target :
63
39
{CFSTR (" PBXAggregateTarget" ), CFSTR (" PBXNativeTarget" ), CFSTR (" PBXLegacyTarget" )}) {
@@ -77,66 +53,66 @@ static void mapTargetsToSourceFiles(CFDictionaryRef objects,
77
53
78
54
auto kv = CFKeyValues::fromDictionary (objects);
79
55
for (size_t i = 0 ; i < kv.size ; i++) {
80
- auto object = (CFDictionaryRef) kv.values [i];
56
+ auto object = cf_dictionary_ref ( kv.values [i]) ;
81
57
if (objectIsTarget (object)) {
82
- auto name = stringValue (object, CFSTR (" name" ));
58
+ auto name = stringValueForKey (object, CFSTR (" name" ));
83
59
dependencies[name] = {};
84
60
buildFiles[name] = {};
85
61
targets.emplace (name, object);
86
62
}
87
63
}
88
64
89
65
for (auto & [targetName, targetObject] : targets) {
90
- auto deps = (CFArrayRef) CFDictionaryGetValue (targetObject, CFSTR (" dependencies" ));
66
+ auto deps = cf_array_ref ( CFDictionaryGetValue (targetObject, CFSTR (" dependencies" ) ));
91
67
auto size = CFArrayGetCount (deps);
92
68
for (CFIndex i = 0 ; i < size; i++) {
93
- auto dependencyID = (CFStringRef) CFArrayGetValueAtIndex (deps, i);
94
- auto dependency = (CFDictionaryRef) CFDictionaryGetValue (objects, dependencyID);
95
- auto targetID = (CFStringRef) CFDictionaryGetValue (dependency, CFSTR (" target" ));
69
+ auto dependencyID = cf_string_ref ( CFArrayGetValueAtIndex (deps, i) );
70
+ auto dependency = cf_dictionary_ref ( CFDictionaryGetValue (objects, dependencyID) );
71
+ auto targetID = cf_string_ref ( CFDictionaryGetValue (dependency, CFSTR (" target" ) ));
96
72
if (!targetID) {
97
73
// Skipping non-targets (e.g., productRef)
98
74
continue ;
99
75
}
100
- auto targetDependency = (CFDictionaryRef) CFDictionaryGetValue (objects, targetID);
101
- auto dependencyName = stringValue (targetDependency, CFSTR (" name" ));
76
+ auto targetDependency = cf_dictionary_ref ( CFDictionaryGetValue (objects, targetID) );
77
+ auto dependencyName = stringValueForKey (targetDependency, CFSTR (" name" ));
102
78
if (!dependencyName.empty ()) {
103
79
dependencies[targetName].push_back (dependencyName);
104
80
}
105
81
}
106
82
}
107
83
108
84
for (auto & [targetName, targetObject] : targets) {
109
- auto buildPhases = (CFArrayRef) CFDictionaryGetValue (targetObject, CFSTR (" buildPhases" ));
85
+ auto buildPhases = cf_array_ref ( CFDictionaryGetValue (targetObject, CFSTR (" buildPhases" ) ));
110
86
auto buildPhaseCount = CFArrayGetCount (buildPhases);
111
87
for (CFIndex buildPhaseIndex = 0 ; buildPhaseIndex < buildPhaseCount; buildPhaseIndex++) {
112
- auto buildPhaseID = (CFStringRef) CFArrayGetValueAtIndex (buildPhases, buildPhaseIndex);
113
- auto buildPhase = (CFDictionaryRef) CFDictionaryGetValue (objects, buildPhaseID);
114
- auto fileRefs = (CFArrayRef) CFDictionaryGetValue (buildPhase, CFSTR (" files" ));
88
+ auto buildPhaseID = cf_string_ref ( CFArrayGetValueAtIndex (buildPhases, buildPhaseIndex) );
89
+ auto buildPhase = cf_dictionary_ref ( CFDictionaryGetValue (objects, buildPhaseID) );
90
+ auto fileRefs = cf_array_ref ( CFDictionaryGetValue (buildPhase, CFSTR (" files" ) ));
115
91
if (!fileRefs) {
116
92
continue ;
117
93
}
118
94
auto fileRefsCount = CFArrayGetCount (fileRefs);
119
95
for (CFIndex fileRefIndex = 0 ; fileRefIndex < fileRefsCount; fileRefIndex++) {
120
- auto fileRefID = (CFStringRef) CFArrayGetValueAtIndex (fileRefs, fileRefIndex);
121
- auto fileRef = (CFDictionaryRef) CFDictionaryGetValue (objects, fileRefID);
122
- auto fileID = (CFStringRef) CFDictionaryGetValue (fileRef, CFSTR (" fileRef" ));
96
+ auto fileRefID = cf_string_ref ( CFArrayGetValueAtIndex (fileRefs, fileRefIndex) );
97
+ auto fileRef = cf_dictionary_ref ( CFDictionaryGetValue (objects, fileRefID) );
98
+ auto fileID = cf_string_ref ( CFDictionaryGetValue (fileRef, CFSTR (" fileRef" ) ));
123
99
if (!fileID) {
124
100
// FileRef is not a reference to a file (e.g., PBXBuildFile)
125
101
continue ;
126
102
}
127
- auto file = (CFDictionaryRef) CFDictionaryGetValue (objects, fileID);
103
+ auto file = cf_dictionary_ref ( CFDictionaryGetValue (objects, fileID) );
128
104
if (!file) {
129
105
// Sometimes the references file belongs to another project, which is not present for
130
106
// various reasons
131
107
continue ;
132
108
}
133
- auto isa = stringValue (file, CFSTR (" isa" ));
109
+ auto isa = stringValueForKey (file, CFSTR (" isa" ));
134
110
if (isa != " PBXFileReference" ) {
135
111
// Skipping anything that is not a 'file', e.g. PBXVariantGroup
136
112
continue ;
137
113
}
138
- auto fileType = stringValue (file, CFSTR (" lastKnownFileType" ));
139
- auto path = stringValue (file, CFSTR (" path" ));
114
+ auto fileType = stringValueForKey (file, CFSTR (" lastKnownFileType" ));
115
+ auto path = stringValueForKey (file, CFSTR (" path" ));
140
116
if (fileType == " sourcecode.swift" && !path.empty ()) {
141
117
buildFiles[targetName].emplace_back (path, file);
142
118
}
@@ -161,15 +137,13 @@ static CFDictionaryRef xcodeProjectObjects(const std::string& xcodeProject) {
161
137
CFErrorRef error = nullptr ;
162
138
auto plist = CFPropertyListCreateWithData (allocator, data, 0 , nullptr , &error);
163
139
if (error) {
164
- auto description = CFCopyDescription (error);
165
- std::cerr << " [xcode autobuilder] Cannot read Xcode project: "
166
- << CFStringGetCStringPtr (description, kCFStringEncodingUTF8 ) << " : " << pbxproj
167
- << " \n " ;
168
- CFRelease (description);
140
+ std::cerr << " [xcode autobuilder] Cannot read Xcode project: " ;
141
+ CFShow (error);
142
+ std::cerr << " : " << pbxproj << " \n " ;
169
143
return CFDictionaryCreate (allocator, nullptr , nullptr , 0 , nullptr , nullptr );
170
144
}
171
145
172
- return (CFDictionaryRef) CFDictionaryGetValue ((CFDictionaryRef)plist, CFSTR (" objects" ));
146
+ return cf_dictionary_ref ( CFDictionaryGetValue ((CFDictionaryRef)plist, CFSTR (" objects" ) ));
173
147
}
174
148
175
149
// Maps each target to the number of Swift source files it contains transitively
@@ -200,8 +174,8 @@ static std::vector<std::pair<std::string, std::string>> readTargets(const std::s
200
174
for (size_t i = 0 ; i < kv.size ; i++) {
201
175
auto object = (CFDictionaryRef)kv.values [i];
202
176
if (objectIsTarget (object)) {
203
- auto name = stringValue (object, CFSTR (" name" ));
204
- auto type = stringValue (object, CFSTR (" productType" ));
177
+ auto name = stringValueForKey (object, CFSTR (" name" ));
178
+ auto type = stringValueForKey (object, CFSTR (" productType" ));
205
179
targets.emplace_back (name, type.empty () ? " <unknown_target_type>" : type);
206
180
}
207
181
}
0 commit comments