cmXCodeObject.cxx 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmXCodeObject.h"
  11. #include "cmSystemTools.h"
  12. #include <CoreFoundation/CoreFoundation.h> // CFUUIDCreate
  13. const char* cmXCodeObject::PBXTypeNames[] = {
  14. /* clang-format needs this comment to break after the opening brace */
  15. "PBXGroup",
  16. "PBXBuildStyle",
  17. "PBXProject",
  18. "PBXHeadersBuildPhase",
  19. "PBXSourcesBuildPhase",
  20. "PBXFrameworksBuildPhase",
  21. "PBXNativeTarget",
  22. "PBXFileReference",
  23. "PBXBuildFile",
  24. "PBXContainerItemProxy",
  25. "PBXTargetDependency",
  26. "PBXShellScriptBuildPhase",
  27. "PBXResourcesBuildPhase",
  28. "PBXApplicationReference",
  29. "PBXExecutableFileReference",
  30. "PBXLibraryReference",
  31. "PBXToolTarget",
  32. "PBXLibraryTarget",
  33. "PBXAggregateTarget",
  34. "XCBuildConfiguration",
  35. "XCConfigurationList",
  36. "PBXCopyFilesBuildPhase",
  37. "None"
  38. };
  39. cmXCodeObject::~cmXCodeObject()
  40. {
  41. this->Version = 15;
  42. }
  43. cmXCodeObject::cmXCodeObject(PBXType ptype, Type type)
  44. {
  45. this->Version = 15;
  46. this->Target = 0;
  47. this->Object = 0;
  48. this->IsA = ptype;
  49. if (type == OBJECT) {
  50. // Set the Id of an Xcode object to a unique string for each instance.
  51. // However the Xcode user file references certain Ids: for those cases,
  52. // override the generated Id using SetId().
  53. //
  54. char cUuid[40] = { 0 };
  55. CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
  56. CFStringRef s = CFUUIDCreateString(kCFAllocatorDefault, uuid);
  57. CFStringGetCString(s, cUuid, sizeof(cUuid), kCFStringEncodingUTF8);
  58. this->Id = cUuid;
  59. CFRelease(s);
  60. CFRelease(uuid);
  61. } else {
  62. this->Id =
  63. "Temporary cmake object, should not be referred to in Xcode file";
  64. }
  65. cmSystemTools::ReplaceString(this->Id, "-", "");
  66. if (this->Id.size() > 24) {
  67. this->Id = this->Id.substr(0, 24);
  68. }
  69. this->TypeValue = type;
  70. if (this->TypeValue == OBJECT) {
  71. this->AddAttribute("isa", 0);
  72. }
  73. }
  74. bool cmXCodeObject::IsEmpty() const
  75. {
  76. switch (this->TypeValue) {
  77. case OBJECT_LIST:
  78. return this->List.empty();
  79. case STRING:
  80. return this->String.empty();
  81. case ATTRIBUTE_GROUP:
  82. return this->ObjectAttributes.empty();
  83. case OBJECT_REF:
  84. case OBJECT:
  85. return this->Object == 0;
  86. }
  87. return true; // unreachable, but quiets warnings
  88. }
  89. void cmXCodeObject::Indent(int level, std::ostream& out)
  90. {
  91. while (level) {
  92. out << "\t";
  93. level--;
  94. }
  95. }
  96. void cmXCodeObject::Print(std::ostream& out)
  97. {
  98. std::string separator = "\n";
  99. int indentFactor = 1;
  100. cmXCodeObject::Indent(2 * indentFactor, out);
  101. if (this->Version > 15 &&
  102. (this->IsA == PBXFileReference || this->IsA == PBXBuildFile)) {
  103. separator = " ";
  104. indentFactor = 0;
  105. }
  106. out << this->Id;
  107. this->PrintComment(out);
  108. out << " = {";
  109. if (separator == "\n") {
  110. out << separator;
  111. }
  112. std::map<std::string, cmXCodeObject*>::iterator i;
  113. cmXCodeObject::Indent(3 * indentFactor, out);
  114. out << "isa = " << PBXTypeNames[this->IsA] << ";" << separator;
  115. for (i = this->ObjectAttributes.begin(); i != this->ObjectAttributes.end();
  116. ++i) {
  117. if (i->first == "isa")
  118. continue;
  119. PrintAttribute(out, 3, separator, indentFactor, i->first, i->second, this);
  120. }
  121. cmXCodeObject::Indent(2 * indentFactor, out);
  122. out << "};\n";
  123. }
  124. void cmXCodeObject::PrintAttribute(std::ostream& out, const int level,
  125. const std::string separator,
  126. const int factor, const std::string& name,
  127. const cmXCodeObject* object,
  128. const cmXCodeObject* parent)
  129. {
  130. cmXCodeObject::Indent(level * factor, out);
  131. switch (object->TypeValue) {
  132. case OBJECT_LIST: {
  133. out << name << " = (";
  134. if (parent->TypeValue != ATTRIBUTE_GROUP) {
  135. out << separator;
  136. }
  137. for (unsigned int i = 0; i < object->List.size(); ++i) {
  138. if (object->List[i]->TypeValue == STRING) {
  139. object->List[i]->PrintString(out);
  140. if (i + 1 < object->List.size()) {
  141. out << ",";
  142. }
  143. } else {
  144. cmXCodeObject::Indent((level + 1) * factor, out);
  145. out << object->List[i]->Id;
  146. object->List[i]->PrintComment(out);
  147. out << "," << separator;
  148. }
  149. }
  150. if (parent->TypeValue != ATTRIBUTE_GROUP) {
  151. cmXCodeObject::Indent(level * factor, out);
  152. }
  153. out << ");" << separator;
  154. } break;
  155. case ATTRIBUTE_GROUP: {
  156. out << name << " = {";
  157. if (separator == "\n") {
  158. out << separator;
  159. }
  160. std::map<std::string, cmXCodeObject*>::const_iterator i;
  161. for (i = object->ObjectAttributes.begin();
  162. i != object->ObjectAttributes.end(); ++i) {
  163. PrintAttribute(out, (level + 1) * factor, separator, factor, i->first,
  164. i->second, object);
  165. }
  166. cmXCodeObject::Indent(level * factor, out);
  167. out << "};" << separator;
  168. } break;
  169. case OBJECT_REF: {
  170. cmXCodeObject::PrintString(out, name);
  171. out << " = " << object->Object->Id;
  172. if (object->Object->HasComment() && name != "remoteGlobalIDString") {
  173. object->Object->PrintComment(out);
  174. }
  175. out << ";" << separator;
  176. } break;
  177. case STRING: {
  178. cmXCodeObject::PrintString(out, name);
  179. out << " = ";
  180. object->PrintString(out);
  181. out << ";" << separator;
  182. } break;
  183. default: {
  184. break;
  185. }
  186. }
  187. }
  188. void cmXCodeObject::PrintList(std::vector<cmXCodeObject*> const& objs,
  189. std::ostream& out)
  190. {
  191. cmXCodeObject::Indent(1, out);
  192. out << "objects = {\n";
  193. for (unsigned int i = 0; i < objs.size(); ++i) {
  194. if (objs[i]->TypeValue == OBJECT) {
  195. objs[i]->Print(out);
  196. }
  197. }
  198. cmXCodeObject::Indent(1, out);
  199. out << "};\n";
  200. }
  201. void cmXCodeObject::CopyAttributes(cmXCodeObject* copy)
  202. {
  203. this->ObjectAttributes = copy->ObjectAttributes;
  204. this->List = copy->List;
  205. this->String = copy->String;
  206. this->Object = copy->Object;
  207. }
  208. void cmXCodeObject::PrintString(std::ostream& os, std::string String)
  209. {
  210. // The string needs to be quoted if it contains any characters
  211. // considered special by the Xcode project file parser.
  212. bool needQuote = (String.empty() || String.find("//") != String.npos ||
  213. String.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  214. "abcdefghijklmnopqrstuvwxyz"
  215. "0123456789"
  216. "$_./") != String.npos);
  217. const char* quote = needQuote ? "\"" : "";
  218. // Print the string, quoted and escaped as necessary.
  219. os << quote;
  220. for (std::string::const_iterator i = String.begin(); i != String.end();
  221. ++i) {
  222. if (*i == '"' || *i == '\\') {
  223. // Escape double-quotes and backslashes.
  224. os << '\\';
  225. }
  226. os << *i;
  227. }
  228. os << quote;
  229. }
  230. void cmXCodeObject::PrintString(std::ostream& os) const
  231. {
  232. cmXCodeObject::PrintString(os, this->String);
  233. }
  234. void cmXCodeObject::SetString(const std::string& s)
  235. {
  236. this->String = s;
  237. }