11#include " swift/xcode-autobuilder/XcodeProjectParser.h"
22#include " swift/xcode-autobuilder/XcodeWorkspaceParser.h"
3+ #include " swift/xcode-autobuilder/CFHelpers.h"
34
45#include < iostream>
56#include < filesystem>
@@ -16,31 +17,6 @@ struct TargetData {
1617 std::string type;
1718};
1819
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-
4420typedef std::unordered_map<std::string, CFDictionaryRef> Targets;
4521typedef std::unordered_map<std::string, std::vector<std::string>> Dependencies;
4622typedef std::unordered_map<std::string, std::vector<std::pair<std::string, CFDictionaryRef>>>
@@ -57,7 +33,7 @@ static size_t totalFilesCount(const std::string& target,
5733}
5834
5935static bool objectIsTarget (CFDictionaryRef object) {
60- auto isa = (CFStringRef) CFDictionaryGetValue (object, CFSTR (" isa" ));
36+ auto isa = cf_string_ref ( CFDictionaryGetValue (object, CFSTR (" isa" ) ));
6137 if (isa) {
6238 for (auto target :
6339 {CFSTR (" PBXAggregateTarget" ), CFSTR (" PBXNativeTarget" ), CFSTR (" PBXLegacyTarget" )}) {
@@ -77,66 +53,66 @@ static void mapTargetsToSourceFiles(CFDictionaryRef objects,
7753
7854 auto kv = CFKeyValues::fromDictionary (objects);
7955 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]) ;
8157 if (objectIsTarget (object)) {
82- auto name = stringValue (object, CFSTR (" name" ));
58+ auto name = stringValueForKey (object, CFSTR (" name" ));
8359 dependencies[name] = {};
8460 buildFiles[name] = {};
8561 targets.emplace (name, object);
8662 }
8763 }
8864
8965 for (auto & [targetName, targetObject] : targets) {
90- auto deps = (CFArrayRef) CFDictionaryGetValue (targetObject, CFSTR (" dependencies" ));
66+ auto deps = cf_array_ref ( CFDictionaryGetValue (targetObject, CFSTR (" dependencies" ) ));
9167 auto size = CFArrayGetCount (deps);
9268 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" ) ));
9672 if (!targetID) {
9773 // Skipping non-targets (e.g., productRef)
9874 continue ;
9975 }
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" ));
10278 if (!dependencyName.empty ()) {
10379 dependencies[targetName].push_back (dependencyName);
10480 }
10581 }
10682 }
10783
10884 for (auto & [targetName, targetObject] : targets) {
109- auto buildPhases = (CFArrayRef) CFDictionaryGetValue (targetObject, CFSTR (" buildPhases" ));
85+ auto buildPhases = cf_array_ref ( CFDictionaryGetValue (targetObject, CFSTR (" buildPhases" ) ));
11086 auto buildPhaseCount = CFArrayGetCount (buildPhases);
11187 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" ) ));
11591 if (!fileRefs) {
11692 continue ;
11793 }
11894 auto fileRefsCount = CFArrayGetCount (fileRefs);
11995 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" ) ));
12399 if (!fileID) {
124100 // FileRef is not a reference to a file (e.g., PBXBuildFile)
125101 continue ;
126102 }
127- auto file = (CFDictionaryRef) CFDictionaryGetValue (objects, fileID);
103+ auto file = cf_dictionary_ref ( CFDictionaryGetValue (objects, fileID) );
128104 if (!file) {
129105 // Sometimes the references file belongs to another project, which is not present for
130106 // various reasons
131107 continue ;
132108 }
133- auto isa = stringValue (file, CFSTR (" isa" ));
109+ auto isa = stringValueForKey (file, CFSTR (" isa" ));
134110 if (isa != " PBXFileReference" ) {
135111 // Skipping anything that is not a 'file', e.g. PBXVariantGroup
136112 continue ;
137113 }
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" ));
140116 if (fileType == " sourcecode.swift" && !path.empty ()) {
141117 buildFiles[targetName].emplace_back (path, file);
142118 }
@@ -161,15 +137,13 @@ static CFDictionaryRef xcodeProjectObjects(const std::string& xcodeProject) {
161137 CFErrorRef error = nullptr ;
162138 auto plist = CFPropertyListCreateWithData (allocator, data, 0 , nullptr , &error);
163139 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 " ;
169143 return CFDictionaryCreate (allocator, nullptr , nullptr , 0 , nullptr , nullptr );
170144 }
171145
172- return (CFDictionaryRef) CFDictionaryGetValue ((CFDictionaryRef)plist, CFSTR (" objects" ));
146+ return cf_dictionary_ref ( CFDictionaryGetValue ((CFDictionaryRef)plist, CFSTR (" objects" ) ));
173147}
174148
175149// 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
200174 for (size_t i = 0 ; i < kv.size ; i++) {
201175 auto object = (CFDictionaryRef)kv.values [i];
202176 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" ));
205179 targets.emplace_back (name, type.empty () ? " <unknown_target_type>" : type);
206180 }
207181 }
0 commit comments