目前,我尝试使用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等中看到一个插图