cairo 1.8.3-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of cairo might be problematic. Click here for more details.

Files changed (352) hide show
  1. data/AUTHORS +4 -0
  2. data/COPYING +59 -0
  3. data/GPL +340 -0
  4. data/NEWS +163 -0
  5. data/Rakefile +190 -0
  6. data/doc/doc.css +91 -0
  7. data/doc/en/cairo-antialias.html +38 -0
  8. data/doc/en/cairo-clip-not-representable-error.html +47 -0
  9. data/doc/en/cairo-color-base.html +69 -0
  10. data/doc/en/cairo-color-cmyk.html +157 -0
  11. data/doc/en/cairo-color-hsv.html +137 -0
  12. data/doc/en/cairo-color-rgb.html +142 -0
  13. data/doc/en/cairo-color-x11.html +173 -0
  14. data/doc/en/cairo-color.html +238 -0
  15. data/doc/en/cairo-content.html +37 -0
  16. data/doc/en/cairo-context-blur.html +39 -0
  17. data/doc/en/cairo-context-circle.html +39 -0
  18. data/doc/en/cairo-context-color.html +39 -0
  19. data/doc/en/cairo-context-path.html +44 -0
  20. data/doc/en/cairo-context-rectangle.html +39 -0
  21. data/doc/en/cairo-context-triangle.html +39 -0
  22. data/doc/en/cairo-context.html +643 -0
  23. data/doc/en/cairo-error.html +44 -0
  24. data/doc/en/cairo-extend.html +38 -0
  25. data/doc/en/cairo-file-not-found.html +47 -0
  26. data/doc/en/cairo-fill-rule.html +36 -0
  27. data/doc/en/cairo-filter.html +40 -0
  28. data/doc/en/cairo-font-extents.html +129 -0
  29. data/doc/en/cairo-font-face.html +38 -0
  30. data/doc/en/cairo-font-options.html +139 -0
  31. data/doc/en/cairo-font-slant.html +37 -0
  32. data/doc/en/cairo-font-type-mismatch.html +47 -0
  33. data/doc/en/cairo-font-weight.html +36 -0
  34. data/doc/en/cairo-format.html +46 -0
  35. data/doc/en/cairo-glyph.html +99 -0
  36. data/doc/en/cairo-gradient-pattern.html +74 -0
  37. data/doc/en/cairo-hint-metrics.html +37 -0
  38. data/doc/en/cairo-hint-style.html +39 -0
  39. data/doc/en/cairo-image-surface.html +82 -0
  40. data/doc/en/cairo-invalid-clusters.html +47 -0
  41. data/doc/en/cairo-invalid-content-error.html +47 -0
  42. data/doc/en/cairo-invalid-dash-error.html +47 -0
  43. data/doc/en/cairo-invalid-dsc-comment-error.html +47 -0
  44. data/doc/en/cairo-invalid-format-error.html +47 -0
  45. data/doc/en/cairo-invalid-index-error.html +47 -0
  46. data/doc/en/cairo-invalid-matrix-error.html +47 -0
  47. data/doc/en/cairo-invalid-path-data-error.html +47 -0
  48. data/doc/en/cairo-invalid-pop-group-error.html +47 -0
  49. data/doc/en/cairo-invalid-restore-error.html +47 -0
  50. data/doc/en/cairo-invalid-slant.html +47 -0
  51. data/doc/en/cairo-invalid-status-error.html +47 -0
  52. data/doc/en/cairo-invalid-stride-error.html +47 -0
  53. data/doc/en/cairo-invalid-string-error.html +47 -0
  54. data/doc/en/cairo-invalid-visual-error.html +47 -0
  55. data/doc/en/cairo-invalid-weight.html +47 -0
  56. data/doc/en/cairo-line-cap.html +37 -0
  57. data/doc/en/cairo-line-join.html +37 -0
  58. data/doc/en/cairo-linear-pattern.html +60 -0
  59. data/doc/en/cairo-matrix.html +259 -0
  60. data/doc/en/cairo-negative-count.html +47 -0
  61. data/doc/en/cairo-no-current-point-error.html +47 -0
  62. data/doc/en/cairo-null-pointer-error.html +47 -0
  63. data/doc/en/cairo-operator.html +48 -0
  64. data/doc/en/cairo-paper-parse-error.html +47 -0
  65. data/doc/en/cairo-paper-unknown-paper-name.html +66 -0
  66. data/doc/en/cairo-paper-unknown-unit.html +66 -0
  67. data/doc/en/cairo-paper-unrecognized-paper-description.html +66 -0
  68. data/doc/en/cairo-paper.html +184 -0
  69. data/doc/en/cairo-path-close-path.html +49 -0
  70. data/doc/en/cairo-path-curve-to.html +49 -0
  71. data/doc/en/cairo-path-data-type.html +38 -0
  72. data/doc/en/cairo-path-data.html +98 -0
  73. data/doc/en/cairo-path-line-to.html +49 -0
  74. data/doc/en/cairo-path-move-to.html +49 -0
  75. data/doc/en/cairo-path.html +155 -0
  76. data/doc/en/cairo-pattern-type-mismatch-error.html +47 -0
  77. data/doc/en/cairo-pattern.html +99 -0
  78. data/doc/en/cairo-pdf-surface.html +57 -0
  79. data/doc/en/cairo-point.html +74 -0
  80. data/doc/en/cairo-ps-level.html +49 -0
  81. data/doc/en/cairo-ps-surface.html +92 -0
  82. data/doc/en/cairo-quartz-image-surface.html +57 -0
  83. data/doc/en/cairo-quartz-surface.html +57 -0
  84. data/doc/en/cairo-radial-pattern.html +60 -0
  85. data/doc/en/cairo-read-error.html +47 -0
  86. data/doc/en/cairo-rectangle.html +89 -0
  87. data/doc/en/cairo-scaled-font.html +94 -0
  88. data/doc/en/cairo-solid-pattern.html +62 -0
  89. data/doc/en/cairo-subpixel-order.html +39 -0
  90. data/doc/en/cairo-surface-finished-error.html +47 -0
  91. data/doc/en/cairo-surface-pattern.html +57 -0
  92. data/doc/en/cairo-surface-type-mismatch-error.html +47 -0
  93. data/doc/en/cairo-surface.html +121 -0
  94. data/doc/en/cairo-svg-surface.html +77 -0
  95. data/doc/en/cairo-svg-version.html +49 -0
  96. data/doc/en/cairo-temp-file-error.html +47 -0
  97. data/doc/en/cairo-text-cluster-flag.html +35 -0
  98. data/doc/en/cairo-text-cluster.html +84 -0
  99. data/doc/en/cairo-text-extents.html +144 -0
  100. data/doc/en/cairo-toy-font-face.html +67 -0
  101. data/doc/en/cairo-user-font-error.html +47 -0
  102. data/doc/en/cairo-user-font-face-text-to-glyphs-data.html +94 -0
  103. data/doc/en/cairo-user-font-face.html +72 -0
  104. data/doc/en/cairo-user-font-immutable.html +47 -0
  105. data/doc/en/cairo-win32-printing-surface.html +57 -0
  106. data/doc/en/cairo-win32-surface.html +62 -0
  107. data/doc/en/cairo-write-error.html +47 -0
  108. data/doc/en/cairo.html +131 -0
  109. data/doc/en/index.html +1154 -0
  110. data/doc/index.html +18 -0
  111. data/doc/ja/cairo-antialias.html +57 -0
  112. data/doc/ja/cairo-clip-not-representable-error.html +56 -0
  113. data/doc/ja/cairo-color-base.html +75 -0
  114. data/doc/ja/cairo-color-cmyk.html +152 -0
  115. data/doc/ja/cairo-color-hsv.html +135 -0
  116. data/doc/ja/cairo-color-rgb.html +145 -0
  117. data/doc/ja/cairo-color-x11.html +183 -0
  118. data/doc/ja/cairo-color.html +317 -0
  119. data/doc/ja/cairo-content.html +51 -0
  120. data/doc/ja/cairo-context-blur.html +53 -0
  121. data/doc/ja/cairo-context-circle.html +54 -0
  122. data/doc/ja/cairo-context-color.html +52 -0
  123. data/doc/ja/cairo-context-path.html +77 -0
  124. data/doc/ja/cairo-context-rectangle.html +60 -0
  125. data/doc/ja/cairo-context-triangle.html +47 -0
  126. data/doc/ja/cairo-context.html +1542 -0
  127. data/doc/ja/cairo-error.html +56 -0
  128. data/doc/ja/cairo-extend.html +56 -0
  129. data/doc/ja/cairo-file-not-found.html +51 -0
  130. data/doc/ja/cairo-fill-rule.html +58 -0
  131. data/doc/ja/cairo-filter.html +43 -0
  132. data/doc/ja/cairo-font-extents.html +164 -0
  133. data/doc/ja/cairo-font-face.html +55 -0
  134. data/doc/ja/cairo-font-options.html +189 -0
  135. data/doc/ja/cairo-font-slant.html +50 -0
  136. data/doc/ja/cairo-font-type-mismatch.html +52 -0
  137. data/doc/ja/cairo-font-weight.html +47 -0
  138. data/doc/ja/cairo-format.html +81 -0
  139. data/doc/ja/cairo-glyph.html +115 -0
  140. data/doc/ja/cairo-gradient-pattern.html +119 -0
  141. data/doc/ja/cairo-hint-metrics.html +57 -0
  142. data/doc/ja/cairo-hint-style.html +64 -0
  143. data/doc/ja/cairo-image-surface.html +131 -0
  144. data/doc/ja/cairo-invalid-clusters.html +55 -0
  145. data/doc/ja/cairo-invalid-content-error.html +54 -0
  146. data/doc/ja/cairo-invalid-dash-error.html +54 -0
  147. data/doc/ja/cairo-invalid-dsc-comment-error.html +54 -0
  148. data/doc/ja/cairo-invalid-format-error.html +54 -0
  149. data/doc/ja/cairo-invalid-index-error.html +54 -0
  150. data/doc/ja/cairo-invalid-matrix-error.html +54 -0
  151. data/doc/ja/cairo-invalid-path-data-error.html +54 -0
  152. data/doc/ja/cairo-invalid-pop-group-error.html +54 -0
  153. data/doc/ja/cairo-invalid-restore-error.html +55 -0
  154. data/doc/ja/cairo-invalid-slant.html +57 -0
  155. data/doc/ja/cairo-invalid-status-error.html +55 -0
  156. data/doc/ja/cairo-invalid-stride-error.html +55 -0
  157. data/doc/ja/cairo-invalid-string-error.html +54 -0
  158. data/doc/ja/cairo-invalid-visual-error.html +57 -0
  159. data/doc/ja/cairo-invalid-weight.html +57 -0
  160. data/doc/ja/cairo-line-cap.html +50 -0
  161. data/doc/ja/cairo-line-join.html +53 -0
  162. data/doc/ja/cairo-linear-pattern.html +87 -0
  163. data/doc/ja/cairo-matrix.html +354 -0
  164. data/doc/ja/cairo-negative-count.html +52 -0
  165. data/doc/ja/cairo-no-current-point-error.html +54 -0
  166. data/doc/ja/cairo-null-pointer-error.html +54 -0
  167. data/doc/ja/cairo-operator.html +51 -0
  168. data/doc/ja/cairo-paper-parse-error.html +55 -0
  169. data/doc/ja/cairo-paper-unknown-paper-name.html +76 -0
  170. data/doc/ja/cairo-paper-unknown-unit.html +75 -0
  171. data/doc/ja/cairo-paper-unrecognized-paper-description.html +76 -0
  172. data/doc/ja/cairo-paper.html +357 -0
  173. data/doc/ja/cairo-path-close-path.html +57 -0
  174. data/doc/ja/cairo-path-curve-to.html +70 -0
  175. data/doc/ja/cairo-path-data-type.html +53 -0
  176. data/doc/ja/cairo-path-data.html +127 -0
  177. data/doc/ja/cairo-path-line-to.html +62 -0
  178. data/doc/ja/cairo-path-move-to.html +62 -0
  179. data/doc/ja/cairo-path.html +144 -0
  180. data/doc/ja/cairo-pattern-type-mismatch-error.html +56 -0
  181. data/doc/ja/cairo-pattern.html +128 -0
  182. data/doc/ja/cairo-pdf-surface.html +86 -0
  183. data/doc/ja/cairo-point.html +90 -0
  184. data/doc/ja/cairo-ps-level.html +62 -0
  185. data/doc/ja/cairo-ps-surface.html +214 -0
  186. data/doc/ja/cairo-quartz-image-surface.html +75 -0
  187. data/doc/ja/cairo-quartz-surface.html +93 -0
  188. data/doc/ja/cairo-radial-pattern.html +93 -0
  189. data/doc/ja/cairo-read-error.html +55 -0
  190. data/doc/ja/cairo-rectangle.html +109 -0
  191. data/doc/ja/cairo-scaled-font.html +180 -0
  192. data/doc/ja/cairo-solid-pattern.html +87 -0
  193. data/doc/ja/cairo-subpixel-order.html +57 -0
  194. data/doc/ja/cairo-surface-finished-error.html +54 -0
  195. data/doc/ja/cairo-surface-pattern.html +68 -0
  196. data/doc/ja/cairo-surface-type-mismatch-error.html +56 -0
  197. data/doc/ja/cairo-surface.html +213 -0
  198. data/doc/ja/cairo-svg-surface.html +114 -0
  199. data/doc/ja/cairo-svg-version.html +66 -0
  200. data/doc/ja/cairo-temp-file-error.html +50 -0
  201. data/doc/ja/cairo-text-cluster-flag.html +46 -0
  202. data/doc/ja/cairo-text-cluster.html +102 -0
  203. data/doc/ja/cairo-text-extents.html +163 -0
  204. data/doc/ja/cairo-toy-font-face.html +107 -0
  205. data/doc/ja/cairo-user-font-error.html +55 -0
  206. data/doc/ja/cairo-user-font-face-text-to-glyphs-data.html +156 -0
  207. data/doc/ja/cairo-user-font-face.html +268 -0
  208. data/doc/ja/cairo-user-font-immutable.html +54 -0
  209. data/doc/ja/cairo-win32-printing-surface.html +80 -0
  210. data/doc/ja/cairo-win32-surface.html +100 -0
  211. data/doc/ja/cairo-write-error.html +55 -0
  212. data/doc/ja/cairo.html +177 -0
  213. data/doc/ja/index.html +1156 -0
  214. data/ext/cairo/cairo.def +104 -0
  215. data/ext/cairo/extconf.rb +80 -0
  216. data/ext/cairo/rb_cairo.c +104 -0
  217. data/ext/cairo/rb_cairo.h +275 -0
  218. data/ext/cairo/rb_cairo_constants.c +478 -0
  219. data/ext/cairo/rb_cairo_context.c +1693 -0
  220. data/ext/cairo/rb_cairo_exception.c +354 -0
  221. data/ext/cairo/rb_cairo_font_extents.c +200 -0
  222. data/ext/cairo/rb_cairo_font_face.c +713 -0
  223. data/ext/cairo/rb_cairo_font_options.c +197 -0
  224. data/ext/cairo/rb_cairo_glyph.c +161 -0
  225. data/ext/cairo/rb_cairo_matrix.c +366 -0
  226. data/ext/cairo/rb_cairo_path.c +459 -0
  227. data/ext/cairo/rb_cairo_pattern.c +540 -0
  228. data/ext/cairo/rb_cairo_private.c +242 -0
  229. data/ext/cairo/rb_cairo_private.h +114 -0
  230. data/ext/cairo/rb_cairo_scaled_font.c +235 -0
  231. data/ext/cairo/rb_cairo_surface.c +1371 -0
  232. data/ext/cairo/rb_cairo_text_cluster.c +151 -0
  233. data/ext/cairo/rb_cairo_text_extents.c +221 -0
  234. data/extconf.rb +45 -0
  235. data/lib/1.8/cairo.so +0 -0
  236. data/lib/1.9/cairo.so +0 -0
  237. data/lib/cairo.rb +151 -0
  238. data/lib/cairo/color.rb +267 -0
  239. data/lib/cairo/colors.rb +656 -0
  240. data/lib/cairo/constants.rb +24 -0
  241. data/lib/cairo/context.rb +29 -0
  242. data/lib/cairo/context/blur.rb +45 -0
  243. data/lib/cairo/context/circle.rb +9 -0
  244. data/lib/cairo/context/color.rb +11 -0
  245. data/lib/cairo/context/path.rb +116 -0
  246. data/lib/cairo/context/rectangle.rb +33 -0
  247. data/lib/cairo/context/triangle.rb +12 -0
  248. data/lib/cairo/paper.rb +183 -0
  249. data/lib/cairo/papers.rb +41 -0
  250. data/lib/cairo/path.rb +15 -0
  251. data/lib/cairo/point.rb +7 -0
  252. data/misc/update-colors.rb +143 -0
  253. data/pkg-config.rb +313 -0
  254. data/samples/agg/README +4 -0
  255. data/samples/agg/aa_test.rb +304 -0
  256. data/samples/blur.rb +47 -0
  257. data/samples/pac.rb +99 -0
  258. data/samples/pac2.rb +171 -0
  259. data/samples/png.rb +45 -0
  260. data/samples/scalable.rb +56 -0
  261. data/samples/text-on-path.rb +60 -0
  262. data/samples/text2.rb +131 -0
  263. data/test-unit/Rakefile +30 -0
  264. data/test-unit/bin/testrb +5 -0
  265. data/test-unit/lib/test/unit.rb +280 -0
  266. data/test-unit/lib/test/unit/assertionfailederror.rb +14 -0
  267. data/test-unit/lib/test/unit/assertions.rb +722 -0
  268. data/test-unit/lib/test/unit/attribute.rb +125 -0
  269. data/test-unit/lib/test/unit/autorunner.rb +254 -0
  270. data/test-unit/lib/test/unit/collector.rb +43 -0
  271. data/test-unit/lib/test/unit/collector/descendant.rb +23 -0
  272. data/test-unit/lib/test/unit/collector/dir.rb +108 -0
  273. data/test-unit/lib/test/unit/collector/load.rb +135 -0
  274. data/test-unit/lib/test/unit/collector/objectspace.rb +34 -0
  275. data/test-unit/lib/test/unit/color.rb +61 -0
  276. data/test-unit/lib/test/unit/diff.rb +524 -0
  277. data/test-unit/lib/test/unit/error.rb +124 -0
  278. data/test-unit/lib/test/unit/exceptionhandler.rb +39 -0
  279. data/test-unit/lib/test/unit/failure.rb +110 -0
  280. data/test-unit/lib/test/unit/fixture.rb +185 -0
  281. data/test-unit/lib/test/unit/notification.rb +125 -0
  282. data/test-unit/lib/test/unit/omission.rb +143 -0
  283. data/test-unit/lib/test/unit/pending.rb +146 -0
  284. data/test-unit/lib/test/unit/priority.rb +146 -0
  285. data/test-unit/lib/test/unit/runner/console.rb +46 -0
  286. data/test-unit/lib/test/unit/runner/emacs.rb +8 -0
  287. data/test-unit/lib/test/unit/testcase.rb +281 -0
  288. data/test-unit/lib/test/unit/testresult.rb +89 -0
  289. data/test-unit/lib/test/unit/testsuite.rb +110 -0
  290. data/test-unit/lib/test/unit/ui/console/outputlevel.rb +14 -0
  291. data/test-unit/lib/test/unit/ui/console/testrunner.rb +195 -0
  292. data/test-unit/lib/test/unit/ui/emacs/testrunner.rb +49 -0
  293. data/test-unit/lib/test/unit/ui/testrunner.rb +20 -0
  294. data/test-unit/lib/test/unit/ui/testrunnermediator.rb +77 -0
  295. data/test-unit/lib/test/unit/ui/testrunnerutilities.rb +41 -0
  296. data/test-unit/lib/test/unit/util/backtracefilter.rb +41 -0
  297. data/test-unit/lib/test/unit/util/observable.rb +90 -0
  298. data/test-unit/lib/test/unit/util/procwrapper.rb +48 -0
  299. data/test-unit/lib/test/unit/version.rb +7 -0
  300. data/test-unit/sample/adder.rb +13 -0
  301. data/test-unit/sample/subtracter.rb +12 -0
  302. data/test-unit/sample/tc_adder.rb +18 -0
  303. data/test-unit/sample/tc_subtracter.rb +18 -0
  304. data/test-unit/sample/ts_examples.rb +7 -0
  305. data/test-unit/test/collector/test_descendant.rb +135 -0
  306. data/test-unit/test/collector/test_dir.rb +406 -0
  307. data/test-unit/test/collector/test_load.rb +333 -0
  308. data/test-unit/test/collector/test_objectspace.rb +98 -0
  309. data/test-unit/test/run-test.rb +13 -0
  310. data/test-unit/test/test_assertions.rb +693 -0
  311. data/test-unit/test/test_attribute.rb +86 -0
  312. data/test-unit/test/test_color.rb +37 -0
  313. data/test-unit/test/test_diff.rb +477 -0
  314. data/test-unit/test/test_emacs_runner.rb +60 -0
  315. data/test-unit/test/test_error.rb +26 -0
  316. data/test-unit/test/test_failure.rb +33 -0
  317. data/test-unit/test/test_fixture.rb +252 -0
  318. data/test-unit/test/test_notification.rb +33 -0
  319. data/test-unit/test/test_omission.rb +81 -0
  320. data/test-unit/test/test_pending.rb +70 -0
  321. data/test-unit/test/test_priority.rb +89 -0
  322. data/test-unit/test/test_testcase.rb +430 -0
  323. data/test-unit/test/test_testresult.rb +113 -0
  324. data/test-unit/test/test_testsuite.rb +129 -0
  325. data/test-unit/test/testunit_test_util.rb +14 -0
  326. data/test-unit/test/ui/test_testrunmediator.rb +20 -0
  327. data/test-unit/test/util/test_backtracefilter.rb +41 -0
  328. data/test-unit/test/util/test_observable.rb +102 -0
  329. data/test-unit/test/util/test_procwrapper.rb +36 -0
  330. data/test/cairo-test-utils.rb +18 -0
  331. data/test/run-test.rb +28 -0
  332. data/test/test_color.rb +17 -0
  333. data/test/test_constants.rb +16 -0
  334. data/test/test_context.rb +105 -0
  335. data/test/test_exception.rb +27 -0
  336. data/test/test_font_extents.rb +36 -0
  337. data/test/test_font_face.rb +244 -0
  338. data/test/test_font_options.rb +13 -0
  339. data/test/test_paper.rb +81 -0
  340. data/test/test_pkg_config.rb +123 -0
  341. data/test/test_scaled_font.rb +34 -0
  342. data/test/test_surface.rb +41 -0
  343. data/test/test_text_cluster.rb +32 -0
  344. data/test/test_text_extents.rb +40 -0
  345. data/test/test_text_to_glyphs_data.rb +51 -0
  346. data/tmp/x86-mingw32/cairo/1.8.7/fake.rb +6 -0
  347. data/tmp/x86-mingw32/cairo/1.8.7/mkmf.rb +1836 -0
  348. data/tmp/x86-mingw32/cairo/1.8.7/rbconfig.rb +183 -0
  349. data/tmp/x86-mingw32/cairo/1.9.2/fake.rb +6 -0
  350. data/tmp/x86-mingw32/cairo/1.9.2/mkmf.rb +2079 -0
  351. data/tmp/x86-mingw32/cairo/1.9.2/rbconfig.rb +226 -0
  352. metadata +437 -0
@@ -0,0 +1,13 @@
1
+ require 'cairo'
2
+
3
+ class FontOptionsTest < Test::Unit::TestCase
4
+ include CairoTestUtils
5
+
6
+ def setup
7
+ @options = Cairo::FontOptions.new
8
+ end
9
+
10
+ def test_something
11
+ # WRITE ME!
12
+ end
13
+ end
@@ -0,0 +1,81 @@
1
+ require 'cairo'
2
+
3
+ class PaperTest < Test::Unit::TestCase
4
+ def test_parse_paper
5
+ a4 = Cairo::Paper::A4
6
+ assert_parse(a4, a4)
7
+ end
8
+
9
+ def test_parse_name
10
+ assert_parse(:A4, "A4")
11
+ assert_parse(:A4_LANDSCAPE, "A4 landscape")
12
+ assert_parse(:A4, :A4)
13
+ assert_parse(:A4, :a4)
14
+
15
+ assert_parse(:JAPANESE_POSTCARD, :japanese_postcard)
16
+ assert_parse(:JAPANESE_POSTCARD, "japanese-postcard")
17
+ assert_parse(:JAPANESE_POSTCARD, "Japanese postcard")
18
+
19
+ exception = assert_raise(Cairo::Paper::UnknownPaperName) do
20
+ Cairo::Paper.parse(:nonexistence)
21
+ end
22
+ assert_equal(:nonexistence, exception.name)
23
+ end
24
+
25
+ def test_parse_size
26
+ assert_parse(paper(100, 200), "100x200")
27
+ assert_parse(paper(283.46456664, 566.929134), "100mmx200mm")
28
+ assert_parse(paper(284.88188952, 200.9), "100.5mmx200.9")
29
+ assert_parse(paper(72, 612.0), "1inx8.5inch")
30
+ assert_parse(paper(28.346456664, 24094.488168), "1cmx8.5m")
31
+ assert_parse(paper(100, 200), [100, 200])
32
+
33
+ exception = assert_raise(Cairo::Paper::UnknownUnit) do
34
+ Cairo::Paper.parse("100kmx100")
35
+ end
36
+ assert_equal("km", exception.unit)
37
+ end
38
+
39
+ def test_parse_size_with_name
40
+ assert_parse(paper(28.346456664, 24094.488168, nil, "Name"),
41
+ "1cmx8.5m#Name")
42
+ end
43
+
44
+ def test_unrecognized_input
45
+ assert_nothing_raised do
46
+ Cairo::Paper.parse({})
47
+ end
48
+
49
+ exception = assert_raise(Cairo::Paper::UnrecognizedPaperDescription) do
50
+ Cairo::Paper.parse({}, true)
51
+ end
52
+ assert_equal({}, exception.description)
53
+ end
54
+
55
+ def test_unit
56
+ paper = parse("1cmx8.5m")
57
+ assert_nil(paper.unit)
58
+ assert_in_delta(28.346456664, 0.01, paper.width)
59
+ assert_in_delta(24094.488168, 0.01, paper.height)
60
+
61
+ paper.unit = "inch"
62
+ assert_equal("inch", paper.unit)
63
+ assert_in_delta(0.393700787, 0.01, paper.width)
64
+ assert_in_delta(334.645669, 0.01, paper.height)
65
+ end
66
+
67
+ private
68
+ def paper(width, height, *rest)
69
+ Cairo::Paper.new(width, height, *rest)
70
+ end
71
+
72
+ def parse(paper_description)
73
+ Cairo::Paper.parse(paper_description)
74
+ end
75
+
76
+ def assert_parse(expected, paper_description, message=nil)
77
+ expected = Cairo::Paper.const_get(expected) if expected.is_a?(Symbol)
78
+ actual_paper = parse(paper_description)
79
+ assert_equal(expected, actual_paper, message)
80
+ end
81
+ end
@@ -0,0 +1,123 @@
1
+ require 'pkg-config'
2
+
3
+ class PkgConfigTest < Test::Unit::TestCase
4
+ def setup
5
+ @cairo = PackageConfig.new("cairo")
6
+ @cairo_png = PackageConfig.new("cairo-png")
7
+ end
8
+
9
+ def test_exist?
10
+ assert(system('pkg-config --exists cairo'))
11
+ assert(@cairo.exist?)
12
+
13
+ assert(system('pkg-config --exists cairo-png'))
14
+ assert(@cairo_png.exist?)
15
+ end
16
+
17
+ def test_cflags
18
+ assert_pkg_config("cairo", ["--cflags"], @cairo.cflags)
19
+ assert_pkg_config("cairo-png", ["--cflags"], @cairo_png.cflags)
20
+ end
21
+
22
+ def test_cflags_only_I
23
+ assert_pkg_config("cairo", ["--cflags-only-I"], @cairo.cflags_only_I)
24
+ assert_pkg_config("cairo-png", ["--cflags-only-I"], @cairo_png.cflags_only_I)
25
+ end
26
+
27
+ def test_libs
28
+ assert_pkg_config("cairo", ["--libs"], @cairo.libs)
29
+ assert_pkg_config("cairo-png", ["--libs"], @cairo_png.libs)
30
+
31
+ @cairo.msvc_syntax = true
32
+ result = pkg_config("cairo", "--libs")
33
+ msvc_result = result.gsub(/-lcairo\b/, "cairo.lib")
34
+ assert_not_equal(msvc_result, result)
35
+ assert_equal(msvc_result, @cairo.libs)
36
+ end
37
+
38
+ def test_libs_only_l
39
+ assert_pkg_config("cairo", ["--libs-only-l"], @cairo.libs_only_l)
40
+ assert_pkg_config("cairo-png", ["--libs-only-l"], @cairo_png.libs_only_l)
41
+
42
+ @cairo_png.msvc_syntax = true
43
+ result = pkg_config("cairo-png", "--libs-only-l")
44
+ msvc_result = result.gsub(/-l(cairo|png12)\b/, '\1.lib')
45
+ assert_not_equal(msvc_result, result)
46
+ assert_equal(msvc_result, @cairo_png.libs_only_l)
47
+ end
48
+
49
+ def test_requires
50
+ assert_equal([], @cairo.requires)
51
+ end
52
+
53
+ def test_requires_private
54
+ assert_equal(["freetype2", "fontconfig", "libpng12",
55
+ "xcb", "xcb-render", "xcb-renderutil",
56
+ "xrender", "x11", "pixman-1"],
57
+ @cairo.requires_private)
58
+ end
59
+
60
+ def test_version
61
+ assert_pkg_config("cairo", ["--modversion"], @cairo.version)
62
+ end
63
+
64
+ def test_parse_override_variables
65
+ assert_override_variables({}, nil)
66
+ assert_override_variables({"prefix" => "c:\\\\gtk-dev"},
67
+ "prefix=c:\\\\gtk-dev")
68
+ assert_override_variables({
69
+ "prefix" => "c:\\\\gtk-dev",
70
+ "includdir" => "d:\\\\gtk\\include"
71
+ },
72
+ ["prefix=c:\\\\gtk-dev",
73
+ "includdir=d:\\\\gtk\\include"].join(","))
74
+ end
75
+
76
+ def test_override_variables
77
+ overridden_prefix = "c:\\\\gtk-dev"
78
+ original_prefix = @cairo.variable("prefix")
79
+ assert_not_equal(overridden_prefix, original_prefix)
80
+ with_override_variables("prefix=#{overridden_prefix}") do
81
+ cairo = PackageConfig.new("cairo")
82
+ assert_equal(overridden_prefix, cairo.variable("prefix"))
83
+ end
84
+ end
85
+
86
+ private
87
+ def pkg_config(package, *args)
88
+ args = args.collect {|arg| arg.dump}.join(' ')
89
+ `pkg-config #{args} #{package}`.strip
90
+ end
91
+
92
+ def assert_pkg_config(package, pkg_config_args, actual)
93
+ result = pkg_config(package, *pkg_config_args)
94
+ result = nil if result.empty?
95
+ assert_equal(result, actual)
96
+ end
97
+
98
+ def assert_override_variables(expected, override_variables)
99
+ with_override_variables(override_variables) do
100
+ cairo = PackageConfig.new("cairo")
101
+ assert_equal(expected, cairo.instance_variable_get("@override_variables"))
102
+ end
103
+ end
104
+
105
+ def with_override_variables(override_variables)
106
+ if override_variables.nil?
107
+ args = {}
108
+ else
109
+ args = {"--with-override-variables" => override_variables}
110
+ end
111
+ configure_args(args) do
112
+ yield
113
+ end
114
+ end
115
+
116
+ def configure_args(args)
117
+ original_configure_args = $configure_args
118
+ $configure_args = $configure_args.merge(args)
119
+ yield
120
+ ensure
121
+ $configure_args = original_configure_args
122
+ end
123
+ end
@@ -0,0 +1,34 @@
1
+ require 'cairo'
2
+ require 'stringio'
3
+
4
+ class ScaledFontTest < Test::Unit::TestCase
5
+ include CairoTestUtils
6
+
7
+ def test_scale_matrix
8
+ only_cairo_version(1, 7, 2)
9
+
10
+ surface = Cairo::ImageSurface.new(100, 100)
11
+ context = Cairo::Context.new(surface)
12
+ scaled_font = context.scaled_font
13
+
14
+ assert_equal(Cairo::Matrix.new(10.0, 0.0, 0.0,
15
+ 10.0, 0.0, 0.0),
16
+ scaled_font.scale_matrix)
17
+ end
18
+
19
+ def test_text_to_glyphs
20
+ only_cairo_version(1, 7, 6)
21
+
22
+ surface = Cairo::PDFSurface.new(StringIO.new, 10, 10)
23
+ context = Cairo::Context.new(surface)
24
+ scaled_font = Cairo::ScaledFont.new(context.font_face,
25
+ Cairo::Matrix.identity,
26
+ Cairo::Matrix.identity,
27
+ Cairo::FontOptions.new)
28
+ expected_glyphs = []
29
+ expected_clusters = []
30
+ expected_cluster_flags = 0
31
+ assert_equal([expected_glyphs, expected_clusters, expected_cluster_flags],
32
+ scaled_font.text_to_glyphs(0, 0, "text"))
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ require 'cairo'
2
+ require 'stringio'
3
+
4
+ class SurfaceTest < Test::Unit::TestCase
5
+ include CairoTestUtils
6
+
7
+ def test_new
8
+ output = StringIO.new
9
+ surface = Cairo::PDFSurface.new(output, 10, 10)
10
+ assert_no_match(/%%EOF\s*\z/m, output.string)
11
+ surface.finish
12
+ assert_match(/%%EOF\s*\z/m, output.string)
13
+ end
14
+
15
+ def test_new_with_block
16
+ output = StringIO.new
17
+ Cairo::PDFSurface.new(output, 10, 10) do |surface|
18
+ assert_no_match(/%%EOF\s*\z/m, output.string)
19
+ end
20
+ assert_match(/%%EOF\s*\z/m, output.string)
21
+ end
22
+
23
+ def test_new_with_block_and_finish
24
+ assert_nothing_raised do
25
+ Cairo::PDFSurface.new(StringIO.new, 10, 10) do |surface|
26
+ surface.finish
27
+ end
28
+ end
29
+ end
30
+
31
+ def test_fallback_resolution
32
+ only_cairo_version(1, 7, 2)
33
+
34
+ surface = Cairo::ImageSurface.new(100, 100)
35
+
36
+ assert_equal([300.0, 300.0], surface.fallback_resolution)
37
+
38
+ surface.set_fallback_resolution(95, 95)
39
+ assert_equal([95.0, 95.0], surface.fallback_resolution)
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ require 'cairo'
2
+
3
+ class TextClusterTest < Test::Unit::TestCase
4
+ include CairoTestUtils
5
+
6
+ def test_new
7
+ only_cairo_version(1, 7, 2)
8
+
9
+ cluster = Cairo::TextCluster.new(2, 3)
10
+ assert_equal([2, 3], [cluster.num_bytes, cluster.num_glyphs])
11
+ assert_equal("#<Cairo::TextCluster: num_bytes=2, num_glyphs=3>",
12
+ cluster.to_s)
13
+ end
14
+
15
+ def test_accessor
16
+ only_cairo_version(1, 7, 2)
17
+
18
+ cluster = Cairo::TextCluster.new(5, 7)
19
+ assert_equal([5, 7], [cluster.num_bytes, cluster.num_glyphs])
20
+ cluster.num_bytes = 1
21
+ cluster.num_glyphs = 2
22
+ assert_equal([1, 2], [cluster.num_bytes, cluster.num_glyphs])
23
+ end
24
+
25
+ def test_to_s
26
+ only_cairo_version(1, 7, 2)
27
+
28
+ cluster = Cairo::TextCluster.new(9, 1)
29
+ assert_equal("#<Cairo::TextCluster: num_bytes=9, num_glyphs=1>",
30
+ cluster.to_s)
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ require 'cairo'
2
+
3
+ class TextExtentsTest < Test::Unit::TestCase
4
+ include CairoTestUtils
5
+
6
+ def test_new
7
+ extents = Cairo::TextExtents.new
8
+ assert_equal([0.0, -1.0, 0.0, 1.0, 1.0, 0.0],
9
+ [extents.x_bearing, extents.y_bearing,
10
+ extents.width, extents.height,
11
+ extents.x_advance, extents.y_advance])
12
+ end
13
+
14
+ def test_accessor
15
+ extents = Cairo::TextExtents.new
16
+ extents.x_bearing = 0.1
17
+ extents.y_bearing = 0.2
18
+ extents.width = 0.3
19
+ extents.height = 0.4
20
+ extents.x_advance = 0.5
21
+ extents.y_advance = 0.6
22
+ assert_equal([0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
23
+ [extents.x_bearing, extents.y_bearing,
24
+ extents.width, extents.height,
25
+ extents.x_advance, extents.y_advance])
26
+ end
27
+
28
+ def test_to_s
29
+ extents = Cairo::TextExtents.new
30
+ extents.x_bearing = 0.1
31
+ extents.y_bearing = 0.2
32
+ extents.width = 0.3
33
+ extents.height = 0.4
34
+ extents.x_advance = 0.5
35
+ extents.y_advance = 0.6
36
+ assert_equal("#<Cairo::TextExtents: x_bearing=0.1, y_bearing=0.2, " +
37
+ "width=0.3, height=0.4, x_advance=0.5, y_advance=0.6>",
38
+ extents.to_s)
39
+ end
40
+ end
@@ -0,0 +1,51 @@
1
+ require 'cairo'
2
+
3
+ class TextToGlyphsDataTest < Test::Unit::TestCase
4
+ include CairoTestUtils
5
+
6
+ def test_new
7
+ only_cairo_version(1, 7, 6)
8
+
9
+ data = Cairo::UserFontFace::TextToGlyphsData.new(false, false, false)
10
+ assert_equal([false, false, false],
11
+ [data.need_glyphs?, data.need_clusters?,
12
+ data.need_cluster_flags?])
13
+
14
+ data = Cairo::UserFontFace::TextToGlyphsData.new(true, false, false)
15
+ assert_equal([true, false, false],
16
+ [data.need_glyphs?, data.need_clusters?,
17
+ data.need_cluster_flags?])
18
+
19
+ data = Cairo::UserFontFace::TextToGlyphsData.new(false, true, false)
20
+ assert_equal([false, true, false],
21
+ [data.need_glyphs?, data.need_clusters?,
22
+ data.need_cluster_flags?])
23
+
24
+ data = Cairo::UserFontFace::TextToGlyphsData.new(false, false, true)
25
+ assert_equal([false, false, true],
26
+ [data.need_glyphs?, data.need_clusters?,
27
+ data.need_cluster_flags?])
28
+ end
29
+
30
+ def test_accessor
31
+ only_cairo_version(1, 7, 6)
32
+
33
+ data = Cairo::UserFontFace::TextToGlyphsData.new(true, true, true)
34
+ assert_equal([nil, nil, 0],
35
+ [data.glyphs, data.clusters, data.cluster_flags])
36
+
37
+ glyph = Cairo::Glyph.new(0, 5, 10)
38
+ data.glyphs = [glyph]
39
+ assert_equal([[glyph], nil, 0],
40
+ [data.glyphs, data.clusters, data.cluster_flags])
41
+
42
+ cluster = Cairo::TextCluster.new(0, 1)
43
+ data.clusters = [cluster]
44
+ assert_equal([[glyph], [cluster], 0],
45
+ [data.glyphs, data.clusters, data.cluster_flags])
46
+
47
+ data.cluster_flags = :backward
48
+ assert_equal([[glyph], [cluster], Cairo::TextClusterFlag::BACKWARD],
49
+ [data.glyphs, data.clusters, data.cluster_flags])
50
+ end
51
+ end
@@ -0,0 +1,6 @@
1
+ class Object
2
+ remove_const :RUBY_PLATFORM
3
+ remove_const :RUBY_VERSION
4
+ RUBY_PLATFORM = "i386-mingw32"
5
+ RUBY_VERSION = "1.8.7"
6
+ end
@@ -0,0 +1,1836 @@
1
+ # module to create Makefile for extension modules
2
+ # invoke like: ruby -r mkmf extconf.rb
3
+
4
+ require 'rbconfig'
5
+ require 'fileutils'
6
+ require 'shellwords'
7
+
8
+ CONFIG = Config::MAKEFILE_CONFIG
9
+ ORIG_LIBPATH = ENV['LIB']
10
+
11
+ CXX_EXT = %w[cc cxx cpp]
12
+ if /mswin|bccwin|mingw|msdosdjgpp|human|os2/ !~ CONFIG['build_os']
13
+ CXX_EXT.concat(%w[C])
14
+ end
15
+ SRC_EXT = %w[c m].concat(CXX_EXT)
16
+ $static = $config_h = nil
17
+ $default_static = $static
18
+
19
+ unless defined? $configure_args
20
+ $configure_args = {}
21
+ args = CONFIG["configure_args"]
22
+ if ENV["CONFIGURE_ARGS"]
23
+ args << " " << ENV["CONFIGURE_ARGS"]
24
+ end
25
+ for arg in Shellwords::shellwords(args)
26
+ arg, val = arg.split('=', 2)
27
+ next unless arg
28
+ arg.tr!('_', '-')
29
+ if arg.sub!(/^(?!--)/, '--')
30
+ val or next
31
+ arg.downcase!
32
+ end
33
+ next if /^--(?:top|topsrc|src|cur)dir$/ =~ arg
34
+ $configure_args[arg] = val || true
35
+ end
36
+ for arg in ARGV
37
+ arg, val = arg.split('=', 2)
38
+ next unless arg
39
+ arg.tr!('_', '-')
40
+ if arg.sub!(/^(?!--)/, '--')
41
+ val or next
42
+ arg.downcase!
43
+ end
44
+ $configure_args[arg] = val || true
45
+ end
46
+ end
47
+
48
+ $libdir = CONFIG["libdir"]
49
+ $rubylibdir = CONFIG["rubylibdir"]
50
+ $archdir = CONFIG["archdir"]
51
+ $sitedir = CONFIG["sitedir"]
52
+ $sitelibdir = CONFIG["sitelibdir"]
53
+ $sitearchdir = CONFIG["sitearchdir"]
54
+ $vendordir = CONFIG["vendordir"]
55
+ $vendorlibdir = CONFIG["vendorlibdir"]
56
+ $vendorarchdir = CONFIG["vendorarchdir"]
57
+
58
+ $mswin = /mswin/ =~ RUBY_PLATFORM
59
+ $bccwin = /bccwin/ =~ RUBY_PLATFORM
60
+ $mingw = /mingw/ =~ RUBY_PLATFORM
61
+ $cygwin = /cygwin/ =~ RUBY_PLATFORM
62
+ $human = /human/ =~ RUBY_PLATFORM
63
+ $netbsd = /netbsd/ =~ RUBY_PLATFORM
64
+ $os2 = /os2/ =~ RUBY_PLATFORM
65
+ $beos = /beos/ =~ RUBY_PLATFORM
66
+ $solaris = /solaris/ =~ RUBY_PLATFORM
67
+ $dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
68
+
69
+ # :stopdoc:
70
+
71
+ def config_string(key, config = CONFIG)
72
+ s = config[key] and !s.empty? and block_given? ? yield(s) : s
73
+ end
74
+
75
+ def dir_re(dir)
76
+ Regexp.new('\$(?:\('+dir+'\)|\{'+dir+'\})(?:\$(?:\(target_prefix\)|\{target_prefix\}))?')
77
+ end
78
+
79
+ INSTALL_DIRS = [
80
+ [dir_re('commondir'), "$(RUBYCOMMONDIR)"],
81
+ [dir_re('sitedir'), "$(RUBYCOMMONDIR)"],
82
+ [dir_re('vendordir'), "$(RUBYCOMMONDIR)"],
83
+ [dir_re('rubylibdir'), "$(RUBYLIBDIR)"],
84
+ [dir_re('archdir'), "$(RUBYARCHDIR)"],
85
+ [dir_re('sitelibdir'), "$(RUBYLIBDIR)"],
86
+ [dir_re('vendorlibdir'), "$(RUBYLIBDIR)"],
87
+ [dir_re('sitearchdir'), "$(RUBYARCHDIR)"],
88
+ [dir_re('bindir'), "$(BINDIR)"],
89
+ [dir_re('vendorarchdir'), "$(RUBYARCHDIR)"],
90
+ ]
91
+
92
+ def install_dirs(target_prefix = nil)
93
+ if $extout
94
+ dirs = [
95
+ ['BINDIR', '$(extout)/bin'],
96
+ ['RUBYCOMMONDIR', '$(extout)/common'],
97
+ ['RUBYLIBDIR', '$(RUBYCOMMONDIR)$(target_prefix)'],
98
+ ['RUBYARCHDIR', '$(extout)/$(arch)$(target_prefix)'],
99
+ ['extout', "#$extout"],
100
+ ['extout_prefix', "#$extout_prefix"],
101
+ ]
102
+ elsif $extmk
103
+ dirs = [
104
+ ['BINDIR', '$(bindir)'],
105
+ ['RUBYCOMMONDIR', '$(rubylibdir)'],
106
+ ['RUBYLIBDIR', '$(rubylibdir)$(target_prefix)'],
107
+ ['RUBYARCHDIR', '$(archdir)$(target_prefix)'],
108
+ ]
109
+ elsif $configure_args.has_key?('--vendor')
110
+ dirs = [
111
+ ['BINDIR', '$(bindir)'],
112
+ ['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'],
113
+ ['RUBYLIBDIR', '$(vendorlibdir)$(target_prefix)'],
114
+ ['RUBYARCHDIR', '$(vendorarchdir)$(target_prefix)'],
115
+ ]
116
+ else
117
+ dirs = [
118
+ ['BINDIR', '$(bindir)'],
119
+ ['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
120
+ ['RUBYLIBDIR', '$(sitelibdir)$(target_prefix)'],
121
+ ['RUBYARCHDIR', '$(sitearchdir)$(target_prefix)'],
122
+ ]
123
+ end
124
+ dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
125
+ dirs
126
+ end
127
+
128
+ def map_dir(dir, map = nil)
129
+ map ||= INSTALL_DIRS
130
+ map.inject(dir) {|dir, (orig, new)| dir.gsub(orig, new)}
131
+ end
132
+
133
+ topdir = File.dirname(libdir = File.dirname(__FILE__))
134
+ extdir = File.expand_path("ext", topdir)
135
+ $extmk = File.expand_path($0)[0, extdir.size+1] == extdir+"/"
136
+ if not $extmk and File.exist?(($hdrdir = Config::CONFIG["archdir"]) + "/ruby.h")
137
+ $topdir = $hdrdir
138
+ elsif File.exist?(($hdrdir = ($top_srcdir ||= topdir)) + "/ruby.h") and
139
+ File.exist?(($topdir ||= Config::CONFIG["topdir"]) + "/config.h")
140
+ else
141
+ abort "mkmf.rb can't find header files for ruby at #{$hdrdir}/ruby.h"
142
+ end
143
+
144
+ OUTFLAG = CONFIG['OUTFLAG']
145
+ CPPOUTFILE = CONFIG['CPPOUTFILE']
146
+
147
+ CONFTEST_C = "conftest.c"
148
+
149
+ class String
150
+ # Wraps a string in escaped quotes if it contains whitespace.
151
+ def quote
152
+ /\s/ =~ self ? "\"#{self}\"" : "#{self}"
153
+ end
154
+
155
+ # Generates a string used as cpp macro name.
156
+ def tr_cpp
157
+ strip.upcase.tr_s("^A-Z0-9_", "_")
158
+ end
159
+ end
160
+ class Array
161
+ # Wraps all strings in escaped quotes if they contain whitespace.
162
+ def quote
163
+ map {|s| s.quote}
164
+ end
165
+ end
166
+
167
+ def rm_f(*files)
168
+ FileUtils.rm_f(Dir[files.join("\0")])
169
+ end
170
+
171
+ # Returns time stamp of the +target+ file if it exists and is newer
172
+ # than or equal to all of +times+.
173
+ def modified?(target, times)
174
+ (t = File.mtime(target)) rescue return nil
175
+ Array === times or times = [times]
176
+ t if times.all? {|n| n <= t}
177
+ end
178
+
179
+ def merge_libs(*libs)
180
+ libs.inject([]) do |x, y|
181
+ xy = x & y
182
+ xn = yn = 0
183
+ y = y.inject([]) {|ary, e| ary.last == e ? ary : ary << e}
184
+ y.each_with_index do |v, yi|
185
+ if xy.include?(v)
186
+ xi = [x.index(v), xn].max()
187
+ x[xi, 1] = y[yn..yi]
188
+ xn, yn = xi + (yi - yn + 1), yi + 1
189
+ end
190
+ end
191
+ x.concat(y[yn..-1] || [])
192
+ end
193
+ end
194
+
195
+ # This is a custom logging module. It generates an mkmf.log file when you
196
+ # run your extconf.rb script. This can be useful for debugging unexpected
197
+ # failures.
198
+ #
199
+ # This module and its associated methods are meant for internal use only.
200
+ #
201
+ module Logging
202
+ @log = nil
203
+ @logfile = 'mkmf.log'
204
+ @orgerr = $stderr.dup
205
+ @orgout = $stdout.dup
206
+ @postpone = 0
207
+ @quiet = $extmk
208
+
209
+ def self::open
210
+ @log ||= File::open(@logfile, 'w')
211
+ @log.sync = true
212
+ $stderr.reopen(@log)
213
+ $stdout.reopen(@log)
214
+ yield
215
+ ensure
216
+ $stderr.reopen(@orgerr)
217
+ $stdout.reopen(@orgout)
218
+ end
219
+
220
+ def self::message(*s)
221
+ @log ||= File::open(@logfile, 'w')
222
+ @log.sync = true
223
+ @log.printf(*s)
224
+ end
225
+
226
+ def self::logfile file
227
+ @logfile = file
228
+ if @log and not @log.closed?
229
+ @log.flush
230
+ @log.close
231
+ @log = nil
232
+ end
233
+ end
234
+
235
+ def self::postpone
236
+ tmplog = "mkmftmp#{@postpone += 1}.log"
237
+ open do
238
+ log, *save = @log, @logfile, @orgout, @orgerr
239
+ @log, @logfile, @orgout, @orgerr = nil, tmplog, log, log
240
+ begin
241
+ log.print(open {yield})
242
+ @log.close
243
+ File::open(tmplog) {|t| FileUtils.copy_stream(t, log)}
244
+ ensure
245
+ @log, @logfile, @orgout, @orgerr = log, *save
246
+ @postpone -= 1
247
+ rm_f tmplog
248
+ end
249
+ end
250
+ end
251
+
252
+ class << self
253
+ attr_accessor :quiet
254
+ end
255
+ end
256
+
257
+ def xsystem command
258
+ varpat = /\$\((\w+)\)|\$\{(\w+)\}/
259
+ if varpat =~ command
260
+ vars = Hash.new {|h, k| h[k] = ''; ENV[k]}
261
+ command = command.dup
262
+ nil while command.gsub!(varpat) {vars[$1||$2]}
263
+ end
264
+ Logging::open do
265
+ puts command.quote
266
+ system(command)
267
+ end
268
+ end
269
+
270
+ def xpopen command, *mode, &block
271
+ Logging::open do
272
+ case mode[0]
273
+ when nil, /^r/
274
+ puts "#{command} |"
275
+ else
276
+ puts "| #{command}"
277
+ end
278
+ IO.popen(command, *mode, &block)
279
+ end
280
+ end
281
+
282
+ def log_src(src)
283
+ src = src.split(/^/)
284
+ fmt = "%#{src.size.to_s.size}d: %s"
285
+ Logging::message <<"EOM"
286
+ checked program was:
287
+ /* begin */
288
+ EOM
289
+ src.each_with_index {|line, no| Logging::message fmt, no+1, line}
290
+ Logging::message <<"EOM"
291
+ /* end */
292
+
293
+ EOM
294
+ end
295
+
296
+ def create_tmpsrc(src)
297
+ src = yield(src) if block_given?
298
+ src = src.gsub(/[ \t]+$/, '').gsub(/\A\n+|^\n+$/, '').sub(/[^\n]\z/, "\\&\n")
299
+ open(CONFTEST_C, "wb") do |cfile|
300
+ cfile.print src
301
+ end
302
+ src
303
+ end
304
+
305
+ def try_do(src, command, &b)
306
+ src = create_tmpsrc(src, &b)
307
+ xsystem(command)
308
+ ensure
309
+ log_src(src)
310
+ end
311
+
312
+ def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
313
+ conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote,
314
+ 'src' => CONFTEST_C,
315
+ 'INCFLAGS' => $INCFLAGS,
316
+ 'CPPFLAGS' => $CPPFLAGS,
317
+ 'CFLAGS' => "#$CFLAGS",
318
+ 'ARCH_FLAG' => "#$ARCH_FLAG",
319
+ 'LDFLAGS' => "#$LDFLAGS #{ldflags}",
320
+ 'LIBPATH' => libpathflag(libpath),
321
+ 'LOCAL_LIBS' => "#$LOCAL_LIBS #$libs",
322
+ 'LIBS' => "#$LIBRUBYARG_STATIC #{opt} #$LIBS")
323
+ Config::expand(TRY_LINK.dup, conf)
324
+ end
325
+
326
+ def cc_command(opt="")
327
+ conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote)
328
+ Config::expand("$(CC) #$INCFLAGS #$CPPFLAGS #$CFLAGS #$ARCH_FLAG #{opt} -c #{CONFTEST_C}",
329
+ conf)
330
+ end
331
+
332
+ def cpp_command(outfile, opt="")
333
+ conf = Config::CONFIG.merge('hdrdir' => $hdrdir.quote, 'srcdir' => $srcdir.quote)
334
+ Config::expand("$(CPP) #$INCFLAGS #$CPPFLAGS #$CFLAGS #{opt} #{CONFTEST_C} #{outfile}",
335
+ conf)
336
+ end
337
+
338
+ def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
339
+ libpath.map{|x|
340
+ case x
341
+ when "$(topdir)", /\A\./
342
+ LIBPATHFLAG
343
+ else
344
+ LIBPATHFLAG+RPATHFLAG
345
+ end % x.quote
346
+ }.join
347
+ end
348
+
349
+ def try_link0(src, opt="", &b)
350
+ try_do(src, link_command("", opt), &b)
351
+ end
352
+
353
+ def try_link(src, opt="", &b)
354
+ try_link0(src, opt, &b)
355
+ ensure
356
+ rm_f "conftest*", "c0x32*"
357
+ end
358
+
359
+ def try_compile(src, opt="", &b)
360
+ try_do(src, cc_command(opt), &b)
361
+ ensure
362
+ rm_f "conftest*"
363
+ end
364
+
365
+ def try_cpp(src, opt="", &b)
366
+ try_do(src, cpp_command(CPPOUTFILE, opt), &b)
367
+ ensure
368
+ rm_f "conftest*"
369
+ end
370
+
371
+ def cpp_include(header)
372
+ if header
373
+ header = [header] unless header.kind_of? Array
374
+ header.map {|h| "#include <#{h}>\n"}.join
375
+ else
376
+ ""
377
+ end
378
+ end
379
+
380
+ def with_cppflags(flags)
381
+ cppflags = $CPPFLAGS
382
+ $CPPFLAGS = flags
383
+ ret = yield
384
+ ensure
385
+ $CPPFLAGS = cppflags unless ret
386
+ end
387
+
388
+ def with_cflags(flags)
389
+ cflags = $CFLAGS
390
+ $CFLAGS = flags
391
+ ret = yield
392
+ ensure
393
+ $CFLAGS = cflags unless ret
394
+ end
395
+
396
+ def with_ldflags(flags)
397
+ ldflags = $LDFLAGS
398
+ $LDFLAGS = flags
399
+ ret = yield
400
+ ensure
401
+ $LDFLAGS = ldflags unless ret
402
+ end
403
+
404
+ def try_static_assert(expr, headers = nil, opt = "", &b)
405
+ headers = cpp_include(headers)
406
+ try_compile(<<SRC, opt, &b)
407
+ #{COMMON_HEADERS}
408
+ #{headers}
409
+ /*top*/
410
+ int conftest_const[(#{expr}) ? 1 : -1];
411
+ SRC
412
+ end
413
+
414
+ def try_constant(const, headers = nil, opt = "", &b)
415
+ includes = cpp_include(headers)
416
+ if CROSS_COMPILING
417
+ if try_static_assert("#{const} > 0", headers, opt)
418
+ # positive constant
419
+ elsif try_static_assert("#{const} < 0", headers, opt)
420
+ neg = true
421
+ const = "-(#{const})"
422
+ elsif try_static_assert("#{const} == 0", headers, opt)
423
+ return 0
424
+ else
425
+ # not a constant
426
+ return nil
427
+ end
428
+ upper = 1
429
+ lower = 0
430
+ until try_static_assert("#{const} <= #{upper}", headers, opt)
431
+ lower = upper
432
+ upper <<= 1
433
+ end
434
+ return nil unless lower
435
+ while upper > lower + 1
436
+ mid = (upper + lower) / 2
437
+ if try_static_assert("#{const} > #{mid}", headers, opt)
438
+ lower = mid
439
+ else
440
+ upper = mid
441
+ end
442
+ end
443
+ upper = -upper if neg
444
+ return upper
445
+ else
446
+ src = %{#{COMMON_HEADERS}
447
+ #{includes}
448
+ #include <stdio.h>
449
+ /*top*/
450
+ int conftest_const = (int)(#{const});
451
+ int main() {printf("%d\\n", conftest_const); return 0;}
452
+ }
453
+ if try_link0(src, opt, &b)
454
+ xpopen("./conftest") do |f|
455
+ return Integer(f.gets)
456
+ end
457
+ end
458
+ end
459
+ nil
460
+ end
461
+
462
+ def try_func(func, libs, headers = nil, &b)
463
+ headers = cpp_include(headers)
464
+ try_link(<<"SRC", libs, &b) or try_link(<<"SRC", libs, &b)
465
+ #{COMMON_HEADERS}
466
+ #{headers}
467
+ /*top*/
468
+ int main() { return 0; }
469
+ int t() { void ((*volatile p)()); p = (void ((*)()))#{func}; return 0; }
470
+ SRC
471
+ #{headers}
472
+ /*top*/
473
+ int main() { return 0; }
474
+ int t() { #{func}(); return 0; }
475
+ SRC
476
+ end
477
+
478
+ def try_var(var, headers = nil, &b)
479
+ headers = cpp_include(headers)
480
+ try_compile(<<"SRC", &b)
481
+ #{COMMON_HEADERS}
482
+ #{headers}
483
+ /*top*/
484
+ int main() { return 0; }
485
+ int t() { const volatile void *volatile p; p = &(&#{var})[0]; return 0; }
486
+ SRC
487
+ end
488
+
489
+ def egrep_cpp(pat, src, opt = "", &b)
490
+ src = create_tmpsrc(src, &b)
491
+ xpopen(cpp_command('', opt)) do |f|
492
+ if Regexp === pat
493
+ puts(" ruby -ne 'print if #{pat.inspect}'")
494
+ f.grep(pat) {|l|
495
+ puts "#{f.lineno}: #{l}"
496
+ return true
497
+ }
498
+ false
499
+ else
500
+ puts(" egrep '#{pat}'")
501
+ begin
502
+ stdin = $stdin.dup
503
+ $stdin.reopen(f)
504
+ system("egrep", pat)
505
+ ensure
506
+ $stdin.reopen(stdin)
507
+ end
508
+ end
509
+ end
510
+ ensure
511
+ rm_f "conftest*"
512
+ log_src(src)
513
+ end
514
+
515
+ # This is used internally by the have_macro? method.
516
+ def macro_defined?(macro, src, opt = "", &b)
517
+ src = src.sub(/[^\n]\z/, "\\&\n")
518
+ try_compile(src + <<"SRC", opt, &b)
519
+ /*top*/
520
+ #ifndef #{macro}
521
+ # error
522
+ >>>>>> #{macro} undefined <<<<<<
523
+ #endif
524
+ SRC
525
+ end
526
+
527
+ def try_run(src, opt = "", &b)
528
+ if try_link0(src, opt, &b)
529
+ xsystem("./conftest")
530
+ else
531
+ nil
532
+ end
533
+ ensure
534
+ rm_f "conftest*"
535
+ end
536
+
537
+ def install_files(mfile, ifiles, map = nil, srcprefix = nil)
538
+ ifiles or return
539
+ ifiles.empty? and return
540
+ srcprefix ||= '$(srcdir)'
541
+ Config::expand(srcdir = srcprefix.dup)
542
+ dirs = []
543
+ path = Hash.new {|h, i| h[i] = dirs.push([i])[-1]}
544
+ ifiles.each do |files, dir, prefix|
545
+ dir = map_dir(dir, map)
546
+ prefix &&= %r|\A#{Regexp.quote(prefix)}/?|
547
+ if /\A\.\// =~ files
548
+ # install files which are in current working directory.
549
+ files = files[2..-1]
550
+ len = nil
551
+ else
552
+ # install files which are under the $(srcdir).
553
+ files = File.join(srcdir, files)
554
+ len = srcdir.size
555
+ end
556
+ f = nil
557
+ Dir.glob(files) do |f|
558
+ f[0..len] = "" if len
559
+ case File.basename(f)
560
+ when *$NONINSTALLFILES
561
+ next
562
+ end
563
+ d = File.dirname(f)
564
+ d.sub!(prefix, "") if prefix
565
+ d = (d.empty? || d == ".") ? dir : File.join(dir, d)
566
+ f = File.join(srcprefix, f) if len
567
+ path[d] << f
568
+ end
569
+ unless len or f
570
+ d = File.dirname(files)
571
+ d.sub!(prefix, "") if prefix
572
+ d = (d.empty? || d == ".") ? dir : File.join(dir, d)
573
+ path[d] << files
574
+ end
575
+ end
576
+ dirs
577
+ end
578
+
579
+ def install_rb(mfile, dest, srcdir = nil)
580
+ install_files(mfile, [["lib/**/*.rb", dest, "lib"]], nil, srcdir)
581
+ end
582
+
583
+ def append_library(libs, lib) # :no-doc:
584
+ format(LIBARG, lib) + " " + libs
585
+ end
586
+
587
+ def message(*s)
588
+ unless Logging.quiet and not $VERBOSE
589
+ printf(*s)
590
+ $stdout.flush
591
+ end
592
+ end
593
+
594
+ # This emits a string to stdout that allows users to see the results of the
595
+ # various have* and find* methods as they are tested.
596
+ #
597
+ # Internal use only.
598
+ #
599
+ def checking_for(m, fmt = nil)
600
+ f = caller[0][/in `(.*)'$/, 1] and f << ": " #` for vim
601
+ m = "checking #{/\Acheck/ =~ f ? '' : 'for '}#{m}... "
602
+ message "%s", m
603
+ a = r = nil
604
+ Logging::postpone do
605
+ r = yield
606
+ a = (fmt ? fmt % r : r ? "yes" : "no") << "\n"
607
+ "#{f}#{m}-------------------- #{a}\n"
608
+ end
609
+ message(a)
610
+ Logging::message "--------------------\n\n"
611
+ r
612
+ end
613
+
614
+ def checking_message(target, place = nil, opt = nil)
615
+ [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)|
616
+ if noun
617
+ [[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
618
+ if noun.respond_to?(meth)
619
+ break noun = noun.send(meth, *args)
620
+ end
621
+ end
622
+ msg << " #{pre} #{noun}" unless noun.empty?
623
+ end
624
+ msg
625
+ end
626
+ end
627
+
628
+ # :startdoc:
629
+
630
+ # Returns whether or not +macro+ is defined either in the common header
631
+ # files or within any +headers+ you provide.
632
+ #
633
+ # Any options you pass to +opt+ are passed along to the compiler.
634
+ #
635
+ def have_macro(macro, headers = nil, opt = "", &b)
636
+ checking_for checking_message(macro, headers, opt) do
637
+ macro_defined?(macro, cpp_include(headers), opt, &b)
638
+ end
639
+ end
640
+
641
+ # Returns whether or not the given entry point +func+ can be found within
642
+ # +lib+. If +func+ is nil, the 'main()' entry point is used by default.
643
+ # If found, it adds the library to list of libraries to be used when linking
644
+ # your extension.
645
+ #
646
+ # If +headers+ are provided, it will include those header files as the
647
+ # header files it looks in when searching for +func+.
648
+ #
649
+ # The real name of the library to be linked can be altered by
650
+ # '--with-FOOlib' configuration option.
651
+ #
652
+ def have_library(lib, func = nil, headers = nil, &b)
653
+ func = "main" if !func or func.empty?
654
+ lib = with_config(lib+'lib', lib)
655
+ checking_for checking_message("#{func}()", LIBARG%lib) do
656
+ if COMMON_LIBS.include?(lib)
657
+ true
658
+ else
659
+ libs = append_library($libs, lib)
660
+ if try_func(func, libs, headers, &b)
661
+ $libs = libs
662
+ true
663
+ else
664
+ false
665
+ end
666
+ end
667
+ end
668
+ end
669
+
670
+ # Returns whether or not the entry point +func+ can be found within the library
671
+ # +lib+ in one of the +paths+ specified, where +paths+ is an array of strings.
672
+ # If +func+ is nil , then the main() function is used as the entry point.
673
+ #
674
+ # If +lib+ is found, then the path it was found on is added to the list of
675
+ # library paths searched and linked against.
676
+ #
677
+ def find_library(lib, func, *paths, &b)
678
+ func = "main" if !func or func.empty?
679
+ lib = with_config(lib+'lib', lib)
680
+ paths = paths.collect {|path| path.split(File::PATH_SEPARATOR)}.flatten
681
+ checking_for "#{func}() in #{LIBARG%lib}" do
682
+ libpath = $LIBPATH
683
+ libs = append_library($libs, lib)
684
+ begin
685
+ until r = try_func(func, libs, &b) or paths.empty?
686
+ $LIBPATH = libpath | [paths.shift]
687
+ end
688
+ if r
689
+ $libs = libs
690
+ libpath = nil
691
+ end
692
+ ensure
693
+ $LIBPATH = libpath if libpath
694
+ end
695
+ r
696
+ end
697
+ end
698
+
699
+ # Returns whether or not the function +func+ can be found in the common
700
+ # header files, or within any +headers+ that you provide. If found, a
701
+ # macro is passed as a preprocessor constant to the compiler using the
702
+ # function name, in uppercase, prepended with 'HAVE_'.
703
+ #
704
+ # For example, if have_func('foo') returned true, then the HAVE_FOO
705
+ # preprocessor macro would be passed to the compiler.
706
+ #
707
+ def have_func(func, headers = nil, &b)
708
+ checking_for checking_message("#{func}()", headers) do
709
+ if try_func(func, $libs, headers, &b)
710
+ $defs.push(format("-DHAVE_%s", func.tr_cpp))
711
+ true
712
+ else
713
+ false
714
+ end
715
+ end
716
+ end
717
+
718
+ # Returns whether or not the variable +var+ can be found in the common
719
+ # header files, or within any +headers+ that you provide. If found, a
720
+ # macro is passed as a preprocessor constant to the compiler using the
721
+ # variable name, in uppercase, prepended with 'HAVE_'.
722
+ #
723
+ # For example, if have_var('foo') returned true, then the HAVE_FOO
724
+ # preprocessor macro would be passed to the compiler.
725
+ #
726
+ def have_var(var, headers = nil, &b)
727
+ checking_for checking_message(var, headers) do
728
+ if try_var(var, headers, &b)
729
+ $defs.push(format("-DHAVE_%s", var.tr_cpp))
730
+ true
731
+ else
732
+ false
733
+ end
734
+ end
735
+ end
736
+
737
+ # Returns whether or not the given +header+ file can be found on your system.
738
+ # If found, a macro is passed as a preprocessor constant to the compiler using
739
+ # the header file name, in uppercase, prepended with 'HAVE_'.
740
+ #
741
+ # For example, if have_header('foo.h') returned true, then the HAVE_FOO_H
742
+ # preprocessor macro would be passed to the compiler.
743
+ #
744
+ def have_header(header, &b)
745
+ checking_for header do
746
+ if try_cpp(cpp_include(header), &b)
747
+ $defs.push(format("-DHAVE_%s", header.tr("a-z./\055", "A-Z___")))
748
+ true
749
+ else
750
+ false
751
+ end
752
+ end
753
+ end
754
+
755
+ # Instructs mkmf to search for the given +header+ in any of the +paths+
756
+ # provided, and returns whether or not it was found in those paths.
757
+ #
758
+ # If the header is found then the path it was found on is added to the list
759
+ # of included directories that are sent to the compiler (via the -I switch).
760
+ #
761
+ def find_header(header, *paths)
762
+ message = checking_message(header, paths)
763
+ header = cpp_include(header)
764
+ checking_for message do
765
+ if try_cpp(header)
766
+ true
767
+ else
768
+ found = false
769
+ paths.each do |dir|
770
+ opt = "-I#{dir}".quote
771
+ if try_cpp(header, opt)
772
+ $INCFLAGS << " " << opt
773
+ found = true
774
+ break
775
+ end
776
+ end
777
+ found
778
+ end
779
+ end
780
+ end
781
+
782
+ # Returns whether or not the struct of type +type+ contains +member+. If
783
+ # it does not, or the struct type can't be found, then false is returned. You
784
+ # may optionally specify additional +headers+ in which to look for the struct
785
+ # (in addition to the common header files).
786
+ #
787
+ # If found, a macro is passed as a preprocessor constant to the compiler using
788
+ # the member name, in uppercase, prepended with 'HAVE_ST_'.
789
+ #
790
+ # For example, if have_struct_member('struct foo', 'bar') returned true, then the
791
+ # HAVE_ST_BAR preprocessor macro would be passed to the compiler.
792
+ #
793
+ def have_struct_member(type, member, headers = nil, &b)
794
+ checking_for checking_message("#{type}.#{member}", headers) do
795
+ if try_compile(<<"SRC", &b)
796
+ #{COMMON_HEADERS}
797
+ #{cpp_include(headers)}
798
+ /*top*/
799
+ int main() { return 0; }
800
+ int s = (char *)&((#{type}*)0)->#{member} - (char *)0;
801
+ SRC
802
+ $defs.push(format("-DHAVE_ST_%s", member.tr_cpp))
803
+ true
804
+ else
805
+ false
806
+ end
807
+ end
808
+ end
809
+
810
+ def try_type(type, headers = nil, opt = "", &b)
811
+ if try_compile(<<"SRC", opt, &b)
812
+ #{COMMON_HEADERS}
813
+ #{cpp_include(headers)}
814
+ /*top*/
815
+ typedef #{type} conftest_type;
816
+ int conftestval[sizeof(conftest_type)?1:-1];
817
+ SRC
818
+ $defs.push(format("-DHAVE_TYPE_%s", type.tr_cpp))
819
+ true
820
+ else
821
+ false
822
+ end
823
+ end
824
+
825
+ # Returns whether or not the static type +type+ is defined. You may
826
+ # optionally pass additional +headers+ to check against in addition to the
827
+ # common header files.
828
+ #
829
+ # You may also pass additional flags to +opt+ which are then passed along to
830
+ # the compiler.
831
+ #
832
+ # If found, a macro is passed as a preprocessor constant to the compiler using
833
+ # the type name, in uppercase, prepended with 'HAVE_TYPE_'.
834
+ #
835
+ # For example, if have_type('foo') returned true, then the HAVE_TYPE_FOO
836
+ # preprocessor macro would be passed to the compiler.
837
+ #
838
+ def have_type(type, headers = nil, opt = "", &b)
839
+ checking_for checking_message(type, headers, opt) do
840
+ try_type(type, headers, opt, &b)
841
+ end
842
+ end
843
+
844
+ # Returns where the static type +type+ is defined.
845
+ #
846
+ # You may also pass additional flags to +opt+ which are then passed along to
847
+ # the compiler.
848
+ #
849
+ # See also +have_type+.
850
+ #
851
+ def find_type(type, opt, *headers, &b)
852
+ opt ||= ""
853
+ fmt = "not found"
854
+ def fmt.%(x)
855
+ x ? x.respond_to?(:join) ? x.join(",") : x : self
856
+ end
857
+ checking_for checking_message(type, nil, opt), fmt do
858
+ headers.find do |h|
859
+ try_type(type, h, opt, &b)
860
+ end
861
+ end
862
+ end
863
+
864
+ def try_const(const, headers = nil, opt = "", &b)
865
+ const, type = *const
866
+ if try_compile(<<"SRC", opt, &b)
867
+ #{COMMON_HEADERS}
868
+ #{cpp_include(headers)}
869
+ /*top*/
870
+ typedef #{type || 'int'} conftest_type;
871
+ conftest_type conftestval = #{type ? '' : '(int)'}#{const};
872
+ SRC
873
+ $defs.push(format("-DHAVE_CONST_%s", const.tr_cpp))
874
+ true
875
+ else
876
+ false
877
+ end
878
+ end
879
+
880
+ # Returns whether or not the constant +const+ is defined. You may
881
+ # optionally pass the +type+ of +const+ as <code>[const, type]</code>,
882
+ # like as:
883
+ #
884
+ # have_const(%w[PTHREAD_MUTEX_INITIALIZER pthread_mutex_t], "pthread.h")
885
+ #
886
+ # You may also pass additional +headers+ to check against in addition
887
+ # to the common header files, and additional flags to +opt+ which are
888
+ # then passed along to the compiler.
889
+ #
890
+ # If found, a macro is passed as a preprocessor constant to the compiler using
891
+ # the type name, in uppercase, prepended with 'HAVE_CONST_'.
892
+ #
893
+ # For example, if have_const('foo') returned true, then the HAVE_CONST_FOO
894
+ # preprocessor macro would be passed to the compiler.
895
+ #
896
+ def have_const(const, headers = nil, opt = "", &b)
897
+ checking_for checking_message([*const].compact.join(' '), headers, opt) do
898
+ try_const(const, headers, opt, &b)
899
+ end
900
+ end
901
+
902
+ # Returns the size of the given +type+. You may optionally specify additional
903
+ # +headers+ to search in for the +type+.
904
+ #
905
+ # If found, a macro is passed as a preprocessor constant to the compiler using
906
+ # the type name, in uppercase, prepended with 'SIZEOF_', followed by the type
907
+ # name, followed by '=X' where 'X' is the actual size.
908
+ #
909
+ # For example, if check_sizeof('mystruct') returned 12, then the
910
+ # SIZEOF_MYSTRUCT=12 preprocessor macro would be passed to the compiler.
911
+ #
912
+ def check_sizeof(type, headers = nil, &b)
913
+ expr = "sizeof(#{type})"
914
+ fmt = "%d"
915
+ def fmt.%(x)
916
+ x ? super : "failed"
917
+ end
918
+ checking_for checking_message("size of #{type}", headers), fmt do
919
+ if size = try_constant(expr, headers, &b)
920
+ $defs.push(format("-DSIZEOF_%s=%d", type.tr_cpp, size))
921
+ size
922
+ end
923
+ end
924
+ end
925
+
926
+ # :stopdoc:
927
+
928
+ # Used internally by the what_type? method to determine if +type+ is a scalar
929
+ # pointer.
930
+ def scalar_ptr_type?(type, member = nil, headers = nil, &b)
931
+ try_compile(<<"SRC", &b) # pointer
932
+ #{COMMON_HEADERS}
933
+ #{cpp_include(headers)}
934
+ /*top*/
935
+ volatile #{type} conftestval;
936
+ int main() { return 0; }
937
+ int t() {return (int)(1-*(conftestval#{member ? ".#{member}" : ""}));}
938
+ SRC
939
+ end
940
+
941
+ # Used internally by the what_type? method to determine if +type+ is a scalar
942
+ # pointer.
943
+ def scalar_type?(type, member = nil, headers = nil, &b)
944
+ try_compile(<<"SRC", &b) # pointer
945
+ #{COMMON_HEADERS}
946
+ #{cpp_include(headers)}
947
+ /*top*/
948
+ volatile #{type} conftestval;
949
+ int main() { return 0; }
950
+ int t() {return (int)(1-(conftestval#{member ? ".#{member}" : ""}));}
951
+ SRC
952
+ end
953
+
954
+ def what_type?(type, member = nil, headers = nil, &b)
955
+ m = "#{type}"
956
+ name = type
957
+ if member
958
+ m << "." << member
959
+ name = "(((#{type} *)0)->#{member})"
960
+ end
961
+ fmt = "seems %s"
962
+ def fmt.%(x)
963
+ x ? super : "unknown"
964
+ end
965
+ checking_for checking_message(m, headers), fmt do
966
+ if scalar_ptr_type?(type, member, headers, &b)
967
+ if try_static_assert("sizeof(*#{name}) == 1", headers)
968
+ "string"
969
+ end
970
+ elsif scalar_type?(type, member, headers, &b)
971
+ if try_static_assert("sizeof(#{name}) > sizeof(long)", headers)
972
+ "long long"
973
+ elsif try_static_assert("sizeof(#{name}) > sizeof(int)", headers)
974
+ "long"
975
+ elsif try_static_assert("sizeof(#{name}) > sizeof(short)", headers)
976
+ "int"
977
+ elsif try_static_assert("sizeof(#{name}) > 1", headers)
978
+ "short"
979
+ else
980
+ "char"
981
+ end
982
+ end
983
+ end
984
+ end
985
+
986
+ # This method is used internally by the find_executable method.
987
+ #
988
+ # Internal use only.
989
+ #
990
+ def find_executable0(bin, path = nil)
991
+ ext = config_string('EXEEXT')
992
+ if File.expand_path(bin) == bin
993
+ return bin if File.executable?(bin)
994
+ ext and File.executable?(file = bin + ext) and return file
995
+ return nil
996
+ end
997
+ if path ||= ENV['PATH']
998
+ path = path.split(File::PATH_SEPARATOR)
999
+ else
1000
+ path = %w[/usr/local/bin /usr/ucb /usr/bin /bin]
1001
+ end
1002
+ file = nil
1003
+ path.each do |dir|
1004
+ return file if File.executable?(file = File.join(dir, bin))
1005
+ return file if ext and File.executable?(file << ext)
1006
+ end
1007
+ nil
1008
+ end
1009
+
1010
+ # :startdoc:
1011
+
1012
+ # Searches for the executable +bin+ on +path+. The default path is your
1013
+ # PATH environment variable. If that isn't defined, it will resort to
1014
+ # searching /usr/local/bin, /usr/ucb, /usr/bin and /bin.
1015
+ #
1016
+ # If found, it will return the full path, including the executable name,
1017
+ # of where it was found.
1018
+ #
1019
+ # Note that this method does not actually affect the generated Makefile.
1020
+ #
1021
+ def find_executable(bin, path = nil)
1022
+ checking_for checking_message(bin, path) do
1023
+ find_executable0(bin, path)
1024
+ end
1025
+ end
1026
+
1027
+ # :stopdoc:
1028
+
1029
+ def arg_config(config, *defaults, &block)
1030
+ $arg_config << [config, *defaults]
1031
+ defaults << nil if !block and defaults.empty?
1032
+ $configure_args.fetch(config.tr('_', '-'), *defaults, &block)
1033
+ end
1034
+
1035
+ # :startdoc:
1036
+
1037
+ # Tests for the presence of a --with-<tt>config</tt> or --without-<tt>config</tt>
1038
+ # option. Returns true if the with option is given, false if the without
1039
+ # option is given, and the default value otherwise.
1040
+ #
1041
+ # This can be useful for adding custom definitions, such as debug information.
1042
+ #
1043
+ # Example:
1044
+ #
1045
+ # if with_config("debug")
1046
+ # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1047
+ # end
1048
+ #
1049
+ def with_config(config, *defaults)
1050
+ config = config.sub(/^--with[-_]/, '')
1051
+ val = arg_config("--with-"+config) do
1052
+ if arg_config("--without-"+config)
1053
+ false
1054
+ elsif block_given?
1055
+ yield(config, *defaults)
1056
+ else
1057
+ break *defaults
1058
+ end
1059
+ end
1060
+ case val
1061
+ when "yes"
1062
+ true
1063
+ when "no"
1064
+ false
1065
+ else
1066
+ val
1067
+ end
1068
+ end
1069
+
1070
+ # Tests for the presence of an --enable-<tt>config</tt> or
1071
+ # --disable-<tt>config</tt> option. Returns true if the enable option is given,
1072
+ # false if the disable option is given, and the default value otherwise.
1073
+ #
1074
+ # This can be useful for adding custom definitions, such as debug information.
1075
+ #
1076
+ # Example:
1077
+ #
1078
+ # if enable_config("debug")
1079
+ # $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
1080
+ # end
1081
+ #
1082
+ def enable_config(config, *defaults)
1083
+ if arg_config("--enable-"+config)
1084
+ true
1085
+ elsif arg_config("--disable-"+config)
1086
+ false
1087
+ elsif block_given?
1088
+ yield(config, *defaults)
1089
+ else
1090
+ return *defaults
1091
+ end
1092
+ end
1093
+
1094
+ # Generates a header file consisting of the various macro definitions generated
1095
+ # by other methods such as have_func and have_header. These are then wrapped in
1096
+ # a custom #ifndef based on the +header+ file name, which defaults to
1097
+ # 'extconf.h'.
1098
+ #
1099
+ # For example:
1100
+ #
1101
+ # # extconf.rb
1102
+ # require 'mkmf'
1103
+ # have_func('realpath')
1104
+ # have_header('sys/utime.h')
1105
+ # create_header
1106
+ # create_makefile('foo')
1107
+ #
1108
+ # The above script would generate the following extconf.h file:
1109
+ #
1110
+ # #ifndef EXTCONF_H
1111
+ # #define EXTCONF_H
1112
+ # #define HAVE_REALPATH 1
1113
+ # #define HAVE_SYS_UTIME_H 1
1114
+ # #endif
1115
+ #
1116
+ # Given that the create_header method generates a file based on definitions
1117
+ # set earlier in your extconf.rb file, you will probably want to make this
1118
+ # one of the last methods you call in your script.
1119
+ #
1120
+ def create_header(header = "extconf.h")
1121
+ message "creating %s\n", header
1122
+ sym = header.tr("a-z./\055", "A-Z___")
1123
+ hdr = ["#ifndef #{sym}\n#define #{sym}\n"]
1124
+ for line in $defs
1125
+ case line
1126
+ when /^-D([^=]+)(?:=(.*))?/
1127
+ hdr << "#define #$1 #{$2 ? Shellwords.shellwords($2)[0] : 1}\n"
1128
+ when /^-U(.*)/
1129
+ hdr << "#undef #$1\n"
1130
+ end
1131
+ end
1132
+ hdr << "#endif\n"
1133
+ hdr = hdr.join
1134
+ unless (IO.read(header) == hdr rescue false)
1135
+ open(header, "w") do |hfile|
1136
+ hfile.write(hdr)
1137
+ end
1138
+ end
1139
+ $extconf_h = header
1140
+ end
1141
+
1142
+ # Sets a +target+ name that the user can then use to configure various 'with'
1143
+ # options with on the command line by using that name. For example, if the
1144
+ # target is set to "foo", then the user could use the --with-foo-dir command
1145
+ # line option.
1146
+ #
1147
+ # You may pass along additional 'include' or 'lib' defaults via the +idefault+
1148
+ # and +ldefault+ parameters, respectively.
1149
+ #
1150
+ # Note that dir_config only adds to the list of places to search for libraries
1151
+ # and include files. It does not link the libraries into your application.
1152
+ #
1153
+ def dir_config(target, idefault=nil, ldefault=nil)
1154
+ if dir = with_config(target + "-dir", (idefault unless ldefault))
1155
+ defaults = Array === dir ? dir : dir.split(File::PATH_SEPARATOR)
1156
+ idefault = ldefault = nil
1157
+ end
1158
+
1159
+ idir = with_config(target + "-include", idefault)
1160
+ $arg_config.last[1] ||= "${#{target}-dir}/include"
1161
+ ldir = with_config(target + "-lib", ldefault)
1162
+ $arg_config.last[1] ||= "${#{target}-dir}/lib"
1163
+
1164
+ idirs = idir ? Array === idir ? idir : idir.split(File::PATH_SEPARATOR) : []
1165
+ if defaults
1166
+ idirs.concat(defaults.collect {|dir| dir + "/include"})
1167
+ idir = ([idir] + idirs).compact.join(File::PATH_SEPARATOR)
1168
+ end
1169
+ unless idirs.empty?
1170
+ idirs.collect! {|dir| "-I" + dir}
1171
+ idirs -= Shellwords.shellwords($CPPFLAGS)
1172
+ unless idirs.empty?
1173
+ $CPPFLAGS = (idirs.quote << $CPPFLAGS).join(" ")
1174
+ end
1175
+ end
1176
+
1177
+ ldirs = ldir ? Array === ldir ? ldir : ldir.split(File::PATH_SEPARATOR) : []
1178
+ if defaults
1179
+ ldirs.concat(defaults.collect {|dir| dir + "/lib"})
1180
+ ldir = ([ldir] + ldirs).compact.join(File::PATH_SEPARATOR)
1181
+ end
1182
+ $LIBPATH = ldirs | $LIBPATH
1183
+
1184
+ [idir, ldir]
1185
+ end
1186
+
1187
+ # :stopdoc:
1188
+
1189
+ # Handles meta information about installed libraries. Uses your platform's
1190
+ # pkg-config program if it has one.
1191
+ def pkg_config(pkg)
1192
+ if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
1193
+ # iff package specific config command is given
1194
+ get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1195
+ elsif ($PKGCONFIG ||=
1196
+ (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
1197
+ find_executable0(pkgconfig) && pkgconfig) and
1198
+ system("#{$PKGCONFIG} --exists #{pkg}")
1199
+ # default to pkg-config command
1200
+ get = proc {|opt| `#{$PKGCONFIG} --#{opt} #{pkg}`.chomp}
1201
+ elsif find_executable0(pkgconfig = "#{pkg}-config")
1202
+ # default to package specific config command, as a last resort.
1203
+ get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
1204
+ end
1205
+ if get
1206
+ cflags = get['cflags']
1207
+ ldflags = get['libs']
1208
+ libs = get['libs-only-l']
1209
+ ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
1210
+ $CFLAGS += " " << cflags
1211
+ $LDFLAGS += " " << ldflags
1212
+ $libs += " " << libs
1213
+ Logging::message "package configuration for %s\n", pkg
1214
+ Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
1215
+ cflags, ldflags, libs
1216
+ [cflags, ldflags, libs]
1217
+ else
1218
+ Logging::message "package configuration for %s is not found\n", pkg
1219
+ nil
1220
+ end
1221
+ end
1222
+
1223
+ def with_destdir(dir)
1224
+ dir = dir.sub($dest_prefix_pattern, '')
1225
+ /\A\$[\(\{]/ =~ dir ? dir : "$(DESTDIR)"+dir
1226
+ end
1227
+
1228
+ # Converts forward slashes to backslashes. Aimed at MS Windows.
1229
+ #
1230
+ # Internal use only.
1231
+ #
1232
+ def winsep(s)
1233
+ s.tr('/', '\\')
1234
+ end
1235
+
1236
+ # Converts native path to format acceptable in Makefile
1237
+ #
1238
+ # Internal use only.
1239
+ #
1240
+ if !CROSS_COMPILING
1241
+ case CONFIG['build_os']
1242
+ when 'mingw32'
1243
+ def mkintpath(path)
1244
+ # mingw uses make from msys and it needs special care
1245
+ # converts from C:\some\path to /C/some/path
1246
+ path = path.dup
1247
+ path.tr!('\\', '/')
1248
+ path.sub!(/\A([A-Za-z]):(?=\/)/, '/\1')
1249
+ path
1250
+ end
1251
+ end
1252
+ end
1253
+ unless defined?(mkintpath)
1254
+ def mkintpath(path)
1255
+ path
1256
+ end
1257
+ end
1258
+
1259
+ def configuration(srcdir)
1260
+ mk = []
1261
+ vpath = %w[$(srcdir) $(topdir) $(hdrdir)]
1262
+ if !CROSS_COMPILING
1263
+ case CONFIG['build_os']
1264
+ when 'cygwin'
1265
+ if CONFIG['target_os'] != 'cygwin'
1266
+ vpath.each {|p| p.sub!(/.*/, '$(shell cygpath -u \&)')}
1267
+ end
1268
+ when 'msdosdjgpp'
1269
+ CONFIG['PATH_SEPARATOR'] = ';'
1270
+ end
1271
+ end
1272
+ mk << %{
1273
+ SHELL = /bin/sh
1274
+
1275
+ #### Start of system configuration section. ####
1276
+ #{
1277
+ if $extmk
1278
+ "top_srcdir = " + $top_srcdir.sub(%r"\A#{Regexp.quote($topdir)}/", "$(topdir)/")
1279
+ end
1280
+ }
1281
+ srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2])}.quote}
1282
+ topdir = #{mkintpath($extmk ? CONFIG["topdir"] : $topdir).quote}
1283
+ hdrdir = #{$extmk ? mkintpath(CONFIG["hdrdir"]).quote : '$(topdir)'}
1284
+ VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
1285
+ }
1286
+ if $extmk
1287
+ mk << "RUBYLIB = -\nRUBYOPT = -rpurelib.rb\n"
1288
+ end
1289
+ if destdir = CONFIG["prefix"][$dest_prefix_pattern, 1]
1290
+ mk << "\nDESTDIR = #{destdir}\n"
1291
+ end
1292
+ CONFIG.each do |key, var|
1293
+ next unless /prefix$/ =~ key
1294
+ mk << "#{key} = #{with_destdir(var)}\n"
1295
+ end
1296
+ CONFIG.each do |key, var|
1297
+ next if /^abs_/ =~ key
1298
+ next unless /^(?:src|top|hdr|(.*))dir$/ =~ key and $1
1299
+ mk << "#{key} = #{with_destdir(var)}\n"
1300
+ end
1301
+ if !$extmk and !$configure_args.has_key?('--ruby') and
1302
+ sep = config_string('BUILD_FILE_SEPARATOR')
1303
+ sep = ":/=#{sep}"
1304
+ else
1305
+ sep = ""
1306
+ end
1307
+ extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ")<<" "
1308
+ mk << %{
1309
+ CC = #{CONFIG['CC']}
1310
+ LIBRUBY = #{CONFIG['LIBRUBY']}
1311
+ LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
1312
+ LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
1313
+ LIBRUBYARG_STATIC = #$LIBRUBYARG_STATIC
1314
+
1315
+ RUBY_EXTCONF_H = #{$extconf_h}
1316
+ CFLAGS = #{$static ? '' : CONFIG['CCDLFLAGS']} #$CFLAGS #$ARCH_FLAG
1317
+ INCFLAGS = -I. #$INCFLAGS
1318
+ DEFS = #{CONFIG['DEFS']}
1319
+ CPPFLAGS = #{extconf_h}#{$CPPFLAGS}
1320
+ CXXFLAGS = $(CFLAGS) #{CONFIG['CXXFLAGS']}
1321
+ ldflags = #{$LDFLAGS}
1322
+ dldflags = #{$DLDFLAGS}
1323
+ archflag = #{$ARCH_FLAG}
1324
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
1325
+ LDSHARED = #{CONFIG['LDSHARED']}
1326
+ AR = #{CONFIG['AR']}
1327
+ EXEEXT = #{CONFIG['EXEEXT']}
1328
+
1329
+ RUBY_INSTALL_NAME = #{CONFIG['RUBY_INSTALL_NAME']}
1330
+ RUBY_SO_NAME = #{CONFIG['RUBY_SO_NAME']}
1331
+ arch = #{CONFIG['arch']}
1332
+ sitearch = #{CONFIG['sitearch']}
1333
+ ruby_version = #{Config::CONFIG['ruby_version']}
1334
+ ruby = #{$ruby}
1335
+ RUBY = $(ruby#{sep})
1336
+ RM = #{config_string('RM') || '$(RUBY) -run -e rm -- -f'}
1337
+ MAKEDIRS = #{config_string('MAKEDIRS') || '@$(RUBY) -run -e mkdir -- -p'}
1338
+ INSTALL = #{config_string('INSTALL') || '@$(RUBY) -run -e install -- -vp'}
1339
+ INSTALL_PROG = #{config_string('INSTALL_PROG') || '$(INSTALL) -m 0755'}
1340
+ INSTALL_DATA = #{config_string('INSTALL_DATA') || '$(INSTALL) -m 0644'}
1341
+ COPY = #{config_string('CP') || '@$(RUBY) -run -e cp -- -v'}
1342
+
1343
+ #### End of system configuration section. ####
1344
+
1345
+ preload = #{$preload ? $preload.join(' ') : ''}
1346
+ }
1347
+ if $nmake == ?b
1348
+ mk.each do |x|
1349
+ x.gsub!(/^(MAKEDIRS|INSTALL_(?:PROG|DATA))+\s*=.*\n/) do
1350
+ "!ifndef " + $1 + "\n" +
1351
+ $& +
1352
+ "!endif\n"
1353
+ end
1354
+ end
1355
+ end
1356
+ mk
1357
+ end
1358
+
1359
+ def dummy_makefile(srcdir)
1360
+ configuration(srcdir) << <<RULES << CLEANINGS
1361
+ CLEANFILES = #{$cleanfiles.join(' ')}
1362
+ DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1363
+
1364
+ all install static install-so install-rb: Makefile
1365
+
1366
+ RULES
1367
+ end
1368
+ # :startdoc:
1369
+
1370
+ # Generates the Makefile for your extension, passing along any options and
1371
+ # preprocessor constants that you may have generated through other methods.
1372
+ #
1373
+ # The +target+ name should correspond the name of the global function name
1374
+ # defined within your C extension, minus the 'Init_'. For example, if your
1375
+ # C extension is defined as 'Init_foo', then your target would simply be 'foo'.
1376
+ #
1377
+ # If any '/' characters are present in the target name, only the last name
1378
+ # is interpreted as the target name, and the rest are considered toplevel
1379
+ # directory names, and the generated Makefile will be altered accordingly to
1380
+ # follow that directory structure.
1381
+ #
1382
+ # For example, if you pass 'test/foo' as a target name, your extension will
1383
+ # be installed under the 'test' directory. This means that in order to
1384
+ # load the file within a Ruby program later, that directory structure will
1385
+ # have to be followed, e.g. "require 'test/foo'".
1386
+ #
1387
+ # The +srcprefix+ should be used when your source files are not in the same
1388
+ # directory as your build script. This will not only eliminate the need for
1389
+ # you to manually copy the source files into the same directory as your build
1390
+ # script, but it also sets the proper +target_prefix+ in the generated
1391
+ # Makefile.
1392
+ #
1393
+ # Setting the +target_prefix+ will, in turn, install the generated binary in
1394
+ # a directory under your Config::CONFIG['sitearchdir'] that mimics your local
1395
+ # filesystem when you run 'make install'.
1396
+ #
1397
+ # For example, given the following file tree:
1398
+ #
1399
+ # ext/
1400
+ # extconf.rb
1401
+ # test/
1402
+ # foo.c
1403
+ #
1404
+ # And given the following code:
1405
+ #
1406
+ # create_makefile('test/foo', 'test')
1407
+ #
1408
+ # That will set the +target_prefix+ in the generated Makefile to 'test'. That,
1409
+ # in turn, will create the following file tree when installed via the
1410
+ # 'make install' command:
1411
+ #
1412
+ # /path/to/ruby/sitearchdir/test/foo.so
1413
+ #
1414
+ # It is recommended that you use this approach to generate your makefiles,
1415
+ # instead of copying files around manually, because some third party
1416
+ # libraries may depend on the +target_prefix+ being set properly.
1417
+ #
1418
+ # The +srcprefix+ argument can be used to override the default source
1419
+ # directory, i.e. the current directory . It is included as part of the VPATH
1420
+ # and added to the list of INCFLAGS.
1421
+ #
1422
+ def create_makefile(target, srcprefix = nil)
1423
+ $target = target
1424
+ libpath = $DEFLIBPATH|$LIBPATH
1425
+ message "creating Makefile\n"
1426
+ rm_f "conftest*"
1427
+ if CONFIG["DLEXT"] == $OBJEXT
1428
+ for lib in libs = $libs.split
1429
+ lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
1430
+ end
1431
+ $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
1432
+ end
1433
+
1434
+ if target.include?('/')
1435
+ target_prefix, target = File.split(target)
1436
+ target_prefix[0,0] = '/'
1437
+ else
1438
+ target_prefix = ""
1439
+ end
1440
+
1441
+ srcprefix ||= '$(srcdir)'
1442
+ Config::expand(srcdir = srcprefix.dup)
1443
+
1444
+ if not $objs
1445
+ $objs = []
1446
+ srcs = Dir[File.join(srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
1447
+ for f in srcs
1448
+ obj = File.basename(f, ".*") << ".o"
1449
+ $objs.push(obj) unless $objs.index(obj)
1450
+ end
1451
+ elsif !(srcs = $srcs)
1452
+ srcs = $objs.collect {|obj| obj.sub(/\.o\z/, '.c')}
1453
+ end
1454
+ $srcs = srcs
1455
+ for i in $objs
1456
+ i.sub!(/\.o\z/, ".#{$OBJEXT}")
1457
+ end
1458
+ $objs = $objs.join(" ")
1459
+
1460
+ target = nil if $objs == ""
1461
+
1462
+ if target and EXPORT_PREFIX
1463
+ if File.exist?(File.join(srcdir, target + '.def'))
1464
+ deffile = "$(srcdir)/$(TARGET).def"
1465
+ unless EXPORT_PREFIX.empty?
1466
+ makedef = %{-pe "sub!(/^(?=\\w)/,'#{EXPORT_PREFIX}') unless 1../^EXPORTS$/i"}
1467
+ end
1468
+ else
1469
+ makedef = %{-e "puts 'EXPORTS', '#{EXPORT_PREFIX}Init_$(TARGET)'"}
1470
+ end
1471
+ if makedef
1472
+ $distcleanfiles << '$(DEFFILE)'
1473
+ origdef = deffile
1474
+ deffile = "$(TARGET)-$(arch).def"
1475
+ end
1476
+ end
1477
+ origdef ||= ''
1478
+
1479
+ libpath = libpathflag(libpath)
1480
+
1481
+ dllib = target ? "$(TARGET).#{CONFIG['DLEXT']}" : ""
1482
+ staticlib = target ? "$(TARGET).#$LIBEXT" : ""
1483
+ mfile = open("Makefile", "wb")
1484
+ mfile.print configuration(srcprefix)
1485
+ mfile.print "
1486
+ libpath = #{($DEFLIBPATH|$LIBPATH).join(" ")}
1487
+ LIBPATH = #{libpath}
1488
+ DEFFILE = #{deffile}
1489
+
1490
+ CLEANFILES = #{$cleanfiles.join(' ')}
1491
+ DISTCLEANFILES = #{$distcleanfiles.join(' ')}
1492
+
1493
+ extout = #{$extout}
1494
+ extout_prefix = #{$extout_prefix}
1495
+ target_prefix = #{target_prefix}
1496
+ LOCAL_LIBS = #{$LOCAL_LIBS}
1497
+ LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
1498
+ SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
1499
+ OBJS = #{$objs}
1500
+ TARGET = #{target}
1501
+ DLLIB = #{dllib}
1502
+ EXTSTATIC = #{$static || ""}
1503
+ STATIC_LIB = #{staticlib unless $static.nil?}
1504
+ #{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""}
1505
+ "
1506
+ install_dirs.each {|d| mfile.print("%-14s= %s\n" % d) if /^[[:upper:]]/ =~ d[0]}
1507
+ n = ($extout ? '$(RUBYARCHDIR)/' : '') + '$(TARGET).'
1508
+ mfile.print "
1509
+ TARGET_SO = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
1510
+ CLEANLIBS = #{n}#{CONFIG['DLEXT']} #{n}il? #{n}tds #{n}map
1511
+ CLEANOBJS = *.#{$OBJEXT} *.#{$LIBEXT} *.s[ol] *.pdb *.exp *.bak
1512
+
1513
+ all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
1514
+ static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
1515
+ "
1516
+ mfile.print CLEANINGS
1517
+ dirs = []
1518
+ mfile.print "install: install-so install-rb\n\n"
1519
+ sodir = (dir = "$(RUBYARCHDIR)").dup
1520
+ mfile.print("install-so: ")
1521
+ if target
1522
+ f = "$(DLLIB)"
1523
+ dest = "#{dir}/#{f}"
1524
+ mfile.puts dir, "install-so: #{dest}"
1525
+ unless $extout
1526
+ mfile.print "#{dest}: #{f}\n"
1527
+ if (sep = config_string('BUILD_FILE_SEPARATOR'))
1528
+ f.gsub!("/", sep)
1529
+ dir.gsub!("/", sep)
1530
+ sep = ":/="+sep
1531
+ f.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
1532
+ f.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
1533
+ dir.gsub!(/(\$\(\w+)(\))/) {$1+sep+$2}
1534
+ dir.gsub!(/(\$\{\w+)(\})/) {$1+sep+$2}
1535
+ end
1536
+ mfile.print "\t$(INSTALL_PROG) #{f} #{dir}\n"
1537
+ if defined?($installed_list)
1538
+ mfile.print "\t@echo #{dir}/#{File.basename(f)}>>$(INSTALLED_LIST)\n"
1539
+ end
1540
+ end
1541
+ else
1542
+ mfile.puts "Makefile"
1543
+ end
1544
+ mfile.print("install-rb: pre-install-rb install-rb-default\n")
1545
+ mfile.print("install-rb-default: pre-install-rb-default\n")
1546
+ mfile.print("pre-install-rb: Makefile\n")
1547
+ mfile.print("pre-install-rb-default: Makefile\n")
1548
+ for sfx, i in [["-default", [["lib/**/*.rb", "$(RUBYLIBDIR)", "lib"]]], ["", $INSTALLFILES]]
1549
+ files = install_files(mfile, i, nil, srcprefix) or next
1550
+ for dir, *files in files
1551
+ unless dirs.include?(dir)
1552
+ dirs << dir
1553
+ mfile.print "pre-install-rb#{sfx}: #{dir}\n"
1554
+ end
1555
+ files.each do |f|
1556
+ dest = "#{dir}/#{File.basename(f)}"
1557
+ mfile.print("install-rb#{sfx}: #{dest}\n")
1558
+ mfile.print("#{dest}: #{f} #{dir}\n\t$(#{$extout ? 'COPY' : 'INSTALL_DATA'}) ")
1559
+ sep = config_string('BUILD_FILE_SEPARATOR')
1560
+ if sep
1561
+ f = f.gsub("/", sep)
1562
+ sep = ":/="+sep
1563
+ f = f.gsub(/(\$\(\w+)(\))/) {$1+sep+$2}
1564
+ f = f.gsub(/(\$\{\w+)(\})/) {$1+sep+$2}
1565
+ else
1566
+ sep = ""
1567
+ end
1568
+ mfile.print("#{f} $(@D#{sep})\n")
1569
+ if defined?($installed_list) and !$extout
1570
+ mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
1571
+ end
1572
+ end
1573
+ end
1574
+ end
1575
+ dirs.unshift(sodir) if target and !dirs.include?(sodir)
1576
+ dirs.each {|dir| mfile.print "#{dir}:\n\t$(MAKEDIRS) $@\n"}
1577
+
1578
+ mfile.print <<-SITEINSTALL
1579
+
1580
+ site-install: site-install-so site-install-rb
1581
+ site-install-so: install-so
1582
+ site-install-rb: install-rb
1583
+
1584
+ SITEINSTALL
1585
+
1586
+ return unless target
1587
+
1588
+ mfile.puts SRC_EXT.collect {|ext| ".path.#{ext} = $(VPATH)"} if $nmake == ?b
1589
+ mfile.print ".SUFFIXES: .#{SRC_EXT.join(' .')} .#{$OBJEXT}\n"
1590
+ mfile.print "\n"
1591
+
1592
+ CXX_EXT.each do |ext|
1593
+ COMPILE_RULES.each do |rule|
1594
+ mfile.printf(rule, ext, $OBJEXT)
1595
+ mfile.printf("\n\t%s\n\n", COMPILE_CXX)
1596
+ end
1597
+ end
1598
+ %w[c].each do |ext|
1599
+ COMPILE_RULES.each do |rule|
1600
+ mfile.printf(rule, ext, $OBJEXT)
1601
+ mfile.printf("\n\t%s\n\n", COMPILE_C)
1602
+ end
1603
+ end
1604
+
1605
+ mfile.print "$(RUBYARCHDIR)/" if $extout
1606
+ mfile.print "$(DLLIB): "
1607
+ mfile.print "$(DEFFILE) " if makedef
1608
+ mfile.print "$(OBJS) Makefile\n"
1609
+ mfile.print "\t@-$(RM) $@\n"
1610
+ mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout
1611
+ link_so = LINK_SO.gsub(/^/, "\t")
1612
+ mfile.print link_so, "\n\n"
1613
+ unless $static.nil?
1614
+ mfile.print "$(STATIC_LIB): $(OBJS)\n\t"
1615
+ mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
1616
+ config_string('RANLIB') do |ranlib|
1617
+ mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
1618
+ end
1619
+ end
1620
+ mfile.print "\n\n"
1621
+ if makedef
1622
+ mfile.print "$(DEFFILE): #{origdef}\n"
1623
+ mfile.print "\t$(RUBY) #{makedef} #{origdef} > $@\n\n"
1624
+ end
1625
+
1626
+ depend = File.join(srcdir, "depend")
1627
+ if File.exist?(depend)
1628
+ suffixes = []
1629
+ depout = []
1630
+ open(depend, "r") do |dfile|
1631
+ mfile.printf "###\n"
1632
+ cont = implicit = nil
1633
+ impconv = proc do
1634
+ COMPILE_RULES.each {|rule| depout << (rule % implicit[0]) << implicit[1]}
1635
+ implicit = nil
1636
+ end
1637
+ ruleconv = proc do |line|
1638
+ if implicit
1639
+ if /\A\t/ =~ line
1640
+ implicit[1] << line
1641
+ next
1642
+ else
1643
+ impconv[]
1644
+ end
1645
+ end
1646
+ if m = /\A\.(\w+)\.(\w+)(?:\s*:)/.match(line)
1647
+ suffixes << m[1] << m[2]
1648
+ implicit = [[m[1], m[2]], [m.post_match]]
1649
+ next
1650
+ elsif RULE_SUBST and /\A(?!\s*\w+\s*=)[$\w][^#]*:/ =~ line
1651
+ line.gsub!(%r"(\s)(?!\.)([^$(){}+=:\s\/\\,]+)(?=\s|\z)") {$1 + RULE_SUBST % $2}
1652
+ end
1653
+ depout << line
1654
+ end
1655
+ while line = dfile.gets()
1656
+ line.gsub!(/\.o\b/, ".#{$OBJEXT}")
1657
+ line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h) if $config_h
1658
+ if /(?:^|[^\\])(?:\\\\)*\\$/ =~ line
1659
+ (cont ||= []) << line
1660
+ next
1661
+ elsif cont
1662
+ line = (cont << line).join
1663
+ cont = nil
1664
+ end
1665
+ ruleconv.call(line)
1666
+ end
1667
+ if cont
1668
+ ruleconv.call(cont.join)
1669
+ elsif implicit
1670
+ impconv.call
1671
+ end
1672
+ end
1673
+ unless suffixes.empty?
1674
+ mfile.print ".SUFFIXES: .", suffixes.uniq.join(" ."), "\n\n"
1675
+ end
1676
+ mfile.print "$(OBJS): $(RUBY_EXTCONF_H)\n\n" if $extconf_h
1677
+ mfile.print depout
1678
+ else
1679
+ headers = %w[ruby.h defines.h]
1680
+ if RULE_SUBST
1681
+ headers.each {|h| h.sub!(/.*/) {|*m| RULE_SUBST % m}}
1682
+ end
1683
+ headers << $config_h if $config_h
1684
+ headers << "$(RUBY_EXTCONF_H)" if $extconf_h
1685
+ mfile.print "$(OBJS): ", headers.join(' '), "\n"
1686
+ end
1687
+
1688
+ $makefile_created = true
1689
+ ensure
1690
+ mfile.close if mfile
1691
+ end
1692
+
1693
+ # :stopdoc:
1694
+
1695
+ def init_mkmf(config = CONFIG)
1696
+ $makefile_created = false
1697
+ $arg_config = []
1698
+ $enable_shared = config['ENABLE_SHARED'] == 'yes'
1699
+ $defs = []
1700
+ $extconf_h = nil
1701
+ $CFLAGS = with_config("cflags", arg_config("CFLAGS", config["CFLAGS"])).dup
1702
+ $ARCH_FLAG = with_config("arch_flag", arg_config("ARCH_FLAG", config["ARCH_FLAG"])).dup
1703
+ $CPPFLAGS = with_config("cppflags", arg_config("CPPFLAGS", config["CPPFLAGS"])).dup
1704
+ $LDFLAGS = with_config("ldflags", arg_config("LDFLAGS", config["LDFLAGS"])).dup
1705
+ $INCFLAGS = "-I$(topdir) -I$(hdrdir) -I$(srcdir)"
1706
+ $DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
1707
+ $LIBEXT = config['LIBEXT'].dup
1708
+ $OBJEXT = config["OBJEXT"].dup
1709
+ $LIBS = "#{config['LIBS']} #{config['DLDLIBS']}"
1710
+ $LIBRUBYARG = ""
1711
+ $LIBRUBYARG_STATIC = config['LIBRUBYARG_STATIC']
1712
+ $LIBRUBYARG_SHARED = config['LIBRUBYARG_SHARED']
1713
+ $DEFLIBPATH = $extmk ? ["$(topdir)"] : CROSS_COMPILING ? [] : ["$(libdir)"]
1714
+ $DEFLIBPATH.unshift(".")
1715
+ $LIBPATH = []
1716
+ $INSTALLFILES = []
1717
+ $NONINSTALLFILES = [/~\z/, /\A#.*#\z/, /\A\.#/, /\.bak\z/i, /\.orig\z/, /\.rej\z/, /\.l[ao]\z/, /\.o\z/]
1718
+
1719
+ $objs = nil
1720
+ $srcs = nil
1721
+ $libs = ""
1722
+ if $enable_shared or Config.expand(config["LIBRUBY"].dup) != Config.expand(config["LIBRUBY_A"].dup)
1723
+ $LIBRUBYARG = config['LIBRUBYARG']
1724
+ end
1725
+
1726
+ $LOCAL_LIBS = ""
1727
+
1728
+ $cleanfiles = config_string('CLEANFILES') {|s| Shellwords.shellwords(s)} || []
1729
+ $cleanfiles << "mkmf.log"
1730
+ $distcleanfiles = config_string('DISTCLEANFILES') {|s| Shellwords.shellwords(s)} || []
1731
+
1732
+ $extout ||= nil
1733
+ $extout_prefix ||= nil
1734
+
1735
+ $arg_config.clear
1736
+ dir_config("opt")
1737
+ end
1738
+
1739
+ FailedMessage = <<MESSAGE
1740
+ Could not create Makefile due to some reason, probably lack of
1741
+ necessary libraries and/or headers. Check the mkmf.log file for more
1742
+ details. You may need configuration options.
1743
+
1744
+ Provided configuration options:
1745
+ MESSAGE
1746
+
1747
+ # Returns whether or not the Makefile was successfully generated. If not,
1748
+ # the script will abort with an error message.
1749
+ #
1750
+ # Internal use only.
1751
+ #
1752
+ def mkmf_failed(path)
1753
+ unless $makefile_created or File.exist?("Makefile")
1754
+ opts = $arg_config.collect {|t, n| "\t#{t}#{n ? "=#{n}" : ""}\n"}
1755
+ abort "*** #{path} failed ***\n" + FailedMessage + opts.join
1756
+ end
1757
+ end
1758
+
1759
+ # :startdoc:
1760
+
1761
+ init_mkmf
1762
+
1763
+ $make = with_config("make-prog", ENV["MAKE"] || "make")
1764
+ make, = Shellwords.shellwords($make)
1765
+ $nmake = nil
1766
+ case
1767
+ when $mswin
1768
+ $nmake = ?m if /nmake/i =~ make
1769
+ when $bccwin
1770
+ $nmake = ?b if /Borland/i =~ `#{make} -h`
1771
+ end
1772
+
1773
+ Config::CONFIG["srcdir"] = CONFIG["srcdir"] =
1774
+ $srcdir = arg_config("--srcdir", File.dirname($0))
1775
+ $configure_args["--topsrcdir"] ||= $srcdir
1776
+ if $curdir = arg_config("--curdir")
1777
+ Config.expand(curdir = $curdir.dup)
1778
+ else
1779
+ curdir = $curdir = "."
1780
+ end
1781
+ unless File.expand_path(Config::CONFIG["topdir"]) == File.expand_path(curdir)
1782
+ CONFIG["topdir"] = $curdir
1783
+ Config::CONFIG["topdir"] = curdir
1784
+ end
1785
+ $configure_args["--topdir"] ||= $curdir
1786
+ $ruby = arg_config("--ruby", File.join(Config::CONFIG["bindir"], CONFIG["ruby_install_name"]))
1787
+
1788
+ split = Shellwords.method(:shellwords).to_proc
1789
+
1790
+ EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip}
1791
+
1792
+ hdr = []
1793
+ config_string('COMMON_MACROS') do |s|
1794
+ Shellwords.shellwords(s).each do |w|
1795
+ hdr << "#define " + w.split(/=/, 2).join(" ")
1796
+ end
1797
+ end
1798
+ config_string('COMMON_HEADERS') do |s|
1799
+ Shellwords.shellwords(s).each {|s| hdr << "#include <#{s}>"}
1800
+ end
1801
+ COMMON_HEADERS = hdr.join("\n")
1802
+ COMMON_LIBS = config_string('COMMON_LIBS', &split) || []
1803
+
1804
+ COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:]
1805
+ RULE_SUBST = config_string('RULE_SUBST')
1806
+ COMPILE_C = config_string('COMPILE_C') || '$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<'
1807
+ COMPILE_CXX = config_string('COMPILE_CXX') || '$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<'
1808
+ TRY_LINK = config_string('TRY_LINK') ||
1809
+ "$(CC) #{OUTFLAG}conftest $(INCFLAGS) $(CPPFLAGS) " \
1810
+ "$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
1811
+ LINK_SO = config_string('LINK_SO') ||
1812
+ if CONFIG["DLEXT"] == $OBJEXT
1813
+ "ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
1814
+ else
1815
+ "$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
1816
+ "$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
1817
+ end
1818
+ LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
1819
+ RPATHFLAG = config_string('RPATHFLAG') || ''
1820
+ LIBARG = config_string('LIBARG') || '-l%s'
1821
+
1822
+ sep = config_string('BUILD_FILE_SEPARATOR') {|sep| ":/=#{sep}" if sep != "/"} || ""
1823
+ CLEANINGS = "
1824
+ clean:
1825
+ @-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
1826
+
1827
+ distclean: clean
1828
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
1829
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
1830
+
1831
+ realclean: distclean
1832
+ "
1833
+
1834
+ if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
1835
+ END {mkmf_failed($0)}
1836
+ end