Search code examples
bazeldrake

Are there any recommendations to prevent drake from rebuilding when using it as an External via Bazel?


Platform: Ubuntu 22.04 Drake Version: 1.22.0v

I am using drake as an external library via bazel and have set up my project mirroring the format described in this example: https://github.com/RobotLocomotion/drake-external-examples/tree/main/drake_bazel_external. However, it seems the drake dependences are frequently being rebuilt and causing long build times even if no changes are made. I am using VSCode and building via the in-built terminal. The built drake cache remains typically for 1-2 days but the cache seems to no longer be valid afterwards and causes especially long build times for targets using pydrake. I unfortunately can not use the precompiled drake binaries since I am using pybind. Any suggestions on how to prevent bazel from building drake more than once would be greatly appreciated, thanks in advance!


Solution

  • Tough to say without more info on exactly when the putatively-spurous rebuilds happen. Things should only rebuild when something that affects them changes. That could be simple things like Debug vs Release or changing environment variables like $CC or $CXX, or something intricate with VSCode internals.

    By default, Bazel has a build cache per workspace which keeps only the latest version of any target. It won't rebuild things that it has already build exactly the same the most recent time around, but if you swap between different build configs, or between branches of your code, it won't resurrect the old artifacts beyond the most recent one.

    To improve on that, many Drake developers instead opt-in to a permanent disk cache, which remembers everything you've ever built. Then if you switch branches a lot, it might still have cache hits from last time.

    To do that, use the "disk_cache" flag in your $HOME/.bazelrc. Here's my rcfile by way of example:

    build --keep_going
    build --jobs=HOST_CPUS*0.8
    fetch --repository_cache /home/myusername/.cache/bazel-externals
    fetch --disk_cache /home/myusername/.cache/bazel_local_disk
    build --repository_cache /home/myusername/.cache/bazel-externals
    build --disk_cache /home/myusername/.cache/bazel_local_disk
    

    The last line is one that matters most here.

    The downside of the disk cache is that nothing (yet) cleans it up automatically. (See https://github.com/bazelbuild/bazel/issues/5139.) Therefore, you need to keep an eye on your disk space and rm -rf the bazel_local_disk when its too big.

    I also put the cache on a second SSD drive (not my $HOME drive) to help segregate it.

    The disk_cache would help in case the root cause is swapping between options or versions. If the root cause is that something build input is completely novel, no kind of cache can help with that.

    Possibly other Bazel experts know tricks for "Ask Bazel why its rebuilding stuff that I thought I'd already built".