Skip to content

Commit b72cc22

Browse files
committed
[GR-16345] Only call our C preprocessor on files which require it.
PullRequest: truffleruby/871
2 parents 3b001bd + c2484a6 commit b72cc22

File tree

9 files changed

+144
-66
lines changed

9 files changed

+144
-66
lines changed

lib/cext/linker.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def self.compile_if_needed(files)
7676
files.map do |file|
7777
if file.end_with?('.c')
7878
objfile = "#{File.dirname(file)}/#{File.basename(file, '.*')}.#{RbConfig::CONFIG['OBJEXT']}"
79-
compile = RbConfig::CONFIG['COMPILE_C'].gsub('$<', file).gsub('$@', objfile)
79+
compile = RbConfig::CONFIG['TRUFFLE_RAW_COMPILE_C'].gsub('$<', file).gsub('$@', objfile)
8080
compile = compile.sub('$(INCFLAGS)', @incflags.join(' '))
8181
compile = compile.sub('$(COUTFLAG)', '')
8282
if system(compile)

lib/cext/preprocess.rb

Lines changed: 14 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,69 +6,23 @@
66
# GNU General Public License version 2, or
77
# GNU Lesser General Public License version 2.1.
88

9-
require_relative 'patches/json_patches'
10-
require_relative 'patches/nokogiri_patches'
11-
require_relative 'patches/pg_patches'
9+
require_relative '../truffle/truffle/cext_preprocessor.rb'
1210

13-
class Preprocessor
11+
if __FILE__ == $0
12+
require 'stringio'
1413

15-
PATCHED_FILES = {}
14+
file_name = ARGV.first
15+
original_content = File.read(file_name)
16+
output = Truffle::CExt::Preprocessor.patch(file_name, original_content, Dir.pwd)
1617

17-
def self.add_gem_patches(patch_hash, gem_patches)
18-
gem = gem_patches[:gem]
19-
patch_list = gem_patches[:patches]
20-
patch_list.each do |path_parts, patch|
21-
processed_patch = {}
22-
if path_parts.kind_of?(String)
23-
key = path_parts
24-
else
25-
key = path_parts.last
26-
processed_patch[:ext_dir] = path_parts.first if path_parts.size > 1
27-
end
28-
processed_patch[:patches] = patch
29-
processed_patch[:gem] = gem
30-
raise "Duplicate patch file #{key}." if patch_hash.include?(key)
31-
patch_hash[key] = processed_patch
32-
end
18+
if ENV['PREPROCESS_DEBUG'] && original_content != output
19+
patched_file_name = "#{File.dirname file_name}/.#{File.basename file_name, '.*'}.patched#{File.extname file_name}"
20+
File.write patched_file_name, output
21+
$stderr.print `git diff --no-index --color -- #{file_name} #{patched_file_name}`
22+
file_name = patched_file_name
3323
end
3424

35-
add_gem_patches(PATCHED_FILES, ::JsonPatches::PATCHES)
36-
add_gem_patches(PATCHED_FILES, ::NokogiriPatches::PATCHES)
37-
add_gem_patches(PATCHED_FILES, ::PgPatches::PATCHES)
38-
39-
def self.patch(file, contents, directory)
40-
if patched_file = PATCHED_FILES[File.basename(file)]
41-
matched = if patched_file[:ext_dir]
42-
directory.end_with?(File.join(patched_file[:gem], 'ext', patched_file[:ext_dir]))
43-
else
44-
regexp = /^#{Regexp.escape(patched_file[:gem])}\b/
45-
directory.split('/').last(3).any? { |part| part =~ regexp } || file.split('/').last(2).any? { |part| part =~ regexp }
46-
end
47-
if matched
48-
patched_file[:patches].each do |patch|
49-
contents = contents.gsub(patch[:match], patch[:replacement].rstrip)
50-
end
51-
end
52-
end
53-
contents
54-
end
55-
56-
if __FILE__ == $0
57-
require 'stringio'
58-
59-
file_name = ARGV.first
60-
original_content = File.read(file_name)
61-
output = patch(file_name, original_content, Dir.pwd)
62-
63-
if ENV['PREPROCESS_DEBUG'] && original_content != output
64-
patched_file_name = "#{File.dirname file_name}/.#{File.basename file_name, '.*'}.patched#{File.extname file_name}"
65-
File.write patched_file_name, output
66-
$stderr.print `git diff --no-index --color -- #{file_name} #{patched_file_name}`
67-
file_name = patched_file_name
68-
end
69-
70-
expanded_path = File.expand_path(file_name)
71-
$stdout.puts "#line 1 \"#{expanded_path}\""
72-
$stdout.puts output
73-
end
25+
expanded_path = File.expand_path(file_name)
26+
$stdout.puts "#line 1 \"#{expanded_path}\""
27+
$stdout.puts output
7428
end

lib/truffle/rbconfig-for-mkmf.rb

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# clang, opt and llvm-link versions.
1111

1212
require 'rbconfig'
13+
require_relative 'truffle/cext_preprocessor.rb'
1314

1415
search_paths = {}
1516
if Truffle::Platform.darwin?
@@ -129,12 +130,36 @@
129130
# directory are include in preference to others on the include path,
130131
# and is required because we are actually piping the file into the
131132
# compiler which disables this standard behaviour of the C preprocessor.
132-
mkconfig['COMPILE_C'] = "#{preprocess_ruby} #{cext_dir}/preprocess.rb $< | $(CC) -I$(<D) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG) -xc - -o $@ && #{opt} #{opt_passes} $@ -o $@"
133-
mkconfig['COMPILE_CXX'] = "#{preprocess_ruby} #{cext_dir}/preprocess.rb $< | $(CXX) -I$(<D) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG) -xc++ - -o $@ && #{opt} #{opt_passes} $@ -o $@"
133+
begin
134+
with_conditional_preprocessing = proc do |command1, command2|
135+
Truffle::CExt::Preprocessor.makefile_matcher(command1, command2)
136+
end
137+
138+
for_file = proc do |compiler, flags, opt_command|
139+
"#{compiler} #{flags} $< && #{opt_command}"
140+
end
141+
142+
for_pipe = proc do |compiler, flags, opt_command|
143+
"#{preprocess_ruby} #{cext_dir}/preprocess.rb $< | #{compiler} -I$(<D) #{flags} - -o $@ && #{opt_command}"
144+
end
145+
146+
c_flags = '$(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG) -xc'
147+
cxx_flags = '$(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG) -xc++'
148+
opt_command = "#{opt} #{opt_passes} $@ -o $@"
149+
150+
mkconfig['TRUFFLE_RAW_COMPILE_C'] = for_pipe.call('$(CC)', c_flags, opt_command)
151+
mkconfig['COMPILE_C'] = with_conditional_preprocessing.call(
152+
for_pipe.call('$(CC)', c_flags, opt_command),
153+
for_file.call('$(CC)', c_flags, opt_command))
154+
155+
mkconfig['COMPILE_CXX'] = with_conditional_preprocessing.call(
156+
for_pipe.call('$(CXX)', cxx_flags, opt_command),
157+
for_file.call('$(CXX)', cxx_flags, opt_command))
158+
end
134159

135160
# From mkmf.rb: "$(CC) #{OUTFLAG}#{CONFTEST}#{$EXEEXT} $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
136161
mkconfig['TRY_LINK'] = "#{cc} -o conftest $(INCFLAGS) $(CPPFLAGS) #{base_cflags} #{link_o_files} $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
137162

138-
%w[COMPILE_C COMPILE_CXX TRY_LINK].each do |key|
163+
%w[COMPILE_C COMPILE_CXX TRY_LINK TRUFFLE_RAW_COMPILE_C].each do |key|
139164
expanded[key] = mkconfig[key].gsub(/\$\((\w+)\)/) { expanded.fetch($1) { $& } }
140165
end
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. This
2+
# code is released under a tri EPL/GPL/LGPL license. You can use it,
3+
# redistribute it and/or modify it under the terms of the:
4+
#
5+
# Eclipse Public License version 1.0, or
6+
# GNU General Public License version 2, or
7+
# GNU Lesser General Public License version 2.1.
8+
9+
require_relative 'patches/json_patches'
10+
require_relative 'patches/nokogiri_patches'
11+
require_relative 'patches/pg_patches'
12+
module Truffle
13+
module CExt
14+
class Preprocessor
15+
16+
PATCHED_FILES = {}
17+
18+
def self.add_gem_patches(patch_hash, gem_patches)
19+
gem = gem_patches[:gem]
20+
patch_list = gem_patches[:patches]
21+
patch_list.each do |path_parts, patch|
22+
processed_patch = {}
23+
if path_parts.kind_of?(String)
24+
key = path_parts
25+
else
26+
key = path_parts.last
27+
processed_patch[:ext_dir] = path_parts.first if path_parts.size > 1
28+
end
29+
processed_patch[:patches] = patch
30+
processed_patch[:gem] = gem
31+
raise "Duplicate patch file #{key}." if patch_hash.include?(key)
32+
patch_hash[key] = processed_patch
33+
end
34+
end
35+
36+
add_gem_patches(PATCHED_FILES, ::JsonPatches::PATCHES)
37+
add_gem_patches(PATCHED_FILES, ::NokogiriPatches::PATCHES)
38+
add_gem_patches(PATCHED_FILES, ::PgPatches::PATCHES)
39+
40+
def self.makefile_matcher(command1, command2)
41+
file_list = Hash.new { |h,k| h[k] = [] }
42+
PATCHED_FILES.each_pair do |file, patch|
43+
dir = if patch[:ext_dir]
44+
File.join(patch[:gem], 'ext', patch[:ext_dir])
45+
else
46+
"/#{patch[:gem]}"
47+
end
48+
file_list[dir] << file
49+
end
50+
51+
make_function = <<-EOF
52+
$(if\\
53+
$(or\\
54+
EOF
55+
file_list.each_pair do |dir, files|
56+
if !files.empty?
57+
make_function += <<-EOF
58+
$(and\\
59+
$(findstring #{dir}, $(realpath $(<))),\\
60+
$(or\\
61+
EOF
62+
files.each do |file|
63+
make_function += <<-EOF
64+
$(findstring #{file}, $(<)),\\
65+
EOF
66+
end
67+
make_function += <<-EOF
68+
)\\
69+
),\\
70+
EOF
71+
end
72+
end
73+
make_function += <<-EOF
74+
),\\
75+
#{command1},\\
76+
#{command2}\\
77+
)
78+
EOF
79+
80+
end
81+
82+
def self.patch(file, contents, directory)
83+
if patched_file = PATCHED_FILES[File.basename(file)]
84+
matched = if patched_file[:ext_dir]
85+
directory.end_with?(File.join(patched_file[:gem], 'ext', patched_file[:ext_dir]))
86+
else
87+
regexp = /^#{Regexp.escape(patched_file[:gem])}\b/
88+
directory.split('/').last(3).any? { |part| part =~ regexp } || file.split('/').last(2).any? { |part| part =~ regexp }
89+
end
90+
if matched
91+
patched_file[:patches].each do |patch|
92+
contents = contents.gsub(patch[:match], patch[:replacement].rstrip)
93+
end
94+
end
95+
end
96+
contents
97+
end
98+
end
99+
end
100+
end

mx.truffleruby/suite.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,6 @@
399399
"file:lib/truffle",
400400
],
401401
"lib/cext/": [
402-
"file:lib/cext/patches",
403402
"file:lib/cext/*.rb",
404403
"dependency:org.truffleruby.cext/src/main/c/truffleposix/<lib:truffleposix>",
405404
"dependency:org.truffleruby.cext/src/main/c/sulongmock/sulongmock.o",

test/truffle/cexts/test-preprocess.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
require_relative '../../../lib/cext/preprocess'
1010

1111
def test_patch(file, directory, input, expected)
12-
got = Preprocessor.patch(file, input, directory)
12+
got = Truffle::CExt::Preprocessor.patch(file, input, directory)
1313
abort "expected\n#{expected.inspect}\ngot\n#{got.inspect}" unless got == expected
1414
end
1515

0 commit comments

Comments
 (0)