1# Copyright 2023 Nordic Semiconductor ASA
2# SPDX-License-Identifier: Apache-2.0
3
4# Native Simulator (NSI) Makefile.
5# It builds the simulator runner itself, and produces the final
6# Linux executable by linking it to the embedded cpu library
7
8# By default all the build output is placed under the _build folder, but the user can override it
9# setting the NSI_BUILD_PATH
10#
11# The caller can provide an optional configuration file and point to it with NSI_CONFIG_FILE
12# See "Configurable/user overridible variables" below.
13#
14# By default only the core of the runner will be built, but the caller can set NSI_NATIVE
15# to also build the components in native/src/
16
17NSI_CONFIG_FILE?=nsi_config
18-include ${NSI_CONFIG_FILE}
19#If the file does not exist, we don't use it as a build dependency
20NSI_CONFIG_FILE:=$(wildcard ${NSI_CONFIG_FILE})
21
22# Configurable/user overridible variables:
23#  Path to the native_simulator (this folder):
24NSI_PATH?=./
25#  Folder where the build output will be placed
26NSI_BUILD_PATH?=$(abspath _build/)
27EXE_NAME?=native_simulator.exe
28#  Final executable path/file_name which will be produced
29NSI_EXE?=${NSI_BUILD_PATH}/${EXE_NAME}
30# Number of embedded CPUs/MCUs
31NSI_N_CPUS?=1
32# Path to all CPUs embedded SW which will be linked with the final executable
33NSI_EMBEDDED_CPU_SW?=
34#  Host architecture configuration switch
35NSI_ARCH?=-m32
36#  Coverage switch (GCOV coverage is enabled by default)
37NSI_COVERAGE?=--coverage
38NSI_LOCALIZE_OPTIONS?=
39NSI_BUILD_OPTIONS?=${NSI_ARCH} ${NSI_COVERAGE}
40NSI_LINK_OPTIONS?=${NSI_ARCH} ${NSI_COVERAGE}
41NSI_BUILD_C_OPTIONS?=
42NSI_BUILD_CXX_OPTIONS?=
43#  Extra source files to be built in the runner context
44NSI_EXTRA_SRCS?=
45#  Extra include directories to be used while building in the runner context
46NSI_EXTRA_INCLUDES?=
47#  Extra libraries to be linked to the final executable
48NSI_EXTRA_LIBS?=
49
50SHELL?=bash
51#  Compiler
52NSI_CC?=gcc
53NSI_CXX?=g++
54NSI_LINKER?=${NSI_CC}
55#  Archive program (it is unlikely you'll need to change this)
56NSI_AR?=ar
57#  Objcopy program (it is unlikely you'll need to change this)
58NSI_OBJCOPY?=objcopy
59
60#  Build debug switch (by default enabled)
61NSI_DEBUG?=-g
62#  Build optimization level (by default disabled to ease debugging)
63NSI_OPT?=-O0
64#  Warnings switches (for the runner itself)
65NSI_WARNINGS?=-Wall -Wpedantic
66#  Preprocessor flags
67NSI_CPPFLAGS?=-D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED
68
69NO_PIE_CO:=-fno-pie -fno-pic
70DEPENDFLAGS:=-MMD -MP
71COMMON_BUILD_FLAGS:=-DNSI_RUNNER_BUILD ${NSI_DEBUG} ${NSI_WARNINGS} ${NSI_OPT} ${NO_PIE_CO} \
72  -DNSI_N_CPUS=${NSI_N_CPUS} -ffunction-sections -fdata-sections ${DEPENDFLAGS} ${NSI_BUILD_OPTIONS}
73CFLAGS:=-std=c11 ${COMMON_BUILD_FLAGS} ${NSI_BUILD_C_OPTIONS}
74CXXFLAGS:=${COMMON_BUILD_FLAGS} ${NSI_BUILD_CXX_OPTIONS}
75FINALLINK_FLAGS:=${NO_PIE_CO} -no-pie  ${NSI_WARNINGS} \
76  -Wl,--gc-sections -ldl -pthread \
77  ${NSI_LINK_OPTIONS} -lm
78
79no_default:
80	@echo "There is no default rule, please specify what you want to build,\
81 or run make help for more info"
82
83RUNNER_LIB:=runner.a
84
85SRCS:=$(shell ls ${NSI_PATH}common/src/*.c)
86ifdef NSI_NATIVE
87  SRCS+=$(shell ls ${NSI_PATH}native/src/*.c)
88endif
89
90INCLUDES:=-I${NSI_PATH}common/src/include/ \
91 -I${NSI_PATH}common/src \
92 ${NSI_EXTRA_INCLUDES}
93
94ifdef NSI_NATIVE
95  INCLUDES+=-I${NSI_PATH}native/src/include/
96endif
97
98EXTRA_OBJS:=$(abspath $(addprefix $(NSI_BUILD_PATH)/,$(sort $(patsubst %.c,%.o,${NSI_EXTRA_SRCS:%.cpp=%.c}))))
99OBJS:=$(abspath $(addprefix $(NSI_BUILD_PATH)/,${SRCS:${NSI_PATH}%.c=%.o})) ${EXTRA_OBJS}
100
101DEPENDFILES:=$(addsuffix .d,$(basename ${OBJS}))
102
103-include ${DEPENDFILES}
104
105LOCALIZED_EMBSW:=$(abspath $(addprefix $(NSI_BUILD_PATH)/,$(addsuffix .loc_cpusw.o,${NSI_EMBEDDED_CPU_SW})))
106
107${NSI_BUILD_PATH}:
108	@if [ ! -d ${NSI_BUILD_PATH} ]; then mkdir -p ${NSI_BUILD_PATH}; fi
109
110#Extra sources build:
111${NSI_BUILD_PATH}/%.o: /%.c ${NSI_PATH}Makefile ${NSI_CONFIG_FILE}
112	@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
113	${NSI_CC} ${NSI_CPPFLAGS} ${INCLUDES} ${CFLAGS} -c $< -o $@
114
115#Extra C++ sources build:
116${NSI_BUILD_PATH}/%.o: /%.cpp ${NSI_PATH}Makefile ${NSI_CONFIG_FILE}
117	@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
118	${NSI_CXX} ${NSI_CPPFLAGS} ${INCLUDES} ${CXXFLAGS} -c $< -o $@
119
120${NSI_BUILD_PATH}/%.o: ${NSI_PATH}/%.c ${NSI_PATH}Makefile ${NSI_CONFIG_FILE}
121	@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
122	${NSI_CC} ${NSI_CPPFLAGS} ${INCLUDES} ${CFLAGS} -c $< -o $@
123
124${NSI_BUILD_PATH}/linker_script.ld : ${NSI_PATH}/common/other/linker_script.pre.ld | ${NSI_BUILD_PATH}
125	${NSI_CC} -x c -E -P $< -o $@  ${DEPENDFLAGS}
126
127${NSI_BUILD_PATH}/${RUNNER_LIB}: ${OBJS}
128	if [ -f $@ ]; then rm $@ ; fi
129	${NSI_AR} -cr $@ ${OBJS}
130
131${NSI_BUILD_PATH}/%.loc_cpusw.o: /% ${NSI_CONFIG_FILE}
132	@if [ -z $< ] || [ ! -f $< ]; then \
133	  echo "Error: Input embedded CPU SW ($<) not found \
134(NSI_EMBEDDED_CPU_SW=${NSI_EMBEDDED_CPU_SW} )"; \
135	  false; \
136	fi
137	@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
138	${NSI_OBJCOPY} --localize-hidden $< $@ -w --localize-symbol=_* ${NSI_LOCALIZE_OPTIONS}
139
140${NSI_EXE}: ${NSI_BUILD_PATH}/${RUNNER_LIB} ${LOCALIZED_EMBSW} ${NSI_EXTRA_LIBS} \
141 ${NSI_BUILD_PATH}/linker_script.ld
142	${NSI_LINKER} -Wl,--whole-archive ${LOCALIZED_EMBSW} ${NSI_BUILD_PATH}/${RUNNER_LIB} \
143	  ${NSI_EXTRA_LIBS} -Wl,--no-whole-archive \
144	  -o $@ ${FINALLINK_FLAGS} -T ${NSI_BUILD_PATH}/linker_script.ld
145
146Makefile: ;
147
148link_with_esw: ${NSI_EXE};
149
150runner_lib: ${NSI_BUILD_PATH}/${RUNNER_LIB}
151
152all: link_with_esw
153
154clean:
155	@echo "Deleting intermediate compilation results + libraries + executables (*.d .o .a .exe)"
156	find $(NSI_BUILD_PATH) -name "*.o" -or -name "*.exe" -or -name "*.a" -or -name "*.d" | xargs rm -f
157
158clean_coverage:
159	find $(NSI_BUILD_PATH) -name "*.gcda" -or -name "*.gcno" | xargs rm -f ; true
160
161clean_all: clean clean_coverage ;
162
163.PHONY: clean clean_coverage clean_all link_with_esw runner_lib no_default all ${DEPENDFILES}
164
165ifndef NSI_BUILD_VERBOSE
166.SILENT:
167endif
168
169help:
170	@echo "*******************************"
171	@echo "* Native Simulator makefile *"
172	@echo "*******************************"
173	@echo "Provided rules:"
174	@echo " clean           : clean all build output"
175	@echo " clean_coverage  : clean all coverage files"
176	@echo " clean_all       : clean + clean_coverage"
177	@echo " link_with_esw   : Link the runner with the CPU embedded sw"
178	@echo " runner_lib      : Build the runner itself (pending the embedded SW)"
179	@echo " all             : link_with_esw"
180	@echo "Note that you can use TAB to autocomplete rules in the command line in modern OSs"
181