Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Bazel project with a Data repository

Tags:

c++

bazel

I have a (basic) C++ project:

├── bin
│   ├── BUILD
│   ├── example.cpp
├── data
│   └── someData.txt
└── WORKSPACE

where the executable example.cpp use some data files from data/ directory:

#include <fstream>
#include <iostream>

int main()
{
  std::ifstream in("data/someData.txt");

  if (!in)
  {
    std::cerr << "Can not open file!";
    return EXIT_FAILURE;
  }

  std::string message;

  if (!(in >> message))
  {
    std::cerr << "Can not read file content!";
    return EXIT_FAILURE;
  }

  std::cout << message << std::endl;

  return EXIT_SUCCESS;
}

My Bazel setup is the minimal one:

  • WORKSPACE: empty file
  • bin/BUILD: cc_binary(name = "example",srcs = ["example.cpp"])
  • data/someData.txt: contains the Hello_world! line

The problem is that Bazel moves all these files in special locations:

.
├── bazel-Bazel_with_Data -> ...
├── bazel-bin -> ...
├── bazel-genfiles -> ...
├── bazel-out -> ...
├── bazel-testlogs -> ...

In peculiar the example executable will not found the data/someData.txt file:

bazel run bin:example

will print:

INFO: Analysed target //bin:example (0 packages loaded).
INFO: Found 1 target...
Target //bin:example up-to-date:
  bazel-bin/bin/example
INFO: Elapsed time: 0.101s, Critical Path: 0.00s
INFO: Build completed successfully, 1 total action

INFO: Running command line: bazel-bin/bin/example
Can not open file!ERROR: Non-zero return code '1' from command: Process exited with status 1

The question is how to manage this?

I want the example executable to be able to find the Data/someData.txt file.

like image 853
Picaud Vincent Avatar asked Sep 07 '17 16:09

Picaud Vincent


2 Answers

CAVEAT: it seems this solution does not work under Windows (see comments).

One must create an extra BUILD file in the data directory that defines what data files must be exported. The project structure is now:

├── bin
│   ├── BUILD
│   ├── example.cpp
├── data
│   ├── BUILD
│   └── someData.txt
└── WORKSPACE

This new data/BUILD file is:

exports_files(["someData.txt"])

And the bin/BUILD file is modified to add the someData.txt dependency:

cc_binary(
    name = "example",
    srcs = ["example.cpp"],
    data = ["//data:someData.txt"],
)

Now if you run:

bazel run bin:example

you should get:

INFO: Analysed target //bin:example (2 packages loaded).
INFO: Found 1 target...
Target //bin:example up-to-date:
  bazel-bin/bin/example
INFO: Elapsed time: 0.144s, Critical Path: 0.01s
INFO: Build completed successfully, 3 total actions

INFO: Running command line: bazel-bin/bin/example
Hello_world!

meaning that the example executable has found the data/someData.txt file and printed its content.

Also note that you can use the same scheme for unit testing with

 cc_test(...,data =["//data:someData.txt"], )

You can reproduce this note from this GitHub repo.

like image 72
Picaud Vincent Avatar answered Oct 02 '22 15:10

Picaud Vincent


On Windows try:

bazel run --enable_runfiles

More details can be found here.

You can add this also to a .bazelrc file:

build:myconfig --enable_runfiles

Build on Windows this way:

bazel build --config=myconfig //...

Also the runfile lib is an option.

like image 39
Vertexwahn Avatar answered Oct 02 '22 16:10

Vertexwahn