lounge_lizard 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (348) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +2 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +4 -0
  7. data/Guardfile +33 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +50 -0
  10. data/Rakefile +43 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/circle.yml +14 -0
  14. data/ext/drafter/CHANGELOG.md +278 -0
  15. data/ext/drafter/Dockerfile +17 -0
  16. data/ext/drafter/Makefile +62 -0
  17. data/ext/drafter/appveyor.yml +17 -0
  18. data/ext/drafter/bin/drafter +0 -0
  19. data/ext/drafter/build/Makefile +387 -0
  20. data/ext/drafter/build/drafter.Makefile +6 -0
  21. data/ext/drafter/build/drafter.target.mk +159 -0
  22. data/ext/drafter/build/ext/snowcrash/libmarkdownparser.target.mk +141 -0
  23. data/ext/drafter/build/ext/snowcrash/libsnowcrash.target.mk +154 -0
  24. data/ext/drafter/build/ext/snowcrash/libsundown.target.mk +149 -0
  25. data/ext/drafter/build/ext/snowcrash/perf-libsnowcrash.target.mk +147 -0
  26. data/ext/drafter/build/ext/snowcrash/snowcrash.Makefile +6 -0
  27. data/ext/drafter/build/gyp-mac-tool +606 -0
  28. data/ext/drafter/build/libdrafter.target.mk +186 -0
  29. data/ext/drafter/build/libsos.target.mk +137 -0
  30. data/ext/drafter/build/out/Release/drafter +0 -0
  31. data/ext/drafter/build/out/Release/libdrafter.dylib +0 -0
  32. data/ext/drafter/build/out/Release/libmarkdownparser.a +0 -0
  33. data/ext/drafter/build/out/Release/libsnowcrash.a +0 -0
  34. data/ext/drafter/build/out/Release/libsos.a +0 -0
  35. data/ext/drafter/build/out/Release/libsundown.a +0 -0
  36. data/ext/drafter/build/out/Release/obj.target/drafter/src/config.o +0 -0
  37. data/ext/drafter/build/out/Release/obj.target/drafter/src/main.o +0 -0
  38. data/ext/drafter/build/out/Release/obj.target/drafter/src/reporting.o +0 -0
  39. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/ConversionContext.o +0 -0
  40. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/NamedTypesRegistry.o +0 -0
  41. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/RefractAPI.o +0 -0
  42. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/RefractDataStructure.o +0 -0
  43. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/RefractElementFactory.o +0 -0
  44. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/RefractSourceMap.o +0 -0
  45. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/Render.o +0 -0
  46. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/Serialize.o +0 -0
  47. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/SerializeAST.o +0 -0
  48. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/SerializeResult.o +0 -0
  49. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/SerializeSourcemap.o +0 -0
  50. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/drafter.o +0 -0
  51. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/drafter_private.o +0 -0
  52. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/ComparableVisitor.o +0 -0
  53. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/Element.o +0 -0
  54. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/ExpandVisitor.o +0 -0
  55. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/IsExpandableVisitor.o +0 -0
  56. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/JSONSchemaVisitor.o +0 -0
  57. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/PrintVisitor.o +0 -0
  58. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/Query.o +0 -0
  59. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/Registry.o +0 -0
  60. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/RenderJSONVisitor.o +0 -0
  61. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/SerializeCompactVisitor.o +0 -0
  62. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/SerializeVisitor.o +0 -0
  63. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/TypeQueryVisitor.o +0 -0
  64. data/ext/drafter/build/out/Release/obj.target/libdrafter/src/refract/VisitorUtils.o +0 -0
  65. data/ext/drafter/build/out/Release/obj.target/libmarkdownparser/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.o +0 -0
  66. data/ext/drafter/build/out/Release/obj.target/libmarkdownparser/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.o +0 -0
  67. data/ext/drafter/build/out/Release/obj.target/libmarkdownparser/ext/snowcrash/ext/markdown-parser/src/MarkdownParser.o +0 -0
  68. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/Blueprint.o +0 -0
  69. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/BlueprintSourcemap.o +0 -0
  70. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/HTTP.o +0 -0
  71. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/HeadersParser.o +0 -0
  72. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSON.o +0 -0
  73. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSONOneOfParser.o +0 -0
  74. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSONSourcemap.o +0 -0
  75. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSONTypeSectionParser.o +0 -0
  76. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/MSONValueMemberParser.o +0 -0
  77. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/Section.o +0 -0
  78. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/Signature.o +0 -0
  79. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/UriTemplateParser.o +0 -0
  80. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/posix/RegexMatch.o +0 -0
  81. data/ext/drafter/build/out/Release/obj.target/libsnowcrash/ext/snowcrash/src/snowcrash.o +0 -0
  82. data/ext/drafter/build/out/Release/obj.target/libsos/ext/sos/src/sos.o +0 -0
  83. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/html/houdini_href_e.o +0 -0
  84. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/html/houdini_html_e.o +0 -0
  85. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/html/html.o +0 -0
  86. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/html/html_smartypants.o +0 -0
  87. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/autolink.o +0 -0
  88. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/buffer.o +0 -0
  89. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/markdown.o +0 -0
  90. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/src_map.o +0 -0
  91. data/ext/drafter/build/out/Release/obj.target/libsundown/ext/snowcrash/ext/markdown-parser/ext/sundown/src/stack.o +0 -0
  92. data/ext/drafter/circle.yml +32 -0
  93. data/ext/drafter/config.gypi +10 -0
  94. data/ext/drafter/config.mk +5 -0
  95. data/ext/drafter/configure +224 -0
  96. data/ext/drafter/drafter.gyp +189 -0
  97. data/ext/drafter/drafter.xcworkspace/contents.xcworkspacedata +13 -0
  98. data/ext/drafter/ext/snowcrash/Makefile +58 -0
  99. data/ext/drafter/ext/snowcrash/appveyor.yml +7 -0
  100. data/ext/drafter/ext/snowcrash/common.gypi +165 -0
  101. data/ext/drafter/ext/snowcrash/configure +197 -0
  102. data/ext/drafter/ext/snowcrash/ext/markdown-parser/Makefile +90 -0
  103. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/CONTRIBUTING.md +10 -0
  104. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/Makefile +84 -0
  105. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/Makefile.win +33 -0
  106. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/examples/smartypants.c +72 -0
  107. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/examples/sundown.c +80 -0
  108. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/html/houdini.h +37 -0
  109. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/html/houdini_href_e.c +108 -0
  110. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/html/houdini_html_e.c +84 -0
  111. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/html/html.c +647 -0
  112. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/html/html.h +77 -0
  113. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/html/html_smartypants.c +389 -0
  114. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/html_block_names.txt +25 -0
  115. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/autolink.c +297 -0
  116. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/autolink.h +51 -0
  117. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/buffer.c +225 -0
  118. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/buffer.h +96 -0
  119. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/html_blocks.h +206 -0
  120. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/markdown.c +2726 -0
  121. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/markdown.h +147 -0
  122. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/src_map.c +204 -0
  123. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/src_map.h +58 -0
  124. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/stack.c +81 -0
  125. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/src/stack.h +29 -0
  126. data/ext/drafter/ext/snowcrash/ext/markdown-parser/ext/sundown/sundown.def +20 -0
  127. data/ext/drafter/ext/snowcrash/ext/markdown-parser/msvc/markdown/markdown.vcproj +188 -0
  128. data/ext/drafter/ext/snowcrash/ext/markdown-parser/msvc/msvc.sln +38 -0
  129. data/ext/drafter/ext/snowcrash/ext/markdown-parser/msvc/sundown/sundown.vcproj +206 -0
  130. data/ext/drafter/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.cc +160 -0
  131. data/ext/drafter/ext/snowcrash/ext/markdown-parser/src/ByteBuffer.h +90 -0
  132. data/ext/drafter/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.cc +152 -0
  133. data/ext/drafter/ext/snowcrash/ext/markdown-parser/src/MarkdownNode.h +103 -0
  134. data/ext/drafter/ext/snowcrash/ext/markdown-parser/src/MarkdownParser.cc +388 -0
  135. data/ext/drafter/ext/snowcrash/ext/markdown-parser/src/MarkdownParser.h +106 -0
  136. data/ext/drafter/ext/snowcrash/snowcrash.gyp +196 -0
  137. data/ext/drafter/ext/snowcrash/src/ActionParser.h +560 -0
  138. data/ext/drafter/ext/snowcrash/src/AssetParser.h +123 -0
  139. data/ext/drafter/ext/snowcrash/src/AttributesParser.h +123 -0
  140. data/ext/drafter/ext/snowcrash/src/Blueprint.cc +90 -0
  141. data/ext/drafter/ext/snowcrash/src/Blueprint.h +489 -0
  142. data/ext/drafter/ext/snowcrash/src/BlueprintParser.h +845 -0
  143. data/ext/drafter/ext/snowcrash/src/BlueprintSourcemap.cc +81 -0
  144. data/ext/drafter/ext/snowcrash/src/BlueprintSourcemap.h +345 -0
  145. data/ext/drafter/ext/snowcrash/src/BlueprintUtility.h +111 -0
  146. data/ext/drafter/ext/snowcrash/src/CodeBlockUtility.h +276 -0
  147. data/ext/drafter/ext/snowcrash/src/DataStructureGroupParser.h +157 -0
  148. data/ext/drafter/ext/snowcrash/src/HTTP.cc +49 -0
  149. data/ext/drafter/ext/snowcrash/src/HTTP.h +108 -0
  150. data/ext/drafter/ext/snowcrash/src/HeadersParser.cc +117 -0
  151. data/ext/drafter/ext/snowcrash/src/HeadersParser.h +377 -0
  152. data/ext/drafter/ext/snowcrash/src/MSON.cc +272 -0
  153. data/ext/drafter/ext/snowcrash/src/MSON.h +405 -0
  154. data/ext/drafter/ext/snowcrash/src/MSONMixinParser.h +103 -0
  155. data/ext/drafter/ext/snowcrash/src/MSONNamedTypeParser.h +135 -0
  156. data/ext/drafter/ext/snowcrash/src/MSONOneOfParser.cc +132 -0
  157. data/ext/drafter/ext/snowcrash/src/MSONOneOfParser.h +80 -0
  158. data/ext/drafter/ext/snowcrash/src/MSONParameterParser.h +166 -0
  159. data/ext/drafter/ext/snowcrash/src/MSONPropertyMemberParser.h +106 -0
  160. data/ext/drafter/ext/snowcrash/src/MSONSourcemap.cc +141 -0
  161. data/ext/drafter/ext/snowcrash/src/MSONSourcemap.h +181 -0
  162. data/ext/drafter/ext/snowcrash/src/MSONTypeSectionParser.cc +209 -0
  163. data/ext/drafter/ext/snowcrash/src/MSONTypeSectionParser.h +213 -0
  164. data/ext/drafter/ext/snowcrash/src/MSONUtility.h +506 -0
  165. data/ext/drafter/ext/snowcrash/src/MSONValueMemberParser.cc +214 -0
  166. data/ext/drafter/ext/snowcrash/src/MSONValueMemberParser.h +390 -0
  167. data/ext/drafter/ext/snowcrash/src/ModelTable.h +87 -0
  168. data/ext/drafter/ext/snowcrash/src/ParameterParser.h +516 -0
  169. data/ext/drafter/ext/snowcrash/src/ParametersParser.h +222 -0
  170. data/ext/drafter/ext/snowcrash/src/PayloadParser.h +733 -0
  171. data/ext/drafter/ext/snowcrash/src/Platform.h +33 -0
  172. data/ext/drafter/ext/snowcrash/src/RegexMatch.h +32 -0
  173. data/ext/drafter/ext/snowcrash/src/RelationParser.h +87 -0
  174. data/ext/drafter/ext/snowcrash/src/ResourceGroupParser.h +297 -0
  175. data/ext/drafter/ext/snowcrash/src/ResourceParser.h +536 -0
  176. data/ext/drafter/ext/snowcrash/src/Section.cc +48 -0
  177. data/ext/drafter/ext/snowcrash/src/Section.h +60 -0
  178. data/ext/drafter/ext/snowcrash/src/SectionParser.h +246 -0
  179. data/ext/drafter/ext/snowcrash/src/SectionParserData.h +109 -0
  180. data/ext/drafter/ext/snowcrash/src/SectionProcessor.h +299 -0
  181. data/ext/drafter/ext/snowcrash/src/Signature.cc +75 -0
  182. data/ext/drafter/ext/snowcrash/src/Signature.h +103 -0
  183. data/ext/drafter/ext/snowcrash/src/SignatureSectionProcessor.h +442 -0
  184. data/ext/drafter/ext/snowcrash/src/SourceAnnotation.h +166 -0
  185. data/ext/drafter/ext/snowcrash/src/StringUtility.h +323 -0
  186. data/ext/drafter/ext/snowcrash/src/UriTemplateParser.cc +195 -0
  187. data/ext/drafter/ext/snowcrash/src/UriTemplateParser.h +240 -0
  188. data/ext/drafter/ext/snowcrash/src/ValuesParser.h +111 -0
  189. data/ext/drafter/ext/snowcrash/src/posix/RegexMatch.cc +99 -0
  190. data/ext/drafter/ext/snowcrash/src/snowcrash.cc +90 -0
  191. data/ext/drafter/ext/snowcrash/src/snowcrash.h +44 -0
  192. data/ext/drafter/ext/snowcrash/src/win/RegexMatch.cc +78 -0
  193. data/ext/drafter/ext/snowcrash/tools/gyp/AUTHORS +12 -0
  194. data/ext/drafter/ext/snowcrash/tools/gyp/DEPS +23 -0
  195. data/ext/drafter/ext/snowcrash/tools/gyp/OWNERS +1 -0
  196. data/ext/drafter/ext/snowcrash/tools/gyp/PRESUBMIT.py +137 -0
  197. data/ext/drafter/ext/snowcrash/tools/gyp/buildbot/buildbot_run.py +136 -0
  198. data/ext/drafter/ext/snowcrash/tools/gyp/buildbot/commit_queue/OWNERS +6 -0
  199. data/ext/drafter/ext/snowcrash/tools/gyp/buildbot/commit_queue/cq_config.json +15 -0
  200. data/ext/drafter/ext/snowcrash/tools/gyp/codereview.settings +10 -0
  201. data/ext/drafter/ext/snowcrash/tools/gyp/data/win/large-pdb-shim.cc +12 -0
  202. data/ext/drafter/ext/snowcrash/tools/gyp/gyp +8 -0
  203. data/ext/drafter/ext/snowcrash/tools/gyp/gyp.bat +5 -0
  204. data/ext/drafter/ext/snowcrash/tools/gyp/gyp_main.py +16 -0
  205. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSNew.py +340 -0
  206. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSProject.py +208 -0
  207. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSSettings.py +1096 -0
  208. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSToolFile.py +58 -0
  209. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUserFile.py +147 -0
  210. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUtil.py +270 -0
  211. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSUtil.pyc +0 -0
  212. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSVersion.py +445 -0
  213. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/MSVSVersion.pyc +0 -0
  214. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/__init__.py +548 -0
  215. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/__init__.pyc +0 -0
  216. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/common.py +608 -0
  217. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/common.pyc +0 -0
  218. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/easy_xml.py +157 -0
  219. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/flock_tool.py +54 -0
  220. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.py +0 -0
  221. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/__init__.pyc +0 -0
  222. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/analyzer.py +741 -0
  223. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/android.py +1069 -0
  224. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/cmake.py +1248 -0
  225. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/dump_dependency_json.py +99 -0
  226. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/eclipse.py +425 -0
  227. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypd.py +94 -0
  228. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/gypsh.py +56 -0
  229. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.py +2218 -0
  230. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/make.pyc +0 -0
  231. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/msvs.py +3467 -0
  232. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/ninja.py +2427 -0
  233. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/ninja.pyc +0 -0
  234. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.py +1300 -0
  235. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/generator/xcode.pyc +0 -0
  236. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/input.py +2899 -0
  237. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/input.pyc +0 -0
  238. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/mac_tool.py +605 -0
  239. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/msvs_emulation.py +1093 -0
  240. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/msvs_emulation.pyc +0 -0
  241. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/ninja_syntax.py +160 -0
  242. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/ninja_syntax.pyc +0 -0
  243. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/ordered_dict.py +289 -0
  244. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/simple_copy.py +46 -0
  245. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/simple_copy.pyc +0 -0
  246. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/win_tool.py +314 -0
  247. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.py +1664 -0
  248. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xcode_emulation.pyc +0 -0
  249. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xcode_ninja.py +276 -0
  250. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xcode_ninja.pyc +0 -0
  251. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.py +2927 -0
  252. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xcodeproj_file.pyc +0 -0
  253. data/ext/drafter/ext/snowcrash/tools/gyp/pylib/gyp/xml_fix.py +69 -0
  254. data/ext/drafter/ext/snowcrash/tools/gyp/pylintrc +307 -0
  255. data/ext/drafter/ext/snowcrash/tools/gyp/samples/samples +81 -0
  256. data/ext/drafter/ext/snowcrash/tools/gyp/samples/samples.bat +5 -0
  257. data/ext/drafter/ext/snowcrash/tools/gyp/setup.py +19 -0
  258. data/ext/drafter/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.pbfilespec +27 -0
  259. data/ext/drafter/ext/snowcrash/tools/gyp/tools/Xcode/Specifications/gyp.xclangspec +226 -0
  260. data/ext/drafter/ext/snowcrash/tools/gyp/tools/emacs/gyp.el +275 -0
  261. data/ext/drafter/ext/snowcrash/tools/gyp/tools/graphviz.py +100 -0
  262. data/ext/drafter/ext/snowcrash/tools/gyp/tools/pretty_gyp.py +155 -0
  263. data/ext/drafter/ext/snowcrash/tools/gyp/tools/pretty_sln.py +169 -0
  264. data/ext/drafter/ext/snowcrash/tools/gyp/tools/pretty_vcproj.py +329 -0
  265. data/ext/drafter/ext/snowcrash/vcbuild.bat +139 -0
  266. data/ext/drafter/ext/sos/Makefile +62 -0
  267. data/ext/drafter/ext/sos/src/sos.cc +235 -0
  268. data/ext/drafter/ext/sos/src/sos.h +188 -0
  269. data/ext/drafter/ext/sos/src/sosJSON.h +121 -0
  270. data/ext/drafter/ext/sos/src/sosYAML.h +105 -0
  271. data/ext/drafter/src/ConversionContext.cc +39 -0
  272. data/ext/drafter/src/ConversionContext.h +34 -0
  273. data/ext/drafter/src/NamedTypesRegistry.cc +405 -0
  274. data/ext/drafter/src/NamedTypesRegistry.h +28 -0
  275. data/ext/drafter/src/NodeInfo.h +143 -0
  276. data/ext/drafter/src/RefractAPI.cc +579 -0
  277. data/ext/drafter/src/RefractAPI.h +28 -0
  278. data/ext/drafter/src/RefractDataStructure.cc +1199 -0
  279. data/ext/drafter/src/RefractDataStructure.h +26 -0
  280. data/ext/drafter/src/RefractElementFactory.cc +107 -0
  281. data/ext/drafter/src/RefractElementFactory.h +67 -0
  282. data/ext/drafter/src/RefractSourceMap.cc +29 -0
  283. data/ext/drafter/src/RefractSourceMap.h +57 -0
  284. data/ext/drafter/src/Render.cc +157 -0
  285. data/ext/drafter/src/Render.h +40 -0
  286. data/ext/drafter/src/Serialize.cc +160 -0
  287. data/ext/drafter/src/Serialize.h +289 -0
  288. data/ext/drafter/src/SerializeAST.cc +507 -0
  289. data/ext/drafter/src/SerializeAST.h +29 -0
  290. data/ext/drafter/src/SerializeResult.cc +170 -0
  291. data/ext/drafter/src/SerializeResult.h +34 -0
  292. data/ext/drafter/src/SerializeSourcemap.cc +331 -0
  293. data/ext/drafter/src/SerializeSourcemap.h +21 -0
  294. data/ext/drafter/src/Version.h +40 -0
  295. data/ext/drafter/src/config.cc +91 -0
  296. data/ext/drafter/src/config.h +38 -0
  297. data/ext/drafter/src/drafter.cc +137 -0
  298. data/ext/drafter/src/drafter.h +102 -0
  299. data/ext/drafter/src/drafter_private.cc +85 -0
  300. data/ext/drafter/src/drafter_private.h +34 -0
  301. data/ext/drafter/src/main.cc +137 -0
  302. data/ext/drafter/src/refract/AppendDecorator.h +58 -0
  303. data/ext/drafter/src/refract/Build.h +67 -0
  304. data/ext/drafter/src/refract/ComparableVisitor.cc +43 -0
  305. data/ext/drafter/src/refract/ComparableVisitor.h +62 -0
  306. data/ext/drafter/src/refract/Element.cc +409 -0
  307. data/ext/drafter/src/refract/Element.h +656 -0
  308. data/ext/drafter/src/refract/ElementFwd.h +37 -0
  309. data/ext/drafter/src/refract/ElementInserter.h +59 -0
  310. data/ext/drafter/src/refract/Exception.h +31 -0
  311. data/ext/drafter/src/refract/ExpandVisitor.cc +359 -0
  312. data/ext/drafter/src/refract/ExpandVisitor.h +58 -0
  313. data/ext/drafter/src/refract/FilterVisitor.h +52 -0
  314. data/ext/drafter/src/refract/IsExpandableVisitor.cc +140 -0
  315. data/ext/drafter/src/refract/IsExpandableVisitor.h +31 -0
  316. data/ext/drafter/src/refract/Iterate.h +160 -0
  317. data/ext/drafter/src/refract/JSONSchemaVisitor.cc +675 -0
  318. data/ext/drafter/src/refract/JSONSchemaVisitor.h +73 -0
  319. data/ext/drafter/src/refract/PrintVisitor.cc +164 -0
  320. data/ext/drafter/src/refract/PrintVisitor.h +50 -0
  321. data/ext/drafter/src/refract/Query.cc +13 -0
  322. data/ext/drafter/src/refract/Query.h +38 -0
  323. data/ext/drafter/src/refract/Registry.cc +114 -0
  324. data/ext/drafter/src/refract/Registry.h +43 -0
  325. data/ext/drafter/src/refract/RenderJSONVisitor.cc +255 -0
  326. data/ext/drafter/src/refract/RenderJSONVisitor.h +51 -0
  327. data/ext/drafter/src/refract/SerializeCompactVisitor.cc +167 -0
  328. data/ext/drafter/src/refract/SerializeCompactVisitor.h +56 -0
  329. data/ext/drafter/src/refract/SerializeVisitor.cc +214 -0
  330. data/ext/drafter/src/refract/SerializeVisitor.h +55 -0
  331. data/ext/drafter/src/refract/TypeQueryVisitor.cc +46 -0
  332. data/ext/drafter/src/refract/TypeQueryVisitor.h +110 -0
  333. data/ext/drafter/src/refract/Visitor.h +126 -0
  334. data/ext/drafter/src/refract/VisitorUtils.cc +63 -0
  335. data/ext/drafter/src/refract/VisitorUtils.h +231 -0
  336. data/ext/drafter/src/reporting.cc +263 -0
  337. data/ext/drafter/src/reporting.h +39 -0
  338. data/ext/drafter/src/stream.h +148 -0
  339. data/ext/drafter/tools/homebrew/drafter.rb +18 -0
  340. data/ext/drafter/tools/make-tarball.sh +39 -0
  341. data/ext/drafter/tools/refract-filter.py +96 -0
  342. data/ext/drafter/tools/release.sh +17 -0
  343. data/ext/drafter/vcbuild.bat +203 -0
  344. data/lib/lounge_lizard/binding.rb +29 -0
  345. data/lib/lounge_lizard/version.rb +3 -0
  346. data/lib/lounge_lizard.rb +18 -0
  347. data/lounge_lizard.gemspec +37 -0
  348. metadata +547 -0
@@ -0,0 +1,2427 @@
1
+ # Copyright (c) 2013 Google Inc. All rights reserved.
2
+ # Use of this source code is governed by a BSD-style license that can be
3
+ # found in the LICENSE file.
4
+
5
+ import collections
6
+ import copy
7
+ import hashlib
8
+ import json
9
+ import multiprocessing
10
+ import os.path
11
+ import re
12
+ import signal
13
+ import subprocess
14
+ import sys
15
+ import gyp
16
+ import gyp.common
17
+ from gyp.common import OrderedSet
18
+ import gyp.msvs_emulation
19
+ import gyp.MSVSUtil as MSVSUtil
20
+ import gyp.xcode_emulation
21
+ from cStringIO import StringIO
22
+
23
+ from gyp.common import GetEnvironFallback
24
+ import gyp.ninja_syntax as ninja_syntax
25
+
26
+ generator_default_variables = {
27
+ 'EXECUTABLE_PREFIX': '',
28
+ 'EXECUTABLE_SUFFIX': '',
29
+ 'STATIC_LIB_PREFIX': 'lib',
30
+ 'STATIC_LIB_SUFFIX': '.a',
31
+ 'SHARED_LIB_PREFIX': 'lib',
32
+
33
+ # Gyp expects the following variables to be expandable by the build
34
+ # system to the appropriate locations. Ninja prefers paths to be
35
+ # known at gyp time. To resolve this, introduce special
36
+ # variables starting with $! and $| (which begin with a $ so gyp knows it
37
+ # should be treated specially, but is otherwise an invalid
38
+ # ninja/shell variable) that are passed to gyp here but expanded
39
+ # before writing out into the target .ninja files; see
40
+ # ExpandSpecial.
41
+ # $! is used for variables that represent a path and that can only appear at
42
+ # the start of a string, while $| is used for variables that can appear
43
+ # anywhere in a string.
44
+ 'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR',
45
+ 'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen',
46
+ 'PRODUCT_DIR': '$!PRODUCT_DIR',
47
+ 'CONFIGURATION_NAME': '$|CONFIGURATION_NAME',
48
+
49
+ # Special variables that may be used by gyp 'rule' targets.
50
+ # We generate definitions for these variables on the fly when processing a
51
+ # rule.
52
+ 'RULE_INPUT_ROOT': '${root}',
53
+ 'RULE_INPUT_DIRNAME': '${dirname}',
54
+ 'RULE_INPUT_PATH': '${source}',
55
+ 'RULE_INPUT_EXT': '${ext}',
56
+ 'RULE_INPUT_NAME': '${name}',
57
+ }
58
+
59
+ # Placates pylint.
60
+ generator_additional_non_configuration_keys = []
61
+ generator_additional_path_sections = []
62
+ generator_extra_sources_for_rules = []
63
+ generator_filelist_paths = None
64
+
65
+ generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested()
66
+
67
+ def StripPrefix(arg, prefix):
68
+ if arg.startswith(prefix):
69
+ return arg[len(prefix):]
70
+ return arg
71
+
72
+
73
+ def QuoteShellArgument(arg, flavor):
74
+ """Quote a string such that it will be interpreted as a single argument
75
+ by the shell."""
76
+ # Rather than attempting to enumerate the bad shell characters, just
77
+ # whitelist common OK ones and quote anything else.
78
+ if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg):
79
+ return arg # No quoting necessary.
80
+ if flavor == 'win':
81
+ return gyp.msvs_emulation.QuoteForRspFile(arg)
82
+ return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'"
83
+
84
+
85
+ def Define(d, flavor):
86
+ """Takes a preprocessor define and returns a -D parameter that's ninja- and
87
+ shell-escaped."""
88
+ if flavor == 'win':
89
+ # cl.exe replaces literal # characters with = in preprocesor definitions for
90
+ # some reason. Octal-encode to work around that.
91
+ d = d.replace('#', '\\%03o' % ord('#'))
92
+ return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor)
93
+
94
+
95
+ def AddArch(output, arch):
96
+ """Adds an arch string to an output path."""
97
+ output, extension = os.path.splitext(output)
98
+ return '%s.%s%s' % (output, arch, extension)
99
+
100
+
101
+ class Target(object):
102
+ """Target represents the paths used within a single gyp target.
103
+
104
+ Conceptually, building a single target A is a series of steps:
105
+
106
+ 1) actions/rules/copies generates source/resources/etc.
107
+ 2) compiles generates .o files
108
+ 3) link generates a binary (library/executable)
109
+ 4) bundle merges the above in a mac bundle
110
+
111
+ (Any of these steps can be optional.)
112
+
113
+ From a build ordering perspective, a dependent target B could just
114
+ depend on the last output of this series of steps.
115
+
116
+ But some dependent commands sometimes need to reach inside the box.
117
+ For example, when linking B it needs to get the path to the static
118
+ library generated by A.
119
+
120
+ This object stores those paths. To keep things simple, member
121
+ variables only store concrete paths to single files, while methods
122
+ compute derived values like "the last output of the target".
123
+ """
124
+ def __init__(self, type):
125
+ # Gyp type ("static_library", etc.) of this target.
126
+ self.type = type
127
+ # File representing whether any input dependencies necessary for
128
+ # dependent actions have completed.
129
+ self.preaction_stamp = None
130
+ # File representing whether any input dependencies necessary for
131
+ # dependent compiles have completed.
132
+ self.precompile_stamp = None
133
+ # File representing the completion of actions/rules/copies, if any.
134
+ self.actions_stamp = None
135
+ # Path to the output of the link step, if any.
136
+ self.binary = None
137
+ # Path to the file representing the completion of building the bundle,
138
+ # if any.
139
+ self.bundle = None
140
+ # On Windows, incremental linking requires linking against all the .objs
141
+ # that compose a .lib (rather than the .lib itself). That list is stored
142
+ # here. In this case, we also need to save the compile_deps for the target,
143
+ # so that the the target that directly depends on the .objs can also depend
144
+ # on those.
145
+ self.component_objs = None
146
+ self.compile_deps = None
147
+ # Windows only. The import .lib is the output of a build step, but
148
+ # because dependents only link against the lib (not both the lib and the
149
+ # dll) we keep track of the import library here.
150
+ self.import_lib = None
151
+
152
+ def Linkable(self):
153
+ """Return true if this is a target that can be linked against."""
154
+ return self.type in ('static_library', 'shared_library')
155
+
156
+ def UsesToc(self, flavor):
157
+ """Return true if the target should produce a restat rule based on a TOC
158
+ file."""
159
+ # For bundles, the .TOC should be produced for the binary, not for
160
+ # FinalOutput(). But the naive approach would put the TOC file into the
161
+ # bundle, so don't do this for bundles for now.
162
+ if flavor == 'win' or self.bundle:
163
+ return False
164
+ return self.type in ('shared_library', 'loadable_module')
165
+
166
+ def PreActionInput(self, flavor):
167
+ """Return the path, if any, that should be used as a dependency of
168
+ any dependent action step."""
169
+ if self.UsesToc(flavor):
170
+ return self.FinalOutput() + '.TOC'
171
+ return self.FinalOutput() or self.preaction_stamp
172
+
173
+ def PreCompileInput(self):
174
+ """Return the path, if any, that should be used as a dependency of
175
+ any dependent compile step."""
176
+ return self.actions_stamp or self.precompile_stamp
177
+
178
+ def FinalOutput(self):
179
+ """Return the last output of the target, which depends on all prior
180
+ steps."""
181
+ return self.bundle or self.binary or self.actions_stamp
182
+
183
+
184
+ # A small discourse on paths as used within the Ninja build:
185
+ # All files we produce (both at gyp and at build time) appear in the
186
+ # build directory (e.g. out/Debug).
187
+ #
188
+ # Paths within a given .gyp file are always relative to the directory
189
+ # containing the .gyp file. Call these "gyp paths". This includes
190
+ # sources as well as the starting directory a given gyp rule/action
191
+ # expects to be run from. We call the path from the source root to
192
+ # the gyp file the "base directory" within the per-.gyp-file
193
+ # NinjaWriter code.
194
+ #
195
+ # All paths as written into the .ninja files are relative to the build
196
+ # directory. Call these paths "ninja paths".
197
+ #
198
+ # We translate between these two notions of paths with two helper
199
+ # functions:
200
+ #
201
+ # - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file)
202
+ # into the equivalent ninja path.
203
+ #
204
+ # - GypPathToUniqueOutput translates a gyp path into a ninja path to write
205
+ # an output file; the result can be namespaced such that it is unique
206
+ # to the input file name as well as the output target name.
207
+
208
+ class NinjaWriter(object):
209
+ def __init__(self, hash_for_rules, target_outputs, base_dir, build_dir,
210
+ output_file, toplevel_build, output_file_name, flavor,
211
+ toplevel_dir=None):
212
+ """
213
+ base_dir: path from source root to directory containing this gyp file,
214
+ by gyp semantics, all input paths are relative to this
215
+ build_dir: path from source root to build output
216
+ toplevel_dir: path to the toplevel directory
217
+ """
218
+
219
+ self.hash_for_rules = hash_for_rules
220
+ self.target_outputs = target_outputs
221
+ self.base_dir = base_dir
222
+ self.build_dir = build_dir
223
+ self.ninja = ninja_syntax.Writer(output_file)
224
+ self.toplevel_build = toplevel_build
225
+ self.output_file_name = output_file_name
226
+
227
+ self.flavor = flavor
228
+ self.abs_build_dir = None
229
+ if toplevel_dir is not None:
230
+ self.abs_build_dir = os.path.abspath(os.path.join(toplevel_dir,
231
+ build_dir))
232
+ self.obj_ext = '.obj' if flavor == 'win' else '.o'
233
+ if flavor == 'win':
234
+ # See docstring of msvs_emulation.GenerateEnvironmentFiles().
235
+ self.win_env = {}
236
+ for arch in ('x86', 'x64'):
237
+ self.win_env[arch] = 'environment.' + arch
238
+
239
+ # Relative path from build output dir to base dir.
240
+ build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir)
241
+ self.build_to_base = os.path.join(build_to_top, base_dir)
242
+ # Relative path from base dir to build dir.
243
+ base_to_top = gyp.common.InvertRelativePath(base_dir, toplevel_dir)
244
+ self.base_to_build = os.path.join(base_to_top, build_dir)
245
+
246
+ def ExpandSpecial(self, path, product_dir=None):
247
+ """Expand specials like $!PRODUCT_DIR in |path|.
248
+
249
+ If |product_dir| is None, assumes the cwd is already the product
250
+ dir. Otherwise, |product_dir| is the relative path to the product
251
+ dir.
252
+ """
253
+
254
+ PRODUCT_DIR = '$!PRODUCT_DIR'
255
+ if PRODUCT_DIR in path:
256
+ if product_dir:
257
+ path = path.replace(PRODUCT_DIR, product_dir)
258
+ else:
259
+ path = path.replace(PRODUCT_DIR + '/', '')
260
+ path = path.replace(PRODUCT_DIR + '\\', '')
261
+ path = path.replace(PRODUCT_DIR, '.')
262
+
263
+ INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR'
264
+ if INTERMEDIATE_DIR in path:
265
+ int_dir = self.GypPathToUniqueOutput('gen')
266
+ # GypPathToUniqueOutput generates a path relative to the product dir,
267
+ # so insert product_dir in front if it is provided.
268
+ path = path.replace(INTERMEDIATE_DIR,
269
+ os.path.join(product_dir or '', int_dir))
270
+
271
+ CONFIGURATION_NAME = '$|CONFIGURATION_NAME'
272
+ path = path.replace(CONFIGURATION_NAME, self.config_name)
273
+
274
+ return path
275
+
276
+ def ExpandRuleVariables(self, path, root, dirname, source, ext, name):
277
+ if self.flavor == 'win':
278
+ path = self.msvs_settings.ConvertVSMacros(
279
+ path, config=self.config_name)
280
+ path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root)
281
+ path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'],
282
+ dirname)
283
+ path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source)
284
+ path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext)
285
+ path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name)
286
+ return path
287
+
288
+ def GypPathToNinja(self, path, env=None):
289
+ """Translate a gyp path to a ninja path, optionally expanding environment
290
+ variable references in |path| with |env|.
291
+
292
+ See the above discourse on path conversions."""
293
+ if env:
294
+ if self.flavor == 'mac':
295
+ path = gyp.xcode_emulation.ExpandEnvVars(path, env)
296
+ elif self.flavor == 'win':
297
+ path = gyp.msvs_emulation.ExpandMacros(path, env)
298
+ if path.startswith('$!'):
299
+ expanded = self.ExpandSpecial(path)
300
+ if self.flavor == 'win':
301
+ expanded = os.path.normpath(expanded)
302
+ return expanded
303
+ if '$|' in path:
304
+ path = self.ExpandSpecial(path)
305
+ assert '$' not in path, path
306
+ return os.path.normpath(os.path.join(self.build_to_base, path))
307
+
308
+ def GypPathToUniqueOutput(self, path, qualified=True):
309
+ """Translate a gyp path to a ninja path for writing output.
310
+
311
+ If qualified is True, qualify the resulting filename with the name
312
+ of the target. This is necessary when e.g. compiling the same
313
+ path twice for two separate output targets.
314
+
315
+ See the above discourse on path conversions."""
316
+
317
+ path = self.ExpandSpecial(path)
318
+ assert not path.startswith('$'), path
319
+
320
+ # Translate the path following this scheme:
321
+ # Input: foo/bar.gyp, target targ, references baz/out.o
322
+ # Output: obj/foo/baz/targ.out.o (if qualified)
323
+ # obj/foo/baz/out.o (otherwise)
324
+ # (and obj.host instead of obj for cross-compiles)
325
+ #
326
+ # Why this scheme and not some other one?
327
+ # 1) for a given input, you can compute all derived outputs by matching
328
+ # its path, even if the input is brought via a gyp file with '..'.
329
+ # 2) simple files like libraries and stamps have a simple filename.
330
+
331
+ obj = 'obj'
332
+ if self.toolset != 'target':
333
+ obj += '.' + self.toolset
334
+
335
+ path_dir, path_basename = os.path.split(path)
336
+ assert not os.path.isabs(path_dir), (
337
+ "'%s' can not be absolute path (see crbug.com/462153)." % path_dir)
338
+
339
+ if qualified:
340
+ path_basename = self.name + '.' + path_basename
341
+ return os.path.normpath(os.path.join(obj, self.base_dir, path_dir,
342
+ path_basename))
343
+
344
+ def WriteCollapsedDependencies(self, name, targets, order_only=None):
345
+ """Given a list of targets, return a path for a single file
346
+ representing the result of building all the targets or None.
347
+
348
+ Uses a stamp file if necessary."""
349
+
350
+ assert targets == filter(None, targets), targets
351
+ if len(targets) == 0:
352
+ assert not order_only
353
+ return None
354
+ if len(targets) > 1 or order_only:
355
+ stamp = self.GypPathToUniqueOutput(name + '.stamp')
356
+ targets = self.ninja.build(stamp, 'stamp', targets, order_only=order_only)
357
+ self.ninja.newline()
358
+ return targets[0]
359
+
360
+ def _SubninjaNameForArch(self, arch):
361
+ output_file_base = os.path.splitext(self.output_file_name)[0]
362
+ return '%s.%s.ninja' % (output_file_base, arch)
363
+
364
+ def WriteSpec(self, spec, config_name, generator_flags):
365
+ """The main entry point for NinjaWriter: write the build rules for a spec.
366
+
367
+ Returns a Target object, which represents the output paths for this spec.
368
+ Returns None if there are no outputs (e.g. a settings-only 'none' type
369
+ target)."""
370
+
371
+ self.config_name = config_name
372
+ self.name = spec['target_name']
373
+ self.toolset = spec['toolset']
374
+ config = spec['configurations'][config_name]
375
+ self.target = Target(spec['type'])
376
+ self.is_standalone_static_library = bool(
377
+ spec.get('standalone_static_library', 0))
378
+ # Track if this target contains any C++ files, to decide if gcc or g++
379
+ # should be used for linking.
380
+ self.uses_cpp = False
381
+
382
+ self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
383
+ self.xcode_settings = self.msvs_settings = None
384
+ if self.flavor == 'mac':
385
+ self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
386
+ if self.flavor == 'win':
387
+ self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec,
388
+ generator_flags)
389
+ arch = self.msvs_settings.GetArch(config_name)
390
+ self.ninja.variable('arch', self.win_env[arch])
391
+ self.ninja.variable('cc', '$cl_' + arch)
392
+ self.ninja.variable('cxx', '$cl_' + arch)
393
+ self.ninja.variable('cc_host', '$cl_' + arch)
394
+ self.ninja.variable('cxx_host', '$cl_' + arch)
395
+ self.ninja.variable('asm', '$ml_' + arch)
396
+
397
+ if self.flavor == 'mac':
398
+ self.archs = self.xcode_settings.GetActiveArchs(config_name)
399
+ if len(self.archs) > 1:
400
+ self.arch_subninjas = dict(
401
+ (arch, ninja_syntax.Writer(
402
+ OpenOutput(os.path.join(self.toplevel_build,
403
+ self._SubninjaNameForArch(arch)),
404
+ 'w')))
405
+ for arch in self.archs)
406
+
407
+ # Compute predepends for all rules.
408
+ # actions_depends is the dependencies this target depends on before running
409
+ # any of its action/rule/copy steps.
410
+ # compile_depends is the dependencies this target depends on before running
411
+ # any of its compile steps.
412
+ actions_depends = []
413
+ compile_depends = []
414
+ # TODO(evan): it is rather confusing which things are lists and which
415
+ # are strings. Fix these.
416
+ if 'dependencies' in spec:
417
+ for dep in spec['dependencies']:
418
+ if dep in self.target_outputs:
419
+ target = self.target_outputs[dep]
420
+ actions_depends.append(target.PreActionInput(self.flavor))
421
+ compile_depends.append(target.PreCompileInput())
422
+ actions_depends = filter(None, actions_depends)
423
+ compile_depends = filter(None, compile_depends)
424
+ actions_depends = self.WriteCollapsedDependencies('actions_depends',
425
+ actions_depends)
426
+ compile_depends = self.WriteCollapsedDependencies('compile_depends',
427
+ compile_depends)
428
+ self.target.preaction_stamp = actions_depends
429
+ self.target.precompile_stamp = compile_depends
430
+
431
+ # Write out actions, rules, and copies. These must happen before we
432
+ # compile any sources, so compute a list of predependencies for sources
433
+ # while we do it.
434
+ extra_sources = []
435
+ mac_bundle_depends = []
436
+ self.target.actions_stamp = self.WriteActionsRulesCopies(
437
+ spec, extra_sources, actions_depends, mac_bundle_depends)
438
+
439
+ # If we have actions/rules/copies, we depend directly on those, but
440
+ # otherwise we depend on dependent target's actions/rules/copies etc.
441
+ # We never need to explicitly depend on previous target's link steps,
442
+ # because no compile ever depends on them.
443
+ compile_depends_stamp = (self.target.actions_stamp or compile_depends)
444
+
445
+ # Write out the compilation steps, if any.
446
+ link_deps = []
447
+ sources = extra_sources + spec.get('sources', [])
448
+ if sources:
449
+ if self.flavor == 'mac' and len(self.archs) > 1:
450
+ # Write subninja file containing compile and link commands scoped to
451
+ # a single arch if a fat binary is being built.
452
+ for arch in self.archs:
453
+ self.ninja.subninja(self._SubninjaNameForArch(arch))
454
+
455
+ pch = None
456
+ if self.flavor == 'win':
457
+ gyp.msvs_emulation.VerifyMissingSources(
458
+ sources, self.abs_build_dir, generator_flags, self.GypPathToNinja)
459
+ pch = gyp.msvs_emulation.PrecompiledHeader(
460
+ self.msvs_settings, config_name, self.GypPathToNinja,
461
+ self.GypPathToUniqueOutput, self.obj_ext)
462
+ else:
463
+ pch = gyp.xcode_emulation.MacPrefixHeader(
464
+ self.xcode_settings, self.GypPathToNinja,
465
+ lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang))
466
+ link_deps = self.WriteSources(
467
+ self.ninja, config_name, config, sources, compile_depends_stamp, pch,
468
+ spec)
469
+ # Some actions/rules output 'sources' that are already object files.
470
+ obj_outputs = [f for f in sources if f.endswith(self.obj_ext)]
471
+ if obj_outputs:
472
+ if self.flavor != 'mac' or len(self.archs) == 1:
473
+ link_deps += [self.GypPathToNinja(o) for o in obj_outputs]
474
+ else:
475
+ print "Warning: Actions/rules writing object files don't work with " \
476
+ "multiarch targets, dropping. (target %s)" % spec['target_name']
477
+ elif self.flavor == 'mac' and len(self.archs) > 1:
478
+ link_deps = collections.defaultdict(list)
479
+
480
+ compile_deps = self.target.actions_stamp or actions_depends
481
+ if self.flavor == 'win' and self.target.type == 'static_library':
482
+ self.target.component_objs = link_deps
483
+ self.target.compile_deps = compile_deps
484
+
485
+ # Write out a link step, if needed.
486
+ output = None
487
+ is_empty_bundle = not link_deps and not mac_bundle_depends
488
+ if link_deps or self.target.actions_stamp or actions_depends:
489
+ output = self.WriteTarget(spec, config_name, config, link_deps,
490
+ compile_deps)
491
+ if self.is_mac_bundle:
492
+ mac_bundle_depends.append(output)
493
+
494
+ # Bundle all of the above together, if needed.
495
+ if self.is_mac_bundle:
496
+ output = self.WriteMacBundle(spec, mac_bundle_depends, is_empty_bundle)
497
+
498
+ if not output:
499
+ return None
500
+
501
+ assert self.target.FinalOutput(), output
502
+ return self.target
503
+
504
+ def _WinIdlRule(self, source, prebuild, outputs):
505
+ """Handle the implicit VS .idl rule for one source file. Fills |outputs|
506
+ with files that are generated."""
507
+ outdir, output, vars, flags = self.msvs_settings.GetIdlBuildData(
508
+ source, self.config_name)
509
+ outdir = self.GypPathToNinja(outdir)
510
+ def fix_path(path, rel=None):
511
+ path = os.path.join(outdir, path)
512
+ dirname, basename = os.path.split(source)
513
+ root, ext = os.path.splitext(basename)
514
+ path = self.ExpandRuleVariables(
515
+ path, root, dirname, source, ext, basename)
516
+ if rel:
517
+ path = os.path.relpath(path, rel)
518
+ return path
519
+ vars = [(name, fix_path(value, outdir)) for name, value in vars]
520
+ output = [fix_path(p) for p in output]
521
+ vars.append(('outdir', outdir))
522
+ vars.append(('idlflags', flags))
523
+ input = self.GypPathToNinja(source)
524
+ self.ninja.build(output, 'idl', input,
525
+ variables=vars, order_only=prebuild)
526
+ outputs.extend(output)
527
+
528
+ def WriteWinIdlFiles(self, spec, prebuild):
529
+ """Writes rules to match MSVS's implicit idl handling."""
530
+ assert self.flavor == 'win'
531
+ if self.msvs_settings.HasExplicitIdlRulesOrActions(spec):
532
+ return []
533
+ outputs = []
534
+ for source in filter(lambda x: x.endswith('.idl'), spec['sources']):
535
+ self._WinIdlRule(source, prebuild, outputs)
536
+ return outputs
537
+
538
+ def WriteActionsRulesCopies(self, spec, extra_sources, prebuild,
539
+ mac_bundle_depends):
540
+ """Write out the Actions, Rules, and Copies steps. Return a path
541
+ representing the outputs of these steps."""
542
+ outputs = []
543
+ if self.is_mac_bundle:
544
+ mac_bundle_resources = spec.get('mac_bundle_resources', [])[:]
545
+ else:
546
+ mac_bundle_resources = []
547
+ extra_mac_bundle_resources = []
548
+
549
+ if 'actions' in spec:
550
+ outputs += self.WriteActions(spec['actions'], extra_sources, prebuild,
551
+ extra_mac_bundle_resources)
552
+ if 'rules' in spec:
553
+ outputs += self.WriteRules(spec['rules'], extra_sources, prebuild,
554
+ mac_bundle_resources,
555
+ extra_mac_bundle_resources)
556
+ if 'copies' in spec:
557
+ outputs += self.WriteCopies(spec['copies'], prebuild, mac_bundle_depends)
558
+
559
+ if 'sources' in spec and self.flavor == 'win':
560
+ outputs += self.WriteWinIdlFiles(spec, prebuild)
561
+
562
+ stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs)
563
+
564
+ if self.is_mac_bundle:
565
+ xcassets = self.WriteMacBundleResources(
566
+ extra_mac_bundle_resources + mac_bundle_resources, mac_bundle_depends)
567
+ partial_info_plist = self.WriteMacXCassets(xcassets, mac_bundle_depends)
568
+ self.WriteMacInfoPlist(partial_info_plist, mac_bundle_depends)
569
+
570
+ return stamp
571
+
572
+ def GenerateDescription(self, verb, message, fallback):
573
+ """Generate and return a description of a build step.
574
+
575
+ |verb| is the short summary, e.g. ACTION or RULE.
576
+ |message| is a hand-written description, or None if not available.
577
+ |fallback| is the gyp-level name of the step, usable as a fallback.
578
+ """
579
+ if self.toolset != 'target':
580
+ verb += '(%s)' % self.toolset
581
+ if message:
582
+ return '%s %s' % (verb, self.ExpandSpecial(message))
583
+ else:
584
+ return '%s %s: %s' % (verb, self.name, fallback)
585
+
586
+ def WriteActions(self, actions, extra_sources, prebuild,
587
+ extra_mac_bundle_resources):
588
+ # Actions cd into the base directory.
589
+ env = self.GetToolchainEnv()
590
+ all_outputs = []
591
+ for action in actions:
592
+ # First write out a rule for the action.
593
+ name = '%s_%s' % (action['action_name'], self.hash_for_rules)
594
+ description = self.GenerateDescription('ACTION',
595
+ action.get('message', None),
596
+ name)
597
+ is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action)
598
+ if self.flavor == 'win' else False)
599
+ args = action['action']
600
+ depfile = action.get('depfile', None)
601
+ if depfile:
602
+ depfile = self.ExpandSpecial(depfile, self.base_to_build)
603
+ pool = 'console' if int(action.get('ninja_use_console', 0)) else None
604
+ rule_name, _ = self.WriteNewNinjaRule(name, args, description,
605
+ is_cygwin, env, pool,
606
+ depfile=depfile)
607
+
608
+ inputs = [self.GypPathToNinja(i, env) for i in action['inputs']]
609
+ if int(action.get('process_outputs_as_sources', False)):
610
+ extra_sources += action['outputs']
611
+ if int(action.get('process_outputs_as_mac_bundle_resources', False)):
612
+ extra_mac_bundle_resources += action['outputs']
613
+ outputs = [self.GypPathToNinja(o, env) for o in action['outputs']]
614
+
615
+ # Then write out an edge using the rule.
616
+ self.ninja.build(outputs, rule_name, inputs,
617
+ order_only=prebuild)
618
+ all_outputs += outputs
619
+
620
+ self.ninja.newline()
621
+
622
+ return all_outputs
623
+
624
+ def WriteRules(self, rules, extra_sources, prebuild,
625
+ mac_bundle_resources, extra_mac_bundle_resources):
626
+ env = self.GetToolchainEnv()
627
+ all_outputs = []
628
+ for rule in rules:
629
+ # Skip a rule with no action and no inputs.
630
+ if 'action' not in rule and not rule.get('rule_sources', []):
631
+ continue
632
+
633
+ # First write out a rule for the rule action.
634
+ name = '%s_%s' % (rule['rule_name'], self.hash_for_rules)
635
+
636
+ args = rule['action']
637
+ description = self.GenerateDescription(
638
+ 'RULE',
639
+ rule.get('message', None),
640
+ ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name)
641
+ is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule)
642
+ if self.flavor == 'win' else False)
643
+ pool = 'console' if int(rule.get('ninja_use_console', 0)) else None
644
+ rule_name, args = self.WriteNewNinjaRule(
645
+ name, args, description, is_cygwin, env, pool)
646
+
647
+ # TODO: if the command references the outputs directly, we should
648
+ # simplify it to just use $out.
649
+
650
+ # Rules can potentially make use of some special variables which
651
+ # must vary per source file.
652
+ # Compute the list of variables we'll need to provide.
653
+ special_locals = ('source', 'root', 'dirname', 'ext', 'name')
654
+ needed_variables = set(['source'])
655
+ for argument in args:
656
+ for var in special_locals:
657
+ if '${%s}' % var in argument:
658
+ needed_variables.add(var)
659
+ needed_variables = sorted(needed_variables)
660
+
661
+ def cygwin_munge(path):
662
+ # pylint: disable=cell-var-from-loop
663
+ if is_cygwin:
664
+ return path.replace('\\', '/')
665
+ return path
666
+
667
+ inputs = [self.GypPathToNinja(i, env) for i in rule.get('inputs', [])]
668
+
669
+ # If there are n source files matching the rule, and m additional rule
670
+ # inputs, then adding 'inputs' to each build edge written below will
671
+ # write m * n inputs. Collapsing reduces this to m + n.
672
+ sources = rule.get('rule_sources', [])
673
+ num_inputs = len(inputs)
674
+ if prebuild:
675
+ num_inputs += 1
676
+ if num_inputs > 2 and len(sources) > 2:
677
+ inputs = [self.WriteCollapsedDependencies(
678
+ rule['rule_name'], inputs, order_only=prebuild)]
679
+ prebuild = []
680
+
681
+ # For each source file, write an edge that generates all the outputs.
682
+ for source in sources:
683
+ source = os.path.normpath(source)
684
+ dirname, basename = os.path.split(source)
685
+ root, ext = os.path.splitext(basename)
686
+
687
+ # Gather the list of inputs and outputs, expanding $vars if possible.
688
+ outputs = [self.ExpandRuleVariables(o, root, dirname,
689
+ source, ext, basename)
690
+ for o in rule['outputs']]
691
+
692
+ if int(rule.get('process_outputs_as_sources', False)):
693
+ extra_sources += outputs
694
+
695
+ was_mac_bundle_resource = source in mac_bundle_resources
696
+ if was_mac_bundle_resource or \
697
+ int(rule.get('process_outputs_as_mac_bundle_resources', False)):
698
+ extra_mac_bundle_resources += outputs
699
+ # Note: This is n_resources * n_outputs_in_rule. Put to-be-removed
700
+ # items in a set and remove them all in a single pass if this becomes
701
+ # a performance issue.
702
+ if was_mac_bundle_resource:
703
+ mac_bundle_resources.remove(source)
704
+
705
+ extra_bindings = []
706
+ for var in needed_variables:
707
+ if var == 'root':
708
+ extra_bindings.append(('root', cygwin_munge(root)))
709
+ elif var == 'dirname':
710
+ # '$dirname' is a parameter to the rule action, which means
711
+ # it shouldn't be converted to a Ninja path. But we don't
712
+ # want $!PRODUCT_DIR in there either.
713
+ dirname_expanded = self.ExpandSpecial(dirname, self.base_to_build)
714
+ extra_bindings.append(('dirname', cygwin_munge(dirname_expanded)))
715
+ elif var == 'source':
716
+ # '$source' is a parameter to the rule action, which means
717
+ # it shouldn't be converted to a Ninja path. But we don't
718
+ # want $!PRODUCT_DIR in there either.
719
+ source_expanded = self.ExpandSpecial(source, self.base_to_build)
720
+ extra_bindings.append(('source', cygwin_munge(source_expanded)))
721
+ elif var == 'ext':
722
+ extra_bindings.append(('ext', ext))
723
+ elif var == 'name':
724
+ extra_bindings.append(('name', cygwin_munge(basename)))
725
+ else:
726
+ assert var == None, repr(var)
727
+
728
+ outputs = [self.GypPathToNinja(o, env) for o in outputs]
729
+ if self.flavor == 'win':
730
+ # WriteNewNinjaRule uses unique_name for creating an rsp file on win.
731
+ extra_bindings.append(('unique_name',
732
+ hashlib.md5(outputs[0]).hexdigest()))
733
+
734
+ self.ninja.build(outputs, rule_name, self.GypPathToNinja(source),
735
+ implicit=inputs,
736
+ order_only=prebuild,
737
+ variables=extra_bindings)
738
+
739
+ all_outputs.extend(outputs)
740
+
741
+ return all_outputs
742
+
743
+ def WriteCopies(self, copies, prebuild, mac_bundle_depends):
744
+ outputs = []
745
+ env = self.GetToolchainEnv()
746
+ for copy in copies:
747
+ for path in copy['files']:
748
+ # Normalize the path so trailing slashes don't confuse us.
749
+ path = os.path.normpath(path)
750
+ basename = os.path.split(path)[1]
751
+ src = self.GypPathToNinja(path, env)
752
+ dst = self.GypPathToNinja(os.path.join(copy['destination'], basename),
753
+ env)
754
+ outputs += self.ninja.build(dst, 'copy', src, order_only=prebuild)
755
+ if self.is_mac_bundle:
756
+ # gyp has mac_bundle_resources to copy things into a bundle's
757
+ # Resources folder, but there's no built-in way to copy files to other
758
+ # places in the bundle. Hence, some targets use copies for this. Check
759
+ # if this file is copied into the current bundle, and if so add it to
760
+ # the bundle depends so that dependent targets get rebuilt if the copy
761
+ # input changes.
762
+ if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()):
763
+ mac_bundle_depends.append(dst)
764
+
765
+ return outputs
766
+
767
+ def WriteMacBundleResources(self, resources, bundle_depends):
768
+ """Writes ninja edges for 'mac_bundle_resources'."""
769
+ xcassets = []
770
+
771
+ extra_env = self.xcode_settings.GetPerTargetSettings()
772
+ env = self.GetSortedXcodeEnv(additional_settings=extra_env)
773
+ env = self.ComputeExportEnvString(env)
774
+ isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name)
775
+
776
+ for output, res in gyp.xcode_emulation.GetMacBundleResources(
777
+ generator_default_variables['PRODUCT_DIR'],
778
+ self.xcode_settings, map(self.GypPathToNinja, resources)):
779
+ output = self.ExpandSpecial(output)
780
+ if os.path.splitext(output)[-1] != '.xcassets':
781
+ self.ninja.build(output, 'mac_tool', res,
782
+ variables=[('mactool_cmd', 'copy-bundle-resource'), \
783
+ ('env', env), ('binary', isBinary)])
784
+ bundle_depends.append(output)
785
+ else:
786
+ xcassets.append(res)
787
+ return xcassets
788
+
789
+ def WriteMacXCassets(self, xcassets, bundle_depends):
790
+ """Writes ninja edges for 'mac_bundle_resources' .xcassets files.
791
+
792
+ This add an invocation of 'actool' via the 'mac_tool.py' helper script.
793
+ It assumes that the assets catalogs define at least one imageset and
794
+ thus an Assets.car file will be generated in the application resources
795
+ directory. If this is not the case, then the build will probably be done
796
+ at each invocation of ninja."""
797
+ if not xcassets:
798
+ return
799
+
800
+ extra_arguments = {}
801
+ settings_to_arg = {
802
+ 'XCASSETS_APP_ICON': 'app-icon',
803
+ 'XCASSETS_LAUNCH_IMAGE': 'launch-image',
804
+ }
805
+ settings = self.xcode_settings.xcode_settings[self.config_name]
806
+ for settings_key, arg_name in settings_to_arg.iteritems():
807
+ value = settings.get(settings_key)
808
+ if value:
809
+ extra_arguments[arg_name] = value
810
+
811
+ partial_info_plist = None
812
+ if extra_arguments:
813
+ partial_info_plist = self.GypPathToUniqueOutput(
814
+ 'assetcatalog_generated_info.plist')
815
+ extra_arguments['output-partial-info-plist'] = partial_info_plist
816
+
817
+ outputs = []
818
+ outputs.append(
819
+ os.path.join(
820
+ self.xcode_settings.GetBundleResourceFolder(),
821
+ 'Assets.car'))
822
+ if partial_info_plist:
823
+ outputs.append(partial_info_plist)
824
+
825
+ keys = QuoteShellArgument(json.dumps(extra_arguments), self.flavor)
826
+ extra_env = self.xcode_settings.GetPerTargetSettings()
827
+ env = self.GetSortedXcodeEnv(additional_settings=extra_env)
828
+ env = self.ComputeExportEnvString(env)
829
+
830
+ bundle_depends.extend(self.ninja.build(
831
+ outputs, 'compile_xcassets', xcassets,
832
+ variables=[('env', env), ('keys', keys)]))
833
+ return partial_info_plist
834
+
835
+ def WriteMacInfoPlist(self, partial_info_plist, bundle_depends):
836
+ """Write build rules for bundle Info.plist files."""
837
+ info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
838
+ generator_default_variables['PRODUCT_DIR'],
839
+ self.xcode_settings, self.GypPathToNinja)
840
+ if not info_plist:
841
+ return
842
+ out = self.ExpandSpecial(out)
843
+ if defines:
844
+ # Create an intermediate file to store preprocessed results.
845
+ intermediate_plist = self.GypPathToUniqueOutput(
846
+ os.path.basename(info_plist))
847
+ defines = ' '.join([Define(d, self.flavor) for d in defines])
848
+ info_plist = self.ninja.build(
849
+ intermediate_plist, 'preprocess_infoplist', info_plist,
850
+ variables=[('defines',defines)])
851
+
852
+ env = self.GetSortedXcodeEnv(additional_settings=extra_env)
853
+ env = self.ComputeExportEnvString(env)
854
+
855
+ if partial_info_plist:
856
+ intermediate_plist = self.GypPathToUniqueOutput('merged_info.plist')
857
+ info_plist = self.ninja.build(
858
+ intermediate_plist, 'merge_infoplist',
859
+ [partial_info_plist, info_plist])
860
+
861
+ keys = self.xcode_settings.GetExtraPlistItems(self.config_name)
862
+ keys = QuoteShellArgument(json.dumps(keys), self.flavor)
863
+ isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name)
864
+ self.ninja.build(out, 'copy_infoplist', info_plist,
865
+ variables=[('env', env), ('keys', keys),
866
+ ('binary', isBinary)])
867
+ bundle_depends.append(out)
868
+
869
+ def WriteSources(self, ninja_file, config_name, config, sources, predepends,
870
+ precompiled_header, spec):
871
+ """Write build rules to compile all of |sources|."""
872
+ if self.toolset == 'host':
873
+ self.ninja.variable('ar', '$ar_host')
874
+ self.ninja.variable('cc', '$cc_host')
875
+ self.ninja.variable('cxx', '$cxx_host')
876
+ self.ninja.variable('ld', '$ld_host')
877
+ self.ninja.variable('ldxx', '$ldxx_host')
878
+ self.ninja.variable('nm', '$nm_host')
879
+ self.ninja.variable('readelf', '$readelf_host')
880
+
881
+ if self.flavor != 'mac' or len(self.archs) == 1:
882
+ return self.WriteSourcesForArch(
883
+ self.ninja, config_name, config, sources, predepends,
884
+ precompiled_header, spec)
885
+ else:
886
+ return dict((arch, self.WriteSourcesForArch(
887
+ self.arch_subninjas[arch], config_name, config, sources, predepends,
888
+ precompiled_header, spec, arch=arch))
889
+ for arch in self.archs)
890
+
891
+ def WriteSourcesForArch(self, ninja_file, config_name, config, sources,
892
+ predepends, precompiled_header, spec, arch=None):
893
+ """Write build rules to compile all of |sources|."""
894
+
895
+ extra_defines = []
896
+ if self.flavor == 'mac':
897
+ cflags = self.xcode_settings.GetCflags(config_name, arch=arch)
898
+ cflags_c = self.xcode_settings.GetCflagsC(config_name)
899
+ cflags_cc = self.xcode_settings.GetCflagsCC(config_name)
900
+ cflags_objc = ['$cflags_c'] + \
901
+ self.xcode_settings.GetCflagsObjC(config_name)
902
+ cflags_objcc = ['$cflags_cc'] + \
903
+ self.xcode_settings.GetCflagsObjCC(config_name)
904
+ elif self.flavor == 'win':
905
+ asmflags = self.msvs_settings.GetAsmflags(config_name)
906
+ cflags = self.msvs_settings.GetCflags(config_name)
907
+ cflags_c = self.msvs_settings.GetCflagsC(config_name)
908
+ cflags_cc = self.msvs_settings.GetCflagsCC(config_name)
909
+ extra_defines = self.msvs_settings.GetComputedDefines(config_name)
910
+ # See comment at cc_command for why there's two .pdb files.
911
+ pdbpath_c = pdbpath_cc = self.msvs_settings.GetCompilerPdbName(
912
+ config_name, self.ExpandSpecial)
913
+ if not pdbpath_c:
914
+ obj = 'obj'
915
+ if self.toolset != 'target':
916
+ obj += '.' + self.toolset
917
+ pdbpath = os.path.normpath(os.path.join(obj, self.base_dir, self.name))
918
+ pdbpath_c = pdbpath + '.c.pdb'
919
+ pdbpath_cc = pdbpath + '.cc.pdb'
920
+ self.WriteVariableList(ninja_file, 'pdbname_c', [pdbpath_c])
921
+ self.WriteVariableList(ninja_file, 'pdbname_cc', [pdbpath_cc])
922
+ self.WriteVariableList(ninja_file, 'pchprefix', [self.name])
923
+ else:
924
+ cflags = config.get('cflags', [])
925
+ cflags_c = config.get('cflags_c', [])
926
+ cflags_cc = config.get('cflags_cc', [])
927
+
928
+ # Respect environment variables related to build, but target-specific
929
+ # flags can still override them.
930
+ if self.toolset == 'target':
931
+ cflags_c = (os.environ.get('CPPFLAGS', '').split() +
932
+ os.environ.get('CFLAGS', '').split() + cflags_c)
933
+ cflags_cc = (os.environ.get('CPPFLAGS', '').split() +
934
+ os.environ.get('CXXFLAGS', '').split() + cflags_cc)
935
+ elif self.toolset == 'host':
936
+ cflags_c = (os.environ.get('CPPFLAGS_host', '').split() +
937
+ os.environ.get('CFLAGS_host', '').split() + cflags_c)
938
+ cflags_cc = (os.environ.get('CPPFLAGS_host', '').split() +
939
+ os.environ.get('CXXFLAGS_host', '').split() + cflags_cc)
940
+
941
+ defines = config.get('defines', []) + extra_defines
942
+ self.WriteVariableList(ninja_file, 'defines',
943
+ [Define(d, self.flavor) for d in defines])
944
+ if self.flavor == 'win':
945
+ self.WriteVariableList(ninja_file, 'asmflags',
946
+ map(self.ExpandSpecial, asmflags))
947
+ self.WriteVariableList(ninja_file, 'rcflags',
948
+ [QuoteShellArgument(self.ExpandSpecial(f), self.flavor)
949
+ for f in self.msvs_settings.GetRcflags(config_name,
950
+ self.GypPathToNinja)])
951
+
952
+ include_dirs = config.get('include_dirs', [])
953
+
954
+ env = self.GetToolchainEnv()
955
+ if self.flavor == 'win':
956
+ include_dirs = self.msvs_settings.AdjustIncludeDirs(include_dirs,
957
+ config_name)
958
+ self.WriteVariableList(ninja_file, 'includes',
959
+ [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor)
960
+ for i in include_dirs])
961
+
962
+ if self.flavor == 'win':
963
+ midl_include_dirs = config.get('midl_include_dirs', [])
964
+ midl_include_dirs = self.msvs_settings.AdjustMidlIncludeDirs(
965
+ midl_include_dirs, config_name)
966
+ self.WriteVariableList(ninja_file, 'midl_includes',
967
+ [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor)
968
+ for i in midl_include_dirs])
969
+
970
+ pch_commands = precompiled_header.GetPchBuildCommands(arch)
971
+ if self.flavor == 'mac':
972
+ # Most targets use no precompiled headers, so only write these if needed.
973
+ for ext, var in [('c', 'cflags_pch_c'), ('cc', 'cflags_pch_cc'),
974
+ ('m', 'cflags_pch_objc'), ('mm', 'cflags_pch_objcc')]:
975
+ include = precompiled_header.GetInclude(ext, arch)
976
+ if include: ninja_file.variable(var, include)
977
+
978
+ arflags = config.get('arflags', [])
979
+
980
+ self.WriteVariableList(ninja_file, 'cflags',
981
+ map(self.ExpandSpecial, cflags))
982
+ self.WriteVariableList(ninja_file, 'cflags_c',
983
+ map(self.ExpandSpecial, cflags_c))
984
+ self.WriteVariableList(ninja_file, 'cflags_cc',
985
+ map(self.ExpandSpecial, cflags_cc))
986
+ if self.flavor == 'mac':
987
+ self.WriteVariableList(ninja_file, 'cflags_objc',
988
+ map(self.ExpandSpecial, cflags_objc))
989
+ self.WriteVariableList(ninja_file, 'cflags_objcc',
990
+ map(self.ExpandSpecial, cflags_objcc))
991
+ self.WriteVariableList(ninja_file, 'arflags',
992
+ map(self.ExpandSpecial, arflags))
993
+ ninja_file.newline()
994
+ outputs = []
995
+ has_rc_source = False
996
+ for source in sources:
997
+ filename, ext = os.path.splitext(source)
998
+ ext = ext[1:]
999
+ obj_ext = self.obj_ext
1000
+ if ext in ('cc', 'cpp', 'cxx'):
1001
+ command = 'cxx'
1002
+ self.uses_cpp = True
1003
+ elif ext == 'c' or (ext == 'S' and self.flavor != 'win'):
1004
+ command = 'cc'
1005
+ elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files.
1006
+ command = 'cc_s'
1007
+ elif (self.flavor == 'win' and ext == 'asm' and
1008
+ not self.msvs_settings.HasExplicitAsmRules(spec)):
1009
+ command = 'asm'
1010
+ # Add the _asm suffix as msvs is capable of handling .cc and
1011
+ # .asm files of the same name without collision.
1012
+ obj_ext = '_asm.obj'
1013
+ elif self.flavor == 'mac' and ext == 'm':
1014
+ command = 'objc'
1015
+ elif self.flavor == 'mac' and ext == 'mm':
1016
+ command = 'objcxx'
1017
+ self.uses_cpp = True
1018
+ elif self.flavor == 'win' and ext == 'rc':
1019
+ command = 'rc'
1020
+ obj_ext = '.res'
1021
+ has_rc_source = True
1022
+ else:
1023
+ # Ignore unhandled extensions.
1024
+ continue
1025
+ input = self.GypPathToNinja(source)
1026
+ output = self.GypPathToUniqueOutput(filename + obj_ext)
1027
+ if arch is not None:
1028
+ output = AddArch(output, arch)
1029
+ implicit = precompiled_header.GetObjDependencies([input], [output], arch)
1030
+ variables = []
1031
+ if self.flavor == 'win':
1032
+ variables, output, implicit = precompiled_header.GetFlagsModifications(
1033
+ input, output, implicit, command, cflags_c, cflags_cc,
1034
+ self.ExpandSpecial)
1035
+ ninja_file.build(output, command, input,
1036
+ implicit=[gch for _, _, gch in implicit],
1037
+ order_only=predepends, variables=variables)
1038
+ outputs.append(output)
1039
+
1040
+ if has_rc_source:
1041
+ resource_include_dirs = config.get('resource_include_dirs', include_dirs)
1042
+ self.WriteVariableList(ninja_file, 'resource_includes',
1043
+ [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor)
1044
+ for i in resource_include_dirs])
1045
+
1046
+ self.WritePchTargets(ninja_file, pch_commands)
1047
+
1048
+ ninja_file.newline()
1049
+ return outputs
1050
+
1051
+ def WritePchTargets(self, ninja_file, pch_commands):
1052
+ """Writes ninja rules to compile prefix headers."""
1053
+ if not pch_commands:
1054
+ return
1055
+
1056
+ for gch, lang_flag, lang, input in pch_commands:
1057
+ var_name = {
1058
+ 'c': 'cflags_pch_c',
1059
+ 'cc': 'cflags_pch_cc',
1060
+ 'm': 'cflags_pch_objc',
1061
+ 'mm': 'cflags_pch_objcc',
1062
+ }[lang]
1063
+
1064
+ map = { 'c': 'cc', 'cc': 'cxx', 'm': 'objc', 'mm': 'objcxx', }
1065
+ cmd = map.get(lang)
1066
+ ninja_file.build(gch, cmd, input, variables=[(var_name, lang_flag)])
1067
+
1068
+ def WriteLink(self, spec, config_name, config, link_deps, compile_deps):
1069
+ """Write out a link step. Fills out target.binary. """
1070
+ if self.flavor != 'mac' or len(self.archs) == 1:
1071
+ return self.WriteLinkForArch(
1072
+ self.ninja, spec, config_name, config, link_deps, compile_deps)
1073
+ else:
1074
+ output = self.ComputeOutput(spec)
1075
+ inputs = [self.WriteLinkForArch(self.arch_subninjas[arch], spec,
1076
+ config_name, config, link_deps[arch],
1077
+ compile_deps, arch=arch)
1078
+ for arch in self.archs]
1079
+ extra_bindings = []
1080
+ build_output = output
1081
+ if not self.is_mac_bundle:
1082
+ self.AppendPostbuildVariable(extra_bindings, spec, output, output)
1083
+
1084
+ # TODO(yyanagisawa): more work needed to fix:
1085
+ # https://code.google.com/p/gyp/issues/detail?id=411
1086
+ if (spec['type'] in ('shared_library', 'loadable_module') and
1087
+ not self.is_mac_bundle):
1088
+ extra_bindings.append(('lib', output))
1089
+ self.ninja.build([output, output + '.TOC'], 'solipo', inputs,
1090
+ variables=extra_bindings)
1091
+ else:
1092
+ self.ninja.build(build_output, 'lipo', inputs, variables=extra_bindings)
1093
+ return output
1094
+
1095
+ def WriteLinkForArch(self, ninja_file, spec, config_name, config,
1096
+ link_deps, compile_deps, arch=None):
1097
+ """Write out a link step. Fills out target.binary. """
1098
+ command = {
1099
+ 'executable': 'link',
1100
+ 'loadable_module': 'solink_module',
1101
+ 'shared_library': 'solink',
1102
+ }[spec['type']]
1103
+ command_suffix = ''
1104
+
1105
+ implicit_deps = set()
1106
+ solibs = set()
1107
+ order_deps = set()
1108
+
1109
+ if compile_deps:
1110
+ # Normally, the compiles of the target already depend on compile_deps,
1111
+ # but a shared_library target might have no sources and only link together
1112
+ # a few static_library deps, so the link step also needs to depend
1113
+ # on compile_deps to make sure actions in the shared_library target
1114
+ # get run before the link.
1115
+ order_deps.add(compile_deps)
1116
+
1117
+ if 'dependencies' in spec:
1118
+ # Two kinds of dependencies:
1119
+ # - Linkable dependencies (like a .a or a .so): add them to the link line.
1120
+ # - Non-linkable dependencies (like a rule that generates a file
1121
+ # and writes a stamp file): add them to implicit_deps
1122
+ extra_link_deps = set()
1123
+ for dep in spec['dependencies']:
1124
+ target = self.target_outputs.get(dep)
1125
+ if not target:
1126
+ continue
1127
+ linkable = target.Linkable()
1128
+ if linkable:
1129
+ new_deps = []
1130
+ if (self.flavor == 'win' and
1131
+ target.component_objs and
1132
+ self.msvs_settings.IsUseLibraryDependencyInputs(config_name)):
1133
+ new_deps = target.component_objs
1134
+ if target.compile_deps:
1135
+ order_deps.add(target.compile_deps)
1136
+ elif self.flavor == 'win' and target.import_lib:
1137
+ new_deps = [target.import_lib]
1138
+ elif target.UsesToc(self.flavor):
1139
+ solibs.add(target.binary)
1140
+ implicit_deps.add(target.binary + '.TOC')
1141
+ else:
1142
+ new_deps = [target.binary]
1143
+ for new_dep in new_deps:
1144
+ if new_dep not in extra_link_deps:
1145
+ extra_link_deps.add(new_dep)
1146
+ link_deps.append(new_dep)
1147
+
1148
+ final_output = target.FinalOutput()
1149
+ if not linkable or final_output != target.binary:
1150
+ implicit_deps.add(final_output)
1151
+
1152
+ extra_bindings = []
1153
+ if self.uses_cpp and self.flavor != 'win':
1154
+ extra_bindings.append(('ld', '$ldxx'))
1155
+
1156
+ output = self.ComputeOutput(spec, arch)
1157
+ if arch is None and not self.is_mac_bundle:
1158
+ self.AppendPostbuildVariable(extra_bindings, spec, output, output)
1159
+
1160
+ is_executable = spec['type'] == 'executable'
1161
+ # The ldflags config key is not used on mac or win. On those platforms
1162
+ # linker flags are set via xcode_settings and msvs_settings, respectively.
1163
+ env_ldflags = os.environ.get('LDFLAGS', '').split()
1164
+ if self.flavor == 'mac':
1165
+ ldflags = self.xcode_settings.GetLdflags(config_name,
1166
+ self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
1167
+ self.GypPathToNinja, arch)
1168
+ ldflags = env_ldflags + ldflags
1169
+ elif self.flavor == 'win':
1170
+ manifest_base_name = self.GypPathToUniqueOutput(
1171
+ self.ComputeOutputFileName(spec))
1172
+ ldflags, intermediate_manifest, manifest_files = \
1173
+ self.msvs_settings.GetLdflags(config_name, self.GypPathToNinja,
1174
+ self.ExpandSpecial, manifest_base_name,
1175
+ output, is_executable,
1176
+ self.toplevel_build)
1177
+ ldflags = env_ldflags + ldflags
1178
+ self.WriteVariableList(ninja_file, 'manifests', manifest_files)
1179
+ implicit_deps = implicit_deps.union(manifest_files)
1180
+ if intermediate_manifest:
1181
+ self.WriteVariableList(
1182
+ ninja_file, 'intermediatemanifest', [intermediate_manifest])
1183
+ command_suffix = _GetWinLinkRuleNameSuffix(
1184
+ self.msvs_settings.IsEmbedManifest(config_name))
1185
+ def_file = self.msvs_settings.GetDefFile(self.GypPathToNinja)
1186
+ if def_file:
1187
+ implicit_deps.add(def_file)
1188
+ else:
1189
+ # Respect environment variables related to build, but target-specific
1190
+ # flags can still override them.
1191
+ ldflags = env_ldflags + config.get('ldflags', [])
1192
+ if is_executable and len(solibs):
1193
+ rpath = 'lib/'
1194
+ if self.toolset != 'target':
1195
+ rpath += self.toolset
1196
+ ldflags.append(r'-Wl,-rpath=\$$ORIGIN/%s' % rpath)
1197
+ ldflags.append('-Wl,-rpath-link=%s' % rpath)
1198
+ self.WriteVariableList(ninja_file, 'ldflags',
1199
+ map(self.ExpandSpecial, ldflags))
1200
+
1201
+ library_dirs = config.get('library_dirs', [])
1202
+ if self.flavor == 'win':
1203
+ library_dirs = [self.msvs_settings.ConvertVSMacros(l, config_name)
1204
+ for l in library_dirs]
1205
+ library_dirs = ['/LIBPATH:' + QuoteShellArgument(self.GypPathToNinja(l),
1206
+ self.flavor)
1207
+ for l in library_dirs]
1208
+ else:
1209
+ library_dirs = [QuoteShellArgument('-L' + self.GypPathToNinja(l),
1210
+ self.flavor)
1211
+ for l in library_dirs]
1212
+
1213
+ libraries = gyp.common.uniquer(map(self.ExpandSpecial,
1214
+ spec.get('libraries', [])))
1215
+ if self.flavor == 'mac':
1216
+ libraries = self.xcode_settings.AdjustLibraries(libraries, config_name)
1217
+ elif self.flavor == 'win':
1218
+ libraries = self.msvs_settings.AdjustLibraries(libraries)
1219
+
1220
+ self.WriteVariableList(ninja_file, 'libs', library_dirs + libraries)
1221
+
1222
+ linked_binary = output
1223
+
1224
+ if command in ('solink', 'solink_module'):
1225
+ extra_bindings.append(('soname', os.path.split(output)[1]))
1226
+ extra_bindings.append(('lib',
1227
+ gyp.common.EncodePOSIXShellArgument(output)))
1228
+ if self.flavor != 'win':
1229
+ link_file_list = output
1230
+ if self.is_mac_bundle:
1231
+ # 'Dependency Framework.framework/Versions/A/Dependency Framework' ->
1232
+ # 'Dependency Framework.framework.rsp'
1233
+ link_file_list = self.xcode_settings.GetWrapperName()
1234
+ if arch:
1235
+ link_file_list += '.' + arch
1236
+ link_file_list += '.rsp'
1237
+ # If an rspfile contains spaces, ninja surrounds the filename with
1238
+ # quotes around it and then passes it to open(), creating a file with
1239
+ # quotes in its name (and when looking for the rsp file, the name
1240
+ # makes it through bash which strips the quotes) :-/
1241
+ link_file_list = link_file_list.replace(' ', '_')
1242
+ extra_bindings.append(
1243
+ ('link_file_list',
1244
+ gyp.common.EncodePOSIXShellArgument(link_file_list)))
1245
+ if self.flavor == 'win':
1246
+ extra_bindings.append(('binary', output))
1247
+ if ('/NOENTRY' not in ldflags and
1248
+ not self.msvs_settings.GetNoImportLibrary(config_name)):
1249
+ self.target.import_lib = output + '.lib'
1250
+ extra_bindings.append(('implibflag',
1251
+ '/IMPLIB:%s' % self.target.import_lib))
1252
+ pdbname = self.msvs_settings.GetPDBName(
1253
+ config_name, self.ExpandSpecial, output + '.pdb')
1254
+ output = [output, self.target.import_lib]
1255
+ if pdbname:
1256
+ output.append(pdbname)
1257
+ elif not self.is_mac_bundle:
1258
+ output = [output, output + '.TOC']
1259
+ else:
1260
+ command = command + '_notoc'
1261
+ elif self.flavor == 'win':
1262
+ extra_bindings.append(('binary', output))
1263
+ pdbname = self.msvs_settings.GetPDBName(
1264
+ config_name, self.ExpandSpecial, output + '.pdb')
1265
+ if pdbname:
1266
+ output = [output, pdbname]
1267
+
1268
+
1269
+ if len(solibs):
1270
+ extra_bindings.append(('solibs',
1271
+ gyp.common.EncodePOSIXShellList(sorted(solibs))))
1272
+
1273
+ ninja_file.build(output, command + command_suffix, link_deps,
1274
+ implicit=sorted(implicit_deps),
1275
+ order_only=list(order_deps),
1276
+ variables=extra_bindings)
1277
+ return linked_binary
1278
+
1279
+ def WriteTarget(self, spec, config_name, config, link_deps, compile_deps):
1280
+ extra_link_deps = any(self.target_outputs.get(dep).Linkable()
1281
+ for dep in spec.get('dependencies', [])
1282
+ if dep in self.target_outputs)
1283
+ if spec['type'] == 'none' or (not link_deps and not extra_link_deps):
1284
+ # TODO(evan): don't call this function for 'none' target types, as
1285
+ # it doesn't do anything, and we fake out a 'binary' with a stamp file.
1286
+ self.target.binary = compile_deps
1287
+ self.target.type = 'none'
1288
+ elif spec['type'] == 'static_library':
1289
+ self.target.binary = self.ComputeOutput(spec)
1290
+ if (self.flavor not in ('mac', 'openbsd', 'netbsd', 'win') and not
1291
+ self.is_standalone_static_library):
1292
+ self.ninja.build(self.target.binary, 'alink_thin', link_deps,
1293
+ order_only=compile_deps)
1294
+ else:
1295
+ variables = []
1296
+ if self.xcode_settings:
1297
+ libtool_flags = self.xcode_settings.GetLibtoolflags(config_name)
1298
+ if libtool_flags:
1299
+ variables.append(('libtool_flags', libtool_flags))
1300
+ if self.msvs_settings:
1301
+ libflags = self.msvs_settings.GetLibFlags(config_name,
1302
+ self.GypPathToNinja)
1303
+ variables.append(('libflags', libflags))
1304
+
1305
+ if self.flavor != 'mac' or len(self.archs) == 1:
1306
+ self.AppendPostbuildVariable(variables, spec,
1307
+ self.target.binary, self.target.binary)
1308
+ self.ninja.build(self.target.binary, 'alink', link_deps,
1309
+ order_only=compile_deps, variables=variables)
1310
+ else:
1311
+ inputs = []
1312
+ for arch in self.archs:
1313
+ output = self.ComputeOutput(spec, arch)
1314
+ self.arch_subninjas[arch].build(output, 'alink', link_deps[arch],
1315
+ order_only=compile_deps,
1316
+ variables=variables)
1317
+ inputs.append(output)
1318
+ # TODO: It's not clear if libtool_flags should be passed to the alink
1319
+ # call that combines single-arch .a files into a fat .a file.
1320
+ self.AppendPostbuildVariable(variables, spec,
1321
+ self.target.binary, self.target.binary)
1322
+ self.ninja.build(self.target.binary, 'alink', inputs,
1323
+ # FIXME: test proving order_only=compile_deps isn't
1324
+ # needed.
1325
+ variables=variables)
1326
+ else:
1327
+ self.target.binary = self.WriteLink(spec, config_name, config, link_deps,
1328
+ compile_deps)
1329
+ return self.target.binary
1330
+
1331
+ def WriteMacBundle(self, spec, mac_bundle_depends, is_empty):
1332
+ assert self.is_mac_bundle
1333
+ package_framework = spec['type'] in ('shared_library', 'loadable_module')
1334
+ output = self.ComputeMacBundleOutput()
1335
+ if is_empty:
1336
+ output += '.stamp'
1337
+ variables = []
1338
+ self.AppendPostbuildVariable(variables, spec, output, self.target.binary,
1339
+ is_command_start=not package_framework)
1340
+ if package_framework and not is_empty:
1341
+ variables.append(('version', self.xcode_settings.GetFrameworkVersion()))
1342
+ self.ninja.build(output, 'package_framework', mac_bundle_depends,
1343
+ variables=variables)
1344
+ else:
1345
+ self.ninja.build(output, 'stamp', mac_bundle_depends,
1346
+ variables=variables)
1347
+ self.target.bundle = output
1348
+ return output
1349
+
1350
+ def GetToolchainEnv(self, additional_settings=None):
1351
+ """Returns the variables toolchain would set for build steps."""
1352
+ env = self.GetSortedXcodeEnv(additional_settings=additional_settings)
1353
+ if self.flavor == 'win':
1354
+ env = self.GetMsvsToolchainEnv(
1355
+ additional_settings=additional_settings)
1356
+ return env
1357
+
1358
+ def GetMsvsToolchainEnv(self, additional_settings=None):
1359
+ """Returns the variables Visual Studio would set for build steps."""
1360
+ return self.msvs_settings.GetVSMacroEnv('$!PRODUCT_DIR',
1361
+ config=self.config_name)
1362
+
1363
+ def GetSortedXcodeEnv(self, additional_settings=None):
1364
+ """Returns the variables Xcode would set for build steps."""
1365
+ assert self.abs_build_dir
1366
+ abs_build_dir = self.abs_build_dir
1367
+ return gyp.xcode_emulation.GetSortedXcodeEnv(
1368
+ self.xcode_settings, abs_build_dir,
1369
+ os.path.join(abs_build_dir, self.build_to_base), self.config_name,
1370
+ additional_settings)
1371
+
1372
+ def GetSortedXcodePostbuildEnv(self):
1373
+ """Returns the variables Xcode would set for postbuild steps."""
1374
+ postbuild_settings = {}
1375
+ # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack.
1376
+ # TODO(thakis): It would be nice to have some general mechanism instead.
1377
+ strip_save_file = self.xcode_settings.GetPerTargetSetting(
1378
+ 'CHROMIUM_STRIP_SAVE_FILE')
1379
+ if strip_save_file:
1380
+ postbuild_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file
1381
+ return self.GetSortedXcodeEnv(additional_settings=postbuild_settings)
1382
+
1383
+ def AppendPostbuildVariable(self, variables, spec, output, binary,
1384
+ is_command_start=False):
1385
+ """Adds a 'postbuild' variable if there is a postbuild for |output|."""
1386
+ postbuild = self.GetPostbuildCommand(spec, output, binary, is_command_start)
1387
+ if postbuild:
1388
+ variables.append(('postbuilds', postbuild))
1389
+
1390
+ def GetPostbuildCommand(self, spec, output, output_binary, is_command_start):
1391
+ """Returns a shell command that runs all the postbuilds, and removes
1392
+ |output| if any of them fails. If |is_command_start| is False, then the
1393
+ returned string will start with ' && '."""
1394
+ if not self.xcode_settings or spec['type'] == 'none' or not output:
1395
+ return ''
1396
+ output = QuoteShellArgument(output, self.flavor)
1397
+ postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True)
1398
+ if output_binary is not None:
1399
+ postbuilds = self.xcode_settings.AddImplicitPostbuilds(
1400
+ self.config_name,
1401
+ os.path.normpath(os.path.join(self.base_to_build, output)),
1402
+ QuoteShellArgument(
1403
+ os.path.normpath(os.path.join(self.base_to_build, output_binary)),
1404
+ self.flavor),
1405
+ postbuilds, quiet=True)
1406
+
1407
+ if not postbuilds:
1408
+ return ''
1409
+ # Postbuilds expect to be run in the gyp file's directory, so insert an
1410
+ # implicit postbuild to cd to there.
1411
+ postbuilds.insert(0, gyp.common.EncodePOSIXShellList(
1412
+ ['cd', self.build_to_base]))
1413
+ env = self.ComputeExportEnvString(self.GetSortedXcodePostbuildEnv())
1414
+ # G will be non-null if any postbuild fails. Run all postbuilds in a
1415
+ # subshell.
1416
+ commands = env + ' (' + \
1417
+ ' && '.join([ninja_syntax.escape(command) for command in postbuilds])
1418
+ command_string = (commands + '); G=$$?; '
1419
+ # Remove the final output if any postbuild failed.
1420
+ '((exit $$G) || rm -rf %s) ' % output + '&& exit $$G)')
1421
+ if is_command_start:
1422
+ return '(' + command_string + ' && '
1423
+ else:
1424
+ return '$ && (' + command_string
1425
+
1426
+ def ComputeExportEnvString(self, env):
1427
+ """Given an environment, returns a string looking like
1428
+ 'export FOO=foo; export BAR="${FOO} bar;'
1429
+ that exports |env| to the shell."""
1430
+ export_str = []
1431
+ for k, v in env:
1432
+ export_str.append('export %s=%s;' %
1433
+ (k, ninja_syntax.escape(gyp.common.EncodePOSIXShellArgument(v))))
1434
+ return ' '.join(export_str)
1435
+
1436
+ def ComputeMacBundleOutput(self):
1437
+ """Return the 'output' (full output path) to a bundle output directory."""
1438
+ assert self.is_mac_bundle
1439
+ path = generator_default_variables['PRODUCT_DIR']
1440
+ return self.ExpandSpecial(
1441
+ os.path.join(path, self.xcode_settings.GetWrapperName()))
1442
+
1443
+ def ComputeOutputFileName(self, spec, type=None):
1444
+ """Compute the filename of the final output for the current target."""
1445
+ if not type:
1446
+ type = spec['type']
1447
+
1448
+ default_variables = copy.copy(generator_default_variables)
1449
+ CalculateVariables(default_variables, {'flavor': self.flavor})
1450
+
1451
+ # Compute filename prefix: the product prefix, or a default for
1452
+ # the product type.
1453
+ DEFAULT_PREFIX = {
1454
+ 'loadable_module': default_variables['SHARED_LIB_PREFIX'],
1455
+ 'shared_library': default_variables['SHARED_LIB_PREFIX'],
1456
+ 'static_library': default_variables['STATIC_LIB_PREFIX'],
1457
+ 'executable': default_variables['EXECUTABLE_PREFIX'],
1458
+ }
1459
+ prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(type, ''))
1460
+
1461
+ # Compute filename extension: the product extension, or a default
1462
+ # for the product type.
1463
+ DEFAULT_EXTENSION = {
1464
+ 'loadable_module': default_variables['SHARED_LIB_SUFFIX'],
1465
+ 'shared_library': default_variables['SHARED_LIB_SUFFIX'],
1466
+ 'static_library': default_variables['STATIC_LIB_SUFFIX'],
1467
+ 'executable': default_variables['EXECUTABLE_SUFFIX'],
1468
+ }
1469
+ extension = spec.get('product_extension')
1470
+ if extension:
1471
+ extension = '.' + extension
1472
+ else:
1473
+ extension = DEFAULT_EXTENSION.get(type, '')
1474
+
1475
+ if 'product_name' in spec:
1476
+ # If we were given an explicit name, use that.
1477
+ target = spec['product_name']
1478
+ else:
1479
+ # Otherwise, derive a name from the target name.
1480
+ target = spec['target_name']
1481
+ if prefix == 'lib':
1482
+ # Snip out an extra 'lib' from libs if appropriate.
1483
+ target = StripPrefix(target, 'lib')
1484
+
1485
+ if type in ('static_library', 'loadable_module', 'shared_library',
1486
+ 'executable'):
1487
+ return '%s%s%s' % (prefix, target, extension)
1488
+ elif type == 'none':
1489
+ return '%s.stamp' % target
1490
+ else:
1491
+ raise Exception('Unhandled output type %s' % type)
1492
+
1493
+ def ComputeOutput(self, spec, arch=None):
1494
+ """Compute the path for the final output of the spec."""
1495
+ type = spec['type']
1496
+
1497
+ if self.flavor == 'win':
1498
+ override = self.msvs_settings.GetOutputName(self.config_name,
1499
+ self.ExpandSpecial)
1500
+ if override:
1501
+ return override
1502
+
1503
+ if arch is None and self.flavor == 'mac' and type in (
1504
+ 'static_library', 'executable', 'shared_library', 'loadable_module'):
1505
+ filename = self.xcode_settings.GetExecutablePath()
1506
+ else:
1507
+ filename = self.ComputeOutputFileName(spec, type)
1508
+
1509
+ if arch is None and 'product_dir' in spec:
1510
+ path = os.path.join(spec['product_dir'], filename)
1511
+ return self.ExpandSpecial(path)
1512
+
1513
+ # Some products go into the output root, libraries go into shared library
1514
+ # dir, and everything else goes into the normal place.
1515
+ type_in_output_root = ['executable', 'loadable_module']
1516
+ if self.flavor == 'mac' and self.toolset == 'target':
1517
+ type_in_output_root += ['shared_library', 'static_library']
1518
+ elif self.flavor == 'win' and self.toolset == 'target':
1519
+ type_in_output_root += ['shared_library']
1520
+
1521
+ if arch is not None:
1522
+ # Make sure partial executables don't end up in a bundle or the regular
1523
+ # output directory.
1524
+ archdir = 'arch'
1525
+ if self.toolset != 'target':
1526
+ archdir = os.path.join('arch', '%s' % self.toolset)
1527
+ return os.path.join(archdir, AddArch(filename, arch))
1528
+ elif type in type_in_output_root or self.is_standalone_static_library:
1529
+ return filename
1530
+ elif type == 'shared_library':
1531
+ libdir = 'lib'
1532
+ if self.toolset != 'target':
1533
+ libdir = os.path.join('lib', '%s' % self.toolset)
1534
+ return os.path.join(libdir, filename)
1535
+ else:
1536
+ return self.GypPathToUniqueOutput(filename, qualified=False)
1537
+
1538
+ def WriteVariableList(self, ninja_file, var, values):
1539
+ assert not isinstance(values, str)
1540
+ if values is None:
1541
+ values = []
1542
+ ninja_file.variable(var, ' '.join(values))
1543
+
1544
+ def WriteNewNinjaRule(self, name, args, description, is_cygwin, env, pool,
1545
+ depfile=None):
1546
+ """Write out a new ninja "rule" statement for a given command.
1547
+
1548
+ Returns the name of the new rule, and a copy of |args| with variables
1549
+ expanded."""
1550
+
1551
+ if self.flavor == 'win':
1552
+ args = [self.msvs_settings.ConvertVSMacros(
1553
+ arg, self.base_to_build, config=self.config_name)
1554
+ for arg in args]
1555
+ description = self.msvs_settings.ConvertVSMacros(
1556
+ description, config=self.config_name)
1557
+ elif self.flavor == 'mac':
1558
+ # |env| is an empty list on non-mac.
1559
+ args = [gyp.xcode_emulation.ExpandEnvVars(arg, env) for arg in args]
1560
+ description = gyp.xcode_emulation.ExpandEnvVars(description, env)
1561
+
1562
+ # TODO: we shouldn't need to qualify names; we do it because
1563
+ # currently the ninja rule namespace is global, but it really
1564
+ # should be scoped to the subninja.
1565
+ rule_name = self.name
1566
+ if self.toolset == 'target':
1567
+ rule_name += '.' + self.toolset
1568
+ rule_name += '.' + name
1569
+ rule_name = re.sub('[^a-zA-Z0-9_]', '_', rule_name)
1570
+
1571
+ # Remove variable references, but not if they refer to the magic rule
1572
+ # variables. This is not quite right, as it also protects these for
1573
+ # actions, not just for rules where they are valid. Good enough.
1574
+ protect = [ '${root}', '${dirname}', '${source}', '${ext}', '${name}' ]
1575
+ protect = '(?!' + '|'.join(map(re.escape, protect)) + ')'
1576
+ description = re.sub(protect + r'\$', '_', description)
1577
+
1578
+ # gyp dictates that commands are run from the base directory.
1579
+ # cd into the directory before running, and adjust paths in
1580
+ # the arguments to point to the proper locations.
1581
+ rspfile = None
1582
+ rspfile_content = None
1583
+ args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args]
1584
+ if self.flavor == 'win':
1585
+ rspfile = rule_name + '.$unique_name.rsp'
1586
+ # The cygwin case handles this inside the bash sub-shell.
1587
+ run_in = '' if is_cygwin else ' ' + self.build_to_base
1588
+ if is_cygwin:
1589
+ rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine(
1590
+ args, self.build_to_base)
1591
+ else:
1592
+ rspfile_content = gyp.msvs_emulation.EncodeRspFileList(args)
1593
+ command = ('%s gyp-win-tool action-wrapper $arch ' % sys.executable +
1594
+ rspfile + run_in)
1595
+ else:
1596
+ env = self.ComputeExportEnvString(env)
1597
+ command = gyp.common.EncodePOSIXShellList(args)
1598
+ command = 'cd %s; ' % self.build_to_base + env + command
1599
+
1600
+ # GYP rules/actions express being no-ops by not touching their outputs.
1601
+ # Avoid executing downstream dependencies in this case by specifying
1602
+ # restat=1 to ninja.
1603
+ self.ninja.rule(rule_name, command, description, depfile=depfile,
1604
+ restat=True, pool=pool,
1605
+ rspfile=rspfile, rspfile_content=rspfile_content)
1606
+ self.ninja.newline()
1607
+
1608
+ return rule_name, args
1609
+
1610
+
1611
+ def CalculateVariables(default_variables, params):
1612
+ """Calculate additional variables for use in the build (called by gyp)."""
1613
+ global generator_additional_non_configuration_keys
1614
+ global generator_additional_path_sections
1615
+ flavor = gyp.common.GetFlavor(params)
1616
+ if flavor == 'mac':
1617
+ default_variables.setdefault('OS', 'mac')
1618
+ default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
1619
+ default_variables.setdefault('SHARED_LIB_DIR',
1620
+ generator_default_variables['PRODUCT_DIR'])
1621
+ default_variables.setdefault('LIB_DIR',
1622
+ generator_default_variables['PRODUCT_DIR'])
1623
+
1624
+ # Copy additional generator configuration data from Xcode, which is shared
1625
+ # by the Mac Ninja generator.
1626
+ import gyp.generator.xcode as xcode_generator
1627
+ generator_additional_non_configuration_keys = getattr(xcode_generator,
1628
+ 'generator_additional_non_configuration_keys', [])
1629
+ generator_additional_path_sections = getattr(xcode_generator,
1630
+ 'generator_additional_path_sections', [])
1631
+ global generator_extra_sources_for_rules
1632
+ generator_extra_sources_for_rules = getattr(xcode_generator,
1633
+ 'generator_extra_sources_for_rules', [])
1634
+ elif flavor == 'win':
1635
+ exts = gyp.MSVSUtil.TARGET_TYPE_EXT
1636
+ default_variables.setdefault('OS', 'win')
1637
+ default_variables['EXECUTABLE_SUFFIX'] = '.' + exts['executable']
1638
+ default_variables['STATIC_LIB_PREFIX'] = ''
1639
+ default_variables['STATIC_LIB_SUFFIX'] = '.' + exts['static_library']
1640
+ default_variables['SHARED_LIB_PREFIX'] = ''
1641
+ default_variables['SHARED_LIB_SUFFIX'] = '.' + exts['shared_library']
1642
+
1643
+ # Copy additional generator configuration data from VS, which is shared
1644
+ # by the Windows Ninja generator.
1645
+ import gyp.generator.msvs as msvs_generator
1646
+ generator_additional_non_configuration_keys = getattr(msvs_generator,
1647
+ 'generator_additional_non_configuration_keys', [])
1648
+ generator_additional_path_sections = getattr(msvs_generator,
1649
+ 'generator_additional_path_sections', [])
1650
+
1651
+ gyp.msvs_emulation.CalculateCommonVariables(default_variables, params)
1652
+ else:
1653
+ operating_system = flavor
1654
+ if flavor == 'android':
1655
+ operating_system = 'linux' # Keep this legacy behavior for now.
1656
+ default_variables.setdefault('OS', operating_system)
1657
+ default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
1658
+ default_variables.setdefault('SHARED_LIB_DIR',
1659
+ os.path.join('$!PRODUCT_DIR', 'lib'))
1660
+ default_variables.setdefault('LIB_DIR',
1661
+ os.path.join('$!PRODUCT_DIR', 'obj'))
1662
+
1663
+ def ComputeOutputDir(params):
1664
+ """Returns the path from the toplevel_dir to the build output directory."""
1665
+ # generator_dir: relative path from pwd to where make puts build files.
1666
+ # Makes migrating from make to ninja easier, ninja doesn't put anything here.
1667
+ generator_dir = os.path.relpath(params['options'].generator_output or '.')
1668
+
1669
+ # output_dir: relative path from generator_dir to the build directory.
1670
+ output_dir = params.get('generator_flags', {}).get('output_dir', 'out')
1671
+
1672
+ # Relative path from source root to our output files. e.g. "out"
1673
+ return os.path.normpath(os.path.join(generator_dir, output_dir))
1674
+
1675
+
1676
+ def CalculateGeneratorInputInfo(params):
1677
+ """Called by __init__ to initialize generator values based on params."""
1678
+ # E.g. "out/gypfiles"
1679
+ toplevel = params['options'].toplevel_dir
1680
+ qualified_out_dir = os.path.normpath(os.path.join(
1681
+ toplevel, ComputeOutputDir(params), 'gypfiles'))
1682
+
1683
+ global generator_filelist_paths
1684
+ generator_filelist_paths = {
1685
+ 'toplevel': toplevel,
1686
+ 'qualified_out_dir': qualified_out_dir,
1687
+ }
1688
+
1689
+
1690
+ def OpenOutput(path, mode='w'):
1691
+ """Open |path| for writing, creating directories if necessary."""
1692
+ gyp.common.EnsureDirExists(path)
1693
+ return open(path, mode)
1694
+
1695
+
1696
+ def CommandWithWrapper(cmd, wrappers, prog):
1697
+ wrapper = wrappers.get(cmd, '')
1698
+ if wrapper:
1699
+ return wrapper + ' ' + prog
1700
+ return prog
1701
+
1702
+
1703
+ def GetDefaultConcurrentLinks():
1704
+ """Returns a best-guess for a number of concurrent links."""
1705
+ pool_size = int(os.environ.get('GYP_LINK_CONCURRENCY', 0))
1706
+ if pool_size:
1707
+ return pool_size
1708
+
1709
+ if sys.platform in ('win32', 'cygwin'):
1710
+ import ctypes
1711
+
1712
+ class MEMORYSTATUSEX(ctypes.Structure):
1713
+ _fields_ = [
1714
+ ("dwLength", ctypes.c_ulong),
1715
+ ("dwMemoryLoad", ctypes.c_ulong),
1716
+ ("ullTotalPhys", ctypes.c_ulonglong),
1717
+ ("ullAvailPhys", ctypes.c_ulonglong),
1718
+ ("ullTotalPageFile", ctypes.c_ulonglong),
1719
+ ("ullAvailPageFile", ctypes.c_ulonglong),
1720
+ ("ullTotalVirtual", ctypes.c_ulonglong),
1721
+ ("ullAvailVirtual", ctypes.c_ulonglong),
1722
+ ("sullAvailExtendedVirtual", ctypes.c_ulonglong),
1723
+ ]
1724
+
1725
+ stat = MEMORYSTATUSEX()
1726
+ stat.dwLength = ctypes.sizeof(stat)
1727
+ ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))
1728
+
1729
+ # VS 2015 uses 20% more working set than VS 2013 and can consume all RAM
1730
+ # on a 64 GB machine.
1731
+ mem_limit = max(1, stat.ullTotalPhys / (5 * (2 ** 30))) # total / 5GB
1732
+ hard_cap = max(1, int(os.environ.get('GYP_LINK_CONCURRENCY_MAX', 2**32)))
1733
+ return min(mem_limit, hard_cap)
1734
+ elif sys.platform.startswith('linux'):
1735
+ if os.path.exists("/proc/meminfo"):
1736
+ with open("/proc/meminfo") as meminfo:
1737
+ memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB')
1738
+ for line in meminfo:
1739
+ match = memtotal_re.match(line)
1740
+ if not match:
1741
+ continue
1742
+ # Allow 8Gb per link on Linux because Gold is quite memory hungry
1743
+ return max(1, int(match.group(1)) / (8 * (2 ** 20)))
1744
+ return 1
1745
+ elif sys.platform == 'darwin':
1746
+ try:
1747
+ avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize']))
1748
+ # A static library debug build of Chromium's unit_tests takes ~2.7GB, so
1749
+ # 4GB per ld process allows for some more bloat.
1750
+ return max(1, avail_bytes / (4 * (2 ** 30))) # total / 4GB
1751
+ except:
1752
+ return 1
1753
+ else:
1754
+ # TODO(scottmg): Implement this for other platforms.
1755
+ return 1
1756
+
1757
+
1758
+ def _GetWinLinkRuleNameSuffix(embed_manifest):
1759
+ """Returns the suffix used to select an appropriate linking rule depending on
1760
+ whether the manifest embedding is enabled."""
1761
+ return '_embed' if embed_manifest else ''
1762
+
1763
+
1764
+ def _AddWinLinkRules(master_ninja, embed_manifest):
1765
+ """Adds link rules for Windows platform to |master_ninja|."""
1766
+ def FullLinkCommand(ldcmd, out, binary_type):
1767
+ resource_name = {
1768
+ 'exe': '1',
1769
+ 'dll': '2',
1770
+ }[binary_type]
1771
+ return '%(python)s gyp-win-tool link-with-manifests $arch %(embed)s ' \
1772
+ '%(out)s "%(ldcmd)s" %(resname)s $mt $rc "$intermediatemanifest" ' \
1773
+ '$manifests' % {
1774
+ 'python': sys.executable,
1775
+ 'out': out,
1776
+ 'ldcmd': ldcmd,
1777
+ 'resname': resource_name,
1778
+ 'embed': embed_manifest }
1779
+ rule_name_suffix = _GetWinLinkRuleNameSuffix(embed_manifest)
1780
+ use_separate_mspdbsrv = (
1781
+ int(os.environ.get('GYP_USE_SEPARATE_MSPDBSRV', '0')) != 0)
1782
+ dlldesc = 'LINK%s(DLL) $binary' % rule_name_suffix.upper()
1783
+ dllcmd = ('%s gyp-win-tool link-wrapper $arch %s '
1784
+ '$ld /nologo $implibflag /DLL /OUT:$binary '
1785
+ '@$binary.rsp' % (sys.executable, use_separate_mspdbsrv))
1786
+ dllcmd = FullLinkCommand(dllcmd, '$binary', 'dll')
1787
+ master_ninja.rule('solink' + rule_name_suffix,
1788
+ description=dlldesc, command=dllcmd,
1789
+ rspfile='$binary.rsp',
1790
+ rspfile_content='$libs $in_newline $ldflags',
1791
+ restat=True,
1792
+ pool='link_pool')
1793
+ master_ninja.rule('solink_module' + rule_name_suffix,
1794
+ description=dlldesc, command=dllcmd,
1795
+ rspfile='$binary.rsp',
1796
+ rspfile_content='$libs $in_newline $ldflags',
1797
+ restat=True,
1798
+ pool='link_pool')
1799
+ # Note that ldflags goes at the end so that it has the option of
1800
+ # overriding default settings earlier in the command line.
1801
+ exe_cmd = ('%s gyp-win-tool link-wrapper $arch %s '
1802
+ '$ld /nologo /OUT:$binary @$binary.rsp' %
1803
+ (sys.executable, use_separate_mspdbsrv))
1804
+ exe_cmd = FullLinkCommand(exe_cmd, '$binary', 'exe')
1805
+ master_ninja.rule('link' + rule_name_suffix,
1806
+ description='LINK%s $binary' % rule_name_suffix.upper(),
1807
+ command=exe_cmd,
1808
+ rspfile='$binary.rsp',
1809
+ rspfile_content='$in_newline $libs $ldflags',
1810
+ pool='link_pool')
1811
+
1812
+
1813
+ def GenerateOutputForConfig(target_list, target_dicts, data, params,
1814
+ config_name):
1815
+ options = params['options']
1816
+ flavor = gyp.common.GetFlavor(params)
1817
+ generator_flags = params.get('generator_flags', {})
1818
+
1819
+ # build_dir: relative path from source root to our output files.
1820
+ # e.g. "out/Debug"
1821
+ build_dir = os.path.normpath(
1822
+ os.path.join(ComputeOutputDir(params), config_name))
1823
+
1824
+ toplevel_build = os.path.join(options.toplevel_dir, build_dir)
1825
+
1826
+ master_ninja_file = OpenOutput(os.path.join(toplevel_build, 'build.ninja'))
1827
+ master_ninja = ninja_syntax.Writer(master_ninja_file, width=120)
1828
+
1829
+ # Put build-time support tools in out/{config_name}.
1830
+ gyp.common.CopyTool(flavor, toplevel_build)
1831
+
1832
+ # Grab make settings for CC/CXX.
1833
+ # The rules are
1834
+ # - The priority from low to high is gcc/g++, the 'make_global_settings' in
1835
+ # gyp, the environment variable.
1836
+ # - If there is no 'make_global_settings' for CC.host/CXX.host or
1837
+ # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set
1838
+ # to cc/cxx.
1839
+ if flavor == 'win':
1840
+ ar = 'lib.exe'
1841
+ # cc and cxx must be set to the correct architecture by overriding with one
1842
+ # of cl_x86 or cl_x64 below.
1843
+ cc = 'UNSET'
1844
+ cxx = 'UNSET'
1845
+ ld = 'link.exe'
1846
+ ld_host = '$ld'
1847
+ else:
1848
+ ar = 'ar'
1849
+ cc = 'cc'
1850
+ cxx = 'c++'
1851
+ ld = '$cc'
1852
+ ldxx = '$cxx'
1853
+ ld_host = '$cc_host'
1854
+ ldxx_host = '$cxx_host'
1855
+
1856
+ ar_host = ar
1857
+ cc_host = None
1858
+ cxx_host = None
1859
+ cc_host_global_setting = None
1860
+ cxx_host_global_setting = None
1861
+ clang_cl = None
1862
+ nm = 'nm'
1863
+ nm_host = 'nm'
1864
+ readelf = 'readelf'
1865
+ readelf_host = 'readelf'
1866
+
1867
+ build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
1868
+ make_global_settings = data[build_file].get('make_global_settings', [])
1869
+ build_to_root = gyp.common.InvertRelativePath(build_dir,
1870
+ options.toplevel_dir)
1871
+ wrappers = {}
1872
+ for key, value in make_global_settings:
1873
+ if key == 'AR':
1874
+ ar = os.path.join(build_to_root, value)
1875
+ if key == 'AR.host':
1876
+ ar_host = os.path.join(build_to_root, value)
1877
+ if key == 'CC':
1878
+ cc = os.path.join(build_to_root, value)
1879
+ if cc.endswith('clang-cl'):
1880
+ clang_cl = cc
1881
+ if key == 'CXX':
1882
+ cxx = os.path.join(build_to_root, value)
1883
+ if key == 'CC.host':
1884
+ cc_host = os.path.join(build_to_root, value)
1885
+ cc_host_global_setting = value
1886
+ if key == 'CXX.host':
1887
+ cxx_host = os.path.join(build_to_root, value)
1888
+ cxx_host_global_setting = value
1889
+ if key == 'LD':
1890
+ ld = os.path.join(build_to_root, value)
1891
+ if key == 'LD.host':
1892
+ ld_host = os.path.join(build_to_root, value)
1893
+ if key == 'NM':
1894
+ nm = os.path.join(build_to_root, value)
1895
+ if key == 'NM.host':
1896
+ nm_host = os.path.join(build_to_root, value)
1897
+ if key == 'READELF':
1898
+ readelf = os.path.join(build_to_root, value)
1899
+ if key == 'READELF.host':
1900
+ readelf_host = os.path.join(build_to_root, value)
1901
+ if key.endswith('_wrapper'):
1902
+ wrappers[key[:-len('_wrapper')]] = os.path.join(build_to_root, value)
1903
+
1904
+ # Support wrappers from environment variables too.
1905
+ for key, value in os.environ.iteritems():
1906
+ if key.lower().endswith('_wrapper'):
1907
+ key_prefix = key[:-len('_wrapper')]
1908
+ key_prefix = re.sub(r'\.HOST$', '.host', key_prefix)
1909
+ wrappers[key_prefix] = os.path.join(build_to_root, value)
1910
+
1911
+ if flavor == 'win':
1912
+ configs = [target_dicts[qualified_target]['configurations'][config_name]
1913
+ for qualified_target in target_list]
1914
+ shared_system_includes = None
1915
+ if not generator_flags.get('ninja_use_custom_environment_files', 0):
1916
+ shared_system_includes = \
1917
+ gyp.msvs_emulation.ExtractSharedMSVSSystemIncludes(
1918
+ configs, generator_flags)
1919
+ cl_paths = gyp.msvs_emulation.GenerateEnvironmentFiles(
1920
+ toplevel_build, generator_flags, shared_system_includes, OpenOutput)
1921
+ for arch, path in sorted(cl_paths.iteritems()):
1922
+ if clang_cl:
1923
+ # If we have selected clang-cl, use that instead.
1924
+ path = clang_cl
1925
+ command = CommandWithWrapper('CC', wrappers,
1926
+ QuoteShellArgument(path, 'win'))
1927
+ if clang_cl:
1928
+ # Use clang-cl to cross-compile for x86 or x86_64.
1929
+ command += (' -m32' if arch == 'x86' else ' -m64')
1930
+ master_ninja.variable('cl_' + arch, command)
1931
+
1932
+ cc = GetEnvironFallback(['CC_target', 'CC'], cc)
1933
+ master_ninja.variable('cc', CommandWithWrapper('CC', wrappers, cc))
1934
+ cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx)
1935
+ master_ninja.variable('cxx', CommandWithWrapper('CXX', wrappers, cxx))
1936
+
1937
+ if flavor == 'win':
1938
+ master_ninja.variable('ld', ld)
1939
+ master_ninja.variable('idl', 'midl.exe')
1940
+ master_ninja.variable('ar', ar)
1941
+ master_ninja.variable('rc', 'rc.exe')
1942
+ master_ninja.variable('ml_x86', 'ml.exe')
1943
+ master_ninja.variable('ml_x64', 'ml64.exe')
1944
+ master_ninja.variable('mt', 'mt.exe')
1945
+ else:
1946
+ master_ninja.variable('ld', CommandWithWrapper('LINK', wrappers, ld))
1947
+ master_ninja.variable('ldxx', CommandWithWrapper('LINK', wrappers, ldxx))
1948
+ master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], ar))
1949
+ if flavor != 'mac':
1950
+ # Mac does not use readelf/nm for .TOC generation, so avoiding polluting
1951
+ # the master ninja with extra unused variables.
1952
+ master_ninja.variable(
1953
+ 'nm', GetEnvironFallback(['NM_target', 'NM'], nm))
1954
+ master_ninja.variable(
1955
+ 'readelf', GetEnvironFallback(['READELF_target', 'READELF'], readelf))
1956
+
1957
+ if generator_supports_multiple_toolsets:
1958
+ if not cc_host:
1959
+ cc_host = cc
1960
+ if not cxx_host:
1961
+ cxx_host = cxx
1962
+
1963
+ master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], ar_host))
1964
+ master_ninja.variable('nm_host', GetEnvironFallback(['NM_host'], nm_host))
1965
+ master_ninja.variable('readelf_host',
1966
+ GetEnvironFallback(['READELF_host'], readelf_host))
1967
+ cc_host = GetEnvironFallback(['CC_host'], cc_host)
1968
+ cxx_host = GetEnvironFallback(['CXX_host'], cxx_host)
1969
+
1970
+ # The environment variable could be used in 'make_global_settings', like
1971
+ # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here.
1972
+ if '$(CC)' in cc_host and cc_host_global_setting:
1973
+ cc_host = cc_host_global_setting.replace('$(CC)', cc)
1974
+ if '$(CXX)' in cxx_host and cxx_host_global_setting:
1975
+ cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx)
1976
+ master_ninja.variable('cc_host',
1977
+ CommandWithWrapper('CC.host', wrappers, cc_host))
1978
+ master_ninja.variable('cxx_host',
1979
+ CommandWithWrapper('CXX.host', wrappers, cxx_host))
1980
+ if flavor == 'win':
1981
+ master_ninja.variable('ld_host', ld_host)
1982
+ else:
1983
+ master_ninja.variable('ld_host', CommandWithWrapper(
1984
+ 'LINK', wrappers, ld_host))
1985
+ master_ninja.variable('ldxx_host', CommandWithWrapper(
1986
+ 'LINK', wrappers, ldxx_host))
1987
+
1988
+ master_ninja.newline()
1989
+
1990
+ master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks())
1991
+ master_ninja.newline()
1992
+
1993
+ deps = 'msvc' if flavor == 'win' else 'gcc'
1994
+
1995
+ if flavor != 'win':
1996
+ master_ninja.rule(
1997
+ 'cc',
1998
+ description='CC $out',
1999
+ command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
2000
+ '$cflags_pch_c -c $in -o $out'),
2001
+ depfile='$out.d',
2002
+ deps=deps)
2003
+ master_ninja.rule(
2004
+ 'cc_s',
2005
+ description='CC $out',
2006
+ command=('$cc $defines $includes $cflags $cflags_c '
2007
+ '$cflags_pch_c -c $in -o $out'))
2008
+ master_ninja.rule(
2009
+ 'cxx',
2010
+ description='CXX $out',
2011
+ command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
2012
+ '$cflags_pch_cc -c $in -o $out'),
2013
+ depfile='$out.d',
2014
+ deps=deps)
2015
+ else:
2016
+ # TODO(scottmg) Separate pdb names is a test to see if it works around
2017
+ # http://crbug.com/142362. It seems there's a race between the creation of
2018
+ # the .pdb by the precompiled header step for .cc and the compilation of
2019
+ # .c files. This should be handled by mspdbsrv, but rarely errors out with
2020
+ # c1xx : fatal error C1033: cannot open program database
2021
+ # By making the rules target separate pdb files this might be avoided.
2022
+ cc_command = ('ninja -t msvc -e $arch ' +
2023
+ '-- '
2024
+ '$cc /nologo /showIncludes /FC '
2025
+ '@$out.rsp /c $in /Fo$out /Fd$pdbname_c ')
2026
+ cxx_command = ('ninja -t msvc -e $arch ' +
2027
+ '-- '
2028
+ '$cxx /nologo /showIncludes /FC '
2029
+ '@$out.rsp /c $in /Fo$out /Fd$pdbname_cc ')
2030
+ master_ninja.rule(
2031
+ 'cc',
2032
+ description='CC $out',
2033
+ command=cc_command,
2034
+ rspfile='$out.rsp',
2035
+ rspfile_content='$defines $includes $cflags $cflags_c',
2036
+ deps=deps)
2037
+ master_ninja.rule(
2038
+ 'cxx',
2039
+ description='CXX $out',
2040
+ command=cxx_command,
2041
+ rspfile='$out.rsp',
2042
+ rspfile_content='$defines $includes $cflags $cflags_cc',
2043
+ deps=deps)
2044
+ master_ninja.rule(
2045
+ 'idl',
2046
+ description='IDL $in',
2047
+ command=('%s gyp-win-tool midl-wrapper $arch $outdir '
2048
+ '$tlb $h $dlldata $iid $proxy $in '
2049
+ '$midl_includes $idlflags' % sys.executable))
2050
+ master_ninja.rule(
2051
+ 'rc',
2052
+ description='RC $in',
2053
+ # Note: $in must be last otherwise rc.exe complains.
2054
+ command=('%s gyp-win-tool rc-wrapper '
2055
+ '$arch $rc $defines $resource_includes $rcflags /fo$out $in' %
2056
+ sys.executable))
2057
+ master_ninja.rule(
2058
+ 'asm',
2059
+ description='ASM $out',
2060
+ command=('%s gyp-win-tool asm-wrapper '
2061
+ '$arch $asm $defines $includes $asmflags /c /Fo $out $in' %
2062
+ sys.executable))
2063
+
2064
+ if flavor != 'mac' and flavor != 'win':
2065
+ master_ninja.rule(
2066
+ 'alink',
2067
+ description='AR $out',
2068
+ command='rm -f $out && $ar rcs $arflags $out $in')
2069
+ master_ninja.rule(
2070
+ 'alink_thin',
2071
+ description='AR $out',
2072
+ command='rm -f $out && $ar rcsT $arflags $out $in')
2073
+
2074
+ # This allows targets that only need to depend on $lib's API to declare an
2075
+ # order-only dependency on $lib.TOC and avoid relinking such downstream
2076
+ # dependencies when $lib changes only in non-public ways.
2077
+ # The resulting string leaves an uninterpolated %{suffix} which
2078
+ # is used in the final substitution below.
2079
+ mtime_preserving_solink_base = (
2080
+ 'if [ ! -e $lib -o ! -e $lib.TOC ]; then '
2081
+ '%(solink)s && %(extract_toc)s > $lib.TOC; else '
2082
+ '%(solink)s && %(extract_toc)s > $lib.tmp && '
2083
+ 'if ! cmp -s $lib.tmp $lib.TOC; then mv $lib.tmp $lib.TOC ; '
2084
+ 'fi; fi'
2085
+ % { 'solink':
2086
+ '$ld -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s',
2087
+ 'extract_toc':
2088
+ ('{ $readelf -d $lib | grep SONAME ; '
2089
+ '$nm -gD -f p $lib | cut -f1-2 -d\' \'; }')})
2090
+
2091
+ master_ninja.rule(
2092
+ 'solink',
2093
+ description='SOLINK $lib',
2094
+ restat=True,
2095
+ command=mtime_preserving_solink_base % {'suffix': '@$link_file_list'},
2096
+ rspfile='$link_file_list',
2097
+ rspfile_content=
2098
+ '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive $libs',
2099
+ pool='link_pool')
2100
+ master_ninja.rule(
2101
+ 'solink_module',
2102
+ description='SOLINK(module) $lib',
2103
+ restat=True,
2104
+ command=mtime_preserving_solink_base % {'suffix': '@$link_file_list'},
2105
+ rspfile='$link_file_list',
2106
+ rspfile_content='-Wl,--start-group $in -Wl,--end-group $solibs $libs',
2107
+ pool='link_pool')
2108
+ master_ninja.rule(
2109
+ 'link',
2110
+ description='LINK $out',
2111
+ command=('$ld $ldflags -o $out '
2112
+ '-Wl,--start-group $in -Wl,--end-group $solibs $libs'),
2113
+ pool='link_pool')
2114
+ elif flavor == 'win':
2115
+ master_ninja.rule(
2116
+ 'alink',
2117
+ description='LIB $out',
2118
+ command=('%s gyp-win-tool link-wrapper $arch False '
2119
+ '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' %
2120
+ sys.executable),
2121
+ rspfile='$out.rsp',
2122
+ rspfile_content='$in_newline $libflags')
2123
+ _AddWinLinkRules(master_ninja, embed_manifest=True)
2124
+ _AddWinLinkRules(master_ninja, embed_manifest=False)
2125
+ else:
2126
+ master_ninja.rule(
2127
+ 'objc',
2128
+ description='OBJC $out',
2129
+ command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
2130
+ '$cflags_pch_objc -c $in -o $out'),
2131
+ depfile='$out.d',
2132
+ deps=deps)
2133
+ master_ninja.rule(
2134
+ 'objcxx',
2135
+ description='OBJCXX $out',
2136
+ command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc '
2137
+ '$cflags_pch_objcc -c $in -o $out'),
2138
+ depfile='$out.d',
2139
+ deps=deps)
2140
+ master_ninja.rule(
2141
+ 'alink',
2142
+ description='LIBTOOL-STATIC $out, POSTBUILDS',
2143
+ command='rm -f $out && '
2144
+ './gyp-mac-tool filter-libtool libtool $libtool_flags '
2145
+ '-static -o $out $in'
2146
+ '$postbuilds')
2147
+ master_ninja.rule(
2148
+ 'lipo',
2149
+ description='LIPO $out, POSTBUILDS',
2150
+ command='rm -f $out && lipo -create $in -output $out$postbuilds')
2151
+ master_ninja.rule(
2152
+ 'solipo',
2153
+ description='SOLIPO $out, POSTBUILDS',
2154
+ command=(
2155
+ 'rm -f $lib $lib.TOC && lipo -create $in -output $lib$postbuilds &&'
2156
+ '%(extract_toc)s > $lib.TOC'
2157
+ % { 'extract_toc':
2158
+ '{ otool -l $lib | grep LC_ID_DYLIB -A 5; '
2159
+ 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'}))
2160
+
2161
+
2162
+ # Record the public interface of $lib in $lib.TOC. See the corresponding
2163
+ # comment in the posix section above for details.
2164
+ solink_base = '$ld %(type)s $ldflags -o $lib %(suffix)s'
2165
+ mtime_preserving_solink_base = (
2166
+ 'if [ ! -e $lib -o ! -e $lib.TOC ] || '
2167
+ # Always force dependent targets to relink if this library
2168
+ # reexports something. Handling this correctly would require
2169
+ # recursive TOC dumping but this is rare in practice, so punt.
2170
+ 'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then '
2171
+ '%(solink)s && %(extract_toc)s > $lib.TOC; '
2172
+ 'else '
2173
+ '%(solink)s && %(extract_toc)s > $lib.tmp && '
2174
+ 'if ! cmp -s $lib.tmp $lib.TOC; then '
2175
+ 'mv $lib.tmp $lib.TOC ; '
2176
+ 'fi; '
2177
+ 'fi'
2178
+ % { 'solink': solink_base,
2179
+ 'extract_toc':
2180
+ '{ otool -l $lib | grep LC_ID_DYLIB -A 5; '
2181
+ 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'})
2182
+
2183
+
2184
+ solink_suffix = '@$link_file_list$postbuilds'
2185
+ master_ninja.rule(
2186
+ 'solink',
2187
+ description='SOLINK $lib, POSTBUILDS',
2188
+ restat=True,
2189
+ command=mtime_preserving_solink_base % {'suffix': solink_suffix,
2190
+ 'type': '-shared'},
2191
+ rspfile='$link_file_list',
2192
+ rspfile_content='$in $solibs $libs',
2193
+ pool='link_pool')
2194
+ master_ninja.rule(
2195
+ 'solink_notoc',
2196
+ description='SOLINK $lib, POSTBUILDS',
2197
+ restat=True,
2198
+ command=solink_base % {'suffix':solink_suffix, 'type': '-shared'},
2199
+ rspfile='$link_file_list',
2200
+ rspfile_content='$in $solibs $libs',
2201
+ pool='link_pool')
2202
+
2203
+ master_ninja.rule(
2204
+ 'solink_module',
2205
+ description='SOLINK(module) $lib, POSTBUILDS',
2206
+ restat=True,
2207
+ command=mtime_preserving_solink_base % {'suffix': solink_suffix,
2208
+ 'type': '-bundle'},
2209
+ rspfile='$link_file_list',
2210
+ rspfile_content='$in $solibs $libs',
2211
+ pool='link_pool')
2212
+ master_ninja.rule(
2213
+ 'solink_module_notoc',
2214
+ description='SOLINK(module) $lib, POSTBUILDS',
2215
+ restat=True,
2216
+ command=solink_base % {'suffix': solink_suffix, 'type': '-bundle'},
2217
+ rspfile='$link_file_list',
2218
+ rspfile_content='$in $solibs $libs',
2219
+ pool='link_pool')
2220
+
2221
+ master_ninja.rule(
2222
+ 'link',
2223
+ description='LINK $out, POSTBUILDS',
2224
+ command=('$ld $ldflags -o $out '
2225
+ '$in $solibs $libs$postbuilds'),
2226
+ pool='link_pool')
2227
+ master_ninja.rule(
2228
+ 'preprocess_infoplist',
2229
+ description='PREPROCESS INFOPLIST $out',
2230
+ command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && '
2231
+ 'plutil -convert xml1 $out $out'))
2232
+ master_ninja.rule(
2233
+ 'copy_infoplist',
2234
+ description='COPY INFOPLIST $in',
2235
+ command='$env ./gyp-mac-tool copy-info-plist $in $out $binary $keys')
2236
+ master_ninja.rule(
2237
+ 'merge_infoplist',
2238
+ description='MERGE INFOPLISTS $in',
2239
+ command='$env ./gyp-mac-tool merge-info-plist $out $in')
2240
+ master_ninja.rule(
2241
+ 'compile_xcassets',
2242
+ description='COMPILE XCASSETS $in',
2243
+ command='$env ./gyp-mac-tool compile-xcassets $keys $in')
2244
+ master_ninja.rule(
2245
+ 'mac_tool',
2246
+ description='MACTOOL $mactool_cmd $in',
2247
+ command='$env ./gyp-mac-tool $mactool_cmd $in $out $binary')
2248
+ master_ninja.rule(
2249
+ 'package_framework',
2250
+ description='PACKAGE FRAMEWORK $out, POSTBUILDS',
2251
+ command='./gyp-mac-tool package-framework $out $version$postbuilds '
2252
+ '&& touch $out')
2253
+ if flavor == 'win':
2254
+ master_ninja.rule(
2255
+ 'stamp',
2256
+ description='STAMP $out',
2257
+ command='%s gyp-win-tool stamp $out' % sys.executable)
2258
+ master_ninja.rule(
2259
+ 'copy',
2260
+ description='COPY $in $out',
2261
+ command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable)
2262
+ else:
2263
+ master_ninja.rule(
2264
+ 'stamp',
2265
+ description='STAMP $out',
2266
+ command='${postbuilds}touch $out')
2267
+ master_ninja.rule(
2268
+ 'copy',
2269
+ description='COPY $in $out',
2270
+ command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)')
2271
+ master_ninja.newline()
2272
+
2273
+ all_targets = set()
2274
+ for build_file in params['build_files']:
2275
+ for target in gyp.common.AllTargets(target_list,
2276
+ target_dicts,
2277
+ os.path.normpath(build_file)):
2278
+ all_targets.add(target)
2279
+ all_outputs = set()
2280
+
2281
+ # target_outputs is a map from qualified target name to a Target object.
2282
+ target_outputs = {}
2283
+ # target_short_names is a map from target short name to a list of Target
2284
+ # objects.
2285
+ target_short_names = {}
2286
+
2287
+ # short name of targets that were skipped because they didn't contain anything
2288
+ # interesting.
2289
+ # NOTE: there may be overlap between this an non_empty_target_names.
2290
+ empty_target_names = set()
2291
+
2292
+ # Set of non-empty short target names.
2293
+ # NOTE: there may be overlap between this an empty_target_names.
2294
+ non_empty_target_names = set()
2295
+
2296
+ for qualified_target in target_list:
2297
+ # qualified_target is like: third_party/icu/icu.gyp:icui18n#target
2298
+ build_file, name, toolset = \
2299
+ gyp.common.ParseQualifiedTarget(qualified_target)
2300
+
2301
+ this_make_global_settings = data[build_file].get('make_global_settings', [])
2302
+ assert make_global_settings == this_make_global_settings, (
2303
+ "make_global_settings needs to be the same for all targets. %s vs. %s" %
2304
+ (this_make_global_settings, make_global_settings))
2305
+
2306
+ spec = target_dicts[qualified_target]
2307
+ if flavor == 'mac':
2308
+ gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec)
2309
+
2310
+ # If build_file is a symlink, we must not follow it because there's a chance
2311
+ # it could point to a path above toplevel_dir, and we cannot correctly deal
2312
+ # with that case at the moment.
2313
+ build_file = gyp.common.RelativePath(build_file, options.toplevel_dir,
2314
+ False)
2315
+
2316
+ qualified_target_for_hash = gyp.common.QualifiedTarget(build_file, name,
2317
+ toolset)
2318
+ hash_for_rules = hashlib.md5(qualified_target_for_hash).hexdigest()
2319
+
2320
+ base_path = os.path.dirname(build_file)
2321
+ obj = 'obj'
2322
+ if toolset != 'target':
2323
+ obj += '.' + toolset
2324
+ output_file = os.path.join(obj, base_path, name + '.ninja')
2325
+
2326
+ ninja_output = StringIO()
2327
+ writer = NinjaWriter(hash_for_rules, target_outputs, base_path, build_dir,
2328
+ ninja_output,
2329
+ toplevel_build, output_file,
2330
+ flavor, toplevel_dir=options.toplevel_dir)
2331
+
2332
+ target = writer.WriteSpec(spec, config_name, generator_flags)
2333
+
2334
+ if ninja_output.tell() > 0:
2335
+ # Only create files for ninja files that actually have contents.
2336
+ with OpenOutput(os.path.join(toplevel_build, output_file)) as ninja_file:
2337
+ ninja_file.write(ninja_output.getvalue())
2338
+ ninja_output.close()
2339
+ master_ninja.subninja(output_file)
2340
+
2341
+ if target:
2342
+ if name != target.FinalOutput() and spec['toolset'] == 'target':
2343
+ target_short_names.setdefault(name, []).append(target)
2344
+ target_outputs[qualified_target] = target
2345
+ if qualified_target in all_targets:
2346
+ all_outputs.add(target.FinalOutput())
2347
+ non_empty_target_names.add(name)
2348
+ else:
2349
+ empty_target_names.add(name)
2350
+
2351
+ if target_short_names:
2352
+ # Write a short name to build this target. This benefits both the
2353
+ # "build chrome" case as well as the gyp tests, which expect to be
2354
+ # able to run actions and build libraries by their short name.
2355
+ master_ninja.newline()
2356
+ master_ninja.comment('Short names for targets.')
2357
+ for short_name in sorted(target_short_names):
2358
+ master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in
2359
+ target_short_names[short_name]])
2360
+
2361
+ # Write phony targets for any empty targets that weren't written yet. As
2362
+ # short names are not necessarily unique only do this for short names that
2363
+ # haven't already been output for another target.
2364
+ empty_target_names = empty_target_names - non_empty_target_names
2365
+ if empty_target_names:
2366
+ master_ninja.newline()
2367
+ master_ninja.comment('Empty targets (output for completeness).')
2368
+ for name in sorted(empty_target_names):
2369
+ master_ninja.build(name, 'phony')
2370
+
2371
+ if all_outputs:
2372
+ master_ninja.newline()
2373
+ master_ninja.build('all', 'phony', sorted(all_outputs))
2374
+ master_ninja.default(generator_flags.get('default_target', 'all'))
2375
+
2376
+ master_ninja_file.close()
2377
+
2378
+
2379
+ def PerformBuild(data, configurations, params):
2380
+ options = params['options']
2381
+ for config in configurations:
2382
+ builddir = os.path.join(options.toplevel_dir, 'out', config)
2383
+ arguments = ['ninja', '-C', builddir]
2384
+ print 'Building [%s]: %s' % (config, arguments)
2385
+ subprocess.check_call(arguments)
2386
+
2387
+
2388
+ def CallGenerateOutputForConfig(arglist):
2389
+ # Ignore the interrupt signal so that the parent process catches it and
2390
+ # kills all multiprocessing children.
2391
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
2392
+
2393
+ (target_list, target_dicts, data, params, config_name) = arglist
2394
+ GenerateOutputForConfig(target_list, target_dicts, data, params, config_name)
2395
+
2396
+
2397
+ def GenerateOutput(target_list, target_dicts, data, params):
2398
+ # Update target_dicts for iOS device builds.
2399
+ target_dicts = gyp.xcode_emulation.CloneConfigurationForDeviceAndEmulator(
2400
+ target_dicts)
2401
+
2402
+ user_config = params.get('generator_flags', {}).get('config', None)
2403
+ if gyp.common.GetFlavor(params) == 'win':
2404
+ target_list, target_dicts = MSVSUtil.ShardTargets(target_list, target_dicts)
2405
+ target_list, target_dicts = MSVSUtil.InsertLargePdbShims(
2406
+ target_list, target_dicts, generator_default_variables)
2407
+
2408
+ if user_config:
2409
+ GenerateOutputForConfig(target_list, target_dicts, data, params,
2410
+ user_config)
2411
+ else:
2412
+ config_names = target_dicts[target_list[0]]['configurations'].keys()
2413
+ if params['parallel']:
2414
+ try:
2415
+ pool = multiprocessing.Pool(len(config_names))
2416
+ arglists = []
2417
+ for config_name in config_names:
2418
+ arglists.append(
2419
+ (target_list, target_dicts, data, params, config_name))
2420
+ pool.map(CallGenerateOutputForConfig, arglists)
2421
+ except KeyboardInterrupt, e:
2422
+ pool.terminate()
2423
+ raise e
2424
+ else:
2425
+ for config_name in config_names:
2426
+ GenerateOutputForConfig(target_list, target_dicts, data, params,
2427
+ config_name)