Merge "Annotate dependency tags for dependencies of installed files"
diff --git a/android/Android.bp b/android/Android.bp
index 279d442..47e941b 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -23,6 +23,7 @@
"defaults.go",
"defs.go",
"depset.go",
+ "deptag.go",
"expand.go",
"filegroup.go",
"hooks.go",
@@ -72,6 +73,7 @@
"config_test.go",
"csuite_config_test.go",
"depset_test.go",
+ "deptag_test.go",
"expand_test.go",
"module_test.go",
"mutator_test.go",
diff --git a/android/arch.go b/android/arch.go
index eb651e6..df407d4 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -271,7 +271,7 @@
if _, found := commonTargetMap[name]; found {
panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name))
} else {
- commonTargetMap[name] = Target{Os: os, Arch: Arch{ArchType: Common}}
+ commonTargetMap[name] = Target{Os: os, Arch: CommonArch}
}
osArchTypeMap[os] = archTypes
@@ -341,6 +341,10 @@
// CommonOS is a pseudo OSType for a common OS variant, which is OsType agnostic and which
// has dependencies on all the OS variants.
CommonOS = newOsType("common_os", Generic, false)
+
+ // CommonArch is the Arch for all modules that are os-specific but not arch specific,
+ // for example most Java modules.
+ CommonArch = Arch{ArchType: Common}
)
// Target specifies the OS and architecture that a module is being compiled for.
@@ -511,9 +515,6 @@
// Identifies the dependency from CommonOS variant to the os specific variants.
var commonOsToOsSpecificVariantTag = archDepTag{name: "common os to os specific"}
-// Identifies the dependency from arch variant to the common variant for a "common_first" multilib.
-var firstArchToCommonArchDepTag = archDepTag{name: "first arch to common arch"}
-
// Get the OsType specific variants for the current CommonOS variant.
//
// The returned list will only contain enabled OsType specific variants of the
@@ -667,12 +668,6 @@
addTargetProperties(m, targets[i], multiTargets, i == 0)
m.base().setArchProperties(mctx)
}
-
- if multilib == "common_first" && len(modules) >= 2 {
- for i := range modules[1:] {
- mctx.AddInterVariantDependency(firstArchToCommonArchDepTag, modules[i+1], modules[0])
- }
- }
}
// addTargetProperties annotates a variant with the Target is is being compiled for, the list
diff --git a/android/deptag.go b/android/deptag.go
new file mode 100644
index 0000000..be5c35c
--- /dev/null
+++ b/android/deptag.go
@@ -0,0 +1,45 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import "github.com/google/blueprint"
+
+// Dependency tags can implement this interface and return true from InstallDepNeeded to annotate
+// that the installed files of the parent should depend on the installed files of the child.
+type InstallNeededDependencyTag interface {
+ // If InstallDepNeeded returns true then the installed files of the parent will depend on the
+ // installed files of the child.
+ InstallDepNeeded() bool
+}
+
+// Dependency tags can embed this struct to annotate that the installed files of the parent should
+// depend on the installed files of the child.
+type InstallAlwaysNeededDependencyTag struct{}
+
+func (i InstallAlwaysNeededDependencyTag) InstallDepNeeded() bool {
+ return true
+}
+
+var _ InstallNeededDependencyTag = InstallAlwaysNeededDependencyTag{}
+
+// IsInstallDepNeeded returns true if the dependency tag implements the InstallNeededDependencyTag
+// interface and the InstallDepNeeded returns true, meaning that the installed files of the parent
+// should depend on the installed files of the child.
+func IsInstallDepNeeded(tag blueprint.DependencyTag) bool {
+ if i, ok := tag.(InstallNeededDependencyTag); ok {
+ return i.InstallDepNeeded()
+ }
+ return false
+}
diff --git a/android/deptag_test.go b/android/deptag_test.go
new file mode 100644
index 0000000..bdd449e
--- /dev/null
+++ b/android/deptag_test.go
@@ -0,0 +1,135 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "testing"
+
+ "github.com/google/blueprint"
+)
+
+type testInstallDependencyTagModule struct {
+ ModuleBase
+ Properties struct {
+ Install_deps []string
+ Deps []string
+ }
+}
+
+func (t *testInstallDependencyTagModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ outputFile := PathForModuleOut(ctx, "out")
+ ctx.Build(pctx, BuildParams{
+ Rule: Touch,
+ Output: outputFile,
+ })
+ ctx.InstallFile(PathForModuleInstall(ctx), ctx.ModuleName(), outputFile)
+}
+
+var testInstallDependencyTagAlwaysDepTag = struct {
+ blueprint.DependencyTag
+ InstallAlwaysNeededDependencyTag
+}{}
+
+var testInstallDependencyTagNeverDepTag = struct {
+ blueprint.DependencyTag
+}{}
+
+func (t *testInstallDependencyTagModule) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddVariationDependencies(nil, testInstallDependencyTagAlwaysDepTag, t.Properties.Install_deps...)
+ ctx.AddVariationDependencies(nil, testInstallDependencyTagNeverDepTag, t.Properties.Deps...)
+}
+
+func testInstallDependencyTagModuleFactory() Module {
+ module := &testInstallDependencyTagModule{}
+ InitAndroidArchModule(module, HostAndDeviceDefault, MultilibCommon)
+ module.AddProperties(&module.Properties)
+ return module
+}
+
+func TestInstallDependencyTag(t *testing.T) {
+ bp := `
+ test_module {
+ name: "foo",
+ deps: ["dep"],
+ install_deps: ["install_dep"],
+ }
+
+ test_module {
+ name: "install_dep",
+ install_deps: ["transitive"],
+ }
+
+ test_module {
+ name: "transitive",
+ }
+
+ test_module {
+ name: "dep",
+ }
+ `
+
+ config := TestArchConfig(buildDir, nil, bp, nil)
+ ctx := NewTestArchContext(config)
+
+ ctx.RegisterModuleType("test_module", testInstallDependencyTagModuleFactory)
+
+ ctx.Register()
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ hostFoo := ctx.ModuleForTests("foo", config.BuildOSCommonTarget.String()).Description("install")
+ hostInstallDep := ctx.ModuleForTests("install_dep", config.BuildOSCommonTarget.String()).Description("install")
+ hostTransitive := ctx.ModuleForTests("transitive", config.BuildOSCommonTarget.String()).Description("install")
+ hostDep := ctx.ModuleForTests("dep", config.BuildOSCommonTarget.String()).Description("install")
+
+ if g, w := hostFoo.Implicits.Strings(), hostInstallDep.Output.String(); !InList(w, g) {
+ t.Errorf("expected host dependency %q, got %q", w, g)
+ }
+
+ if g, w := hostFoo.Implicits.Strings(), hostTransitive.Output.String(); !InList(w, g) {
+ t.Errorf("expected host dependency %q, got %q", w, g)
+ }
+
+ if g, w := hostInstallDep.Implicits.Strings(), hostTransitive.Output.String(); !InList(w, g) {
+ t.Errorf("expected host dependency %q, got %q", w, g)
+ }
+
+ if g, w := hostFoo.Implicits.Strings(), hostDep.Output.String(); InList(w, g) {
+ t.Errorf("expected no host dependency %q, got %q", w, g)
+ }
+
+ deviceFoo := ctx.ModuleForTests("foo", "android_common").Description("install")
+ deviceInstallDep := ctx.ModuleForTests("install_dep", "android_common").Description("install")
+ deviceTransitive := ctx.ModuleForTests("transitive", "android_common").Description("install")
+ deviceDep := ctx.ModuleForTests("dep", "android_common").Description("install")
+
+ if g, w := deviceFoo.OrderOnly.Strings(), deviceInstallDep.Output.String(); !InList(w, g) {
+ t.Errorf("expected device dependency %q, got %q", w, g)
+ }
+
+ if g, w := deviceFoo.OrderOnly.Strings(), deviceTransitive.Output.String(); !InList(w, g) {
+ t.Errorf("expected device dependency %q, got %q", w, g)
+ }
+
+ if g, w := deviceInstallDep.OrderOnly.Strings(), deviceTransitive.Output.String(); !InList(w, g) {
+ t.Errorf("expected device dependency %q, got %q", w, g)
+ }
+
+ if g, w := deviceFoo.OrderOnly.Strings(), deviceDep.Output.String(); InList(w, g) {
+ t.Errorf("expected no device dependency %q, got %q", w, g)
+ }
+}
diff --git a/android/module.go b/android/module.go
index 7a05096..bd60829 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1286,14 +1286,18 @@
return m.commonProperties.NamespaceExportedToMake
}
+// computeInstallDeps finds the installed paths of all dependencies that have a dependency
+// tag that is annotated as needing installation via the IsInstallDepNeeded method.
func (m *ModuleBase) computeInstallDeps(ctx blueprint.ModuleContext) InstallPaths {
-
var result InstallPaths
- // TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
- ctx.VisitDepsDepthFirst(func(m blueprint.Module) {
- if a, ok := m.(Module); ok {
- result = append(result, a.FilesToInstall()...)
+ ctx.WalkDeps(func(child, parent blueprint.Module) bool {
+ if a, ok := child.(Module); ok {
+ if IsInstallDepNeeded(ctx.OtherModuleDependencyTag(child)) {
+ result = append(result, a.FilesToInstall()...)
+ return true
+ }
}
+ return false
})
return result
diff --git a/cc/cc.go b/cc/cc.go
index bd6e5d5..3a9349b 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -551,7 +551,15 @@
return d.Kind == staticLibraryDependency
}
-// dependencyTag is used for tagging miscellanous dependency types that don't fit into
+// InstallDepNeeded returns true for shared libraries so that shared library dependencies of
+// binaries or other shared libraries are installed as dependencies.
+func (d libraryDependencyTag) InstallDepNeeded() bool {
+ return d.shared()
+}
+
+var _ android.InstallNeededDependencyTag = libraryDependencyTag{}
+
+// dependencyTag is used for tagging miscellaneous dependency types that don't fit into
// libraryDependencyTag. Each tag object is created globally and reused for multiple
// dependencies (although since the object contains no references, assigning a tag to a
// variable and modifying it will not modify the original). Users can compare the tag
@@ -561,6 +569,15 @@
name string
}
+// installDependencyTag is used for tagging miscellaneous dependency types that don't fit into
+// libraryDependencyTag, but where the dependency needs to be installed when the parent is
+// installed.
+type installDependencyTag struct {
+ blueprint.BaseDependencyTag
+ android.InstallAlwaysNeededDependencyTag
+ name string
+}
+
var (
genSourceDepTag = dependencyTag{name: "gen source"}
genHeaderDepTag = dependencyTag{name: "gen header"}
@@ -572,7 +589,7 @@
staticVariantTag = dependencyTag{name: "static variant"}
vndkExtDepTag = dependencyTag{name: "vndk extends"}
dataLibDepTag = dependencyTag{name: "data lib"}
- runtimeDepTag = dependencyTag{name: "runtime lib"}
+ runtimeDepTag = installDependencyTag{name: "runtime lib"}
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
stubImplDepTag = dependencyTag{name: "stub_impl"}
)
@@ -599,8 +616,7 @@
}
func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool {
- ccDepTag, ok := depTag.(dependencyTag)
- return ok && ccDepTag == runtimeDepTag
+ return depTag == runtimeDepTag
}
func IsTestPerSrcDepTag(depTag blueprint.DependencyTag) bool {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f5ce867..7c98585 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -4069,3 +4069,98 @@
}
}
+
+func TestInstallSharedLibs(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "bin",
+ host_supported: true,
+ shared_libs: ["libshared"],
+ runtime_libs: ["libruntime"],
+ srcs: [":gen"],
+ }
+
+ cc_library_shared {
+ name: "libshared",
+ host_supported: true,
+ shared_libs: ["libtransitive"],
+ }
+
+ cc_library_shared {
+ name: "libtransitive",
+ host_supported: true,
+ }
+
+ cc_library_shared {
+ name: "libruntime",
+ host_supported: true,
+ }
+
+ cc_binary_host {
+ name: "tool",
+ srcs: ["foo.cpp"],
+ }
+
+ genrule {
+ name: "gen",
+ tools: ["tool"],
+ out: ["gen.cpp"],
+ cmd: "$(location tool) $(out)",
+ }
+ `
+
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ ctx := testCcWithConfig(t, config)
+
+ hostBin := ctx.ModuleForTests("bin", config.BuildOSTarget.String()).Description("install")
+ hostShared := ctx.ModuleForTests("libshared", config.BuildOSTarget.String()+"_shared").Description("install")
+ hostRuntime := ctx.ModuleForTests("libruntime", config.BuildOSTarget.String()+"_shared").Description("install")
+ hostTransitive := ctx.ModuleForTests("libtransitive", config.BuildOSTarget.String()+"_shared").Description("install")
+ hostTool := ctx.ModuleForTests("tool", config.BuildOSTarget.String()).Description("install")
+
+ if g, w := hostBin.Implicits.Strings(), hostShared.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected host bin dependency %q, got %q", w, g)
+ }
+
+ if g, w := hostBin.Implicits.Strings(), hostTransitive.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected host bin dependency %q, got %q", w, g)
+ }
+
+ if g, w := hostShared.Implicits.Strings(), hostTransitive.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected host bin dependency %q, got %q", w, g)
+ }
+
+ if g, w := hostBin.Implicits.Strings(), hostRuntime.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected host bin dependency %q, got %q", w, g)
+ }
+
+ if g, w := hostBin.Implicits.Strings(), hostTool.Output.String(); android.InList(w, g) {
+ t.Errorf("expected no host bin dependency %q, got %q", w, g)
+ }
+
+ deviceBin := ctx.ModuleForTests("bin", "android_arm64_armv8-a").Description("install")
+ deviceShared := ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared").Description("install")
+ deviceTransitive := ctx.ModuleForTests("libtransitive", "android_arm64_armv8-a_shared").Description("install")
+ deviceRuntime := ctx.ModuleForTests("libruntime", "android_arm64_armv8-a_shared").Description("install")
+
+ if g, w := deviceBin.OrderOnly.Strings(), deviceShared.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected device bin dependency %q, got %q", w, g)
+ }
+
+ if g, w := deviceBin.OrderOnly.Strings(), deviceTransitive.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected device bin dependency %q, got %q", w, g)
+ }
+
+ if g, w := deviceShared.OrderOnly.Strings(), deviceTransitive.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected device bin dependency %q, got %q", w, g)
+ }
+
+ if g, w := deviceBin.OrderOnly.Strings(), deviceRuntime.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected device bin dependency %q, got %q", w, g)
+ }
+
+ if g, w := deviceBin.OrderOnly.Strings(), hostTool.Output.String(); android.InList(w, g) {
+ t.Errorf("expected no device bin dependency %q, got %q", w, g)
+ }
+
+}
diff --git a/cc/testing.go b/cc/testing.go
index 7161313..198764b 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/genrule"
)
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
@@ -24,6 +25,7 @@
RegisterBinaryBuildComponents(ctx)
RegisterLibraryBuildComponents(ctx)
RegisterLibraryHeadersBuildComponents(ctx)
+ genrule.RegisterGenruleBuildComponents(ctx)
ctx.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
ctx.RegisterModuleType("llndk_library", LlndkLibraryFactory)
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 0743e67..d5f9c70 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -30,10 +30,10 @@
)
func init() {
- registerGenruleBuildComponents(android.InitRegistrationContext)
+ RegisterGenruleBuildComponents(android.InitRegistrationContext)
}
-func registerGenruleBuildComponents(ctx android.RegistrationContext) {
+func RegisterGenruleBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
ctx.RegisterModuleType("gensrcs", GenSrcsFactory)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 6779c73..7d3a7b9 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -57,7 +57,7 @@
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("tool", toolFactory)
- registerGenruleBuildComponents(ctx)
+ RegisterGenruleBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.Register()
diff --git a/java/java.go b/java/java.go
index 3c9c92d..5012279 100644
--- a/java/java.go
+++ b/java/java.go
@@ -556,6 +556,14 @@
name string
}
+// installDependencyTag is a dependency tag that is annotated to cause the installed files of the
+// dependency to be installed when the parent module is installed.
+type installDependencyTag struct {
+ blueprint.BaseDependencyTag
+ android.InstallAlwaysNeededDependencyTag
+ name string
+}
+
type usesLibraryDependencyTag struct {
dependencyTag
sdkVersion int // SDK version in which the library appared as a standalone library.
@@ -590,6 +598,8 @@
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
extraLintCheckTag = dependencyTag{name: "extra-lint-check"}
jniLibTag = dependencyTag{name: "jnilib"}
+ jniInstallTag = installDependencyTag{name: "jni install"}
+ binaryInstallTag = installDependencyTag{name: "binary install"}
usesLibTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion)
usesLibCompat28Tag = makeUsesLibraryDependencyTag(28)
usesLibCompat29Tag = makeUsesLibraryDependencyTag(29)
@@ -2586,9 +2596,12 @@
if ctx.Arch().ArchType == android.Common {
j.deps(ctx)
} else {
- // This dependency ensures the host installation rules will install the jni libraries
- // when the wrapper is installed.
- ctx.AddVariationDependencies(nil, jniLibTag, j.binaryProperties.Jni_libs...)
+ // These dependencies ensure the host installation rules will install the jar file and
+ // the jni libraries when the wrapper is installed.
+ ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
+ ctx.AddVariationDependencies(
+ []blueprint.Variation{{Mutator: "arch", Variation: android.CommonArch.String()}},
+ binaryInstallTag, ctx.ModuleName())
}
}
diff --git a/java/java_test.go b/java/java_test.go
index 3ab228b..83db443 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -30,7 +30,6 @@
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
- "android/soong/genrule"
"android/soong/python"
)
@@ -81,7 +80,6 @@
RegisterSystemModulesBuildComponents(ctx)
ctx.RegisterModuleType("java_plugin", PluginFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
ctx.RegisterModuleType("python_binary_host", python.PythonBinaryHostFactory)
RegisterDocsBuildComponents(ctx)
RegisterStubsBuildComponents(ctx)
diff --git a/python/python.go b/python/python.go
index d7b1bba..c27a096 100644
--- a/python/python.go
+++ b/python/python.go
@@ -217,11 +217,17 @@
name string
}
+type installDependencyTag struct {
+ blueprint.BaseDependencyTag
+ android.InstallAlwaysNeededDependencyTag
+ name string
+}
+
var (
pythonLibTag = dependencyTag{name: "pythonLib"}
javaDataTag = dependencyTag{name: "javaData"}
launcherTag = dependencyTag{name: "launcher"}
- launcherSharedLibTag = dependencyTag{name: "launcherSharedLib"}
+ launcherSharedLibTag = installDependencyTag{name: "launcherSharedLib"}
pyIdentifierRegexp = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_-]*$`)
pyExt = ".py"
protoExt = ".proto"
@@ -336,6 +342,7 @@
// cannot read the property at this stage and it will be too late to add
// dependencies later.
ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag, "libsqlite")
+ ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag, "libc++")
if ctx.Target().Os.Bionic() {
ctx.AddFarVariationDependencies(ctx.Target().Variations(), launcherSharedLibTag,
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 14bbd0b..187f0b6 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -286,6 +286,12 @@
srcs: ["src/any.h"],
out: ["src/any.rs"],
}
+ rust_binary_host {
+ name: "any_rust_binary",
+ srcs: [
+ "foo.rs",
+ ],
+ }
rust_bindgen {
name: "libbindings",
crate_name: "bindings",
diff --git a/rust/testing.go b/rust/testing.go
index 66877a9..001f322 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -17,7 +17,6 @@
import (
"android/soong/android"
"android/soong/cc"
- "android/soong/genrule"
)
func GatherRequiredDepsForTest() string {
@@ -132,7 +131,6 @@
android.RegisterPrebuiltMutators(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
cc.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
ctx.RegisterModuleType("rust_binary", RustBinaryFactory)
ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory)
ctx.RegisterModuleType("rust_bindgen", RustBindgenFactory)