buildr 1.3.0-java

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