nokogiri 1.6.8.1 → 1.13.4

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 (354) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +3 -20
  3. data/LICENSE-DEPENDENCIES.md +1903 -0
  4. data/LICENSE.md +9 -0
  5. data/README.md +197 -83
  6. data/bin/nokogiri +63 -50
  7. data/dependencies.yml +16 -22
  8. data/ext/nokogiri/depend +38 -358
  9. data/ext/nokogiri/extconf.rb +751 -432
  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 +120 -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 -95
  18. data/ext/nokogiri/nokogiri.h +190 -98
  19. data/ext/nokogiri/test_global_handlers.c +40 -0
  20. data/ext/nokogiri/xml_attr.c +49 -40
  21. data/ext/nokogiri/xml_attribute_decl.c +18 -18
  22. data/ext/nokogiri/xml_cdata.c +24 -23
  23. data/ext/nokogiri/xml_comment.c +19 -26
  24. data/ext/nokogiri/xml_document.c +291 -217
  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 -58
  33. data/ext/nokogiri/xml_node.c +1194 -729
  34. data/ext/nokogiri/xml_node_set.c +178 -165
  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 +115 -114
  39. data/ext/nokogiri/xml_sax_parser_context.c +105 -86
  40. data/ext/nokogiri/xml_sax_push_parser.c +88 -35
  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 +410 -372
  94. data/lib/nokogiri/css/parser.y +260 -244
  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 +7 -6
  99. data/lib/nokogiri/css/xpath_visitor.rb +226 -92
  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 +104 -106
  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 +24 -13
  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 -107
  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 +231 -93
  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 +20 -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 +911 -337
  139. data/lib/nokogiri/xml/node_set.rb +141 -84
  140. data/lib/nokogiri/xml/notation.rb +13 -0
  141. data/lib/nokogiri/xml/parse_options.rb +23 -9
  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 +43 -40
  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 +138 -89
  155. data/lib/nokogiri/xml/syntax_error.rb +26 -1
  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 +39 -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/libxml2/0010-Revert-Different-approach-to-fix-quadratic-behavior.patch +45 -0
  174. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +3037 -0
  175. data/ports/archives/libxml2-2.9.13.tar.xz +0 -0
  176. data/ports/archives/libxslt-1.1.35.tar.xz +0 -0
  177. metadata +233 -258
  178. data/.autotest +0 -26
  179. data/.cross_rubies +0 -9
  180. data/.editorconfig +0 -17
  181. data/.gemtest +0 -0
  182. data/.travis.yml +0 -51
  183. data/CHANGELOG.rdoc +0 -1160
  184. data/CONTRIBUTING.md +0 -42
  185. data/C_CODING_STYLE.rdoc +0 -33
  186. data/LICENSE.txt +0 -31
  187. data/Manifest.txt +0 -364
  188. data/ROADMAP.md +0 -111
  189. data/Rakefile +0 -375
  190. data/STANDARD_RESPONSES.md +0 -47
  191. data/Y_U_NO_GEMSPEC.md +0 -155
  192. data/appveyor.yml +0 -22
  193. data/build_all +0 -45
  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 -60
  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 -13
  221. data/ext/nokogiri/xml_node.h +0 -13
  222. data/ext/nokogiri/xml_node_set.h +0 -13
  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 -39
  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/sort-patches-by-date +0 -25
  238. data/ports/archives/libxml2-2.9.4.tar.gz +0 -0
  239. data/ports/archives/libxslt-1.1.29.tar.gz +0 -0
  240. data/suppressions/README.txt +0 -1
  241. data/suppressions/nokogiri_ree-1.8.7.358.supp +0 -61
  242. data/suppressions/nokogiri_ruby-1.8.7.370.supp +0 -0
  243. data/suppressions/nokogiri_ruby-1.9.2.320.supp +0 -28
  244. data/suppressions/nokogiri_ruby-1.9.3.327.supp +0 -28
  245. data/tasks/test.rb +0 -100
  246. data/test/css/test_nthiness.rb +0 -226
  247. data/test/css/test_parser.rb +0 -369
  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 -20
  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 -181
  289. data/test/html/sax/test_parser.rb +0 -141
  290. data/test/html/sax/test_parser_context.rb +0 -46
  291. data/test/html/sax/test_push_parser.rb +0 -87
  292. data/test/html/test_builder.rb +0 -164
  293. data/test/html/test_document.rb +0 -701
  294. data/test/html/test_document_encoding.rb +0 -145
  295. data/test/html/test_document_fragment.rb +0 -301
  296. data/test/html/test_element_description.rb +0 -105
  297. data/test/html/test_named_characters.rb +0 -14
  298. data/test/html/test_node.rb +0 -212
  299. data/test/html/test_node_encoding.rb +0 -85
  300. data/test/namespaces/test_additional_namespaces_in_builder_doc.rb +0 -14
  301. data/test/namespaces/test_namespaces_aliased_default.rb +0 -24
  302. data/test/namespaces/test_namespaces_in_builder_doc.rb +0 -75
  303. data/test/namespaces/test_namespaces_in_cloned_doc.rb +0 -31
  304. data/test/namespaces/test_namespaces_in_created_doc.rb +0 -75
  305. data/test/namespaces/test_namespaces_in_parsed_doc.rb +0 -80
  306. data/test/namespaces/test_namespaces_preservation.rb +0 -31
  307. data/test/test_convert_xpath.rb +0 -135
  308. data/test/test_css_cache.rb +0 -45
  309. data/test/test_encoding_handler.rb +0 -48
  310. data/test/test_memory_leak.rb +0 -156
  311. data/test/test_nokogiri.rb +0 -138
  312. data/test/test_soap4r_sax.rb +0 -52
  313. data/test/test_xslt_transforms.rb +0 -314
  314. data/test/xml/node/test_save_options.rb +0 -28
  315. data/test/xml/node/test_subclass.rb +0 -44
  316. data/test/xml/sax/test_parser.rb +0 -394
  317. data/test/xml/sax/test_parser_context.rb +0 -115
  318. data/test/xml/sax/test_push_parser.rb +0 -157
  319. data/test/xml/test_attr.rb +0 -67
  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 -48
  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 -271
  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 -251
  334. data/test/xml/test_namespace.rb +0 -96
  335. data/test/xml/test_node.rb +0 -1244
  336. data/test/xml/test_node_attributes.rb +0 -115
  337. data/test/xml/test_node_encoding.rb +0 -69
  338. data/test/xml/test_node_inheritance.rb +0 -32
  339. data/test/xml/test_node_reparenting.rb +0 -549
  340. data/test/xml/test_node_set.rb +0 -775
  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 -589
  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 -30
  348. data/test/xml/test_text.rb +0 -60
  349. data/test/xml/test_unparented_node.rb +0 -440
  350. data/test/xml/test_xinclude.rb +0 -83
  351. data/test/xml/test_xpath.rb +0 -445
  352. data/test/xslt/test_custom_functions.rb +0 -133
  353. data/test/xslt/test_exception_handling.rb +0 -37
  354. data/test_all +0 -107
@@ -1,209 +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
  #
11
- def windows?
12
- RbConfig::CONFIG['target_os'] =~ /mingw32|mswin/
159
+ def config_clean?
160
+ enable_config("clean", true)
13
161
  end
14
162
 
15
- def solaris?
16
- RbConfig::CONFIG['target_os'] =~ /solaris/
163
+ def config_static?
164
+ default_static = !truffle?
165
+ enable_config("static", default_static)
17
166
  end
18
167
 
19
- def darwin?
20
- RbConfig::CONFIG['target_os'] =~ /darwin/
168
+ def config_cross_build?
169
+ enable_config("cross-build")
21
170
  end
22
171
 
23
- def nix?
24
- ! (windows? || solaris? || darwin?)
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
25
176
  end
26
177
 
27
- def sh_export_path path
28
- # because libxslt 1.1.29 configure.in uses AC_PATH_TOOL which treats ":"
29
- # as a $PATH separator, we need to convert windows paths from
30
- #
31
- # C:/path/to/foo
32
- #
33
- # to
34
- #
35
- # /C/path/to/foo
36
- #
37
- # which is sh-compatible, in order to find things properly during
38
- # configuration
39
- if windows?
40
- match = Regexp.new("^([A-Z]):(/.*)").match(path)
41
- if match && match.length == 3
42
- return File.join("/", match[1], match[2])
43
- end
44
- end
45
- path
178
+ def windows?
179
+ RbConfig::CONFIG["target_os"].match?(/mingw|mswin/)
46
180
  end
47
181
 
48
- def do_help
49
- print <<HELP
50
- usage: ruby #{$0} [options]
182
+ def solaris?
183
+ RbConfig::CONFIG["target_os"].include?("solaris")
184
+ end
51
185
 
52
- --disable-clean
53
- Do not clean out intermediate files after successful build.
186
+ def darwin?
187
+ RbConfig::CONFIG["target_os"].include?("darwin")
188
+ end
54
189
 
55
- --disable-static
56
- Do not statically link bundled libraries.
190
+ def openbsd?
191
+ RbConfig::CONFIG["target_os"].include?("openbsd")
192
+ end
57
193
 
58
- --with-iconv-dir=DIR
59
- Use the iconv library placed under DIR.
194
+ def aix?
195
+ RbConfig::CONFIG["target_os"].include?("aix")
196
+ end
60
197
 
61
- --with-zlib-dir=DIR
62
- Use the zlib library placed under DIR.
198
+ def nix?
199
+ !(windows? || solaris? || darwin?)
200
+ end
63
201
 
64
- --use-system-libraries
65
- Use system libraries intead of building and using the bundled
66
- libraries.
202
+ def truffle?
203
+ ::RUBY_ENGINE == "truffleruby"
204
+ end
67
205
 
68
- --with-xml2-dir=DIR / --with-xml2-config=CONFIG
69
- --with-xslt-dir=DIR / --with-xslt-config=CONFIG
70
- --with-exslt-dir=DIR / --with-exslt-config=CONFIG
71
- Use libxml2/libxslt/libexslt as specified.
206
+ def concat_flags(*args)
207
+ args.compact.join(" ")
208
+ end
72
209
 
73
- --enable-cross-build
74
- Do cross-build.
75
- HELP
76
- exit! 0
210
+ def local_have_library(lib, func = nil, headers = nil)
211
+ have_library(lib, func, headers) || have_library("lib#{lib}", func, headers)
77
212
  end
78
213
 
79
- def do_clean
80
- require 'pathname'
81
- require 'fileutils'
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
82
225
 
83
- root = Pathname(ROOT)
84
- pwd = Pathname(Dir.pwd)
226
+ LOCAL_PACKAGE_RESPONSE = Object.new
227
+ def LOCAL_PACKAGE_RESPONSE.%(package)
228
+ package ? "yes: #{package}" : "no"
229
+ end
85
230
 
86
- # Skip if this is a development work tree
87
- unless (root + '.git').exist?
88
- message "Cleaning files only used during build.\n"
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
89
239
 
90
- # (root + 'tmp') cannot be removed at this stage because
91
- # nokogiri.so is yet to be copied to lib.
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"
92
247
 
93
- # clean the ports build directory
94
- Pathname.glob(pwd.join('tmp', '*', 'ports')) do |dir|
95
- FileUtils.rm_rf(dir, verbose: true)
96
- end
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)
97
253
 
98
- if enable_config('static')
99
- # ports installation can be safely removed if statically linked.
100
- FileUtils.rm_rf(root + 'ports', verbose: true)
101
- else
102
- FileUtils.rm_rf(root + 'ports' + 'archives', verbose: true)
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
103
259
  end
260
+ rescue LoadError
261
+ message("Please install either the `pkg-config` utility or the `pkg-config` rubygem.\n")
104
262
  end
105
-
106
- exit! 0
107
263
  end
108
264
 
109
- def package_config pkg, options={}
110
- package = pkg_config(pkg)
111
- return package if package
112
-
113
- begin
114
- require 'rubygems'
115
- gem 'pkg-config', (gem_ver='~> 1.1.7')
116
- require 'pkg-config' and message("Using pkg-config gem version #{PKGConfig::VERSION}\n")
117
- rescue LoadError
118
- 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"
119
- else
120
- return nil unless PKGConfig.have_package(pkg)
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
121
271
 
122
- cflags = PKGConfig.cflags(pkg)
123
- ldflags = PKGConfig.libs_only_L(pkg)
124
- libs = PKGConfig.libs_only_l(pkg)
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
125
276
 
126
- Logging::message "PKGConfig package configuration for %s\n", pkg
127
- Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n", cflags, ldflags, libs
277
+ try_package_configuration(pc) if pc
128
278
 
129
- [cflags, ldflags, libs]
130
- end
279
+ # verify that we can compile and link against the library
280
+ local_have_library(lib, func, headers)
131
281
  end
132
282
 
133
- def nokogiri_try_compile
134
- args = if defined?(RUBY_VERSION) && RUBY_VERSION <= "1.9.2"
135
- ["int main() {return 0;}"]
136
- else
137
- ["int main() {return 0;}", "", {werror: true}]
138
- end
139
- try_compile(*args)
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)
140
286
  end
141
287
 
142
- def check_libxml_version version=nil
143
- source = if version.nil?
144
- <<-SRC
145
- #include <libxml/xmlversion.h>
146
- SRC
147
- else
148
- version_int = sprintf "%d%2.2d%2.2d", *(version.split("."))
149
- <<-SRC
150
- #include <libxml/xmlversion.h>
151
- #if LIBXML_VERSION < #{version_int}
152
- #error libxml2 is older than #{version}
153
- #endif
154
- SRC
155
- end
156
-
157
- try_cpp source
158
- end
159
-
160
- def add_cflags(flags)
161
- print "checking if the C compiler accepts #{flags}... "
162
- with_cflags("#{$CFLAGS} #{flags}") do
163
- if nokogiri_try_compile
164
- puts 'yes'
165
- true
166
- else
167
- puts 'no'
168
- false
169
- end
170
- end
288
+ def ensure_func(func, headers = nil)
289
+ have_func(func, headers) || abort_could_not_find_library(func)
171
290
  end
172
291
 
173
292
  def preserving_globals
174
- values = [
175
- $arg_config,
176
- $CFLAGS, $CPPFLAGS,
177
- $LDFLAGS, $LIBPATH, $libs
178
- ].map(&:dup)
293
+ values = [$arg_config, $INCFLAGS, $CFLAGS, $CPPFLAGS, $LDFLAGS, $DLDFLAGS, $LIBPATH, $libs].map(&:dup)
179
294
  yield
180
295
  ensure
181
- $arg_config,
182
- $CFLAGS, $CPPFLAGS,
183
- $LDFLAGS, $LIBPATH, $libs =
184
- values
296
+ $arg_config, $INCFLAGS, $CFLAGS, $CPPFLAGS, $LDFLAGS, $DLDFLAGS, $LIBPATH, $libs = values
185
297
  end
186
298
 
187
- def asplode(lib)
188
- abort "-----\n#{lib} is missing. Please locate mkmf.log to investigate how it is failing.\n-----"
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-----")
189
302
  end
190
303
 
191
- def have_iconv?(using = nil)
192
- checking_for(using ? "iconv using #{using}" : 'iconv') do
193
- ['', '-liconv'].any? do |opt|
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
311
+
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?
325
+
326
+ match = Regexp.new("^([A-Z]):(/.*)").match(path)
327
+ if match && match.length == 3
328
+ return File.join("/", match[1], match[2])
329
+ end
330
+
331
+ path
332
+ end
333
+
334
+ def libflag_to_filename(ldflag)
335
+ case ldflag
336
+ when /\A-l(.+)/
337
+ "lib#{Regexp.last_match(1)}.#{$LIBEXT}"
338
+ end
339
+ end
340
+
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
355
+
356
+ try_cpp(source)
357
+ end
358
+
359
+ def try_link_iconv(using = nil)
360
+ checking_for(using ? "iconv using #{using}" : "iconv") do
361
+ ["", "-liconv"].any? do |opt|
194
362
  preserving_globals do
195
363
  yield if block_given?
196
364
 
197
- try_link(<<-'SRC', opt)
198
- #include <stdlib.h>
199
- #include <iconv.h>
200
-
201
- int main(void)
202
- {
203
- iconv_t cd = iconv_open("", "");
204
- iconv(cd, NULL, NULL, NULL, NULL);
205
- return EXIT_SUCCESS;
206
- }
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
+ }
207
374
  SRC
208
375
  end
209
376
  end
@@ -211,66 +378,68 @@ int main(void)
211
378
  end
212
379
 
213
380
  def iconv_configure_flags
214
- # If --with-iconv-dir or --with-opt-dir is given, it should be
215
- # the first priority
216
- %w[iconv opt].each do |name|
217
- if (config = preserving_globals { dir_config(name) }).any? &&
218
- have_iconv?("--with-#{name}-* flags") { dir_config(name) }
219
- idirs, ldirs = config.map do |dirs|
220
- Array(dirs).flat_map do |dir|
221
- dir.split(File::PATH_SEPARATOR)
222
- end if dirs
223
- end
224
-
225
- return [
226
- '--with-iconv=yes',
227
- *("CPPFLAGS=#{idirs.map { |dir| '-I' << dir }.join(' ')}" if idirs),
228
- *("LDFLAGS=#{ldirs.map { |dir| '-L' << dir }.join(' ')}" if ldirs),
229
- ]
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
230
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
+ ]
231
397
  end
232
398
 
233
- if have_iconv?
234
- return ['--with-iconv=yes']
399
+ if try_link_iconv
400
+ return ["--with-iconv=yes"]
235
401
  end
236
402
 
237
- if (config = preserving_globals { package_config('libiconv') }) &&
238
- 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") }
239
405
  cflags, ldflags, libs = config
240
406
 
241
407
  return [
242
- '--with-iconv=yes',
408
+ "--with-iconv=yes",
243
409
  "CPPFLAGS=#{cflags}",
244
410
  "LDFLAGS=#{ldflags}",
245
411
  "LIBS=#{libs}",
246
412
  ]
247
413
  end
248
414
 
249
- asplode "libiconv"
415
+ abort_could_not_find_library("libiconv")
250
416
  end
251
417
 
252
- # When using rake-compiler-dock on Windows, the underlying Virtualbox shared
253
- # folders don't support symlinks, but libiconv expects it for a build on
254
- # Linux. We work around this limitation by using the temp dir for cooking.
255
- def chdir_for_build
256
- build_dir = ENV['RCD_HOST_RUBY_PLATFORM'].to_s =~ /mingw|mswin|cygwin/ ? '/tmp' : '.'
257
- Dir.chdir(build_dir) do
258
- 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
259
426
  end
260
- end
261
427
 
262
- def process_recipe(name, version, static_p, cross_p)
263
428
  MiniPortile.new(name, version).tap do |recipe|
264
- recipe.target = portsdir = File.join(ROOT, "ports")
265
- # Prefer host_alias over host in order to use i586-mingw32msvc as
266
- # 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.
267
436
  recipe.host = RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"]
268
- recipe.patch_files = Dir[File.join(ROOT, "patches", name, "*.patch")].sort
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,330 +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
-
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
- # monkey patches
386
- #
549
+ def do_clean
550
+ root = Pathname(PACKAGE_ROOT_DIR)
551
+ pwd = Pathname(Dir.pwd)
387
552
 
388
- # Workaround for Ruby bug #8074, introduced in Ruby 2.0.0, fixed in Ruby 2.1.0
389
- # https://bugs.ruby-lang.org/issues/8074
390
- @libdir_basename = "lib" if RUBY_VERSION < '2.1.0'
553
+ # Skip if this is a development work tree
554
+ unless (root + ".git").exist?
555
+ message("Cleaning files only used during build.\n")
391
556
 
392
- #
393
- # main
394
- #
557
+ # (root + 'tmp') cannot be removed at this stage because
558
+ # nokogiri.so is yet to be copied to lib.
395
559
 
396
- case
397
- when arg_config('--help')
398
- do_help
399
- when arg_config('--clean')
400
- do_clean
401
- end
560
+ # clean the ports build directory
561
+ Pathname.glob(pwd.join("tmp", "*", "ports")) do |dir|
562
+ FileUtils.rm_rf(dir, verbose: true)
563
+ end
402
564
 
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']
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
406
572
 
407
- # TODO: deprecate MacRuby: https://github.com/sparklemotion/nokogiri/issues/1474
408
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'macruby'
409
- $LIBRUBYARG_STATIC.gsub!(/-static/, '')
573
+ exit!(0)
410
574
  end
411
575
 
412
- $LIBS << " #{ENV["LIBS"]}"
413
-
414
- # Read CFLAGS from ENV and make sure compiling works.
415
- add_cflags(ENV["CFLAGS"])
576
+ #
577
+ # main
578
+ #
579
+ do_help if arg_config("--help")
580
+ do_clean if arg_config("--clean")
416
581
 
417
- if windows?
418
- $CFLAGS << " -DXP_WIN -DXP_WIN32 -DUSE_INCLUDED_VASPRINTF"
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"
419
588
  end
420
589
 
421
- if solaris?
422
- $CFLAGS << " -DUSE_INCLUDED_VASPRINTF"
590
+ if ENV["CC"]
591
+ RbConfig::CONFIG["CC"] = RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"]
423
592
  end
424
593
 
425
- if darwin?
426
- # Let Apple LLVM/clang 5.1 ignore unknown compiler flags
427
- add_cflags("-Wno-error=unused-command-line-argument-hard-error-in-future")
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
428
607
  end
429
608
 
430
- if nix?
431
- $CFLAGS << " -g -DXP_UNIX"
432
- 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"])
433
614
 
434
- if RUBY_PLATFORM =~ /mingw/i
435
- # Work around a character escaping bug in MSYS by passing an arbitrary
436
- # double quoted parameter to gcc. See https://sourceforge.net/p/mingw/bugs/2142
437
- $CPPFLAGS << ' "-Idummypath"'
438
- end
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"])
439
618
 
440
- if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
441
- $CFLAGS << " -O3" unless $CFLAGS[/-O\d/]
442
- $CFLAGS << " -Wall -Wcast-qual -Wwrite-strings -Wconversion -Wmissing-noreturn -Winline"
443
- end
619
+ # always include debugging information
620
+ append_cflags("-g")
444
621
 
445
- case
446
- when using_system_libraries?
447
- message "Building nokogiri using system libraries.\n"
622
+ # we use at least one inline function in the C extension
623
+ append_cflags("-Winline")
624
+
625
+ # good to have no matter what Ruby was compiled with
626
+ append_cflags("-Wmissing-noreturn")
448
627
 
449
- dir_config('zlib')
628
+ # handle clang variations, see #1101
629
+ append_cflags("-Wno-error=unused-command-line-argument-hard-error-in-future") if darwin?
450
630
 
451
- # Using system libraries means we rely on the system libxml2 with
452
- # regard to the iconv support.
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
453
639
 
454
- dir_config('xml2').any? or package_config('libxml-2.0')
455
- dir_config('xslt').any? or package_config('libxslt')
456
- dir_config('exslt').any? or package_config('libexslt')
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?
457
643
 
458
- check_libxml_version or abort "ERROR: cannot discover where libxml2 is located on your system. please make sure `pkg-config` is installed."
459
- check_libxml_version("2.6.21") or abort "ERROR: libxml2 version 2.6.21 or later is required!"
460
- check_libxml_version("2.9.3") or warn "WARNING: libxml2 version 2.9.3 or later is highly recommended, but proceeding anyway."
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.")
461
659
 
462
660
  else
463
661
  message "Building nokogiri using packaged libraries.\n"
464
662
 
465
- # The gem version constraint in the Rakefile is not respected at install time.
466
- # Keep this version in sync with the one in the Rakefile !
467
- require 'rubygems'
468
- gem 'mini_portile2', '~> 2.1.0'
469
- require 'mini_portile2'
470
- message "Using mini_portile version #{MiniPortile::VERSION}\n"
471
-
472
- require 'yaml'
663
+ static_p = config_static?
664
+ message "Static linking is #{static_p ? "enabled" : "disabled"}.\n"
473
665
 
474
- static_p = enable_config('static', true) or
475
- message "Static linking is disabled.\n"
666
+ cross_build_p = config_cross_build?
667
+ message "Cross build is #{cross_build_p ? "enabled" : "disabled"}.\n"
476
668
 
477
- dir_config('zlib')
669
+ require "yaml"
670
+ dependencies = YAML.load_file(File.join(PACKAGE_ROOT_DIR, "dependencies.yml"))
478
671
 
479
- dependencies = YAML.load_file(File.join(ROOT, "dependencies.yml"))
672
+ dir_config("zlib")
480
673
 
481
- cross_build_p = enable_config("cross-build")
482
674
  if cross_build_p || windows?
483
675
  zlib_recipe = process_recipe("zlib", dependencies["zlib"]["version"], static_p, cross_build_p) do |recipe|
484
676
  recipe.files = [{
485
- url: "http://zlib.net/#{recipe.name}-#{recipe.version}.tar.gz",
486
- md5: dependencies["zlib"]["md5"]
487
- }]
488
- class << recipe
489
- attr_accessor :cross_build_p
490
-
491
- def configure
492
- Dir.chdir work_path do
493
- mk = File.read 'win32/Makefile.gcc'
494
- File.open 'win32/Makefile.gcc', 'wb' do |f|
495
- f.puts "BINARY_PATH = #{path}/bin"
496
- f.puts "LIBRARY_PATH = #{path}/lib"
497
- f.puts "INCLUDE_PATH = #{path}/include"
498
- mk.sub!(/^PREFIX\s*=\s*$/, "PREFIX = #{host}-") if cross_build_p
499
- 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
500
694
  end
501
695
  end
502
- end
503
696
 
504
- def configured?
505
- Dir.chdir work_path do
506
- !! (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
507
701
  end
508
- end
509
702
 
510
- def compile
511
- execute "compile", "make -f win32/Makefile.gcc"
512
- end
703
+ def compile
704
+ execute("compile", "make -f win32/Makefile.gcc")
705
+ end
513
706
 
514
- def install
515
- 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
516
719
  end
517
720
  end
518
- recipe.cross_build_p = cross_build_p
519
721
  end
520
722
 
521
- libiconv_recipe = process_recipe("libiconv", dependencies["libiconv"]["version"], static_p, cross_build_p) do |recipe|
522
- recipe.files = [{
523
- url: "http://ftp.gnu.org/pub/gnu/libiconv/#{recipe.name}-#{recipe.version}.tar.gz",
524
- md5: dependencies["libiconv"]["md5"]
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"],
525
729
  }]
526
- recipe.configure_options += [
527
- "CPPFLAGS=-Wall",
528
- "CFLAGS=-O2 -g",
529
- "CXXFLAGS=-O2 -g",
530
- "LDFLAGS="
531
- ]
532
- end
533
- else
534
- if darwin? && !have_header('iconv.h')
535
- abort <<'EOM'.chomp
536
- -----
537
- The file "iconv.h" is missing in your build environment,
538
- which means you haven't installed Xcode Command Line Tools properly.
539
-
540
- To install Command Line Tools, try running `xcode-select --install` on
541
- terminal and follow the instructions. If it fails, open Xcode.app,
542
- select from the menu "Xcode" - "Open Developer Tool" - "More Developer
543
- Tools" to open the developer site, download the installer for your OS
544
- version and run it.
545
- -----
546
- 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
547
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
548
758
  end
549
759
 
550
- unless windows?
551
- preserving_globals {
552
- have_library('z', 'gzdopen', 'zlib.h')
553
- } or abort 'zlib is missing; necessary for building libxml2'
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")
765
+ end
766
+
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")
554
772
  end
555
773
 
556
774
  libxml2_recipe = process_recipe("libxml2", dependencies["libxml2"]["version"], static_p, cross_build_p) do |recipe|
557
- recipe.files = [{
558
- url: "http://xmlsoft.org/sources/#{recipe.name}-#{recipe.version}.tar.gz",
559
- md5: dependencies["libxml2"]["md5"]
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"],
560
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
+
561
813
  recipe.configure_options += [
562
814
  "--without-python",
563
815
  "--without-readline",
564
- *(zlib_recipe ? ["--with-zlib=#{zlib_recipe.path}", "CFLAGS=-I#{zlib_recipe.path}/include"] : []),
565
- *(libiconv_recipe ? "--with-iconv=#{libiconv_recipe.path}" : iconv_configure_flags),
566
816
  "--with-c14n",
567
817
  "--with-debug",
568
- "--with-threads"
818
+ "--with-threads",
819
+ "CFLAGS=#{cflags}",
569
820
  ]
570
821
  end
571
822
 
572
823
  libxslt_recipe = process_recipe("libxslt", dependencies["libxslt"]["version"], static_p, cross_build_p) do |recipe|
573
- recipe.files = [{
574
- url: "http://xmlsoft.org/sources/#{recipe.name}-#{recipe.version}.tar.gz",
575
- md5: dependencies["libxslt"]["md5"]
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"],
576
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
+
577
848
  recipe.configure_options += [
578
849
  "--without-python",
579
850
  "--without-crypto",
580
851
  "--with-debug",
581
- "--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}"
852
+ "--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}",
853
+ "CFLAGS=#{cflags}",
582
854
  ]
583
855
  end
584
856
 
585
- $CFLAGS << ' ' << '-DNOKOGIRI_USE_PACKAGED_LIBRARIES'
586
- $LIBPATH = ["#{zlib_recipe.path}/lib"] | $LIBPATH if zlib_recipe
587
- $LIBPATH = ["#{libiconv_recipe.path}/lib"] | $LIBPATH if libiconv_recipe
588
-
589
- have_lzma = preserving_globals {
590
- have_library('lzma')
591
- }
857
+ append_cppflags("-DNOKOGIRI_PACKAGED_LIBRARIES")
858
+ append_cppflags("-DNOKOGIRI_PRECOMPILED_LIBRARIES") if cross_build_p
592
859
 
593
860
  $libs = $libs.shellsplit.tap do |libs|
594
861
  [libxml2_recipe, libxslt_recipe].each do |recipe|
595
862
  libname = recipe.name[/\Alib(.+)\z/, 1]
596
863
  File.join(recipe.path, "bin", "#{libname}-config").tap do |config|
597
864
  # call config scripts explicit with 'sh' for compat with Windows
598
- $CPPFLAGS = `sh #{config} --cflags`.strip << ' ' << $CPPFLAGS
599
- `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|
600
867
  case arg
601
868
  when /\A-L(.+)\z/
602
869
  # Prioritize ports' directories
603
- if $1.start_with?(ROOT + '/')
604
- $LIBPATH = [$1] | $LIBPATH
870
+ $LIBPATH = if Regexp.last_match(1).start_with?(PACKAGE_ROOT_DIR + "/")
871
+ [Regexp.last_match(1)] | $LIBPATH
605
872
  else
606
- $LIBPATH = $LIBPATH | [$1]
873
+ $LIBPATH | [Regexp.last_match(1)]
607
874
  end
608
875
  when /\A-l./
609
876
  libs.unshift(arg)
610
877
  else
611
- $LDFLAGS << ' ' << arg.shellescape
878
+ $LDFLAGS << " " << arg.shellescape
612
879
  end
613
880
  end
614
881
  end
615
882
 
616
- # Defining a macro that expands to a C string; double quotes are significant.
617
- $CPPFLAGS << ' ' << "-DNOKOGIRI_#{recipe.name.upcase}_PATH=\"#{recipe.path}\"".inspect
618
- $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}\\\""])
619
885
 
620
886
  case libname
621
- when 'xml2'
887
+ when "xml2"
622
888
  # xslt-config --libs or pkg-config libxslt --libs does not include
623
889
  # -llzma, so we need to add it manually when linking statically.
624
- if static_p && have_lzma
890
+ if static_p && preserving_globals { local_have_library("lzma") }
625
891
  # Add it at the end; GH #988
626
- libs << '-llzma'
892
+ libs << "-llzma"
627
893
  end
628
- when 'xslt'
894
+ when "xslt"
629
895
  # xslt-config does not have a flag to emit options including
630
896
  # -lexslt, so add it manually.
631
- libs.unshift('-lexslt')
897
+ libs.unshift("-lexslt")
632
898
  end
633
899
  end
634
900
  end.shelljoin
@@ -636,54 +902,107 @@ EOM
636
902
  if static_p
637
903
  $libs = $libs.shellsplit.map do |arg|
638
904
  case arg
639
- when '-lxml2'
640
- File.join(libxml2_recipe.path, 'lib', lib_a(arg))
641
- when '-lxslt', '-lexslt'
642
- 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))
643
909
  else
644
910
  arg
645
911
  end
646
912
  end.shelljoin
647
913
  end
914
+
915
+ ensure_func("xmlParseDoc", "libxml/parser.h")
916
+ ensure_func("xsltParseStylesheetDoc", "libxslt/xslt.h")
917
+ ensure_func("exsltFuncRegister", "libexslt/exslt.h")
648
918
  end
649
919
 
650
- {
651
- "xml2" => ['xmlParseDoc', 'libxml/parser.h'],
652
- "xslt" => ['xsltParseStylesheetDoc', 'libxslt/xslt.h'],
653
- "exslt" => ['exsltFuncRegister', 'libexslt/exslt.h'],
654
- }.each do |lib, (func, header)|
655
- have_func(func, header) ||
656
- have_library(lib, func, header) ||
657
- have_library("lib#{lib}", func, header) or
658
- asplode("lib#{lib}")
659
- end
660
-
661
- have_func('xmlHasFeature') or abort "xmlHasFeature() is missing."
662
- have_func('xmlFirstElementChild')
663
- have_func('xmlRelaxNGSetParserStructuredErrors')
664
- have_func('xmlRelaxNGSetParserStructuredErrors')
665
- have_func('xmlRelaxNGSetValidStructuredErrors')
666
- have_func('xmlSchemaSetValidStructuredErrors')
667
- have_func('xmlSchemaSetParserStructuredErrors')
668
-
669
- if ENV['CPUPROFILE']
670
- unless find_library('profiler', 'ProfilerEnable', *LIB_DIRS)
671
- abort "google performance tools are not installed"
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
927
+
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
934
+
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")
949
+
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
963
+ end
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)"]
672
993
  end
673
994
  end
674
995
 
675
- create_makefile('nokogiri/nokogiri')
996
+ create_makefile("nokogiri/nokogiri")
676
997
 
677
- if enable_config('clean', true)
998
+ if config_clean?
678
999
  # Do not clean if run in a development work tree.
679
- File.open('Makefile', 'at') do |mk|
680
- mk.print <<EOF
681
- all: clean-ports
1000
+ File.open("Makefile", "at") do |mk|
1001
+ mk.print(<<~EOF)
682
1002
 
683
- clean-ports: $(DLLIB)
684
- -$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? 'enable' : 'disable'}-static
685
- EOF
1003
+ all: clean-ports
1004
+ clean-ports: $(DLLIB)
1005
+ \t-$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? "enable" : "disable"}-static
1006
+ EOF
686
1007
  end
687
1008
  end
688
-
689
- # :startdoc: