Skip to content

Commit ba9fa34

Browse files
committed
[GR-17457] Improve building of nokogiri by reducing applied patches.
PullRequest: truffleruby/3298
2 parents 5c7903e + ca4bdb1 commit ba9fa34

File tree

6 files changed

+39
-62
lines changed

6 files changed

+39
-62
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Compatibility:
1717
* Fix `Marshal.dump` to raise an error when an object has singleton methods (@bjfish).
1818
* `Exception#full_message` now defaults the order to `:top` like CRuby 3+ (@eregon).
1919
* Fix `Process.wait2` to return `nil` when the `WNOHANG` flag is given and the child process is still running (@bjfish).
20+
* Disable most `nokogiri` C extension patches when system libraries are not being used (#2693, @aardvark179).
2021

2122
Performance:
2223

lib/cext/ABI_check.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1
1+
2

lib/mri/mkmf.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
for_pipe = proc do |compiler, flags|
3434
language_flag = '$(CXX)' == compiler ? '-xc++' : '-xc'
35-
"#{RbConfig.ruby} #{cext_dir}/preprocess.rb $< | #{compiler} -I$(<D) #{flags} #{language_flag} -"
35+
"#{RbConfig.ruby} #{cext_dir}/preprocess.rb $< #{flags} | #{compiler} -I$(<D) #{flags} #{language_flag} -"
3636
end
3737

3838
c_flags = '$(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c'

lib/truffle/truffle/cext_preprocessor.rb

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,18 @@ def self.patch(file, contents, directory)
9696
# preprocessor macro which _must_ end with a newline and
9797
# so requires that we preserve the trailing whitespace.
9898
patched_file[:patches].each do |patch|
99-
replacement = patch[:replacement].rstrip
100-
last_line = replacement.lines.last || replacement # .lines returns an empty Array if String#empty?
101-
last_line = last_line.lstrip
102-
contents = contents.gsub(patch[:match],
103-
if last_line && last_line.start_with?('#')
104-
patch[:replacement]
105-
else
106-
patch[:replacement].rstrip
107-
end)
99+
predicate = patch[:predicate] || -> { true }
100+
if predicate.call
101+
replacement = patch[:replacement].rstrip
102+
last_line = replacement.lines.last || replacement # .lines returns an empty Array if String#empty?
103+
last_line = last_line.lstrip
104+
contents = contents.gsub(patch[:match],
105+
if last_line && last_line.start_with?('#')
106+
patch[:replacement]
107+
else
108+
patch[:replacement].rstrip
109+
end)
110+
end
108111
end
109112
end
110113
end

lib/truffle/truffle/patches/nokogiri_patches.rb

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,8 @@ class NokogiriPatches
2323
xmlDocPtr doc = (xmlDocPtr)c;
2424
EOF
2525

26-
def self.patch_for_system_libraries(replacement)
27-
<<-EOF
28-
#ifdef NOKOGIRI_PACKAGED_LIBRARIES
29-
\\&
30-
#else
31-
#{replacement}
32-
#endif
33-
EOF
26+
def self.using_system_libraries?
27+
!ARGV.include?('-DNOKOGIRI_PACKAGED_LIBRARIES')
3428
end
3529

3630
PATCHES = {
@@ -41,14 +35,16 @@ def self.patch_for_system_libraries(replacement)
4135
# is called with. This works on MRI but causes an error in
4236
# TruffleRuby.
4337
match: 'static VALUE to_array(VALUE self, VALUE rb_node)',
44-
replacement: patch_for_system_libraries('static VALUE to_array(VALUE self)')
38+
replacement: 'static VALUE to_array(VALUE self)',
39+
predicate: -> { using_system_libraries? }
4540
},
4641
],
4742
'xslt_stylesheet.c' => [
4843
{ # It is not currently possible to pass var args from native
4944
# functions to sulong, so we work round the issue here.
5045
match: 'va_list args;',
51-
replacement: patch_for_system_libraries('va_list args; rb_str_cat2(ctx, "Generic error"); return;')
46+
replacement: 'va_list args; rb_str_cat2(ctx, "Generic error"); return;',
47+
predicate: -> { using_system_libraries? }
5248
}
5349
],
5450
'xml_document.c' => [
@@ -61,31 +57,37 @@ def self.patch_for_system_libraries(replacement)
6157
{ # It is not currently possible to pass var args from native
6258
# functions to sulong, so we work round the issue here.
6359
match: /va_list args;[^}]*id_warning, 1, ruby_message\);/,
64-
replacement: patch_for_system_libraries('rb_funcall(doc, id_warning, 1, NOKOGIRI_STR_NEW2("Warning."));')
60+
replacement: 'rb_funcall(doc, id_warning, 1, NOKOGIRI_STR_NEW2("Warning."));',
61+
predicate: -> { using_system_libraries? }
6562
},
6663
{ # It is not currently possible to pass var args from native
6764
# functions to sulong, so we work round the issue here.
6865
match: /va_list args;[^}]*id_error, 1, ruby_message\);/,
69-
replacement: patch_for_system_libraries('rb_funcall(doc, id_error, 1, NOKOGIRI_STR_NEW2("Warning."));')
66+
replacement: 'rb_funcall(doc, id_error, 1, NOKOGIRI_STR_NEW2("Warning."));',
67+
predicate: -> { using_system_libraries? }
7068
}
7169
],
7270
'xml_xpath_context.c' => [
7371
{ # It is not currently possible to pass var args from native
7472
# functions to sulong, so we work round the issue here.
7573
match: 'va_list args;',
76-
replacement: patch_for_system_libraries('va_list args; rb_raise(rb_eRuntimeError, "%s", "Exception:"); return;')
74+
replacement: 'va_list args; rb_raise(rb_eRuntimeError, "%s", "Exception:"); return;',
75+
predicate: -> { using_system_libraries? }
7776
},
7877
{
7978
match: 'VALUE thing = Qnil;',
80-
replacement: patch_for_system_libraries("VALUE thing = Qnil;\nVALUE errors = rb_ary_new();")
79+
replacement: "VALUE thing = Qnil;\nVALUE errors = rb_ary_new();",
80+
predicate: -> { using_system_libraries? }
8181
},
8282
{
8383
match: 'xmlSetStructuredErrorFunc(NULL, Nokogiri_error_raise);',
84-
replacement: patch_for_system_libraries('xmlSetStructuredErrorFunc(errors, Nokogiri_error_array_pusher);')
84+
replacement: 'xmlSetStructuredErrorFunc(errors, Nokogiri_error_array_pusher);',
85+
predicate: -> { using_system_libraries? }
8586
},
8687
{
8788
match: 'if(xpath == NULL)',
88-
replacement: patch_for_system_libraries("if (RARRAY_LEN(errors) > 0) { rb_exc_raise(rb_ary_entry(errors, 0)); }\nif(xpath == NULL)")
89+
replacement: "if (RARRAY_LEN(errors) > 0) { rb_exc_raise(rb_ary_entry(errors, 0)); }\nif(xpath == NULL)",
90+
predicate: -> { using_system_libraries? }
8991
},
9092
],
9193
}

test/truffle/cexts/test_preprocess.rb

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,46 +14,17 @@ def test_patch(file, directory, input, expected)
1414
end
1515

1616
original = <<-EOF
17-
static void warning_func(void * ctx, const char *msg, ...)
17+
static int dealloc_node_i(xmlNodePtr key, xmlNodePtr node, xmlDocPtr doc)
1818
{
19-
VALUE self = NOKOGIRI_SAX_SELF(ctx);
20-
VALUE doc = rb_iv_get(self, "@document");
21-
char * message;
22-
VALUE ruby_message;
23-
24-
va_list args;
25-
va_start(args, msg);
26-
vasprintf(&message, msg, args);
27-
va_end(args);
28-
29-
ruby_message = NOKOGIRI_STR_NEW2(message);
30-
vasprintf_free(message);
31-
rb_funcall(doc, id_warning, 1, ruby_message);
3219
}
3320
EOF
3421

3522
modified = <<-EOF
36-
static void warning_func(void * ctx, const char *msg, ...)
23+
static int dealloc_node_i(st_data_t a, st_data_t b, st_data_t c, int errorState)
3724
{
38-
VALUE self = NOKOGIRI_SAX_SELF(ctx);
39-
VALUE doc = rb_iv_get(self, "@document");
40-
char * message;
41-
VALUE ruby_message;
42-
43-
#ifdef NOKOGIRI_PACKAGED_LIBRARIES
44-
va_list args;
45-
va_start(args, msg);
46-
vasprintf(&message, msg, args);
47-
va_end(args);
48-
49-
ruby_message = NOKOGIRI_STR_NEW2(message);
50-
vasprintf_free(message);
51-
rb_funcall(doc, id_warning, 1, ruby_message);
52-
#else
53-
rb_funcall(doc, id_warning, 1, NOKOGIRI_STR_NEW2("Warning."));
54-
#endif
55-
56-
}
25+
xmlNodePtr key = (xmlNodePtr)a;
26+
xmlNodePtr node = (xmlNodePtr)b;
27+
xmlDocPtr doc = (xmlDocPtr)c;}
5728
EOF
5829

5930
json_original = <<-EOF
@@ -68,7 +39,7 @@ def test_patch(file, directory, input, expected)
6839
# endif
6940
EOF
7041

71-
test_patch 'xml_sax_parser.c', 'ext/nokogiri', original, modified
42+
test_patch 'xml_document.c', 'ext/nokogiri', original, modified
7243
# Should not patch other files or other gems
7344
test_patch 'other_file.c', 'ext/nokogiri', original, original
7445
test_patch 'xml_sax_parser.c', 'ext/other_gem', original, original

0 commit comments

Comments
 (0)