Skip to content

Commit 10fab24

Browse files
zygoloidjosh11b
andauthored
Add example showing basic interop with C++ RE2 library (#5967)
Co-authored-by: josh11b <[email protected]>
1 parent 870c538 commit 10fab24

File tree

4 files changed

+98
-6
lines changed

4 files changed

+98
-6
lines changed

bazel/carbon_rules/defs.bzl

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
"""Provides rules for building Carbon files using the toolchain."""
66

7+
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
8+
79
def _carbon_binary_impl(ctx):
810
toolchain_driver = ctx.executable.internal_exec_toolchain_driver
911
toolchain_data = ctx.files.internal_exec_toolchain_data
@@ -14,12 +16,40 @@ def _carbon_binary_impl(ctx):
1416
toolchain_driver = ctx.executable.internal_target_toolchain_driver
1517
toolchain_data = ctx.files.internal_target_toolchain_data
1618

19+
# Pass any C++ flags from our dependencies onto Carbon.
20+
dep_flags = []
21+
dep_hdrs = []
22+
dep_link_flags = []
23+
dep_link_inputs = []
24+
for dep in ctx.attr.deps:
25+
if CcInfo in dep:
26+
cc_info = dep[CcInfo]
27+
28+
# TODO: We should reuse the feature-based flag generation in
29+
# bazel/cc_toolchains here.
30+
dep_flags += ["--clang-arg=-D{0}".format(define) for define in cc_info.compilation_context.defines.to_list()]
31+
dep_flags += ["--clang-arg=-I{0}".format(path) for path in cc_info.compilation_context.includes.to_list()]
32+
dep_flags += ["--clang-arg=-iquote{0}".format(path) for path in cc_info.compilation_context.quote_includes.to_list()]
33+
dep_flags += ["--clang-arg=-isystem{0}".format(path) for path in cc_info.compilation_context.system_includes.to_list()]
34+
dep_hdrs.append(cc_info.compilation_context.headers)
35+
for link_input in cc_info.linking_context.linker_inputs.to_list():
36+
# TODO: `carbon link` doesn't support linker flags yet.
37+
# dep_link_flags += link_input.user_link_flags
38+
dep_link_inputs += link_input.additional_inputs
39+
for lib in link_input.libraries:
40+
dep_link_inputs += [dep for dep in [lib.dynamic_library, lib.static_library] if dep]
41+
dep_link_inputs += lib.objects
42+
if DefaultInfo in dep:
43+
dep_link_inputs += dep[DefaultInfo].files.to_list()
44+
dep_link_flags += [dep.path for dep in dep_link_inputs]
45+
1746
# Build object files for the prelude and for the binary itself.
1847
# TODO: Eventually the prelude should be build as a separate `carbon_library`.
1948
srcs_and_flags = [
2049
(ctx.files.prelude_srcs, ["--no-prelude-import"]),
21-
(ctx.files.srcs, []),
50+
(ctx.files.srcs, dep_flags),
2251
]
52+
2353
objs = []
2454
for (srcs, extra_flags) in srcs_and_flags:
2555
for src in srcs:
@@ -42,21 +72,21 @@ def _carbon_binary_impl(ctx):
4272
srcs_reordered = [s for s in srcs if s != src] + [src]
4373
ctx.actions.run(
4474
outputs = [out],
45-
inputs = srcs_reordered,
75+
inputs = depset(direct = srcs_reordered, transitive = dep_hdrs),
4676
executable = toolchain_driver,
4777
tools = depset(toolchain_data),
48-
arguments = ["compile", "--output=" + out.path] + [s.path for s in srcs_reordered] + extra_flags,
78+
arguments = ["compile", "--output=" + out.path, "--clang-arg=-stdlib=libc++"] + [s.path for s in srcs_reordered] + extra_flags,
4979
mnemonic = "CarbonCompile",
5080
progress_message = "Compiling " + src.short_path,
5181
)
5282

5383
bin = ctx.actions.declare_file(ctx.label.name)
5484
ctx.actions.run(
5585
outputs = [bin],
56-
inputs = objs,
86+
inputs = objs + dep_link_inputs,
5787
executable = toolchain_driver,
5888
tools = depset(toolchain_data),
59-
arguments = ["link", "--output=" + bin.path] + [o.path for o in objs],
89+
arguments = ["link", "--output=" + bin.path] + dep_link_flags + [o.path for o in objs],
6090
mnemonic = "CarbonLink",
6191
progress_message = "Linking " + bin.short_path,
6292
)
@@ -65,6 +95,7 @@ def _carbon_binary_impl(ctx):
6595
_carbon_binary_internal = rule(
6696
implementation = _carbon_binary_impl,
6797
attrs = {
98+
"deps": attr.label_list(allow_files = True, providers = [[CcInfo]]),
6899
# The exec config toolchain driver and data. These will be `None` when
69100
# using the target config and populated when using the exec config. We
70101
# have to use duplicate attributes here and below to have different
@@ -94,21 +125,26 @@ _carbon_binary_internal = rule(
94125
),
95126
"prelude_srcs": attr.label_list(allow_files = [".carbon"]),
96127
"srcs": attr.label_list(allow_files = [".carbon"]),
128+
"_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"),
97129
},
98130
executable = True,
99131
)
100132

101-
def carbon_binary(name, srcs):
133+
def carbon_binary(name, srcs, deps = [], tags = []):
102134
"""Compiles a Carbon binary.
103135
104136
Args:
105137
name: The name of the build target.
106138
srcs: List of Carbon source files to compile.
139+
deps: List of dependencies.
140+
tags: Tags to apply to the rule.
107141
"""
108142
_carbon_binary_internal(
109143
name = name,
110144
srcs = srcs,
111145
prelude_srcs = ["//core:prelude_files"],
146+
deps = deps,
147+
tags = tags,
112148

113149
# We synthesize two sets of attributes from mirrored `select`s here
114150
# because we want to select on an internal property of these attributes

core/prelude/types/string.carbon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import library "prelude/types/char";
99
import library "prelude/types/uint";
1010

1111
class String {
12+
fn Size[self: Self]() -> u64 { return self.size; }
13+
1214
// TODO: This should be an array iterator.
1315
private var ptr: Char*;
1416
// TODO: This should be a word-sized integer.

examples/re2_playground/BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
2+
# Exceptions. See /LICENSE for license information.
3+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
load("//bazel/carbon_rules:defs.bzl", "carbon_binary")
6+
7+
carbon_binary(
8+
name = "re2_playground",
9+
srcs = ["re2_playground.carbon"],
10+
tags = ["manual"],
11+
deps = ["@re2"],
12+
)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
2+
// Exceptions. See /LICENSE for license information.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
import Cpp library "re2/re2.h";
6+
7+
import Cpp inline '''c++
8+
// A wrapper around RE2 working around lack of:
9+
//
10+
// * Overloading support for the constructor.
11+
// * Non-null pointer support for the `submatch` parameter.
12+
struct WrapRE2 : re2::RE2 {
13+
WrapRE2(std::string_view v) : RE2(v) {}
14+
bool Match(absl::string_view text, size_t startpos, size_t endpos,
15+
Anchor re_anchor, absl::string_view* _Nonnull submatch,
16+
int nsubmatch) const {
17+
return RE2::Match(text, startpos, endpos, re_anchor, submatch, nsubmatch);
18+
}
19+
};
20+
''';
21+
22+
class RE2 {
23+
extend adapt Cpp.WrapRE2;
24+
fn Make(re: str) -> Self {
25+
return WrapRE2(re) as Self;
26+
}
27+
fn Match[self: Self](text: str) -> bool {
28+
var submatches: str;
29+
return (self as Cpp.WrapRE2).Match(text, 0, text.Size(), UNANCHORED, &submatches, 0);
30+
}
31+
}
32+
33+
fn Run() -> i32 {
34+
var re: RE2 = RE2.Make("^a*$");
35+
if (re.Match("aaaaaaaab")) {
36+
return 1;
37+
}
38+
if (not re.Match("aaaaaaaaa")) {
39+
return 1;
40+
}
41+
return 0;
42+
}

0 commit comments

Comments
 (0)