Search code examples
bazel

Can Bazel be instructed to use a single command for updating N targets?


The Google Bazel build tool makes it easy enough to explain that each CoffeeScript file in a particular directory tree needs to be compiled to a corresponding output JavaScript file:

[genrule(
    name = 'compile-' + f,
    srcs = [f],
    outs = [f.replace('src/', 'static/').replace('.coffee', '.js')],
    cmd = 'coffee --compile --map --output $$(dirname $@) $<',
) for f in glob(['src/**/*.coffee'])]

But given, say, 100 CoffeeScript files, this will invoke the coffee tool 100 separate times, adding many seconds to the compilation process. If instead it could be explained to Bazel that the coffee command can take many input files as input, then files could be batched together and offered to fewer coffee invocations, allowing the startup time of the process to be amortized over more files than just one.

Is there any way to explain to Bazel that coffee can be invoked with many files at once?


Solution

  • I haven't worked with coffee script, so this may need to be adjusted (particularly the --output @D part), but something like this might work:

    coffee_files = glob(['src/**/*.coffee'])
    
    genrule(
        name = 'compile-coffee-files',
        srcs = coffee_files,
        outs = [f.replace('src/', 'static/').replace('.coffee', '.js') for f in coffee_files],
        cmd = 'coffee --compile --map --output @D $(SRCS)' % coffee)
    

    Note that if just one input coffee script file is changed, the entire genrule will be rerun with all 100 files (the same as with, say, a java_library with 100 input java files).