nokogiri 1.8.5 → 1.13.9

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 (353) 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 +765 -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 +199 -88
  19. data/ext/nokogiri/test_global_handlers.c +40 -0
  20. data/ext/nokogiri/xml_attr.c +42 -37
  21. data/ext/nokogiri/xml_attribute_decl.c +21 -21
  22. data/ext/nokogiri/xml_cdata.c +14 -19
  23. data/ext/nokogiri/xml_comment.c +19 -26
  24. data/ext/nokogiri/xml_document.c +296 -217
  25. data/ext/nokogiri/xml_document_fragment.c +12 -16
  26. data/ext/nokogiri/xml_dtd.c +64 -58
  27. data/ext/nokogiri/xml_element_content.c +31 -26
  28. data/ext/nokogiri/xml_element_decl.c +25 -25
  29. data/ext/nokogiri/xml_encoding_handler.c +43 -18
  30. data/ext/nokogiri/xml_entity_decl.c +37 -35
  31. data/ext/nokogiri/xml_entity_reference.c +16 -18
  32. data/ext/nokogiri/xml_namespace.c +99 -54
  33. data/ext/nokogiri/xml_node.c +1107 -658
  34. data/ext/nokogiri/xml_node_set.c +178 -166
  35. data/ext/nokogiri/xml_processing_instruction.c +17 -19
  36. data/ext/nokogiri/xml_reader.c +277 -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 +114 -35
  42. data/ext/nokogiri/xml_syntax_error.c +42 -21
  43. data/ext/nokogiri/xml_text.c +14 -18
  44. data/ext/nokogiri/xml_xpath_context.c +226 -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 +21 -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/0005-avoid-isnan-isinf.patch +81 -0
  169. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  170. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +3037 -0
  171. data/ports/archives/libxml2-2.10.3.tar.xz +0 -0
  172. data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
  173. metadata +211 -266
  174. data/.autotest +0 -22
  175. data/.cross_rubies +0 -8
  176. data/.editorconfig +0 -17
  177. data/.gemtest +0 -0
  178. data/.travis.yml +0 -63
  179. data/CHANGELOG.md +0 -1368
  180. data/CONTRIBUTING.md +0 -42
  181. data/C_CODING_STYLE.rdoc +0 -33
  182. data/Gemfile-libxml-ruby +0 -3
  183. data/Manifest.txt +0 -370
  184. data/ROADMAP.md +0 -111
  185. data/Rakefile +0 -348
  186. data/SECURITY.md +0 -19
  187. data/STANDARD_RESPONSES.md +0 -47
  188. data/Y_U_NO_GEMSPEC.md +0 -155
  189. data/appveyor.yml +0 -29
  190. data/build_all +0 -44
  191. data/ext/nokogiri/html_document.c +0 -170
  192. data/ext/nokogiri/html_document.h +0 -10
  193. data/ext/nokogiri/html_element_description.c +0 -279
  194. data/ext/nokogiri/html_element_description.h +0 -10
  195. data/ext/nokogiri/html_entity_lookup.c +0 -32
  196. data/ext/nokogiri/html_entity_lookup.h +0 -8
  197. data/ext/nokogiri/html_sax_parser_context.c +0 -116
  198. data/ext/nokogiri/html_sax_parser_context.h +0 -11
  199. data/ext/nokogiri/html_sax_push_parser.c +0 -87
  200. data/ext/nokogiri/html_sax_push_parser.h +0 -9
  201. data/ext/nokogiri/xml_attr.h +0 -9
  202. data/ext/nokogiri/xml_attribute_decl.h +0 -9
  203. data/ext/nokogiri/xml_cdata.h +0 -9
  204. data/ext/nokogiri/xml_comment.h +0 -9
  205. data/ext/nokogiri/xml_document.h +0 -23
  206. data/ext/nokogiri/xml_document_fragment.h +0 -10
  207. data/ext/nokogiri/xml_dtd.h +0 -10
  208. data/ext/nokogiri/xml_element_content.h +0 -10
  209. data/ext/nokogiri/xml_element_decl.h +0 -9
  210. data/ext/nokogiri/xml_encoding_handler.h +0 -8
  211. data/ext/nokogiri/xml_entity_decl.h +0 -10
  212. data/ext/nokogiri/xml_entity_reference.h +0 -9
  213. data/ext/nokogiri/xml_io.c +0 -61
  214. data/ext/nokogiri/xml_io.h +0 -11
  215. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
  216. data/ext/nokogiri/xml_libxml2_hacks.h +0 -12
  217. data/ext/nokogiri/xml_namespace.h +0 -15
  218. data/ext/nokogiri/xml_node.h +0 -13
  219. data/ext/nokogiri/xml_node_set.h +0 -12
  220. data/ext/nokogiri/xml_processing_instruction.h +0 -9
  221. data/ext/nokogiri/xml_reader.h +0 -10
  222. data/ext/nokogiri/xml_relax_ng.h +0 -9
  223. data/ext/nokogiri/xml_sax_parser.h +0 -39
  224. data/ext/nokogiri/xml_sax_parser_context.h +0 -10
  225. data/ext/nokogiri/xml_sax_push_parser.h +0 -9
  226. data/ext/nokogiri/xml_schema.h +0 -9
  227. data/ext/nokogiri/xml_syntax_error.h +0 -13
  228. data/ext/nokogiri/xml_text.h +0 -9
  229. data/ext/nokogiri/xml_xpath_context.h +0 -10
  230. data/ext/nokogiri/xslt_stylesheet.h +0 -14
  231. data/lib/nokogiri/html/document_fragment.rb +0 -49
  232. data/lib/nokogiri/html/element_description_defaults.rb +0 -671
  233. data/lib/nokogiri/html/sax/parser_context.rb +0 -16
  234. data/patches/libxml2/0001-Revert-Do-not-URI-escape-in-server-side-includes.patch +0 -78
  235. data/patches/libxml2/0002-Fix-nullptr-deref-with-XPath-logic-ops.patch +0 -54
  236. data/patches/libxml2/0003-Fix-infinite-loop-in-LZMA-decompression.patch +0 -50
  237. data/patches/sort-patches-by-date +0 -25
  238. data/ports/archives/libxml2-2.9.8.tar.gz +0 -0
  239. data/ports/archives/libxslt-1.1.32.tar.gz +0 -0
  240. data/suppressions/README.txt +0 -1
  241. data/suppressions/nokogiri_ruby-2.supp +0 -10
  242. data/tasks/test.rb +0 -100
  243. data/test/css/test_nthiness.rb +0 -226
  244. data/test/css/test_parser.rb +0 -386
  245. data/test/css/test_tokenizer.rb +0 -215
  246. data/test/css/test_xpath_visitor.rb +0 -96
  247. data/test/decorators/test_slop.rb +0 -23
  248. data/test/files/2ch.html +0 -108
  249. data/test/files/GH_1042.html +0 -18
  250. data/test/files/address_book.rlx +0 -12
  251. data/test/files/address_book.xml +0 -10
  252. data/test/files/atom.xml +0 -344
  253. data/test/files/bar/bar.xsd +0 -4
  254. data/test/files/bogus.xml +0 -0
  255. data/test/files/dont_hurt_em_why.xml +0 -422
  256. data/test/files/encoding.html +0 -82
  257. data/test/files/encoding.xhtml +0 -84
  258. data/test/files/exslt.xml +0 -8
  259. data/test/files/exslt.xslt +0 -35
  260. data/test/files/foo/foo.xsd +0 -4
  261. data/test/files/metacharset.html +0 -10
  262. data/test/files/namespace_pressure_test.xml +0 -1684
  263. data/test/files/noencoding.html +0 -47
  264. data/test/files/po.xml +0 -32
  265. data/test/files/po.xsd +0 -66
  266. data/test/files/saml/saml20assertion_schema.xsd +0 -283
  267. data/test/files/saml/saml20protocol_schema.xsd +0 -302
  268. data/test/files/saml/xenc_schema.xsd +0 -146
  269. data/test/files/saml/xmldsig_schema.xsd +0 -318
  270. data/test/files/shift_jis.html +0 -10
  271. data/test/files/shift_jis.xml +0 -5
  272. data/test/files/shift_jis_no_charset.html +0 -9
  273. data/test/files/slow-xpath.xml +0 -25509
  274. data/test/files/snuggles.xml +0 -3
  275. data/test/files/staff.dtd +0 -10
  276. data/test/files/staff.xml +0 -59
  277. data/test/files/staff.xslt +0 -32
  278. data/test/files/test_document_url/bar.xml +0 -2
  279. data/test/files/test_document_url/document.dtd +0 -4
  280. data/test/files/test_document_url/document.xml +0 -6
  281. data/test/files/tlm.html +0 -851
  282. data/test/files/to_be_xincluded.xml +0 -2
  283. data/test/files/valid_bar.xml +0 -2
  284. data/test/files/xinclude.xml +0 -4
  285. data/test/helper.rb +0 -271
  286. data/test/html/sax/test_parser.rb +0 -168
  287. data/test/html/sax/test_parser_context.rb +0 -46
  288. data/test/html/sax/test_parser_text.rb +0 -163
  289. data/test/html/sax/test_push_parser.rb +0 -87
  290. data/test/html/test_attributes.rb +0 -85
  291. data/test/html/test_builder.rb +0 -164
  292. data/test/html/test_document.rb +0 -712
  293. data/test/html/test_document_encoding.rb +0 -143
  294. data/test/html/test_document_fragment.rb +0 -310
  295. data/test/html/test_element_description.rb +0 -105
  296. data/test/html/test_named_characters.rb +0 -14
  297. data/test/html/test_node.rb +0 -212
  298. data/test/html/test_node_encoding.rb +0 -91
  299. data/test/namespaces/test_additional_namespaces_in_builder_doc.rb +0 -14
  300. data/test/namespaces/test_namespaces_aliased_default.rb +0 -24
  301. data/test/namespaces/test_namespaces_in_builder_doc.rb +0 -75
  302. data/test/namespaces/test_namespaces_in_cloned_doc.rb +0 -31
  303. data/test/namespaces/test_namespaces_in_created_doc.rb +0 -75
  304. data/test/namespaces/test_namespaces_in_parsed_doc.rb +0 -80
  305. data/test/namespaces/test_namespaces_preservation.rb +0 -31
  306. data/test/test_convert_xpath.rb +0 -135
  307. data/test/test_css_cache.rb +0 -47
  308. data/test/test_encoding_handler.rb +0 -48
  309. data/test/test_memory_leak.rb +0 -156
  310. data/test/test_nokogiri.rb +0 -138
  311. data/test/test_soap4r_sax.rb +0 -52
  312. data/test/test_xslt_transforms.rb +0 -314
  313. data/test/xml/node/test_save_options.rb +0 -28
  314. data/test/xml/node/test_subclass.rb +0 -44
  315. data/test/xml/sax/test_parser.rb +0 -402
  316. data/test/xml/sax/test_parser_context.rb +0 -115
  317. data/test/xml/sax/test_parser_text.rb +0 -202
  318. data/test/xml/sax/test_push_parser.rb +0 -265
  319. data/test/xml/test_attr.rb +0 -74
  320. data/test/xml/test_attribute_decl.rb +0 -86
  321. data/test/xml/test_builder.rb +0 -341
  322. data/test/xml/test_c14n.rb +0 -180
  323. data/test/xml/test_cdata.rb +0 -54
  324. data/test/xml/test_comment.rb +0 -40
  325. data/test/xml/test_document.rb +0 -982
  326. data/test/xml/test_document_encoding.rb +0 -31
  327. data/test/xml/test_document_fragment.rb +0 -298
  328. data/test/xml/test_dtd.rb +0 -187
  329. data/test/xml/test_dtd_encoding.rb +0 -31
  330. data/test/xml/test_element_content.rb +0 -56
  331. data/test/xml/test_element_decl.rb +0 -73
  332. data/test/xml/test_entity_decl.rb +0 -122
  333. data/test/xml/test_entity_reference.rb +0 -262
  334. data/test/xml/test_namespace.rb +0 -96
  335. data/test/xml/test_node.rb +0 -1325
  336. data/test/xml/test_node_attributes.rb +0 -115
  337. data/test/xml/test_node_encoding.rb +0 -75
  338. data/test/xml/test_node_inheritance.rb +0 -32
  339. data/test/xml/test_node_reparenting.rb +0 -592
  340. data/test/xml/test_node_set.rb +0 -809
  341. data/test/xml/test_parse_options.rb +0 -64
  342. data/test/xml/test_processing_instruction.rb +0 -30
  343. data/test/xml/test_reader.rb +0 -620
  344. data/test/xml/test_reader_encoding.rb +0 -134
  345. data/test/xml/test_relax_ng.rb +0 -60
  346. data/test/xml/test_schema.rb +0 -142
  347. data/test/xml/test_syntax_error.rb +0 -36
  348. data/test/xml/test_text.rb +0 -60
  349. data/test/xml/test_unparented_node.rb +0 -483
  350. data/test/xml/test_xinclude.rb +0 -83
  351. data/test/xml/test_xpath.rb +0 -470
  352. data/test/xslt/test_custom_functions.rb +0 -133
  353. 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
81
- end
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)
82
256
 
83
- def do_clean
84
- require 'pathname'
85
- require 'fileutils'
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
263
+ end
86
264
 
87
- root = Pathname(ROOT)
88
- pwd = Pathname(Dir.pwd)
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
89
271
 
90
- # Skip if this is a development work tree
91
- unless (root + '.git').exist?
92
- message "Cleaning files only used during build.\n"
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
93
276
 
94
- # (root + 'tmp') cannot be removed at this stage because
95
- # nokogiri.so is yet to be copied to lib.
277
+ try_package_configuration(pc) if pc
96
278
 
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,436 @@ 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
-
335
- message <<-"EOS"
336
-
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:
341
510
 
342
- gem install nokogiri -- --use-system-libraries
343
- [--with-xml2-config=/path/to/xml2-config]
344
- [--with-xslt-config=/path/to/xslt-config]
511
+ message(<<~EOM) if name != "libgumbo"
345
512
 
346
- If you are using Bundler, tell it to use the option:
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:
347
517
 
348
- bundle config build.nokogiri --use-system-libraries
349
- bundle install
350
- EOS
518
+ https://nokogiri.org/tutorials/installing_nokogiri.html#installing-using-standard-system-libraries
351
519
 
352
- message <<-"EOS" if name == 'libxml2'
520
+ EOM
353
521
 
354
- Note, however, that nokogiri is not fully compatible with arbitrary
355
- versions of libxml2 provided by OS/package vendors.
356
- 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.
357
525
 
358
- message <<-"EOS"
359
- ************************************************************************
360
- EOS
526
+ EOM
361
527
 
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
+ env = {}
716
+ env["CFLAGS"] = concat_flags(ENV["CFLAGS"], "-fPIC", "-g")
717
+ env["CHOST"] = host
718
+ execute("configure", ["./configure", "--static", configure_prefix], { env: env })
719
+ if darwin?
720
+ # needed as of zlib 1.2.13
721
+ Dir.chdir(work_path) do
722
+ makefile = File.read("Makefile").gsub(/^AR=.*$/, "AR=#{host}-libtool")
723
+ File.open("Makefile", "w") { |m| m.write(makefile) }
724
+ end
725
+ end
726
+ end
511
727
  end
512
728
  end
513
- recipe.cross_build_p = cross_build_p
514
729
  end
515
730
 
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"]
731
+ unless nix?
732
+ libiconv_recipe = process_recipe("libiconv", dependencies["libiconv"]["version"], static_p,
733
+ cross_build_p) do |recipe|
734
+ recipe.files = [{
735
+ url: "https://ftp.gnu.org/pub/gnu/libiconv/#{recipe.name}-#{recipe.version}.tar.gz",
736
+ sha256: dependencies["libiconv"]["sha256"],
520
737
  }]
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
738
+
739
+ # The libiconv configure script doesn't accept "arm64" host string but "aarch64"
740
+ recipe.host = recipe.host.gsub("arm64-apple-darwin", "aarch64-apple-darwin")
741
+
742
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-U_FORTIFY_SOURCE", "-g")
743
+
744
+ recipe.configure_options += [
745
+ "--disable-dependency-tracking",
746
+ "CPPFLAGS=-Wall",
747
+ "CFLAGS=#{cflags}",
748
+ "CXXFLAGS=#{cflags}",
749
+ "LDFLAGS=",
750
+ ]
751
+ end
542
752
  end
753
+ elsif darwin? && !have_header("iconv.h")
754
+ abort(<<~EOM.chomp)
755
+ -----
756
+ The file "iconv.h" is missing in your build environment,
757
+ which means you haven't installed Xcode Command Line Tools properly.
758
+
759
+ To install Command Line Tools, try running `xcode-select --install` on
760
+ terminal and follow the instructions. If it fails, open Xcode.app,
761
+ select from the menu "Xcode" - "Open Developer Tool" - "More Developer
762
+ Tools" to open the developer site, download the installer for your OS
763
+ version and run it.
764
+ -----
765
+ EOM
766
+ end
767
+
768
+ if zlib_recipe
769
+ append_cppflags("-I#{zlib_recipe.path}/include")
770
+ $LIBPATH = ["#{zlib_recipe.path}/lib"] | $LIBPATH
771
+ ensure_package_configuration(opt: "zlib", pc: "zlib", lib: "z",
772
+ headers: "zlib.h", func: "gzdopen")
543
773
  end
544
774
 
545
- unless windows?
546
- preserving_globals {
547
- have_library('z', 'gzdopen', 'zlib.h')
548
- } or abort 'zlib is missing; necessary for building libxml2'
775
+ if libiconv_recipe
776
+ append_cppflags("-I#{libiconv_recipe.path}/include")
777
+ $LIBPATH = ["#{libiconv_recipe.path}/lib"] | $LIBPATH
778
+ ensure_package_configuration(opt: "iconv", pc: "iconv", lib: "iconv",
779
+ headers: "iconv.h", func: "iconv_open")
549
780
  end
550
781
 
551
782
  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"]
783
+ source_dir = arg_config("--with-xml2-source-dir")
784
+ if source_dir
785
+ recipe.source_directory = source_dir
786
+ else
787
+ minor_version = Gem::Version.new(recipe.version).segments.take(2).join(".")
788
+ recipe.files = [{
789
+ url: "#{gnome_source}/sources/libxml2/#{minor_version}/#{recipe.name}-#{recipe.version}.tar.xz",
790
+ sha256: dependencies["libxml2"]["sha256"],
555
791
  }]
792
+ recipe.patch_files = Dir[File.join(PACKAGE_ROOT_DIR, "patches", "libxml2", "*.patch")].sort
793
+ end
794
+
795
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-U_FORTIFY_SOURCE", "-g")
796
+
797
+ if zlib_recipe
798
+ recipe.configure_options << "--with-zlib=#{zlib_recipe.path}"
799
+ end
800
+
801
+ if libiconv_recipe
802
+ recipe.configure_options << "--with-iconv=#{libiconv_recipe.path}"
803
+ else
804
+ recipe.configure_options += iconv_configure_flags
805
+ end
806
+
807
+ if darwin? && !cross_build_p
808
+ recipe.configure_options += ["RANLIB=/usr/bin/ranlib", "AR=/usr/bin/ar"]
809
+ end
810
+
811
+ if windows?
812
+ cflags = concat_flags(cflags, "-ULIBXML_STATIC", "-DIN_LIBXML")
813
+ end
814
+
815
+ recipe.configure_options << if source_dir
816
+ "--config-cache"
817
+ else
818
+ "--disable-dependency-tracking"
819
+ end
820
+
556
821
  recipe.configure_options += [
557
822
  "--without-python",
558
823
  "--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
824
  "--with-c14n",
562
825
  "--with-debug",
563
- "--with-threads"
826
+ "--with-threads",
827
+ "CFLAGS=#{cflags}",
564
828
  ]
565
829
  end
566
830
 
567
831
  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"]
832
+ source_dir = arg_config("--with-xslt-source-dir")
833
+ if source_dir
834
+ recipe.source_directory = source_dir
835
+ else
836
+ minor_version = Gem::Version.new(recipe.version).segments.take(2).join(".")
837
+ recipe.files = [{
838
+ url: "#{gnome_source}/sources/libxslt/#{minor_version}/#{recipe.name}-#{recipe.version}.tar.xz",
839
+ sha256: dependencies["libxslt"]["sha256"],
571
840
  }]
841
+ recipe.patch_files = Dir[File.join(PACKAGE_ROOT_DIR, "patches", "libxslt", "*.patch")].sort
842
+ end
843
+
844
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-U_FORTIFY_SOURCE", "-g")
845
+
846
+ if darwin? && !cross_build_p
847
+ recipe.configure_options += ["RANLIB=/usr/bin/ranlib", "AR=/usr/bin/ar"]
848
+ end
849
+
850
+ if windows?
851
+ cflags = concat_flags(cflags, "-ULIBXSLT_STATIC", "-DIN_LIBXSLT")
852
+ cflags = concat_flags(cflags, "-ULIBEXSLT_STATIC", "-DIN_LIBEXSLT")
853
+ end
854
+
855
+ recipe.configure_options << if source_dir
856
+ "--config-cache"
857
+ else
858
+ "--disable-dependency-tracking"
859
+ end
860
+
572
861
  recipe.configure_options += [
573
862
  "--without-python",
574
863
  "--without-crypto",
575
864
  "--with-debug",
576
- "--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}"
865
+ "--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}",
866
+ "CFLAGS=#{cflags}",
577
867
  ]
578
868
  end
579
869
 
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
- }
870
+ append_cppflags("-DNOKOGIRI_PACKAGED_LIBRARIES")
871
+ append_cppflags("-DNOKOGIRI_PRECOMPILED_LIBRARIES") if cross_build_p
587
872
 
588
873
  $libs = $libs.shellsplit.tap do |libs|
589
874
  [libxml2_recipe, libxslt_recipe].each do |recipe|
590
875
  libname = recipe.name[/\Alib(.+)\z/, 1]
591
876
  File.join(recipe.path, "bin", "#{libname}-config").tap do |config|
592
877
  # 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|
878
+ $CPPFLAGS = %x(sh #{config} --cflags).strip << " " << $CPPFLAGS
879
+ %x(sh #{config} --libs).strip.shellsplit.each do |arg|
595
880
  case arg
596
881
  when /\A-L(.+)\z/
597
882
  # Prioritize ports' directories
598
- if $1.start_with?(ROOT + '/')
599
- $LIBPATH = [$1] | $LIBPATH
883
+ $LIBPATH = if Regexp.last_match(1).start_with?(PACKAGE_ROOT_DIR + "/")
884
+ [Regexp.last_match(1)] | $LIBPATH
600
885
  else
601
- $LIBPATH = $LIBPATH | [$1]
886
+ $LIBPATH | [Regexp.last_match(1)]
602
887
  end
603
888
  when /\A-l./
604
889
  libs.unshift(arg)
605
890
  else
606
- $LDFLAGS << ' ' << arg.shellescape
891
+ $LDFLAGS << " " << arg.shellescape
607
892
  end
608
893
  end
609
894
  end
610
895
 
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
896
+ patches_string = recipe.patch_files.map { |path| File.basename(path) }.join(" ")
897
+ append_cppflags(%[-DNOKOGIRI_#{recipe.name.upcase}_PATCHES="\\\"#{patches_string}\\\""])
614
898
 
615
899
  case libname
616
- when 'xml2'
900
+ when "xml2"
617
901
  # xslt-config --libs or pkg-config libxslt --libs does not include
618
902
  # -llzma, so we need to add it manually when linking statically.
619
- if static_p && have_lzma
903
+ if static_p && preserving_globals { local_have_library("lzma") }
620
904
  # Add it at the end; GH #988
621
- libs << '-llzma'
905
+ libs << "-llzma"
622
906
  end
623
- when 'xslt'
907
+ when "xslt"
624
908
  # xslt-config does not have a flag to emit options including
625
909
  # -lexslt, so add it manually.
626
- libs.unshift('-lexslt')
910
+ libs.unshift("-lexslt")
627
911
  end
628
912
  end
629
913
  end.shelljoin
@@ -631,48 +915,109 @@ EOM
631
915
  if static_p
632
916
  $libs = $libs.shellsplit.map do |arg|
633
917
  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))
918
+ when "-lxml2"
919
+ File.join(libxml2_recipe.path, "lib", libflag_to_filename(arg))
920
+ when "-lxslt", "-lexslt"
921
+ File.join(libxslt_recipe.path, "lib", libflag_to_filename(arg))
638
922
  else
639
923
  arg
640
924
  end
641
925
  end.shelljoin
642
926
  end
643
- end
644
927
 
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}")
928
+ ensure_func("xmlParseDoc", "libxml/parser.h")
929
+ ensure_func("xsltParseStylesheetDoc", "libxslt/xslt.h")
930
+ ensure_func("exsltFuncRegister", "libexslt/exslt.h")
654
931
  end
655
932
 
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')
933
+ libgumbo_recipe = process_recipe("libgumbo", "1.0.0-nokogiri", static_p, cross_build_p, false) do |recipe|
934
+ recipe.configure_options = []
663
935
 
664
- create_makefile('nokogiri/nokogiri')
936
+ class << recipe
937
+ def downloaded?
938
+ true
939
+ end
665
940
 
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
941
+ def extract
942
+ target = File.join(tmp_path, "gumbo-parser")
943
+ output("Copying gumbo-parser files into #{target}...")
944
+ FileUtils.mkdir_p(target)
945
+ FileUtils.cp(Dir.glob(File.join(PACKAGE_ROOT_DIR, "gumbo-parser/src/*")), target)
946
+ end
671
947
 
672
- clean-ports: $(DLLIB)
673
- -$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? 'enable' : 'disable'}-static
674
- EOF
948
+ def configured?
949
+ true
950
+ end
951
+
952
+ def install
953
+ lib_dir = File.join(port_path, "lib")
954
+ inc_dir = File.join(port_path, "include")
955
+ FileUtils.mkdir_p([lib_dir, inc_dir])
956
+ FileUtils.cp(File.join(work_path, "libgumbo.a"), lib_dir)
957
+ FileUtils.cp(Dir.glob(File.join(work_path, "*.h")), inc_dir)
958
+ end
959
+
960
+ def compile
961
+ cflags = concat_flags(ENV["CFLAGS"], "-fPIC", "-g")
962
+
963
+ env = { "CC" => gcc_cmd, "CFLAGS" => cflags }
964
+ if config_cross_build?
965
+ if /darwin/.match?(host)
966
+ env["AR"] = "#{host}-libtool"
967
+ env["ARFLAGS"] = "-o"
968
+ else
969
+ env["AR"] = "#{host}-ar"
970
+ end
971
+ env["RANLIB"] = "#{host}-ranlib"
972
+ end
973
+
974
+ execute("compile", make_cmd, { env: env })
975
+ end
675
976
  end
676
977
  end
978
+ append_cppflags("-I#{File.join(libgumbo_recipe.path, "include")}")
979
+ $libs = $libs + " " + File.join(libgumbo_recipe.path, "lib", "libgumbo.a")
980
+ $LIBPATH = $LIBPATH | [File.join(libgumbo_recipe.path, "lib")]
981
+ ensure_func("gumbo_parse_with_options", "gumbo.h")
982
+
983
+ have_func("xmlHasFeature") || abort("xmlHasFeature() is missing.") # introduced in libxml 2.6.21
984
+ have_func("xmlFirstElementChild") # introduced in libxml 2.7.3
985
+ have_func("xmlRelaxNGSetParserStructuredErrors") # introduced in libxml 2.6.24
986
+ have_func("xmlRelaxNGSetValidStructuredErrors") # introduced in libxml 2.6.21
987
+ have_func("xmlSchemaSetValidStructuredErrors") # introduced in libxml 2.6.23
988
+ have_func("xmlSchemaSetParserStructuredErrors") # introduced in libxml 2.6.23
989
+ have_func("rb_gc_location") # introduced in Ruby 2.7
990
+ have_func("rb_category_warning") # introduced in Ruby 3.0
991
+
992
+ have_func("vasprintf")
993
+
994
+ other_library_versions_string = OTHER_LIBRARY_VERSIONS.map { |k, v| [k, v].join(":") }.join(",")
995
+ append_cppflags(%[-DNOKOGIRI_OTHER_LIBRARY_VERSIONS="\\\"#{other_library_versions_string}\\\""])
996
+
997
+ unless config_system_libraries?
998
+ if cross_build_p
999
+ # When precompiling native gems, copy packaged libraries' headers to ext/nokogiri/include
1000
+ # These are packaged up by the cross-compiling callback in the ExtensionTask
1001
+ copy_packaged_libraries_headers(to_path: File.join(PACKAGE_ROOT_DIR, "ext/nokogiri/include"),
1002
+ from_recipes: [libxml2_recipe, libxslt_recipe])
1003
+ else
1004
+ # When compiling during installation, install packaged libraries' header files into ext/nokogiri/include
1005
+ copy_packaged_libraries_headers(to_path: "include",
1006
+ from_recipes: [libxml2_recipe, libxslt_recipe])
1007
+ $INSTALLFILES << ["include/**/*.h", "$(rubylibdir)"]
1008
+ end
1009
+ end
1010
+
1011
+ create_makefile("nokogiri/nokogiri")
677
1012
 
678
- # :startdoc:
1013
+ if config_clean?
1014
+ # Do not clean if run in a development work tree.
1015
+ File.open("Makefile", "at") do |mk|
1016
+ mk.print(<<~EOF)
1017
+
1018
+ all: clean-ports
1019
+ clean-ports: $(DLLIB)
1020
+ \t-$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? "enable" : "disable"}-static
1021
+ EOF
1022
+ end
1023
+ end