1# 2# Build Template 3# 4# Invoke this template with a set of variables in order to make build targets 5# for a build variant that targets a specific CPU architecture. 6# 7 8################################################################################ 9# 10# Build Template 11# 12# Invoke this to instantiate a set of build targets. Two build targets are 13# produced by this template that can be either used directly or depended on to 14# perform post processing (ie: during a nanoapp build). 15# 16# TARGET_NAME_ar - An archive of the code compiled by this template. 17# TARGET_NAME_so - A shared object of the code compiled by this template. 18# TARGET_NAME - A convenience target that depends on the above archive and 19# shared object targets. 20# 21# Nanoapps can optionally use the NANOAPP_LATE_CFLAGS variable to provide 22# compile flags, which will be added at the end of the compile command 23# (for instance, it can be used to override common flags in COMMON_CFLAGS). 24# 25# Argument List: 26# $1 - TARGET_NAME - The name of the target being built. 27# $2 - TARGET_CFLAGS - The compiler flags to use for this target. 28# $3 - TARGET_CC - The C/C++ compiler for the target variant. 29# $4 - TARGET_SO_LDFLAGS - The linker flags to use for this target. 30# $5 - TARGET_LD - The linker for the target variant. 31# $6 - TARGET_ARFLAGS - The archival flags to use for this target. 32# $7 - TARGET_AR - The archival tool for the targer variant. 33# $8 - TARGET_VARIANT_SRCS - Source files specific to this variant. 34# $9 - TARGET_BUILD_BIN - Build a binary. Typically this means that the 35# source files provided include an entry point. 36# $10 - TARGET_BIN_LDFLAGS - Linker flags that are passed to the linker 37# when building an executable binary. 38# $11 - TARGET_SO_EARLY_LIBS - Link against a set of libraries when building 39# a shared object or binary. These are placed 40# before the objects produced by this build. 41# $12 - TARGET_SO_LATE_LIBS - Link against a set of libraries when building 42# a shared object or binary. These are placed 43# after the objects produced by this build. 44# $13 - TARGET_PLATFORM_ID - The ID of the platform that this nanoapp 45# build targets. 46# $14 - TARGET_ACONFIGFLAGS - The list of aconfig flag value files specific 47# to this build target 48# $15 - TARGET_ADDITIONAL_LD - Additional linker for this target variant. 49# 50################################################################################ 51 52ifndef BUILD_TEMPLATE 53define BUILD_TEMPLATE 54 55# Target Objects ############################################################### 56 57# Remove duplicates 58COMMON_SRCS := $(sort $(COMMON_SRCS)) 59 60# Source files. 61$(1)_CC_SRCS = $$(filter %.cc, $(COMMON_SRCS) $(8)) 62$(1)_CPP_SRCS = $$(filter %.cpp, $(COMMON_SRCS) $(8)) 63$(1)_C_SRCS = $$(filter %.c, $(COMMON_SRCS) $(8)) 64$(1)_S_SRCS = $$(filter %.S, $(COMMON_SRCS) $(8)) 65 66# Object files. 67$(1)_OBJS_DIR = $(1)_objs 68$(1)_CC_OBJS = $$(patsubst %.cc, $(OUT)/$$($(1)_OBJS_DIR)/%.o, \ 69 $$($(1)_CC_SRCS)) 70$(1)_CPP_OBJS = $$(patsubst %.cpp, $(OUT)/$$($(1)_OBJS_DIR)/%.o, \ 71 $$($(1)_CPP_SRCS)) 72$(1)_C_OBJS = $$(patsubst %.c, $(OUT)/$$($(1)_OBJS_DIR)/%.o, \ 73 $$($(1)_C_SRCS)) 74$(1)_S_OBJS = $$(patsubst %.S, $(OUT)/$$($(1)_OBJS_DIR)/%.o, \ 75 $$($(1)_S_SRCS)) 76 77# Automatic dependency resolution Makefiles. 78$(1)_CC_DEPS = $$(patsubst %.cc, $(OUT)/$$($(1)_OBJS_DIR)/%.d, \ 79 $$($(1)_CC_SRCS)) 80$(1)_CPP_DEPS = $$(patsubst %.cpp, $(OUT)/$$($(1)_OBJS_DIR)/%.d, \ 81 $$($(1)_CPP_SRCS)) 82$(1)_C_DEPS = $$(patsubst %.c, $(OUT)/$$($(1)_OBJS_DIR)/%.d, \ 83 $$($(1)_C_SRCS)) 84$(1)_S_DEPS = $$(patsubst %.S, $(OUT)/$$($(1)_OBJS_DIR)/%.d, \ 85 $$($(1)_S_SRCS)) 86 87# Add object file directories. 88$(1)_DIRS = $$(sort $$(dir $$($(1)_CC_OBJS) \ 89 $$($(1)_CPP_OBJS) \ 90 $$($(1)_C_OBJS) \ 91 $$($(1)_S_OBJS))) 92 93# Outputs ###################################################################### 94 95# Shared Object 96$(1)_SO = $(OUT)/$(1)/$(OUTPUT_NAME).so 97 98# Static Archive 99$(1)_AR = $(OUT)/$(1)/$(OUTPUT_NAME).a 100 101# Nanoapp Header 102$(1)_HEADER = $$(if $(IS_NANOAPP_BUILD), $(OUT)/$(1)/$(OUTPUT_NAME).napp_header, ) 103 104# Optional Binary 105$(1)_BIN = $$(if $(9), $(OUT)/$(1)/$(OUTPUT_NAME), ) 106 107# Optional token mapping 108$(1)_TOKEN_MAP = $$(if $(CHRE_TOKENIZED_LOGGING_ENABLED), \ 109 $(OUT)/$(1)/$(OUTPUT_NAME)_log_database.bin,) 110 111$(1)_TOKEN_MAP_CSV = $$(if $(CHRE_TOKENIZED_LOGGING_ENABLED), \ 112 $(OUT)/$(1)/$(OUTPUT_NAME)_log_database.csv,) 113 114# Top-level Build Rule ######################################################### 115 116# Define the phony target. 117.PHONY: $(1)_ar 118$(1)_ar: $$($(1)_AR) 119 120.PHONY: $(1)_so 121$(1)_so: $$($(1)_SO) 122 123.PHONY: $(1)_bin 124$(1)_bin: $$($(1)_BIN) 125 126.PHONY: $(1)_header 127$(1)_header: $$($(1)_HEADER) 128 129.PHONY: $(1)_token_map 130$(1)_token_map: $$($(1)_TOKEN_MAP) 131 132.PHONY: $(1)_flags 133$(1)_flags: $$((1)_FLAGS) 134 135.PHONY: $(1) 136ifeq ($(IS_ARCHIVE_ONLY_BUILD),true) 137$(1): $(1)_flags $(1)_ar $(1)_token_map 138else 139$(1): $(1)_flags $(1)_ar $(1)_so $(1)_bin $(1)_header $(1)_token_map 140endif 141 142# If building the runtime, simply add the archive and shared object to the all 143# target. When building CHRE, it is expected that this runtime just be linked 144# into another build system (or the entire runtime is built using another build 145# system). 146ifeq ($(IS_NANOAPP_BUILD),) 147all: $(1) 148endif 149 150# Nanoapp Header Generation #################################################### 151 152# 153# Whoa there... what have we here? Some binary file generation ala bash? ಠ_ಠ 154# 155# The following build rule generates a nanoapp header. A nanoapp header is a 156# small binary blob that is prepended to a nanoapp. Android can parse this 157# blob to determine some attributes about the nanoapp, such as version and 158# target hub. The layout is as follows: 159# 160# struct NanoAppBinaryHeader { 161# uint32_t headerVersion; // 0x1 for this version 162# uint32_t magic; // "NANO" 163# uint64_t appId; // App Id, contains vendor id 164# uint32_t appVersion; // Version of the app 165# uint32_t flags; // Signed, encrypted, TCM-capable 166# uint64_t hwHubType; // Which hub type is this compiled for 167# uint8_t targetChreApiMajorVersion; // CHRE API version 168# uint8_t targetChreApiMinorVersion; 169# uint8_t reserved[6]; 170# } __attribute__((packed)); 171# 172# The basic idea here is to generate a hexdump formatted file and then reverse 173# that hexdump into binary form. The way that is accomplished is as follows. 174# 175# ... Why tho? 176# 177# The build system has a lot of knowledge of what it is building: the name of 178# the nanoapp, the version and the app ID. Marshalling this data from the 179# Makefile environment into something like python or even a small C program 180# is an unnecessary step. 181# 182# For the flags field of the struct, the following values are currently defined: 183# Signed = 0x00000001 184# Encrypted = 0x00000002 185# TCM-capable = 0x00000004 186# 187# The highest order byte is reserved for platform-specific usage. 188 189$$($(1)_HEADER): $$(OUT)/$(1) $$($(1)_DIRS) 190 printf "00000000 %.8x " `$(BE_TO_LE_SCRIPT) 0x00000001` > $$@ 191 printf "%.8x " `$(BE_TO_LE_SCRIPT) 0x4f4e414e` >> $$@ 192 printf "%.16x\n" `$(BE_TO_LE_SCRIPT) $(NANOAPP_ID)` >> $$@ 193 printf "00000010 %.8x " `$(BE_TO_LE_SCRIPT) $(NANOAPP_VERSION)` >> $$@ 194 printf "%.8x " `$(BE_TO_LE_SCRIPT) $(TARGET_NANOAPP_FLAGS)` >> $$@ 195 printf "%.16x\n" `$(BE_TO_LE_SCRIPT) $(13)` >> $$@ 196 printf "00000020 %.2x " \ 197 `$(BE_TO_LE_SCRIPT) $(TARGET_CHRE_API_VERSION_MAJOR)` >> $$@ 198 printf "%.2x " \ 199 `$(BE_TO_LE_SCRIPT) $(TARGET_CHRE_API_VERSION_MINOR)` >> $$@ 200 printf "%.12x \n" `$(BE_TO_LE_SCRIPT) 0x000000` >> $$@ 201 cp $$@ $$@_ascii 202 xxd -r $$@_ascii > $$@ 203 rm $$@_ascii 204 205# Compile ###################################################################### 206 207$$($(1)_CPP_OBJS): $(OUT)/$$($(1)_OBJS_DIR)/%.o: %.cpp $(MAKEFILE_LIST) 208 @echo " [CPP] $$<" 209 $(V)$(3) $(COMMON_CXX_CFLAGS) -DCHRE_FILENAME=\"$$(notdir $$<)\" $(2) -c \ 210 $$< -o $$@ 211 212$$($(1)_CC_OBJS): $(OUT)/$$($(1)_OBJS_DIR)/%.o: %.cc $(MAKEFILE_LIST) 213 @echo " [CC] $$<" 214 $(V)$(3) $(COMMON_CXX_CFLAGS) -DCHRE_FILENAME=\"$$(notdir $$<)\" $(2) -c \ 215 $$< -o $$@ 216 217$$($(1)_C_OBJS): $(OUT)/$$($(1)_OBJS_DIR)/%.o: %.c $(MAKEFILE_LIST) 218 @echo " [C] $$<" 219 $(V)$(3) $(COMMON_C_CFLAGS) -DCHRE_FILENAME=\"$$(notdir $$<)\" $(2) -c $$< \ 220 -o $$@ 221 222$$($(1)_S_OBJS): $(OUT)/$$($(1)_OBJS_DIR)/%.o: %.S $(MAKEFILE_LIST) 223 @echo " [AS] $$<" 224 $(V)$(3) -DCHRE_FILENAME=\"$$(notdir $$<)\" $(2) -c $$< \ 225 -o $$@ 226 227# Archive ###################################################################### 228 229# Add common and target-specific archive flags. 230$(1)_ARFLAGS = $(COMMON_ARFLAGS) \ 231 $(6) 232 233$$($(1)_AR): $$($(1)_CC_OBJS) $$($(1)_CPP_OBJS) $$($(1)_C_OBJS) \ 234 $$($(1)_S_OBJS) | $$(OUT)/$(1) $$($(1)_DIRS) 235 @echo " [AR] $$@" 236 $(V)$(7) $$($(1)_ARFLAGS) $$@ $$(filter %.o, $$^) 237 238# Token Mapping ################################################################ 239 240$$($(1)_TOKEN_MAP): $$($(1)_AR) 241 @echo " [TOKEN_MAP_GEN] $$@" 242 $(V)mkdir -p $$(@D) 243 $(V)$(TOKEN_MAP_GEN_CMD) $$($(1)_TOKEN_MAP) $$($(1)_AR) 2>&1 244 $(V)$(TOKEN_MAP_CSV_GEN_CMD) $$($(1)_TOKEN_MAP_CSV) $$($(1)_AR) 2>&1 245 246# Rust ######################################################################### 247 248ifeq ($(IS_BUILD_REQUIRING_RUST),) 249RUST_DEPENDENCIES = 250else 251RUST_DEPENDENCIES = rust_archive_$(1) 252endif 253 254# Always invoke the cargo build, let cargo decide if updates are needed 255.PHONY: rust_archive_$(1) 256rust_archive_$(1): 257 @echo " [RUST_ARCHIVE] $$@" 258 $(RUST_FLAGS) cargo +nightly build -Z build-std=core,alloc \ 259 --$(RUST_OPT_LEVEL) --target $(RUST_TARGET_DIR)/$(RUST_TARGET).json 260 261# Aconfig Flag Generation ###################################################### 262 263# This must be handled in the final build_template to allow for layers of flag 264# overwriting ( common > device_specific > local ). 265 266ifeq ($(IS_BUILD_REQUIRING_FLAG_LIBRARY),) 267FLAG_DEPENDENCIES = 268else 269FLAG_DEPENDENCIES = flagging_library_$(1) 270endif 271 272$$((1)_FLAGS): $(FLAG_DEPENDENCIES) 273 274.PHONY: flagging_library_$(1) 275flagging_library_$(1): 276 @echo " [ACONFIG] $$@" 277 $(ACONFIG_FLAG_BUILD_SCRIPT) $(ACONFIG_BIN) $(ACONFIG_EMB_DIR) \ 278 $(COMMON_ACONFIG_FLAG_VALUES) $(TARGET_ACONFIGFLAGS) 279 280# Link ######################################################################### 281 282$$($(1)_SO): $$($(1)_CC_DEPS) \ 283 $$($(1)_CPP_DEPS) $$($(1)_C_DEPS) $$($(1)_S_DEPS) \ 284 $$($(1)_CC_OBJS) $$($(1)_CPP_OBJS) $$($(1)_C_OBJS) \ 285 $$($(1)_S_OBJS) $(RUST_DEPENDENCIES) | $$(OUT)/$(1) $$($(1)_DIRS) 286 $(5) $(4) -o $$@ $(11) $$(filter %.o, $$^) $(12) $(15) 287 288$$($(1)_BIN): $$($(1)_CC_DEPS) \ 289 $$($(1)_CPP_DEPS) $$($(1)_C_DEPS) $$($(1)_S_DEPS) \ 290 $$($(1)_CC_OBJS) $$($(1)_CPP_OBJS) $$($(1)_C_OBJS) \ 291 $$($(1)_S_OBJS) | $$(OUT)/$(1) $$($(1)_DIRS) 292 $(V)$(3) -o $$@ $(11) $$(filter %.o, $$^) $(12) $(10) 293 294# Output Directories ########################################################### 295 296$$($$$(1)_DIRS): 297 $(V)mkdir -p $$@ 298 299$$(OUT)/$(1): 300 $(V)mkdir -p $$@ 301 302# Automatic Dependency Resolution ############################################## 303 304$$($(1)_CC_DEPS): $(OUT)/$$($(1)_OBJS_DIR)/%.d: %.cc 305 $(V)mkdir -p $$(dir $$@) 306 $(V)$(3) $(DEP_CFLAGS) $(COMMON_CXX_CFLAGS) \ 307 -DCHRE_FILENAME=\"$$(notdir $$<)\" $(2) -c $$< -o $$@ 308 309$$($(1)_CPP_DEPS): $(OUT)/$$($(1)_OBJS_DIR)/%.d: %.cpp 310 $(V)mkdir -p $$(dir $$@) 311 $(V)$(3) $(DEP_CFLAGS) $(COMMON_CXX_CFLAGS) \ 312 -DCHRE_FILENAME=\"$$(notdir $$<)\" $(2) -c $$< -o $$@ 313 314$$($(1)_C_DEPS): $(OUT)/$$($(1)_OBJS_DIR)/%.d: %.c 315 $(V)mkdir -p $$(dir $$@) 316 $(V)$(3) $(DEP_CFLAGS) $(COMMON_C_CFLAGS) \ 317 -DCHRE_FILENAME=\"$$(notdir $$<)\" $(2) -c $$< -o $$@ 318 319$$($(1)_S_DEPS): $(OUT)/$$($(1)_OBJS_DIR)/%.d: %.S 320 $(V)mkdir -p $$(dir $$@) 321 $(V)$(3) $(DEP_CFLAGS) \ 322 -DCHRE_FILENAME=\"$$(notdir $$<)\" $(2) -c $$< -o $$@ 323 324# Include generated dependency files if they are in the requested build target. 325# This avoids dependency generation from occuring for a debug target when a 326# non-debug target is requested. 327ifneq ($(filter $(1) all, $(MAKECMDGOALS)),) 328-include $$(patsubst %.o, %.d, $$($(1)_CC_DEPS)) 329-include $$(patsubst %.o, %.d, $$($(1)_CPP_DEPS)) 330-include $$(patsubst %.o, %.d, $$($(1)_C_DEPS)) 331-include $$(patsubst %.o, %.d, $$($(1)_S_DEPS)) 332endif 333 334endef 335endif 336 337# Template Invocation ########################################################## 338 339TARGET_CFLAGS_LOCAL = $(TARGET_CFLAGS) 340TARGET_CFLAGS_LOCAL += -DCHRE_PLATFORM_ID=$(TARGET_PLATFORM_ID) 341 342# Default the nanoapp header flag values to signed if not overidden. 343TARGET_NANOAPP_FLAGS ?= 0x00000001 344$(eval $(call BUILD_TEMPLATE,$(TARGET_NAME), \ 345 $(COMMON_CFLAGS) $(TARGET_CFLAGS_LOCAL) \ 346 $(NANOAPP_LATE_CFLAGS), \ 347 $(TARGET_CC), \ 348 $(TARGET_SO_LDFLAGS), \ 349 $(TARGET_LD), \ 350 $(TARGET_ARFLAGS), \ 351 $(TARGET_AR), \ 352 $(TARGET_VARIANT_SRCS), \ 353 $(TARGET_BUILD_BIN), \ 354 $(TARGET_BIN_LDFLAGS), \ 355 $(TARGET_SO_EARLY_LIBS), \ 356 $(TARGET_SO_LATE_LIBS), \ 357 $(TARGET_PLATFORM_ID), \ 358 $(TARGET_ACONFIGFLAGS), \ 359 $(TARGET_ADDITIONAL_LD))) 360 361# Debug Template Invocation #################################################### 362 363$(eval $(call BUILD_TEMPLATE,$(TARGET_NAME)_debug, \ 364 $(COMMON_CFLAGS) $(COMMON_DEBUG_CFLAGS) \ 365 $(TARGET_CFLAGS_LOCAL) $(TARGET_DEBUG_CFLAGS) \ 366 $(NANOAPP_LATE_CFLAGS), \ 367 $(TARGET_CC), \ 368 $(TARGET_SO_LDFLAGS), \ 369 $(TARGET_LD), \ 370 $(TARGET_ARFLAGS), \ 371 $(TARGET_AR), \ 372 $(TARGET_VARIANT_SRCS), \ 373 $(TARGET_BUILD_BIN), \ 374 $(TARGET_BIN_LDFLAGS), \ 375 $(TARGET_SO_EARLY_LIBS), \ 376 $(TARGET_SO_LATE_LIBS), \ 377 $(TARGET_PLATFORM_ID), \ 378 $(TARGET_ACONFIGFLAGS), \ 379 $(TARGET_ADDITIONAL_LD))) 380