# Phusion Passenger - https://www.phusionpassenger.com/
# Copyright (c) 2010 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 'pathname'
# Provides useful extensions for Rake.
module RakeExtensions
# Allows one to define Rake rules in the context of the given
# subdirectory. For example,
#
# subdir 'foo' do
# file 'libfoo.so' => ['foo.c'] do
# sh 'gcc foo.c -shared -fPIC -o libfoo.so'
# end
# end
#
# subdir 'bar' do
# file 'bar' => ['bar.c', '../foo/libfoo.so'] do
# sh 'gcc bar.c -o bar -L../foo -lfoo'
# end
# end
#
# is equivalent to:
#
# file 'foo/libfoo.so' => ['foo/foo.c'] do
# Dir.chdir('foo') do
# sh 'gcc foo.c -shared -fPIC -o libfoo.so'
# end
# end
#
# file 'bar/bar' => ['bar/bar.c', 'foo/libfoo.so'] do
# Dir.chdir('bar') do
# sh 'gcc bar.c -o bar -L../foo -lfoo'
# end
# end
#
# === String dependencies are assumed to be filenames
#
# But be careful with string dependencies. They are assumed to be filenames,
# and will be automatically converted. For example:
#
# subdir 'foo' do
# task 'super_app' => ['super_app:compile', 'super_app:unit_test']
#
# task 'super_app:compile' do
# ...
# end
#
# task 'super_app:unit_test' do
# ...
# end
# end
#
# will be treated like:
#
# subdir 'foo' do
# # !!!!!!!
# task 'super_app' => ['foo/super_app:compile', 'foo/super_app:unit_test']
#
# task 'super_app:compile' do
# ...
# end
#
# task 'super_app:unit_test' do
# ...
# end
# end
#
# To solve this, declare your dependencies as symbols:
#
# task 'super_app' => [:'super_app:compile', :'super_app:unit_test']
#
# (note the leading ':' character)
#
# === Supported Rake commands
#
# Only the file and target Rake commands are supported.
def subdir(dir, &block)
subdir = Subdir.new(dir)
Dir.chdir(dir) do
subdir.instance_eval(&block)
end
end
class Subdir # :nodoc:
# Rake 0.9 compatibility since methods like task and desc
# aren't available in Object anymore.
# See: https://github.com/jimweirich/rake/issues/33#issuecomment-1213705
include Rake::DSL if defined?(Rake::DSL)
def initialize(dir)
@dir = dir
@toplevel_dir = Pathname.getwd
end
def file(args, &block)
case args
when String
args = mangle_path(args)
when Hash
target = mangle_path(args.keys[0])
sources = mangle_path_or_path_array(args.values[0])
args = { target => sources }
end
Rake::FileTask.define_task(args) do
puts "### In #{@dir}:"
Dir.chdir(@dir) do
Object.class_eval(&block)
end
puts ""
end
end
def task(*args, &block)
if !args.empty? && args[0].is_a?(Hash)
target = args[0].keys[0]
sources = mangle_path_or_path_array(args[0].values[0])
args[0] = { target => sources }
end
if block_given?
Rake::Task.define_task(*args) do
puts "### In #{@dir}:"
Dir.chdir(@dir) do
Object.class_eval(&block)
end
puts ""
end
else
Rake::Task.define_task(*args)
end
end
private
def mangle_path(path)
path = File.expand_path(path)
return Pathname.new(path).relative_path_from(@toplevel_dir).to_s
end
def mangle_path_array(array)
array = array.dup
array.each_with_index do |item, i|
if item.is_a?(String)
array[i] = mangle_path(item)
end
end
return array
end
def mangle_path_or_path_array(item)
case item
when String
return mangle_path(item)
when Array
return mangle_path_array(item)
else
return item
end
end
end
end # module RakeExtensions
Object.class_eval do
include RakeExtensions
end