buildr 1.2.10 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. data/CHANGELOG +566 -268
  2. data/DISCLAIMER +7 -1
  3. data/KEYS +151 -0
  4. data/NOTICE +23 -8
  5. data/README +122 -22
  6. data/Rakefile +49 -229
  7. data/{lib → addon}/buildr/antlr.rb +23 -10
  8. data/addon/buildr/cobertura.rb +232 -0
  9. data/{lib → addon}/buildr/hibernate.rb +20 -4
  10. data/{lib → addon}/buildr/javacc.rb +27 -12
  11. data/addon/buildr/jdepend.rb +60 -0
  12. data/{lib → addon}/buildr/jetty.rb +34 -18
  13. data/addon/buildr/nailgun.rb +892 -0
  14. data/{lib → addon}/buildr/openjpa.rb +23 -6
  15. data/addon/buildr/org/apache/buildr/JettyWrapper$1.class +0 -0
  16. data/addon/buildr/org/apache/buildr/JettyWrapper$BuildrHandler.class +0 -0
  17. data/addon/buildr/org/apache/buildr/JettyWrapper.class +0 -0
  18. data/{lib/buildr/jetty → addon/buildr/org/apache/buildr}/JettyWrapper.java +19 -0
  19. data/{lib → addon}/buildr/xmlbeans.rb +39 -14
  20. data/bin/buildr +21 -7
  21. data/buildr.gemspec +50 -0
  22. data/doc/css/default.css +225 -0
  23. data/doc/css/print.css +95 -0
  24. data/doc/css/syntax.css +43 -0
  25. data/doc/images/apache-incubator-logo.png +0 -0
  26. data/doc/images/buildr-hires.png +0 -0
  27. data/doc/images/buildr.png +0 -0
  28. data/doc/images/note.png +0 -0
  29. data/doc/images/tip.png +0 -0
  30. data/doc/images/zbuildr.tif +0 -0
  31. data/doc/pages/artifacts.textile +317 -0
  32. data/doc/pages/building.textile +501 -0
  33. data/doc/pages/contributing.textile +178 -0
  34. data/doc/pages/download.textile +25 -0
  35. data/doc/pages/extending.textile +229 -0
  36. data/doc/pages/getting_started.textile +337 -0
  37. data/doc/pages/index.textile +63 -0
  38. data/doc/pages/mailing_lists.textile +17 -0
  39. data/doc/pages/more_stuff.textile +367 -0
  40. data/doc/pages/packaging.textile +592 -0
  41. data/doc/pages/projects.textile +449 -0
  42. data/doc/pages/recipes.textile +127 -0
  43. data/doc/pages/settings_profiles.textile +339 -0
  44. data/doc/pages/testing.textile +475 -0
  45. data/doc/pages/troubleshooting.textile +121 -0
  46. data/doc/pages/whats_new.textile +389 -0
  47. data/doc/print.haml +52 -0
  48. data/doc/print.toc.yaml +28 -0
  49. data/doc/scripts/buildr-git.rb +411 -0
  50. data/doc/scripts/install-jruby.sh +44 -0
  51. data/doc/scripts/install-linux.sh +64 -0
  52. data/doc/scripts/install-osx.sh +52 -0
  53. data/doc/site.haml +55 -0
  54. data/doc/site.toc.yaml +44 -0
  55. data/lib/buildr.rb +28 -45
  56. data/lib/buildr/core.rb +27 -0
  57. data/lib/buildr/core/application.rb +373 -0
  58. data/lib/buildr/core/application_cli.rb +134 -0
  59. data/lib/{core → buildr/core}/build.rb +91 -77
  60. data/lib/{core → buildr/core}/checks.rb +116 -95
  61. data/lib/buildr/core/common.rb +155 -0
  62. data/lib/buildr/core/compile.rb +594 -0
  63. data/lib/buildr/core/environment.rb +120 -0
  64. data/lib/buildr/core/filter.rb +258 -0
  65. data/lib/{core → buildr/core}/generate.rb +22 -5
  66. data/lib/buildr/core/help.rb +118 -0
  67. data/lib/buildr/core/progressbar.rb +156 -0
  68. data/lib/{core → buildr/core}/project.rb +468 -213
  69. data/lib/buildr/core/test.rb +690 -0
  70. data/lib/{core → buildr/core}/transports.rb +107 -127
  71. data/lib/buildr/core/util.rb +235 -0
  72. data/lib/buildr/ide.rb +19 -0
  73. data/lib/{java → buildr/ide}/eclipse.rb +86 -60
  74. data/lib/{java → buildr/ide}/idea.ipr.template +16 -0
  75. data/lib/buildr/ide/idea.rb +194 -0
  76. data/lib/buildr/ide/idea7x.ipr.template +290 -0
  77. data/lib/buildr/ide/idea7x.rb +210 -0
  78. data/lib/buildr/java.rb +26 -0
  79. data/lib/buildr/java/ant.rb +71 -0
  80. data/lib/buildr/java/bdd_frameworks.rb +267 -0
  81. data/lib/buildr/java/commands.rb +210 -0
  82. data/lib/buildr/java/compilers.rb +432 -0
  83. data/lib/buildr/java/deprecated.rb +141 -0
  84. data/lib/buildr/java/groovyc.rb +137 -0
  85. data/lib/buildr/java/jruby.rb +99 -0
  86. data/lib/buildr/java/org/apache/buildr/BuildrNail$Main.class +0 -0
  87. data/lib/buildr/java/org/apache/buildr/BuildrNail.class +0 -0
  88. data/lib/buildr/java/org/apache/buildr/BuildrNail.java +41 -0
  89. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.class +0 -0
  90. data/lib/buildr/java/org/apache/buildr/JavaTestFilter.java +116 -0
  91. data/lib/buildr/java/packaging.rb +706 -0
  92. data/lib/{java → buildr/java}/pom.rb +20 -4
  93. data/lib/buildr/java/rjb.rb +142 -0
  94. data/lib/buildr/java/test_frameworks.rb +290 -0
  95. data/lib/buildr/java/version_requirement.rb +172 -0
  96. data/lib/buildr/packaging.rb +21 -0
  97. data/lib/{java → buildr/packaging}/artifact.rb +170 -179
  98. data/lib/buildr/packaging/artifact_namespace.rb +957 -0
  99. data/lib/buildr/packaging/artifact_search.rb +140 -0
  100. data/lib/buildr/packaging/gems.rb +102 -0
  101. data/lib/buildr/packaging/package.rb +233 -0
  102. data/lib/{tasks → buildr/packaging}/tar.rb +18 -1
  103. data/lib/{tasks → buildr/packaging}/zip.rb +153 -105
  104. data/rakelib/apache.rake +126 -0
  105. data/rakelib/changelog.rake +56 -0
  106. data/rakelib/doc.rake +103 -0
  107. data/rakelib/package.rake +44 -0
  108. data/rakelib/release.rake +53 -0
  109. data/rakelib/rspec.rake +81 -0
  110. data/rakelib/rubyforge.rake +45 -0
  111. data/rakelib/scm.rake +49 -0
  112. data/rakelib/setup.rake +59 -0
  113. data/rakelib/stage.rake +45 -0
  114. data/spec/application_spec.rb +316 -0
  115. data/spec/archive_spec.rb +494 -0
  116. data/spec/artifact_namespace_spec.rb +635 -0
  117. data/spec/artifact_spec.rb +738 -0
  118. data/spec/build_spec.rb +193 -0
  119. data/spec/checks_spec.rb +537 -0
  120. data/spec/common_spec.rb +579 -0
  121. data/spec/compile_spec.rb +561 -0
  122. data/spec/groovy_compilers_spec.rb +239 -0
  123. data/spec/java_bdd_frameworks_spec.rb +238 -0
  124. data/spec/java_compilers_spec.rb +446 -0
  125. data/spec/java_packaging_spec.rb +1042 -0
  126. data/spec/java_test_frameworks_spec.rb +414 -0
  127. data/spec/packaging_helper.rb +63 -0
  128. data/spec/packaging_spec.rb +589 -0
  129. data/spec/project_spec.rb +739 -0
  130. data/spec/sandbox.rb +116 -0
  131. data/spec/scala_compilers_spec.rb +239 -0
  132. data/spec/spec.opts +6 -0
  133. data/spec/spec_helpers.rb +283 -0
  134. data/spec/test_spec.rb +871 -0
  135. data/spec/transport_spec.rb +300 -0
  136. data/spec/version_requirement_spec.rb +115 -0
  137. metadata +188 -77
  138. data/lib/buildr/cobertura.rb +0 -89
  139. data/lib/buildr/jdepend.rb +0 -40
  140. data/lib/buildr/jetty/JettyWrapper$1.class +0 -0
  141. data/lib/buildr/jetty/JettyWrapper$BuildrHandler.class +0 -0
  142. data/lib/buildr/jetty/JettyWrapper.class +0 -0
  143. data/lib/buildr/scala.rb +0 -368
  144. data/lib/core/application.rb +0 -188
  145. data/lib/core/common.rb +0 -562
  146. data/lib/core/help.rb +0 -72
  147. data/lib/core/rake_ext.rb +0 -81
  148. data/lib/java/ant.rb +0 -71
  149. data/lib/java/compile.rb +0 -589
  150. data/lib/java/idea.rb +0 -159
  151. data/lib/java/java.rb +0 -432
  152. data/lib/java/packaging.rb +0 -581
  153. data/lib/java/test.rb +0 -795
  154. data/lib/tasks/concat.rb +0 -35
@@ -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