-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tree artifact as input for cc_library fails with headers #5092
Comments
@mhlopko Can you take a look? |
After careful studying of the documentation, I found a way to make things work. The rule documentation states that output to genfiles is deprecated, except when necessary and header files seem to be this exception. Splitting the output into load("@rules_antlr//antlr:antlr4.bzl", "antlr4", "headers", "sources")
antlr4(
name = "generated",
srcs = ["src/antlr4/Hello.g4"],
language = "Cpp",
)
headers(
name = "headers",
srcs = [":generated"],
)
sources(
name = "sources",
srcs = [":generated"],
)
cc_library(
name = "Cpp",
hdrs = [":headers"],
srcs = [":sources"],
includes = ["."],
) But it feels hacky as there is an extra step necessary to filter the output and there does not seem to be proper API support for directories in both output hierarchies (but I would therefore appreciate if someone could look into it and provide proper support for this (not exactly uncommon) use case. Thanks. |
I think the problem is that in your previous example you put headers into As currently implemented c++ rules assume that all files in the directory are source files. Is my guess making sense to you? |
It makes perfect sense, but that doesn't help :) While initially my workaround seemed to work, it really doesn't. While cc_library(
name = "lib",
hdrs = [":headers"],
srcs = [":sources"],
includes = ["."],
deps = ["@antlr4_runtimes//:cpp"],
)
cc_binary(
name = "Cpp",
srcs = ["src/main.cpp"],
includes = ["."],
deps = [":lib"],
)
There is mention about missing "generated header propagation" for 0.13.0. Does this apply to this use case? Right now I'm stuck. Any help would be appreciated. Thanks. BTW, this is how I split the sources. sources = ctx.actions.declare_directory(ctx.attr.name + _extension(ctx.attr.language))
output_dir = sources.path
# for C/C++ we must split headers from sources
if ctx.attr.language == "Cpp" or ctx.attr.language == "C":
artifacts = ctx.actions.declare_directory(ctx.attr.name + ".antlr")
# TODO headers currently must be stored below bazel-genfiles
headers = ctx.new_file(ctx.genfiles_dir, "")
# headers = ctx.actions.declare_directory(ctx.attr.name + ".hh")
outputs = [sources, headers, artifacts]
else:
outputs = [sources] The generated files tree looks like this:
|
Found the culprit for the original issue (srcs + hdrs together). Fix is in the pipeline. I'll still have to look into the second issue after the first fix it's submitted. |
Before, Bazel expected that it can compile whatever appeared in cc_library.srcs directory artifacts. That is true for C/C++ source files, and for headers when the C++ toolchain supported header parsing/processing (which used CppCompileAction). When the toolchain doesn't support header parsing/processing, Bazel would crash. Addresses issue #5092. One part of it. Fixes #5372. RELNOTES: None. PiperOrigin-RevId: 202114286
@mhlopko Thanks much for work! Just tried with HEAD.
load("@rules_antlr//antlr:antlr4.bzl", "antlr4")
antlr4(
name = "generated",
srcs = glob(["src/antlr4/*.g4"]),
language = "Cpp",
)
cc_library(
name = "lib",
srcs = [":generated"],
includes = ["."],
deps = ["@antlr4_runtimes//:cpp"],
) That works without issues. But consuming the library still fails. Not sure whether it's just a configuration problem, though. From the the error message (see below), it looks to me as there might already be a way to make it work, but I was not able to. I'm trying to compile the following source file:
#include <iostream>
#include "antlr4-runtime.h"
#include "TLexer.h"
#include "TParser.h"
using namespace antlr4;
int main(int , const char **) {
ANTLRInputStream input(u8"🍴 = 🍐 + \"😎\";(((x * π))) * µ + ∰; a + (x * (y ? 0 : 1) + z);");
TLexer lexer(&input);
CommonTokenStream tokens(&lexer);
tokens.fill();
for (auto token : tokens.getTokens()) {
std::cout << token->toString() << std::endl;
}
TParser parser(&tokens);
tree::ParseTree* tree = parser.main();
std::cout << tree->toStringTree(&parser) << std::endl << std::endl;
return 0;
}
...
cc_binary(
name = "Cpp",
srcs = ["src/main.cpp"],
deps = [":lib"],
) The generated file tree looks like this. bazel-bin/
└── antlr4
└── Cpp
├── generated.antlr
│ ├── TLexer.interp
│ ├── TLexer.tokens
│ ├── TParser.interp
│ └── TParser.tokens
└── generated.cc
├── TLexer.cpp
├── TLexer.h
├── TParserBaseListener.cpp
├── TParserBaseListener.h
├── TParser.cpp
├── TParser.h
├── TParserListener.cpp
└── TParserListener.h
|
hmmm maybe just precisely placed |
Before, Bazel expected that it can compile whatever appeared in cc_library.srcs directory artifacts. That is true for C/C++ source files, and for headers when the C++ toolchain supported header parsing/processing (which used CppCompileAction). When the toolchain doesn't support header parsing/processing, Bazel would crash. Addresses issue bazelbuild#5092. One part of it. Fixes bazelbuild#5372. RELNOTES: None. PiperOrigin-RevId: 202114286
Not quite. It only works if I split headers and sources. With the proper includes antlr4(
name = "generated",
srcs = glob(["src/antlr4/*.g4"]),
language = "Cpp",
package = "antlrcpptest",
)
headers(
name = "headers",
srcs = [":generated"],
)
sources(
name = "sources",
srcs = [":generated"],
)
cc_library(
name = "lib",
hdrs = [":headers"],
srcs = [":sources"],
includes = ["generated.hh/antlrcpptest"],
deps = ["@antlr4_runtimes//:cpp"]
)
cc_binary(
name = "bin",
srcs = ["src/cpp/main.cpp"],
deps = [":lib"],
) This limits the usage scenarios as the includes can't be dynamically determined from grammars (at least I don't see how I could feed this information back to the Skylark rule from my Java binary) and the usage feels a bit awkward, but at least there is a first working solution. Do you see any chance this could be made simpler? BTW, this is the ANTLR C++ project I'm trying to port to Bazel: https://github.com/antlr/antlr4/tree/master/runtime/Cpp/demo |
I've been pondering a bit more about the C++ support. I think the And there seems to be a way to simplify the process for the user via a custom toolchain. This is the route that rules_flex takes and as it might become an official Bazel project I guess it's the recommended approach. |
FYI, the final solution was amazingly simple. You just have to return a CcInfo provider with the compilation context! In the BUILD file you have to provide the generating rule as a dependency as well as input: cc_library(
name = "lib",
srcs = [":generated"],
deps = [
":generated",
"@antlr4_runtimes//:cpp",
],
) |
Using a tree artifact as input for
cc_library
does not work if the directory contains both sources and headers. If the directory only contains sources, it works fine.My expectation would be that it works for both cases. The following contrived example demonstrates the behavior:
tree.bzl
BUILD
The current bazel@HEAD yields the following exception:
The text was updated successfully, but these errors were encountered: