Skip to content

Commit c973751

Browse files
committed
Add new option --with-sanitize[=list,of,clang,sanitizers]
1 parent 2af8e67 commit c973751

File tree

2 files changed

+43
-15
lines changed

2 files changed

+43
-15
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ This may be needed if you deploy to a system where these libraries
5858
are located somewhere different than on your build system.
5959
This overrides any rpath calculated by default or by the options above.
6060

61+
* `--with-sanitize[=address,cfi,integer,memory,thread,undefined]` -
62+
Enable sanitizers for Clang / GCC. If no argument is given, try to enable
63+
all sanitizers or fail if none are available. If a command-separated list of
64+
specific sanitizers is given, configure will fail unless they all are available.
65+
Note that the some sanitizers may incur a performance penalty, and the Address
66+
Sanitizer may require a runtime library.
67+
6168
### Linux and other Unixes
6269

6370
You may need to install a package such as `libmysqlclient-dev` or `mysql-devel`;

ext/mysql2/extconf.rb

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -105,31 +105,52 @@ def asplode(lib)
105105
'-Wno-missing-field-initializers', # gperf generates bad code
106106
'-Wno-missing-variable-declarations', # missing symbols due to ruby native ext initialization
107107
'-Wno-padded', # mysql :(
108+
'-Wno-reserved-id-macro', # rubby :(
108109
'-Wno-sign-conversion', # gperf generates bad code
109110
'-Wno-static-in-inline', # gperf generates bad code
110111
'-Wno-switch-enum', # result.c -- enum_field_types (when not fully covered, e.g. mysql 5.6+)
111112
'-Wno-undef', # rubinius :(
113+
'-Wno-unreachable-code', # rubby :(
112114
'-Wno-used-but-marked-unused', # rubby :(
113115
]
114116

115-
if ENV['CI']
116-
wishlist += [
117-
'-Werror',
118-
'-fsanitize=address',
119-
'-fsanitize=cfi',
120-
'-fsanitize=integer',
121-
'-fsanitize=memory',
122-
'-fsanitize=thread',
123-
'-fsanitize=undefined',
124-
]
125-
end
126-
127117
usable_flags = wishlist.select do |flag|
128-
try_link('int main() {return 0;}', flag)
118+
try_link('int main() {return 0;}', "-Werror -Wunknown-warning-option #{flag}")
129119
end
130120

131121
$CFLAGS << ' ' << usable_flags.join(' ')
132122

123+
enabled_sanitizers = disabled_sanitizers = []
124+
# Specify a commna-separated list of sanitizers, or try them all by default
125+
sanitizers = with_config('sanitize')
126+
case sanitizers
127+
when true
128+
# Try them all, turn on whatever we can
129+
enabled_sanitizers = %w(address cfi integer memory thread undefined).select do |s|
130+
try_link('int main() {return 0;}', "-Werror -Wunknown-warning-option -fsanitize=#{s}")
131+
end
132+
when String
133+
# Figure out which sanitizers are supported
134+
enabled_sanitizers, disabled_sanitizers = sanitizers.split(',').partition do |s|
135+
try_link('int main() {return 0;}', "-Werror -Wunknown-warning-option -fsanitize=#{s}")
136+
end
137+
end
138+
139+
unless disabled_sanitizers.empty?
140+
abort "-----\nCould not enable requested sanitizers: #{disabled_sanitizers.join(',')}\n-----"
141+
end
142+
143+
unless enabled_sanitizers.empty?
144+
warn "-----\nEnabling sanitizers: #{enabled_sanitizers.join(',')}\n-----"
145+
enabled_sanitizers.each do |s|
146+
# address sanitizer requires runtime support
147+
if s == 'address' # rubocop:disable Style/IfUnlessModifier
148+
have_library('asan') || $LDFLAGS << ' -fsanitize=address'
149+
end
150+
$CFLAGS << " -fsanitize=#{s}"
151+
end
152+
end
153+
133154
if RUBY_PLATFORM =~ /mswin|mingw/
134155
# Build libmysql.a interface link library
135156
require 'rake'
@@ -155,8 +176,8 @@ def asplode(lib)
155176

156177
# Make sure the generated interface library works (if cross-compiling, trust without verifying)
157178
unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
158-
abort "-----\nCannot find libmysql.a\n----" unless have_library('libmysql')
159-
abort "-----\nCannot link to libmysql.a (my_init)\n----" unless have_func('my_init')
179+
abort "-----\nCannot find libmysql.a\n-----" unless have_library('libmysql')
180+
abort "-----\nCannot link to libmysql.a (my_init)\n-----" unless have_func('my_init')
160181
end
161182

162183
# Vendor libmysql.dll

0 commit comments

Comments
 (0)