Show how to declare and execute a binary, how to declare a library, and how to declare and run a test.
In this example we have declared 3 targets. A library, an application and a test. The binary and the test depends on the library.
-
//:lib: A Pyhton library. It can be defined in Bazel as follows:py_library( name = "lib", srcs = [ "__init__.py", "lib.py", ], )
nameis the name for the target.srcsis the list of Python files needed to generate the library. -
//:bin: A binary that depends on the library mentioned above. It can be defined in Bazel as follows:py_binary( name = "bin", srcs = ["bin.py"], deps = [":lib"], )
nameis the name for the target, it will also be used to identify which of thesrcsfiles is the entry point of the application.srcsis the list of source files needed to generate the target. The file that has the same name like the target is considered the entry point of the application.py_binaryhas also the option to specify the parametermainto specify which file is the entry point of the application.depsis the list of libraries that the binary depends on. In this case we specify the target:libthat is the library that we want to use in this binary. -
//:test: A test forlibtarget. In the end it is very similar to apy_binarybut Bazel will treat it different in several aspects. It can be defined in Bazel as follows:py_test( name = "test", srcs = ["test.py"], deps = [":lib"], )
nameis the name for the target, likepy_binaryit will also be used to identify which of thesrcsfiles is the entry point of the application.py_testalso allows to definemainas a parameter.srcsis the list of source files needed to generate the test target. The requirement like a binary is that it has to contain a__main__function (if __name__ == "__main__":). If it exits with a 0 it is considered that the test passed, otherwise is considered as failure.depslike for the binary, is the list of libraries that your test depends on.
To have a good experience with Bazel and Python, the flag --incompatible_default_to_explicit_init_py needs to be set in the .bazelrc file.
Otherwise, Bazel will automatically create __init__.py files in ever single folder of the output tree that contains Python code.
This might lead to unexpected behavior and importing problems.
The recomendation is that if you need empty __init__.py files in the source code, you just add them on your own.
If you are on Windows and you use rules_python >= 2.0, you will have to also set --windows_enable_symlinks to enable symbolic links, otherwise Python in Bazel will not work.
Additionally, Windows need to be in Developer Mode otherwise it is not possible to create symbolic links.
To run the application you call:
bazel run //:binIt will run the application and display the output on the terminal.
To run the test you call:
bazel test //:testIt will run the test without showing any output from the test but a Bazel output indicating if the test succeeded or failed.
//:test PASSED in 0.0sA test, compared to an application executed with bazel run will not be allways executed. If Bazel detects that nothing changed it will cache the result of the test and show it in the report.
//:test (cached) PASSED in 0.0s