nokogiri 1.10.3 → 1.13.9

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

Potentially problematic release.


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

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