# Phusion Passenger - https://www.phusionpassenger.com/ # Copyright (c) 2010, 2011, 2012 Phusion # # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'rbconfig' require 'phusion_passenger' require 'phusion_passenger/packaging' require 'phusion_passenger/platform_info' require 'phusion_passenger/platform_info/apache' require 'phusion_passenger/platform_info/ruby' require 'phusion_passenger/platform_info/linux' require 'phusion_passenger/platform_info/curl' module PhusionPassenger # Represents a dependency software that Passenger requires. It's used by the # installer to check whether all dependencies are available. A Dependency object # contains full information about a dependency, such as its name, code for # detecting whether it is installed, and installation instructions for the # current platform. class Dependency # :nodoc: all [:name, :install_command, :install_instructions, :install_comments, :website, :website_comments, :provides].each do |attr_name| attr_writer attr_name define_method(attr_name) do call_init_block return instance_variable_get("@#{attr_name}") end end def initialize(&block) @included_by = [] @init_block = block end def define_checker(&block) @checker = block end def check call_init_block result = Result.new @checker.call(result) return result end private class Result def found(*args) if args.empty? @found = true else @found = args.first end end def not_found found(false) end def found? return !@found.nil? && @found end def found_at if @found.is_a?(TrueClass) || @found.is_a?(FalseClass) return nil else return @found end end end def call_init_block if @init_block init_block = @init_block @init_block = nil init_block.call(self) end end end # Namespace which contains the different dependencies that Passenger may require. # See Dependency for more information. module Dependencies # :nodoc: all # Returns whether fastthread is a required dependency for the current # Ruby interpreter. def self.fastthread_required? return (!defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby") && RUBY_VERSION < "1.8.7" end # Returns whether Mizuho is required in order to be able to package all files # in the packaging list. def self.mizuho_required? return Packaging::ASCII_DOCS.any? do |fn| !File.exist?("#{PhusionPassenger.doc_dir}/#{fn}") end end GCC = Dependency.new do |dep| dep.name = "GNU C++ compiler" dep.define_checker do |result| gxx = PlatformInfo.find_command('g++') if gxx.nil? result.not_found else result.found(gxx) end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install build-essential" elsif tags.include?(:mandriva) dep.install_command = "urpmi gcc-c++" elsif tags.include?(:redhat) dep.install_command = "yum install gcc-c++" elsif tags.include?(:gentoo) dep.install_command = "emerge -av gcc" end elsif RUBY_PLATFORM =~ /darwin/ dep.install_instructions = "Please install the Apple Development Tools: http://developer.apple.com/tools/" end dep.website = "http://gcc.gnu.org/" end Make = Dependency.new do |dep| dep.name = "The 'make' tool" dep.define_checker do |result| make = PlatformInfo.find_command('make') if make result.found(make) else result.not_found end end if RUBY_PLATFORM =~ /linux/ case PlatformInfo.linux_distro when :ubuntu, :debian dep.install_command = "apt-get install build-essential" when :rhel, :fedora, :centos dep.install_command = "yum install make" end elsif RUBY_PLATFORM =~ /darwin/ dep.install_instructions = "Please install the Apple Development Tools: http://developer.apple.com/tools/" end dep.website = "http://www.gnu.org/software/make/" end GnuMake = Dependency.new do |dep| dep.name = "GNU make" dep.define_checker do |result| make = PlatformInfo.gnu_make if make result.found(make) else result.not_found end end if RUBY_PLATFORM =~ /linux/ case PlatformInfo.linux_distro when :ubuntu, :debian dep.install_command = "apt-get install build-essential" when :rhel, :fedora, :centos dep.install_command = "yum install make" end elsif RUBY_PLATFORM =~ /darwin/ dep.install_instructions = "Please install the Apple Development Tools: http://developer.apple.com/tools/" end dep.website = "http://www.gnu.org/software/make/" end DownloadTool = Dependency.new do |dep| dep.name = "A download tool like 'wget' or 'curl'" dep.define_checker do |result| tool = PlatformInfo.find_command('wget') if tool result.found(tool) else tool = PlatformInfo.find_command('curl') if tool result.found(tool) else result.not_found end end end if RUBY_PLATFORM =~ /linux/ case PlatformInfo.linux_distro when :ubuntu, :debian dep.install_command = "apt-get install wget curl" when :rhel, :fedora, :centos dep.install_command = "yum install wget curl" end else dep.install_instructions = "Please install either wget (http://www.gnu.org/software/wget/) or curl (http://curl.haxx.se/)." end end Ruby_DevHeaders = Dependency.new do |dep| dep.name = "Ruby development headers" dep.define_checker do |result| require 'rbconfig' begin require 'mkmf' if defined?(::RbConfig) config = ::RbConfig::CONFIG else config = ::Config::CONFIG end header_dir = config['rubyhdrdir'] || config['archdir'] result.found(File.exist?("#{header_dir}/ruby.h")) rescue LoadError, SystemExit # On RedHat/Fedora/CentOS, if ruby-devel is not installed then # mkmf.rb will print an error and call 'exit'. So here we # catch SystemExit. result.not_found end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install ruby1.8-dev" elsif tags.include?(:mandriva) dep.install_command = "urpmi urpmi ruby-RubyGems" elsif tags.include?(:redhat) dep.install_command = "yum install ruby-devel" elsif tags.include?(:gentoo) dep.install_command = "emerge -av ruby" end elsif RUBY_PLATFORM =~ /freebsd/ dep.install_command = "make -C /usr/ports/lang/ruby18 install" end dep.website = "http://www.ruby-lang.org/" dep.install_instructions = "Please reinstall Ruby by downloading it from #{dep.website}" end Ruby_OpenSSL = Dependency.new do |dep| dep.name = "OpenSSL support for Ruby" dep.define_checker do |result| begin require 'openssl' result.found rescue LoadError result.not_found end end if RUBY_PLATFORM =~ /linux/ case PlatformInfo.linux_distro when :ubuntu, :debian dep.install_command = "apt-get install libopenssl-ruby" end end if dep.install_command.nil? dep.website = "http://www.ruby-lang.org/" dep.install_instructions = "Please (re)install Ruby with OpenSSL " << "support by downloading it from #{dep.website}." end end RubyGems = Dependency.new do |dep| dep.name = "RubyGems" dep.define_checker do |result| begin require 'rubygems' result.found rescue LoadError result.not_found end end dep.website = "http://www.rubygems.org/" dep.install_instructions = "Please download it from #{dep.website}. " << "Extract the tarball, and run ruby setup.rb" end Rake = Dependency.new do |dep| dep.name = "Rake" dep.define_checker do |result| if PlatformInfo.rake.nil? result.not_found else result.found(PlatformInfo.rake) end end dep.website = "http://rake.rubyforge.org/" dep.install_instructions = "Please install RubyGems first, then run #{PlatformInfo.gem_command || "gem"} install rake" end Apache2 = Dependency.new do |dep| dep.name = "Apache 2" dep.define_checker do |result| if PlatformInfo.httpd.nil? result.not_found else result.found(PlatformInfo.httpd) end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install apache2-mpm-prefork" elsif tags.include?(:mandriva) dep.install_command = "urpmi apache" elsif tags.include?(:redhat) dep.install_command = "yum install httpd" elsif tags.include?(:gentoo) dep.install_command = "emerge -av apache" end elsif RUBY_PLATFORM =~ /freebsd/ dep.install_command = "make -C /usr/ports/www/apache22 install" dep.provides = [Apache2_DevHeaders, APR_DevHeaders, APU_DevHeaders] end dep.website = "http://httpd.apache.org/" end Apache2_DevHeaders = Dependency.new do |dep| dep.name = "Apache 2 development headers" dep.define_checker do |result| if PlatformInfo.apxs2.nil? result.not_found else result.found(PlatformInfo.apxs2) end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install apache2-prefork-dev" dep.provides = [Apache2] elsif tags.include?(:mandriva) dep.install_command = "urpmi apache-devel" dep.provides = [Apache2] elsif tags.include?(:redhat) dep.install_command = "yum install httpd-devel" dep.provides = [Apache2] elsif tags.include?(:gentoo) dep.install_command = "emerge -av apache" dep.provides = [Apache2] end elsif RUBY_PLATFORM =~ /freebsd/ dep.install_command = "make -C /usr/ports/www/apache22 install" end dep.website = "http://httpd.apache.org/" end APR_DevHeaders = Dependency.new do |dep| dep.name = "Apache Portable Runtime (APR) development headers" dep.define_checker do |result| if PlatformInfo.apr_config.nil? result.not_found else result.found(PlatformInfo.apr_config) end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install libapr1-dev" elsif tags.include?(:mandriva) dep.install_command = "urpmi libapr-devel" elsif tags.include?(:redhat) dep.install_command = "yum install apr-devel" elsif tags.include?(:gentoo) dep.install_command = "emerge -av apr" end elsif RUBY_PLATFORM =~ /darwin/ dep.install_instructions = "Please install Apache from MacPorts, which will " << "provide APR automatically. Or, if you're installing against MacOS X's " << "default provided Apache, then please install the OS X Developer SDK." end dep.website = "http://httpd.apache.org/" dep.website_comments = "APR is an integrated part of Apache." end APU_DevHeaders = Dependency.new do |dep| dep.name = "Apache Portable Runtime Utility (APU) development headers" dep.define_checker do |result| if PlatformInfo.apu_config.nil? result.not_found else result.found(PlatformInfo.apu_config) end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install libaprutil1-dev" elsif tags.include?(:mandriva) dep.install_command = "urpmi libapr-util-devel" elsif tags.include?(:redhat) dep.install_command = "yum install apr-util-devel" end elsif RUBY_PLATFORM =~ /darwin/ dep.install_instructions = "Please install Apache from MacPorts, which will " << "provide APU automatically. Or, if you're installing against MacOS X's " << "default provided Apache, then please install the OS X Developer SDK." end dep.website = "http://httpd.apache.org/" dep.website_comments = "APR Utility is an integrated part of Apache." end FastThread = Dependency.new do |dep| dep.name = "fastthread" dep.define_checker do |result| begin begin require 'rubygems' rescue LoadError end require 'fastthread' result.found rescue LoadError result.not_found end end dep.install_instructions = "Please install RubyGems first, then run #{PlatformInfo.gem_command || "gem"} install fastthread" end Rack = Dependency.new do |dep| dep.name = "rack" dep.define_checker do |result| begin begin require 'rubygems' rescue LoadError end require 'rack' result.found rescue LoadError result.not_found end end dep.install_instructions = "Please install RubyGems first, then run #{PlatformInfo.gem_command || "gem"} install rack" end Curl_Dev = Dependency.new do |dep| dep.name = "Curl development headers with SSL support" dep.define_checker do |result| source_file = "#{PlatformInfo.tmpexedir}/passenger-curl-check.c" output_file = "#{PlatformInfo.tmpexedir}/passenger-curl-check" begin found = true File.open(source_file, 'w') do |f| f.puts("#include ") f.puts("int main() {") f.puts(" curl_global_init(CURL_GLOBAL_ALL);") f.puts(" return 0;") f.puts("}") end Dir.chdir(File.dirname(source_file)) do command = "(gcc #{ENV['CFLAGS']} " + "-o '#{output_file}' '#{source_file}' " + "#{PlatformInfo.curl_flags} #{PlatformInfo.curl_libs}) " + ">/dev/null 2>/dev/null" if !system(command) found = false end end if found && !PlatformInfo.curl_supports_ssl? dep.install_comments = "Curl was found, but it doesn't support SSL." found = false end result.found(found) ensure File.unlink(source_file) rescue nil File.unlink(output_file) rescue nil end end dep.install_instructions = "Please download Curl from http://curl.haxx.se/libcurl " + "and make sure you install it with SSL support." if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_instructions = "Please run " + "apt-get install libcurl4-openssl-dev " + "or libcurl4-gnutls-dev, whichever you prefer." elsif tags.include?(:redhat) begin release = File.read("/etc/redhat-release") rescue release = nil end if release =~ /release 4/ # http://code.google.com/p/phusion-passenger/issues/detail?id=554 dep.install_command = "yum install zlib-devel e2fsprogs-devel krb5-devel libidn-devel" else dep.install_command = "yum install curl-devel" end end end end OpenSSL_Dev = Dependency.new do |dep| dep.name = "OpenSSL development headers" dep.define_checker do |result| source_file = "#{PlatformInfo.tmpexedir}/passenger-openssl-check.c" object_file = "#{PlatformInfo.tmpexedir}/passenger-openssl-check.o" begin File.open(source_file, 'w') do |f| f.write("#include ") end Dir.chdir(File.dirname(source_file)) do if system("(gcc #{ENV['CFLAGS']} -c '#{source_file}') >/dev/null 2>/dev/null") result.found else result.not_found end end ensure File.unlink(source_file) rescue nil File.unlink(object_file) rescue nil end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install libssl-dev" elsif tags.include?(:redhat) dep.install_command = "yum install openssl-devel" end end dep.website = "http://www.openssl.org/" end Zlib_Dev = Dependency.new do |dep| dep.name = "Zlib development headers" dep.define_checker do |result| source_file = "#{PlatformInfo.tmpexedir}/zlib-check.c" object_file = "#{PlatformInfo.tmpexedir}/zlib-check.o" begin File.open(source_file, 'w') do |f| f.write("#include ") end Dir.chdir(File.dirname(source_file)) do if system("(g++ -c zlib-check.c) >/dev/null 2>/dev/null") result.found else result.not_found end end ensure File.unlink(source_file) rescue nil File.unlink(object_file) rescue nil end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install zlib1g-dev" elsif tags.include?(:mandriva) dep.install_command = "urpmi zlib1-devel" elsif tags.include?(:redhat) dep.install_command = "yum install zlib-devel" end end dep.website = "http://www.zlib.net/" end PCRE_Dev = Dependency.new do |dep| dep.name = "PCRE development headers" dep.define_checker do |result| source_file = "#{PlatformInfo.tmpexedir}/pcre-check.c" object_file = "#{PlatformInfo.tmpexedir}/pcre-check.o" begin File.open(source_file, 'w') do |f| f.write("#include ") end Dir.chdir(File.dirname(source_file)) do if system("(g++ -c pcre-check.c) >/dev/null 2>/dev/null") result.found else result.not_found end end ensure File.unlink(source_file) rescue nil File.unlink(object_file) rescue nil end end if RUBY_PLATFORM =~ /linux/ tags = PlatformInfo.linux_distro_tags if tags.include?(:debian) dep.install_command = "apt-get install libpcre3-dev" end end dep.website = "http://www.pcre.org/" end Daemon_Controller = Dependency.new do |dep| dep.name = "daemon_controller >= 1.1.0" dep.install_instructions = "Please install RubyGems first, then run " << "#{PlatformInfo.gem_command || "gem"} install daemon_controller" dep.define_checker do |result| begin begin require 'rubygems' rescue LoadError end require 'daemon_controller' begin require 'daemon_controller/version' too_old = DaemonController::VERSION_STRING < '1.1.0' rescue LoadError too_old = true end if too_old result.not_found dep.install_instructions = "Your version of daemon_controller is too old. " << "Please upgrade with the following commands:\n" << " #{PlatformInfo.gem_command || "gem"} uninstall FooBarWidget-daemon_controller\n" << " #{PlatformInfo.gem_command || "gem"} install daemon_controller" else result.found end rescue LoadError result.not_found end end end Mizuho = Dependency.new do |dep| dep.name = "Mizuho" dep.define_checker do |result| mizuho = PlatformInfo.find_command('mizuho') if mizuho.nil? result.not_found else result.found(mizuho) end end dep.website = "http://github.com/FooBarWidget/mizuho" dep.install_instructions = "Please install RubyGems first, then run #{PlatformInfo.gem_command || "gem"} install mizuho" end end end # module PhusionPassenger