class CommonLibraryBuilder

This file lists all the Phusion Passenger C++ library files and contains code for calculating how to compile and how to link them into executables. It's used by the build system (build/*.rb) and lib/phusion_passenger/standalone/runtime_installer.rb.

Attributes

all_components[R]
output_dir[R]
selected_components[R]

Public Class Methods

new(&block) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 34
def initialize(&block)
        @all_components = {}
        @all_ordered_components = []
        @selected_components = {}
        @namespace = "common"
        if defined?(COMMON_OUTPUT_DIR)
                @output_dir = COMMON_OUTPUT_DIR + "libpassenger_common"
        else
                @output_dir = "."
        end
        instance_eval(&block) if block
end

Public Instance Methods

define_component(object_name, options) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 54
def define_component(object_name, options)
        options[:deps] ||= []
        @all_components[object_name] = options
        @all_ordered_components << object_name
        @selected_components[object_name] = options
end
define_tasks(extra_compiler_flags = nil) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 103
def define_tasks(extra_compiler_flags = nil)
        flags =  "-Iext -Iext/common #{LIBEV_CFLAGS} #{extra_compiler_flags} "
        flags << "#{PlatformInfo.portability_cflags} #{EXTRA_CXXFLAGS}"
        flags.strip!

        group_all_components_by_category.each_pair do |category, object_names|
                define_category_tasks(category, object_names, flags)
        end

        task("#{@namespace}:clean") do
                sh "rm -rf #{@output_dir}"
        end

        return self
end
exclude(*selector) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 65
def exclude(*selector)
        return dup.send(:exclude!, *selector)
end
initialize_copy(other) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 47
def initialize_copy(other)
        [:all_components, :all_ordered_components, :selected_components, :namespace, :output_dir].each do |name|
                var_name = "@#{name}"
                instance_variable_set(var_name, other.instance_variable_get(var_name).dup)
        end
end
only(*selector) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 61
def only(*selector)
        return dup.send(:only!, *selector)
end
set_namespace(namespace) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 69
def set_namespace(namespace)
        return dup.send(:set_namespace!, namespace)
end
set_output_dir(dir) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 73
def set_output_dir(dir)
        return dup.send(:set_output_dir!, dir)
end

Private Instance Methods

aggregate_sources?() click to toggle source
# File lib/phusion_passenger/common_library.rb, line 306
def aggregate_sources?
        # Feature disabled: it's too hard to make it work because
        # lots of executables have to be linked to individual objects
        # anyway.
        return false
end
apply_selector(*selector) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 208
def apply_selector(*selector)
        result = {}
        selector = [selector].flatten
        selector.each do |condition|
                @selected_components.each do |object_name, options|
                        if component_satisfies_condition?(object_name, options, condition)
                                result[object_name] = options
                        end
                end
        end
        return result
end
category_complete?(category) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 244
def category_complete?(category)
        expected = 0
        actual   = 0
        @all_components.each_value do |options|
                if options[:category] == category
                        expected += 1
                end
        end
        @selected_components.each_value do |options|
                if options[:category] == category
                        actual += 1
                end
        end
        return expected == actual
end
component_satisfies_condition?(object_name, options, condition) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 221
def component_satisfies_condition?(object_name, options, condition)
        case condition
        when Symbol
                return condition == :all || options[:category] == condition
        when String
                return object_name == condition
        else
                raise ArgumentError, "Invalid condition #{condition.inspect}"
        end
end
define_category_tasks(category, object_names, flags) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 120
def define_category_tasks(category, object_names, flags)
        object_filenames = object_filenames_for(object_names)

        object_names.each do |object_name|
                options     = @all_components[object_name]
                source_file = "ext/common/#{options[:source]}"
                object_file = "#{@output_dir}/#{object_name}"

                file(object_file => dependencies_for(options)) do
                        ensure_directory_exists(File.dirname(object_file))
                        if source_file =~ /\.c$/
                                compile_c(source_file, "#{flags} -o #{object_file}")
                        else
                                compile_cxx(source_file, "#{flags} -o #{object_file}")
                        end
                end
        end

        task "#{@namespace}:clean" do
                sh "rm -f #{object_filenames.join(' ')}"
        end

        if aggregate_sources?
                aggregate_source = "#{@output_dir}/#{category}.cpp"
                aggregate_object = "#{@output_dir}/#{category}.o"

                file(aggregate_object => dependencies_for(object_names)) do
                        ensure_directory_exists(File.dirname(aggregate_source))
                        ensure_directory_exists(File.dirname(aggregate_object))

                        File.open(aggregate_source, "w") do |f|
                                f.puts %q{
                                        #ifndef _GNU_SOURCE
                                                #define _GNU_SOURCE
                                        #endif
                                }
                                object_names.each do |object_name|
                                        options = @all_components[object_name]
                                        source_file = options[:source].sub(%r(^ext/common), '')
                                        f.puts "#include \"#{source_file}\""
                                end
                        end

                        compile_cxx(aggregate_source, "#{flags} -o #{aggregate_object}")
                end

                task "#{@namespace}:clean" do
                        sh "rm -f #{aggregate_source} #{aggregate_object}"
                end
        elsif false
                # Feature disabled: we don't want to waste too much space when
                # packaging the runtime ('passenger package-runtime') so we
                # never generate static libraries.
                library = "#{@output_dir}/#{category}.a"
                
                file(library => object_filenames) do
                        create_static_library(library, object_filenames.join(' '))
                end

                task "#{@namespace}:clean" do
                        sh "rm -f #{library}"
                end
        end
end
dependencies_for(component_options_or_object_names) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 270
def dependencies_for(component_options_or_object_names)
        result = nil
        case component_options_or_object_names
        when Hash
                component_options = component_options_or_object_names
                result = ["ext/common/#{component_options[:source]}"]
                component_options[:deps].each do |dependency|
                        result << "ext/common/#{dependency}"
                end
        when Array
                result = []
                object_names = component_options_or_object_names
                object_names.each do |object_name|
                        options = @all_components[object_name]
                        result.concat(dependencies_for(options))
                end
                result.uniq!
        end
        return result
end
ensure_directory_exists(dir) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 232
def ensure_directory_exists(dir)
        sh("mkdir -p #{dir}") if !File.directory?(dir)
end
exclude!(*selector) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 201
def exclude!(*selector)
        apply_selector(*selector).each_key do |object_name|
                @selected_components.delete(object_name)
        end
        return self
end
group_all_components_by_category() click to toggle source
# File lib/phusion_passenger/common_library.rb, line 295
def group_all_components_by_category
        categories = {}
        @all_ordered_components.each do |object_name|
                options  = @all_components[object_name]
                category = options[:category]
                categories[category] ||= []
                categories[category] << object_name
        end
        return categories
end
object_filenames_for(object_names) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 291
def object_filenames_for(object_names)
        return object_names.map { |name| "#{@output_dir}/#{name}" }
end
only!(*selector) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 195
def only!(*selector)
        new_components = apply_selector(*selector)
        @selected_components = new_components
        return self
end
selected_categories() click to toggle source
# File lib/phusion_passenger/common_library.rb, line 236
def selected_categories
        categories = {}
        @selected_components.each_value do |options|
                categories[options[:category]] = true
        end
        return categories.keys
end
selected_objects_beloging_to_category(category) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 260
def selected_objects_beloging_to_category(category)
        result = []
        @selected_components.each_pair do |object_name, options|
                if options[:category] == category
                        result << object_name
                end
        end
        return result
end
set_namespace!(namespace) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 185
def set_namespace!(namespace)
        @namespace = namespace
        return self
end
set_output_dir!(dir) click to toggle source
# File lib/phusion_passenger/common_library.rb, line 190
def set_output_dir!(dir)
        @output_dir = dir
        return self
end