are for loops allowed in build files?

5,219 views
Skip to first unread message

Francis Hitchens

unread,
Jun 19, 2017, 11:33:53 AM6/19/17
to bazel-discuss
Hi,

I wrote this nice little for loop to remove hundreds of lines of boilerplate from my BUILD files.

[cc_library(
    name = "%s" % d, 
    hdrs = glob(["%s/inc/*.h" % d, "%s/inc/*.ph" % d,]),
    includes = ["%s/inc" % d,],
) for d in ["aa", "bb", "cc", "dd", "ee", "ff", "gg", "hh", "ii", "etc",]]


After that I found this statement in the build-ref.html document...

Many Python features are missing: control-flow constructs (loops, conditionals, exceptions), basic datatypes (floating-point numbers, big integers), import and the module system, support for definition of classes, some Python's built-in functions. Function definitions and for statements are allowed only in extension files (.bzl). Available functions are documented in the library section.

Am I safe to use the for loop in a BUILD files?

regards, Francis.

Marcel Hlopko

unread,
Jun 19, 2017, 11:46:14 AM6/19/17
to Francis Hitchens, bazel-discuss, laur...@google.com
Hi Francis,

yup you're perfectly fine. What you did is what we call BUILD macros, and they are supported. What the comment says is about the Skylark language used to write new rules, and the idea there is that Skylark is by design not Touring complete, so it will always halt, and is deterministic (as far as we could make it so). Any source of non-determinism (such as random numbers) is removed from the language. Summoning +Laurent Le Brun to verify I'm not lying :)

--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/ddd3af3d-b3ec-4424-b804-77064e89b605%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
-- 
Marcel Hlopko | Software Engineer | hlo...@google.com | 

Google Germany GmbH | Erika-Mann-Str. 33  | 80636 München | Germany | Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle | Registergericht und -nummer: Hamburg, HRB 86891

Laurent Le Brun

unread,
Jun 19, 2017, 11:54:59 AM6/19/17
to Marcel Hlopko, Francis Hitchens, bazel-discuss
What you use is a list comprehension. It's the only kind of loop
allowed in BUILD files.

A "for statement" is something like:
for d in ["aa", "bb", "cc"]:
cc_library(...)

This is not allowed in BUILD files (that's what the documentation said).
We should try to clarify it a bit.

Thanks for the feedback!
--
Laurent

Jon Brandvein

unread,
Jun 19, 2017, 10:40:41 PM6/19/17
to bazel-discuss, hlo...@google.com, fhit...@gmail.com
Just a note on style: The reason for loops are disallowed in BUILD files is that we want them to be pretty straightforward declarations, rather than programmatic logic. Using list comprehensions is kind of a loophole in that regard.

It'd be better style to put your loop in a macro, and call that macro, so that the BUILD file itself resembles any other BUILD file -- just a flat series of function calls.

Francis Hitchens

unread,
Jun 20, 2017, 5:26:26 PM6/20/17
to bazel-discuss, hlo...@google.com, fhit...@gmail.com
I'll try that and see what it looks like.

Thanks, Francis.

Austin Schuh

unread,
Jun 21, 2017, 6:49:56 PM6/21/17
to Jon Brandvein, bazel-discuss, hlo...@google.com, fhit...@gmail.com
On Mon, Jun 19, 2017 at 7:40 PM 'Jon Brandvein' via bazel-discuss <bazel-...@googlegroups.com> wrote:
Just a note on style: The reason for loops are disallowed in BUILD files is that we want them to be pretty straightforward declarations, rather than programmatic logic. Using list comprehensions is kind of a loophole in that regard.

It'd be better style to put your loop in a macro, and call that macro, so that the BUILD file itself resembles any other BUILD file -- just a flat series of function calls.

There are a couple places in our code base where we have to build a cc_library twice with different macros defined, or other small changes.  We've been using the list comprehension loops instead, but that's not very readable.

For example (not tested, so excuse any syntax errors)

[cc_library(name = 'mylib_' + n,
    srcs = [
      'foo.cc'
    ],
    hdrs = [
      'foo.h'
    ],
    defines = [
      'MYDEFINE=' + d,
    ],
    deps = [
      '//base',
    ]) for n, d in [['one', 1], ['two', 2]]]

Pulling those out into a skylark macro would hamper readability in my opinion, since it would be a 2 use macro, and require the user to open another file to figure out what they mean.

Is there a cleaner way to do this?

Austin

László Csomor

unread,
Jun 22, 2017, 2:53:04 AM6/22/17
to Austin Schuh, Jon Brandvein, bazel-discuss, Marcel Hlopko, Francis Hitchens
Hi Austin,

I think the list comprehension as you've shown is the best (cleanest, most readable) approach here, and I'm not aware of anything nicer.


--
László Csomor | Software Engineer | laszlo...@google.com


Google Germany GmbH | Erika-Mann-Str. 33 | 80636 München | Germany
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg

Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle

--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discuss+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/CABsbf%3DF_ra0gH76%2BK1URGzLZG1G5%2BvntUgZVB%3Dxi7a-k7tSwHA%40mail.gmail.com.

Jon Brandvein

unread,
Jun 22, 2017, 8:06:32 AM6/22/17
to László Csomor, Austin Schuh, bazel-discuss, Marcel Hlopko, Francis Hitchens
Pulling those out into a skylark macro would hamper readability in my opinion, since it would be a 2 use macro, and require the user to open another file to figure out what they mean.

Current style guide thinking is that it's better to either 1) use a one-off macro, or 2) if the number of targets to created is small, just inline them into the BUILD file without a loop at all. But the choice is yours.

Laurent Le Brun

unread,
Jun 23, 2017, 8:42:38 AM6/23/17
to Jon Brandvein, László Csomor, Austin Schuh, bazel-discuss, Marcel Hlopko, Francis Hitchens
For the example above, I really recommend inlining the definitions:

cc_library(
name = "mylib_one",
srcs = ["foo.cc"],
hdrs = ["foo.h"],
defines = ["MYDEFINE=1"],
deps = ["//base"],
)

cc_library(
name = "mylib_two",
srcs = ["foo.cc"],
hdrs = ["foo.h"],
defines = ["MYDEFINE=2"],
deps = ["//base"],
)

That's simple and declarative.
If you have a large number of targets, you may prefer alternatives.
But for small numbers, inlining typically works best.


On 22 June 2017 at 14:06, 'Jon Brandvein' via bazel-discuss
>>> email to bazel-discus...@googlegroups.com.
> --
> You received this message because you are subscribed to the Google Groups
> "bazel-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to bazel-discus...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/bazel-discuss/CAEoyresUz0gJpXY1COF07qwG5JzCwW10HasxqADi1mpBb4Lx3w%40mail.gmail.com.
>
> For more options, visit https://groups.google.com/d/optout.



--
Laurent
Reply all
Reply to author
Forward
0 new messages