Skip to content

Commit

Permalink
Put native_support.so in a Ruby version- and architecture-specific su…
Browse files Browse the repository at this point in the history
…bdirectory and have native_support.rb auto-compile it if necessary.
  • Loading branch information
FooBarWidget committed Jan 18, 2010
1 parent c49a75f commit 45c1e01
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 40 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Expand Up @@ -17,8 +17,8 @@ ext/apache2/PassengerHelperServer
ext/nginx/PassengerHelperServer
ext/common/PassengerWatchdog
ext/common/PassengerLoggingAgent
ext/phusion_passenger/Makefile
ext/phusion_passenger/mkmf.log
ext/phusion_passenger/*/Makefile
ext/phusion_passenger/*/mkmf.log
ext/*.a
doc/rdoc
doc/cxxapi
Expand Down
29 changes: 19 additions & 10 deletions Rakefile
Expand Up @@ -87,24 +87,34 @@ task :clobber

##### Ruby C extension

task :native_support => "ext/phusion_passenger/native_support.#{LIBEXT}"
native_support_archdir = PlatformInfo.ruby_extension_binary_compatibility_ids.join("-")
task :native_support => "ext/phusion_passenger/#{native_support_archdir}/native_support.#{LIBEXT}"

file 'ext/phusion_passenger/Makefile' => 'ext/phusion_passenger/extconf.rb' do
sh "cd ext/phusion_passenger && #{RUBY} extconf.rb"
file "ext/phusion_passenger/#{native_support_archdir}/Makefile" => 'ext/phusion_passenger/extconf.rb' do
if !File.exist?("ext/phusion_passenger/#{native_support_archdir}")
sh "mkdir -p ext/phusion_passenger/#{native_support_archdir}"
end
sh "cd ext/phusion_passenger/#{native_support_archdir} && #{RUBY} ../extconf.rb"
end

file "ext/phusion_passenger/native_support.#{LIBEXT}" => [
'ext/phusion_passenger/Makefile',
'ext/phusion_passenger/native_support.c'
file "ext/phusion_passenger/#{native_support_archdir}/native_support.#{LIBEXT}" => [
"ext/phusion_passenger/#{native_support_archdir}/Makefile",
"ext/phusion_passenger/native_support.c"
] do
sh "cd ext/phusion_passenger && make"
if !File.exist?("ext/phusion_passenger/#{native_support_archdir}")
sh "mkdir -p ext/phusion_passenger/#{native_support_archdir}"
end
sh "cd ext/phusion_passenger/#{native_support_archdir} && make"
end

task :clean => 'native_support:clean'

task 'native_support:clean' do
sh "cd ext/phusion_passenger && make clean" if File.exist?('ext/phusion_passenger/Makefile')
sh "rm -f ext/phusion_passenger/Makefile"
Dir["ext/phusion_passenger/*"].each do |entry|
if File.exist?("#{entry}/Makefile")
sh "rm -rf #{entry}"
end
end
end


Expand Down Expand Up @@ -823,7 +833,6 @@ spec = Gem::Specification.new do |s|
s.add_dependency 'daemon_controller', '>= 0.2.3'
s.add_dependency 'file-tail'
s.add_dependency 'rack'
s.extensions << 'ext/phusion_passenger/extconf.rb'
s.files = FileList[
'Rakefile',
'README',
Expand Down
16 changes: 7 additions & 9 deletions lib/phusion_passenger.rb
Expand Up @@ -36,24 +36,22 @@ def self.natively_packaged?
LIBDIR = File.expand_path(File.dirname(__FILE__))
TEMPLATES_DIR = File.join(LIBDIR, "phusion_passenger", "templates")
if natively_packaged?
require 'rbconfig'

# Top directory of the Phusion Passenger source code.
SOURCE_ROOT = "/usr/lib/phusion_passenger/source"

# Directory containing native_support.so.
NATIVE_SUPPORT_DIR = File.join(Config::CONFIG["archdir"], "phusion_passenger")

# Documentation directory.
NATIVE_SUPPORT_DIR = "/usr/lib/phusion_passenger/native_support"
DOCDIR = "/usr/share/doc/phusion_passenger"
else
# Top directory of the Phusion Passenger source code.
SOURCE_ROOT = File.expand_path(File.join(LIBDIR, ".."))

# Directory containing native_support.so.
NATIVE_SUPPORT_DIR = File.join(SOURCE_ROOT, "ext", "phusion_passenger")

# Documentation directory.
DOCDIR = File.join(SOURCE_ROOT, "doc")
end

if $LOAD_PATH.first != LIBDIR
$LOAD_PATH.unshift(LIBDIR)
$LOAD_PATH.uniq!
end
end if !defined?(PhusionPassenger)
end if !defined?(PhusionPassenger::LIBDIR)
86 changes: 83 additions & 3 deletions lib/phusion_passenger/native_support.rb
Expand Up @@ -22,7 +22,87 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
module PhusionPassenger
require 'phusion_passenger'
require "#{PhusionPassenger::NATIVE_SUPPORT_DIR}/native_support"
end
require 'phusion_passenger/platform_info'

archdir = PlatformInfo.ruby_extension_binary_compatibility_ids.join("-")
libext = PlatformInfo.library_extension
loaded = false
begin
require "#{NATIVE_SUPPORT_DIR}/#{archdir}/native_support.#{libext}"
loaded = true
rescue LoadError
require 'etc'
require 'phusion_passenger/constants'

home = Etc.getpwuid(Process.uid).dir
begin
require "#{home}/.passenger/native_support/#{VERSION_STRING}/#{archdir}/native_support.#{libext}"
loaded = true
rescue LoadError
end
end

if !loaded
STDERR.puts "*** Phusion Passenger: no native_support.#{libext} found for " +
"the current Ruby interpreter. Compiling one..."

require 'fileutils'

mkdir = proc do |dir|
begin
STDERR.puts "# mkdir -p #{dir}"
FileUtils.mkdir_p(dir)
rescue Errno::EEXIST
end
end

sh = proc do |*args|
command_string = args.join(' ')
STDERR.puts "# #{command_string}"
if !system(*args)
raise "Could not compile native_support.#{libext} ('#{command_string}' failed)"
end
end

compile = proc do |target_dirs|
result = nil
target_dirs.each_with_index do |target_dir, i|
begin
mkdir.call(target_dir)
File.open("#{target_dir}/.permission_test", "w").close
File.unlink("#{target_dir}/.permission_test")
STDERR.puts "cd #{target_dir}"
Dir.chdir(target_dir) do
extconf_rb = File.join(SOURCE_ROOT, "ext",
"phusion_passenger", "extconf.rb")
sh.call(PlatformInfo::RUBY, extconf_rb)
sh.call("make")
end
result = target_dir
break
rescue Errno::EACCES
# If we encountered a permission error, then try
# the next target directory. If we get a permission
# error on the last one too then propagate the
# exception.
if i == target_dirs.size - 1
raise
else
STDERR.puts "Encountered permission error, " +
"trying a different directory..."
STDERR.puts "-------------------------------"
end
end
end
result
end

target_dir = compile.call([
"#{NATIVE_SUPPORT_DIR}/#{archdir}",
"#{home}/.passenger/native_support/#{VERSION_STRING}/#{archdir}"
])
require "#{target_dir}/native_support.#{libext}"
end
end if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
38 changes: 22 additions & 16 deletions lib/phusion_passenger/platform_info.rb
Expand Up @@ -620,6 +620,27 @@ def self.cpu_architecture
end
memoize :cpu_architecture

def self.ruby_extension_binary_compatibility_ids
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
ruby_ext_version = RUBY_VERSION
if RUBY_PLATFORM =~ /darwin/
if RUBY_PLATFORM =~ /universal/
ruby_arch = "universal"
else
# Something like:
# "/opt/ruby-enterprise/bin/ruby: Mach-O 64-bit executable x86_64"
ruby_arch = `file -L "#{RUBY}"`.strip
ruby_arch.sub!(/.* /, '')
end
elsif RUBY_PLATFORM == "java"
ruby_arch = "java"
else
ruby_arch = cpu_architecture
end
return [ruby_engine, ruby_ext_version, ruby_arch]
end
memoize :ruby_extension_binary_compatibility_ids

# Returns a string that describes the current platform's binary
# compatibility with regard to Phusion Passenger binaries.
# Two systems with the same binary compatibility identifiers
Expand Down Expand Up @@ -661,22 +682,7 @@ def self.cpu_architecture
# compiling a binary with the system's C++ compiler with its default
# options.
def self.passenger_binary_compatibility_identifier
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
ruby_ext_version = RUBY_VERSION
if RUBY_PLATFORM =~ /darwin/
if RUBY_PLATFORM =~ /universal/
ruby_arch = "universal"
else
# Something like:
# "/opt/ruby-enterprise/bin/ruby: Mach-O 64-bit executable x86_64"
ruby_arch = `file -L "#{RUBY}"`.strip
ruby_arch.sub!(/.* /, '')
end
elsif RUBY_PLATFORM == "java"
ruby_arch = "java"
else
ruby_arch = cpu_architecture
end
ruby_engine, ruby_ext_version, ruby_arch = ruby_extension_binary_compatibility_ids

if Config::CONFIG['target_os'] =~ /darwin/ && (sw_vers = find_command('sw_vers'))
# RUBY_PLATFORM gives us the kernel version, but we want
Expand Down

0 comments on commit 45c1e01

Please sign in to comment.