Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e21ca0a authored by Ivan Lozano's avatar Ivan Lozano Committed by Gerrit Code Review
Browse files

Merge "rust: Support for generated c files from bindgen" into main

parents 5fea5684 3b591c77
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -608,6 +608,10 @@ func transformSourceToObj(ctx ModuleContext, subdir string, srcFiles, noTidySrcs
			ccCmd = "clang++"
			moduleFlags = cppflags
			moduleToolingFlags = toolingCppflags
		case ".rs":
			// A source provider (e.g. rust_bindgen) may provide both rs and c files.
			// Ignore the rs files.
			continue
		case ".h", ".hpp":
			ctx.PropertyErrorf("srcs", "Header file %s is not supported, instead use export_include_dirs or local_include_dirs.", srcFile)
			continue
+51 −9
Original line number Diff line number Diff line
@@ -102,8 +102,17 @@ type BindgenProperties struct {
	// "my_bindgen [flags] wrapper_header.h -o [output_path] -- [clang flags]"
	Custom_bindgen string

	// flag to indicate if bindgen should handle `static inline` functions (default is false)
	Handle_static_inline bool
	// flag to indicate if bindgen should handle `static inline` functions (default is false).
	// If true, Static_inline_library must be set.
	Handle_static_inline *bool

	// module name of the corresponding cc_library_static which includes the static_inline wrapper
	// generated functions from bindgen. Must be used together with handle_static_inline.
	//
	// If there are no static inline functions provided through the header file,
	// then bindgen (as of 0.69.2) will silently fail to output a .c file, and
	// the cc_library_static depending on this module will fail compilation.
	Static_inline_library *string
}

type bindgenDecorator struct {
@@ -159,6 +168,18 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr

	var cflags []string
	var implicits android.Paths
	var implicitOutputs android.WritablePaths
	var validations android.Paths

	if Bool(b.Properties.Handle_static_inline) && b.Properties.Static_inline_library == nil {
		ctx.PropertyErrorf("handle_static_inline",
			"requires declaring static_inline_library to the corresponding cc_library module that includes the generated C source from bindgen.")
	}

	if b.Properties.Static_inline_library != nil && !Bool(b.Properties.Handle_static_inline) {
		ctx.PropertyErrorf("static_inline_library",
			"requires declaring handle_static_inline.")
	}

	implicits = append(implicits, deps.depGeneratedHeaders...)

@@ -235,8 +256,11 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr

	bindgenFlags := defaultBindgenFlags
	bindgenFlags = append(bindgenFlags, esc(b.Properties.Bindgen_flags)...)
	if b.Properties.Handle_static_inline {
		bindgenFlags = append(bindgenFlags, "--experimental --wrap-static-fns")
	if Bool(b.Properties.Handle_static_inline) {
		outputStaticFnsFile := android.PathForModuleOut(ctx, b.BaseSourceProvider.getStem(ctx)+".c")
		implicitOutputs = append(implicitOutputs, outputStaticFnsFile)
		validations = append(validations, outputStaticFnsFile)
		bindgenFlags = append(bindgenFlags, []string{"--experimental", "--wrap-static-fns", "--wrap-static-fns-path=" + outputStaticFnsFile.String()}...)
	}

	// cat reads from stdin if its command line is empty,
@@ -290,6 +314,8 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr
		Output:          outputFile,
		Input:           wrapperFile.Path(),
		Implicits:       implicits,
		ImplicitOutputs: implicitOutputs,
		Validations:     validations,
		Args: map[string]string{
			"cmd":       cmd,
			"flags":     strings.Join(bindgenFlags, " "),
@@ -299,6 +325,14 @@ func (b *bindgenDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) andr
	})

	b.BaseSourceProvider.OutputFiles = android.Paths{outputFile}

	// Append any additional implicit outputs after the entry point source.
	// We append any generated .c file here so it can picked up by cc_library_static modules.
	// Those CC modules need to be sure not to pass any included .rs files to Clang.
	// We don't have to worry about the additional .c files for Rust modules as only the entry point
	// is passed to rustc.
	b.BaseSourceProvider.OutputFiles = append(b.BaseSourceProvider.OutputFiles, implicitOutputs.Paths()...)

	return outputFile
}

@@ -350,6 +384,14 @@ func (b *bindgenDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
		deps = muslDeps(ctx, deps, false)
	}

	if !ctx.RustModule().Source() && b.Properties.Static_inline_library != nil {
		// This is not the source variant, so add the static inline library as a dependency.
		//
		// This is necessary to avoid a circular dependency between the source variant and the
		// dependent cc module.
		deps.StaticLibs = append(deps.StaticLibs, String(b.Properties.Static_inline_library))
	}

	deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...)
	deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs...)
	deps.HeaderLibs = append(deps.HeaderLibs, b.ClangProperties.Header_libs...)
+43 −2
Original line number Diff line number Diff line
@@ -228,7 +228,6 @@ func TestBindgenFlagFile(t *testing.T) {
	// we may be able to check libbinder.RuleParams.Command to see if it contains $(cat /dev/null flag_file.txt)
}


func TestBindgenHandleStaticInlining(t *testing.T) {
	ctx := testRust(t, `
		rust_bindgen {
@@ -237,7 +236,14 @@ func TestBindgenHandleStaticInlining(t *testing.T) {
			crate_name: "bindgen",
			stem: "libbindgen",
			source_stem: "bindings",
			handle_static_inline: true
			handle_static_inline: true,
			static_inline_library: "libbindgen_staticfns"
		}

		cc_library_static {
			name: "libbindgen_staticfns",
			srcs: [":libbindgen"],
			include_dirs: ["src/"],
		}
	`)
	libbindgen := ctx.ModuleForTests("libbindgen", "android_arm64_armv8-a_source").Output("bindings.rs")
@@ -245,4 +251,39 @@ func TestBindgenHandleStaticInlining(t *testing.T) {
	if !strings.Contains(libbindgen.Args["flags"], "--wrap-static-fns") {
		t.Errorf("missing flag to handle static inlining in rust_bindgen rule: flags %#v", libbindgen.Args["flags"])
	}

	if !strings.Contains(libbindgen.Args["flags"], "--wrap-static-fns-path") {
		t.Errorf("missing flag to define path for static inlining C source from bindgen (--wrap-static-fns-path): flags %#v", libbindgen.Args["flags"])
	}

}

func TestBindgenStaticInlineProperties(t *testing.T) {
	// Make sure handle_static_inline without static_inline_library generates an error
	testRustError(t, "requires declaring static_inline_library to the corresponding cc_library module that includes the generated C source from bindgen", `
		rust_bindgen {
			name: "libbindgen",
			wrapper_src: "src/any.h",
			crate_name: "bindgen",
			stem: "libbindgen",
			source_stem: "bindings",
			handle_static_inline: true
		}
	`)
	testRustError(t, "requires declaring handle_static_inline", `
		rust_bindgen {
			name: "libbindgen",
			wrapper_src: "src/any.h",
			crate_name: "bindgen",
			stem: "libbindgen",
			source_stem: "bindings",
			static_inline_library: "libbindgen_staticfns"
		}

		cc_library_static {
			name: "libbindgen_staticfns",
			srcs: [":libbindgen"],
			include_dirs: ["src/"],
		}
	`)
}