1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
require 'fileutils'
require 'mkmf'
# Eager check devs tools
have_devel? if respond_to?(:have_devel?)
def check_libs libs = [], fatal = false
libs.all? { |lib| have_library(lib) || (abort("could not find library: #{lib}") if fatal) }
end
def check_heads heads = [], fatal = false
heads.all? { |head| have_header(head) || (abort("could not find header: #{head}") if fatal)}
end
def add_define(name)
$defs.push("-D#{name}")
end
##
# OpenSSL:
# override append_library, so it actually appends (instead of prepending)
# this fixes issues with linking ssl, since libcrypto depends on symbols in libssl
def append_library(libs, lib)
libs + " " + format(LIBARG, lib)
end
SSL_HEADS = %w(openssl/ssl.h openssl/err.h)
SSL_LIBS = %w(crypto ssl)
# OpenSSL 1.1.0 and above for Windows use the Unix library names
# OpenSSL 0.9.8 and 1.0.x for Windows use the *eay32 library names
SSL_LIBS_WIN = RUBY_PLATFORM =~ /mswin|mingw|bccwin/ ? %w(ssleay32 libeay32) : []
def dir_config_wrapper(pretty_name, name, idefault=nil, ldefault=nil)
inc, lib = dir_config(name, idefault, ldefault)
if inc && lib
# TODO: Remove when 2.0.0 is the minimum supported version
# Ruby versions not incorporating the mkmf fix at
# https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/39717
# do not properly search for lib directories, and must be corrected
unless lib && lib[-3, 3] == 'lib'
@libdir_basename = 'lib'
inc, lib = dir_config(name, idefault, ldefault)
end
unless idefault && ldefault
abort "-----\nCannot find #{pretty_name} include path #{inc}\n-----" unless inc && inc.split(File::PATH_SEPARATOR).any? { |dir| File.directory?(dir) }
abort "-----\nCannot find #{pretty_name} library path #{lib}\n-----" unless lib && lib.split(File::PATH_SEPARATOR).any? { |dir| File.directory?(dir) }
warn "-----\nUsing #{pretty_name} in path #{File.dirname inc}\n-----"
end
true
end
end
def dir_config_search(pretty_name, name, paths, &b)
paths.each do |p|
if dir_config_wrapper('OpenSSL', 'ssl', p + '/include', p + '/lib') && yield
warn "-----\nFound #{pretty_name} in path #{p}\n-----"
return true
end
end
false
end
def pkg_config_wrapper(pretty_name, name)
cflags, ldflags, libs = pkg_config(name)
unless [cflags, ldflags, libs].any?(&:nil?) || [cflags, ldflags, libs].any?(&:empty?)
warn "-----\nUsing #{pretty_name} from pkg-config #{cflags} && #{ldflags} && #{libs}\n-----"
true
end
end
if ENV['CROSS_COMPILING']
openssl_version = ENV.fetch("OPENSSL_VERSION", "1.0.2e")
openssl_dir = File.expand_path("~/.rake-compiler/builds/openssl-#{openssl_version}/")
if File.exist?(openssl_dir)
FileUtils.mkdir_p Dir.pwd+"/openssl/"
FileUtils.cp Dir[openssl_dir+"/include/openssl/*.h"], Dir.pwd+"/openssl/", :verbose => true
FileUtils.cp Dir[openssl_dir+"/lib*.a"], Dir.pwd, :verbose => true
$INCFLAGS << " -I#{Dir.pwd}" # for the openssl headers
add_define "WITH_SSL"
else
STDERR.puts
STDERR.puts "**************************************************************************************"
STDERR.puts "**** Cross-compiled OpenSSL not found"
STDERR.puts "**** Run: hg clone http://bitbucket.org/ged/ruby-pg && cd ruby-pg && rake openssl_libs"
STDERR.puts "**************************************************************************************"
STDERR.puts
end
elsif dir_config_wrapper('OpenSSL', 'ssl')
# If the user has provided a --with-ssl-dir argument, we must respect it or fail.
add_define 'WITH_SSL' if (check_libs(SSL_LIBS) || check_libs(SSL_LIBS_WIN)) && check_heads(SSL_HEADS)
elsif pkg_config_wrapper('OpenSSL', 'openssl')
# If we can detect OpenSSL by pkg-config, use it as the next-best option
add_define 'WITH_SSL' if (check_libs(SSL_LIBS) || check_libs(SSL_LIBS_WIN)) && check_heads(SSL_HEADS)
elsif (check_libs(SSL_LIBS) || check_libs(SSL_LIBS_WIN)) && check_heads(SSL_HEADS)
# If we don't even need any options to find a usable OpenSSL, go with it
add_define 'WITH_SSL'
elsif dir_config_search('OpenSSL', 'ssl', ['/usr/local', '/opt/local', '/usr/local/opt/openssl']) do
(check_libs(SSL_LIBS) || check_libs(SSL_LIBS_WIN)) && check_heads(SSL_HEADS)
end
# Finally, look for OpenSSL in alternate locations including MacPorts and HomeBrew
add_define 'WITH_SSL'
end
add_define 'BUILD_FOR_RUBY'
# Ruby features:
have_var('rb_trap_immediate', ['ruby.h', 'rubysig.h'])
have_func('rb_thread_blocking_region')
have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
have_func('rb_thread_fd_select')
have_type('rb_fdset_t', 'ruby/intern.h')
have_func('rb_wait_for_single_fd')
have_func('rb_enable_interrupt')
have_func('rb_time_new')
# System features:
add_define('HAVE_INOTIFY') if inotify = have_func('inotify_init', 'sys/inotify.h')
add_define('HAVE_OLD_INOTIFY') if !inotify && have_macro('__NR_inotify_init', 'sys/syscall.h')
have_func('writev', 'sys/uio.h')
have_func('pipe2', 'unistd.h')
have_func('accept4', 'sys/socket.h')
have_const('SOCK_CLOEXEC', 'sys/socket.h')
# Minor platform details between *nix and Windows:
if RUBY_PLATFORM =~ /(mswin|mingw|bccwin)/
GNU_CHAIN = ENV['CROSS_COMPILING'] || $1 == 'mingw'
OS_WIN32 = true
add_define "OS_WIN32"
else
GNU_CHAIN = true
OS_UNIX = true
add_define 'OS_UNIX'
add_define "HAVE_KQUEUE" if have_header("sys/event.h") && have_header("sys/queue.h")
end
# Adjust number of file descriptors (FD) on Windows
if RbConfig::CONFIG["host_os"] =~ /mingw/
found = RbConfig::CONFIG.values_at("CFLAGS", "CPPFLAGS").
any? { |v| v.include?("FD_SETSIZE") }
add_define "FD_SETSIZE=32767" unless found
end
# Main platform invariances:
case RUBY_PLATFORM
when /mswin32/, /mingw32/, /bccwin32/
check_heads(%w[windows.h winsock.h], true)
check_libs(%w[kernel32 rpcrt4 gdi32], true)
if GNU_CHAIN
CONFIG['LDSHAREDXX'] = "$(CXX) -shared -static-libgcc -static-libstdc++"
else
$defs.push "-EHs"
$defs.push "-GR"
end
# Newer versions of Ruby already define _WIN32_WINNT, which is needed
# to get access to newer POSIX networking functions (e.g. getaddrinfo)
add_define '_WIN32_WINNT=0x0501' unless have_func('getaddrinfo')
when /solaris/
add_define 'OS_SOLARIS8'
check_libs(%w[nsl socket], true)
# If Ruby was compiled for 32-bits, then select() can only handle 1024 fds
# There is an alternate function, select_large_fdset, that supports more.
have_func('select_large_fdset', 'sys/select.h')
if CONFIG['CC'] == 'cc' && (
`cc -flags 2>&1` =~ /Sun/ || # detect SUNWspro compiler
`cc -V 2>&1` =~ /Sun/ # detect Solaris Studio compiler
)
# SUN CHAIN
add_define 'CC_SUNWspro'
$preload = ["\nCXX = CC"] # hack a CXX= line into the makefile
$CFLAGS = CONFIG['CFLAGS'] = "-KPIC"
CONFIG['CCDLFLAGS'] = "-KPIC"
CONFIG['LDSHARED'] = "$(CXX) -G -KPIC -lCstd"
CONFIG['LDSHAREDXX'] = "$(CXX) -G -KPIC -lCstd"
else
# GNU CHAIN
# on Unix we need a g++ link, not gcc.
CONFIG['LDSHARED'] = "$(CXX) -shared"
end
when /openbsd/
# OpenBSD branch contributed by Guillaume Sellier.
# on Unix we need a g++ link, not gcc. On OpenBSD, linking against libstdc++ have to be explicitly done for shared libs
CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++ -fPIC"
CONFIG['LDSHAREDXX'] = "$(CXX) -shared -lstdc++ -fPIC"
when /darwin/
add_define 'OS_DARWIN'
# on Unix we need a g++ link, not gcc.
# Ff line contributed by Daniel Harple.
CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
when /linux/
add_define 'HAVE_EPOLL' if have_func('epoll_create', 'sys/epoll.h')
# on Unix we need a g++ link, not gcc.
CONFIG['LDSHARED'] = "$(CXX) -shared"
when /aix/
CONFIG['LDSHARED'] = "$(CXX) -Wl,-bstatic -Wl,-bdynamic -Wl,-G -Wl,-brtl"
when /cygwin/
# For rubies built with Cygwin, CXX may be set to CC, which is just
# a wrapper for gcc.
# This will compile, but it will not link to the C++ std library.
# Explicitly set CXX to use g++.
CONFIG['CXX'] = "g++"
# on Unix we need a g++ link, not gcc.
CONFIG['LDSHARED'] = "$(CXX) -shared"
else
# on Unix we need a g++ link, not gcc.
CONFIG['LDSHARED'] = "$(CXX) -shared"
end
# Platform-specific time functions
if have_func('clock_gettime')
# clock_gettime is POSIX, but the monotonic clocks are not
have_const('CLOCK_MONOTONIC_RAW', 'time.h') # Linux
have_const('CLOCK_MONOTONIC', 'time.h') # Linux, Solaris, BSDs
else
have_func('gethrtime') # Older Solaris and HP-UX
end
# Hack so that try_link will test with a C++ compiler instead of a C compiler
TRY_LINK.sub!('$(CC)', '$(CXX)')
# This is our wishlist. We use whichever flags work on the host.
# In the future, add -Werror to make sure all warnings are resolved.
# deprecated-declarations are used in OS X OpenSSL
# ignored-qualifiers are used by the Bindings (would-be void *)
# unused-result because GCC 4.6 no longer silences (void) ignore_this(function)
# address because on Windows, rb_fd_select checks if &fds is non-NULL, which it cannot be
%w(
-Wall
-Wextra
-Wno-deprecated-declarations
-Wno-ignored-qualifiers
-Wno-unused-result
-Wno-address
).select do |flag|
try_link('int main() {return 0;}', flag)
end.each do |flag|
CONFIG['CXXFLAGS'] << ' ' << flag
end
puts "CXXFLAGS=#{CONFIG['CXXFLAGS']}"
# Solaris C++ compiler doesn't have make_pair()
add_define 'HAVE_MAKE_PAIR' if try_link(<<SRC, '-lstdc++')
#include <utility>
using namespace std;
int main(){ pair<const int,int> tuple = make_pair(1,2); }
SRC
TRY_LINK.sub!('$(CXX)', '$(CC)')
create_makefile "rubyeventmachine"
|