Add Header Library support to Make

We currently use static libraries without any source files to represent
header libraries, but Soong actually has cc_library_headers. So to
export those in a separate namespace from static libraries, implement
them in Make as well.

This also adds a nice pretty-warning / pretty-error macro that can be
used to print out standard warning messages pointing to the real source
file having the problem.

Test: Use a header library exported by Soong in a Make module
Change-Id: I3486539e247524cb82a20620745fc7be03014e14
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 8cceaad..e90c1bb 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -564,6 +564,7 @@
   $(LOCAL_STATIC_LIBRARIES) \
   $(LOCAL_WHOLE_STATIC_LIBRARIES) \
   $(LOCAL_SHARED_LIBRARIES) \
+  $(LOCAL_HEADER_LIBRARIES) \
   $(LOCAL_STATIC_JAVA_LIBRARIES) \
   $(LOCAL_JAVA_LIBRARIES)\
   $(LOCAL_JNI_SHARED_LIBRARIES))
@@ -585,7 +586,7 @@
 ## umbrella targets used to verify builds
 ###########################################################
 j_or_n :=
-ifneq (,$(filter EXECUTABLES SHARED_LIBRARIES STATIC_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)))
+ifneq (,$(filter EXECUTABLES SHARED_LIBRARIES STATIC_LIBRARIES HEADER_LIBRARIES NATIVE_TESTS,$(LOCAL_MODULE_CLASS)))
 j_or_n := native
 else
 ifneq (,$(filter JAVA_LIBRARIES APPS,$(LOCAL_MODULE_CLASS)))
diff --git a/core/binary.mk b/core/binary.mk
index 304a72e..44f0e95 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -40,6 +40,7 @@
 my_static_libraries := $(LOCAL_STATIC_LIBRARIES)
 my_whole_static_libraries := $(LOCAL_WHOLE_STATIC_LIBRARIES)
 my_shared_libraries := $(LOCAL_SHARED_LIBRARIES)
+my_header_libraries := $(LOCAL_HEADER_LIBRARIES)
 my_cflags := $(LOCAL_CFLAGS)
 my_conlyflags := $(LOCAL_CONLYFLAGS)
 my_cppflags := $(LOCAL_CPPFLAGS)
@@ -320,6 +321,7 @@
 my_src_files += $(LOCAL_SRC_FILES_$($(my_prefix)OS)) $(LOCAL_SRC_FILES_$($(my_prefix)OS)_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
 my_static_libraries += $(LOCAL_STATIC_LIBRARIES_$($(my_prefix)OS))
 my_shared_libraries += $(LOCAL_SHARED_LIBRARIES_$($(my_prefix)OS))
+my_header_libraries += $(LOCAL_HEADER_LIBRARIES_$($(my_prefix)OS))
 my_cflags += $(LOCAL_CFLAGS_$($(my_prefix)OS))
 my_cppflags += $(LOCAL_CPPFLAGS_$($(my_prefix)OS))
 my_ldflags += $(LOCAL_LDFLAGS_$($(my_prefix)OS))
@@ -443,6 +445,7 @@
 # arch-specific static libraries go first so that generic ones can depend on them
 my_static_libraries := $(LOCAL_STATIC_LIBRARIES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_STATIC_LIBRARIES_$(my_32_64_bit_suffix)) $(my_static_libraries)
 my_whole_static_libraries := $(LOCAL_WHOLE_STATIC_LIBRARIES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_WHOLE_STATIC_LIBRARIES_$(my_32_64_bit_suffix)) $(my_whole_static_libraries)
+my_header_libraries := $(LOCAL_HEADER_LIBRARIES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)) $(LOCAL_HEADER_LIBRARIES_$(my_32_64_bit_suffix)) $(my_header_libraries)
 
 include $(BUILD_SYSTEM)/cxx_stl_setup.mk
 
@@ -1396,7 +1399,9 @@
     $(foreach l, $(installed_shared_library_module_names), \
       $(call intermediates-dir-for,SHARED_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes) \
     $(foreach l, $(my_static_libraries) $(my_whole_static_libraries), \
-      $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
+      $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes) \
+    $(foreach l, $(my_header_libraries), \
+      $(call intermediates-dir-for,HEADER_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
 $(import_includes): PRIVATE_IMPORT_EXPORT_INCLUDES := $(import_includes_deps)
 $(import_includes) : $(import_includes_deps)
 	@echo Import includes file: $@
@@ -1430,10 +1435,12 @@
    $(foreach l,$(my_whole_static_libraries) $(my_static_libraries), \
      $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/link_type))
 ifneq ($(LOCAL_MODULE_CLASS),STATIC_LIBRARIES)
+ifneq ($(LOCAL_MODULE_CLASS),HEADER_LIBRARIES)
 my_link_type_deps += $(strip \
    $(foreach l,$(my_shared_libraries), \
      $(call intermediates-dir-for,SHARED_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/link_type))
 endif
+endif
 $(my_link_type): PRIVATE_DEPS := $(my_link_type_deps)
 $(my_link_type): PRIVATE_MODULE := $(LOCAL_MODULE)
 $(my_link_type): PRIVATE_MAKEFILE := $(LOCAL_MODULE_MAKEFILE)
@@ -1791,10 +1798,14 @@
 export_include_deps += $(strip \
    $(foreach l,$(LOCAL_EXPORT_STATIC_LIBRARY_HEADERS), \
      $(call intermediates-dir-for,STATIC_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
+# Re-export requested headers from header libraries.
+export_include_deps += $(strip \
+   $(foreach l,$(LOCAL_EXPORT_HEADER_LIBRARY_HEADERS), \
+     $(call intermediates-dir-for,HEADER_LIBRARIES,$(l),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX),$(my_host_cross))/export_includes))
 $(export_includes): PRIVATE_REEXPORTED_INCLUDES := $(export_include_deps)
 # By adding $(my_generated_sources) it makes sure the headers get generated
 # before any dependent source files get compiled.
-$(export_includes) : $(my_export_c_include_deps) $(my_generated_sources) $(export_include_deps)
+$(export_includes) : $(my_export_c_include_deps) $(my_generated_sources) $(export_include_deps) $(LOCAL_EXPORT_C_INCLUDE_DEPS)
 	@echo Export includes file: $< -- $@
 	$(hide) mkdir -p $(dir $@) && rm -f [email protected] && touch [email protected]
 ifdef my_export_c_include_dirs
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 614a7ca..6e8672b 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -66,6 +66,7 @@
 LOCAL_EMMA_INSTRUMENT:=
 LOCAL_EXPORT_C_INCLUDE_DEPS:=
 LOCAL_EXPORT_C_INCLUDE_DIRS:=
+LOCAL_EXPORT_HEADER_LIBRARY_HEADERS:=
 LOCAL_EXPORT_PACKAGE_RESOURCES:=
 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS:=
 LOCAL_EXPORT_STATIC_LIBRARY_HEADERS:=
@@ -82,6 +83,7 @@
 LOCAL_GROUP_STATIC_LIBRARIES:=
 LOCAL_GTEST:=true
 LOCAL_HAL_STATIC_LIBRARIES:=
+LOCAL_HEADER_LIBRARIES:=
 LOCAL_INIT_RC:=
 LOCAL_INSTALLED_MODULE:=
 LOCAL_INSTALLED_MODULE_STEM:=
@@ -240,6 +242,7 @@
 LOCAL_CLANG_$(TARGET_ARCH):=
 LOCAL_CPPFLAGS_$(TARGET_ARCH):=
 LOCAL_GENERATED_SOURCES_$(TARGET_ARCH):=
+LOCAL_HEADER_LIBRARIES_$(TARGET_ARCH):=
 LOCAL_LDFLAGS_$(TARGET_ARCH):=
 LOCAL_PACK_MODULE_RELOCATIONS_$(TARGET_ARCH):=
 LOCAL_PREBUILT_JNI_LIBS_$(TARGET_ARCH):=
@@ -261,6 +264,7 @@
 LOCAL_CLANG_$(TARGET_2ND_ARCH):=
 LOCAL_CPPFLAGS_$(TARGET_2ND_ARCH):=
 LOCAL_GENERATED_SOURCES_$(TARGET_2ND_ARCH):=
+LOCAL_HEADER_LIBRARIES_$(TARGET_2ND_ARCH):=
 LOCAL_LDFLAGS_$(TARGET_2ND_ARCH):=
 LOCAL_PACK_MODULE_RELOCATIONS_$(TARGET_2ND_ARCH):=
 LOCAL_PREBUILT_JNI_LIBS_$(TARGET_2ND_ARCH):=
@@ -282,6 +286,7 @@
 LOCAL_CLANG_LDFLAGS_$(HOST_ARCH):=
 LOCAL_CPPFLAGS_$(HOST_ARCH):=
 LOCAL_GENERATED_SOURCES_$(HOST_ARCH):=
+LOCAL_HEADER_LIBRARIES_$(HOST_ARCH):=
 LOCAL_LDFLAGS_$(HOST_ARCH):=
 LOCAL_REQUIRED_MODULES_$(HOST_ARCH):=
 LOCAL_SHARED_LIBRARIES_$(HOST_ARCH):=
@@ -300,6 +305,7 @@
 LOCAL_CLANG_LDFLAGS_$(HOST_2ND_ARCH):=
 LOCAL_CPPFLAGS_$(HOST_2ND_ARCH):=
 LOCAL_GENERATED_SOURCES_$(HOST_2ND_ARCH):=
+LOCAL_HEADER_LIBRARIES_$(HOST_2ND_ARCH):=
 LOCAL_LDFLAGS_$(HOST_2ND_ARCH):=
 LOCAL_REQUIRED_MODULES_$(HOST_2ND_ARCH):=
 LOCAL_SHARED_LIBRARIES_$(HOST_2ND_ARCH):=
@@ -314,6 +320,7 @@
 LOCAL_C_INCLUDES_$(HOST_OS):=
 LOCAL_CPPFLAGS_$(HOST_OS):=
 LOCAL_GENERATED_SOURCES_$(HOST_OS):=
+LOCAL_HEADER_LIBRARIES_$(HOST_OS):=
 LOCAL_LDFLAGS_$(HOST_OS):=
 LOCAL_LDLIBS_$(HOST_OS):=
 LOCAL_REQUIRED_MODULES_$(HOST_OS):=
@@ -327,6 +334,7 @@
 LOCAL_C_INCLUDES_$(HOST_CROSS_OS):=
 LOCAL_CPPFLAGS_$(HOST_CROSS_OS):=
 LOCAL_GENERATED_SOURCES_$(HOST_CROSS_OS):=
+LOCAL_HEADER_LIBRARIES_$(HOST_CROSS_OS):=
 LOCAL_LDFLAGS_$(HOST_CROSS_OS):=
 LOCAL_LDLIBS_$(HOST_CROSS_OS):=
 LOCAL_REQUIRED_MODULES_$(HOST_CROSS_OS):=
@@ -366,6 +374,8 @@
 LOCAL_CPPFLAGS_64:=
 LOCAL_GENERATED_SOURCES_32:=
 LOCAL_GENERATED_SOURCES_64:=
+LOCAL_HEADER_LIBRARIES_32:=
+LOCAL_HEADER_LIBRARIES_64:=
 LOCAL_INIT_RC_32:=
 LOCAL_INIT_RC_64:=
 LOCAL_LDFLAGS_32:=
diff --git a/core/config.mk b/core/config.mk
index 2f43f46..3fd7cc2 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -92,6 +92,7 @@
 BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
 BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
 BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
+BUILD_HEADER_LIBRARY:= $(BUILD_SYSTEM)/header_library.mk
 BUILD_AUX_STATIC_LIBRARY:= $(BUILD_SYSTEM)/aux_static_library.mk
 BUILD_AUX_EXECUTABLE:= $(BUILD_SYSTEM)/aux_executable.mk
 BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
diff --git a/core/definitions.mk b/core/definitions.mk
index da5aff1..9d1c2eb 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -850,18 +850,37 @@
 
 
 ###########################################################
-## Color-coded warnings and errors in build rules
-##
-## $(1): message to print
+## Color-coded warnings and errors
+## Use echo-(warning|error) in a build rule
+## Use pretty-(warning|error) instead of $(warning)/$(error)
 ###########################################################
+ESC_BOLD := \e[1m
+ESC_WARNING := \e[35m
+ESC_ERROR := \e[31m
+ESC_RESET := \e[0m
+
+# $(1): path (and optionally line) information
+# $(2): message to print
 define echo-warning
-echo -e "\e[1;35mwarning:\e[0m \e[1m" $(1) "\e[0m\n"
+echo -e "$(ESC_BOLD)$(1): $(ESC_WARNING)warning:$(ESC_RESET)$(ESC_BOLD)" $(2) "$(ESC_RESET)" >&2
 endef
 
+# $(1): path (and optionally line) information
+# $(2): message to print
 define echo-error
-echo -e "\e[1;31merror:\e[0m \e[1m" $(1) "\e[0m\n"
+echo -e "$(ESC_BOLD)$(1): $(ESC_ERROR)error:$(ESC_RESET)$(ESC_BOLD)" $(2) "$(ESC_RESET)" >&2
 endef
 
+# $(1): message to print
+define pretty-warning
+$(shell $(call echo-warning,$(LOCAL_MODULE_MAKEFILE),$(LOCAL_MODULE): $(1)))
+endef
+
+# $(1): message to print
+define pretty-error
+$(shell $(call echo-error,$(LOCAL_MODULE_MAKEFILE),$(LOCAL_MODULE): $(1)))
+$(error done)
+endef
 
 ###########################################################
 ## Package filtering
diff --git a/core/envsetup.mk b/core/envsetup.mk
index b0f35b1..64668c5 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -504,7 +504,7 @@
 TARGET_INSTALLER_SYSTEM_OUT := $(TARGET_INSTALLER_OUT)/root/system
 
 COMMON_MODULE_CLASSES := TARGET-NOTICE_FILES HOST-NOTICE_FILES HOST-JAVA_LIBRARIES
-PER_ARCH_MODULE_CLASSES := SHARED_LIBRARIES STATIC_LIBRARIES EXECUTABLES GYP RENDERSCRIPT_BITCODE NATIVE_TESTS
+PER_ARCH_MODULE_CLASSES := SHARED_LIBRARIES STATIC_LIBRARIES EXECUTABLES GYP RENDERSCRIPT_BITCODE NATIVE_TESTS HEADER_LIBRARIES
 
 ifeq (,$(strip $(DIST_DIR)))
   DIST_DIR := $(OUT_DIR)/dist
diff --git a/core/header_library.mk b/core/header_library.mk
new file mode 100644
index 0000000..5144679
--- /dev/null
+++ b/core/header_library.mk
@@ -0,0 +1,72 @@
+$(call record-module-type,HEADER_LIBRARY)
+ifdef LOCAL_IS_HOST_MODULE
+  my_prefix := HOST_
+  LOCAL_HOST_PREFIX :=
+else
+  my_prefix := TARGET_
+endif
+include $(BUILD_SYSTEM)/multilib.mk
+
+ifndef my_module_multilib
+  # libraries default to building for both architecturess
+  my_module_multilib := both
+endif
+
+LOCAL_2ND_ARCH_VAR_PREFIX :=
+include $(BUILD_SYSTEM)/module_arch_supported.mk
+
+ifeq ($(my_module_arch_supported),true)
+  include $(BUILD_SYSTEM)/header_library_internal.mk
+endif
+
+ifdef $(my_prefix)2ND_ARCH
+  LOCAL_2ND_ARCH_VAR_PREFIX := $($(my_prefix)2ND_ARCH_VAR_PREFIX)
+  include $(BUILD_SYSTEM)/module_arch_supported.mk
+
+  ifeq ($(my_module_arch_supported),true)
+    # Build for 2ND_ARCH
+    OVERRIDE_BUILT_MODULE_PATH :=
+    LOCAL_BUILT_MODULE :=
+    LOCAL_INSTALLED_MODULE :=
+    LOCAL_INTERMEDIATE_TARGETS :=
+    include $(BUILD_SYSTEM)/header_library_internal.mk
+  endif
+  LOCAL_2ND_ARCH_VAR_PREFIX :=
+endif # 2ND_ARCH
+
+ifdef LOCAL_IS_HOST_MODULE
+  ifdef HOST_CROSS_OS
+    my_prefix := HOST_CROSS_
+    LOCAL_HOST_PREFIX := $(my_prefix)
+
+    include $(BUILD_SYSTEM)/module_arch_supported.mk
+
+    ifeq ($(my_module_arch_supported),true)
+      # Build for 2ND_ARCH
+      OVERRIDE_BUILT_MODULE_PATH :=
+      LOCAL_BUILT_MODULE :=
+      LOCAL_INSTALLED_MODULE :=
+      LOCAL_INTERMEDIATE_TARGETS :=
+      include $(BUILD_SYSTEM)/header_library_internal.mk
+    endif
+
+    ifdef HOST_CROSS_2ND_ARCH
+      LOCAL_2ND_ARCH_VAR_PREFIX := $(HOST_CROSS_2ND_ARCH_VAR_PREFIX)
+      include $(BUILD_SYSTEM)/module_arch_supported.mk
+
+      ifeq ($(my_module_arch_supported),true)
+        # Build for HOST_CROSS_2ND_ARCH
+        OVERRIDE_BUILT_MODULE_PATH :=
+        LOCAL_BUILT_MODULE :=
+        LOCAL_INSTALLED_MODULE :=
+        LOCAL_INTERMEDIATE_TARGETS :=
+        include $(BUILD_SYSTEM)/header_library_internal.mk
+      endif
+      LOCAL_2ND_ARCH_VAR_PREFIX :=
+    endif
+
+    LOCAL_HOST_PREFIX :=
+  endif
+endif
+
+my_module_arch_supported :=
diff --git a/core/header_library_internal.mk b/core/header_library_internal.mk
new file mode 100644
index 0000000..35ee1bc
--- /dev/null
+++ b/core/header_library_internal.mk
@@ -0,0 +1,21 @@
+###########################################################
+## Standard rules for building a header library.
+##
+## Additional inputs from base_rules.make:
+## None.
+###########################################################
+
+LOCAL_MODULE_CLASS := HEADER_LIBRARIES
+LOCAL_UNINSTALLABLE_MODULE := true
+ifneq ($(strip $(LOCAL_MODULE_STEM)$(LOCAL_BUILT_MODULE_STEM)),)
+$(error $(LOCAL_PATH): Cannot set module stem for a library)
+endif
+
+include $(BUILD_SYSTEM)/binary.mk
+
+ifneq ($(strip $(all_objects)),)
+$(call pretty-error,Header libraries may not have any sources)
+endif
+
+$(LOCAL_BUILT_MODULE):
+	$(hide) touch $@
diff --git a/core/notice_files.mk b/core/notice_files.mk
index 8a0ae6f..447e59b 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -36,7 +36,7 @@
   module_installed_filename := $(patsubst $(PRODUCT_OUT)/%,%,$(LOCAL_INSTALLED_MODULE))
 else
   # This module isn't installable
-  ifeq ($(LOCAL_MODULE_CLASS),STATIC_LIBRARIES)
+  ifneq ($(filter STATIC_LIBRARIES HEADER_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
     # Stick the static libraries with the dynamic libraries.
     # We can't use xxx_OUT_STATIC_LIBRARIES because it points into
     # device-obj or host-obj.