9
$ python gencpp.py 

This command generates a cpp file foo.cpp in the working directory.

I'd like to run this command in bazel before building to be able to include foo.cpp in cc_binary's srcs attribute.

What I've tried:

genrule(
    name = 'foo',
    outs = ['foo.cpp'],
    cmd = 'python gencpp.py',
)

cc_library(
    srcs = ['foo.cpp'], # tried also with :foo
    ...
)

declared output 'external/somelib/foo.cpp' was not created by genrule. This is probably because the genrule actually didn't create this output, or because the output was a directory and the genrule was run remotely (note that only the contents of declared file outputs are copied from genrules run remotely).

I know that there is a solution that requires gencpp.py to be modified a little bit, but it's not what I'm looking for.

Ghilas BELHADJ
  • 13,412
  • 10
  • 59
  • 99
  • I had quite a similar problem [stackoverflow/bazel-automatically-generated-cpp-hpp-files](https://stackoverflow.com/questions/44312549/bazel-automatically-generated-cpp-hpp-files). The given answers may complete those given here. – Picaud Vincent Jun 02 '17 at 06:01

2 Answers2

5

This command generates a cpp file foo.cpp in the working directory.

I would recommend that you change this, so that either:

  • You write the output to a file specified by a command-line flag
  • You write the output to standard output, and redirect standard output to a file

Then your genrule command can be either:

python gencpp.py --outputFile=$@

or

python gencpp.py > $@

(My general personal preference is for the latter, although that can't be used in cases where multiple outputs need to be written.)

respectively.

As Ulf Adams points out:

Bazel runs multiple actions in parallel, and if the same rule is a dependency of a tool as well as of an app, it may try to run both at the same time, and they'd overwrite each other, with potentially very bad results.

So, writing output files which bazel doesn't directly know about is best avoided.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • 2
    It's actually worse. Bazel runs multiple actions in parallel, and if the same rule is a dependency of a tool as well as of an app, it may try to run both at the same time, and they'd overwrite each other, with potentially very bad results. (Though not if sandboxing is enabled.) – Ulf Adams Feb 17 '17 at 20:54
  • @UlfAdams "It's actually worse" as in "my suggestion is worse", or as in "the consequences of writing and copying are worse than I suggest"? – Andy Turner Feb 17 '17 at 20:58
  • 1
    The latter. The consequences of writing to the current directory and then copying or moving to the destination can lead to silent breakage. – Ulf Adams Feb 17 '17 at 20:59
  • @UlfAdams does my edit capture what you're trying to say? – Andy Turner Feb 17 '17 at 21:02
2

Thank's to @kristina for the answer.

I have to copy foo.cpp to outs directory once it's generated.

genrule(
    name = 'foo',
    outs = ['foo.cpp'],
    cmd = """
            python gencpp.py
            cp foo.cpp $@
    """,

)
Ghilas BELHADJ
  • 13,412
  • 10
  • 59
  • 99
  • the copy trick worked for me too. Beware that when you have several outs (my script generates C++ code, one hpp file and one cpp file) you must use: cp file.hpp $(@D); cp file.cpp $(@D); – Picaud Vincent May 31 '17 at 22:53