1# Rake DSL functions.
2require 'rake/file_utils_ext'
3
4module Rake
5
6  ##
7  # DSL is a module that provides #task, #desc, #namespace, etc.  Use this
8  # when you'd like to use rake outside the top level scope.
9
10  module DSL
11
12    #--
13    # Include the FileUtils file manipulation functions in the top
14    # level module, but mark them private so that they don't
15    # unintentionally define methods on other objects.
16    #++
17
18    include FileUtilsExt
19    private(*FileUtils.instance_methods(false))
20    private(*FileUtilsExt.instance_methods(false))
21
22    private
23
24    # Declare a basic task.
25    #
26    # Example:
27    #   task :clobber => [:clean] do
28    #     rm_rf "html"
29    #   end
30    #
31    def task(*args, &block)
32      Rake::Task.define_task(*args, &block)
33    end
34
35
36    # Declare a file task.
37    #
38    # Example:
39    #   file "config.cfg" => ["config.template"] do
40    #     open("config.cfg", "w") do |outfile|
41    #       open("config.template") do |infile|
42    #         while line = infile.gets
43    #           outfile.puts line
44    #         end
45    #       end
46    #     end
47    #  end
48    #
49    def file(*args, &block)
50      Rake::FileTask.define_task(*args, &block)
51    end
52
53    # Declare a file creation task.
54    # (Mainly used for the directory command).
55    def file_create(*args, &block)
56      Rake::FileCreationTask.define_task(*args, &block)
57    end
58
59    # Declare a set of files tasks to create the given directories on
60    # demand.
61    #
62    # Example:
63    #   directory "testdata/doc"
64    #
65    def directory(*args, &block)
66      result = file_create(*args, &block)
67      dir, _ = *Rake.application.resolve_args(args)
68      Rake.each_dir_parent(dir) do |d|
69        file_create d do |t|
70          mkdir_p t.name if ! File.exist?(t.name)
71        end
72      end
73      result
74    end
75
76    # Declare a task that performs its prerequisites in
77    # parallel. Multitasks does *not* guarantee that its prerequisites
78    # will execute in any given order (which is obvious when you think
79    # about it)
80    #
81    # Example:
82    #   multitask :deploy => [:deploy_gem, :deploy_rdoc]
83    #
84    def multitask(*args, &block)
85      Rake::MultiTask.define_task(*args, &block)
86    end
87
88    # Create a new rake namespace and use it for evaluating the given
89    # block.  Returns a NameSpace object that can be used to lookup
90    # tasks defined in the namespace.
91    #
92    # E.g.
93    #
94    #   ns = namespace "nested" do
95    #     task :run
96    #   end
97    #   task_run = ns[:run] # find :run in the given namespace.
98    #
99    def namespace(name=nil, &block)
100      name = name.to_s if name.kind_of?(Symbol)
101      name = name.to_str if name.respond_to?(:to_str)
102      unless name.kind_of?(String) || name.nil?
103        raise ArgumentError, "Expected a String or Symbol for a namespace name"
104      end
105      Rake.application.in_namespace(name, &block)
106    end
107
108    # Declare a rule for auto-tasks.
109    #
110    # Example:
111    #  rule '.o' => '.c' do |t|
112    #    sh %{cc -o #{t.name} #{t.source}}
113    #  end
114    #
115    def rule(*args, &block)
116      Rake::Task.create_rule(*args, &block)
117    end
118
119    # Describe the next rake task.
120    #
121    # Example:
122    #   desc "Run the Unit Tests"
123    #   task :test => [:build]
124    #     runtests
125    #   end
126    #
127    def desc(description)
128      Rake.application.last_description = description
129    end
130
131    # Import the partial Rakefiles +fn+.  Imported files are loaded
132    # _after_ the current file is completely loaded.  This allows the
133    # import statement to appear anywhere in the importing file, and yet
134    # allowing the imported files to depend on objects defined in the
135    # importing file.
136    #
137    # A common use of the import statement is to include files
138    # containing dependency declarations.
139    #
140    # See also the --rakelibdir command line option.
141    #
142    # Example:
143    #   import ".depend", "my_rules"
144    #
145    def import(*fns)
146      fns.each do |fn|
147        Rake.application.add_import(fn)
148      end
149    end
150
151  end
152
153  DeprecatedCommands = Object.new.extend(DSL)
154
155  module DeprecatedObjectDSL # :nodoc:
156    DSL.private_instance_methods(false).each do |name|
157      line = __LINE__+1
158      class_eval %{
159        def #{name}(*args, &block)
160          unless Rake.application.options.ignore_deprecate
161            unless @rake_dsl_warning
162              $stderr.puts "WARNING: Global access to Rake DSL methods is deprecated.  Please include"
163              $stderr.puts "    ...  Rake::DSL into classes and modules which use the Rake DSL methods."
164              @rake_dsl_warning = true
165            end
166            $stderr.puts "WARNING: DSL method \#{self.class}##{name} called at \#{caller.first}"
167          end
168          Rake::DeprecatedCommands.send(:#{name}, *args, &block)
169        end
170        private :#{name}
171      }, __FILE__, line
172    end
173  end unless defined? Rake::REDUCE_COMPAT
174
175  extend FileUtilsExt
176end
177
178# Extend the main object with the DSL commands. This allows top-level
179# calls to task, etc. to work from a Rakefile without polluting the
180# object inheritance tree.
181self.extend Rake::DSL
182include Rake::DeprecatedObjectDSL unless defined? Rake::REDUCE_COMPAT
183