nokogiri 1.18.0.rc1-x86_64-linux-gnu

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +38 -0
  3. data/LICENSE-DEPENDENCIES.md +2224 -0
  4. data/LICENSE.md +9 -0
  5. data/README.md +293 -0
  6. data/bin/nokogiri +131 -0
  7. data/dependencies.yml +42 -0
  8. data/ext/nokogiri/depend +38 -0
  9. data/ext/nokogiri/extconf.rb +1173 -0
  10. data/ext/nokogiri/gumbo.c +610 -0
  11. data/ext/nokogiri/html4_document.c +171 -0
  12. data/ext/nokogiri/html4_element_description.c +299 -0
  13. data/ext/nokogiri/html4_entity_lookup.c +37 -0
  14. data/ext/nokogiri/html4_sax_parser.c +40 -0
  15. data/ext/nokogiri/html4_sax_parser_context.c +98 -0
  16. data/ext/nokogiri/html4_sax_push_parser.c +96 -0
  17. data/ext/nokogiri/include/libexslt/exslt.h +108 -0
  18. data/ext/nokogiri/include/libexslt/exsltconfig.h +70 -0
  19. data/ext/nokogiri/include/libexslt/exsltexports.h +63 -0
  20. data/ext/nokogiri/include/libxml2/libxml/HTMLparser.h +336 -0
  21. data/ext/nokogiri/include/libxml2/libxml/HTMLtree.h +147 -0
  22. data/ext/nokogiri/include/libxml2/libxml/SAX.h +202 -0
  23. data/ext/nokogiri/include/libxml2/libxml/SAX2.h +171 -0
  24. data/ext/nokogiri/include/libxml2/libxml/c14n.h +115 -0
  25. data/ext/nokogiri/include/libxml2/libxml/catalog.h +182 -0
  26. data/ext/nokogiri/include/libxml2/libxml/chvalid.h +230 -0
  27. data/ext/nokogiri/include/libxml2/libxml/debugXML.h +217 -0
  28. data/ext/nokogiri/include/libxml2/libxml/dict.h +82 -0
  29. data/ext/nokogiri/include/libxml2/libxml/encoding.h +244 -0
  30. data/ext/nokogiri/include/libxml2/libxml/entities.h +166 -0
  31. data/ext/nokogiri/include/libxml2/libxml/globals.h +41 -0
  32. data/ext/nokogiri/include/libxml2/libxml/hash.h +251 -0
  33. data/ext/nokogiri/include/libxml2/libxml/list.h +137 -0
  34. data/ext/nokogiri/include/libxml2/libxml/nanoftp.h +186 -0
  35. data/ext/nokogiri/include/libxml2/libxml/nanohttp.h +98 -0
  36. data/ext/nokogiri/include/libxml2/libxml/parser.h +1390 -0
  37. data/ext/nokogiri/include/libxml2/libxml/parserInternals.h +671 -0
  38. data/ext/nokogiri/include/libxml2/libxml/pattern.h +106 -0
  39. data/ext/nokogiri/include/libxml2/libxml/relaxng.h +219 -0
  40. data/ext/nokogiri/include/libxml2/libxml/schemasInternals.h +959 -0
  41. data/ext/nokogiri/include/libxml2/libxml/schematron.h +143 -0
  42. data/ext/nokogiri/include/libxml2/libxml/threads.h +87 -0
  43. data/ext/nokogiri/include/libxml2/libxml/tree.h +1382 -0
  44. data/ext/nokogiri/include/libxml2/libxml/uri.h +106 -0
  45. data/ext/nokogiri/include/libxml2/libxml/valid.h +477 -0
  46. data/ext/nokogiri/include/libxml2/libxml/xinclude.h +136 -0
  47. data/ext/nokogiri/include/libxml2/libxml/xlink.h +189 -0
  48. data/ext/nokogiri/include/libxml2/libxml/xmlIO.h +438 -0
  49. data/ext/nokogiri/include/libxml2/libxml/xmlautomata.h +146 -0
  50. data/ext/nokogiri/include/libxml2/libxml/xmlerror.h +962 -0
  51. data/ext/nokogiri/include/libxml2/libxml/xmlexports.h +146 -0
  52. data/ext/nokogiri/include/libxml2/libxml/xmlmemory.h +188 -0
  53. data/ext/nokogiri/include/libxml2/libxml/xmlmodule.h +57 -0
  54. data/ext/nokogiri/include/libxml2/libxml/xmlreader.h +436 -0
  55. data/ext/nokogiri/include/libxml2/libxml/xmlregexp.h +215 -0
  56. data/ext/nokogiri/include/libxml2/libxml/xmlsave.h +102 -0
  57. data/ext/nokogiri/include/libxml2/libxml/xmlschemas.h +249 -0
  58. data/ext/nokogiri/include/libxml2/libxml/xmlschemastypes.h +152 -0
  59. data/ext/nokogiri/include/libxml2/libxml/xmlstring.h +140 -0
  60. data/ext/nokogiri/include/libxml2/libxml/xmlunicode.h +366 -0
  61. data/ext/nokogiri/include/libxml2/libxml/xmlversion.h +347 -0
  62. data/ext/nokogiri/include/libxml2/libxml/xmlwriter.h +489 -0
  63. data/ext/nokogiri/include/libxml2/libxml/xpath.h +579 -0
  64. data/ext/nokogiri/include/libxml2/libxml/xpathInternals.h +633 -0
  65. data/ext/nokogiri/include/libxml2/libxml/xpointer.h +138 -0
  66. data/ext/nokogiri/include/libxslt/attributes.h +39 -0
  67. data/ext/nokogiri/include/libxslt/documents.h +93 -0
  68. data/ext/nokogiri/include/libxslt/extensions.h +262 -0
  69. data/ext/nokogiri/include/libxslt/extra.h +72 -0
  70. data/ext/nokogiri/include/libxslt/functions.h +78 -0
  71. data/ext/nokogiri/include/libxslt/imports.h +75 -0
  72. data/ext/nokogiri/include/libxslt/keys.h +53 -0
  73. data/ext/nokogiri/include/libxslt/namespaces.h +68 -0
  74. data/ext/nokogiri/include/libxslt/numbersInternals.h +73 -0
  75. data/ext/nokogiri/include/libxslt/pattern.h +84 -0
  76. data/ext/nokogiri/include/libxslt/preproc.h +43 -0
  77. data/ext/nokogiri/include/libxslt/security.h +104 -0
  78. data/ext/nokogiri/include/libxslt/templates.h +77 -0
  79. data/ext/nokogiri/include/libxslt/transform.h +207 -0
  80. data/ext/nokogiri/include/libxslt/variables.h +118 -0
  81. data/ext/nokogiri/include/libxslt/xslt.h +110 -0
  82. data/ext/nokogiri/include/libxslt/xsltInternals.h +1995 -0
  83. data/ext/nokogiri/include/libxslt/xsltconfig.h +146 -0
  84. data/ext/nokogiri/include/libxslt/xsltexports.h +64 -0
  85. data/ext/nokogiri/include/libxslt/xsltlocale.h +44 -0
  86. data/ext/nokogiri/include/libxslt/xsltutils.h +343 -0
  87. data/ext/nokogiri/libxml2_polyfill.c +114 -0
  88. data/ext/nokogiri/nokogiri.c +294 -0
  89. data/ext/nokogiri/nokogiri.h +238 -0
  90. data/ext/nokogiri/test_global_handlers.c +40 -0
  91. data/ext/nokogiri/xml_attr.c +103 -0
  92. data/ext/nokogiri/xml_attribute_decl.c +70 -0
  93. data/ext/nokogiri/xml_cdata.c +62 -0
  94. data/ext/nokogiri/xml_comment.c +57 -0
  95. data/ext/nokogiri/xml_document.c +784 -0
  96. data/ext/nokogiri/xml_document_fragment.c +29 -0
  97. data/ext/nokogiri/xml_dtd.c +208 -0
  98. data/ext/nokogiri/xml_element_content.c +131 -0
  99. data/ext/nokogiri/xml_element_decl.c +69 -0
  100. data/ext/nokogiri/xml_encoding_handler.c +112 -0
  101. data/ext/nokogiri/xml_entity_decl.c +112 -0
  102. data/ext/nokogiri/xml_entity_reference.c +50 -0
  103. data/ext/nokogiri/xml_namespace.c +181 -0
  104. data/ext/nokogiri/xml_node.c +2459 -0
  105. data/ext/nokogiri/xml_node_set.c +518 -0
  106. data/ext/nokogiri/xml_processing_instruction.c +54 -0
  107. data/ext/nokogiri/xml_reader.c +777 -0
  108. data/ext/nokogiri/xml_relax_ng.c +149 -0
  109. data/ext/nokogiri/xml_sax_parser.c +403 -0
  110. data/ext/nokogiri/xml_sax_parser_context.c +390 -0
  111. data/ext/nokogiri/xml_sax_push_parser.c +206 -0
  112. data/ext/nokogiri/xml_schema.c +226 -0
  113. data/ext/nokogiri/xml_syntax_error.c +93 -0
  114. data/ext/nokogiri/xml_text.c +59 -0
  115. data/ext/nokogiri/xml_xpath_context.c +502 -0
  116. data/ext/nokogiri/xslt_stylesheet.c +421 -0
  117. data/gumbo-parser/CHANGES.md +63 -0
  118. data/gumbo-parser/Makefile +129 -0
  119. data/gumbo-parser/THANKS +27 -0
  120. data/lib/nokogiri/3.1/nokogiri.so +0 -0
  121. data/lib/nokogiri/3.2/nokogiri.so +0 -0
  122. data/lib/nokogiri/3.3/nokogiri.so +0 -0
  123. data/lib/nokogiri/3.4/nokogiri.so +0 -0
  124. data/lib/nokogiri/class_resolver.rb +67 -0
  125. data/lib/nokogiri/css/node.rb +58 -0
  126. data/lib/nokogiri/css/parser.rb +772 -0
  127. data/lib/nokogiri/css/parser.y +277 -0
  128. data/lib/nokogiri/css/parser_extras.rb +36 -0
  129. data/lib/nokogiri/css/selector_cache.rb +38 -0
  130. data/lib/nokogiri/css/syntax_error.rb +9 -0
  131. data/lib/nokogiri/css/tokenizer.rb +155 -0
  132. data/lib/nokogiri/css/tokenizer.rex +57 -0
  133. data/lib/nokogiri/css/xpath_visitor.rb +375 -0
  134. data/lib/nokogiri/css.rb +132 -0
  135. data/lib/nokogiri/decorators/slop.rb +42 -0
  136. data/lib/nokogiri/encoding_handler.rb +57 -0
  137. data/lib/nokogiri/extension.rb +32 -0
  138. data/lib/nokogiri/gumbo.rb +15 -0
  139. data/lib/nokogiri/html.rb +48 -0
  140. data/lib/nokogiri/html4/builder.rb +37 -0
  141. data/lib/nokogiri/html4/document.rb +235 -0
  142. data/lib/nokogiri/html4/document_fragment.rb +166 -0
  143. data/lib/nokogiri/html4/element_description.rb +25 -0
  144. data/lib/nokogiri/html4/element_description_defaults.rb +2040 -0
  145. data/lib/nokogiri/html4/encoding_reader.rb +121 -0
  146. data/lib/nokogiri/html4/entity_lookup.rb +15 -0
  147. data/lib/nokogiri/html4/sax/parser.rb +48 -0
  148. data/lib/nokogiri/html4/sax/parser_context.rb +15 -0
  149. data/lib/nokogiri/html4/sax/push_parser.rb +37 -0
  150. data/lib/nokogiri/html4.rb +42 -0
  151. data/lib/nokogiri/html5/builder.rb +40 -0
  152. data/lib/nokogiri/html5/document.rb +199 -0
  153. data/lib/nokogiri/html5/document_fragment.rb +200 -0
  154. data/lib/nokogiri/html5/node.rb +103 -0
  155. data/lib/nokogiri/html5.rb +368 -0
  156. data/lib/nokogiri/jruby/dependencies.rb +3 -0
  157. data/lib/nokogiri/jruby/nokogiri_jars.rb +43 -0
  158. data/lib/nokogiri/syntax_error.rb +6 -0
  159. data/lib/nokogiri/version/constant.rb +6 -0
  160. data/lib/nokogiri/version/info.rb +224 -0
  161. data/lib/nokogiri/version.rb +4 -0
  162. data/lib/nokogiri/xml/attr.rb +66 -0
  163. data/lib/nokogiri/xml/attribute_decl.rb +22 -0
  164. data/lib/nokogiri/xml/builder.rb +494 -0
  165. data/lib/nokogiri/xml/cdata.rb +13 -0
  166. data/lib/nokogiri/xml/character_data.rb +9 -0
  167. data/lib/nokogiri/xml/document.rb +514 -0
  168. data/lib/nokogiri/xml/document_fragment.rb +276 -0
  169. data/lib/nokogiri/xml/dtd.rb +34 -0
  170. data/lib/nokogiri/xml/element_content.rb +46 -0
  171. data/lib/nokogiri/xml/element_decl.rb +17 -0
  172. data/lib/nokogiri/xml/entity_decl.rb +23 -0
  173. data/lib/nokogiri/xml/entity_reference.rb +20 -0
  174. data/lib/nokogiri/xml/namespace.rb +57 -0
  175. data/lib/nokogiri/xml/node/save_options.rb +76 -0
  176. data/lib/nokogiri/xml/node.rb +1650 -0
  177. data/lib/nokogiri/xml/node_set.rb +449 -0
  178. data/lib/nokogiri/xml/notation.rb +19 -0
  179. data/lib/nokogiri/xml/parse_options.rb +213 -0
  180. data/lib/nokogiri/xml/pp/character_data.rb +21 -0
  181. data/lib/nokogiri/xml/pp/node.rb +73 -0
  182. data/lib/nokogiri/xml/pp.rb +4 -0
  183. data/lib/nokogiri/xml/processing_instruction.rb +11 -0
  184. data/lib/nokogiri/xml/reader.rb +139 -0
  185. data/lib/nokogiri/xml/relax_ng.rb +75 -0
  186. data/lib/nokogiri/xml/sax/document.rb +258 -0
  187. data/lib/nokogiri/xml/sax/parser.rb +199 -0
  188. data/lib/nokogiri/xml/sax/parser_context.rb +129 -0
  189. data/lib/nokogiri/xml/sax/push_parser.rb +64 -0
  190. data/lib/nokogiri/xml/sax.rb +54 -0
  191. data/lib/nokogiri/xml/schema.rb +140 -0
  192. data/lib/nokogiri/xml/searchable.rb +297 -0
  193. data/lib/nokogiri/xml/syntax_error.rb +94 -0
  194. data/lib/nokogiri/xml/text.rb +11 -0
  195. data/lib/nokogiri/xml/xpath/syntax_error.rb +13 -0
  196. data/lib/nokogiri/xml/xpath.rb +21 -0
  197. data/lib/nokogiri/xml/xpath_context.rb +49 -0
  198. data/lib/nokogiri/xml.rb +65 -0
  199. data/lib/nokogiri/xslt/stylesheet.rb +49 -0
  200. data/lib/nokogiri/xslt.rb +129 -0
  201. data/lib/nokogiri.rb +128 -0
  202. data/lib/xsd/xmlparser/nokogiri.rb +105 -0
  203. metadata +324 -0
@@ -0,0 +1,1173 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Style/GlobalVars
4
+
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.9.2"
16
+ RECOMMENDED_LIBXML_VERSION = "2.12.0"
17
+
18
+ REQUIRED_MINI_PORTILE_VERSION = "~> 2.8.2" # 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 libxml2:
61
+
62
+ --with-xml2-dir=DIRECTORY
63
+ Look for xml2 headers and library in DIRECTORY.
64
+
65
+ --with-xml2-lib=DIRECTORY
66
+ Look for xml2 library in DIRECTORY.
67
+
68
+ --with-xml2-include=DIRECTORY
69
+ Look for xml2 headers in DIRECTORY.
70
+
71
+ --with-xml2-source-dir=DIRECTORY
72
+ (dev only) Build libxml2 from the source code in DIRECTORY
73
+
74
+ --disable-xml2-legacy
75
+ Do not build libxml2 with zlib, liblzma, or HTTP support. This will become the default
76
+ in a future version of Nokogiri.
77
+
78
+
79
+ Related to libxslt:
80
+
81
+ --with-xslt-dir=DIRECTORY
82
+ Look for xslt headers and library in DIRECTORY.
83
+
84
+ --with-xslt-lib=DIRECTORY
85
+ Look for xslt library in DIRECTORY.
86
+
87
+ --with-xslt-include=DIRECTORY
88
+ Look for xslt headers in DIRECTORY.
89
+
90
+ --with-xslt-source-dir=DIRECTORY
91
+ (dev only) Build libxslt from the source code in DIRECTORY
92
+
93
+
94
+ Related to libexslt:
95
+
96
+ --with-exslt-dir=DIRECTORY
97
+ Look for exslt headers and library in DIRECTORY.
98
+
99
+ --with-exslt-lib=DIRECTORY
100
+ Look for exslt library in DIRECTORY.
101
+
102
+ --with-exslt-include=DIRECTORY
103
+ Look for exslt headers in DIRECTORY.
104
+
105
+
106
+ Related to iconv:
107
+
108
+ --with-iconv-dir=DIRECTORY
109
+ Look for iconv headers and library in DIRECTORY.
110
+
111
+ --with-iconv-lib=DIRECTORY
112
+ Look for iconv library in DIRECTORY.
113
+
114
+ --with-iconv-include=DIRECTORY
115
+ Look for iconv headers in DIRECTORY.
116
+
117
+
118
+ Related to zlib (ignored if `--disable-xml2-legacy` is used):
119
+
120
+ --with-zlib-dir=DIRECTORY
121
+ Look for zlib headers and library in DIRECTORY.
122
+
123
+ --with-zlib-lib=DIRECTORY
124
+ Look for zlib library in DIRECTORY.
125
+
126
+ --with-zlib-include=DIRECTORY
127
+ Look for zlib headers in DIRECTORY.
128
+
129
+
130
+ Flags only used when building and using the packaged libraries:
131
+
132
+ --disable-static
133
+ Do not statically link packaged libraries, instead use shared libraries.
134
+
135
+ --enable-cross-build
136
+ Enable cross-build mode. (You probably do not want to set this manually.)
137
+
138
+
139
+ Environment variables used:
140
+
141
+ NOKOGIRI_USE_SYSTEM_LIBRARIES
142
+ Equivalent to `--enable-system-libraries` when set, even if nil or blank.
143
+
144
+ AR
145
+ Use this path to invoke the library archiver instead of `RbConfig::CONFIG['AR']`
146
+
147
+ CC
148
+ Use this path to invoke the compiler instead of `RbConfig::CONFIG['CC']`
149
+
150
+ CPPFLAGS
151
+ If this string is accepted by the C preprocessor, add it to the flags passed to the C preprocessor
152
+
153
+ CFLAGS
154
+ If this string is accepted by the compiler, add it to the flags passed to the compiler
155
+
156
+ LD
157
+ Use this path to invoke the linker instead of `RbConfig::CONFIG['LD']`
158
+
159
+ LDFLAGS
160
+ If this string is accepted by the linker, add it to the flags passed to the linker
161
+
162
+ LIBS
163
+ Add this string to the flags passed to the linker
164
+ HELP
165
+
166
+ #
167
+ # utility functions
168
+ #
169
+ def config_clean?
170
+ enable_config("clean", true)
171
+ end
172
+
173
+ def config_static?
174
+ default_static = !truffle?
175
+ enable_config("static", default_static)
176
+ end
177
+
178
+ def config_cross_build?
179
+ enable_config("cross-build")
180
+ end
181
+
182
+ def config_system_libraries?
183
+ enable_config("system-libraries", ENV.key?("NOKOGIRI_USE_SYSTEM_LIBRARIES")) do |_, default|
184
+ arg_config("--use-system-libraries", default)
185
+ end
186
+ end
187
+
188
+ def config_with_xml2_legacy?
189
+ enable_config("xml2-legacy", true)
190
+ end
191
+
192
+ def windows?
193
+ RbConfig::CONFIG["target_os"].match?(/mingw|mswin/)
194
+ end
195
+
196
+ def solaris?
197
+ RbConfig::CONFIG["target_os"].include?("solaris")
198
+ end
199
+
200
+ def darwin?
201
+ RbConfig::CONFIG["target_os"].include?("darwin")
202
+ end
203
+
204
+ def openbsd?
205
+ RbConfig::CONFIG["target_os"].include?("openbsd")
206
+ end
207
+
208
+ def aix?
209
+ RbConfig::CONFIG["target_os"].include?("aix")
210
+ end
211
+
212
+ def unix?
213
+ !(windows? || solaris? || darwin?)
214
+ end
215
+
216
+ def nix?
217
+ ENV.key?("NIX_CC")
218
+ end
219
+
220
+ def truffle?
221
+ RUBY_ENGINE == "truffleruby"
222
+ end
223
+
224
+ def concat_flags(*args)
225
+ args.compact.join(" ")
226
+ end
227
+
228
+ def local_have_library(lib, func = nil, headers = nil)
229
+ have_library(lib, func, headers) || have_library("lib#{lib}", func, headers)
230
+ end
231
+
232
+ def zlib_source(version_string)
233
+ # As of 2022-12, I'm starting to see failed downloads often enough from zlib.net that I want to
234
+ # change the default to github.
235
+ if ENV["NOKOGIRI_USE_CANONICAL_ZLIB_SOURCE"]
236
+ "https://zlib.net/fossils/zlib-#{version_string}.tar.gz"
237
+ else
238
+ "https://github.com/madler/zlib/releases/download/v#{version_string}/zlib-#{version_string}.tar.gz"
239
+ end
240
+ end
241
+
242
+ def gnome_source
243
+ # As of 2022-02-20, some mirrors have expired SSL certificates. I'm able to retrieve from my home,
244
+ # but whatever host is resolved on the github actions workers see an expired cert.
245
+ #
246
+ # See https://github.com/sparklemotion/nokogiri/runs/5266206403?check_suite_focus=true
247
+ if ENV["NOKOGIRI_USE_CANONICAL_GNOME_SOURCE"]
248
+ "https://download.gnome.org"
249
+ else
250
+ "https://muug.ca/mirror/gnome" # old reliable
251
+ end
252
+ end
253
+
254
+ LOCAL_PACKAGE_RESPONSE = Object.new
255
+ def LOCAL_PACKAGE_RESPONSE.%(package)
256
+ package ? "yes: #{package}" : "no"
257
+ end
258
+
259
+ # wrapper around MakeMakefil#pkg_config and the PKGConfig gem
260
+ def try_package_configuration(pc)
261
+ unless ENV.key?("NOKOGIRI_TEST_PKG_CONFIG_GEM")
262
+ # try MakeMakefile#pkg_config, which uses the system utility `pkg-config`.
263
+ return if checking_for("#{pc} using `pkg_config`", LOCAL_PACKAGE_RESPONSE) do
264
+ pkg_config(pc)
265
+ end
266
+ end
267
+
268
+ # `pkg-config` probably isn't installed, which appears to be the case for lots of freebsd systems.
269
+ # let's fall back to the pkg-config gem, which knows how to parse .pc files, and wrap it with the
270
+ # same logic as MakeMakefile#pkg_config
271
+ begin
272
+ require "rubygems"
273
+ gem("pkg-config", REQUIRED_PKG_CONFIG_VERSION)
274
+ require "pkg-config"
275
+
276
+ checking_for("#{pc} using pkg-config gem version #{PKGConfig::VERSION}", LOCAL_PACKAGE_RESPONSE) do
277
+ if PKGConfig.have_package(pc)
278
+ cflags = PKGConfig.cflags(pc)
279
+ ldflags = PKGConfig.libs_only_L(pc)
280
+ libs = PKGConfig.libs_only_l(pc)
281
+
282
+ Logging.message("pkg-config gem found package configuration for %s\n", pc)
283
+ Logging.message("cflags: %s\nldflags: %s\nlibs: %s\n\n", cflags, ldflags, libs)
284
+
285
+ [cflags, ldflags, libs]
286
+ end
287
+ end
288
+ rescue LoadError
289
+ message("Please install either the `pkg-config` utility or the `pkg-config` rubygem.\n")
290
+ end
291
+ end
292
+
293
+ # set up mkmf to link against the library if we can find it
294
+ def have_package_configuration(opt: nil, pc: nil, lib:, func:, headers:)
295
+ if opt
296
+ dir_config(opt)
297
+ dir_config("opt")
298
+ end
299
+
300
+ # see if we have enough path info to do this without trying any harder
301
+ unless ENV.key?("NOKOGIRI_TEST_PKG_CONFIG")
302
+ return true if local_have_library(lib, func, headers)
303
+ end
304
+
305
+ try_package_configuration(pc) if pc
306
+
307
+ # verify that we can compile and link against the library
308
+ local_have_library(lib, func, headers)
309
+ end
310
+
311
+ def ensure_package_configuration(opt: nil, pc: nil, lib:, func:, headers:)
312
+ have_package_configuration(opt: opt, pc: pc, lib: lib, func: func, headers: headers) ||
313
+ abort_could_not_find_library(lib)
314
+ end
315
+
316
+ def ensure_func(func, headers = nil)
317
+ have_func(func, headers) || abort_could_not_find_library(func)
318
+ end
319
+
320
+ def preserving_globals
321
+ values = [$arg_config, $INCFLAGS, $CFLAGS, $CPPFLAGS, $LDFLAGS, $DLDFLAGS, $LIBPATH, $libs].map(&:dup)
322
+ yield
323
+ ensure
324
+ $arg_config, $INCFLAGS, $CFLAGS, $CPPFLAGS, $LDFLAGS, $DLDFLAGS, $LIBPATH, $libs = values
325
+ end
326
+
327
+ def abort_could_not_find_library(lib)
328
+ callers = caller(1..2).join("\n")
329
+ abort("-----\n#{callers}\n#{lib} is missing. Please locate mkmf.log to investigate how it is failing.\n-----")
330
+ end
331
+
332
+ def chdir_for_build(&block)
333
+ # When using rake-compiler-dock on Windows, the underlying Virtualbox shared
334
+ # folders don't support symlinks, but libiconv expects it for a build on
335
+ # Linux. We work around this limitation by using the temp dir for cooking.
336
+ build_dir = /mingw|mswin|cygwin/.match?(ENV["RCD_HOST_RUBY_PLATFORM"].to_s) ? "/tmp" : "."
337
+ Dir.chdir(build_dir, &block)
338
+ end
339
+
340
+ def sh_export_path(path)
341
+ # because libxslt 1.1.29 configure.in uses AC_PATH_TOOL which treats ":"
342
+ # as a $PATH separator, we need to convert windows paths from
343
+ #
344
+ # C:/path/to/foo
345
+ #
346
+ # to
347
+ #
348
+ # /C/path/to/foo
349
+ #
350
+ # which is sh-compatible, in order to find things properly during
351
+ # configuration
352
+ return path unless windows?
353
+
354
+ match = Regexp.new("^([A-Z]):(/.*)").match(path)
355
+ if match && match.length == 3
356
+ return File.join("/", match[1], match[2])
357
+ end
358
+
359
+ path
360
+ end
361
+
362
+ def libflag_to_filename(ldflag)
363
+ case ldflag
364
+ when /\A-l(.+)/
365
+ "lib#{Regexp.last_match(1)}.#{$LIBEXT}"
366
+ end
367
+ end
368
+
369
+ def have_libxml_headers?(version = nil)
370
+ source = if version.nil?
371
+ <<~SRC
372
+ #include <libxml/xmlversion.h>
373
+ SRC
374
+ else
375
+ version_int = format("%d%2.2d%2.2d", *version.split("."))
376
+ <<~SRC
377
+ #include <libxml/xmlversion.h>
378
+ #if LIBXML_VERSION < #{version_int}
379
+ # error libxml2 is older than #{version}
380
+ #endif
381
+ SRC
382
+ end
383
+
384
+ try_cpp(source)
385
+ end
386
+
387
+ def try_link_iconv(using = nil)
388
+ checking_for(using ? "iconv using #{using}" : "iconv") do
389
+ ["", "-liconv"].any? do |opt|
390
+ preserving_globals do
391
+ yield if block_given?
392
+
393
+ try_link(<<~SRC, opt)
394
+ #include <stdlib.h>
395
+ #include <iconv.h>
396
+ int main(void)
397
+ {
398
+ iconv_t cd = iconv_open("", "");
399
+ iconv(cd, NULL, NULL, NULL, NULL);
400
+ return EXIT_SUCCESS;
401
+ }
402
+ SRC
403
+ end
404
+ end
405
+ end
406
+ end
407
+
408
+ def iconv_configure_flags
409
+ # give --with-iconv-dir and --with-opt-dir first priority
410
+ ["iconv", "opt"].each do |target|
411
+ config = preserving_globals { dir_config(target) }
412
+ next unless config.any? && try_link_iconv("--with-#{target}-* flags") { dir_config(target) }
413
+
414
+ idirs, ldirs = config.map do |dirs|
415
+ Array(dirs).flat_map do |dir|
416
+ dir.split(File::PATH_SEPARATOR)
417
+ end if dirs
418
+ end
419
+
420
+ return [
421
+ "--with-iconv=yes",
422
+ *("CPPFLAGS=#{idirs.map { |dir| "-I" + dir }.join(" ")}" if idirs),
423
+ *("LDFLAGS=#{ldirs.map { |dir| "-L" + dir }.join(" ")}" if ldirs),
424
+ ]
425
+ end
426
+
427
+ if try_link_iconv
428
+ return ["--with-iconv=yes"]
429
+ end
430
+
431
+ config = preserving_globals { pkg_config("libiconv") }
432
+ if config && try_link_iconv("pkg-config libiconv") { pkg_config("libiconv") }
433
+ cflags, ldflags, libs = config
434
+
435
+ return [
436
+ "--with-iconv=yes",
437
+ "CPPFLAGS=#{cflags}",
438
+ "LDFLAGS=#{ldflags}",
439
+ "LIBS=#{libs}",
440
+ ]
441
+ end
442
+
443
+ abort_could_not_find_library("libiconv")
444
+ end
445
+
446
+ def process_recipe(name, version, static_p, cross_p, cacheable_p = true)
447
+ require "rubygems"
448
+ gem("mini_portile2", REQUIRED_MINI_PORTILE_VERSION) # gemspec is not respected at install time
449
+ require "mini_portile2"
450
+ message("Using mini_portile version #{MiniPortile::VERSION}\n")
451
+
452
+ unless ["libxml2", "libxslt"].include?(name)
453
+ OTHER_LIBRARY_VERSIONS[name] = version
454
+ end
455
+
456
+ MiniPortile.new(name, version).tap do |recipe|
457
+ def recipe.port_path
458
+ "#{@target}/#{RUBY_PLATFORM}/#{@name}/#{@version}"
459
+ end
460
+
461
+ # We use 'host' to set compiler prefix for cross-compiling. Prefer host_alias over host. And
462
+ # prefer i686 (what external dev tools use) to i386 (what ruby's configure.ac emits).
463
+ recipe.host = RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"]
464
+ recipe.host = recipe.host.gsub("i386", "i686")
465
+
466
+ recipe.target = File.join(PACKAGE_ROOT_DIR, "ports") if cacheable_p
467
+ recipe.configure_options << "--libdir=#{File.join(recipe.path, "lib")}"
468
+
469
+ yield recipe
470
+
471
+ env = Hash.new do |hash, key|
472
+ hash[key] = (ENV[key]).to_s
473
+ end
474
+
475
+ recipe.configure_options.flatten!
476
+
477
+ recipe.configure_options.delete_if do |option|
478
+ case option
479
+ when /\A(\w+)=(.*)\z/
480
+ env[Regexp.last_match(1)] = if env.key?(Regexp.last_match(1))
481
+ concat_flags(env[Regexp.last_match(1)], Regexp.last_match(2))
482
+ else
483
+ Regexp.last_match(2)
484
+ end
485
+ true
486
+ else
487
+ false
488
+ end
489
+ end
490
+
491
+ if static_p
492
+ recipe.configure_options += [
493
+ "--disable-shared",
494
+ "--enable-static",
495
+ ]
496
+ env["CFLAGS"] = concat_flags(env["CFLAGS"], "-fPIC")
497
+ else
498
+ recipe.configure_options += [
499
+ "--enable-shared",
500
+ "--disable-static",
501
+ ]
502
+ end
503
+
504
+ if cross_p
505
+ recipe.configure_options += [
506
+ "--target=#{recipe.host}",
507
+ "--host=#{recipe.host}",
508
+ ]
509
+ end
510
+
511
+ if RbConfig::CONFIG["target_cpu"] == "universal"
512
+ ["CFLAGS", "LDFLAGS"].each do |key|
513
+ unless env[key].include?("-arch")
514
+ env[key] = concat_flags(env[key], RbConfig::CONFIG["ARCH_FLAG"])
515
+ end
516
+ end
517
+ end
518
+
519
+ recipe.configure_options += env.map do |key, value|
520
+ "#{key}=#{value.strip}"
521
+ end
522
+
523
+ checkpoint = "#{recipe.target}/#{recipe.name}-#{recipe.version}-#{RUBY_PLATFORM}.installed"
524
+ if File.exist?(checkpoint) && !recipe.source_directory
525
+ message("Building Nokogiri with a packaged version of #{name}-#{version}.\n")
526
+ else
527
+ message(<<~EOM)
528
+ ---------- IMPORTANT NOTICE ----------
529
+ Building Nokogiri with a packaged version of #{name}-#{version}.
530
+ Configuration options: #{recipe.configure_options.shelljoin}
531
+ EOM
532
+
533
+ unless recipe.patch_files.empty?
534
+ message("The following patches are being applied:\n")
535
+
536
+ recipe.patch_files.each do |patch|
537
+ message(format(" - %s\n", File.basename(patch)))
538
+ end
539
+ end
540
+
541
+ message(<<~EOM) if name != "libgumbo"
542
+
543
+ The Nokogiri maintainers intend to provide timely security updates, but if
544
+ this is a concern for you and want to use your OS/distro system library
545
+ instead, then abort this installation process and install nokogiri as
546
+ instructed at:
547
+
548
+ https://nokogiri.org/tutorials/installing_nokogiri.html#installing-using-standard-system-libraries
549
+
550
+ EOM
551
+
552
+ message(<<~EOM) if name == "libxml2"
553
+ Note, however, that nokogiri cannot guarantee compatibility with every
554
+ version of libxml2 that may be provided by OS/package vendors.
555
+
556
+ EOM
557
+
558
+ chdir_for_build { recipe.cook }
559
+ FileUtils.touch(checkpoint)
560
+ end
561
+ recipe.activate
562
+ end
563
+ end
564
+
565
+ def copy_packaged_libraries_headers(to_path:, from_recipes:)
566
+ FileUtils.rm_rf(to_path, secure: true)
567
+ FileUtils.mkdir(to_path)
568
+ from_recipes.each do |recipe|
569
+ FileUtils.cp_r(Dir[File.join(recipe.path, "include/*")], to_path)
570
+ end
571
+ end
572
+
573
+ def do_help
574
+ print(NOKOGIRI_HELP_MESSAGE)
575
+ exit!(0)
576
+ end
577
+
578
+ def do_clean
579
+ root = Pathname(PACKAGE_ROOT_DIR)
580
+ pwd = Pathname(Dir.pwd)
581
+
582
+ # Skip if this is a development work tree
583
+ unless (root + ".git").exist?
584
+ message("Cleaning files only used during build.\n")
585
+
586
+ # (root + 'tmp') cannot be removed at this stage because
587
+ # nokogiri.so is yet to be copied to lib.
588
+
589
+ # clean the ports build directory
590
+ Pathname.glob(pwd.join("tmp", "*", "ports")) do |dir|
591
+ FileUtils.rm_rf(dir, verbose: true)
592
+ end
593
+
594
+ if config_static?
595
+ # ports installation can be safely removed if statically linked.
596
+ FileUtils.rm_rf(root + "ports", verbose: true)
597
+ else
598
+ FileUtils.rm_rf(root + "ports" + "archives", verbose: true)
599
+ end
600
+ end
601
+
602
+ exit!(0)
603
+ end
604
+
605
+ # In ruby 3.2, symbol resolution changed on Darwin, to introduce the `-bundle_loader` flag to
606
+ # resolve symbols against the ruby binary.
607
+ #
608
+ # This makes it challenging to build a single extension that works with both a ruby with
609
+ # `--enable-shared` and one with `--disable-shared. To work around that, we choose to add
610
+ # `-flat_namespace` to the link line (later in this file).
611
+ #
612
+ # The `-flat_namespace` line introduces its own behavior change, which is that (similar to on
613
+ # Linux), any symbols in the extension that are exported may now be resolved by shared libraries
614
+ # loaded by the Ruby process. Specifically, that means that libxml2 and libxslt, which are
615
+ # statically linked into the nokogiri bundle, will resolve (at runtime) to a system libxml2 loaded
616
+ # by Ruby on Darwin. And it appears that often Ruby on Darwin does indeed load the system libxml2,
617
+ # and that messes with our assumptions about whether we're running with a patched libxml2 or a
618
+ # vanilla libxml2.
619
+ #
620
+ # We choose to use `-load_hidden` in this case to prevent exporting those symbols from libxml2 and
621
+ # libxslt, which ensures that they will be resolved to the static libraries in the bundle. In other
622
+ # words, when we use `load_hidden`, what happens in the extension stays in the extension.
623
+ #
624
+ # See https://github.com/rake-compiler/rake-compiler-dock/issues/87 for more info.
625
+ #
626
+ # Anyway, this method is the logical bit to tell us when to turn on these workarounds.
627
+ def needs_darwin_linker_hack
628
+ config_cross_build? &&
629
+ darwin? &&
630
+ Gem::Requirement.new("~> 3.2").satisfied_by?(Gem::Version.new(RbConfig::CONFIG["ruby_version"].split("+").first))
631
+ end
632
+
633
+ #
634
+ # main
635
+ #
636
+ do_help if arg_config("--help")
637
+ do_clean if arg_config("--clean")
638
+
639
+ if openbsd? && !config_system_libraries?
640
+ unless %x(#{ENV["CC"] || "/usr/bin/cc"} -v 2>&1).include?("clang")
641
+ (ENV["CC"] ||= find_executable("egcc")) ||
642
+ abort("Please install gcc 4.9+ from ports using `pkg_add -v gcc`")
643
+ end
644
+ append_cppflags "-I/usr/local/include"
645
+ end
646
+
647
+ if ENV["AR"]
648
+ RbConfig::CONFIG["AR"] = RbConfig::MAKEFILE_CONFIG["AR"] = ENV["AR"]
649
+ end
650
+
651
+ if ENV["CC"]
652
+ RbConfig::CONFIG["CC"] = RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"]
653
+ end
654
+
655
+ if ENV["LD"]
656
+ RbConfig::CONFIG["LD"] = RbConfig::MAKEFILE_CONFIG["LD"] = ENV["LD"]
657
+ end
658
+
659
+ # use same toolchain for libxml and libxslt
660
+ ENV["AR"] = RbConfig::CONFIG["AR"]
661
+ ENV["CC"] = RbConfig::CONFIG["CC"]
662
+ ENV["LD"] = RbConfig::CONFIG["LD"]
663
+
664
+ if arg_config("--prevent-strip")
665
+ old_cflags = $CFLAGS.split.join(" ")
666
+ old_ldflags = $LDFLAGS.split.join(" ")
667
+ old_dldflags = $DLDFLAGS.split.join(" ")
668
+ $CFLAGS = $CFLAGS.split.reject { |flag| flag == "-s" }.join(" ")
669
+ $LDFLAGS = $LDFLAGS.split.reject { |flag| flag == "-s" }.join(" ")
670
+ $DLDFLAGS = $DLDFLAGS.split.reject { |flag| flag == "-s" }.join(" ")
671
+ puts "Prevent stripping by removing '-s' from $CFLAGS" if old_cflags != $CFLAGS
672
+ puts "Prevent stripping by removing '-s' from $LDFLAGS" if old_ldflags != $LDFLAGS
673
+ puts "Prevent stripping by removing '-s' from $DLDFLAGS" if old_dldflags != $DLDFLAGS
674
+ end
675
+
676
+ # adopt environment config
677
+ append_cflags(ENV["CFLAGS"]) unless ENV["CFLAGS"].nil?
678
+ append_cppflags(ENV["CPPFLAGS"]) unless ENV["CPPFLAGS"].nil?
679
+ append_ldflags(ENV["LDFLAGS"]) unless ENV["LDFLAGS"].nil?
680
+ $LIBS = concat_flags($LIBS, ENV["LIBS"])
681
+
682
+ # libgumbo uses C90/C99 features, see #2302
683
+ append_cflags(["-std=c99", "-Wno-declaration-after-statement"])
684
+
685
+ # gumbo html5 serialization is slower with O3, let's make sure we use O2
686
+ append_cflags("-O2")
687
+
688
+ # always include debugging information
689
+ append_cflags("-g")
690
+
691
+ # we use at least one inline function in the C extension
692
+ append_cflags("-Winline")
693
+
694
+ # good to have no matter what Ruby was compiled with
695
+ append_cflags("-Wmissing-noreturn")
696
+
697
+ # check integer loss of precision. this flag won't generally work until Ruby 3.4.
698
+ # see https://bugs.ruby-lang.org/issues/20507
699
+ append_cflags("-Wconversion")
700
+
701
+ # handle clang variations, see #1101
702
+ if darwin?
703
+ append_cflags("-Wno-error=unused-command-line-argument-hard-error-in-future")
704
+ append_cflags("-Wno-unknown-warning-option")
705
+ end
706
+
707
+ # these tend to be noisy, but on occasion useful during development
708
+ # append_cflags(["-Wcast-qual", "-Wwrite-strings"])
709
+
710
+ # Add SDK-specific include path for macOS and brew versions before v2.2.12 (2020-04-08) [#1851, #1801]
711
+ macos_mojave_sdk_include_path = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libxml2"
712
+ if config_system_libraries? && darwin? && Dir.exist?(macos_mojave_sdk_include_path) && !nix?
713
+ append_cppflags("-I#{macos_mojave_sdk_include_path}")
714
+ end
715
+
716
+ # Work around a character escaping bug in MSYS by passing an arbitrary double-quoted parameter to gcc.
717
+ # See https://sourceforge.net/p/mingw/bugs/2142
718
+ append_cppflags(' "-Idummypath"') if windows?
719
+
720
+ if config_system_libraries?
721
+ message "Building nokogiri using system libraries.\n"
722
+ if config_with_xml2_legacy?
723
+ ensure_package_configuration(
724
+ opt: "zlib",
725
+ pc: "zlib",
726
+ lib: "z",
727
+ headers: "zlib.h",
728
+ func: "gzdopen",
729
+ )
730
+ end
731
+ ensure_package_configuration(
732
+ opt: "xml2",
733
+ pc: "libxml-2.0",
734
+ lib: "xml2",
735
+ headers: "libxml/parser.h",
736
+ func: "xmlParseDoc",
737
+ )
738
+ ensure_package_configuration(
739
+ opt: "xslt",
740
+ pc: "libxslt",
741
+ lib: "xslt",
742
+ headers: "libxslt/xslt.h",
743
+ func: "xsltParseStylesheetDoc",
744
+ )
745
+ ensure_package_configuration(
746
+ opt: "exslt",
747
+ pc: "libexslt",
748
+ lib: "exslt",
749
+ headers: "libexslt/exslt.h",
750
+ func: "exsltFuncRegister",
751
+ )
752
+
753
+ have_libxml_headers?(REQUIRED_LIBXML_VERSION) ||
754
+ abort("ERROR: libxml2 version #{REQUIRED_LIBXML_VERSION} or later is required!")
755
+ have_libxml_headers?(RECOMMENDED_LIBXML_VERSION) ||
756
+ warn("WARNING: libxml2 version #{RECOMMENDED_LIBXML_VERSION} or later is highly recommended, but proceeding anyway.")
757
+
758
+ else
759
+ message "Building nokogiri using packaged libraries.\n"
760
+
761
+ static_p = config_static?
762
+ message "Static linking is #{static_p ? "enabled" : "disabled"}.\n"
763
+
764
+ cross_build_p = config_cross_build?
765
+ message "Cross build is #{cross_build_p ? "enabled" : "disabled"}.\n"
766
+
767
+ if needs_darwin_linker_hack
768
+ append_ldflags("-Wl,-flat_namespace")
769
+ end
770
+
771
+ require "yaml"
772
+ dependencies = YAML.load_file(File.join(PACKAGE_ROOT_DIR, "dependencies.yml"))
773
+
774
+ dir_config("zlib") if config_with_xml2_legacy?
775
+
776
+ if cross_build_p || windows?
777
+ if config_with_xml2_legacy?
778
+ zlib_recipe = process_recipe("zlib", dependencies["zlib"]["version"], static_p, cross_build_p) do |recipe|
779
+ recipe.files = [{
780
+ url: zlib_source(recipe.version),
781
+ sha256: dependencies["zlib"]["sha256"],
782
+ }]
783
+ if windows?
784
+ class << recipe
785
+ attr_accessor :cross_build_p
786
+
787
+ def configure
788
+ Dir.chdir(work_path) do
789
+ mk = File.read("win32/Makefile.gcc")
790
+ File.open("win32/Makefile.gcc", "wb") do |f|
791
+ f.puts "BINARY_PATH = #{path}/bin"
792
+ f.puts "LIBRARY_PATH = #{path}/lib"
793
+ f.puts "INCLUDE_PATH = #{path}/include"
794
+ mk.sub!(/^PREFIX\s*=\s*$/, "PREFIX = #{host}-") if cross_build_p
795
+ f.puts mk
796
+ end
797
+ end
798
+ end
799
+
800
+ def configured?
801
+ Dir.chdir(work_path) do
802
+ !!(File.read("win32/Makefile.gcc") =~ /^BINARY_PATH/)
803
+ end
804
+ end
805
+
806
+ def compile
807
+ execute("compile", "make -f win32/Makefile.gcc")
808
+ end
809
+
810
+ def install
811
+ execute("install", "make -f win32/Makefile.gcc install")
812
+ end
813
+ end
814
+ recipe.cross_build_p = cross_build_p
815
+ else
816
+ class << recipe
817
+ def configure
818
+ env = {}
819
+ env["CFLAGS"] = concat_flags(ENV["CFLAGS"], "-fPIC", "-g")
820
+ env["CHOST"] = host
821
+ execute("configure", ["./configure", "--static", configure_prefix], { env: env })
822
+ if darwin?
823
+ # needed as of zlib 1.2.13
824
+ Dir.chdir(work_path) do
825
+ makefile = File.read("Makefile").gsub(/^AR=.*$/, "AR=#{host}-libtool")
826
+ File.open("Makefile", "w") { |m| m.write(makefile) }
827
+ end
828
+ end
829
+ end
830
+ end
831
+ end
832
+ end
833
+ end
834
+
835
+ unless unix?
836
+ libiconv_recipe = process_recipe(
837
+ "libiconv",
838
+ dependencies["libiconv"]["version"],
839
+ static_p,
840
+ cross_build_p,
841
+ ) do |recipe|
842
+ recipe.files = [{
843
+ url: "https://ftp.gnu.org/pub/gnu/libiconv/#{recipe.name}-#{recipe.version}.tar.gz",
844
+ sha256: dependencies["libiconv"]["sha256"],
845
+ }]
846
+
847
+ # The libiconv configure script doesn't accept "arm64" host string but "aarch64"
848
+ recipe.host = recipe.host.gsub("arm64-apple-darwin", "aarch64-apple-darwin")
849
+
850
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-g")
851
+
852
+ recipe.configure_options += [
853
+ "--disable-dependency-tracking",
854
+ "CPPFLAGS=-Wall",
855
+ "CFLAGS=#{cflags}",
856
+ "CXXFLAGS=#{cflags}",
857
+ "LDFLAGS=",
858
+ ]
859
+ end
860
+ end
861
+ elsif darwin? && !have_header("iconv.h")
862
+ abort(<<~EOM.chomp)
863
+ -----
864
+ The file "iconv.h" is missing in your build environment,
865
+ which means you haven't installed Xcode Command Line Tools properly.
866
+
867
+ To install Command Line Tools, try running `xcode-select --install` on
868
+ terminal and follow the instructions. If it fails, open Xcode.app,
869
+ select from the menu "Xcode" - "Open Developer Tool" - "More Developer
870
+ Tools" to open the developer site, download the installer for your OS
871
+ version and run it.
872
+ -----
873
+ EOM
874
+ end
875
+
876
+ if zlib_recipe
877
+ append_cppflags("-I#{zlib_recipe.path}/include")
878
+ $LIBPATH = ["#{zlib_recipe.path}/lib"] | $LIBPATH
879
+ ensure_package_configuration(
880
+ opt: "zlib",
881
+ pc: "zlib",
882
+ lib: "z",
883
+ headers: "zlib.h",
884
+ func: "gzdopen",
885
+ )
886
+ end
887
+
888
+ if libiconv_recipe
889
+ append_cppflags("-I#{libiconv_recipe.path}/include")
890
+ $LIBPATH = ["#{libiconv_recipe.path}/lib"] | $LIBPATH
891
+ ensure_package_configuration(
892
+ opt: "iconv",
893
+ pc: "iconv",
894
+ lib: "iconv",
895
+ headers: "iconv.h",
896
+ func: "iconv_open",
897
+ )
898
+ end
899
+
900
+ libxml2_recipe = process_recipe("libxml2", dependencies["libxml2"]["version"], static_p, cross_build_p) do |recipe|
901
+ source_dir = arg_config("--with-xml2-source-dir")
902
+ if source_dir
903
+ recipe.source_directory = source_dir
904
+ else
905
+ minor_version = Gem::Version.new(recipe.version).segments.take(2).join(".")
906
+ recipe.files = [{
907
+ url: "#{gnome_source}/sources/libxml2/#{minor_version}/#{recipe.name}-#{recipe.version}.tar.xz",
908
+ sha256: dependencies["libxml2"]["sha256"],
909
+ }]
910
+ recipe.patch_files = Dir[File.join(PACKAGE_ROOT_DIR, "patches", "libxml2", "*.patch")].sort
911
+ end
912
+
913
+ cppflags = concat_flags(ENV["CPPFLAGS"])
914
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-g")
915
+
916
+ if cross_build_p
917
+ cppflags = concat_flags(cppflags, "-DNOKOGIRI_PRECOMPILED_LIBRARIES")
918
+ end
919
+
920
+ if config_with_xml2_legacy?
921
+ recipe.configure_options << "--with-legacy"
922
+ end
923
+
924
+ if zlib_recipe
925
+ recipe.configure_options << "--with-zlib=#{zlib_recipe.path}"
926
+ end
927
+
928
+ if libiconv_recipe
929
+ recipe.configure_options << "--with-iconv=#{libiconv_recipe.path}"
930
+ else
931
+ recipe.configure_options += iconv_configure_flags
932
+ end
933
+
934
+ if darwin? && !cross_build_p
935
+ recipe.configure_options << "RANLIB=/usr/bin/ranlib" unless ENV.key?("RANLIB")
936
+ recipe.configure_options << "AR=/usr/bin/ar" unless ENV.key?("AR")
937
+ end
938
+
939
+ if windows?
940
+ cflags = concat_flags(cflags, "-ULIBXML_STATIC", "-DIN_LIBXML")
941
+ end
942
+
943
+ recipe.configure_options << if source_dir
944
+ "--config-cache"
945
+ else
946
+ "--disable-dependency-tracking"
947
+ end
948
+
949
+ recipe.configure_options += [
950
+ "--without-python",
951
+ "--without-readline",
952
+ "--with-c14n",
953
+ "--with-debug",
954
+ "--with-threads",
955
+ "CPPFLAGS=#{cppflags}",
956
+ "CFLAGS=#{cflags}",
957
+ ]
958
+ end
959
+
960
+ libxslt_recipe = process_recipe("libxslt", dependencies["libxslt"]["version"], static_p, cross_build_p) do |recipe|
961
+ source_dir = arg_config("--with-xslt-source-dir")
962
+ if source_dir
963
+ recipe.source_directory = source_dir
964
+ else
965
+ minor_version = Gem::Version.new(recipe.version).segments.take(2).join(".")
966
+ recipe.files = [{
967
+ url: "#{gnome_source}/sources/libxslt/#{minor_version}/#{recipe.name}-#{recipe.version}.tar.xz",
968
+ sha256: dependencies["libxslt"]["sha256"],
969
+ }]
970
+ recipe.patch_files = Dir[File.join(PACKAGE_ROOT_DIR, "patches", "libxslt", "*.patch")].sort
971
+ end
972
+
973
+ cflags = concat_flags(ENV["CFLAGS"], "-O2", "-g")
974
+
975
+ if darwin? && !cross_build_p
976
+ recipe.configure_options << "RANLIB=/usr/bin/ranlib" unless ENV.key?("RANLIB")
977
+ recipe.configure_options << "AR=/usr/bin/ar" unless ENV.key?("AR")
978
+ end
979
+
980
+ if windows?
981
+ cflags = concat_flags(cflags, "-ULIBXSLT_STATIC", "-DIN_LIBXSLT")
982
+ cflags = concat_flags(cflags, "-ULIBEXSLT_STATIC", "-DIN_LIBEXSLT")
983
+ end
984
+
985
+ recipe.configure_options << if source_dir
986
+ "--config-cache"
987
+ else
988
+ "--disable-dependency-tracking"
989
+ end
990
+
991
+ recipe.configure_options += [
992
+ "--without-python",
993
+ "--without-crypto",
994
+ "--with-debug",
995
+ "--with-libxml-prefix=#{sh_export_path(libxml2_recipe.path)}",
996
+ "CFLAGS=#{cflags}",
997
+ ]
998
+ end
999
+
1000
+ append_cppflags("-DNOKOGIRI_PACKAGED_LIBRARIES")
1001
+ append_cppflags("-DNOKOGIRI_PRECOMPILED_LIBRARIES") if cross_build_p
1002
+
1003
+ $libs = $libs.shellsplit.tap do |libs|
1004
+ [libxml2_recipe, libxslt_recipe].each do |recipe|
1005
+ libname = recipe.name[/\Alib(.+)\z/, 1]
1006
+ config_basename = "#{libname}-config"
1007
+ File.join(recipe.path, "bin", config_basename).tap do |config|
1008
+ # call config scripts explicit with 'sh' for compat with Windows
1009
+ cflags = %x(sh #{config} --cflags).strip
1010
+ message("#{config_basename} cflags: #{cflags}\n")
1011
+ $CPPFLAGS = concat_flags(cflags, $CPPFLAGS) # prepend
1012
+
1013
+ %x(sh #{config} --libs).strip.shellsplit.each do |arg|
1014
+ case arg
1015
+ when /\A-L(.+)\z/
1016
+ # Prioritize ports' directories
1017
+ $LIBPATH = if Regexp.last_match(1).start_with?(PACKAGE_ROOT_DIR + "/")
1018
+ [Regexp.last_match(1)] | $LIBPATH
1019
+ else
1020
+ $LIBPATH | [Regexp.last_match(1)]
1021
+ end
1022
+ when /\A-l./
1023
+ libs.unshift(arg)
1024
+ else
1025
+ $LDFLAGS << " " << arg.shellescape
1026
+ end
1027
+ end
1028
+ end
1029
+
1030
+ patches_string = recipe.patch_files.map { |path| File.basename(path) }.join(" ")
1031
+ append_cppflags(%[-DNOKOGIRI_#{recipe.name.upcase}_PATCHES="\\"#{patches_string}\\""])
1032
+
1033
+ case libname
1034
+ when "xml2"
1035
+ # xslt-config --libs or pkg-config libxslt --libs does not include
1036
+ # -llzma, so we need to add it manually when linking statically.
1037
+ if static_p && preserving_globals { local_have_library("lzma") }
1038
+ # Add it at the end; GH #988
1039
+ libs << "-llzma"
1040
+ end
1041
+ when "xslt"
1042
+ # xslt-config does not have a flag to emit options including
1043
+ # -lexslt, so add it manually.
1044
+ libs.unshift("-lexslt")
1045
+ end
1046
+ end
1047
+ end.shelljoin
1048
+
1049
+ if static_p
1050
+ static_archive_ld_flag = needs_darwin_linker_hack ? ["-load_hidden"] : []
1051
+ $libs = $libs.shellsplit.map do |arg|
1052
+ case arg
1053
+ when "-lxml2"
1054
+ static_archive_ld_flag + [File.join(libxml2_recipe.path, "lib", libflag_to_filename(arg))]
1055
+ when "-lxslt", "-lexslt"
1056
+ static_archive_ld_flag + [File.join(libxslt_recipe.path, "lib", libflag_to_filename(arg))]
1057
+ else
1058
+ arg
1059
+ end
1060
+ end.flatten.shelljoin
1061
+ end
1062
+
1063
+ ensure_func("xmlParseDoc", "libxml/parser.h")
1064
+ ensure_func("xsltParseStylesheetDoc", "libxslt/xslt.h")
1065
+ ensure_func("exsltFuncRegister", "libexslt/exslt.h")
1066
+ end
1067
+
1068
+ if arg_config("--gumbo-dev")
1069
+ message("DEV MODE ENABLED: build libgumbo as packaged source")
1070
+ ext_dir = File.dirname(__FILE__)
1071
+ Dir.chdir(ext_dir) do
1072
+ $srcs = Dir["*.c", "../../gumbo-parser/src/*.c"]
1073
+ $hdrs = Dir["*.h", "../../gumbo-parser/src/*.h"]
1074
+ end
1075
+ $INCFLAGS << " -I$(srcdir)/../../gumbo-parser/src"
1076
+ $VPATH << "$(srcdir)/../../gumbo-parser/src"
1077
+ find_header("nokogiri_gumbo.h") || abort("nokogiri_gumbo.h not found")
1078
+ else
1079
+ libgumbo_recipe = process_recipe("libgumbo", "1.0.0-nokogiri", static_p, cross_build_p, false) do |recipe|
1080
+ recipe.configure_options = []
1081
+
1082
+ class << recipe
1083
+ def downloaded?
1084
+ true
1085
+ end
1086
+
1087
+ def extract
1088
+ target = File.join(tmp_path, "gumbo-parser")
1089
+ output("Copying gumbo-parser files into #{target}...")
1090
+ FileUtils.mkdir_p(target)
1091
+ FileUtils.cp(Dir.glob(File.join(PACKAGE_ROOT_DIR, "gumbo-parser/src/*")), target)
1092
+ end
1093
+
1094
+ def configured?
1095
+ true
1096
+ end
1097
+
1098
+ def install
1099
+ lib_dir = File.join(port_path, "lib")
1100
+ inc_dir = File.join(port_path, "include")
1101
+ FileUtils.mkdir_p([lib_dir, inc_dir])
1102
+ FileUtils.cp(File.join(work_path, "libgumbo.a"), lib_dir)
1103
+ FileUtils.cp(Dir.glob(File.join(work_path, "*.h")), inc_dir)
1104
+ end
1105
+
1106
+ def compile
1107
+ cflags = concat_flags(ENV["CFLAGS"], "-fPIC", "-O2", "-g")
1108
+
1109
+ env = { "CC" => gcc_cmd, "CFLAGS" => cflags }
1110
+ if config_cross_build?
1111
+ if host.include?("darwin")
1112
+ env["AR"] = "#{host}-libtool"
1113
+ env["ARFLAGS"] = "-o"
1114
+ else
1115
+ env["AR"] = "#{host}-ar"
1116
+ end
1117
+ env["RANLIB"] = "#{host}-ranlib"
1118
+ if windows?
1119
+ concat_flags(env["CFLAGS"], "-D_RUBY_UCRT")
1120
+ end
1121
+ end
1122
+
1123
+ execute("compile", make_cmd, { env: env })
1124
+ end
1125
+ end
1126
+ end
1127
+ append_cppflags("-I#{File.join(libgumbo_recipe.path, "include")}")
1128
+ $libs = $libs + " " + File.join(libgumbo_recipe.path, "lib", "libgumbo.a")
1129
+ $LIBPATH = $LIBPATH | [File.join(libgumbo_recipe.path, "lib")]
1130
+ ensure_func("gumbo_parse_with_options", "nokogiri_gumbo.h")
1131
+ end
1132
+
1133
+ have_func("xmlCtxtSetOptions") # introduced in libxml2 2.13.0
1134
+ have_func("xmlCtxtGetOptions") # introduced in libxml2 2.14.0
1135
+ have_func("xmlSwitchEncodingName") # introduced in libxml2 2.13.0
1136
+ have_func("rb_category_warning") # introduced in Ruby 3.0 but had trouble resolving this symbol in truffleruby
1137
+
1138
+ other_library_versions_string = OTHER_LIBRARY_VERSIONS.map { |k, v| [k, v].join(":") }.join(",")
1139
+ append_cppflags(%[-DNOKOGIRI_OTHER_LIBRARY_VERSIONS="\\"#{other_library_versions_string}\\""])
1140
+
1141
+ unless config_system_libraries?
1142
+ if cross_build_p
1143
+ # When precompiling native gems, copy packaged libraries' headers to ext/nokogiri/include
1144
+ # These are packaged up by the cross-compiling callback in the ExtensionTask
1145
+ copy_packaged_libraries_headers(
1146
+ to_path: File.join(PACKAGE_ROOT_DIR, "ext/nokogiri/include"),
1147
+ from_recipes: [libxml2_recipe, libxslt_recipe],
1148
+ )
1149
+ else
1150
+ # When compiling during installation, install packaged libraries' header files into ext/nokogiri/include
1151
+ copy_packaged_libraries_headers(
1152
+ to_path: "include",
1153
+ from_recipes: [libxml2_recipe, libxslt_recipe],
1154
+ )
1155
+ $INSTALLFILES << ["include/**/*.h", "$(rubylibdir)"]
1156
+ end
1157
+ end
1158
+
1159
+ create_makefile("nokogiri/nokogiri")
1160
+
1161
+ if config_clean?
1162
+ # Do not clean if run in a development work tree.
1163
+ File.open("Makefile", "at") do |mk|
1164
+ mk.print(<<~EOF)
1165
+
1166
+ all: clean-ports
1167
+ clean-ports: $(TARGET_SO)
1168
+ \t-$(Q)$(RUBY) $(srcdir)/extconf.rb --clean --#{static_p ? "enable" : "disable"}-static
1169
+ EOF
1170
+ end
1171
+ end
1172
+
1173
+ # rubocop:enable Style/GlobalVars