[rust] Add build system support for proc macro crates

Adds build system support for building proc macro crates and their
dependencies for the host system.

Test: build.py
Bug: 229156386
Change-Id: I648064a509a0198b784605e0cc846c0808aa9e37
diff --git a/make/common_flags.mk b/make/common_flags.mk
index 66ba96e..2f39db3 100644
--- a/make/common_flags.mk
+++ b/make/common_flags.mk
@@ -9,15 +9,6 @@
 endif
 endif
 
-# Default Rust edition unless otherwise specified
-ifeq ($(call TOBOOL,$(MODULE_IS_RUST)),true)
-ifeq ($(MODULE_RUST_EDITION),)
-MODULE_RUST_EDITION := 2021
-endif
-
-MODULE_RUSTFLAGS += --edition $(MODULE_RUST_EDITION)
-endif
-
 # Remaining flags only apply to the trusty userspace, not the test-runner, which
 # is also built with the library system.
 ifeq (true,$(call TOBOOL,$(TRUSTY_USERSPACE)))
diff --git a/make/library.mk b/make/library.mk
index 9492694..85cd717 100644
--- a/make/library.mk
+++ b/make/library.mk
@@ -106,16 +106,33 @@
 # userspace_recurse.mk
 TRUSTY_NEW_MODULE_SYSTEM :=
 
-ifeq ($(call TOBOOL,$(TRUSTY_APP)),false)
-BUILDDIR := $(TRUSTY_LIBRARY_BUILDDIR)
-endif
-
 ifneq ($(filter %.rs,$(MODULE_SRCS)$(MODULE_SRCS_FIRST)),)
 MODULE_IS_RUST := true
 endif
 
+ifneq ($(filter proc-macro,$(MODULE_RUST_CRATE_TYPES)),)
+
+# proc macros must be host libraries, and all their dependencies are as well.
+# This will be reset after we recursively include all dependencies.
+MODULE_RUST_HOST_LIB := true
+
+ifneq ($(strip $(filter-out proc-macro,$(MODULE_RUST_CRATE_TYPES))),)
+$(error $(MODULE) cannot be built as both a proc-macro and a target crate)
+endif
+endif
+
+ifeq ($(call TOBOOL,$(TRUSTY_APP)),false)
+ifeq ($(call TOBOOL,$(MODULE_RUST_HOST_LIB)),false)
+BUILDDIR := $(TRUSTY_LIBRARY_BUILDDIR)
+else
+BUILDDIR := $(TRUSTY_HOST_LIBRARY_BUILDDIR)
+endif
+endif
+
+ifeq ($(call TOBOOL,$(MODULE_RUST_HOST_LIB)),false)
 # Add any common flags to the module
 include make/common_flags.mk
+endif
 
 ifneq ($(INCMODULES),)
 $(error $(MODULE) should only be included from other userspace modules that use library.mk. One of the following modules needs to be updated to use the new library system: $(LIB_SAVED_MODULE) $(ALLMODULES))
@@ -250,8 +267,8 @@
 $(error $(MODULE) includes more than one Rust file in MODULE_SRCS)
 endif
 
-ifneq ($(filter-out rlib staticlib bin,$(MODULE_RUST_CRATE_TYPES)),)
-$(error $(MODULE) contains unrecognized crate type $(filter-out rlib staticlib bin,$(MODULE_RUST_CRATE_TYPES)) in MODULE_RUST_CRATE_TYPES)
+ifneq ($(filter-out rlib staticlib bin proc-macro,$(MODULE_RUST_CRATE_TYPES)),)
+$(error $(MODULE) contains unrecognized crate type $(filter-out rlib staticlib bin proc-macro,$(MODULE_RUST_CRATE_TYPES)) in MODULE_RUST_CRATE_TYPES)
 endif
 
 ifeq ($(MODULE_CRATE_NAME),)
@@ -260,6 +277,13 @@
 
 MODULE_RUSTFLAGS += --crate-name=$(MODULE_CRATE_NAME)
 
+# Default Rust edition unless otherwise specified
+ifeq ($(MODULE_RUST_EDITION),)
+MODULE_RUST_EDITION := 2021
+endif
+
+MODULE_RUSTFLAGS += --edition $(MODULE_RUST_EDITION)
+
 ifeq ($(strip $(MODULE_RUST_CRATE_TYPES)),)
 MODULE_RUST_CRATE_TYPES := rlib
 endif
@@ -270,6 +294,14 @@
 
 MODULE_RSOBJS :=
 
+ifneq ($(filter proc-macro,$(MODULE_RUST_CRATE_TYPES)),)
+MODULE_CRATE_OUTPUT := $(call TOBUILDDIR,lib$(MODULE_CRATE_NAME).so)
+MODULE_RSOBJS += $(MODULE_CRATE_OUTPUT)
+$(MODULE_CRATE_OUTPUT): MODULE_RUSTFLAGS := $(MODULE_RUSTFLAGS) \
+	--crate-type=proc-macro --extern proc_macro -C prefer-dynamic
+MODULE_EXPORT_RLIBS += $(MODULE_CRATE_NAME)=$(MODULE_CRATE_OUTPUT)
+endif # proc-macro crate
+
 ifneq ($(filter rlib,$(MODULE_RUST_CRATE_TYPES)),)
 MODULE_CRATE_OUTPUT := $(call TOBUILDDIR,lib$(MODULE_CRATE_NAME).rlib)
 MODULE_RSOBJS += $(MODULE_CRATE_OUTPUT)
@@ -323,9 +355,15 @@
 ALLMODULE_OBJS :=
 MODULE_LIBRARY_DEPS :=
 
+ifeq ($(call TOBOOL,$(MODULE_RUST_HOST_LIB)),true)
+# Remove the target-specific flags
+$(MODULE_RSOBJS): ARCH_RUSTFLAGS :=
+$(MODULE_RSOBJS): GLOBAL_RUSTFLAGS := $(GLOBAL_HOST_RUSTFLAGS)
+else
 $(MODULE_RSOBJS): ARCH_RUSTFLAGS := $(ARCH_$(ARCH)_RUSTFLAGS)
 $(MODULE_RSOBJS): GLOBAL_RUSTFLAGS := $(GLOBAL_SHARED_RUSTFLAGS) $(GLOBAL_USER_RUSTFLAGS)
 $(MODULE_RSOBJS): MODULE_RUST_ENV := $(MODULE_RUST_ENV)
+endif
 
 include make/module.mk
 
@@ -351,7 +389,7 @@
 $(BUILDDIR)/%.o: ARCH_ASMFLAGS := $(ARCH_$(ARCH)_ASMFLAGS)
 
 ifeq ($(call TOBOOL,$(MODULE_IS_RUST)),true)
-LIBRARY_ARCHIVE := $(filter %.rlib,$(ALLMODULE_OBJS))
+LIBRARY_ARCHIVE := $(filter %.rlib %.so,$(ALLMODULE_OBJS))
 else
 LIBRARY_ARCHIVE := $(filter %.mod.a,$(ALLMODULE_OBJS))
 endif
@@ -390,6 +428,11 @@
 MODULE_RSOBJS :=
 LIB_SAVED_MODULE :=
 LIB_SAVED_ALLMODULE_OBJS :=
+
+ifneq ($(filter proc-macro,$(MODULE_RUST_CRATE_TYPES)),)
+# Reset host build state only once we finish building the proc-macro and its deps
+MODULE_RUST_HOST_LIB :=
+endif
 MODULE_RUST_CRATE_TYPES :=
 MODULE_RUST_TESTS :=
 
diff --git a/make/trusted_app.mk b/make/trusted_app.mk
index 21f551d..d66bca8 100644
--- a/make/trusted_app.mk
+++ b/make/trusted_app.mk
@@ -102,8 +102,8 @@
 # Link app elf
 ifeq ($(call TOBOOL,$(MODULE_IS_RUST)),true)
 MODULE_RUSTFLAGS += \
-	-Z pre-link-args="$(filter-out %.rlib,$(MODULE_EXTRA_OBJECTS))" \
-	-C link-args="$(ALLMODULE_OBJS)" \
+	-Z pre-link-args="$(filter-out %.rlib %.so,$(MODULE_EXTRA_OBJECTS))" \
+	-C link-args="$(filter-out %.rlib %.so,$(ALLMODULE_OBJS))" \
 	-C link-args="$(TRUSTY_APP_LDFLAGS) $(MODULE_LDFLAGS)" \
 
 $(TRUSTY_APP_SYMS_ELF).d: