Getting cc_binary artefacts

101 views
Skip to first unread message

Denys Smirnov

unread,
Jan 10, 2023, 12:18:39 PM1/10/23
to bazel-discuss
Hi all,

TL;DR: How to get all the virtual includes used by cc_binary/cc_library rules?

I'm trying to conveniently use Bazel for competitive programming purposes.
One can say that it's overthinking, but I'm mostly curious of boundaries Bazel allows me to explore rather than having substantial request.

Here's some background: usually competitive programming contests take some input in given format from stdin and print output in stdout. Judge systems usually accepts several languages, however the primary one is bare cpp. For the local development it's handy to automate some testing as well as use prewritten code (rules vary between the systems, but the majority accepts prewritten code).

I already implemented rule that takes Bazel executable target and tests it against all pairs of tests (represented with pair of text files) with default checker and interactor. That comes in handy to test sources I just created.

When it comes to combining all code I used, usually it's either jump-to-definition + copy/paste library, however it can be exhausting to do if library is huge. I already have a tool that combines all the library headers into a single file, however I still need to pass all path members to search at. It works like following:

./expander -I path/to/lib1 -I path/to/lib2 source.cpp -o expanded.cpp

Can I get those -Is from Bazel? More specifically, can I took all cc_binary/cc_library header paths to pass them into my script that expanding those files?

Best,
Denys.

Phil Schrader

unread,
Jan 17, 2023, 1:29:53 PM1/17/23
to bazel-discuss
Does something like this give you what you want?
$ bazel cquery --output=starlark --starlark:expr='providers(target)["CcInfo"].compilation_context.system_includes' //path/to:cc_binary

You can get different includes information as documented here:

You can also make the starlark code more expressive by using --starlark:file instead.
I.e. you can iterate over the elements in the depset and print them out on unique lines etc.

Phil

Denys Smirnov

unread,
Jan 18, 2023, 12:22:35 PM1/18/23
to bazel-discuss
Thanks, Phill!

I managed to achieve everything I wanted with two files:

includes.cquery:
"""Expands all includes associated with cc_(library|binary) target.
"""

def format(target):
result = []
for include in providers(target)["CcInfo"].compilation_context.includes.to_list():
result.append("-I=" + include)
return ' '.join(result)


expand.sh:
#! /usr/bin/env bash -eu

SOURCE=$(bazel query $1)
TARGETS=$(bazel query "attr('srcs', $SOURCE, ${SOURCE//:*/}:*)")
TARGET=$(echo $TARGETS | awk '{print $1;}')

bazel build ${TARGET}
bazel run //tools/expander -- \
  $(bazel cquery --output=starlark --starlark:file=includes.cquery ${TARGET) \
  --cwd=$(bazel info workspace) \
  $(realpath $1)

Note that I need to supply workspace to my script, so it have access to virtual includes under bazel-out/ and absolute path to source, however it's fine.
I was wondering if there's any chance of bundling it all to a single rule/macro so I can reference it in BUILD file like following:

cp_expanded(
    name = "expanded",
    source = ":my-source.cpp",
)

Best,
Denys.
Reply all
Reply to author
Forward
0 new messages