Module PhusionPassenger::PlatformInfo
In: lib/phusion_passenger/platform_info/linux.rb
lib/phusion_passenger/platform_info/operating_system.rb
lib/phusion_passenger/platform_info/documentation_tools.rb
lib/phusion_passenger/platform_info/curl.rb
lib/phusion_passenger/platform_info/ruby.rb
lib/phusion_passenger/platform_info/zlib.rb
lib/phusion_passenger/platform_info/binary_compatibility.rb
lib/phusion_passenger/platform_info/apache.rb
lib/phusion_passenger/platform_info/compiler.rb
lib/phusion_passenger/platform_info.rb

This module autodetects various platform-specific information, and provides that information through constants.

Methods

Constants

GEM_HOME = gem_home
RUBY_ENGINE = ::RUBY_ENGINE
RUBY_ENGINE = "ruby"

Public Class methods

The absolute path to the Apache 2 ‘bin’ directory, or nil if unknown.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 140
140:         def self.apache2_bindir
141:                 if apxs2.nil?
142:                         return nil
143:                 else
144:                         return `#{apxs2} -q BINDIR 2>/dev/null`.strip
145:                 end
146:         end

The C compiler flags that are necessary to compile an Apache module. Also includes APR and APU compiler flags if with_apr_flags is true.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 164
164:         def self.apache2_module_cflags(with_apr_flags = true)
165:                 flags = ["-fPIC"]
166:                 if compiler_supports_visibility_flag?
167:                         flags << "-fvisibility=hidden -DVISIBILITY_ATTRIBUTE_SUPPORTED"
168:                         if compiler_visibility_flag_generates_warnings? && compiler_supports_wno_attributes_flag?
169:                                 flags << "-Wno-attributes"
170:                         end
171:                 end
172:                 if with_apr_flags
173:                         flags << apr_flags
174:                         flags << apu_flags
175:                 end
176:                 if !apxs2.nil?
177:                         apxs2_flags = `#{apxs2} -q CFLAGS`.strip << " -I" << `#{apxs2} -q INCLUDEDIR`.strip
178:                         apxs2_flags.gsub!(/-O\d? /, '')
179: 
180:                         # Remove flags not supported by GCC
181:                         if RUBY_PLATFORM =~ /solaris/ # TODO: Add support for people using SunStudio
182:                                 # The big problem is Coolstack apxs includes a bunch of solaris -x directives.
183:                                 options = apxs2_flags.split
184:                                 options.reject! { |f| f =~ /^\-x/ }
185:                                 options.reject! { |f| f =~ /^\-Xa/ }
186:                                 options.reject! { |f| f =~ /^\-fast/ }
187:                                 options.reject! { |f| f =~ /^\-mt/ }
188:                                 apxs2_flags = options.join(' ')
189:                         end
190:                         
191:                         apxs2_flags.strip!
192:                         flags << apxs2_flags
193:                 end
194:                 if !httpd.nil? && RUBY_PLATFORM =~ /darwin/
195:                         # The default Apache install on OS X is a universal binary.
196:                         # Figure out which architectures it's compiled for and do the same
197:                         # thing for mod_passenger. We use the 'file' utility to do this.
198:                         #
199:                         # Running 'file' on the Apache executable usually outputs something
200:                         # like this:
201:                         #
202:                         #   /usr/sbin/httpd: Mach-O universal binary with 4 architectures
203:                         #   /usr/sbin/httpd (for architecture ppc7400):     Mach-O executable ppc
204:                         #   /usr/sbin/httpd (for architecture ppc64):       Mach-O 64-bit executable ppc64
205:                         #   /usr/sbin/httpd (for architecture i386):        Mach-O executable i386
206:                         #   /usr/sbin/httpd (for architecture x86_64):      Mach-O 64-bit executable x86_64
207:                         #
208:                         # But on some machines, it may output just:
209:                         #
210:                         #   /usr/sbin/httpd: Mach-O fat file with 4 architectures
211:                         #
212:                         # (http://code.google.com/p/phusion-passenger/issues/detail?id=236)
213:                         output = `file "#{httpd}"`.strip
214:                         if output =~ /Mach-O fat file/ && output !~ /for architecture/
215:                                 architectures = ["-arch i386 -arch ppc -arch x86_64 -arch ppc64"]
216:                         else
217:                                 architectures = []
218:                                 output.split("\n").grep(/for architecture/).each do |line|
219:                                         line =~ /for architecture (.*?)\)/
220:                                         architectures << "-arch #{$1}"
221:                                 end
222:                         end
223:                         flags << architectures.compact.join(' ')
224:                 end
225:                 return flags.compact.join(' ').strip
226:         end

Linker flags that are necessary for linking an Apache module. Already includes APR and APU linker flags.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 231
231:         def self.apache2_module_ldflags
232:                 flags = "-fPIC #{apr_libs} #{apu_libs}"
233:                 flags.strip!
234:                 return flags
235:         end

The absolute path to the Apache 2 ‘sbin’ directory, or nil if unknown.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 150
150:         def self.apache2_sbindir
151:                 if apxs2.nil?
152:                         return nil
153:                 else
154:                         return `#{apxs2} -q SBINDIR`.strip
155:                 end
156:         end

The absolute path to the ‘apachectl’ or ‘apache2ctl’ binary, or nil if not found.

[Source]

    # File lib/phusion_passenger/platform_info/apache.rb, line 60
60:         def self.apache2ctl
61:                 return find_apache2_executable('apache2ctl', 'apachectl2', 'apachectl')
62:         end

The absolute path to the ‘apr-config’ or ‘apr-1-config’ executable, or nil if not found.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 86
 86:         def self.apr_config
 87:                 if env_defined?('APR_CONFIG')
 88:                         return ENV['APR_CONFIG']
 89:                 elsif apxs2.nil?
 90:                         return nil
 91:                 else
 92:                         filename = `#{apxs2} -q APR_CONFIG 2>/dev/null`.strip
 93:                         if filename.empty?
 94:                                 apr_bindir = `#{apxs2} -q APR_BINDIR 2>/dev/null`.strip
 95:                                 if apr_bindir.empty?
 96:                                         return nil
 97:                                 else
 98:                                         return select_executable(apr_bindir,
 99:                                                 "apr-1-config", "apr-config")
100:                                 end
101:                         elsif File.exist?(filename)
102:                                 return filename
103:                         else
104:                                 return nil
105:                         end
106:                 end
107:         end

Returns whether it is necessary to use information outputted by ‘apr-config’ and ‘apu-config’ in order to compile an Apache module. When Apache is installed with —with-included-apr, the APR/APU headers are placed into the same directory as the Apache headers, and so ‘apr-config’ and ‘apu-config’ won‘t be necessary in that case.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 266
266:         def self.apr_config_needed_for_building_apache_modules?
267:                 filename = File.join("/tmp/passenger-platform-check-#{Process.pid}.c")
268:                 File.open(filename, "w") do |f|
269:                         f.puts("#include <apr.h>")
270:                 end
271:                 begin
272:                         return !system("(gcc #{apache2_module_cflags(false)} -c '#{filename}' -o '#{filename}.o') >/dev/null 2>/dev/null")
273:                 ensure
274:                         File.unlink(filename) rescue nil
275:                         File.unlink("#{filename}.o") rescue nil
276:                 end
277:         end

The C compiler flags that are necessary for programs that use APR.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 239
239:         def self.apr_flags
240:                 return determine_apr_info[0]
241:         end

The linker flags that are necessary for linking programs that use APR.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 244
244:         def self.apr_libs
245:                 return determine_apr_info[1]
246:         end

The absolute path to the ‘apu-config’ or ‘apu-1-config’ executable, or nil if not found.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 112
112:         def self.apu_config
113:                 if env_defined?('APU_CONFIG')
114:                         return ENV['APU_CONFIG']
115:                 elsif apxs2.nil?
116:                         return nil
117:                 else
118:                         filename = `#{apxs2} -q APU_CONFIG 2>/dev/null`.strip
119:                         if filename.empty?
120:                                 apu_bindir = `#{apxs2} -q APU_BINDIR 2>/dev/null`.strip
121:                                 if apu_bindir.empty?
122:                                         return nil
123:                                 else
124:                                         return select_executable(apu_bindir,
125:                                                 "apu-1-config", "apu-config")
126:                                 end
127:                         elsif File.exist?(filename)
128:                                 return filename
129:                         else
130:                                 return nil
131:                         end
132:                 end
133:         end

The C compiler flags that are necessary for programs that use APR-Util.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 249
249:         def self.apu_flags
250:                 return determine_apu_info[0]
251:         end

The linker flags that are necessary for linking programs that use APR-Util.

[Source]

     # File lib/phusion_passenger/platform_info/apache.rb, line 254
254:         def self.apu_libs
255:                 return determine_apu_info[1]
256:         end

The absolute path to the ‘apxs’ or ‘apxs2’ executable, or nil if not found.

[Source]

    # File lib/phusion_passenger/platform_info/apache.rb, line 44
44:         def self.apxs2
45:                 if env_defined?("APXS2")
46:                         return ENV["APXS2"]
47:                 end
48:                 ['apxs2', 'apxs'].each do |name|
49:                         command = find_command(name)
50:                         if !command.nil?
51:                                 return command
52:                         end
53:                 end
54:                 return nil
55:         end

[Source]

    # File lib/phusion_passenger/platform_info/documentation_tools.rb, line 29
29:         def self.asciidoc
30:                 return find_command('asciidoc') || find_command('mizuho-asciidoc')
31:         end

[Source]

     # File lib/phusion_passenger/platform_info.rb, line 159
159:         def self.cc
160:                 return ENV['CC'] || "gcc"
161:         end

[Source]

    # File lib/phusion_passenger/platform_info/compiler.rb, line 49
49:         def self.compiler_supports_visibility_flag?
50:                 return try_compile(:c, '', '-fvisibility=hidden')
51:         end

[Source]

    # File lib/phusion_passenger/platform_info/compiler.rb, line 54
54:         def self.compiler_supports_wno_attributes_flag?
55:                 return try_compile(:c, '', '-Wno-attributes')
56:         end

Returns whether compiling C++ with -fvisibility=hidden might result in tons of useless warnings, like this: code.google.com/p/phusion-passenger/issues/detail?id=526 This appears to be a bug in older g++ versions: gcc.gnu.org/ml/gcc-patches/2006-07/msg00861.html Warnings should be suppressed with -Wno-attributes.

[Source]

    # File lib/phusion_passenger/platform_info/compiler.rb, line 65
65:         def self.compiler_visibility_flag_generates_warnings?
66:                 if RUBY_PLATFORM =~ /linux/ && `#{cxx} -v 2>&1` =~ /gcc version (.*?)/
67:                         return $1 <= "4.1.2"
68:                 else
69:                         return false
70:                 end
71:         end

Returns a list of all CPU architecture names that the current machine CPU supports. If there are multiple such architectures then the first item in the result denotes that OS runtime‘s main/preferred architecture.

This function normalizes some names. For example x86 is always reported as "x86" regardless of whether the OS reports it as "i386" or "i686". x86_64 is always reported as "x86_64" even if the OS reports it as "amd64".

Please note that even if the CPU supports multiple architectures, the operating system might not. For example most x86 CPUs nowadays also support x86_64, but x86_64 Linux systems require various x86 compatibility libraries to be installed before x86 executables can be run. This function does not detect whether these compatibility libraries are installed. The only guarantee that you have is that the OS can run executables in the architecture denoted by the first item in the result.

For example, on x86_64 Linux this function can return ["x86_64", "x86"]. This indicates that the CPU supports both of these architectures, and that the OS‘s main/preferred architecture is x86_64. Most executables on the system are thus be x86_64. It is guaranteed that the OS can run x86_64 executables, but not x86 executables per se.

Another example: on MacOS X this function can return either

"x86_64", "x86"
or ["x86", "x86_64"]. The former result indicates

OS X 10.6 (Snow Leopard) and beyond because starting from that version everything is 64-bit by default. The latter result indicates an OS X version older than 10.6.

[Source]

     # File lib/phusion_passenger/platform_info/operating_system.rb, line 77
 77:         def self.cpu_architectures
 78:                 if os_name == "macosx"
 79:                         arch = `uname -p`.strip
 80:                         if arch == "i386"
 81:                                 # Macs have been x86 since around 2007. I think all of them come with
 82:                                 # a recent enough Intel CPU that supports both x86 and x86_64, and I
 83:                                 # think every OS X version has both the x86 and x86_64 runtime installed.
 84:                                 major, minor, *rest = `sw_vers -productVersion`.strip.split(".")
 85:                                 major = major.to_i
 86:                                 minor = minor.to_i
 87:                                 if major >= 10 || (major == 10 && minor >= 6)
 88:                                         # Since Snow Leopard x86_64 is the default.
 89:                                         ["x86_64", "x86"]
 90:                                 else
 91:                                         # Before Snow Leopard x86 was the default.
 92:                                         ["x86", "x86_64"]
 93:                                 end
 94:                         else
 95:                                 arch
 96:                         end
 97:                 else
 98:                         arch = `uname -p`.strip
 99:                         # On some systems 'uname -p' returns something like
100:                         # 'Intel(R) Pentium(R) M processor 1400MHz'.
101:                         if arch == "unknown" || arch =~ / /
102:                                 arch = `uname -m`.strip
103:                         end
104:                         if arch =~ /^i.86$/
105:                                 arch = "x86"
106:                         elsif arch == "amd64"
107:                                 arch = "x86_64"
108:                         end
109:                         
110:                         if arch == "x86"
111:                                 # Most x86 operating systems nowadays are probably running on
112:                                 # a CPU that supports both x86 and x86_64, but we're not gonna
113:                                 # go through the trouble of checking that. The main architecture
114:                                 # is what we usually care about.
115:                                 ["x86"]
116:                         elsif arch == "x86_64"
117:                                 # I don't think there's a single x86_64 CPU out there
118:                                 # that doesn't support x86 as well.
119:                                 ["x86_64", "x86"]
120:                         else
121:                                 [arch]
122:                         end
123:                 end
124:         end

[Source]

    # File lib/phusion_passenger/platform_info/curl.rb, line 29
29:         def self.curl_flags
30:                 result = `(curl-config --cflags) 2>/dev/null`.strip
31:                 if result.empty?
32:                         return nil
33:                 else
34:                         version = `curl-config --vernum`.strip
35:                         if version >= '070c01'
36:                                 # Curl >= 7.12.1 supports curl_easy_reset()
37:                                 result << " -DHAS_CURL_EASY_RESET"
38:                         end
39:                         return result
40:                 end
41:         end

[Source]

    # File lib/phusion_passenger/platform_info/curl.rb, line 44
44:         def self.curl_libs
45:                 result = `(curl-config --libs) 2>/dev/null`.strip
46:                 if result.empty?
47:                         return nil
48:                 else
49:                         return result
50:                 end
51:         end

[Source]

    # File lib/phusion_passenger/platform_info/curl.rb, line 54
54:         def self.curl_supports_ssl?
55:                 features = `(curl-config --feature) 2>/dev/null`
56:                 return features =~ /SSL/
57:         end

[Source]

     # File lib/phusion_passenger/platform_info.rb, line 163
163:         def self.cxx
164:                 return ENV['CXX'] || "g++"
165:         end

C compiler flags that should be passed in order to enable debugging information.

[Source]

     # File lib/phusion_passenger/platform_info/compiler.rb, line 163
163:         def self.debugging_cflags
164:                 if RUBY_PLATFORM =~ /openbsd/
165:                         # According to OpenBSD's pthreads man page, pthreads do not work
166:                         # correctly when an app is compiled with -g. It recommends using
167:                         # -ggdb instead.
168:                         return '-ggdb'
169:                 else
170:                         return '-g'
171:                 end
172:         end

[Source]

     # File lib/phusion_passenger/platform_info.rb, line 155
155:         def self.env_defined?(name)
156:                 return !ENV[name].nil? && !ENV[name].empty?
157:         end

[Source]

     # File lib/phusion_passenger/platform_info/compiler.rb, line 174
174:         def self.export_dynamic_flags
175:                 if RUBY_PLATFORM =~ /linux/
176:                         return '-rdynamic'
177:                 else
178:                         return nil
179:                 end
180:         end

Check whether the specified command is in $PATH, and return its absolute filename. Returns nil if the command is not found.

This function exists because system(‘which’) doesn‘t always behave correctly, for some weird reason.

[Source]

     # File lib/phusion_passenger/platform_info.rb, line 145
145:         def self.find_command(name)
146:                 ENV['PATH'].split(File::PATH_SEPARATOR).detect do |directory|
147:                         path = File.join(directory, name.to_s)
148:                         if File.file?(path) && File.executable?(path)
149:                                 return path
150:                         end
151:                 end
152:                 return nil
153:         end

Returns the correct ‘gem’ command for this Ruby interpreter.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 110
110:         def self.gem_command
111:                 return locate_ruby_tool('gem')
112:         end

[Source]

    # File lib/phusion_passenger/platform_info/compiler.rb, line 30
30:         def self.gnu_make
31:                 gmake = find_command('gmake')
32:                 if !gmake
33:                         gmake = find_command('make')
34:                         if gmake
35:                                 if `#{gmake} --version 2>&1` =~ /GNU/
36:                                         return gmake
37:                                 else
38:                                         return nil
39:                                 end
40:                         else
41:                                 return nil
42:                         end
43:                 else
44:                         return gmake
45:                 end
46:         end

[Source]

    # File lib/phusion_passenger/platform_info/compiler.rb, line 74
74:         def self.has_math_library?
75:                 return try_link(:c, "int main() { return 0; }\n", '-lmath')
76:         end

The absolute path to the Apache binary (that is, ‘httpd’, ‘httpd2’, ‘apache’ or ‘apache2’), or nil if not found.

[Source]

    # File lib/phusion_passenger/platform_info/apache.rb, line 67
67:         def self.httpd
68:                 if env_defined?('HTTPD')
69:                         return ENV['HTTPD']
70:                 elsif apxs2.nil?
71:                         ["apache2", "httpd2", "apache", "httpd"].each do |name|
72:                                 command = find_command(name)
73:                                 if !command.nil?
74:                                         return command
75:                                 end
76:                         end
77:                         return nil
78:                 else
79:                         return find_apache2_executable(`#{apxs2} -q TARGET`.strip)
80:                 end
81:         end

Returns whether the current Ruby interpreter is managed by RVM.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 154
154:         def self.in_rvm?
155:                 bindir = Config::CONFIG['bindir']
156:                 return bindir.include?('/.rvm/') || bindir.include?('/rvm/')
157:         end

The current platform‘s shared library extension (‘so’ on most Unices).

[Source]

    # File lib/phusion_passenger/platform_info/operating_system.rb, line 42
42:         def self.library_extension
43:                 if RUBY_PLATFORM =~ /darwin/
44:                         return "bundle"
45:                 else
46:                         return "so"
47:                 end
48:         end

An identifier for the current Linux distribution. nil if the operating system is not Linux.

[Source]

    # File lib/phusion_passenger/platform_info/linux.rb, line 30
30:         def self.linux_distro
31:                 tags = linux_distro_tags
32:                 if tags
33:                         return tags.first
34:                 else
35:                         return nil
36:                 end
37:         end

Autodetects the current Linux distribution and return a number of identifier tags. The first tag identifies the distribution while the other tags indicate which distributions it is likely compatible with. Returns nil if the operating system is not Linux.

[Source]

    # File lib/phusion_passenger/platform_info/linux.rb, line 43
43:         def self.linux_distro_tags
44:                 if RUBY_PLATFORM !~ /linux/
45:                         return nil
46:                 end
47:                 lsb_release = read_file("/etc/lsb-release")
48:                 if lsb_release =~ /Ubuntu/
49:                         return [:ubuntu, :debian]
50:                 elsif File.exist?("/etc/debian_version")
51:                         return [:debian]
52:                 elsif File.exist?("/etc/redhat-release")
53:                         redhat_release = read_file("/etc/redhat-release")
54:                         if redhat_release =~ /CentOS/
55:                                 return [:centos, :redhat]
56:                         elsif redhat_release =~ /Fedora/
57:                                 return [:fedora, :redhat]
58:                         elsif redhat_release =~ /Mandriva/
59:                                 return [:mandriva, :redhat]
60:                         else
61:                                 # On official RHEL distros, the content is in the form of
62:                                 # "Red Hat Enterprise Linux Server release 5.1 (Tikanga)"
63:                                 return [:rhel, :redhat]
64:                         end
65:                 elsif File.exist?("/etc/suse-release")
66:                         return [:suse]
67:                 elsif File.exist?("/etc/gentoo-release")
68:                         return [:gentoo]
69:                 else
70:                         return [:unknown]
71:                 end
72:                 # TODO: Slackware
73:         end

Locates a Ruby tool command, e.g. ‘gem’, ‘rake’, ‘bundle’, etc. Instead of naively looking in $PATH, this function uses a variety of search heuristics to find the command that‘s really associated with the current Ruby interpreter. It should never locate a command that‘s actually associated with a different Ruby interpreter. Returns nil when nothing‘s found.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 246
246:         def self.locate_ruby_tool(name)
247:                 result = locate_ruby_tool_by_basename(name)
248:                 if !result
249:                         exeext = Config::CONFIG['EXEEXT']
250:                         exeext = nil if exeext.empty?
251:                         if exeext
252:                                 result = locate_ruby_tool_by_basename("#{name}#{exeext}")
253:                         end
254:                         if !result
255:                                 result = locate_ruby_tool_by_basename(transform_according_to_ruby_exec_format(name))
256:                         end
257:                         if !result && exeext
258:                                 result = locate_ruby_tool_by_basename(transform_according_to_ruby_exec_format(name) + exeext)
259:                         end
260:                 end
261:                 return result
262:         end

Returns the operating system‘s name. This name is in lowercase and contains no spaces, and thus is suitable to be used in some kind of ID. E.g. "linux", "macosx".

[Source]

    # File lib/phusion_passenger/platform_info/operating_system.rb, line 32
32:         def self.os_name
33:                 if Config::CONFIG['target_os'] =~ /darwin/ && (sw_vers = find_command('sw_vers'))
34:                         return "macosx"
35:                 else
36:                         return RUBY_PLATFORM.sub(/.*?-/, '')
37:                 end
38:         end

Returns an identifier string that describes the current platform‘s binary compatibility with regard to Phusion Passenger binaries, both the Ruby extension and the C++ binaries. Two systems with the same binary compatibility identifiers are able to run the same Phusion Passenger binaries.

The the string depends on the following factors:

  • The Ruby extension binary compatibility identifiers.
  • The operating system name.
  • Operating system runtime identifier. This may include the kernel version, libc version, C++ ABI version, etc. Everything that is of interest for binary compatibility with Phusion Passenger‘s C++ components.
  • Operating system default runtime architecture. This is not the same as the CPU architecture; some CPUs support multiple architectures, e.g. Intel Core 2 Duo supports x86 and x86_64. Some operating systems actually support multiple runtime architectures: a lot of x86_64 Linux distributions also include 32-bit runtimes, and OS X Snow Leopard is x86_64 by default but all system libraries also support x86. This component identifies the architecture that is used when compiling a binary with the system‘s C++ compiler with its default options.

[Source]

     # File lib/phusion_passenger/platform_info/binary_compatibility.rb, line 103
103:         def self.passenger_binary_compatibility_id
104:                 ruby_engine, ruby_ext_version, ruby_arch, os_name =
105:                         ruby_extension_binary_compatibility_ids
106:                 
107:                 if os_name == "macosx"
108:                         # RUBY_PLATFORM gives us the kernel version, but we want
109:                         # the OS X version.
110:                         os_version_string = `sw_vers -productVersion`.strip
111:                         # sw_vers returns something like "10.6.2". We're only
112:                         # interested in the first two digits (MAJOR.MINOR) since
113:                         # tiny releases tend to be binary compatible with each
114:                         # other.
115:                         components = os_version_string.split(".")
116:                         os_version = "#{components[0]}.#{components[1]}"
117:                         os_runtime = os_version
118:                         
119:                         os_arch = cpu_architectures[0]
120:                         if os_version >= "10.5" && os_arch =~ /^i.86$/
121:                                 # On Snow Leopard, 'uname -m' returns i386 but
122:                                 # we *know* that everything is x86_64 by default.
123:                                 os_arch = "x86_64"
124:                         end
125:                 else
126:                         os_arch = cpu_architectures[0]
127:                         
128:                         cpp = find_command('cpp')
129:                         if cpp
130:                                 macros = `#{cpp} -dM < /dev/null`
131:                                 
132:                                 # Can be something like "4.3.2"
133:                                 # or "4.2.1 20070719 (FreeBSD)"
134:                                 macros =~ /__VERSION__ "(.+)"/
135:                                 compiler_version = $1
136:                                 compiler_version.gsub!(/ .*/, '') if compiler_version
137:                                 
138:                                 macros =~ /__GXX_ABI_VERSION (.+)$/
139:                                 cxx_abi_version = $1
140:                         else
141:                                 compiler_version = nil
142:                                 cxx_abi_version = nil
143:                         end
144:                         
145:                         if compiler_version && cxx_abi_version
146:                                 os_runtime = "gcc#{compiler_version}-#{cxx_abi_version}"
147:                         else
148:                                 os_runtime = [compiler_version, cxx_abi_version].compact.join("-")
149:                                 if os_runtime.empty?
150:                                         os_runtime = `uname -r`.strip
151:                                 end
152:                         end
153:                 end
154:                 
155:                 if ruby_engine == "jruby"
156:                         # For JRuby it's kinda useless to prepend "java" as extension
157:                         # architecture because JRuby doesn't allow any other extension
158:                         # architecture.
159:                         identifier = ""
160:                 else
161:                         identifier = "#{ruby_arch}-"
162:                 end
163:                 identifier << "#{ruby_engine}#{ruby_ext_version}-"
164:                 # If the extension architecture is the same as the OS architecture
165:                 # then there's no need to specify it twice.
166:                 if ruby_arch != os_arch
167:                         identifier << "#{os_arch}-"
168:                 end
169:                 identifier << "#{os_name}-#{os_runtime}"
170:                 return identifier
171:         end

Compiler flags that should be used for compiling every C/C++ program, for portability reasons. These flags should be specified as last when invoking the compiler.

[Source]

     # File lib/phusion_passenger/platform_info/compiler.rb, line 82
 82:         def self.portability_cflags
 83:                 flags = ["-D_REENTRANT -I/usr/local/include"]
 84:                 
 85:                 # Google SparseHash flags.
 86:                 # Figure out header for hash function object and its namespace.
 87:                 # Based on stl_hash.m4 and stl_hash_fun.m4 in the Google SparseHash sources.
 88:                 hash_namespace = nil
 89:                 ok = false
 90:                 ['__gnu_cxx', '', 'std', 'stdext'].each do |namespace|
 91:                         ['ext/hash_map', 'hash_map'].each do |hash_map_header|
 92:                                 ok = try_compile(:cxx, %Q{
 93:                                         #include <#{hash_map_header}>
 94:                                         int
 95:                                         main() {
 96:                                                 #{namespace}::hash_map<int, int> m;
 97:                                                 return 0;
 98:                                         }
 99:                                 })
100:                                 if ok
101:                                         hash_namespace = namespace
102:                                         flags << "-DHASH_NAMESPACE=\"#{namespace}\""
103:                                 end
104:                         end
105:                         break if ok
106:                 end
107:                 ['ext/hash_fun.h', 'functional', 'tr1/functional',
108:                  'ext/stl_hash_fun.h', 'hash_fun.h', 'stl_hash_fun.h',
109:                  'stl/_hash_fun.h'].each do |hash_function_header|
110:                         ok = try_compile(:cxx, %Q{
111:                                 #include <#{hash_function_header}>
112:                                 int
113:                                 main() {
114:                                         #{hash_namespace}::hash<int>()(5);
115:                                         return 0;
116:                                 }
117:                         })
118:                         if ok
119:                                 flags << "-DHASH_FUN_H=\"<#{hash_function_header}>\""
120:                                 break
121:                         end
122:                 end
123:                 
124:                 if RUBY_PLATFORM =~ /solaris/
125:                         flags << '-pthreads'
126:                         flags << '-D_XOPEN_SOURCE=500 -D_XPG4_2 -D__EXTENSIONS__ -D__SOLARIS__ -D_FILE_OFFSET_BITS=64'
127:                         flags << '-DBOOST_HAS_STDINT_H' unless RUBY_PLATFORM =~ /solaris2.9/
128:                         flags << '-D__SOLARIS9__ -DBOOST__STDC_CONSTANT_MACROS_DEFINED' if RUBY_PLATFORM =~ /solaris2.9/
129:                         flags << '-mcpu=ultrasparc' if RUBY_PLATFORM =~ /sparc/
130:                 elsif RUBY_PLATFORM =~ /openbsd/
131:                         flags << '-DBOOST_HAS_STDINT_H -D_GLIBCPP__PTHREADS'
132:                 elsif RUBY_PLATFORM =~ /aix/
133:                         flags << '-DOXT_DISABLE_BACKTRACES'
134:                 elsif RUBY_PLATFORM =~ /(sparc-linux|arm-linux|^arm.*-linux|sh4-linux)/
135:                         # http://code.google.com/p/phusion-passenger/issues/detail?id=200
136:                         # http://groups.google.com/group/phusion-passenger/t/6b904a962ee28e5c
137:                         # http://groups.google.com/group/phusion-passenger/browse_thread/thread/aad4bd9d8d200561
138:                         flags << '-DBOOST_SP_USE_PTHREADS'
139:                 end
140:                 
141:                 flags << '-DHAS_SFENCE' if supports_sfence_instruction?
142:                 flags << '-DHAS_LFENCE' if supports_lfence_instruction?
143:                 
144:                 return flags.compact.join(" ").strip
145:         end

Linker flags that should be used for linking every C/C++ program, for portability reasons. These flags should be specified as last when invoking the linker.

[Source]

     # File lib/phusion_passenger/platform_info/compiler.rb, line 151
151:         def self.portability_ldflags
152:                 if RUBY_PLATFORM =~ /solaris/
153:                         result = '-lxnet -lrt -lsocket -lnsl -lpthread'
154:                 else
155:                         result = '-lpthread'
156:                 end
157:                 flags << ' -lmath' if has_math_library?
158:                 return result
159:         end

Returns the absolute path to the Rake executable that belongs to the current Ruby interpreter. Returns nil if it doesn‘t exist.

The return value may not be the actual correct invocation for Rake. Use rake_command for that.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 121
121:         def self.rake
122:                 return locate_ruby_tool('rake')
123:         end

Returns the correct command string for invoking the Rake executable that belongs to the current Ruby interpreter. Returns nil if Rake is not found.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 129
129:         def self.rake_command
130:                 filename = rake
131:                 # If the Rake executable is a Ruby program then we need to run
132:                 # it in the correct Ruby interpreter just in case Rake doesn't
133:                 # have the correct shebang line; we don't want a totally different
134:                 # Ruby than the current one to be invoked.
135:                 if filename && is_ruby_program?(filename)
136:                         return "#{ruby_command} #{filename}"
137:                 else
138:                         # If it's not a Ruby program then it's probably a wrapper
139:                         # script as is the case with e.g. RVM (~/.rvm/wrappers).
140:                         return filename
141:                 end
142:         end

Returns the absolute path to the RSpec runner program that belongs to the current Ruby interpreter. Returns nil if it doesn‘t exist.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 148
148:         def self.rspec
149:                 return locate_ruby_tool('spec')
150:         end

Returns correct command for invoking the current Ruby interpreter. In case of RVM this function will return the path to the RVM wrapper script that executes the current Ruby interpreter in the currently active gem set.

[Source]

    # File lib/phusion_passenger/platform_info/ruby.rb, line 48
48:         def self.ruby_command
49:                 if in_rvm?
50:                         name = rvm_ruby_string
51:                         dir = rvm_path
52:                         if name && dir
53:                                 filename = "#{dir}/wrappers/#{name}/ruby"
54:                                 if File.exist?(filename)
55:                                         contents = File.open(filename, 'rb') do |f|
56:                                                 f.read
57:                                         end
58:                                         # Old wrapper scripts reference $HOME which causes
59:                                         # things to blow up when run by a different user.
60:                                         if contents.include?("$HOME")
61:                                                 filename = nil
62:                                         end
63:                                 else
64:                                         filename = nil
65:                                 end
66:                                 if filename
67:                                         return filename
68:                                 else
69:                                         STDERR.puts "Your RVM wrapper scripts are too old. Please " +
70:                                                 "update them first by running 'rvm update --head && " +
71:                                                 "rvm reload && rvm repair all'."
72:                                         exit 1
73:                                 end
74:                         else
75:                                 # Something's wrong with the user's RVM installation.
76:                                 # Raise an error so that the user knows this instead of
77:                                 # having things fail randomly later on.
78:                                 # 'name' is guaranteed to be non-nil because rvm_ruby_string
79:                                 # already raises an exception on error.
80:                                 STDERR.puts "Your RVM installation appears to be broken: the RVM " +
81:                                         "path cannot be found. Please fix your RVM installation " +
82:                                         "or contact the RVM developers for support."
83:                                 exit 1
84:                         end
85:                 else
86:                         return ruby_executable
87:                 end
88:         end

Returns the full path to the current Ruby interpreter‘s executable file. This might not be the actual correct command to use for invoking the Ruby interpreter; use ruby_command instead.

[Source]

    # File lib/phusion_passenger/platform_info/ruby.rb, line 94
94:         def self.ruby_executable
95:                 @@ruby_executable ||=
96:                         Config::CONFIG['bindir'] + '/' + Config::CONFIG['RUBY_INSTALL_NAME'] + Config::CONFIG['EXEEXT']
97:         end

Returns an array of identifiers that describe the current Ruby interpreter‘s extension binary compatibility. A Ruby extension compiled for a certain Ruby interpreter can also be loaded on a different Ruby interpreter with the same binary compatibility identifiers.

The identifiers depend on the following factors:

  • Ruby engine name.
  • Ruby extension version. This is not the same as the Ruby language version, which identifies language-level compatibility. This is rather about binary compatibility of extensions. MRI seems to break source compatibility between tiny releases, though patchlevel releases tend to be source and binary compatible.
  • Ruby extension architecture. This is not necessarily the same as the operating system runtime architecture or the CPU architecture. For example, in case of JRuby, the extension architecture is just "java" because all extensions target the Java platform; the architecture the JVM was compiled for has no effect on compatibility. On systems with universal binaries support there may be multiple architectures. In this case the architecture is "universal" because extensions must be able to support all of the Ruby executable‘s architectures.
  • The operating system for which the Ruby interpreter was compiled.

[Source]

    # File lib/phusion_passenger/platform_info/binary_compatibility.rb, line 59
59:         def self.ruby_extension_binary_compatibility_ids
60:                 ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
61:                 ruby_ext_version = RUBY_VERSION
62:                 if RUBY_PLATFORM =~ /darwin/
63:                         if RUBY_PLATFORM =~ /universal/
64:                                 ruby_arch = "universal"
65:                         else
66:                                 # Something like:
67:                                 # "/opt/ruby-enterprise/bin/ruby: Mach-O 64-bit executable x86_64"
68:                                 ruby_arch = `file -L "#{ruby_executable}"`.strip
69:                                 ruby_arch.sub!(/.* /, '')
70:                         end
71:                 elsif RUBY_PLATFORM == "java"
72:                         ruby_arch = "java"
73:                 else
74:                         ruby_arch = cpu_architectures[0]
75:                 end
76:                 return [ruby_engine, ruby_ext_version, ruby_arch, os_name]
77:         end

Returns either ‘sudo’ or ‘rvmsudo’ depending on whether the current Ruby interpreter is managed by RVM.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 232
232:         def self.ruby_sudo_command
233:                 if in_rvm?
234:                         return "rvmsudo"
235:                 else
236:                         return "sudo"
237:                 end
238:         end

Returns whether the Ruby interpreter supports process forking.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 100
100:         def self.ruby_supports_fork?
101:                 # MRI >= 1.9.2's respond_to? returns false for methods
102:                 # that are not implemented.
103:                 return Process.respond_to?(:fork) &&
104:                         RUBY_ENGINE != "jruby" &&
105:                         RUBY_ENGINE != "macruby" &&
106:                         Config::CONFIG['target_os'] !~ /mswin|windows|mingw/
107:         end

If the current Ruby interpreter is managed by RVM, returns the directory in which RVM places its working files. Otherwise returns nil.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 162
162:         def self.rvm_path
163:                 if in_rvm?
164:                         [ENV['rvm_path'], "~/.rvm", "/usr/local/rvm"].each do |path|
165:                                 next if path.nil?
166:                                 path = File.expand_path(path)
167:                                 return path if File.directory?(path)
168:                         end
169:                         # Failure to locate the RVM path is probably caused by the
170:                         # user customizing $rvm_path. Older RVM versions don't
171:                         # export $rvm_path, making us unable to detect its value.
172:                         STDERR.puts "Unable to locate the RVM path. Your RVM installation " +
173:                                 "is probably too old. Please update it with " +
174:                                 "'rvm update --head && rvm reload && rvm repair all'."
175:                         exit 1
176:                 else
177:                         return nil
178:                 end
179:         end

If the current Ruby interpreter is managed by RVM, returns the RVM name which identifies the current Ruby interpreter plus the currently active gemset, e.g. something like this: "ruby-1.9.2-p0@mygemset"

Returns nil otherwise.

[Source]

     # File lib/phusion_passenger/platform_info/ruby.rb, line 188
188:         def self.rvm_ruby_string
189:                 if in_rvm?
190:                         # RVM used to export the necessary information through
191:                         # environment variables, but doesn't always do that anymore
192:                         # in the latest versions in order to fight env var pollution.
193:                         # Scanning $LOAD_PATH seems to be the only way to obtain
194:                         # the information.
195:                         
196:                         # Getting the RVM name of the Ruby interpreter ("ruby-1.9.2")
197:                         # isn't so hard, we can extract it from the #ruby_executable
198:                         # string. Getting the gemset name is a bit harder, so let's
199:                         # try various strategies...
200:                         
201:                         # $GEM_HOME usually contains the gem set name.
202:                         if GEM_HOME && GEM_HOME.include?("rvm/gems/")
203:                                 return File.basename(GEM_HOME)
204:                         end
205:                         
206:                         # User somehow managed to nuke $GEM_HOME. Extract info
207:                         # from $LOAD_PATH.
208:                         matching_path = $LOAD_PATH.find_all do |item|
209:                                 item.include?("rvm/gems/")
210:                         end
211:                         if matching_path
212:                                 subpath = matching_path.to_s.gsub(/^.*rvm\/gems\//, '')
213:                                 result = subpath.split('/').first
214:                                 return result if result
215:                         end
216:                         
217:                         # On Ruby 1.9, $LOAD_PATH does not contain any gem paths until
218:                         # at least one gem has been required so the above can fail.
219:                         # We're out of options now, we can't detect the gem set.
220:                         # Raise an exception so that the user knows what's going on
221:                         # instead of having things fail in obscure ways later.
222:                         STDERR.puts "Unable to autodetect the currently active RVM gem " +
223:                                 "set name. Please contact this program's author for support."
224:                         exit 1
225:                 end
226:                 return nil
227:         end

Returns whether the OS‘s main CPU architecture supports the x86/x86_64 lfence instruction.

[Source]

     # File lib/phusion_passenger/platform_info/operating_system.rb, line 144
144:         def self.supports_lfence_instruction?
145:                 arch = cpu_architectures[0]
146:                 return arch == "x86_64" || (arch == "x86" &&
147:                         try_compile_and_run(:c, %Q{
148:                                 int
149:                                 main() {
150:                                         __asm__ __volatile__ ("lfence" ::: "memory");
151:                                         return 0;
152:                                 }
153:                         }))
154:         end

Returns whether the OS‘s main CPU architecture supports the x86/x86_64 sfence instruction.

[Source]

     # File lib/phusion_passenger/platform_info/operating_system.rb, line 129
129:         def self.supports_sfence_instruction?
130:                 arch = cpu_architectures[0]
131:                 return arch == "x86_64" || (arch == "x86" &&
132:                         try_compile_and_run(:c, %Q{
133:                                 int
134:                                 main() {
135:                                         __asm__ __volatile__ ("sfence" ::: "memory");
136:                                         return 0;
137:                                 }
138:                         }))
139:         end

[Source]

    # File lib/phusion_passenger/platform_info/zlib.rb, line 29
29:         def self.zlib_flags
30:                 return nil
31:         end

[Source]

    # File lib/phusion_passenger/platform_info/zlib.rb, line 33
33:         def self.zlib_libs
34:                 return '-lz'
35:         end

[Validate]