2

I'm using rake to help compile Coffeescript for a Chrome extension I'm writing.

My Rakefile looks like this:

COFFEE = FileList['src/*.coffee']
JS = COFFEE.ext 'js'

directory 'extension'

rule '.js' => ['.coffee', 'extension'] do |t|
  `coffee -c -o extension #{t.source}`
end

desc "Build the extension in the 'extension' directory"
task :build => ['extension', JS] do
  cp File.join('src', 'manifest.json'), 'extension'
end

When I only have one .coffee file in my src directory, there's no problem. But as soon as I have more than one .coffee files it errors:

$ rake build
> rake aborted!
> Don't know how to build task 'src/app.js src/background.js'
>
> Tasks: TOP => build
> (See full trace by running task with --trace)

Is it possible to specify a FileList as a dependency? How else would I tell rake that I want all my Coffeescript files compiled durring the build task?

4

4 回答 4

8

Rake’s dependency list is an Array of task names. When you use a FileList as one of its elements, you nest arrays – effectively, this:

task :build => ['extension', ['src/app.js', 'src/background.js']] do

Rake just uses the String representation of all passed dependency Array elements, which is why it complains about being unable to build a 'src/app.js src/background.js' task (note how this is one string).

Splatting your FileList (or flattening the dependency Array) will solve the issue, i.e.:

task :build => ['extension', *JS] do

or

task :build => ['extension', JS].flatten do
于 2013-01-26T22:00:09.283 回答
1

Try this:

files = Dir.entries('path/to/scripts').select { |f| f.include? '.coffee' }
files.each do |file_path|
  `coffee -c -o extension #{file_path}`
end
于 2013-01-25T20:03:05.017 回答
0

So far in my search it looks like the only way to accomplish what I want is to either have a task which loops through my FileList and compiles each one explicitly (like in the answer from @nicooga). Or, I can loop through everything in the FileList and add it as a dependency to the build task.

I don't like either of these because rake has FileLists for getting groups of files, rules for defining how to handle kinds of files, and a nice syntax for defining dependencies, but apparently no way to combine all three of those together.

So, my solution for now is to go with the second option, adding each file as a dependency. The shortest way I've found to do this is to concat the FileList onto the dependency array. So now my build task looks like this:

task :build => ['extension'].concat(JS) do
  cp File.join('src', 'manifest.json'), 'extension'
end

And thanks to the comment by @kopischke, this can even be shortened to ['extension' *JS] using the splat operator.

于 2013-01-26T07:37:39.573 回答
0

Late to the game, but a FileList is lazy, and that is useful, especially if you have lots of file matching. Think of C or C++ where you potentially can have many that require dependencies.

Most of the answers here require the FileList to be expanded/evaluated. Since Rake is Ruby and task is where the last argument is basically a Hash, you will be evaluating the array.

One of the answers suggests ['extension', JS].flatten. This approach will search the directory and collect all the .js files. This approach is fine when you have a task that will always get executed/invoked. However, you don't want to evaluate the FileList and invoke its search if the task is will not get executed/invoked.

The best way to use a FileList is the following

fl = FileList['extension', "src/*.coffee"] do |c|
   c.ext('js')
end
file "somefile" => fl do
   #some stuff
end

Then if "somefile" doesn't exist, or the "somefile" task is not even invoked, the read of your Rakefile doesn't invoke the FileList expansion, saving a bunch of time.

于 2019-09-27T15:18:55.483 回答