nokogiri 1.8.5 → 1.13.6

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

Potentially problematic release.


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

Files changed (356) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -21
  3. data/LICENSE-DEPENDENCIES.md +1159 -868
  4. data/LICENSE.md +5 -28
  5. data/README.md +196 -90
  6. data/bin/nokogiri +63 -50
  7. data/dependencies.yml +13 -59
  8. data/ext/nokogiri/depend +38 -358
  9. data/ext/nokogiri/extconf.rb +750 -420
  10. data/ext/nokogiri/gumbo.c +584 -0
  11. data/ext/nokogiri/html4_document.c +166 -0
  12. data/ext/nokogiri/html4_element_description.c +294 -0
  13. data/ext/nokogiri/html4_entity_lookup.c +37 -0
  14. data/ext/nokogiri/html4_sax_parser_context.c +119 -0
  15. data/ext/nokogiri/html4_sax_push_parser.c +95 -0
  16. data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
  17. data/ext/nokogiri/nokogiri.c +228 -91
  18. data/ext/nokogiri/nokogiri.h +191 -89
  19. data/ext/nokogiri/test_global_handlers.c +40 -0
  20. data/ext/nokogiri/xml_attr.c +41 -36
  21. data/ext/nokogiri/xml_attribute_decl.c +18 -18
  22. data/ext/nokogiri/xml_cdata.c +13 -18
  23. data/ext/nokogiri/xml_comment.c +19 -26
  24. data/ext/nokogiri/xml_document.c +291 -216
  25. data/ext/nokogiri/xml_document_fragment.c +12 -16
  26. data/ext/nokogiri/xml_dtd.c +56 -50
  27. data/ext/nokogiri/xml_element_content.c +31 -26
  28. data/ext/nokogiri/xml_element_decl.c +22 -22
  29. data/ext/nokogiri/xml_encoding_handler.c +43 -18
  30. data/ext/nokogiri/xml_entity_decl.c +32 -30
  31. data/ext/nokogiri/xml_entity_reference.c +16 -18
  32. data/ext/nokogiri/xml_namespace.c +61 -52
  33. data/ext/nokogiri/xml_node.c +1044 -616
  34. data/ext/nokogiri/xml_node_set.c +174 -162
  35. data/ext/nokogiri/xml_processing_instruction.c +17 -19
  36. data/ext/nokogiri/xml_reader.c +226 -175
  37. data/ext/nokogiri/xml_relax_ng.c +52 -28
  38. data/ext/nokogiri/xml_sax_parser.c +112 -112
  39. data/ext/nokogiri/xml_sax_parser_context.c +112 -86
  40. data/ext/nokogiri/xml_sax_push_parser.c +36 -27
  41. data/ext/nokogiri/xml_schema.c +112 -33
  42. data/ext/nokogiri/xml_syntax_error.c +42 -21
  43. data/ext/nokogiri/xml_text.c +13 -17
  44. data/ext/nokogiri/xml_xpath_context.c +223 -115
  45. data/ext/nokogiri/xslt_stylesheet.c +265 -173
  46. data/gumbo-parser/CHANGES.md +63 -0
  47. data/gumbo-parser/Makefile +101 -0
  48. data/gumbo-parser/THANKS +27 -0
  49. data/gumbo-parser/src/Makefile +34 -0
  50. data/gumbo-parser/src/README.md +41 -0
  51. data/gumbo-parser/src/ascii.c +75 -0
  52. data/gumbo-parser/src/ascii.h +115 -0
  53. data/gumbo-parser/src/attribute.c +42 -0
  54. data/gumbo-parser/src/attribute.h +17 -0
  55. data/gumbo-parser/src/char_ref.c +22225 -0
  56. data/gumbo-parser/src/char_ref.h +29 -0
  57. data/gumbo-parser/src/char_ref.rl +2154 -0
  58. data/gumbo-parser/src/error.c +626 -0
  59. data/gumbo-parser/src/error.h +148 -0
  60. data/gumbo-parser/src/foreign_attrs.c +104 -0
  61. data/gumbo-parser/src/foreign_attrs.gperf +27 -0
  62. data/gumbo-parser/src/gumbo.h +943 -0
  63. data/gumbo-parser/src/insertion_mode.h +33 -0
  64. data/gumbo-parser/src/macros.h +91 -0
  65. data/gumbo-parser/src/parser.c +4875 -0
  66. data/gumbo-parser/src/parser.h +41 -0
  67. data/gumbo-parser/src/replacement.h +33 -0
  68. data/gumbo-parser/src/string_buffer.c +103 -0
  69. data/gumbo-parser/src/string_buffer.h +68 -0
  70. data/gumbo-parser/src/string_piece.c +48 -0
  71. data/gumbo-parser/src/svg_attrs.c +174 -0
  72. data/gumbo-parser/src/svg_attrs.gperf +77 -0
  73. data/gumbo-parser/src/svg_tags.c +137 -0
  74. data/gumbo-parser/src/svg_tags.gperf +55 -0
  75. data/gumbo-parser/src/tag.c +222 -0
  76. data/gumbo-parser/src/tag_lookup.c +382 -0
  77. data/gumbo-parser/src/tag_lookup.gperf +169 -0
  78. data/gumbo-parser/src/tag_lookup.h +13 -0
  79. data/gumbo-parser/src/token_buffer.c +79 -0
  80. data/gumbo-parser/src/token_buffer.h +71 -0
  81. data/gumbo-parser/src/token_type.h +17 -0
  82. data/gumbo-parser/src/tokenizer.c +3463 -0
  83. data/gumbo-parser/src/tokenizer.h +112 -0
  84. data/gumbo-parser/src/tokenizer_states.h +339 -0
  85. data/gumbo-parser/src/utf8.c +245 -0
  86. data/gumbo-parser/src/utf8.h +164 -0
  87. data/gumbo-parser/src/util.c +68 -0
  88. data/gumbo-parser/src/util.h +30 -0
  89. data/gumbo-parser/src/vector.c +111 -0
  90. data/gumbo-parser/src/vector.h +45 -0
  91. data/lib/nokogiri/class_resolver.rb +67 -0
  92. data/lib/nokogiri/css/node.rb +10 -8
  93. data/lib/nokogiri/css/parser.rb +397 -377
  94. data/lib/nokogiri/css/parser.y +250 -245
  95. data/lib/nokogiri/css/parser_extras.rb +54 -49
  96. data/lib/nokogiri/css/syntax_error.rb +3 -1
  97. data/lib/nokogiri/css/tokenizer.rb +107 -104
  98. data/lib/nokogiri/css/tokenizer.rex +3 -2
  99. data/lib/nokogiri/css/xpath_visitor.rb +218 -91
  100. data/lib/nokogiri/css.rb +50 -17
  101. data/lib/nokogiri/decorators/slop.rb +9 -7
  102. data/lib/nokogiri/extension.rb +31 -0
  103. data/lib/nokogiri/gumbo.rb +15 -0
  104. data/lib/nokogiri/html.rb +38 -27
  105. data/lib/nokogiri/{html → html4}/builder.rb +4 -2
  106. data/lib/nokogiri/{html → html4}/document.rb +103 -105
  107. data/lib/nokogiri/html4/document_fragment.rb +54 -0
  108. data/lib/nokogiri/{html → html4}/element_description.rb +3 -1
  109. data/lib/nokogiri/html4/element_description_defaults.rb +578 -0
  110. data/lib/nokogiri/{html → html4}/entity_lookup.rb +4 -2
  111. data/lib/nokogiri/{html → html4}/sax/parser.rb +17 -16
  112. data/lib/nokogiri/html4/sax/parser_context.rb +20 -0
  113. data/lib/nokogiri/{html → html4}/sax/push_parser.rb +12 -11
  114. data/lib/nokogiri/html4.rb +46 -0
  115. data/lib/nokogiri/html5/document.rb +91 -0
  116. data/lib/nokogiri/html5/document_fragment.rb +83 -0
  117. data/lib/nokogiri/html5/node.rb +100 -0
  118. data/lib/nokogiri/html5.rb +478 -0
  119. data/lib/nokogiri/jruby/dependencies.rb +21 -0
  120. data/lib/nokogiri/syntax_error.rb +2 -0
  121. data/lib/nokogiri/version/constant.rb +6 -0
  122. data/lib/nokogiri/version/info.rb +222 -0
  123. data/lib/nokogiri/version.rb +3 -108
  124. data/lib/nokogiri/xml/attr.rb +6 -3
  125. data/lib/nokogiri/xml/attribute_decl.rb +3 -1
  126. data/lib/nokogiri/xml/builder.rb +97 -53
  127. data/lib/nokogiri/xml/cdata.rb +3 -1
  128. data/lib/nokogiri/xml/character_data.rb +2 -0
  129. data/lib/nokogiri/xml/document.rb +224 -86
  130. data/lib/nokogiri/xml/document_fragment.rb +57 -44
  131. data/lib/nokogiri/xml/dtd.rb +4 -2
  132. data/lib/nokogiri/xml/element_content.rb +2 -0
  133. data/lib/nokogiri/xml/element_decl.rb +3 -1
  134. data/lib/nokogiri/xml/entity_decl.rb +4 -2
  135. data/lib/nokogiri/xml/entity_reference.rb +2 -0
  136. data/lib/nokogiri/xml/namespace.rb +3 -0
  137. data/lib/nokogiri/xml/node/save_options.rb +10 -5
  138. data/lib/nokogiri/xml/node.rb +895 -377
  139. data/lib/nokogiri/xml/node_set.rb +92 -65
  140. data/lib/nokogiri/xml/notation.rb +13 -0
  141. data/lib/nokogiri/xml/parse_options.rb +22 -8
  142. data/lib/nokogiri/xml/pp/character_data.rb +9 -6
  143. data/lib/nokogiri/xml/pp/node.rb +25 -26
  144. data/lib/nokogiri/xml/pp.rb +4 -2
  145. data/lib/nokogiri/xml/processing_instruction.rb +3 -1
  146. data/lib/nokogiri/xml/reader.rb +23 -28
  147. data/lib/nokogiri/xml/relax_ng.rb +8 -2
  148. data/lib/nokogiri/xml/sax/document.rb +45 -49
  149. data/lib/nokogiri/xml/sax/parser.rb +38 -34
  150. data/lib/nokogiri/xml/sax/parser_context.rb +8 -3
  151. data/lib/nokogiri/xml/sax/push_parser.rb +6 -5
  152. data/lib/nokogiri/xml/sax.rb +6 -4
  153. data/lib/nokogiri/xml/schema.rb +19 -9
  154. data/lib/nokogiri/xml/searchable.rb +112 -72
  155. data/lib/nokogiri/xml/syntax_error.rb +6 -4
  156. data/lib/nokogiri/xml/text.rb +2 -0
  157. data/lib/nokogiri/xml/xpath/syntax_error.rb +4 -2
  158. data/lib/nokogiri/xml/xpath.rb +15 -4
  159. data/lib/nokogiri/xml/xpath_context.rb +3 -3
  160. data/lib/nokogiri/xml.rb +38 -37
  161. data/lib/nokogiri/xslt/stylesheet.rb +3 -1
  162. data/lib/nokogiri/xslt.rb +29 -20
  163. data/lib/nokogiri.rb +49 -65
  164. data/lib/xsd/xmlparser/nokogiri.rb +26 -24
  165. data/patches/libxml2/0001-Remove-script-macro-support.patch +40 -0
  166. data/patches/libxml2/0002-Update-entities-to-remove-handling-of-ssi.patch +44 -0
  167. data/patches/libxml2/0003-libxml2.la-is-in-top_builddir.patch +25 -0
  168. data/patches/libxml2/0004-use-glibc-strlen.patch +53 -0
  169. data/patches/libxml2/0005-avoid-isnan-isinf.patch +81 -0
  170. data/patches/libxml2/0006-update-automake-files-for-arm64.patch +3040 -0
  171. data/patches/libxml2/0008-htmlParseComment-handle-abruptly-closed-comments.patch +61 -0
  172. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  173. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +3037 -0
  174. data/ports/archives/libxml2-2.9.14.tar.xz +0 -0
  175. data/ports/archives/libxslt-1.1.35.tar.xz +0 -0
  176. metadata +220 -266
  177. data/.autotest +0 -22
  178. data/.cross_rubies +0 -8
  179. data/.editorconfig +0 -17
  180. data/.gemtest +0 -0
  181. data/.travis.yml +0 -63
  182. data/CHANGELOG.md +0 -1368
  183. data/CONTRIBUTING.md +0 -42
  184. data/C_CODING_STYLE.rdoc +0 -33
  185. data/Gemfile-libxml-ruby +0 -3
  186. data/Manifest.txt +0 -370
  187. data/ROADMAP.md +0 -111
  188. data/Rakefile +0 -348
  189. data/SECURITY.md +0 -19
  190. data/STANDARD_RESPONSES.md +0 -47
  191. data/Y_U_NO_GEMSPEC.md +0 -155
  192. data/appveyor.yml +0 -29
  193. data/build_all +0 -44
  194. data/ext/nokogiri/html_document.c +0 -170
  195. data/ext/nokogiri/html_document.h +0 -10
  196. data/ext/nokogiri/html_element_description.c +0 -279
  197. data/ext/nokogiri/html_element_description.h +0 -10
  198. data/ext/nokogiri/html_entity_lookup.c +0 -32
  199. data/ext/nokogiri/html_entity_lookup.h +0 -8
  200. data/ext/nokogiri/html_sax_parser_context.c +0 -116
  201. data/ext/nokogiri/html_sax_parser_context.h +0 -11
  202. data/ext/nokogiri/html_sax_push_parser.c +0 -87
  203. data/ext/nokogiri/html_sax_push_parser.h +0 -9
  204. data/ext/nokogiri/xml_attr.h +0 -9
  205. data/ext/nokogiri/xml_attribute_decl.h +0 -9
  206. data/ext/nokogiri/xml_cdata.h +0 -9
  207. data/ext/nokogiri/xml_comment.h +0 -9
  208. data/ext/nokogiri/xml_document.h +0 -23
  209. data/ext/nokogiri/xml_document_fragment.h +0 -10
  210. data/ext/nokogiri/xml_dtd.h +0 -10
  211. data/ext/nokogiri/xml_element_content.h +0 -10
  212. data/ext/nokogiri/xml_element_decl.h +0 -9
  213. data/ext/nokogiri/xml_encoding_handler.h +0 -8
  214. data/ext/nokogiri/xml_entity_decl.h +0 -10
  215. data/ext/nokogiri/xml_entity_reference.h +0 -9
  216. data/ext/nokogiri/xml_io.c +0 -61
  217. data/ext/nokogiri/xml_io.h +0 -11
  218. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
  219. data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
  220. data/ext/nokogiri/xml_namespace.h +0 -15
  221. data/ext/nokogiri/xml_node.h +0 -13
  222. data/ext/nokogiri/xml_node_set.h +0 -12
  223. data/ext/nokogiri/xml_processing_instruction.h +0 -9
  224. data/ext/nokogiri/xml_reader.h +0 -10
  225. data/ext/nokogiri/xml_relax_ng.h +0 -9
  226. data/ext/nokogiri/xml_sax_parser.h +0 -39
  227. data/ext/nokogiri/xml_sax_parser_context.h +0 -10
  228. data/ext/nokogiri/xml_sax_push_parser.h +0 -9
  229. data/ext/nokogiri/xml_schema.h +0 -9
  230. data/ext/nokogiri/xml_syntax_error.h +0 -13
  231. data/ext/nokogiri/xml_text.h +0 -9
  232. data/ext/nokogiri/xml_xpath_context.h +0 -10
  233. data/ext/nokogiri/xslt_stylesheet.h +0 -14
  234. data/lib/nokogiri/html/document_fragment.rb +0 -49
  235. data/lib/nokogiri/html/element_description_defaults.rb +0 -671
  236. data/lib/nokogiri/html/sax/parser_context.rb +0 -16
  237. data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
  238. data/patches/libxml2/0002-Fix-nullptr-deref-with-XPath-logic-ops.patch +0 -54
  239. data/patches/libxml2/0003-Fix-infinite-loop-in-LZMA-decompression.patch +0 -50
  240. data/patches/sort-patches-by-date +0 -25
  241. data/ports/archives/libxml2-2.9.8.tar.gz +0 -0
  242. data/ports/archives/libxslt-1.1.32.tar.gz +0 -0
  243. data/suppressions/README.txt +0 -1
  244. data/suppressions/nokogiri_ruby-2.supp +0 -10
  245. data/tasks/test.rb +0 -100
  246. data/test/css/test_nthiness.rb +0 -226
  247. data/test/css/test_parser.rb +0 -386
  248. data/test/css/test_tokenizer.rb +0 -215
  249. data/test/css/test_xpath_visitor.rb +0 -96
  250. data/test/decorators/test_slop.rb +0 -23
  251. data/test/files/2ch.html +0 -108
  252. data/test/files/GH_1042.html +0 -18
  253. data/test/files/address_book.rlx +0 -12
  254. data/test/files/address_book.xml +0 -10
  255. data/test/files/atom.xml +0 -344
  256. data/test/files/bar/bar.xsd +0 -4
  257. data/test/files/bogus.xml +0 -0
  258. data/test/files/dont_hurt_em_why.xml +0 -422
  259. data/test/files/encoding.html +0 -82
  260. data/test/files/encoding.xhtml +0 -84
  261. data/test/files/exslt.xml +0 -8
  262. data/test/files/exslt.xslt +0 -35
  263. data/test/files/foo/foo.xsd +0 -4
  264. data/test/files/metacharset.html +0 -10
  265. data/test/files/namespace_pressure_test.xml +0 -1684
  266. data/test/files/noencoding.html +0 -47
  267. data/test/files/po.xml +0 -32
  268. data/test/files/po.xsd +0 -66
  269. data/test/files/saml/saml20assertion_schema.xsd +0 -283
  270. data/test/files/saml/saml20protocol_schema.xsd +0 -302
  271. data/test/files/saml/xenc_schema.xsd +0 -146
  272. data/test/files/saml/xmldsig_schema.xsd +0 -318
  273. data/test/files/shift_jis.html +0 -10
  274. data/test/files/shift_jis.xml +0 -5
  275. data/test/files/shift_jis_no_charset.html +0 -9
  276. data/test/files/slow-xpath.xml +0 -25509
  277. data/test/files/snuggles.xml +0 -3
  278. data/test/files/staff.dtd +0 -10
  279. data/test/files/staff.xml +0 -59
  280. data/test/files/staff.xslt +0 -32
  281. data/test/files/test_document_url/bar.xml +0 -2
  282. data/test/files/test_document_url/document.dtd +0 -4
  283. data/test/files/test_document_url/document.xml +0 -6
  284. data/test/files/tlm.html +0 -851
  285. data/test/files/to_be_xincluded.xml +0 -2
  286. data/test/files/valid_bar.xml +0 -2
  287. data/test/files/xinclude.xml +0 -4
  288. data/test/helper.rb +0 -271
  289. data/test/html/sax/test_parser.rb +0 -168
  290. data/test/html/sax/test_parser_context.rb +0 -46
  291. data/test/html/sax/test_parser_text.rb +0 -163
  292. data/test/html/sax/test_push_parser.rb +0 -87
  293. data/test/html/test_attributes.rb +0 -85
  294. data/test/html/test_builder.rb +0 -164
  295. data/test/html/test_document.rb +0 -712
  296. data/test/html/test_document_encoding.rb +0 -143
  297. data/test/html/test_document_fragment.rb +0 -310
  298. data/test/html/test_element_description.rb +0 -105
  299. data/test/html/test_named_characters.rb +0 -14
  300. data/test/html/test_node.rb +0 -212
  301. data/test/html/test_node_encoding.rb +0 -91
  302. data/test/namespaces/test_additional_namespaces_in_builder_doc.rb +0 -14
  303. data/test/namespaces/test_namespaces_aliased_default.rb +0 -24
  304. data/test/namespaces/test_namespaces_in_builder_doc.rb +0 -75
  305. data/test/namespaces/test_namespaces_in_cloned_doc.rb +0 -31
  306. data/test/namespaces/test_namespaces_in_created_doc.rb +0 -75
  307. data/test/namespaces/test_namespaces_in_parsed_doc.rb +0 -80
  308. data/test/namespaces/test_namespaces_preservation.rb +0 -31
  309. data/test/test_convert_xpath.rb +0 -135
  310. data/test/test_css_cache.rb +0 -47
  311. data/test/test_encoding_handler.rb +0 -48
  312. data/test/test_memory_leak.rb +0 -156
  313. data/test/test_nokogiri.rb +0 -138
  314. data/test/test_soap4r_sax.rb +0 -52
  315. data/test/test_xslt_transforms.rb +0 -314
  316. data/test/xml/node/test_save_options.rb +0 -28
  317. data/test/xml/node/test_subclass.rb +0 -44
  318. data/test/xml/sax/test_parser.rb +0 -402
  319. data/test/xml/sax/test_parser_context.rb +0 -115
  320. data/test/xml/sax/test_parser_text.rb +0 -202
  321. data/test/xml/sax/test_push_parser.rb +0 -265
  322. data/test/xml/test_attr.rb +0 -74
  323. data/test/xml/test_attribute_decl.rb +0 -86
  324. data/test/xml/test_builder.rb +0 -341
  325. data/test/xml/test_c14n.rb +0 -180
  326. data/test/xml/test_cdata.rb +0 -54
  327. data/test/xml/test_comment.rb +0 -40
  328. data/test/xml/test_document.rb +0 -982
  329. data/test/xml/test_document_encoding.rb +0 -31
  330. data/test/xml/test_document_fragment.rb +0 -298
  331. data/test/xml/test_dtd.rb +0 -187
  332. data/test/xml/test_dtd_encoding.rb +0 -31
  333. data/test/xml/test_element_content.rb +0 -56
  334. data/test/xml/test_element_decl.rb +0 -73
  335. data/test/xml/test_entity_decl.rb +0 -122
  336. data/test/xml/test_entity_reference.rb +0 -262
  337. data/test/xml/test_namespace.rb +0 -96
  338. data/test/xml/test_node.rb +0 -1325
  339. data/test/xml/test_node_attributes.rb +0 -115
  340. data/test/xml/test_node_encoding.rb +0 -75
  341. data/test/xml/test_node_inheritance.rb +0 -32
  342. data/test/xml/test_node_reparenting.rb +0 -592
  343. data/test/xml/test_node_set.rb +0 -809
  344. data/test/xml/test_parse_options.rb +0 -64
  345. data/test/xml/test_processing_instruction.rb +0 -30
  346. data/test/xml/test_reader.rb +0 -620
  347. data/test/xml/test_reader_encoding.rb +0 -134
  348. data/test/xml/test_relax_ng.rb +0 -60
  349. data/test/xml/test_schema.rb +0 -142
  350. data/test/xml/test_syntax_error.rb +0 -36
  351. data/test/xml/test_text.rb +0 -60
  352. data/test/xml/test_unparented_node.rb +0 -483
  353. data/test/xml/test_xinclude.rb +0 -83
  354. data/test/xml/test_xpath.rb +0 -470
  355. data/test/xslt/test_custom_functions.rb +0 -133
  356. data/test/xslt/test_exception_handling.rb +0 -37
@@ -1,208 +1,376 @@
1
- # :stopdoc:
2
- ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
1
+ # frozen_string_literal: true
3
2
 
4
- require 'mkmf'
3
+ # rubocop:disable Style/GlobalVars
5
4
 
6
- ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
5
+ ENV["RC_ARCHS"] = "" if RUBY_PLATFORM.include?("darwin")
6
+
7
+ require "mkmf"
8
+ require "rbconfig"
9
+ require "fileutils"
10
+ require "shellwords"
11
+ require "pathname"
12
+
13
+ # helpful constants
14
+ PACKAGE_ROOT_DIR = File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
15
+ REQUIRED_LIBXML_VERSION = "2.6.21"
16
+ RECOMMENDED_LIBXML_VERSION = "2.9.3"
17
+
18
+ REQUIRED_MINI_PORTILE_VERSION = "~> 2.8.0" # keep this version in sync with the one in the gemspec
19
+ REQUIRED_PKG_CONFIG_VERSION = "~> 1.1"
20
+
21
+ # Keep track of what versions of what libraries we build against
22
+ OTHER_LIBRARY_VERSIONS = {}
23
+
24
+ NOKOGIRI_HELP_MESSAGE = <<~HELP
25
+ USAGE: ruby #{$PROGRAM_NAME} [options]
26
+
27
+ Flags that are always valid:
28
+
29
+ --use-system-libraries
30
+ --enable-system-libraries
31
+ Use system libraries instead of building and using the packaged libraries.
32
+
33
+ --disable-system-libraries
34
+ Use the packaged libraries, and ignore the system libraries. This is the default on most
35
+ platforms, and overrides `--use-system-libraries` and the environment variable
36
+ `NOKOGIRI_USE_SYSTEM_LIBRARIES`.
37
+
38
+ --disable-clean
39
+ Do not clean out intermediate files after successful build.
40
+
41
+ --prevent-strip
42
+ Take steps to prevent stripping the symbol table and debugging info from the shared
43
+ library, potentially overriding RbConfig's CFLAGS/LDFLAGS/DLDFLAGS.
44
+
45
+
46
+ Flags only used when using system libraries:
47
+
48
+ General:
49
+
50
+ --with-opt-dir=DIRECTORY
51
+ Look for headers and libraries in DIRECTORY.
52
+
53
+ --with-opt-lib=DIRECTORY
54
+ Look for libraries in DIRECTORY.
55
+
56
+ --with-opt-include=DIRECTORY
57
+ Look for headers in DIRECTORY.
58
+
59
+
60
+ Related to zlib:
61
+
62
+ --with-zlib-dir=DIRECTORY
63
+ Look for zlib headers and library in DIRECTORY.
64
+
65
+ --with-zlib-lib=DIRECTORY
66
+ Look for zlib library in DIRECTORY.
67
+
68
+ --with-zlib-include=DIRECTORY
69
+ Look for zlib headers in DIRECTORY.
70
+
71
+
72
+ Related to iconv:
73
+
74
+ --with-iconv-dir=DIRECTORY
75
+ Look for iconv headers and library in DIRECTORY.
76
+
77
+ --with-iconv-lib=DIRECTORY
78
+ Look for iconv library in DIRECTORY.
79
+
80
+ --with-iconv-include=DIRECTORY
81
+ Look for iconv headers in DIRECTORY.
82
+
83
+
84
+ Related to libxml2:
85
+
86
+ --with-xml2-dir=DIRECTORY
87
+ Look for xml2 headers and library in DIRECTORY.
88
+
89
+ --with-xml2-lib=DIRECTORY
90
+ Look for xml2 library in DIRECTORY.
91
+
92
+ --with-xml2-include=DIRECTORY
93
+ Look for xml2 headers in DIRECTORY.
94
+
95
+ --with-xml2-source-dir=DIRECTORY
96
+ (dev only) Build libxml2 from the source code in DIRECTORY
97
+
98
+
99
+ Related to libxslt:
100
+
101
+ --with-xslt-dir=DIRECTORY
102
+ Look for xslt headers and library in DIRECTORY.
103
+
104
+ --with-xslt-lib=DIRECTORY
105
+ Look for xslt library in DIRECTORY.
106
+
107
+ --with-xslt-include=DIRECTORY
108
+ Look for xslt headers in DIRECTORY.
109
+
110
+ --with-xslt-source-dir=DIRECTORY
111
+ (dev only) Build libxslt from the source code in DIRECTORY
112
+
113
+
114
+ Related to libexslt:
115
+
116
+ --with-exslt-dir=DIRECTORY
117
+ Look for exslt headers and library in DIRECTORY.
118
+
119
+ --with-exslt-lib=DIRECTORY
120
+ Look for exslt library in DIRECTORY.
121
+
122
+ --with-exslt-include=DIRECTORY
123
+ Look for exslt headers in DIRECTORY.
124
+
125
+
126
+ Flags only used when building and using the packaged libraries:
127
+
128
+ --disable-static
129
+ Do not statically link packaged libraries, instead use shared libraries.
130
+
131
+ --enable-cross-build
132
+ Enable cross-build mode. (You probably do not want to set this manually.)
133
+
134
+
135
+ Environment variables used:
136
+
137
+ NOKOGIRI_USE_SYSTEM_LIBRARIES
138
+ Equivalent to `--enable-system-libraries` when set, even if nil or blank.
139
+
140
+ CC
141
+ Use this path to invoke the compiler instead of `RbConfig::CONFIG['CC']`
142
+
143
+ CPPFLAGS
144
+ If this string is accepted by the C preprocessor, add it to the flags passed to the C preprocessor
145
+
146
+ CFLAGS
147
+ If this string is accepted by the compiler, add it to the flags passed to the compiler
148
+
149
+ LDFLAGS
150
+ If this string is accepted by the linker, add it to the flags passed to the linker
151
+
152
+ LIBS
153
+ Add this string to the flags passed to the linker
154
+ HELP
7
155
 
8
156
  #
9
- # functions
157
+ # utility functions
10
158
  #
159
+ def config_clean?
160
+ enable_config("clean", true)
161
+ end
162
+
163
+ def config_static?
164
+ default_static = !truffle?
165
+ enable_config("static", default_static)
166
+ end
167
+
168
+ def config_cross_build?
169
+ enable_config("cross-build")
170
+ end
171
+
172
+ def config_system_libraries?
173
+ enable_config("system-libraries", ENV.key?("NOKOGIRI_USE_SYSTEM_LIBRARIES")) do |_, default|
174
+ arg_config("--use-system-libraries", default)
175
+ end
176
+ end
177
+
11
178
  def windows?
12
- RbConfig::CONFIG['target_os'] =~ /mingw32|mswin/
179
+ RbConfig::CONFIG["target_os"].match?(/mingw|mswin/)
13
180
  end
14
181
 
15
182
  def solaris?
16
- RbConfig::CONFIG['target_os'] =~ /solaris/
183
+ RbConfig::CONFIG["target_os"].include?("solaris")
17
184
  end
18
185
 
19
186
  def darwin?
20
- RbConfig::CONFIG['target_os'] =~ /darwin/
187
+ RbConfig::CONFIG["target_os"].include?("darwin")
21
188
  end
22
189
 
23
190
  def openbsd?
24
- RbConfig::CONFIG['target_os'] =~ /openbsd/
191
+ RbConfig::CONFIG["target_os"].include?("openbsd")
192
+ end
193
+
194
+ def aix?
195
+ RbConfig::CONFIG["target_os"].include?("aix")
25
196
  end
26
197
 
27
198
  def nix?
28
- ! (windows? || solaris? || darwin?)
199
+ !(windows? || solaris? || darwin?)
29
200
  end
30
201
 
31
- def sh_export_path path
32
- # because libxslt 1.1.29 configure.in uses AC_PATH_TOOL which treats ":"
33
- # as a $PATH separator, we need to convert windows paths from
34
- #
35
- # C:/path/to/foo
36
- #
37
- # to
38
- #
39
- # /C/path/to/foo
40
- #
41
- # which is sh-compatible, in order to find things properly during
42
- # configuration
43
- if windows?
44
- match = Regexp.new("^([A-Z]):(/.*)").match(path)
45
- if match && match.length == 3
46
- return File.join("/", match[1], match[2])
47
- end
48
- end
49
- path
202
+ def truffle?
203
+ ::RUBY_ENGINE == "truffleruby"
50
204
  end
51
205
 
52
- def do_help
53
- print <<HELP
54
- usage: ruby #{$0} [options]
206
+ def concat_flags(*args)
207
+ args.compact.join(" ")
208
+ end
55
209
 
56
- --disable-clean
57
- Do not clean out intermediate files after successful build.
210
+ def local_have_library(lib, func = nil, headers = nil)
211
+ have_library(lib, func, headers) || have_library("lib#{lib}", func, headers)
212
+ end
58
213
 
59
- --disable-static
60
- Do not statically link bundled libraries.
214
+ def gnome_source
215
+ # As of 2022-02-20, some mirrors have expired SSL certificates. I'm able to retrieve from my home,
216
+ # but whatever host is resolved on the github actions workers see an expired cert.
217
+ #
218
+ # See https://github.com/sparklemotion/nokogiri/runs/5266206403?check_suite_focus=true
219
+ if ENV["NOKOGIRI_USE_CANONICAL_GNOME_SOURCE"]
220
+ "https://download.gnome.org"
221
+ else
222
+ "https://mirror.csclub.uwaterloo.ca/gnome" # old reliable
223
+ end
224
+ end
61
225
 
62
- --with-iconv-dir=DIR
63
- Use the iconv library placed under DIR.
226
+ LOCAL_PACKAGE_RESPONSE = Object.new
227
+ def LOCAL_PACKAGE_RESPONSE.%(package)
228
+ package ? "yes: #{package}" : "no"
229
+ end
64
230
 
65
- --with-zlib-dir=DIR
66
- Use the zlib library placed under DIR.
231
+ # wrapper around MakeMakefil#pkg_config and the PKGConfig gem
232
+ def try_package_configuration(pc)
233
+ unless ENV.key?("NOKOGIRI_TEST_PKG_CONFIG_GEM")
234
+ # try MakeMakefile#pkg_config, which uses the system utility `pkg-config`.
235
+ return if checking_for("#{pc} using `pkg_config`", LOCAL_PACKAGE_RESPONSE) do
236
+ pkg_config(pc)
237
+ end
238
+ end
67
239
 
68
- --use-system-libraries
69
- Use system libraries instead of building and using the bundled
70
- libraries.
240
+ # `pkg-config` probably isn't installed, which appears to be the case for lots of freebsd systems.
241
+ # let's fall back to the pkg-config gem, which knows how to parse .pc files, and wrap it with the
242
+ # same logic as MakeMakefile#pkg_config
243
+ begin
244
+ require "rubygems"
245
+ gem("pkg-config", REQUIRED_PKG_CONFIG_VERSION)
246
+ require "pkg-config"
71
247
 
72
- --with-xml2-dir=DIR / --with-xml2-config=CONFIG
73
- --with-xslt-dir=DIR / --with-xslt-config=CONFIG
74
- --with-exslt-dir=DIR / --with-exslt-config=CONFIG
75
- Use libxml2/libxslt/libexslt as specified.
248
+ checking_for("#{pc} using pkg-config gem version #{PKGConfig::VERSION}", LOCAL_PACKAGE_RESPONSE) do
249
+ if PKGConfig.have_package(pc)
250
+ cflags = PKGConfig.cflags(pc)
251
+ ldflags = PKGConfig.libs_only_L(pc)
252
+ libs = PKGConfig.libs_only_l(pc)
76
253
 
77
- --enable-cross-build
78
- Do cross-build.
79
- HELP
80
- exit! 0
254
+ Logging.message("pkg-config gem found package configuration for %s\n", pc)
255
+ Logging.message("cflags: %s\nldflags: %s\nlibs: %s\n\n", cflags, ldflags, libs)
256
+
257
+ [cflags, ldflags, libs]
258
+ end
259
+ end
260
+ rescue LoadError
261
+ message("Please install either the `pkg-config` utility or the `pkg-config` rubygem.\n")
262
+ end
81
263
  end
82
264
 
83
- def do_clean
84
- require 'pathname'
85
- require 'fileutils'
265
+ # set up mkmf to link against the library if we can find it
266
+ def have_package_configuration(opt: nil, pc: nil, lib:, func:, headers:)
267
+ if opt
268
+ dir_config(opt)
269
+ dir_config("opt")
270
+ end
86
271
 
87
- root = Pathname(ROOT)
88
- pwd = Pathname(Dir.pwd)
272
+ # see if we have enough path info to do this without trying any harder
273
+ unless ENV.key?("NOKOGIRI_TEST_PKG_CONFIG")
274
+ return true if local_have_library(lib, func, headers)
275
+ end
89
276
 
90
- # Skip if this is a development work tree
91
- unless (root + '.git').exist?
92
- message "Cleaning files only used during build.\n"
277
+ try_package_configuration(pc) if pc
93
278
 
94
- # (root + 'tmp') cannot be removed at this stage because
95
- # nokogiri.so is yet to be copied to lib.
96
-
97
- # clean the ports build directory
98
- Pathname.glob(pwd.join('tmp', '*', 'ports')) do |dir|
99
- FileUtils.rm_rf(dir, verbose: true)
100
- end
279
+ # verify that we can compile and link against the library
280
+ local_have_library(lib, func, headers)
281
+ end
101
282
 
102
- if enable_config('static')
103
- # ports installation can be safely removed if statically linked.
104
- FileUtils.rm_rf(root + 'ports', verbose: true)
105
- else
106
- FileUtils.rm_rf(root + 'ports' + 'archives', verbose: true)
107
- end
108
- end
283
+ def ensure_package_configuration(opt: nil, pc: nil, lib:, func:, headers:)
284
+ have_package_configuration(opt: opt, pc: pc, lib: lib, func: func, headers: headers) ||
285
+ abort_could_not_find_library(lib)
286
+ end
109
287
 
110
- exit! 0
288
+ def ensure_func(func, headers = nil)
289
+ have_func(func, headers) || abort_could_not_find_library(func)
111
290
  end
112
291
 
113
- def package_config pkg, options={}
114
- package = pkg_config(pkg)
115
- return package if package
292
+ def preserving_globals
293
+ values = [$arg_config, $INCFLAGS, $CFLAGS, $CPPFLAGS, $LDFLAGS, $DLDFLAGS, $LIBPATH, $libs].map(&:dup)
294
+ yield
295
+ ensure
296
+ $arg_config, $INCFLAGS, $CFLAGS, $CPPFLAGS, $LDFLAGS, $DLDFLAGS, $LIBPATH, $libs = values
297
+ end
116
298
 
117
- begin
118
- require 'rubygems'
119
- gem 'pkg-config', (gem_ver='~> 1.1')
120
- require 'pkg-config' and message("Using pkg-config gem version #{PKGConfig::VERSION}\n")
121
- rescue LoadError
122
- message "pkg-config could not be used to find #{pkg}\nPlease install either `pkg-config` or the pkg-config gem per\n\n gem install pkg-config -v #{gem_ver.inspect}\n\n"
123
- else
124
- return nil unless PKGConfig.have_package(pkg)
299
+ def abort_could_not_find_library(lib)
300
+ callers = caller(1..2).join("\n")
301
+ abort("-----\n#{callers}\n#{lib} is missing. Please locate mkmf.log to investigate how it is failing.\n-----")
302
+ end
125
303
 
126
- cflags = PKGConfig.cflags(pkg)
127
- ldflags = PKGConfig.libs_only_L(pkg)
128
- libs = PKGConfig.libs_only_l(pkg)
304
+ def chdir_for_build(&block)
305
+ # When using rake-compiler-dock on Windows, the underlying Virtualbox shared
306
+ # folders don't support symlinks, but libiconv expects it for a build on
307
+ # Linux. We work around this limitation by using the temp dir for cooking.
308
+ build_dir = /mingw|mswin|cygwin/.match?(ENV["RCD_HOST_RUBY_PLATFORM"].to_s) ? "/tmp" : "."
309
+ Dir.chdir(build_dir, &block)
310
+ end
129
311
 
130
- Logging::message "PKGConfig package configuration for %s\n", pkg
131
- Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n", cflags, ldflags, libs
312
+ def sh_export_path(path)
313
+ # because libxslt 1.1.29 configure.in uses AC_PATH_TOOL which treats ":"
314
+ # as a $PATH separator, we need to convert windows paths from
315
+ #
316
+ # C:/path/to/foo
317
+ #
318
+ # to
319
+ #
320
+ # /C/path/to/foo
321
+ #
322
+ # which is sh-compatible, in order to find things properly during
323
+ # configuration
324
+ return path unless windows?
132
325
 
133
- [cflags, ldflags, libs]
326
+ match = Regexp.new("^([A-Z]):(/.*)").match(path)
327
+ if match && match.length == 3
328
+ return File.join("/", match[1], match[2])
134
329
  end
135
- end
136
330
 
137
- def nokogiri_try_compile
138
- try_compile "int main() {return 0;}", "", {werror: true}
331
+ path
139
332
  end
140
333
 
141
- def check_libxml_version version=nil
142
- source = if version.nil?
143
- <<-SRC
144
- #include <libxml/xmlversion.h>
145
- SRC
146
- else
147
- version_int = sprintf "%d%2.2d%2.2d", *(version.split("."))
148
- <<-SRC
149
- #include <libxml/xmlversion.h>
150
- #if LIBXML_VERSION < #{version_int}
151
- #error libxml2 is older than #{version}
152
- #endif
153
- SRC
154
- end
155
-
156
- try_cpp source
157
- end
158
-
159
- def add_cflags(flags)
160
- print "checking if the C compiler accepts #{flags}... "
161
- with_cflags("#{$CFLAGS} #{flags}") do
162
- if nokogiri_try_compile
163
- puts 'yes'
164
- true
165
- else
166
- puts 'no'
167
- false
168
- end
334
+ def libflag_to_filename(ldflag)
335
+ case ldflag
336
+ when /\A-l(.+)/
337
+ "lib#{Regexp.last_match(1)}.#{$LIBEXT}"
169
338
  end
170
339
  end
171
340
 
172
- def preserving_globals
173
- values = [
174
- $arg_config,
175
- $CFLAGS, $CPPFLAGS,
176
- $LDFLAGS, $LIBPATH, $libs
177
- ].map(&:dup)
178
- yield
179
- ensure
180
- $arg_config,
181
- $CFLAGS, $CPPFLAGS,
182
- $LDFLAGS, $LIBPATH, $libs =
183
- values
184
- end
341
+ def have_libxml_headers?(version = nil)
342
+ source = if version.nil?
343
+ <<~SRC
344
+ #include <libxml/xmlversion.h>
345
+ SRC
346
+ else
347
+ version_int = format("%d%2.2d%2.2d", *version.split("."))
348
+ <<~SRC
349
+ #include <libxml/xmlversion.h>
350
+ #if LIBXML_VERSION < #{version_int}
351
+ # error libxml2 is older than #{version}
352
+ #endif
353
+ SRC
354
+ end
185
355
 
186
- def asplode(lib)
187
- abort "-----\n#{lib} is missing. Please locate mkmf.log to investigate how it is failing.\n-----"
356
+ try_cpp(source)
188
357
  end
189
358
 
190
- def have_iconv?(using = nil)
191
- checking_for(using ? "iconv using #{using}" : 'iconv') do
192
- ['', '-liconv'].any? do |opt|
359
+ def try_link_iconv(using = nil)
360
+ checking_for(using ? "iconv using #{using}" : "iconv") do
361
+ ["", "-liconv"].any? do |opt|
193
362
  preserving_globals do
194
363
  yield if block_given?
195
364
 
196
- try_link(<<-'SRC', opt)
197
- #include <stdlib.h>
198
- #include <iconv.h>
199
-
200
- int main(void)
201
- {
202
- iconv_t cd = iconv_open("", "");
203
- iconv(cd, NULL, NULL, NULL, NULL);
204
- return EXIT_SUCCESS;
205
- }
365
+ try_link(<<~'SRC', opt)
366
+ #include <stdlib.h>
367
+ #include <iconv.h>
368
+ int main(void)
369
+ {
370
+ iconv_t cd = iconv_open("", "");
371
+ iconv(cd, NULL, NULL, NULL, NULL);
372
+ return EXIT_SUCCESS;
373
+ }
206
374
  SRC
207
375
  end
208
376
  end
@@ -210,67 +378,68 @@ int main(void)
210
378
  end
211
379
 
212
380
  def iconv_configure_flags
213
- # If --with-iconv-dir or --with-opt-dir is given, it should be
214
- # the first priority
215
- %w[iconv opt].each do |name|
216
- if (config = preserving_globals { dir_config(name) }).any? &&
217
- have_iconv?("--with-#{name}-* flags") { dir_config(name) }
218
- idirs, ldirs = config.map do |dirs|
219
- Array(dirs).flat_map do |dir|
220
- dir.split(File::PATH_SEPARATOR)
221
- end if dirs
222
- end
223
-
224
- return [
225
- '--with-iconv=yes',
226
- *("CPPFLAGS=#{idirs.map { |dir| '-I' + dir }.join(' ')}" if idirs),
227
- *("LDFLAGS=#{ldirs.map { |dir| '-L' + dir }.join(' ')}" if ldirs),
228
- ]
381
+ # give --with-iconv-dir and --with-opt-dir first priority
382
+ ["iconv", "opt"].each do |target|
383
+ config = preserving_globals { dir_config(target) }
384
+ next unless config.any? && try_link_iconv("--with-#{target}-* flags") { dir_config(target) }
385
+
386
+ idirs, ldirs = config.map do |dirs|
387
+ Array(dirs).flat_map do |dir|
388
+ dir.split(File::PATH_SEPARATOR)
389
+ end if dirs
229
390
  end
391
+
392
+ return [
393
+ "--with-iconv=yes",
394
+ *("CPPFLAGS=#{idirs.map { |dir| "-I" + dir }.join(" ")}" if idirs),
395
+ *("LDFLAGS=#{ldirs.map { |dir| "-L" + dir }.join(" ")}" if ldirs),
396
+ ]
230
397
  end
231
398
 
232
- if have_iconv?
233
- return ['--with-iconv=yes']
399
+ if try_link_iconv
400
+ return ["--with-iconv=yes"]
234
401
  end
235
402
 
236
- if (config = preserving_globals { package_config('libiconv') }) &&
237
- have_iconv?('pkg-config libiconv') { package_config('libiconv') }
403
+ config = preserving_globals { have_package_configuration("libiconv") }
404
+ if config && try_link_iconv("pkg-config libiconv") { have_package_configuration("libiconv") }
238
405
  cflags, ldflags, libs = config
239
406
 
240
407
  return [
241
- '--with-iconv=yes',
408
+ "--with-iconv=yes",
242
409
  "CPPFLAGS=#{cflags}",
243
410
  "LDFLAGS=#{ldflags}",
244
411
  "LIBS=#{libs}",
245
412
  ]
246
413
  end
247
414
 
248
- asplode "libiconv"
415
+ abort_could_not_find_library("libiconv")
249
416
  end
250
417
 
251
- # When using rake-compiler-dock on Windows, the underlying Virtualbox shared
252
- # folders don't support symlinks, but libiconv expects it for a build on
253
- # Linux. We work around this limitation by using the temp dir for cooking.
254
- def chdir_for_build
255
- build_dir = ENV['RCD_HOST_RUBY_PLATFORM'].to_s =~ /mingw|mswin|cygwin/ ? '/tmp' : '.'
256
- Dir.chdir(build_dir) do
257
- yield
418
+ def process_recipe(name, version, static_p, cross_p, cacheable_p = true)
419
+ require "rubygems"
420
+ gem("mini_portile2", REQUIRED_MINI_PORTILE_VERSION) # gemspec is not respected at install time
421
+ require "mini_portile2"
422
+ message("Using mini_portile version #{MiniPortile::VERSION}\n")
423
+
424
+ unless ["libxml2", "libxslt"].include?(name)
425
+ OTHER_LIBRARY_VERSIONS[name] = version
258
426
  end
259
- end
260
427
 
261
- def process_recipe(name, version, static_p, cross_p)
262
428
  MiniPortile.new(name, version).tap do |recipe|
263
- recipe.target = File.join(ROOT, "ports")
264
- # Prefer host_alias over host in order to use i586-mingw32msvc as
265
- # correct compiler prefix for cross build, but use host if not set.
429
+ def recipe.port_path
430
+ "#{@target}/#{RUBY_PLATFORM}/#{@name}/#{@version}"
431
+ end
432
+
433
+ recipe.target = File.join(PACKAGE_ROOT_DIR, "ports") if cacheable_p
434
+ # Prefer host_alias over host in order to use the correct compiler prefix for cross build, but
435
+ # use host if not set.
266
436
  recipe.host = RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"]
267
- recipe.patch_files = Dir[File.join(ROOT, "patches", name, "*.patch")].sort
268
437
  recipe.configure_options << "--libdir=#{File.join(recipe.path, "lib")}"
269
438
 
270
439
  yield recipe
271
440
 
272
441
  env = Hash.new do |hash, key|
273
- hash[key] = "#{ENV[key]}" # (ENV[key].dup rescue '')
442
+ hash[key] = (ENV[key]).to_s
274
443
  end
275
444
 
276
445
  recipe.configure_options.flatten!
@@ -278,7 +447,11 @@ def process_recipe(name, version, static_p, cross_p)
278
447
  recipe.configure_options.delete_if do |option|
279
448
  case option
280
449
  when /\A(\w+)=(.*)\z/
281
- env[$1] = $2
450
+ env[Regexp.last_match(1)] = if env.key?(Regexp.last_match(1))
451
+ concat_flags(env[Regexp.last_match(1)], Regexp.last_match(2))
452
+ else
453
+ Regexp.last_match(2)
454
+ end
282
455
  true
283
456
  else
284
457
  false
@@ -290,7 +463,7 @@ def process_recipe(name, version, static_p, cross_p)
290
463
  "--disable-shared",
291
464
  "--enable-static",
292
465
  ]
293
- env['CFLAGS'] = "-fPIC #{env['CFLAGS']}"
466
+ env["CFLAGS"] = concat_flags(env["CFLAGS"], "-fPIC")
294
467
  else
295
468
  recipe.configure_options += [
296
469
  "--enable-shared",
@@ -305,325 +478,423 @@ def process_recipe(name, version, static_p, cross_p)
305
478
  ]
306
479
  end
307
480
 
308
- if RbConfig::CONFIG['target_cpu'] == 'universal'
309
- %w[CFLAGS LDFLAGS].each do |key|
310
- unless env[key].include?('-arch')
311
- env[key] += ' ' + RbConfig::CONFIG['ARCH_FLAG']
481
+ if RbConfig::CONFIG["target_cpu"] == "universal"
482
+ ["CFLAGS", "LDFLAGS"].each do |key|
483
+ unless env[key].include?("-arch")
484
+ env[key] = concat_flags(env[key], RbConfig::CONFIG["ARCH_FLAG"])
312
485
  end
313
486
  end
314
487
  end
315
488
 
316
489
  recipe.configure_options += env.map do |key, value|
317
- "#{key}=#{value}"
490
+ "#{key}=#{value.strip}"
318
491
  end
319
492
 
320
- message <<-"EOS"
321
- ************************************************************************
322
- IMPORTANT NOTICE:
323
-
324
- Building Nokogiri with a packaged version of #{name}-#{version}#{'.' if recipe.patch_files.empty?}
325
- EOS
493
+ checkpoint = "#{recipe.target}/#{recipe.name}-#{recipe.version}-#{RUBY_PLATFORM}.installed"
494
+ if File.exist?(checkpoint) && !recipe.source_directory
495
+ message("Building Nokogiri with a packaged version of #{name}-#{version}.\n")
496
+ else
497
+ message(<<~EOM)
498
+ ---------- IMPORTANT NOTICE ----------
499
+ Building Nokogiri with a packaged version of #{name}-#{version}.
500
+ Configuration options: #{recipe.configure_options.shelljoin}
501
+ EOM
326
502
 
327
- unless recipe.patch_files.empty?
328
- message "with the following patches applied:\n"
503
+ unless recipe.patch_files.empty?
504
+ message("The following patches are being applied:\n")
329
505
 
330
- recipe.patch_files.each do |patch|
331
- message "\t- %s\n" % File.basename(patch)
506
+ recipe.patch_files.each do |patch|
507
+ message(format(" - %s\n", File.basename(patch)))
508
+ end
332
509
  end
333
- end
334
510
 
335
- message <<-"EOS"
511
+ message(<<~EOM) if name != "libgumbo"
336
512
 
337
- Team Nokogiri will keep on doing their best to provide security
338
- updates in a timely manner, but if this is a concern for you and want
339
- to use the system library instead; abort this installation process and
340
- reinstall nokogiri as follows:
513
+ The Nokogiri maintainers intend to provide timely security updates, but if
514
+ this is a concern for you and want to use your OS/distro system library
515
+ instead, then abort this installation process and install nokogiri as
516
+ instructed at:
341
517
 
342
- gem install nokogiri -- --use-system-libraries
343
- [--with-xml2-config=/path/to/xml2-config]
344
- [--with-xslt-config=/path/to/xslt-config]
518
+ https://nokogiri.org/tutorials/installing_nokogiri.html#installing-using-standard-system-libraries
345
519
 
346
- If you are using Bundler, tell it to use the option:
520
+ EOM
347
521
 
348
- bundle config build.nokogiri --use-system-libraries
349
- bundle install
350
- EOS
522
+ message(<<~EOM) if name == "libxml2"
523
+ Note, however, that nokogiri cannot guarantee compatibility with every
524
+ version of libxml2 that may be provided by OS/package vendors.
351
525
 
352
- message <<-"EOS" if name == 'libxml2'
526
+ EOM
353
527
 
354
- Note, however, that nokogiri is not fully compatible with arbitrary
355
- versions of libxml2 provided by OS/package vendors.
356
- EOS
357
-
358
- message <<-"EOS"
359
- ************************************************************************
360
- EOS
361
-
362
- checkpoint = "#{recipe.target}/#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
363
- unless File.exist?(checkpoint)
364
- chdir_for_build do
365
- recipe.cook
366
- end
367
- FileUtils.touch checkpoint
528
+ pp(recipe.files)
529
+ chdir_for_build { recipe.cook }
530
+ FileUtils.touch(checkpoint)
368
531
  end
369
532
  recipe.activate
370
533
  end
371
534
  end
372
535
 
373
- def lib_a(ldflag)
374
- case ldflag
375
- when /\A-l(.+)/
376
- "lib#{$1}.#{$LIBEXT}"
536
+ def copy_packaged_libraries_headers(to_path:, from_recipes:)
537
+ FileUtils.rm_rf(to_path, secure: true)
538
+ FileUtils.mkdir(to_path)
539
+ from_recipes.each do |recipe|
540
+ FileUtils.cp_r(Dir[File.join(recipe.path, "include/*")], to_path)
377
541
  end
378
542
  end
379
543
 
380
- def using_system_libraries?
381
- arg_config('--use-system-libraries', !!ENV['NOKOGIRI_USE_SYSTEM_LIBRARIES'])
544
+ def do_help
545
+ print(NOKOGIRI_HELP_MESSAGE)
546
+ exit!(0)
382
547
  end
383
548
 
384
- #
385
- # main
386
- #
387
-
388
- case
389
- when arg_config('--help')
390
- do_help
391
- when arg_config('--clean')
392
- do_clean
393
- end
549
+ def do_clean
550
+ root = Pathname(PACKAGE_ROOT_DIR)
551
+ pwd = Pathname(Dir.pwd)
394
552
 
395
- if openbsd? && !using_system_libraries?
396
- if `#{ENV['CC'] || '/usr/bin/cc'} -v 2>&1` !~ /clang/
397
- ENV['CC'] ||= find_executable('egcc') or
398
- abort "Please install gcc 4.9+ from ports using `pkg_add -v gcc`"
399
- end
400
- ENV['CFLAGS'] = "#{ENV['CFLAGS']} -I /usr/local/include"
401
- end
553
+ # Skip if this is a development work tree
554
+ unless (root + ".git").exist?
555
+ message("Cleaning files only used during build.\n")
402
556
 
403
- RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
404
- # use same c compiler for libxml and libxslt
405
- ENV['CC'] = RbConfig::MAKEFILE_CONFIG['CC']
557
+ # (root + 'tmp') cannot be removed at this stage because
558
+ # nokogiri.so is yet to be copied to lib.
406
559
 
407
- $LIBS << " #{ENV["LIBS"]}"
560
+ # clean the ports build directory
561
+ Pathname.glob(pwd.join("tmp", "*", "ports")) do |dir|
562
+ FileUtils.rm_rf(dir, verbose: true)
563
+ end
408
564
 
409
- # Read CFLAGS from ENV and make sure compiling works.
410
- add_cflags(ENV["CFLAGS"])
565
+ if config_static?
566
+ # ports installation can be safely removed if statically linked.
567
+ FileUtils.rm_rf(root + "ports", verbose: true)
568
+ else
569
+ FileUtils.rm_rf(root + "ports" + "archives", verbose: true)
570
+ end
571
+ end
411
572
 
412
- if windows?
413
- $CFLAGS << " -DXP_WIN -DXP_WIN32 -DUSE_INCLUDED_VASPRINTF"
573
+ exit!(0)
414
574
  end
415
575
 
416
- if solaris?
417
- $CFLAGS << " -DUSE_INCLUDED_VASPRINTF"
418
- end
576
+ #
577
+ # main
578
+ #
579
+ do_help if arg_config("--help")
580
+ do_clean if arg_config("--clean")
419
581
 
420
- if darwin?
421
- # Let Apple LLVM/clang 5.1 ignore unknown compiler flags
422
- add_cflags("-Wno-error=unused-command-line-argument-hard-error-in-future")
582
+ if openbsd? && !config_system_libraries?
583
+ if %x(#{ENV["CC"] || "/usr/bin/cc"} -v 2>&1) !~ /clang/
584
+ (ENV["CC"] ||= find_executable("egcc")) ||
585
+ abort("Please install gcc 4.9+ from ports using `pkg_add -v gcc`")
586
+ end
587
+ append_cppflags "-I/usr/local/include"
423
588
  end
424
589
 
425
- if nix?
426
- $CFLAGS << " -g -DXP_UNIX"
590
+ if ENV["CC"]
591
+ RbConfig::CONFIG["CC"] = RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"]
427
592
  end
428
593
 
429
- if RUBY_PLATFORM =~ /mingw/i
430
- # Work around a character escaping bug in MSYS by passing an arbitrary
431
- # double quoted parameter to gcc. See https://sourceforge.net/p/mingw/bugs/2142
432
- $CPPFLAGS << ' "-Idummypath"'
594
+ # use same c compiler for libxml and libxslt
595
+ ENV["CC"] = RbConfig::CONFIG["CC"]
596
+
597
+ if arg_config("--prevent-strip")
598
+ old_cflags = $CFLAGS.split.join(" ")
599
+ old_ldflags = $LDFLAGS.split.join(" ")
600
+ old_dldflags = $DLDFLAGS.split.join(" ")
601
+ $CFLAGS = $CFLAGS.split.reject { |flag| flag == "-s" }.join(" ")
602
+ $LDFLAGS = $LDFLAGS.split.reject { |flag| flag == "-s" }.join(" ")
603
+ $DLDFLAGS = $DLDFLAGS.split.reject { |flag| flag == "-s" }.join(" ")
604
+ puts "Prevent stripping by removing '-s' from $CFLAGS" if old_cflags != $CFLAGS
605
+ puts "Prevent stripping by removing '-s' from $LDFLAGS" if old_ldflags != $LDFLAGS
606
+ puts "Prevent stripping by removing '-s' from $DLDFLAGS" if old_dldflags != $DLDFLAGS
433
607
  end
434
608
 
435
- if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
436
- $CFLAGS << " -O3" unless $CFLAGS[/-O\d/]
437
- $CFLAGS << " -Wall -Wcast-qual -Wwrite-strings -Wmissing-noreturn -Winline"
438
- end
609
+ # adopt environment config
610
+ append_cflags(ENV["CFLAGS"].split) unless ENV["CFLAGS"].nil?
611
+ append_cppflags(ENV["CPPFLAGS"].split) unless ENV["CPPFLAGS"].nil?
612
+ append_ldflags(ENV["LDFLAGS"].split) unless ENV["LDFLAGS"].nil?
613
+ $LIBS = concat_flags($LIBS, ENV["LIBS"])
439
614
 
440
- case
441
- when using_system_libraries?
442
- message "Building nokogiri using system libraries.\n"
615
+ # nokogumbo code uses C90/C99 features, let's make sure older compilers won't give
616
+ # errors/warnings. see #2302
617
+ append_cflags(["-std=c99", "-Wno-declaration-after-statement"])
618
+
619
+ # always include debugging information
620
+ append_cflags("-g")
443
621
 
444
- dir_config('zlib')
622
+ # we use at least one inline function in the C extension
623
+ append_cflags("-Winline")
445
624
 
446
- # Using system libraries means we rely on the system libxml2 with
447
- # regard to the iconv support.
625
+ # good to have no matter what Ruby was compiled with
626
+ append_cflags("-Wmissing-noreturn")
448
627
 
449
- dir_config('xml2').any? or package_config('libxml-2.0')
450
- dir_config('xslt').any? or package_config('libxslt')
451
- dir_config('exslt').any? or package_config('libexslt')
628
+ # handle clang variations, see #1101
629
+ append_cflags("-Wno-error=unused-command-line-argument-hard-error-in-future") if darwin?
452
630
 
453
- check_libxml_version or abort "ERROR: cannot discover where libxml2 is located on your system. please make sure `pkg-config` is installed."
454
- check_libxml_version("2.6.21") or abort "ERROR: libxml2 version 2.6.21 or later is required!"
455
- check_libxml_version("2.9.3") or warn "WARNING: libxml2 version 2.9.3 or later is highly recommended, but proceeding anyway."
631
+ # these tend to be noisy, but on occasion useful during development
632
+ # append_cflags(["-Wcast-qual", "-Wwrite-strings"])
633
+
634
+ # Add SDK-specific include path for macOS and brew versions before v2.2.12 (2020-04-08) [#1851, #1801]
635
+ macos_mojave_sdk_include_path = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libxml2"
636
+ if config_system_libraries? && darwin? && Dir.exist?(macos_mojave_sdk_include_path)
637
+ append_cppflags("-I#{macos_mojave_sdk_include_path}")
638
+ end
639
+
640
+ # Work around a character escaping bug in MSYS by passing an arbitrary double-quoted parameter to gcc.
641
+ # See https://sourceforge.net/p/mingw/bugs/2142
642
+ append_cppflags(' "-Idummypath"') if windows?
643
+
644
+ if config_system_libraries?
645
+ message "Building nokogiri using system libraries.\n"
646
+ ensure_package_configuration(opt: "zlib", pc: "zlib", lib: "z",
647
+ headers: "zlib.h", func: "gzdopen")
648
+ ensure_package_configuration(opt: "xml2", pc: "libxml-2.0", lib: "xml2",
649
+ headers: "libxml/parser.h", func: "xmlParseDoc")
650
+ ensure_package_configuration(opt: "xslt", pc: "libxslt", lib: "xslt",
651
+ headers: "libxslt/xslt.h", func: "xsltParseStylesheetDoc")
652
+ ensure_package_configuration(opt: "exslt", pc: "libexslt", lib: "exslt",
653
+ headers: "libexslt/exslt.h", func: "exsltFuncRegister")
654
+
655
+ have_libxml_headers?(REQUIRED_LIBXML_VERSION) ||
656
+ abort("ERROR: libxml2 version #{REQUIRED_LIBXML_VERSION} or later is required!")
657
+ have_libxml_headers?(RECOMMENDED_LIBXML_VERSION) ||
658
+ warn("WARNING: libxml2 version #{RECOMMENDED_LIBXML_VERSION} or later is highly recommended, but proceeding anyway.")
456
659
 
457
660
  else
458
661
  message "Building nokogiri using packaged libraries.\n"
459
662
 
460
- # The gem version constraint in the Rakefile is not respected at install time.
461
- # Keep this version in sync with the one in the Rakefile !
462
- require 'rubygems'
463
- gem 'mini_portile2', '~> 2.3.0'
464
- require 'mini_portile2'
465
- message "Using mini_portile version #{MiniPortile::VERSION}\n"
466
-
467
- require 'yaml'
663
+ static_p = config_static?
664
+ message "Static linking is #{static_p ? "enabled" : "disabled"}.\n"
468
665
 
469
- static_p = enable_config('static', true) or
470
- message "Static linking is disabled.\n"
666
+ cross_build_p = config_cross_build?
667
+ message "Cross build is #{cross_build_p ? "enabled" : "disabled"}.\n"
471
668
 
472
- dir_config('zlib')
669
+ require "yaml"
670
+ dependencies = YAML.load_file(File.join(PACKAGE_ROOT_DIR, "dependencies.yml"))
473
671
 
474
- dependencies = YAML.load_file(File.join(ROOT, "dependencies.yml"))
672
+ dir_config("zlib")
475
673
 
476
- cross_build_p = enable_config("cross-build")
477
674
  if cross_build_p || windows?
478
675
  zlib_recipe = process_recipe("zlib", dependencies["zlib"]["version"], static_p, cross_build_p) do |recipe|
479
676
  recipe.files = [{
480
- url: "http://zlib.net/fossils/#{recipe.name}-#{recipe.version}.tar.gz",
481
- sha256: dependencies["zlib"]["sha256"]
482
- }]
483
- class << recipe
484
- attr_accessor :cross_build_p
485
-
486
- def configure
487
- Dir.chdir work_path do
488
- mk = File.read 'win32/Makefile.gcc'
489
- File.open 'win32/Makefile.gcc', 'wb' do |f|
490
- f.puts "BINARY_PATH = #{path}/bin"
491
- f.puts "LIBRARY_PATH = #{path}/lib"
492
- f.puts "INCLUDE_PATH = #{path}/include"
493
- mk.sub!(/^PREFIX\s*=\s*$/, "PREFIX = #{host}-") if cross_build_p
494
- f.puts mk
677
+ url: "https://zlib.net/fossils/#{recipe.name}-#{recipe.version}.tar.gz",
678
+ sha256: dependencies["zlib"]["sha256"],
679
+ }]
680
+ if windows?
681
+ class << recipe
682
+ attr_accessor :cross_build_p
683
+
684
+ def configure
685
+ Dir.chdir(work_path) do
686
+ mk = File.read("win32/Makefile.gcc")
687
+ File.open("win32/Makefile.gcc", "wb") do |f|
688
+ f.puts "BINARY_PATH = #{path}/bin"
689
+ f.puts "LIBRARY_PATH = #{path}/lib"
690
+ f.puts "INCLUDE_PATH = #{path}/include"
691
+ mk.sub!(/^PREFIX\s*=\s*$/, "PREFIX = #{host}-") if cross_build_p
692
+ f.puts mk
693
+ end
495
694
  end
496
695
  end
497
- end
498
696
 
499
- def configured?
500
- Dir.chdir work_path do
501
- !! (File.read('win32/Makefile.gcc') =~ /^BINARY_PATH/)
697
+ def configured?
698
+ Dir.chdir(work_path) do
699
+ !!(File.read("win32/Makefile.gcc") =~ /^BINARY_PATH/)
700
+ end
502
701
  end
503
- end
504
702
 
505
- def compile
506
- execute "compile", "make -f win32/Makefile.gcc"
507
- end
703
+ def compile
704
+ execute("compile", "make -f win32/Makefile.gcc")
705
+ end
508
706
 
509
- def install
510
- execute "install", "make -f win32/Makefile.gcc install"
707
+ def install
708
+ execute("install", "make -f win32/Makefile.gcc install")
709
+ end
710
+ end
711
+ recipe.cross_build_p = cross_build_p
712
+ else
713
+ class << recipe
714
+ def configure
715
+ cflags = concat_flags(ENV["CFLAGS"], "-fPIC", "-g")
716
+ execute("configure",
717
+ ["env", "CHOST=#{host}", "CFLAGS=#{cflags}", "./configure", "--static", configure_prefix])
718
+ end
511
719
  end
512
720
  end
513
- recipe.cross_build_p = cross_build_p
514
721
  end
515
722
 
516
- libiconv_recipe = process_recipe("libiconv", dependencies["libiconv"]["version"], static_p, cross_build_p) do |recipe|
517
- recipe.files = [{
518
- url: "http://ftp.gnu.org/pub/gnu/libiconv/#{recipe.name}-#{recipe.version}.tar.gz",
519
- sha256: dependencies["libiconv"]["sha256"]
723
+ unless nix?
724
+ libiconv_recipe = process_recipe("libiconv", dependencies["libiconv"]["version"], static_p,
725
+ cross_build_p) do |recipe|
726
+ recipe.files = [{
727
+ url: "https://ftp.gnu.org/pub/gnu/libiconv/#{recipe.name}-#{recipe.version}.tar.gz",
728
+ sha256: dependencies["libiconv"]["sha256"],
520
729
  }]
521
- recipe.configure_options += [
522
- "CPPFLAGS=-Wall",
523
- "CFLAGS=-O2 -g",
524
- "CXXFLAGS=-O2 -g",
525
- "LDFLAGS="
526
- ]
527
- end
528
- else
529
- if darwin? && !have_header('iconv.h')
530
- abort <<'EOM'.chomp
531
- -----
532
- The file "iconv.h" is missing in your build environment,
533
- which means you haven't installed Xcode Command Line Tools properly.
534
-
535
- To install Command Line Tools, try running `xcode-select --install` on
536
- terminal and follow the instructions. If it fails, open Xcode.app,
537
- select from the menu "Xcode" - "Open Developer Tool" - "More Developer
538
- Tools" to open the developer site, download the installer for your OS
539
- version and run it.
540
- -----
541
- EOM
730
+
731
+ # The libiconv configure script doesn't accept "arm64" host string but "aarch64"
732
+ recipe.host = recipe.host.gsub("arm64-apple-darwin", "aarch64-apple-darwin")
733
+
734
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-U_FORTIFY_SOURCE", "-g")
735
+
736
+ recipe.configure_options += [
737
+ "--disable-dependency-tracking",
738
+ "CPPFLAGS=-Wall",
739
+ "CFLAGS=#{cflags}",
740
+ "CXXFLAGS=#{cflags}",
741
+ "LDFLAGS=",
742
+ ]
743
+ end
542
744
  end
745
+ elsif darwin? && !have_header("iconv.h")
746
+ abort(<<~EOM.chomp)
747
+ -----
748
+ The file "iconv.h" is missing in your build environment,
749
+ which means you haven't installed Xcode Command Line Tools properly.
750
+
751
+ To install Command Line Tools, try running `xcode-select --install` on
752
+ terminal and follow the instructions. If it fails, open Xcode.app,
753
+ select from the menu "Xcode" - "Open Developer Tool" - "More Developer
754
+ Tools" to open the developer site, download the installer for your OS
755
+ version and run it.
756
+ -----
757
+ EOM
758
+ end
759
+
760
+ if zlib_recipe
761
+ append_cppflags("-I#{zlib_recipe.path}/include")
762
+ $LIBPATH = ["#{zlib_recipe.path}/lib"] | $LIBPATH
763
+ ensure_package_configuration(opt: "zlib", pc: "zlib", lib: "z",
764
+ headers: "zlib.h", func: "gzdopen")
543
765
  end
544
766
 
545
- unless windows?
546
- preserving_globals {
547
- have_library('z', 'gzdopen', 'zlib.h')
548
- } or abort 'zlib is missing; necessary for building libxml2'
767
+ if libiconv_recipe
768
+ append_cppflags("-I#{libiconv_recipe.path}/include")
769
+ $LIBPATH = ["#{libiconv_recipe.path}/lib"] | $LIBPATH
770
+ ensure_package_configuration(opt: "iconv", pc: "iconv", lib: "iconv",
771
+ headers: "iconv.h", func: "iconv_open")
549
772
  end
550
773
 
551
774
  libxml2_recipe = process_recipe("libxml2", dependencies["libxml2"]["version"], static_p, cross_build_p) do |recipe|
552
- recipe.files = [{
553
- url: "http://xmlsoft.org/sources/#{recipe.name}-#{recipe.version}.tar.gz",
554
- sha256: dependencies["libxml2"]["sha256"]
775
+ source_dir = arg_config("--with-xml2-source-dir")
776
+ if source_dir
777
+ recipe.source_directory = source_dir
778
+ else
779
+ minor_version = Gem::Version.new(recipe.version).segments.take(2).join(".")
780
+ recipe.files = [{
781
+ url: "#{gnome_source}/sources/libxml2/#{minor_version}/#{recipe.name}-#{recipe.version}.tar.xz",
782
+ sha256: dependencies["libxml2"]["sha256"],
555
783
  }]
784
+ recipe.patch_files = Dir[File.join(PACKAGE_ROOT_DIR, "patches", "libxml2", "*.patch")].sort
785
+ end
786
+
787
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-U_FORTIFY_SOURCE", "-g")
788
+
789
+ if zlib_recipe
790
+ recipe.configure_options << "--with-zlib=#{zlib_recipe.path}"
791
+ end
792
+
793
+ if libiconv_recipe
794
+ recipe.configure_options << "--with-iconv=#{libiconv_recipe.path}"
795
+ else
796
+ recipe.configure_options += iconv_configure_flags
797
+ end
798
+
799
+ if darwin? && !cross_build_p
800
+ recipe.configure_options += ["RANLIB=/usr/bin/ranlib", "AR=/usr/bin/ar"]
801
+ end
802
+
803
+ if windows?
804
+ cflags = concat_flags(cflags, "-ULIBXML_STATIC", "-DIN_LIBXML")
805
+ end
806
+
807
+ recipe.configure_options << if source_dir
808
+ "--config-cache"
809
+ else
810
+ "--disable-dependency-tracking"
811
+ end
812
+
556
813
  recipe.configure_options += [
557
814
  "--without-python",
558
815
  "--without-readline",
559
- *(zlib_recipe ? ["--with-zlib=#{zlib_recipe.path}", "CFLAGS=-I#{zlib_recipe.path}/include"] : []),
560
- *(libiconv_recipe ? "--with-iconv=#{libiconv_recipe.path}" : iconv_configure_flags),
561
816
  "--with-c14n",
562
817
  "--with-debug",
563
- "--with-threads"
818
+ "--with-threads",
819
+ "CFLAGS=#{cflags}",
564
820
  ]
565
821
  end
566
822
 
567
823
  libxslt_recipe = process_recipe("libxslt", dependencies["libxslt"]["version"], static_p, cross_build_p) do |recipe|
568
- recipe.files = [{
569
- url: "http://xmlsoft.org/sources/#{recipe.name}-#{recipe.version}.tar.gz",
570
- sha256: dependencies["libxslt"]["sha256"]
824
+ source_dir = arg_config("--with-xslt-source-dir")
825
+ if source_dir
826
+ recipe.source_directory = source_dir
827
+ else
828
+ minor_version = Gem::Version.new(recipe.version).segments.take(2).join(".")
829
+ recipe.files = [{
830
+ url: "#{gnome_source}/sources/libxslt/#{minor_version}/#{recipe.name}-#{recipe.version}.tar.xz",
831
+ sha256: dependencies["libxslt"]["sha256"],
571
832
  }]
833
+ recipe.patch_files = Dir[File.join(PACKAGE_ROOT_DIR, "patches", "libxslt", "*.patch")].sort
834
+ end
835
+
836
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-U_FORTIFY_SOURCE", "-g")
837
+
838
+ if darwin? && !cross_build_p
839
+ recipe.configure_options += ["RANLIB=/usr/bin/ranlib", "AR=/usr/bin/ar"]
840
+ end
841
+
842
+ recipe.configure_options << if source_dir
843
+ "--config-cache"
844
+ else
845
+ "--disable-dependency-tracking"
846
+ end
847
+
572
848
  recipe.configure_options += [
573
849
  "--without-python",
574
850
  "--without-crypto",
575
851
  "--with-debug",
576
- "--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}"
852
+ "--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}",
853
+ "CFLAGS=#{cflags}",
577
854
  ]
578
855
  end
579
856
 
580
- $CFLAGS << ' ' << '-DNOKOGIRI_USE_PACKAGED_LIBRARIES'
581
- $LIBPATH = ["#{zlib_recipe.path}/lib"] | $LIBPATH if zlib_recipe
582
- $LIBPATH = ["#{libiconv_recipe.path}/lib"] | $LIBPATH if libiconv_recipe
583
-
584
- have_lzma = preserving_globals {
585
- have_library('lzma')
586
- }
857
+ append_cppflags("-DNOKOGIRI_PACKAGED_LIBRARIES")
858
+ append_cppflags("-DNOKOGIRI_PRECOMPILED_LIBRARIES") if cross_build_p
587
859
 
588
860
  $libs = $libs.shellsplit.tap do |libs|
589
861
  [libxml2_recipe, libxslt_recipe].each do |recipe|
590
862
  libname = recipe.name[/\Alib(.+)\z/, 1]
591
863
  File.join(recipe.path, "bin", "#{libname}-config").tap do |config|
592
864
  # call config scripts explicit with 'sh' for compat with Windows
593
- $CPPFLAGS = `sh #{config} --cflags`.strip << ' ' << $CPPFLAGS
594
- `sh #{config} --libs`.strip.shellsplit.each do |arg|
865
+ $CPPFLAGS = %x(sh #{config} --cflags).strip << " " << $CPPFLAGS
866
+ %x(sh #{config} --libs).strip.shellsplit.each do |arg|
595
867
  case arg
596
868
  when /\A-L(.+)\z/
597
869
  # Prioritize ports' directories
598
- if $1.start_with?(ROOT + '/')
599
- $LIBPATH = [$1] | $LIBPATH
870
+ $LIBPATH = if Regexp.last_match(1).start_with?(PACKAGE_ROOT_DIR + "/")
871
+ [Regexp.last_match(1)] | $LIBPATH
600
872
  else
601
- $LIBPATH = $LIBPATH | [$1]
873
+ $LIBPATH | [Regexp.last_match(1)]
602
874
  end
603
875
  when /\A-l./
604
876
  libs.unshift(arg)
605
877
  else
606
- $LDFLAGS << ' ' << arg.shellescape
878
+ $LDFLAGS << " " << arg.shellescape
607
879
  end
608
880
  end
609
881
  end
610
882
 
611
- # Defining a macro that expands to a C string; double quotes are significant.
612
- $CPPFLAGS << ' ' << "-DNOKOGIRI_#{recipe.name.upcase}_PATH=\"#{recipe.path}\"".inspect
613
- $CPPFLAGS << ' ' << "-DNOKOGIRI_#{recipe.name.upcase}_PATCHES=\"#{recipe.patch_files.map { |path| File.basename(path) }.join(' ')}\"".inspect
883
+ patches_string = recipe.patch_files.map { |path| File.basename(path) }.join(" ")
884
+ append_cppflags(%[-DNOKOGIRI_#{recipe.name.upcase}_PATCHES="\\\"#{patches_string}\\\""])
614
885
 
615
886
  case libname
616
- when 'xml2'
887
+ when "xml2"
617
888
  # xslt-config --libs or pkg-config libxslt --libs does not include
618
889
  # -llzma, so we need to add it manually when linking statically.
619
- if static_p && have_lzma
890
+ if static_p && preserving_globals { local_have_library("lzma") }
620
891
  # Add it at the end; GH #988
621
- libs << '-llzma'
892
+ libs << "-llzma"
622
893
  end
623
- when 'xslt'
894
+ when "xslt"
624
895
  # xslt-config does not have a flag to emit options including
625
896
  # -lexslt, so add it manually.
626
- libs.unshift('-lexslt')
897
+ libs.unshift("-lexslt")
627
898
  end
628
899
  end
629
900
  end.shelljoin
@@ -631,48 +902,107 @@ EOM
631
902
  if static_p
632
903
  $libs = $libs.shellsplit.map do |arg|
633
904
  case arg
634
- when '-lxml2'
635
- File.join(libxml2_recipe.path, 'lib', lib_a(arg))
636
- when '-lxslt', '-lexslt'
637
- File.join(libxslt_recipe.path, 'lib', lib_a(arg))
905
+ when "-lxml2"
906
+ File.join(libxml2_recipe.path, "lib", libflag_to_filename(arg))
907
+ when "-lxslt", "-lexslt"
908
+ File.join(libxslt_recipe.path, "lib", libflag_to_filename(arg))
638
909
  else
639
910
  arg
640
911
  end
641
912
  end.shelljoin
642
913
  end
643
- end
644
914
 
645
- {
646
- "xml2" => ['xmlParseDoc', 'libxml/parser.h'],
647
- "xslt" => ['xsltParseStylesheetDoc', 'libxslt/xslt.h'],
648
- "exslt" => ['exsltFuncRegister', 'libexslt/exslt.h'],
649
- }.each do |lib, (func, header)|
650
- have_func(func, header) ||
651
- have_library(lib, func, header) ||
652
- have_library("lib#{lib}", func, header) or
653
- asplode("lib#{lib}")
915
+ ensure_func("xmlParseDoc", "libxml/parser.h")
916
+ ensure_func("xsltParseStylesheetDoc", "libxslt/xslt.h")
917
+ ensure_func("exsltFuncRegister", "libexslt/exslt.h")
654
918
  end
655
919
 
656
- have_func('xmlHasFeature') or abort "xmlHasFeature() is missing."
657
- have_func('xmlFirstElementChild')
658
- have_func('xmlRelaxNGSetParserStructuredErrors')
659
- have_func('xmlRelaxNGSetParserStructuredErrors')
660
- have_func('xmlRelaxNGSetValidStructuredErrors')
661
- have_func('xmlSchemaSetValidStructuredErrors')
662
- have_func('xmlSchemaSetParserStructuredErrors')
920
+ libgumbo_recipe = process_recipe("libgumbo", "1.0.0-nokogiri", static_p, cross_build_p, false) do |recipe|
921
+ recipe.configure_options = []
922
+
923
+ class << recipe
924
+ def downloaded?
925
+ true
926
+ end
663
927
 
664
- create_makefile('nokogiri/nokogiri')
928
+ def extract
929
+ target = File.join(tmp_path, "gumbo-parser")
930
+ output("Copying gumbo-parser files into #{target}...")
931
+ FileUtils.mkdir_p(target)
932
+ FileUtils.cp(Dir.glob(File.join(PACKAGE_ROOT_DIR, "gumbo-parser/src/*")), target)
933
+ end
665
934
 
666
- if enable_config('clean', true)
667
- # Do not clean if run in a development work tree.
668
- File.open('Makefile', 'at') do |mk|
669
- mk.print <<EOF
670
- all: clean-ports
935
+ def configured?
936
+ true
937
+ end
938
+
939
+ def install
940
+ lib_dir = File.join(port_path, "lib")
941
+ inc_dir = File.join(port_path, "include")
942
+ FileUtils.mkdir_p([lib_dir, inc_dir])
943
+ FileUtils.cp(File.join(work_path, "libgumbo.a"), lib_dir)
944
+ FileUtils.cp(Dir.glob(File.join(work_path, "*.h")), inc_dir)
945
+ end
946
+
947
+ def compile
948
+ cflags = concat_flags(ENV["CFLAGS"], "-fPIC", "-g")
671
949
 
672
- clean-ports: $(DLLIB)
673
- -$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? 'enable' : 'disable'}-static
674
- EOF
950
+ env = { "CC" => gcc_cmd, "CFLAGS" => cflags }
951
+ if config_cross_build?
952
+ if /darwin/.match?(host)
953
+ env["AR"] = "#{host}-libtool"
954
+ env["ARFLAGS"] = "-o"
955
+ else
956
+ env["AR"] = "#{host}-ar"
957
+ end
958
+ env["RANLIB"] = "#{host}-ranlib"
959
+ end
960
+
961
+ execute("compile", make_cmd, { env: env })
962
+ end
675
963
  end
676
964
  end
965
+ append_cppflags("-I#{File.join(libgumbo_recipe.path, "include")}")
966
+ $libs = $libs + " " + File.join(libgumbo_recipe.path, "lib", "libgumbo.a")
967
+ $LIBPATH = $LIBPATH | [File.join(libgumbo_recipe.path, "lib")]
968
+ ensure_func("gumbo_parse_with_options", "gumbo.h")
969
+
970
+ have_func("xmlHasFeature") || abort("xmlHasFeature() is missing.") # introduced in libxml 2.6.21
971
+ have_func("xmlFirstElementChild") # introduced in libxml 2.7.3
972
+ have_func("xmlRelaxNGSetParserStructuredErrors") # introduced in libxml 2.6.24
973
+ have_func("xmlRelaxNGSetValidStructuredErrors") # introduced in libxml 2.6.21
974
+ have_func("xmlSchemaSetValidStructuredErrors") # introduced in libxml 2.6.23
975
+ have_func("xmlSchemaSetParserStructuredErrors") # introduced in libxml 2.6.23
976
+
977
+ have_func("vasprintf")
978
+
979
+ other_library_versions_string = OTHER_LIBRARY_VERSIONS.map { |k, v| [k, v].join(":") }.join(",")
980
+ append_cppflags(%[-DNOKOGIRI_OTHER_LIBRARY_VERSIONS="\\\"#{other_library_versions_string}\\\""])
981
+
982
+ unless config_system_libraries?
983
+ if cross_build_p
984
+ # When precompiling native gems, copy packaged libraries' headers to ext/nokogiri/include
985
+ # These are packaged up by the cross-compiling callback in the ExtensionTask
986
+ copy_packaged_libraries_headers(to_path: File.join(PACKAGE_ROOT_DIR, "ext/nokogiri/include"),
987
+ from_recipes: [libxml2_recipe, libxslt_recipe])
988
+ else
989
+ # When compiling during installation, install packaged libraries' header files into ext/nokogiri/include
990
+ copy_packaged_libraries_headers(to_path: "include",
991
+ from_recipes: [libxml2_recipe, libxslt_recipe])
992
+ $INSTALLFILES << ["include/**/*.h", "$(rubylibdir)"]
993
+ end
994
+ end
995
+
996
+ create_makefile("nokogiri/nokogiri")
677
997
 
678
- # :startdoc:
998
+ if config_clean?
999
+ # Do not clean if run in a development work tree.
1000
+ File.open("Makefile", "at") do |mk|
1001
+ mk.print(<<~EOF)
1002
+
1003
+ all: clean-ports
1004
+ clean-ports: $(DLLIB)
1005
+ \t-$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? "enable" : "disable"}-static
1006
+ EOF
1007
+ end
1008
+ end