nokogiri 1.6.0 → 1.13.2

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