Merge "rust: Add rust_bindgen std version w/ cc defaults."

This commit is contained in:
Ivan Lozano 2020-09-25 13:11:34 +00:00 committed by Gerrit Code Review
commit ce2cffd583
2 changed files with 116 additions and 1 deletions

View file

@ -21,6 +21,7 @@ import (
"github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools"
"android/soong/android" "android/soong/android"
cc_config "android/soong/cc/config"
) )
var ( var (
@ -56,7 +57,11 @@ func init() {
var _ SourceProvider = (*bindgenDecorator)(nil) var _ SourceProvider = (*bindgenDecorator)(nil)
type BindgenProperties struct { type BindgenProperties struct {
// The wrapper header file // The wrapper header file. By default this is assumed to be a C header unless the extension is ".hh" or ".hpp".
// This is used to specify how to interpret the header and determines which '-std' flag to use by default.
//
// If your C++ header must have some other extension, then the default behavior can be overridden by setting the
// cpp_std property.
Wrapper_src *string `android:"path,arch_variant"` Wrapper_src *string `android:"path,arch_variant"`
// list of bindgen-specific flags and options // list of bindgen-specific flags and options
@ -81,6 +86,22 @@ type BindgenProperties struct {
// "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]" // "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]"
Custom_bindgen string `android:"path"` Custom_bindgen string `android:"path"`
// C standard version to use. Can be a specific version (such as "gnu11"),
// "experimental" (which will use draft versions like C1x when available),
// or the empty string (which will use the default).
//
// If this is set, the file extension will be ignored and this will be used as the std version value. Setting this
// to "default" will use the build system default version. This cannot be set at the same time as cpp_std.
C_std *string
// C++ standard version to use. Can be a specific version (such as
// "gnu++11"), "experimental" (which will use draft versions like C++1z when
// available), or the empty string (which will use the default).
//
// If this is set, the file extension will be ignored and this will be used as the std version value. Setting this
// to "default" will use the build system default version. This cannot be set at the same time as c_std.
Cpp_std *string
//TODO(b/161141999) Add support for headers from cc_library_header modules. //TODO(b/161141999) Add support for headers from cc_library_header modules.
} }
@ -90,6 +111,45 @@ type bindgenDecorator struct {
Properties BindgenProperties Properties BindgenProperties
} }
func (b *bindgenDecorator) getStdVersion(ctx ModuleContext, src android.Path) (string, bool) {
// Assume headers are C headers
isCpp := false
stdVersion := ""
switch src.Ext() {
case ".hpp", ".hh":
isCpp = true
}
if String(b.Properties.Cpp_std) != "" && String(b.Properties.C_std) != "" {
ctx.PropertyErrorf("c_std", "c_std and cpp_std cannot both be defined at the same time.")
}
if String(b.Properties.Cpp_std) != "" {
if String(b.Properties.Cpp_std) == "experimental" {
stdVersion = cc_config.ExperimentalCppStdVersion
} else if String(b.Properties.Cpp_std) == "default" {
stdVersion = cc_config.CppStdVersion
} else {
stdVersion = String(b.Properties.Cpp_std)
}
} else if b.Properties.C_std != nil {
if String(b.Properties.C_std) == "experimental" {
stdVersion = cc_config.ExperimentalCStdVersion
} else if String(b.Properties.C_std) == "default" {
stdVersion = cc_config.CStdVersion
} else {
stdVersion = String(b.Properties.C_std)
}
} else if isCpp {
stdVersion = cc_config.CppStdVersion
} else {
stdVersion = cc_config.CStdVersion
}
return stdVersion, isCpp
}
func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path { func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
ccToolchain := ctx.RustModule().ccToolchain(ctx) ccToolchain := ctx.RustModule().ccToolchain(ctx)
@ -134,6 +194,17 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr
ctx.PropertyErrorf("wrapper_src", "invalid path to wrapper source") ctx.PropertyErrorf("wrapper_src", "invalid path to wrapper source")
} }
// Add C std version flag
stdVersion, isCpp := b.getStdVersion(ctx, wrapperFile.Path())
cflags = append(cflags, "-std="+stdVersion)
// Specify the header source language to avoid ambiguity.
if isCpp {
cflags = append(cflags, "-x c++")
} else {
cflags = append(cflags, "-x c")
}
outputFile := android.PathForModuleOut(ctx, b.BaseSourceProvider.getStem(ctx)+".rs") outputFile := android.PathForModuleOut(ctx, b.BaseSourceProvider.getStem(ctx)+".rs")
var cmd, cmdDesc string var cmd, cmdDesc string

View file

@ -82,3 +82,47 @@ func TestRustBindgenCustomBindgen(t *testing.T) {
libbindgen.Description) libbindgen.Description)
} }
} }
func TestRustBindgenStdVersions(t *testing.T) {
testRustError(t, "c_std and cpp_std cannot both be defined at the same time.", `
rust_bindgen {
name: "libbindgen",
wrapper_src: "src/any.h",
crate_name: "bindgen",
stem: "libbindgen",
source_stem: "bindings",
c_std: "somevalue",
cpp_std: "somevalue",
}
`)
ctx := testRust(t, `
rust_bindgen {
name: "libbindgen_cstd",
wrapper_src: "src/any.h",
crate_name: "bindgen",
stem: "libbindgen",
source_stem: "bindings",
c_std: "foo"
}
rust_bindgen {
name: "libbindgen_cppstd",
wrapper_src: "src/any.h",
crate_name: "bindgen",
stem: "libbindgen",
source_stem: "bindings",
cpp_std: "foo"
}
`)
libbindgen_cstd := ctx.ModuleForTests("libbindgen_cstd", "android_arm64_armv8-a").Output("bindings.rs")
libbindgen_cppstd := ctx.ModuleForTests("libbindgen_cppstd", "android_arm64_armv8-a").Output("bindings.rs")
if !strings.Contains(libbindgen_cstd.Args["cflags"], "-std=foo") {
t.Errorf("c_std value not passed in to rust_bindgen as a clang flag")
}
if !strings.Contains(libbindgen_cppstd.Args["cflags"], "-std=foo") {
t.Errorf("cpp_std value not passed in to rust_bindgen as a clang flag")
}
}