re2 2.15.0.rc1-x86_64-linux-musl

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,332 @@
1
+ # frozen_string_literal: true
2
+
3
+ # re2 (https://github.com/mudge/re2)
4
+ # Ruby bindings to RE2, a "fast, safe, thread-friendly alternative to
5
+ # backtracking regular expression engines like those used in PCRE, Perl, and
6
+ # Python".
7
+ #
8
+ # Copyright (c) 2010, Paul Mucur (https://mudge.name)
9
+ # Released under the BSD Licence, please see LICENSE.txt
10
+
11
+ require 'mkmf'
12
+ require_relative 'recipes'
13
+
14
+ module RE2
15
+ class Extconf
16
+ def configure
17
+ configure_cross_compiler
18
+
19
+ if config_system_libraries?
20
+ build_with_system_libraries
21
+ else
22
+ build_with_vendored_libraries
23
+ end
24
+
25
+ build_extension
26
+
27
+ create_makefile("re2")
28
+ end
29
+
30
+ def print_help
31
+ print(<<~TEXT)
32
+ USAGE: ruby #{$0} [options]
33
+
34
+ Flags that are always valid:
35
+
36
+ --enable-system-libraries
37
+ Use system libraries instead of building and using the packaged libraries.
38
+
39
+ --disable-system-libraries
40
+ Use the packaged libraries, and ignore the system libraries. This is the default.
41
+
42
+
43
+ Flags only used when using system libraries:
44
+
45
+ Related to re2 library:
46
+
47
+ --with-re2-dir=DIRECTORY
48
+ Look for re2 headers and library in DIRECTORY.
49
+
50
+
51
+ Flags only used when building and using the packaged libraries:
52
+
53
+ --enable-cross-build
54
+ Enable cross-build mode. (You probably do not want to set this manually.)
55
+
56
+
57
+ Environment variables used:
58
+
59
+ CC
60
+ Use this path to invoke the compiler instead of `RbConfig::CONFIG['CC']`
61
+
62
+ CPPFLAGS
63
+ If this string is accepted by the C preprocessor, add it to the flags passed to the C preprocessor
64
+
65
+ CFLAGS
66
+ If this string is accepted by the compiler, add it to the flags passed to the compiler
67
+
68
+ LDFLAGS
69
+ If this string is accepted by the linker, add it to the flags passed to the linker
70
+
71
+ LIBS
72
+ Add this string to the flags passed to the linker
73
+ TEXT
74
+ end
75
+
76
+ private
77
+
78
+ def configure_cross_compiler
79
+ RbConfig::CONFIG["CC"] = RbConfig::MAKEFILE_CONFIG["CC"] = ENV["CC"] if ENV["CC"]
80
+ RbConfig::CONFIG["CXX"] = RbConfig::MAKEFILE_CONFIG["CXX"] = ENV["CXX"] if ENV["CXX"]
81
+ end
82
+
83
+ def build_with_system_libraries
84
+ header_dirs = [
85
+ "/usr/local/include",
86
+ "/opt/homebrew/include",
87
+ "/usr/include"
88
+ ]
89
+
90
+ lib_dirs = [
91
+ "/usr/local/lib",
92
+ "/opt/homebrew/lib",
93
+ "/usr/lib"
94
+ ]
95
+
96
+ dir_config("re2", header_dirs, lib_dirs)
97
+
98
+ unless have_library("re2")
99
+ abort "You must have re2 installed and specified with --with-re2-dir, please see https://github.com/google/re2/wiki/Install"
100
+ end
101
+ end
102
+
103
+ def build_with_vendored_libraries
104
+ message "Building re2 using packaged libraries.\n"
105
+
106
+ abseil_recipe, re2_recipe = load_recipes
107
+
108
+ process_recipe(abseil_recipe) do |recipe|
109
+ recipe.configure_options << '-DABSL_PROPAGATE_CXX_STD=ON'
110
+ # Workaround for https://github.com/abseil/abseil-cpp/issues/1510
111
+ recipe.configure_options << '-DCMAKE_CXX_FLAGS=-DABSL_FORCE_WAITER_MODE=4' if MiniPortile.windows?
112
+ end
113
+
114
+ process_recipe(re2_recipe) do |recipe|
115
+ recipe.configure_options += [
116
+ # Specify Abseil's path so RE2 will prefer that over any system Abseil
117
+ "-DCMAKE_PREFIX_PATH=#{abseil_recipe.path}",
118
+ '-DCMAKE_CXX_FLAGS=-DNDEBUG'
119
+ ]
120
+ end
121
+
122
+ pc_file = File.join(re2_recipe.lib_path, 'pkgconfig', 're2.pc')
123
+ pkg_config_paths = [
124
+ File.join(abseil_recipe.lib_path, 'pkgconfig'),
125
+ File.join(re2_recipe.lib_path, 'pkgconfig')
126
+ ]
127
+
128
+ static_pkg_config(pc_file, pkg_config_paths)
129
+ end
130
+
131
+ def build_extension
132
+ # Enable optional warnings but disable deprecated register warning for Ruby 2.6 support
133
+ $CFLAGS << " -Wall -Wextra -funroll-loops"
134
+ $CXXFLAGS << " -Wall -Wextra -funroll-loops"
135
+ $CPPFLAGS << " -Wno-register"
136
+
137
+ # Pass -x c++ to force gcc to compile the test program
138
+ # as C++ (as it will end in .c by default).
139
+ compile_options = +"-x c++"
140
+
141
+ have_library("stdc++")
142
+ have_header("stdint.h")
143
+ have_func("rb_gc_mark_movable") # introduced in Ruby 2.7
144
+
145
+ minimal_program = <<~SRC
146
+ #include <re2/re2.h>
147
+ int main() { return 0; }
148
+ SRC
149
+
150
+ re2_requires_version_flag = checking_for("re2 that requires explicit C++ version flag") do
151
+ !try_compile(minimal_program, compile_options)
152
+ end
153
+
154
+ if re2_requires_version_flag
155
+ # Recent versions of re2 depend directly on abseil, which requires a
156
+ # compiler with C++14 support (see
157
+ # https://github.com/abseil/abseil-cpp/issues/1127 and
158
+ # https://github.com/abseil/abseil-cpp/issues/1431). However, the
159
+ # `std=c++14` flag doesn't appear to suffice; we need at least
160
+ # `std=c++17`.
161
+ abort "Cannot compile re2 with your compiler: recent versions require C++14 support." unless %w[c++20 c++17 c++11 c++0x].any? do |std|
162
+ checking_for("re2 that compiles with #{std} standard") do
163
+ if try_compile(minimal_program, compile_options + " -std=#{std}")
164
+ compile_options << " -std=#{std}"
165
+ $CPPFLAGS << " -std=#{std}"
166
+
167
+ true
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ # Determine which version of re2 the user has installed.
174
+ # Revision d9f8806c004d added an `endpos` argument to the
175
+ # generic Match() function.
176
+ #
177
+ # To test for this, try to compile a simple program that uses
178
+ # the newer form of Match() and set a flag if it is successful.
179
+ checking_for("RE2::Match() with endpos argument") do
180
+ test_re2_match_signature = <<~SRC
181
+ #include <re2/re2.h>
182
+
183
+ int main() {
184
+ RE2 pattern("test");
185
+ re2::StringPiece *match;
186
+ pattern.Match("test", 0, 0, RE2::UNANCHORED, match, 0);
187
+
188
+ return 0;
189
+ }
190
+ SRC
191
+
192
+ if try_compile(test_re2_match_signature, compile_options)
193
+ $defs.push("-DHAVE_ENDPOS_ARGUMENT")
194
+ end
195
+ end
196
+
197
+ checking_for("RE2::Set::Match() with error information") do
198
+ test_re2_set_match_signature = <<~SRC
199
+ #include <vector>
200
+ #include <re2/re2.h>
201
+ #include <re2/set.h>
202
+
203
+ int main() {
204
+ RE2::Set s(RE2::DefaultOptions, RE2::UNANCHORED);
205
+ s.Add("foo", NULL);
206
+ s.Compile();
207
+
208
+ std::vector<int> v;
209
+ RE2::Set::ErrorInfo ei;
210
+ s.Match("foo", &v, &ei);
211
+
212
+ return 0;
213
+ }
214
+ SRC
215
+
216
+ if try_compile(test_re2_set_match_signature, compile_options)
217
+ $defs.push("-DHAVE_ERROR_INFO_ARGUMENT")
218
+ end
219
+ end
220
+ end
221
+
222
+ def static_pkg_config(pc_file, pkg_config_paths)
223
+ ENV["PKG_CONFIG_PATH"] = [*pkg_config_paths, ENV["PKG_CONFIG_PATH"]].compact.join(File::PATH_SEPARATOR)
224
+
225
+ static_library_paths = minimal_pkg_config(pc_file, '--libs-only-L', '--static')
226
+ .shellsplit
227
+ .map { |flag| flag.delete_prefix('-L') }
228
+
229
+ # Replace all -l flags that can be found in one of the static library
230
+ # paths with the absolute path instead.
231
+ minimal_pkg_config(pc_file, '--libs-only-l', '--static')
232
+ .shellsplit
233
+ .each do |flag|
234
+ lib = "lib#{flag.delete_prefix('-l')}.#{$LIBEXT}"
235
+
236
+ if (static_lib_path = static_library_paths.find { |path| File.exist?(File.join(path, lib)) })
237
+ $libs << ' ' << File.join(static_lib_path, lib).shellescape
238
+ else
239
+ $libs << ' ' << flag.shellescape
240
+ end
241
+ end
242
+
243
+ append_ldflags(minimal_pkg_config(pc_file, '--libs-only-other', '--static'))
244
+
245
+ incflags = minimal_pkg_config(pc_file, '--cflags-only-I')
246
+ $INCFLAGS = [incflags, $INCFLAGS].join(" ").strip
247
+
248
+ cflags = minimal_pkg_config(pc_file, '--cflags-only-other')
249
+ $CFLAGS = [$CFLAGS, cflags].join(" ").strip
250
+ $CXXFLAGS = [$CXXFLAGS, cflags].join(" ").strip
251
+ end
252
+
253
+ def process_recipe(recipe)
254
+ cross_build_p = config_cross_build?
255
+ message "Cross build is #{cross_build_p ? "enabled" : "disabled"}.\n"
256
+
257
+ recipe.host = target_host
258
+ # Ensure x64-mingw-ucrt and x64-mingw32 use different library paths since the host
259
+ # is the same (x86_64-w64-mingw32).
260
+ recipe.target = File.join(recipe.target, target_arch) if cross_build_p
261
+
262
+ yield recipe
263
+
264
+ checkpoint = "#{recipe.target}/#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
265
+ name = recipe.name
266
+ version = recipe.version
267
+
268
+ if File.exist?(checkpoint)
269
+ message("Building re2 with a packaged version of #{name}-#{version}.\n")
270
+ else
271
+ message(<<~EOM)
272
+ ---------- IMPORTANT NOTICE ----------
273
+ Building re2 with a packaged version of #{name}-#{version}.
274
+ Configuration options: #{recipe.configure_options.shelljoin}
275
+ EOM
276
+
277
+ # Use a temporary base directory to reduce filename lengths since
278
+ # Windows can hit a limit of 250 characters (CMAKE_OBJECT_PATH_MAX).
279
+ Dir.mktmpdir { |dir| Dir.chdir(dir) { recipe.cook } }
280
+
281
+ FileUtils.touch(checkpoint)
282
+ end
283
+ end
284
+
285
+ # See MiniPortile2's minimal_pkg_config:
286
+ # https://github.com/flavorjones/mini_portile/blob/52fb0bc41c89a10f1ac7b5abcf0157e059194374/lib/mini_portile2/mini_portile.rb#L760-L783
287
+ # and Ruby's pkg_config:
288
+ # https://github.com/ruby/ruby/blob/c505bb0ca0fd61c7ae931d26451f11122a2644e9/lib/mkmf.rb#L1916-L2004
289
+ def minimal_pkg_config(pc_file, *options)
290
+ if ($PKGCONFIG ||=
291
+ (pkgconfig = MakeMakefile.with_config("pkg-config") {MakeMakefile.config_string("PKG_CONFIG") || "pkg-config"}) &&
292
+ MakeMakefile.find_executable0(pkgconfig) && pkgconfig)
293
+ pkgconfig = $PKGCONFIG
294
+ else
295
+ raise RuntimeError, "pkg-config is not found"
296
+ end
297
+
298
+ response = xpopen([pkgconfig, *options, pc_file], err: %i[child out], &:read)
299
+ raise RuntimeError, response unless $?.success?
300
+
301
+ response.strip
302
+ end
303
+
304
+ def config_system_libraries?
305
+ enable_config("system-libraries", ENV.key?('RE2_USE_SYSTEM_LIBRARIES'))
306
+ end
307
+
308
+ def config_cross_build?
309
+ enable_config("cross-build")
310
+ end
311
+
312
+ # We use 'host' to set compiler prefix for cross-compiling. Prefer host_alias over host. And
313
+ # prefer i686 (what external dev tools use) to i386 (what ruby's configure.ac emits).
314
+ def target_host
315
+ host = RbConfig::CONFIG["host_alias"].empty? ? RbConfig::CONFIG["host"] : RbConfig::CONFIG["host_alias"]
316
+ host.gsub(/i386/, "i686")
317
+ end
318
+
319
+ def target_arch
320
+ RbConfig::CONFIG['arch']
321
+ end
322
+ end
323
+ end
324
+
325
+ extconf = RE2::Extconf.new
326
+
327
+ if arg_config('--help')
328
+ extconf.print_help
329
+ exit!(true)
330
+ end
331
+
332
+ extconf.configure