assaf-buildr 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. data/CHANGELOG +887 -0
  2. data/DISCLAIMER +7 -0
  3. data/LICENSE +176 -0
  4. data/NOTICE +26 -0
  5. data/README.rdoc +146 -0
  6. data/Rakefile +62 -0
  7. data/_buildr +38 -0
  8. data/addon/buildr/antlr.rb +65 -0
  9. data/addon/buildr/cobertura.rb +236 -0
  10. data/addon/buildr/emma.rb +238 -0
  11. data/addon/buildr/hibernate.rb +142 -0
  12. data/addon/buildr/javacc.rb +85 -0
  13. data/addon/buildr/jdepend.rb +60 -0
  14. data/addon/buildr/jetty.rb +248 -0
  15. data/addon/buildr/jibx.rb +86 -0
  16. data/addon/buildr/nailgun.rb +817 -0
  17. data/addon/buildr/openjpa.rb +90 -0
  18. data/addon/buildr/org/apache/buildr/BuildrNail$Main.class +0 -0
  19. data/addon/buildr/org/apache/buildr/BuildrNail.class +0 -0
  20. data/addon/buildr/org/apache/buildr/BuildrNail.java +41 -0
  21. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  22. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  23. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  24. data/addon/buildr/org/apache/buildr/JettyWrapper.java +144 -0
  25. data/addon/buildr/xmlbeans.rb +93 -0
  26. data/bin/buildr +28 -0
  27. data/buildr.buildfile +53 -0
  28. data/buildr.gemspec +58 -0
  29. data/doc/css/default.css +228 -0
  30. data/doc/css/print.css +100 -0
  31. data/doc/css/syntax.css +52 -0
  32. data/doc/images/apache-incubator-logo.png +0 -0
  33. data/doc/images/buildr-hires.png +0 -0
  34. data/doc/images/buildr.png +0 -0
  35. data/doc/images/favicon.png +0 -0
  36. data/doc/images/growl-icon.tiff +0 -0
  37. data/doc/images/note.png +0 -0
  38. data/doc/images/project-structure.png +0 -0
  39. data/doc/images/tip.png +0 -0
  40. data/doc/images/zbuildr.tif +0 -0
  41. data/doc/pages/artifacts.textile +207 -0
  42. data/doc/pages/building.textile +240 -0
  43. data/doc/pages/contributing.textile +208 -0
  44. data/doc/pages/download.textile +62 -0
  45. data/doc/pages/extending.textile +175 -0
  46. data/doc/pages/getting_started.textile +273 -0
  47. data/doc/pages/index.textile +42 -0
  48. data/doc/pages/languages.textile +407 -0
  49. data/doc/pages/mailing_lists.textile +17 -0
  50. data/doc/pages/more_stuff.textile +286 -0
  51. data/doc/pages/packaging.textile +427 -0
  52. data/doc/pages/projects.textile +274 -0
  53. data/doc/pages/recipes.textile +103 -0
  54. data/doc/pages/settings_profiles.textile +274 -0
  55. data/doc/pages/testing.textile +212 -0
  56. data/doc/pages/troubleshooting.textile +103 -0
  57. data/doc/pages/whats_new.textile +323 -0
  58. data/doc/print.haml +51 -0
  59. data/doc/print.toc.yaml +29 -0
  60. data/doc/scripts/buildr-git.rb +412 -0
  61. data/doc/scripts/install-jruby.sh +44 -0
  62. data/doc/scripts/install-linux.sh +64 -0
  63. data/doc/scripts/install-osx.sh +52 -0
  64. data/doc/site.haml +56 -0
  65. data/doc/site.toc.yaml +47 -0
  66. data/etc/KEYS +151 -0
  67. data/etc/git-svn-authors +16 -0
  68. data/lib/buildr.rb +35 -0
  69. data/lib/buildr/core.rb +27 -0
  70. data/lib/buildr/core/application.rb +489 -0
  71. data/lib/buildr/core/application_cli.rb +139 -0
  72. data/lib/buildr/core/build.rb +311 -0
  73. data/lib/buildr/core/checks.rb +382 -0
  74. data/lib/buildr/core/common.rb +154 -0
  75. data/lib/buildr/core/compile.rb +596 -0
  76. data/lib/buildr/core/environment.rb +120 -0
  77. data/lib/buildr/core/filter.rb +362 -0
  78. data/lib/buildr/core/generate.rb +195 -0
  79. data/lib/buildr/core/help.rb +118 -0
  80. data/lib/buildr/core/progressbar.rb +156 -0
  81. data/lib/buildr/core/project.rb +892 -0
  82. data/lib/buildr/core/test.rb +715 -0
  83. data/lib/buildr/core/transports.rb +558 -0
  84. data/lib/buildr/core/util.rb +289 -0
  85. data/lib/buildr/groovy.rb +18 -0
  86. data/lib/buildr/groovy/bdd.rb +105 -0
  87. data/lib/buildr/groovy/compiler.rb +138 -0
  88. data/lib/buildr/ide.rb +19 -0
  89. data/lib/buildr/ide/eclipse.rb +212 -0
  90. data/lib/buildr/ide/idea.ipr.template +300 -0
  91. data/lib/buildr/ide/idea.rb +189 -0
  92. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  93. data/lib/buildr/ide/idea7x.rb +210 -0
  94. data/lib/buildr/java.rb +23 -0
  95. data/lib/buildr/java/ant.rb +92 -0
  96. data/lib/buildr/java/bdd.rb +449 -0
  97. data/lib/buildr/java/commands.rb +211 -0
  98. data/lib/buildr/java/compiler.rb +348 -0
  99. data/lib/buildr/java/deprecated.rb +141 -0
  100. data/lib/buildr/java/jruby.rb +117 -0
  101. data/lib/buildr/java/jtestr_runner.rb.erb +116 -0
  102. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  103. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +119 -0
  104. data/lib/buildr/java/packaging.rb +713 -0
  105. data/lib/buildr/java/pom.rb +178 -0
  106. data/lib/buildr/java/rjb.rb +155 -0
  107. data/lib/buildr/java/test_result.rb +308 -0
  108. data/lib/buildr/java/tests.rb +324 -0
  109. data/lib/buildr/java/version_requirement.rb +172 -0
  110. data/lib/buildr/packaging.rb +21 -0
  111. data/lib/buildr/packaging/artifact.rb +730 -0
  112. data/lib/buildr/packaging/artifact_namespace.rb +972 -0
  113. data/lib/buildr/packaging/artifact_search.rb +140 -0
  114. data/lib/buildr/packaging/gems.rb +102 -0
  115. data/lib/buildr/packaging/package.rb +233 -0
  116. data/lib/buildr/packaging/tar.rb +104 -0
  117. data/lib/buildr/packaging/zip.rb +722 -0
  118. data/lib/buildr/resources/buildr.icns +0 -0
  119. data/lib/buildr/scala.rb +19 -0
  120. data/lib/buildr/scala/compiler.rb +109 -0
  121. data/lib/buildr/scala/tests.rb +203 -0
  122. data/rakelib/apache.rake +191 -0
  123. data/rakelib/changelog.rake +57 -0
  124. data/rakelib/doc.rake +103 -0
  125. data/rakelib/package.rake +73 -0
  126. data/rakelib/release.rake +65 -0
  127. data/rakelib/rspec.rake +83 -0
  128. data/rakelib/rubyforge.rake +53 -0
  129. data/rakelib/scm.rake +49 -0
  130. data/rakelib/setup.rake +86 -0
  131. data/rakelib/stage.rake +48 -0
  132. data/spec/addon/cobertura_spec.rb +77 -0
  133. data/spec/addon/emma_spec.rb +120 -0
  134. data/spec/addon/test_coverage_spec.rb +255 -0
  135. data/spec/core/application_spec.rb +412 -0
  136. data/spec/core/artifact_namespace_spec.rb +646 -0
  137. data/spec/core/build_spec.rb +415 -0
  138. data/spec/core/checks_spec.rb +537 -0
  139. data/spec/core/common_spec.rb +664 -0
  140. data/spec/core/compile_spec.rb +566 -0
  141. data/spec/core/generate_spec.rb +33 -0
  142. data/spec/core/project_spec.rb +754 -0
  143. data/spec/core/test_spec.rb +1091 -0
  144. data/spec/core/transport_spec.rb +500 -0
  145. data/spec/groovy/bdd_spec.rb +80 -0
  146. data/spec/groovy/compiler_spec.rb +239 -0
  147. data/spec/ide/eclipse_spec.rb +243 -0
  148. data/spec/java/ant.rb +28 -0
  149. data/spec/java/bdd_spec.rb +358 -0
  150. data/spec/java/compiler_spec.rb +446 -0
  151. data/spec/java/java_spec.rb +88 -0
  152. data/spec/java/packaging_spec.rb +1103 -0
  153. data/spec/java/tests_spec.rb +466 -0
  154. data/spec/packaging/archive_spec.rb +503 -0
  155. data/spec/packaging/artifact_spec.rb +754 -0
  156. data/spec/packaging/packaging_helper.rb +63 -0
  157. data/spec/packaging/packaging_spec.rb +589 -0
  158. data/spec/sandbox.rb +137 -0
  159. data/spec/scala/compiler_spec.rb +228 -0
  160. data/spec/scala/tests_spec.rb +215 -0
  161. data/spec/spec_helpers.rb +304 -0
  162. data/spec/version_requirement_spec.rb +123 -0
  163. metadata +369 -0
@@ -0,0 +1,154 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+
17
+ require 'rake'
18
+ require 'tempfile'
19
+ require 'open-uri'
20
+ $LOADED_FEATURES << 'rubygems/open-uri.rb' # avoid loading rubygems' open-uri
21
+ require 'buildr/core/util'
22
+ require 'buildr/core/transports'
23
+
24
+
25
+ module Buildr
26
+
27
+ # :call-seq:
28
+ # struct(hash) => Struct
29
+ #
30
+ # Convenience method for creating an anonymous Struct.
31
+ #
32
+ # For example:
33
+ # COMMONS = struct(
34
+ # :collections =>'commons-collections:commons-collections:jar:3.1',
35
+ # :lang =>'commons-lang:commons-lang:jar:2.1',
36
+ # :logging =>'commons-logging:commons-logging:jar:1.0.3',
37
+ # )
38
+ #
39
+ # compile.with COMMONS.logging
40
+ def struct(hash)
41
+ Struct.new(nil, *hash.keys).new(*hash.values)
42
+ end
43
+
44
+ # :call-seq:
45
+ # write(name, content)
46
+ # write(name) { ... }
47
+ #
48
+ # Write the contents into a file. The second form calls the block and writes the result.
49
+ #
50
+ # For example:
51
+ # write 'TIMESTAMP', Time.now
52
+ # write('TIMESTAMP') { Time.now }
53
+ #
54
+ # Yields to the block before writing the file, so you can chain read and write together.
55
+ # For example:
56
+ # write('README') { read('README').sub("${build}", Time.now) }
57
+ def write(name, content = nil)
58
+ mkpath File.dirname(name), :verbose=>false
59
+ content = yield if block_given?
60
+ File.open(name.to_s, 'wb') { |file| file.write content.to_s }
61
+ content.to_s
62
+ end
63
+
64
+ # :call-seq:
65
+ # read(name) => string
66
+ # read(name) { |string| ... } => result
67
+ #
68
+ # Reads and returns the contents of a file. The second form yields to the block and returns
69
+ # the result of the block.
70
+ #
71
+ # For example:
72
+ # puts read('README')
73
+ # read('README') { |text| puts text }
74
+ def read(name)
75
+ contents = File.open(name.to_s) { |f| f.read }
76
+ if block_given?
77
+ yield contents
78
+ else
79
+ contents
80
+ end
81
+ end
82
+
83
+ # :call-seq:
84
+ # download(url_or_uri) => task
85
+ # download(path=>url_or_uri) =>task
86
+ #
87
+ # Create a task that will download a file from a URL.
88
+ #
89
+ # Takes a single argument, a hash with one pair. The key is the file being
90
+ # created, the value if the URL to download. The task executes only if the
91
+ # file does not exist; the URL is not checked for updates.
92
+ #
93
+ # The task will show download progress on the console; if there are MD5/SHA1
94
+ # checksums on the server it will verify the download before saving it.
95
+ #
96
+ # For example:
97
+ # download 'image.jpg'=>'http://example.com/theme/image.jpg'
98
+ def download(args)
99
+ args = URI.parse(args) if String === args
100
+ if URI === args
101
+ # Given only a download URL, download into a temporary file.
102
+ # You can infer the file from task name.
103
+ temp = Tempfile.open(File.basename(args.to_s))
104
+ file(temp.path).tap do |task|
105
+ # Since temporary file exists, force a download.
106
+ class << task ; def needed? ; true ; end ; end
107
+ task.sources << args
108
+ task.enhance { args.download temp }
109
+ end
110
+ else
111
+ # Download to a file created by the task.
112
+ fail unless args.keys.size == 1
113
+ uri = URI.parse(args.values.first.to_s)
114
+ file(args.keys.first.to_s).tap do |task|
115
+ task.sources << uri
116
+ task.enhance { uri.download task.name }
117
+ end
118
+ end
119
+
120
+ end
121
+
122
+ # A file task that concatenates all its prerequisites to create a new file.
123
+ #
124
+ # For example:
125
+ # concat("master.sql"=>["users.sql", "orders.sql", reports.sql"]
126
+ #
127
+ # See also Buildr#concat.
128
+ class ConcatTask < Rake::FileTask
129
+ def initialize(*args) #:nodoc:
130
+ super
131
+ enhance do |task|
132
+ content = prerequisites.inject("") do |content, prereq|
133
+ content << File.read(prereq.to_s) if File.exists?(prereq) && !File.directory?(prereq)
134
+ content
135
+ end
136
+ File.open(task.name, "wb") { |file| file.write content }
137
+ end
138
+ end
139
+ end
140
+
141
+ # :call-seq:
142
+ # concat(target=>files) => task
143
+ #
144
+ # Creates and returns a file task that concatenates all its prerequisites to create
145
+ # a new file. See #ConcatTask.
146
+ #
147
+ # For example:
148
+ # concat("master.sql"=>["users.sql", "orders.sql", reports.sql"]
149
+ def concat(args)
150
+ file, arg_names, deps = Buildr.application.resolve_args([args])
151
+ ConcatTask.define_task(File.expand_path(file)=>deps)
152
+ end
153
+
154
+ end
@@ -0,0 +1,596 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with this
3
+ # work for additional information regarding copyright ownership. The ASF
4
+ # licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations under
14
+ # the License.
15
+
16
+
17
+ require 'buildr/core/common'
18
+
19
+
20
+ module Buildr
21
+
22
+ # The underlying compiler used by CompileTask.
23
+ # To add a new compiler, extend Compiler::Base and add your compiler using:
24
+ # Buildr::Compiler.add MyCompiler
25
+ module Compiler
26
+
27
+ class << self
28
+
29
+ # Returns true if the specified compiler exists.
30
+ def has?(name)
31
+ compilers.any? { |compiler| compiler.to_sym == name.to_sym }
32
+ end
33
+
34
+ # Select a compiler by its name.
35
+ def select(name)
36
+ compilers.detect { |compiler| compiler.to_sym == name.to_sym }
37
+ end
38
+
39
+ # Adds a compiler to the list of supported compiler.
40
+ #
41
+ # For example:
42
+ # Buildr::Compiler << Buildr::Javac
43
+ def add(compiler)
44
+ @compilers ||= []
45
+ @compilers |= [compiler]
46
+ end
47
+ alias :<< :add
48
+
49
+ # Returns a list of available compilers.
50
+ def compilers
51
+ @compilers ||= []
52
+ end
53
+
54
+ end
55
+
56
+ # Base class for all compilers, with common functionality. Extend and over-ride as you see fit
57
+ # (see Javac as an example).
58
+ class Base #:nodoc:
59
+
60
+ class << self
61
+
62
+ # The compiler's identifier (e.g. :javac). Inferred from the class name.
63
+ def to_sym
64
+ @symbol ||= name.split('::').last.downcase.to_sym
65
+ end
66
+
67
+ # The compiled language (e.g. :java).
68
+ attr_reader :language
69
+ # Source directories to use if none were specified (e.g. 'java'). Defaults to #language.
70
+ attr_reader :sources
71
+ # Extension for source files (e.g. 'java'). Defaults to language.
72
+ attr_reader :source_ext
73
+ # The target path (e.g. 'classes')
74
+ attr_reader :target
75
+ # Extension for target files (e.g. 'class').
76
+ attr_reader :target_ext
77
+ # The default packaging type (e.g. :jar).
78
+ attr_reader :packaging
79
+
80
+ # Returns true if this compiler applies to any source code found in the listed source
81
+ # directories. For example, Javac returns true if any of the source directories contains
82
+ # a .java file. The default implementation looks to see if there are any files in the
83
+ # specified path with the extension #source_ext.
84
+ def applies_to?(project, task)
85
+ paths = task.sources + [sources].flatten.map { |src| Array(project.path_to(:source, task.usage, src.to_sym)) }
86
+ paths.flatten!
87
+ ext_glob = Array(source_ext).join(',')
88
+ paths.any? { |path| !Dir["#{path}/**/*.{#{ext_glob}}"].empty? }
89
+ end
90
+
91
+ # Implementations can use this method to specify various compiler attributes.
92
+ # For example:
93
+ # specify :language=>:java, :target=>'classes', :target_ext=>'class', :packaging=>:jar
94
+ def specify(attrs)
95
+ attrs[:sources] ||= attrs[:language].to_s
96
+ attrs[:source_ext] ||= attrs[:language].to_s
97
+ attrs.each { |name, value| instance_variable_set("@#{name}", value) }
98
+ end
99
+
100
+ # Returns additional dependencies required by this language. For example, since the
101
+ # test framework picks on these, you can use the JUnit framework with Scala.
102
+ # Defaults to obtaining a list of artifact specifications from the REQUIRES constant.
103
+ def dependencies
104
+ []
105
+ end
106
+
107
+ end
108
+
109
+ # Construct a new compiler with the specified options. Note that options may
110
+ # change before the compiler is run.
111
+ def initialize(project, options)
112
+ @project = project
113
+ @options = options
114
+ end
115
+
116
+ # Options for this compiler.
117
+ attr_reader :options
118
+
119
+ # Determines if the compiler needs to run by checking if the target files exist,
120
+ # and if any source files or dependencies are newer than corresponding target files.
121
+ def needed?(sources, target, dependencies)
122
+ map = compile_map(sources, target)
123
+ return false if map.empty?
124
+ return true unless File.exist?(target.to_s)
125
+ source_files_not_yet_compiled = map.select { |source, target| !File.exist?(target) }
126
+ trace "Compile needed because source file #{source_files_not_yet_compiled[0][0]} has no corresponding #{source_files_not_yet_compiled[0][1]}" unless source_files_not_yet_compiled.empty?
127
+ return true if map.any? { |source, target| !File.exist?(target) || File.stat(source).mtime > File.stat(target).mtime }
128
+ oldest = map.map { |source, target| File.stat(target).mtime }.min
129
+ return dependencies.any? { |path| file(path).timestamp > oldest }
130
+ end
131
+
132
+ # Compile all files lists in sources (files and directories) into target using the
133
+ # specified dependencies.
134
+ def compile(sources, target, dependencies)
135
+ raise 'Not implemented'
136
+ end
137
+
138
+ # Returns additional dependencies required by this language. For example, since the
139
+ # test framework picks on these, you can use the JUnit framework with Scala.
140
+ def dependencies
141
+ self.class.dependencies
142
+ end
143
+
144
+ protected
145
+
146
+ # Use this to complain about CompileTask options not supported by this compiler.
147
+ #
148
+ # For example:
149
+ # def compile(files, task)
150
+ # check_options task, OPTIONS
151
+ # . . .
152
+ # end
153
+ def check_options(options, *supported)
154
+ unsupported = options.to_hash.keys - supported.flatten
155
+ raise ArgumentError, "No such option: #{unsupported.join(' ')}" unless unsupported.empty?
156
+ end
157
+
158
+ # Expands a list of source directories/files into a list of files that have the #source_ext extension.
159
+ def files_from_sources(sources)
160
+ ext_glob = Array(self.class.source_ext).join(',')
161
+ sources.flatten.map { |source| File.directory?(source) ? FileList["#{source}/**/*.{#{ext_glob}}"] : source }.
162
+ flatten.reject { |file| File.directory?(file) }.map { |file| File.expand_path(file) }.uniq
163
+ end
164
+
165
+ # The compile map is a hash that associates source files with target files based
166
+ # on a list of source directories and target directory. The compile task uses this
167
+ # to determine if there are source files to compile, and which source files to compile.
168
+ # The default method maps all files in the source directories with #source_ext into
169
+ # paths in the target directory with #target_ext (e.g. 'source/foo.java'=>'target/foo.class').
170
+ def compile_map(sources, target)
171
+ target_ext = self.class.target_ext
172
+ ext_glob = Array(self.class.source_ext).join(',')
173
+ sources.flatten.map{|f| File.expand_path(f)}.inject({}) do |map, source|
174
+ if File.directory?(source)
175
+ FileList["#{source}/**/*.{#{ext_glob}}"].reject { |file| File.directory?(file) }.
176
+ each { |file| map[file] = File.join(target, Util.relative_path(file, source).ext(target_ext)) }
177
+ else
178
+ map[source] = target # File.join(target, File.basename(source).ext(target_ext))
179
+ end
180
+ map
181
+ end
182
+ end
183
+
184
+ end
185
+
186
+ end
187
+
188
+
189
+ # Compile task.
190
+ #
191
+ # Attempts to determine which compiler to use based on the project layout, for example,
192
+ # uses the Javac compiler if it finds any .java files in src/main/java. You can also
193
+ # select the compiler explicitly:
194
+ # compile.using(:scalac)
195
+ #
196
+ # Accepts multiple source directories that are invoked as prerequisites before compilation.
197
+ # You can pass a task as a source directory:
198
+ # compile.from(apt)
199
+ #
200
+ # Likewise, dependencies are invoked before compiling. All dependencies are evaluated as
201
+ # #artifacts, so you can pass artifact specifications and even projects:
202
+ # compile.with('module1.jar', 'log4j:log4j:jar:1.0', project('foo'))
203
+ #
204
+ # Creates a file task for the target directory, so executing that task as a dependency will
205
+ # execute the compile task first.
206
+ #
207
+ # Compiler options are inherited form a parent task, e.g. the foo:bar:compile task inherits
208
+ # its options from the foo:compile task. Even if foo is an empty project that does not compile
209
+ # any classes itself, you can use it to set compile options for all its sub-projects.
210
+ #
211
+ # Normally, the project will take care of setting the source and target directory, and you
212
+ # only need to set options and dependencies. See Project#compile.
213
+ class CompileTask < Rake::Task
214
+
215
+ def initialize(*args) #:nodoc:
216
+ super
217
+ parent_task = Project.parent_task(name)
218
+ inherit = lambda { |hash, key| parent_task.options[key] } if parent_task.respond_to?(:options)
219
+ @options = OpenObject.new &inherit
220
+ @sources = FileList[]
221
+ @dependencies = FileList[]
222
+
223
+ enhance do |task|
224
+ unless sources.empty?
225
+ raise 'No compiler selected and can\'t determine which compiler to use' unless compiler
226
+ raise 'No target directory specified' unless target
227
+ mkpath target.to_s, :verbose=>false
228
+ info "Compiling #{task.name.gsub(/:[^:]*$/, '')} into #{target.to_s}"
229
+ @compiler.compile(sources.map(&:to_s), target.to_s, dependencies.map(&:to_s))
230
+ # By touching the target we let other tasks know we did something,
231
+ # and also prevent recompiling again for dependencies.
232
+ touch target.to_s, :verbose=>false
233
+ end
234
+ end
235
+ end
236
+
237
+ # Source directories.
238
+ attr_accessor :sources
239
+
240
+ # :call-seq:
241
+ # from(*sources) => self
242
+ #
243
+ # Adds source directories and files to compile, and returns self.
244
+ #
245
+ # For example:
246
+ # compile.from('src/java').into('classes').with('module1.jar')
247
+ def from(*sources)
248
+ @sources |= sources.flatten
249
+ guess_compiler if @compiler.nil? && sources.flatten.any? { |source| File.exist?(source) }
250
+ self
251
+ end
252
+
253
+ # *Deprecated*: Use dependencies instead.
254
+ def classpath
255
+ Buildr.application.deprecated 'Use dependencies instead.'
256
+ dependencies
257
+ end
258
+
259
+ # *Deprecated*: Use dependencies= instead.
260
+ def classpath=(artifacts)
261
+ Buildr.application.deprecated 'Use dependencies= instead.'
262
+ self.dependencies = artifacts
263
+ end
264
+
265
+ # Compilation dependencies.
266
+ attr_accessor :dependencies
267
+
268
+ # :call-seq:
269
+ # with(*artifacts) => self
270
+ #
271
+ # Adds files and artifacts as dependencies, and returns self.
272
+ #
273
+ # Calls #artifacts on the arguments, so you can pass artifact specifications,
274
+ # tasks, projects, etc. Use this rather than setting the dependencies array directly.
275
+ #
276
+ # For example:
277
+ # compile.with('module1.jar', 'log4j:log4j:jar:1.0', project('foo'))
278
+ def with(*specs)
279
+ @dependencies |= Buildr.artifacts(specs.flatten).uniq
280
+ self
281
+ end
282
+
283
+ # The target directory for the compiled code.
284
+ attr_reader :target
285
+
286
+ # :call-seq:
287
+ # into(path) => self
288
+ #
289
+ # Sets the target directory and returns self. This will also set the compile task
290
+ # as a prerequisite to a file task on the target directory.
291
+ #
292
+ # For example:
293
+ # compile(src_dir).into(target_dir).with(artifacts)
294
+ # Both compile.invoke and file(target_dir).invoke will compile the source files.
295
+ def into(path)
296
+ @target = file(path.to_s).enhance([self]) unless @target.to_s == path.to_s
297
+ self
298
+ end
299
+
300
+ # Returns the compiler options.
301
+ attr_reader :options
302
+
303
+ # :call-seq:
304
+ # using(options) => self
305
+ #
306
+ # Sets the compiler options from a hash and returns self. Can also be used to
307
+ # select the compiler.
308
+ #
309
+ # For example:
310
+ # compile.using(:warnings=>true, :source=>'1.5')
311
+ # compile.using(:scala)
312
+ def using(*args)
313
+ args.pop.each { |key, value| options.send "#{key}=", value } if Hash === args.last
314
+ self.compiler = args.pop until args.empty?
315
+ self
316
+ end
317
+
318
+ # Returns the compiler if known. The compiler is either automatically selected
319
+ # based on existing source directories (e.g. src/main/java), or by requesting
320
+ # a specific compiler (see #using).
321
+ def compiler
322
+ guess_compiler unless @compiler
323
+ @compiler && @compiler.class.to_sym
324
+ end
325
+
326
+ # Returns the compiled language, if known. See also #compiler.
327
+ def language
328
+ compiler && @compiler.class.language
329
+ end
330
+
331
+ # Returns the default packaging type for this compiler, if known.
332
+ def packaging
333
+ compiler && @compiler.class.packaging
334
+ end
335
+
336
+ def timestamp #:nodoc:
337
+ # If we compiled successfully, then the target directory reflects that.
338
+ # If we didn't, see needed?
339
+ target ? target.timestamp : Rake::EARLY
340
+ end
341
+
342
+ # The project this task belongs to.
343
+ attr_reader :project
344
+
345
+ # The usage, one of :main or :test.
346
+ attr_reader :usage
347
+
348
+ protected
349
+
350
+ # Selects which compiler to use.
351
+ def compiler=(name) #:nodoc:
352
+ cls = Compiler.select(name) or raise ArgumentError, "No #{name} compiler available. Did you install it?"
353
+ return self if cls === @compiler
354
+ raise "#{compiler} compiler already selected for this project" if @compiler
355
+ @compiler = cls.new(project, options)
356
+ from Array(cls.sources).map { |path| project.path_to(:source, usage, path) }.
357
+ select { |path| File.exist?(path) } if sources.empty?
358
+ into project.path_to(:target, usage, cls.target) unless target
359
+ with Array(@compiler.dependencies)
360
+ self
361
+ end
362
+
363
+ # Associates this task with project and particular usage (:main, :test).
364
+ def associate_with(project, usage) #:nodoc:
365
+ @project, @usage = project, usage
366
+ guess_compiler
367
+ end
368
+
369
+ # Try to guess if we have a compiler to match source files.
370
+ def guess_compiler #:nodoc:
371
+ candidate = Compiler.compilers.detect { |cls| cls.applies_to?(project, self) }
372
+ self.compiler = candidate if candidate
373
+ end
374
+
375
+ private
376
+
377
+ def needed? #:nodoc:
378
+ return false if sources.empty?
379
+ # Fail during invoke.
380
+ return true unless @compiler && target
381
+ return @compiler.needed?(sources.map(&:to_s), target.to_s, dependencies.map(&:to_s))
382
+ end
383
+
384
+ def invoke_prerequisites(args, chain) #:nodoc:
385
+ @sources = Array(@sources).map(&:to_s).uniq
386
+ @dependencies = FileList[@dependencies.uniq]
387
+ @prerequisites |= @dependencies + @sources
388
+ super
389
+ end
390
+
391
+ end
392
+
393
+
394
+ # The resources task is executed by the compile task to copy resource files over
395
+ # to the target directory. You can enhance this task in the normal way, but mostly
396
+ # you will use the task's filter.
397
+ #
398
+ # For example:
399
+ # resources.filter.using 'Copyright'=>'Acme Inc, 2007'
400
+ class ResourcesTask < Rake::Task
401
+
402
+ # Returns the filter used to copy resources over. See Buildr::Filter.
403
+ attr_reader :filter
404
+
405
+ def initialize(*args) #:nodoc:
406
+ super
407
+ @filter = Buildr::Filter.new
408
+ @filter.using Buildr.settings.profile['filter'] if Hash === Buildr.settings.profile['filter']
409
+ enhance do
410
+ filter.run if target
411
+ end
412
+ end
413
+
414
+ # :call-seq:
415
+ # include(*files) => self
416
+ #
417
+ # Includes the specified files in the filter and returns self.
418
+ def include(*files)
419
+ filter.include *files
420
+ self
421
+ end
422
+
423
+ # :call-seq:
424
+ # exclude(*files) => self
425
+ #
426
+ # Excludes the specified files in the filter and returns self.
427
+ def exclude(*files)
428
+ filter.exclude *files
429
+ self
430
+ end
431
+
432
+ # :call-seq:
433
+ # from(*sources) => self
434
+ #
435
+ # Adds additional directories from which to copy resources.
436
+ #
437
+ # For example:
438
+ # resources.from _('src/etc')
439
+ def from(*sources)
440
+ filter.from *sources
441
+ self
442
+ end
443
+
444
+ # Returns the list of source directories (each being a file task).
445
+ def sources
446
+ filter.sources
447
+ end
448
+
449
+ # :call-seq:
450
+ # target => task
451
+ #
452
+ # Returns the filter's target directory as a file task.
453
+ def target
454
+ filter.into @project.path_to(:target, @usage, :resources) unless filter.target || sources.empty?
455
+ filter.target
456
+ end
457
+
458
+ def prerequisites #:nodoc:
459
+ super + filter.sources.flatten
460
+ end
461
+
462
+ protected
463
+
464
+ # Associates this task with project and particular usage (:main, :test).
465
+ def associate_with(project, usage) #:nodoc:
466
+ @project, @usage = project, usage
467
+ end
468
+
469
+ end
470
+
471
+
472
+ # Methods added to Project for compiling, handling of resources and generating source documentation.
473
+ module Compile
474
+
475
+ include Extension
476
+
477
+ first_time do
478
+ desc 'Compile all projects'
479
+ Project.local_task('compile') { |name| "Compiling #{name}" }
480
+ end
481
+
482
+ before_define do |project|
483
+ resources = ResourcesTask.define_task('resources')
484
+ resources.send :associate_with, project, :main
485
+ project.path_to(:source, :main, :resources).tap { |dir| resources.from dir if File.exist?(dir) }
486
+
487
+ compile = CompileTask.define_task('compile'=>resources)
488
+ compile.send :associate_with, project, :main
489
+ project.recursive_task('compile')
490
+ end
491
+
492
+ after_define do |project|
493
+ # TODO: Is this necessary?
494
+ #if project.resources.target
495
+ # file project.resources.target.to_s=>project.resources do |task|
496
+ # mkpath task.name, :verbose=>false
497
+ # end
498
+ #end
499
+ if project.compile.target
500
+ # This comes last because the target path is set inside the project definition.
501
+ project.build project.compile.target
502
+ project.clean do
503
+ rm_rf project.compile.target.to_s, :verbose=>false
504
+ end
505
+ end
506
+ end
507
+
508
+
509
+ # :call-seq:
510
+ # compile(*sources) => CompileTask
511
+ # compile(*sources) { |task| .. } => CompileTask
512
+ #
513
+ # The compile task does what its name suggests. This method returns the project's
514
+ # CompileTask. It also accepts a list of source directories and files to compile
515
+ # (equivalent to calling CompileTask#from on the task), and a block for any
516
+ # post-compilation work.
517
+ #
518
+ # The compile task attempts to guess which compiler to use. For example, if it finds
519
+ # any Java files in the src/main/java directory, it will use the Java compiler and
520
+ # create class files in the target/classes directory.
521
+ #
522
+ # You can also configure it yourself by telling it which compiler to use, pointing
523
+ # it as source directories and chooing a different target directory.
524
+ #
525
+ # For example:
526
+ # # Include Log4J and the api sub-project artifacts.
527
+ # compile.with 'log4j:log4j:jar:1.2', project('api')
528
+ # # Include Apt-generated source files.
529
+ # compile.from apt
530
+ # # For JavaC, force target compatibility.
531
+ # compile.options.source = '1.6'
532
+ # # Run the OpenJPA bytecode enhancer after compilation.
533
+ # compile { open_jpa_enhance }
534
+ # # Pick a given compiler.
535
+ # compile.using(:scalac).from('src/scala')
536
+ #
537
+ # For more information, see CompileTask.
538
+ def compile(*sources, &block)
539
+ task('compile').from(sources).enhance &block
540
+ end
541
+
542
+ # :call-seq:
543
+ # resources(*prereqs) => ResourcesTask
544
+ # resources(*prereqs) { |task| .. } => ResourcesTask
545
+ #
546
+ # The resources task is executed by the compile task to copy resources files
547
+ # from the resource directory into the target directory. By default the resources
548
+ # task copies files from the src/main/resources into the target/resources directory.
549
+ #
550
+ # This method returns the project's resources task. It also accepts a list of
551
+ # prerequisites and a block, used to enhance the resources task.
552
+ #
553
+ # Resources files are copied and filtered (see Buildr::Filter for more information).
554
+ # The default filter uses the profile properties for the current environment.
555
+ #
556
+ # For example:
557
+ # resources.from _('src/etc')
558
+ # resources.filter.using 'Copyright'=>'Acme Inc, 2007'
559
+ #
560
+ # Or in your profiles.yaml file:
561
+ # common:
562
+ # Copyright: Acme Inc, 2007
563
+ def resources(*prereqs, &block)
564
+ task('resources').enhance prereqs, &block
565
+ end
566
+
567
+ end
568
+
569
+
570
+ class Options
571
+
572
+ # Returns the debug option (environment variable DEBUG).
573
+ def debug
574
+ (ENV['DEBUG'] || ENV['debug']) !~ /(no|off|false)/
575
+ end
576
+
577
+ # Sets the debug option (environment variable DEBUG).
578
+ #
579
+ # You can turn this option off directly, or by setting the environment variable
580
+ # DEBUG to +no+. For example:
581
+ # buildr build DEBUG=no
582
+ #
583
+ # The release tasks runs a build with <tt>DEBUG=no</tt>.
584
+ def debug=(flag)
585
+ ENV['debug'] = nil
586
+ ENV['DEBUG'] = flag.to_s
587
+ end
588
+
589
+ end
590
+
591
+ end
592
+
593
+
594
+ class Buildr::Project
595
+ include Buildr::Compile
596
+ end