Include a generated a header file using a relative path

  bazel, bazel-rules, c++, include

Currently, I try to build a library with Bazel (4.1.0) that originally uses CMake as a build system.

I am running into a problem when trying to include a generated a header file using a relative path (in the CMake build it uses configure_file):

WORKSPACE.bazel:

workspace(name = "TemplateRule")

main.cpp:

#include "kernel/some_header.h"
#include <iostream>

int main() {
    std::cout << VERSION_STR << std::endl;
}

kernel/some_header.h:

#pragma once

#include "../config.h"   // <---- include config.h using a relative path

config.h.in:

#pragma once

#define VERSION_STR "@[email protected]"

BUILD.bazel

load("//bazel:template_rule.bzl", "template_rule")

template_rule(
    name = "config_h",
    src = "config.h.in",
    out = "config.h",
    substitutions = {
        "@[email protected]": "1.0.3",
    },
)

cc_binary(
    name = "HelloWorld",
    srcs = [
        "main.cpp",
        "kernel/some_header.h",
        ":config_h",
    ],
)

bazel/BUILD.bazel: < empty >

bazel/template_rule.bzl:

# Copied from https://github.com/tensorflow/tensorflow/blob/master/third_party/common.bzl

'''
    Copyright 2019 The TensorFlow Authors. All Rights Reserved.
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
'''
    
def template_rule_impl(ctx):
    out = ctx.outputs.out
    ctx.actions.expand_template(
        template = ctx.file.src,
        output = ctx.outputs.out,
        substitutions = ctx.attr.substitutions,
    )
    return [CcInfo(
        compilation_context = cc_common.create_compilation_context(
            includes = depset([out.dirname]),
            headers = depset([out]),
        ),
    )]

template_rule = rule(
    attrs = {
        "src": attr.label(
            mandatory = True,
            allow_single_file = True,
        ),
        "substitutions": attr.string_dict(mandatory = True),
        "out": attr.output(mandatory = True),
    },
    # output_to_genfiles is required for header files.
    output_to_genfiles = True,
    implementation = template_rule_impl,
)

When I run bazel build //...

I get the error:

In file included from main.cpp:1:
kernel/some_header.h:3:10: fatal error: ../config.h: No such file or directory
    3 | #include "../config.h"
      |          ^~~~~~~~~~~~~

When I include config.h in main.cpp and remove it from kernel/some_header.h everything works as expected.

Any ideas how to the relative path .../config.h working?

Source: Windows Questions C++

LEAVE A COMMENT