包括使用相对路径生成的头文件



目前,我尝试使用Bazel(5.1.0(构建一个库,该库最初使用CMake作为构建系统。

当我试图使用相对路径(在CMake构建中,它使用configure_file(包含生成的头文件时,遇到了一个问题:

(下面的例子也可以在这里找到(

WORKSPACE.bazel:

workspace(name = "TemplateRule")

main.cpp

#include "kernels/bvh/some_header.h"
#include <iostream>
int main() {
std::cout << VERSION_STR << std::endl;
}

内核/bvh/some_header.h

#pragma once
// include config.h using a relative path
// if changed to kernels/config.h everything works as expected
// unfortunately, this is legacy code that I cannot change
#include "../config.h"    

config.h.in

#pragma once
#define VERSION_STR "@VERSION_STR@"

BUILD.bazel

load("//bazel:expand_template.bzl", "expand_template")
expand_template(
name = "config_h",
template = "config.h.in",
out = "kernels/config.h",
substitutions = {
"@VERSION_STR@": "1.0.3",
},
)
cc_binary(
name = "HelloWorld",
srcs = [
"main.cpp",
"kernels/bvh/some_header.h",
":config_h",
],
)

bazel/BUILD.bazel:<空>

bazel/expand_template.bzl:

# Copied from https://github.com/tensorflow/tensorflow/blob/master/third_party/common.bzl with minor modifications
# SPDX-License-Identifier: Apache-2.0
def expand_template_impl(ctx):
ctx.actions.expand_template(
template = ctx.file.template,
output = ctx.outputs.out,
substitutions = ctx.attr.substitutions,
)
_expand_template = rule(
implementation = expand_template_impl,
attrs = {
"template": attr.label(mandatory = True, allow_single_file = True),
"substitutions": attr.string_dict(mandatory = True),
"out": attr.output(mandatory = True),
},
output_to_genfiles = True,
)
def expand_template(name, template, substitutions, out):
_expand_template(
name = name,
template = template,
substitutions = substitutions,
out = out,
)

当我运行bazel build //...

我得到错误:

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"
|          ^~~~~~~~~~~~~

当我在main.cpp中包含config.h并将其从kernel/bvh/some_header.h中删除时,一切都按预期进行。

.../config.h的相对路径如何工作有什么想法吗?

创建文件config.h并手动编译代码可以按预期工作:

g++  main.cpp kernel/bvh/some_header.h config.h

根据最佳实践,应该避免使用..的相对路径,但您可以在使用CMake构建的遗留代码中找到这样的东西。这是巴泽尔的限制吗?或者有变通办法吗?

虽然在使用引号时搜索文件的行为和顺序在技术上是平台定义的,但在使用路径相对于包含文件的情况下,最常见的原则是。对于kernel/bvh/some_header.h,路径../config.h导致仅在kernel文件夹、工作文件夹或kernel/bvh/中搜索。某些编译器会检查替代位置。搜索顺序是编译器文档的一部分。

我曾经在这样的情况下看到在另一个标头kernel.h中使用../../config.h,它起到了作用。这是一项维修责任。kernel.h被移到了不同的位置,它选择了一个错误的文件夹和错误的文件,这导致ODR在项目时间线的晚些时候被破坏。其中一个实施了这一举措的人将../../config.h留在原地并复制了一份。一些单位使用旧的表头,而另一些单位则开始在新位置使用修改后的表头。

因此,不建议在库基础结构之外使用反向相对路径。相反,部分相对路径,例如kernel/config.h是优选的,假设核心文件夹将在包含路径的列表中。在实践中,实际项目可以使用预处理器宏,例如#include KERNEL_CONFIG_FILE。可以在freetype、boost等中看到一个插图

最新更新