1#-------------------------------------------------------------------------------
2# Copyright (c) 2001-2020, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8# Makefile definitions common to all Host components build
9# This file should be included at the start of a Makefile
10
11# Note: The caller (or environment) should provide the following variables:
12# ARCH = Target architectore, e.g., powerpc
13# OS = Target OS, e.g., linux
14# HOST_PROJ_ROOT = The root of the host domain tree (where this file is located)
15
16# LOGFILE = log file name. Default is makelog.txt in the current dir.
17
18### Determine host environment
19_UNAME_OS=$(shell uname -o)
20
21ifeq (Cygwin,$(_UNAME_OS))
22  HOST=WINDOWS
23  HOST_OS=CYGWIN
24else ifeq (Msys,$(_UNAME_OS))
25  HOST=WINDOWS
26  HOST_OS=MSYS
27else ifeq (GNU/Linux,$(_UNAME_OS))
28  HOST=LINUX
29  HOST_OS=LINUX
30else
31  HOST=UNKNOWN
32  HOST_OS=UNKNOWN
33endif
34
35
36### Build platform commands (Currently assumes Linux/Unix/Cygwin machine)
37SHELL = /bin/bash -o pipefail
38RM = rm -f
39ECHO = echo
40MKDIR = mkdir -p
41RMDIR = rm -rf
42CP = cp -P
43CP_DEREF = cp -L
44SYMLINK = ln -s
45MAKE = make
46
47LOGFILE ?= ./makelog.txt
48
49### Build environment setup ###
50
51#On windows when running from an emulated POSIX environment we have
52#to deal with three different kind of paths. The native windows path
53#i.e. c:\foo\bar, the POSIX path i.e. /c/foo/bar or
54#/cygdrive/c/foo/bar and the mixed path which is the native path but
55#with forward slashes (i.e. c:/foo/bar).
56#Executables compiled in the POSIX environment understand the
57#POSIX and the mixed path. Native windows executables (i.e. compilers
58#understand the native and the mixed path.
59#To avoid path issues the best is to use the mixed path. Use the
60#cygpath tool to do the conversion.
61#Note: the pwd command provided by the shell must not be used in the
62#      makefiles!
63
64ifneq (,$(filter ${HOST_OS},CYGWIN MSYS))
65	PWD := $(shell cygpath -am . |  tr -d '\r\n')
66else
67	PWD := $(shell readlink -f .)
68endif
69
70ifndef HOST_PROJ_ROOT
71$(error HOST_PROJ_ROOT is undefined)
72endif
73
74# Host domain root converted to absolut path
75ifneq (,$(filter ${HOST_OS},CYGWIN MSYS))
76	HOST_PROJ_ROOT := $(shell cygpath -am $(HOST_PROJ_ROOT) |  tr -d '\r\n')
77else
78	HOST_PROJ_ROOT := $(shell readlink -f $(HOST_PROJ_ROOT))
79endif
80HOST_SRCDIR := $(HOST_PROJ_ROOT)/src
81SHARED_DIR := $(HOST_PROJ_ROOT)/../shared
82SHARED_INCDIR := $(SHARED_DIR)/include
83SHARED_SRCDIR := $(SHARED_DIR)/src
84CODESAFE_DIR := $(HOST_PROJ_ROOT)/../codesafe
85CODESAFE_SRCDIR := $(CODESAFE_DIR)/src
86UTILS_DIR := $(HOST_PROJ_ROOT)/../utils
87UTILS_SRCDIR := $(UTILS_DIR)/src
88#Note: on windows GCC seems to ignore ./ as an include path with:
89#  ignoring nonexistent directory. Using . seems to work.
90INCDIRS = . $(INCDIRS_EXTRA)
91INCDIRS += $(SHARED_INCDIR) $(SHARED_INCDIR)/proj/$(PROJ_PRD)
92# $(SHARED_INCDIR)/pal $(SHARED_INCDIR)/pal/$(TEE_OS) $(SHARED_INCDIR)/pal/$(TEE_OS)/include
93INCDIRS +=  $(HOST_PROJ_ROOT)/include
94LIBDIRS = . $(LIBDIRS_EXTRA) $(HOST_PROJ_ROOT)/lib
95
96HOST_LIBDIR = $(HOST_SRCDIR)/$(HOST_LIBNAME)
97
98# Release directories
99RELEASE_INCDIR = $(HOST_PROJ_ROOT)/include
100RELEASE_LIBDIR = $(HOST_PROJ_ROOT)/lib
101RELEASE_EXEDIR = $(HOST_PROJ_ROOT)/bin
102# SCRDIR for scripts
103RELEASE_SCRDIR = $(HOST_PROJ_ROOT)/bin
104# DATDIR for data/binary files
105RELEASE_DATDIR = $(HOST_PROJ_ROOT)/dat
106
107################################################
108### Handle project configuration definitions ###
109################################################
110PROJ_CFG_FNAME = proj.cfg
111PROJ_EXT_CFG_FNAME = proj.ext.cfg
112PROJ_CFG_PATH = $(HOST_PROJ_ROOT)/$(PROJ_CFG_FNAME)
113PROJ_EXT_CFG_PATH = $(HOST_PROJ_ROOT)/../$(PROJ_EXT_CFG_FNAME)
114CONFIGS_PATH = src/configs
115PROJ_CONFIGS_DIR = $(HOST_PROJ_ROOT)/$(CONFIGS_PATH)
116
117#Test directories
118ifeq ($(TEE_OS),freertos)
119KERNEL_LIB_DIR  := $(KERNEL_DIR)/lib
120KERNEL_TEST_DIR := $(KERNEL_DIR)/lib/tests
121endif
122
123### Toolchain setup ###
124ARCH_SUPPORTED = powerpc arm arm64 i686 x86 x86_64 x86win
125# i686 or x86_64 - compilation for i686(x86)/x86_64 Linux using native toolchain.
126# x86win - compilation for x86 Windows, using MinGW toolchain.
127
128# default ARCH
129ARCH ?= powerpc
130export ARCH
131#$(info ARCH=$(ARCH))
132
133ifeq ($(filter $(ARCH),$(ARCH_SUPPORTED)),)
134  $(error Unsupported ARCH==$(ARCH))
135endif
136
137#initiate variable to avoid concatinatation at every target level
138CFLAGS =
139
140ifeq ($(ARCH),arm64)
141	# aarch64-linux-gnu-
142	CROSS_COMPILE := $(if $(filter aarch64-%,$(CROSS_COMPILE)),$(CROSS_COMPILE),aarch64-linux-gnu-)
143	ARCH_ENDIAN = LITTLE
144endif
145
146# The following statements would be executed only if ARCH is one of the supported ones.
147ifeq ($(ARCH),powerpc)
148	CROSS_COMPILE := ppc_4xx-
149	ARCH_ENDIAN = BIG
150	CFLAGS += -isystem /opt/eldk/ppc_4xx/usr/include
151endif
152
153ifeq ($(ARCH),x86win)
154	# Compiling for x86-windows - using MinGW toolchain.
155	CROSS_COMPILE ?= i586-mingw32msvc-
156endif
157
158# subfolder for compilation/generation outcome/objects/binaries
159BUILDDIR = $(PWD)/build-$(CROSS_COMPILE:%-=%)
160
161### proj.cfg exists. Include it to get project configuration definitions ###
162ifeq ($(wildcard $(PROJ_CFG_PATH)),$(PROJ_CFG_PATH))
163include $(PROJ_EXT_CFG_PATH)
164include $(PROJ_CFG_PATH)
165endif
166
167ifeq ($(ARCH),arm)
168	# For android NDK must define -ffreestanding to be able to build with Bionic library, etc.
169	CFLAGS += $(if $(filter arm-linux-androideabi-,$(CROSS_COMPILE)),-ffreestanding)
170	# Same requirement for arm-eabi (bare metal) due to use of RTOS (private) libc implementation
171	CFLAGS += $(if $(filter arm-eabi-,$(CROSS_COMPILE)),-ffreestanding)
172	ARCH_ENDIAN = LITTLE
173    ifeq ($(CROSS_COMPILE),arm-bcm2708hardfp-linux-gnueabi-)
174        # RaspberryPi (ARM11/ARMv6) support
175        $(info Assuming build for RaspberryPi)
176        CFLAGS += -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
177    else ifeq ($(CROSS_COMPILE),arm-none-eabi-)
178        ifeq ($(ARM_CPU), cortex-m33)
179            CFLAGS += -march=armv8-m.main
180            CFLAGS += -mcmse
181            CFLAGS += -DARCH_V8M
182        else ifeq ($(ARM_CPU), cortex-m3)
183            # For arm-none-eabi assume cortex-m3
184            ARM_CPU ?= cortex-m3
185            CFLAGS += -mcpu=$(ARM_CPU)
186        else ifeq ($(ARM_CPU), cortex-m0plus)
187            ARM_CPU ?= cortex-m0plus
188            CFLAGS += -mcpu=$(ARM_CPU)
189        else
190            $(error unrecognized ARM_CPU "$(ARM_CPU)")
191        endif
192        CFLAGS += -mthumb
193        TEE_OS = no_os
194    else ifeq ($(CROSS_COMPILE),armcc)
195        ARM_CPU ?= cortex-m3
196        CFLAGS += --cpu $(ARM_CPU) --littleend
197        CFLAGS += --thumb
198    else ifeq ($(CROSS_COMPILE),armclang)
199        ifeq ($(ARM_CPU), cortex-m33)
200            CFLAGS += -march=armv8-m.main
201            CFLAGS += -mcmse
202            CFLAGS += -mfpu=none
203            CFLAGS += -DARCH_V8M
204        else ifeq ($(ARM_CPU), cortex-m3)
205            ARM_CPU ?= cortex-m3
206            CFLAGS += -mcpu=$(ARM_CPU)
207        else ifeq ($(ARM_CPU), cortex-m0plus)
208            ARM_CPU ?= cortex-m0plus
209            CFLAGS += -mcpu=$(ARM_CPU)
210        else
211            $(error unrecognized ARM_CPU "$(ARM_CPU)")
212        endif
213        CFLAGS += --target=arm-arm-none-eabi -mlittle-endian
214        CFLAGS += -mthumb
215        CFLAGS += -DCC_TEE -DDX_PLAT_MPS2_PLUS
216    endif
217    # For arm-eabi- assume a15, otherwise assume a9 (zynq7000)
218    ARM_CPU ?= $(if $(filter arm-eabi-,$(CROSS_COMPILE)),cortex-a15,cortex-a9)
219    ifeq ($(filter arm ,$(CROSS_COMPILE)),$(CROSS_COMPILE))
220        CFLAGS += --cpu $(ARM_CPU) --littleend
221    endif
222    CFLAGS += $(if $(filter arm-eabi-,$(CROSS_COMPILE)),-DARCH_ARM -DARM_CPU_CORTEX_A15=1)
223    # for optee_os
224    ifeq ($(CROSS_COMPILE),arm-linux-gnueabihf-)
225        CFLAGS += -mfloat-abi=soft
226    endif #arm-linux-gnueabihf-
227
228    export CORTEX
229    export ARM_CPU
230endif #arm
231
232ifneq ($(filter i686 x86 x86win x86_64,$(ARCH)),) # x86* Arch.
233	ARCH_ENDIAN = LITTLE
234endif
235
236ifeq ($(filter arm arm-dsm- armcc ,$(CROSS_COMPILE)),$(CROSS_COMPILE))
237CC_DEF = 1
238CC = armcc
239LD = armcc
240AR = armar
241ifneq ($(CROSS_COMPILE),armcc)
242override TEE_OS = no_os
243endif
244endif
245
246ifeq ($(filter armclang ,$(CROSS_COMPILE)),$(CROSS_COMPILE))
247CC_DEF = 1
248CC = armclang
249LD = armlink
250AR = armar
251endif
252
253# Object file suffix
254OBJEXT = .o
255
256# Library prefix
257LIBPRE = lib
258
259# In Unix/Linux there is no extension to executables. Set to ".exe" for Windows.
260EXEEXT =
261
262
263ifeq ($(CC_DEF),)
264CC = $(CROSS_COMPILE)gcc
265CPP = $(CROSS_COMPILE)g++
266LD = $(CROSS_COMPILE)gcc
267AR = $(CROSS_COMPILE)ar
268RANLIB = $(CROSS_COMPILE)ranlib
269endif
270
271# Helper variables for complex string definitions
272comma := ,
273
274############
275# Logged execution "function". To be used with make's $(call...).
276# Its "parameter is the command to execute
277# The "function" puts all stdout into LOGFILE. The stderr is output to both terminal and a tmp file, than appends
278# the error to the LOGFILE.
279# This complexity is required because of pipe's nature which prevents appending while piping into the log file.
280ifeq ($(LOGFILE),-)
281	exec_logged = $(1)
282	exec_logged_evaled = $(1)
283else
284	exec_logged = ( $(ECHO) $(shell date): "$(1)"  >> $(LOGFILE) ; ( $(1) ) >>$(LOGFILE) 2>logerr.tmp ; err=$$? ; cat logerr.tmp ; cat logerr.tmp >> $(LOGFILE) ; rm logerr.tmp ; exit $$err)
285	# nested version is to be $(call)ed from within another $(eval)
286	exec_logged_evaled = ( $(ECHO) $$(shell date): "$(1)"  >> $(LOGFILE) ; ( $(1) ) >>$(LOGFILE) 2>logerr.tmp ; err=$$$$? ; cat logerr.tmp ; cat logerr.tmp >> $(LOGFILE) ; rm logerr.tmp ; exit $$$$err)
287endif
288
289exec_logged_and_echo = $(ECHO) $(1) ; $(exec_logged)
290############
291
292
293# Generate dependency on existence only (i.e., don't care if newer).
294# To be used primarily for directories creation
295DEPENDENCY_ON_EXISTENCE_OF = $(filter-out $(wildcard $(1)),$(1))
296
297
298############ Special rules for project configuration selection ##############
299ifneq ($(wildcard $(PROJ_CFG_PATH)),$(PROJ_CFG_PATH)) # No proj.cfg linked
300
301all: # default in case there is no proj.cfg and setconfig_ was not used
302	$(info Invoke 'make setconfig_<config. name>' to select project configuration )
303	$(error 'proj.cfg' not found)
304
305setconfig_%: $(PROJ_CONFIGS_DIR)/proj-%.cfg
306	@$(info [CFG] $(CONFIGS_PATH)/proj-$*.cfg --> proj.cfg)
307	@cd $(HOST_PROJ_ROOT) && ln -s $(CONFIGS_PATH)/proj-$*.cfg $(PROJ_CFG_FNAME)
308	@$(if $(findstring cc312,$<), $(if $(findstring integration_tests,$<),,$(if $(or $(findstring devel,$<), $(findstring llhw,$<)), make -C tests copy_infra_suite,)),)
309
310$(PROJ_CONFIGS_DIR)/proj-%.cfg:
311	@$(error Unknown project configuration. $@ does not exist.)
312
313clrconfig:
314	$(info [CFG-CLN] No active configuration )
315
316.PHONY: all setconfig_% clrconfig
317
318else
319# default TEE_OS
320REE_OS ?= linux
321TEE_OS ?= cc_linux
322export REE_OS
323export TEE_OS
324#$(info REE_OS=$(REE_OS))
325#$(info TEE_OS=$(TEE_OS))
326
327#TestAL defs
328TESTAL_PATH_PAL = $(HOST_SRCDIR)/tests/infrastructure_suite/pal/lib
329TESTAL_PATH_HAL = $(HOST_SRCDIR)/tests/infrastructure_suite/hal/lib
330ifeq ($(ARM_CPU),cortex-a9)
331TESTAL_PAL_ARCH = ca9
332endif
333ifeq ($(ARM_CPU),cortex-m3)
334TESTAL_PAL_ARCH = cm3
335endif
336ifeq ($(ARM_CPU),cortex-m0plus)
337TESTAL_PAL_ARCH = cm0plus
338endif
339ifeq ($(ARM_CPU),cortex-m33)
340TESTAL_PAL_ARCH = cm33
341endif
342ifeq ($(ARCH),arm64)
343TESTAL_PAL_ARCH = ca72.ca53
344endif
345TESTAL_PAL_OS = $(subst cc_,,$(TEE_OS))
346
347TESTAL_PAL_LIB = *PAL*$(TESTAL_PAL_OS)*$(CROSS_COMPILE)*$(TESTAL_PAL_ARCH)*.a
348TESTAL_HAL_LIB = *HAL*$(TESTAL_PAL_OS)*$(CROSS_COMPILE)*$(TESTAL_PAL_ARCH)*.a
349
350#Tests PAL HAL defs
351TESTS_PAL_LIB_NAME = libtests_pal.a
352TESTS_HAL_LIB_NAME = libtests_hal.a
353
354
355all: default
356
357# setconfig_/clrconfig are available only if $(PROJ_CONFIGS_DIR) exists
358# (i.e., eliminated on release trees)
359ifeq ($(wildcard $(PROJ_CONFIGS_DIR)),$(PROJ_CONFIGS_DIR))
360# Configuration rules
361setconfig_%:
362	$(if $(filter $(CONFIGS_PATH)/proj-$*.cfg,$(shell readlink $(PROJ_CFG_PATH))),$(info $* configuration is already set.),$(error Before changing configuration invoke 'make clrconfig'))
363
364clrconfig:
365	@$(ECHO) [CFG-CLN] X $(shell readlink $(PROJ_CFG_PATH))
366	@rm -f $(PROJ_CFG_PATH)
367	@$(ECHO) PROJ_NAME is $(PROJ_NAME)
368	@$(if $(findstring devel,$(PROJ_NAME)), echo calling clean_infra_suite && make -C tests clean_infra_suite, echo ff$(PROJ_NAME)ff clrconfig )
369endif
370
371endif
372
373# Provide lsconfig to list available configurations
374configs_list = $(foreach cfg_file,$(wildcard $(PROJ_CONFIGS_DIR)/proj-*.cfg),$(patsubst $(PROJ_CONFIGS_DIR)/proj-%.cfg,%,$(cfg_file)))
375lsconfig:
376	@$(info Available project configurations:)
377	@$(foreach cfg_file,$(configs_list),$(info $(cfg_file)))
378
379.PHONY: all setconfig_% clrconfig lsconfig
380