How do I Declare a Rake::PackageTask with Prerequisites? - ruby

In Rake, I can use the following syntax to declare that task charlie requires tasks alpha and bravo to have been completed first.
task :charlie => [:alpha, :bravo]
This seems to work fine if charlie is a typical Rake task or a file task but I cannot figure out how to do this for a Rake::PackageTask. Here are the relevant parts of the rakefile so far:
require 'rake/packagetask'
file :package_jar => [:compile] do
puts("Packaging library.jar...")
# code omitted for brevity, but this bit works fine
end
Rake::PackageTask.new("library", "1.0") do |pt|
puts("Packaging library distribution artefact...")
pt.need_tar = true
pt.package_files = ["target/library.jar"]
end
task :package => :package_jar
What's happening here is that, for a clean build, it complains that it doesn't "know how to build task 'target/library.jar'". I have to run rake package_jar from the command line manually to get it to work, which is a bit of a nuisance. Is there any way I can make package depend on package_jar?
For what it's worth, I am using Rake version 0.9.2.2 with Ruby 1.8.7 on Linux.

When you run rake package (without previously running anything else to create any needed files) Rake sees that the package task needs the file target/library.jar. Since this file doesn’t yet exist Rake checks to see if it knows how to create it. It doesn’t know of any rules that will create this file, so it fails with the error you see.
Rake does have a task that it thinks will create a file named package_jar, and that task in fact creates the file target/library.jar, but it doesn’t realise this.
The fix is to tell Rake exactly what file is created in the file task. Rake will then automatically find the dependency.
Change
file :package_jar => [:compile] do
to
file 'target/library.jar' => [:compile] do
and then remove the line
task :package => :package_jar
since package_jar no longer exists and Rake will find the dependency on the file by itself.

In general in rake, if you want to add a dependency to a task, you need that task's name. So you need to figure out the name of the actual rake task that Rake::PackageTask is registering.
The easiest way to do this is by running with --trace — it lists each task's name as it is executing.
(I believe the name of a buildr package task is the filename of the package it produces, but I don't remember for certain. Use --trace to find out.)

You can add a dependency to any task by writing,
someTask.enhance [other, tasks]
where other and tasks can be either task names or task objects.
So in your case, you could write:
library = Rake::PackageTask.new(...) do
...
end
task(:package).enhance([library])

Related

In an Android gradle build, how I can I make it consider a task not UP-TO-DATE when the output directory is not exactly the same?

I'm using gradle for an Android project.
I have a task that downloads some files to put them into the build (as Android assets).
I would like to have a task download some files from the web and put them into a temp directory, from where they are copied (by a separate copy task) into the assets directory during the build.
I would like to make sure that the downloader task will rerun ( and not be considered UP-TO-DATE ) if the output directory changed in any way ( e.g. files changed or missing, directories missing, files in subdirectory missing etc, recursively. ). Currently, I specified the output directory as #OutputDirectory, but it seems to not do what I want:
class AssetDownloaderTask extends DefaultTask {
#OutputDirectory
def File outputDir
#Input
def String databaseChecksum
....
E.g. if I delete a file from one of the subdirectories, gradle still considers the task UP-TO-DATE. Isn't gradle supposed to store a hash of the outputs?
How can I achieve what I want?
I'm not a Gradle expert by any means, but I believe you want to use the #InputDirectory annotation instead.
This will cause the task to be considered out-of-date when the directory location or contents have changed.
https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/InputDirectory.html
EDIT: Wow, didn't notice this was so old. Sorry if necroing is bad SA etiquette.

Check if rake task exists from within Rakefile

I'm looking for a way to be able to check if a certain rake task exists from within the Rakefile. I have a task dependency that I only want to include as a dependency if that task is available. In this particular case, the task is only available in a Rails project, but I want my rake tasks to work in a more general Ruby application environment too (not just Rails).
I want to do something like this:
if tasks.includes?('assets:precompile')
task :archive => [:clean, :vendor_deps, 'assets:precompile']
...
end
else
task :archive => [:clean, :vendor_deps]
...
end
end
What is the best way to conditionally include a task dependency in a rake task?
what about doing something like this? Invoke the task if it exists, as opposed to making it an explicit dependency?
task :archive => [:clean, :vendor_deps] do
Rake.application["assets:precompile"].invoke if Rake::Task.task_defined?('assets:precompile')
....
end
or even easier. Since specifying the task again allows you to add to it, something like this appears to work as well.
task :archive => [:clean, :vendor_deps] do
...
end
task :archive => "assets:precompile" if Rake::Task.task_defined?("assets:precompile")
which will conditionally add the dependency on assets:precompile if it is defined.
You should be able to use task_defined?:
Rake::Task.task_defined?('assets:precompile')

what is the right way to use CLEAN rake task?

This is what I'm trying to do in my Rakefile:
require 'rake/clean'
CLEAN = ['coverage']
This is what I see in the log:
$ rake
/code/foo/Rakefile:29: warning: already initialized constant CLEAN
/Users/foo/.rvm/gems/ruby-2.1.3/gems/rake-10.3.2/lib/rake/clean.rb:61: warning: previous definition of CLEAN was here
I don't like these warnings.. What is the right way?
CLEAN is a FileList that is used by the predefined clean task. To add your own files to be cleaned, add them to this list. You can use the include method:
require 'rake/clean'
CLEAN.include 'coverage'
Now running rake clean will remove your files, as well as the predefined set of temporary files if any have bean created.
'rake/clean' already defines the constant CLEAN like so: CLEAN = ::Rake::FileList["**/*~", "**/*.bak", "**/core"]. Constants aren't meant to be overridden (although ruby will let you). If you want to specify the files to be cleaned, you should create your own rake task similar the existing one.
The existing task runs:
Rake::Cleaner.cleanup_files(CLEAN)
So you could run:
Rake::Cleaner.cleanup_files(['coverage'])
to clean up your coverage files.

Rake delete files task

In msbuild I can delete part of files in certain directory like this
<ItemGroup>
<FilesToDelete Include="$(DeploymentDir)\**\*" exclude="$(DeploymentDir)\**\*.log"/>
</ItemGroup>
<Delete Files="#(FilesToDelete)" />
It will delete all files except *.txt
Is there some rake task I can similar thing?
Ruby has built in classes to make this easy:
Dir['deployment_dir/**/*'].delete_if { |f| f.end_with?('.txt') }
However, for some built in tasks, rake has helpers for this. Adapted from the API docs you can select files like so:
files_to_delete = FileList.new('deployment_dir/**/*') do |fl|
fl.exclude('*.txt')
end
Then you can feed this into your delete task.
Better yet, you can use the built in CLEAN/CLOBBER tasks:
# Your rake file:
require 'rake/clean'
# [] is alias for .new(), and we can chain .exclude
CLEAN = FileList['deployment_dir/**/*'].exclude('*.txt')
Then you can say on the cmd line:
rake clean
Read up the tutorial.
#adzdavies's answer is good, but assigning to CLEAN will produce the following warning since CLEAN is a constant:
warning: already initialized constant CLEAN
You should instead use CLEAN's instance methods. It is a Rake::FileList, so you can add something like this to your Rakefile:
require 'rake/clean'
# this is untested, but you get the idea
CLEAN.include('deployment_dir/**/*').exclude('*.txt')
Then run:
rake clean

How do I pipe my msbuild output to a log file from rake

I'm using the fabulous albacore gem with rake to build a new .NET project. My organization is still using NAnt, and there are lots of folks who expect to see a log file when the build script executes. How do I save the msbuild task output that gets dumped to STDOUT to a log file?
I figured out a solution. We don't really need a build log file for our CI server (hudson), but it would still be nice to have physical files to check when the build runs locally, particularly when we're doing the check-in dance and the build fails.
Fortunately, the albacore dudes were smart enough to create a ".parameters" option, which can be used with any of the command-line tool tasks to add parameters which aren't explicitly handled by that task. So, for example, you can add a parameter to the msbuild task to specify a logfile for MSBuild. And it goes a little something like this:
BUILD_REPORTS = 'BuildReports'
MSBUILD_EXE = "C:/Windows/Microsoft.NET/Framework/v4.0.30319/msbuild.exe"
directory BUILD_REPORTS
CLEAN.include BUILD_REPORTS
task :default => [:build]
desc "Build the solution"
msbuild :build => BUILD_REPORTS do |msb|
msb.properties :configuration => :Debug
msb.path_to_command = MSBUILD_EXE
msb.targets :Clean, :Build
msb.solution = "./mysolution.sln"
msb.parameters "/l:FileLogger,Microsoft.Build;logfile=" + log_file("build")
end
def log_file(log_file_name)
BUILD_REPORTS + log_file_name + ".log"
end
Our rakefile is a little more complex than that because it has to do more stuff, but you get the idea.

Resources