| giuliomoro@301 | 1 # Bela | 
| giuliomoro@64 | 2 # Low-latency, real-time audio and sensor processing on BeagleBone Black | 
| l@260 | 3 # (c) 2016 Andrew McPherson, Victor Zappi, Giulio Moro, Liam Donovan | 
| giuliomoro@64 | 4 # Centre for Digital Music, Queen Mary University of London | 
| giuliomoro@64 | 5 | 
| giuliomoro@64 | 6 # This Makefile is intended for use on the BeagleBone Black itself | 
| giuliomoro@64 | 7 # and not for cross-compiling | 
| giuliomoro@64 | 8 | 
| giuliomoro@386 | 9 .DEFAULT_GOAL := Bela | 
| giuliomoro@386 | 10 | 
| giuliomoro@386 | 11 NO_PROJECT_TARGETS=coreclean distclean stop help | 
| giuliomoro@385 | 12 NO_PROJECT_TARGETS_MESSAGE=PROJECT or EXAMPLE should be set for all targets except: $(NO_PROJECT_TARGETS) | 
| giuliomoro@385 | 13 # Type `$ make help` to get a description of the functionalities of this Makefile. | 
| giuliomoro@385 | 14 help: ## Show this help | 
| giuliomoro@385 | 15 	@echo 'Usage: make [target] CL=[command line options] [PROJECT=[projectName] | EXAMPLE=[exampleName]]' | 
| giuliomoro@386 | 16 	@printf "\n$(NO_PROJECT_TARGETS_MESSAGE)\n\n" | 
| giuliomoro@386 | 17 	@echo 'Targets: (default: $(.DEFAULT_GOAL))' | 
| giuliomoro@385 | 18 	@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e  's/^\(.*\): .*##\(.*\)/\1:#\2/' | column -t -c 2 -s '#' | 
| l@260 | 19 | 
| giuliomoro@385 | 20 # PROJECT or EXAMPLE must be set for targets that are not included in NO_PROJECT_TARGETS | 
| giuliomoro@374 | 21 ifeq (,$(filter $(NO_PROJECT_TARGETS),$(MAKECMDGOALS))) | 
| giuliomoro@374 | 22   ifndef PROJECT | 
| giuliomoro@374 | 23     ifndef EXAMPLE | 
| giuliomoro@385 | 24       $(error $(NO_PROJECT_TARGETS_MESSAGE)) | 
| giuliomoro@374 | 25     endif | 
| giuliomoro@287 | 26   endif | 
| l@260 | 27 endif | 
| l@260 | 28 | 
| giuliomoro@374 | 29 # if we are building an example, just copy it to the projects/ folder | 
| giuliomoro@386 | 30 # and then treat it as a project | 
| giuliomoro@374 | 31 ifdef EXAMPLE | 
| giuliomoro@374 | 32   PROJECT?=exampleTempProject | 
| giuliomoro@374 | 33   PROJECT_DIR?=$(abspath projects/$(PROJECT)) | 
| andrewm@380 | 34   $(shell mkdir -p $(abspath projects)) | 
| giuliomoro@374 | 35   $(shell rm -rf $(PROJECT_DIR)) | 
| giuliomoro@374 | 36   $(shell cp -r examples/$(EXAMPLE) $(PROJECT_DIR)) | 
| giuliomoro@374 | 37 else | 
| giuliomoro@287 | 38   PROJECT_DIR := $(abspath projects/$(PROJECT)) | 
| giuliomoro@287 | 39 endif | 
| giuliomoro@287 | 40 | 
| giuliomoro@374 | 41 ifdef PROJECT | 
| giuliomoro@374 | 42   $(shell mkdir -p $(PROJECT_DIR)/build) | 
| giuliomoro@287 | 43 endif | 
| giuliomoro@374 | 44 | 
| giuliomoro@331 | 45 OUTPUT_FILE?=$(PROJECT_DIR)/$(PROJECT) | 
| giuliomoro@331 | 46 COMMAND_LINE_OPTIONS?=$(CL) | 
| giuliomoro@331 | 47 RUN_COMMAND?=$(OUTPUT_FILE) $(COMMAND_LINE_OPTIONS) | 
| l@387 | 48 RUN_IDE_COMMAND?=stdbuf -i0 -o0 -e0 $(OUTPUT_FILE) $(COMMAND_LINE_OPTIONS) | 
| andrewm@391 | 49 BELA_STARTUP_SCRIPT?=/root/Bela_startup.sh | 
| giuliomoro@359 | 50 BELA_AUDIO_THREAD_NAME?=bela-audio | 
| giuliomoro@377 | 51 SCREEN_NAME?=Bela | 
| giuliomoro@302 | 52 | 
| giuliomoro@374 | 53 | 
| giuliomoro@64 | 54 RM := rm -rf | 
| giuliomoro@64 | 55 STATIC_LIBS := ./libprussdrv.a ./libNE10.a | 
| l@260 | 56 LIBS := -lrt -lnative -lxenomai -lsndfile | 
| l@260 | 57 | 
| giuliomoro@244 | 58 # refresh library cache and check if libpd is there | 
| giuliomoro@326 | 59 #TEST_LIBPD := $(shell ldconfig; ldconfig -p | grep "libpd\.so")  # safest but slower way of checking | 
| giuliomoro@326 | 60 LIBPD_PATH = /usr/lib/libpd.so | 
| giuliomoro@326 | 61 TEST_LIBPD := $(shell which $(LIBPD_PATH)) | 
| giuliomoro@326 | 62 ifneq ($(strip $(TEST_LIBPD)), ) | 
| giuliomoro@244 | 63 # if libpd is there, link it in | 
| giuliomoro@244 | 64   LIBS += -lpd -lpthread_rt | 
| giuliomoro@244 | 65 endif | 
| giuliomoro@64 | 66 | 
| giuliomoro@241 | 67 CPP_FLAGS := -O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon -ftree-vectorize | 
| giuliomoro@241 | 68 C_FLAGS := $(CPP_FLAGS) | 
| giuliomoro@241 | 69 | 
| giuliomoro@241 | 70 ifndef COMPILER | 
| giuliomoro@241 | 71 # check whether clang is installed | 
| giuliomoro@385 | 72   TEST_COMPILER := $(shell which clang) | 
| giuliomoro@302 | 73   ifneq ($(strip $(TEST_COMPILER)), ) | 
| giuliomoro@385 | 74     #if it is installed, use it | 
| giuliomoro@302 | 75     COMPILER := clang | 
| giuliomoro@302 | 76   else | 
| giuliomoro@241 | 77     COMPILER := gcc | 
| giuliomoro@302 | 78   endif | 
| giuliomoro@241 | 79 endif | 
| giuliomoro@241 | 80 | 
| giuliomoro@241 | 81 ifeq ($(COMPILER), clang) | 
| giuliomoro@306 | 82   CC=clang | 
| giuliomoro@306 | 83   CXX=clang++ | 
| giuliomoro@302 | 84   CPP_FLAGS += -DNDEBUG | 
| giuliomoro@302 | 85   C_FLAGS += -DNDEBUG | 
| giuliomoro@241 | 86 else | 
| giuliomoro@241 | 87   CC=gcc | 
| giuliomoro@241 | 88   CXX=g++ | 
| giuliomoro@241 | 89   CPP_FLAGS += --fast-math | 
| giuliomoro@241 | 90   C_FLAGS += --fast-math | 
| giuliomoro@241 | 91 endif | 
| giuliomoro@241 | 92 | 
| l@260 | 93 INCLUDES := -I$(PROJECT_DIR) -I./include -I/usr/include/ne10 -I/usr/xenomai/include -I/usr/arm-linux-gnueabihf/include/xenomai/include -I/usr/arm-linux-gnueabihf/include/ne10 | 
| andrewm@68 | 94 | 
| l@260 | 95 ASM_SRCS := $(wildcard $(PROJECT_DIR)/*.S) | 
| l@260 | 96 ASM_OBJS := $(addprefix $(PROJECT_DIR)/build/,$(notdir $(ASM_SRCS:.S=.o))) | 
| l@260 | 97 ASM_DEPS := $(addprefix $(PROJECT_DIR)/build/,$(notdir $(ASM_SRCS:.S=.d))) | 
| giuliomoro@64 | 98 | 
| l@260 | 99 C_SRCS := $(wildcard $(PROJECT_DIR)/*.c) | 
| l@260 | 100 C_OBJS := $(addprefix $(PROJECT_DIR)/build/,$(notdir $(C_SRCS:.c=.o))) | 
| l@260 | 101 C_DEPS := $(addprefix $(PROJECT_DIR)/build/,$(notdir $(C_SRCS:.c=.d))) | 
| giuliomoro@64 | 102 | 
| l@260 | 103 CPP_SRCS := $(wildcard $(PROJECT_DIR)/*.cpp) | 
| l@260 | 104 CPP_OBJS := $(addprefix $(PROJECT_DIR)/build/,$(notdir $(CPP_SRCS:.cpp=.o))) | 
| l@260 | 105 CPP_DEPS := $(addprefix $(PROJECT_DIR)/build/,$(notdir $(CPP_SRCS:.cpp=.d))) | 
| giuliomoro@64 | 106 | 
| giuliomoro@383 | 107 PROJECT_OBJS = $(ASM_OBJS) $(C_OBJS) $(CPP_OBJS) | 
| giuliomoro@383 | 108 | 
| giuliomoro@301 | 109 # Core Bela sources | 
| giuliomoro@186 | 110 CORE_CPP_SRCS = $(filter-out core/default_main.cpp, $(wildcard core/*.cpp)) | 
| giuliomoro@186 | 111 CORE_OBJS := $(addprefix build/core/,$(notdir $(CORE_CPP_SRCS:.cpp=.o))) | 
| giuliomoro@186 | 112 CORE_CPP_DEPS := $(addprefix build/core/,$(notdir $(CORE_CPP_SRCS:.cpp=.d))) | 
| giuliomoro@64 | 113 | 
| andrewm@318 | 114 CORE_ASM_SRCS := $(wildcard core/*.S) | 
| andrewm@318 | 115 CORE_ASM_OBJS := $(addprefix build/core/,$(notdir $(CORE_ASM_SRCS:.S=.o))) | 
| andrewm@318 | 116 CORE_ASM_DEPS := $(addprefix build/core/,$(notdir $(CORE_ASM_SRCS:.S=.d))) | 
| andrewm@318 | 117 | 
| andrewm@318 | 118 | 
| giuliomoro@64 | 119 # Objects for a system-supplied default main() file, if the user | 
| giuliomoro@64 | 120 # only wants to provide the render functions. | 
| giuliomoro@64 | 121 DEFAULT_MAIN_CPP_SRCS := ./core/default_main.cpp | 
| giuliomoro@64 | 122 DEFAULT_MAIN_OBJS := ./build/core/default_main.o | 
| giuliomoro@64 | 123 DEFAULT_MAIN_CPP_DEPS := ./build/core/default_main.d | 
| andrewm@68 | 124 | 
| giuliomoro@334 | 125 Bela: ## Builds the Bela program with all the opimizations | 
| giuliomoro@334 | 126 Bela: $(OUTPUT_FILE) | 
| giuliomoro@334 | 127 | 
| giuliomoro@301 | 128 # all = build Bela | 
| giuliomoro@334 | 129 all: ## Same as Bela | 
| andrewm@69 | 130 all: SYNTAX_FLAG := | 
| giuliomoro@301 | 131 all: Bela | 
| andrewm@68 | 132 | 
| giuliomoro@301 | 133 # debug = buildBela debug | 
| giuliomoro@334 | 134 debug: ## Same as Bela but with debug flags and no optimizations | 
| giuliomoro@209 | 135 debug: CPP_FLAGS=-g | 
| giuliomoro@209 | 136 debug: C_FLAGS=-g | 
| giuliomoro@209 | 137 debug: all | 
| giuliomoro@209 | 138 | 
| andrewm@69 | 139 # syntax = check syntax | 
| giuliomoro@334 | 140 syntax: ## Only checks syntax | 
| andrewm@69 | 141 syntax: SYNTAX_FLAG := -fsyntax-only | 
| l@260 | 142 syntax: SYNTAX | 
| andrewm@69 | 143 | 
| giuliomoro@301 | 144 # Rule for Bela core C++ files | 
| giuliomoro@64 | 145 build/core/%.o: ./core/%.cpp | 
| l@260 | 146 	@echo 'Building $(notdir $<)...' | 
| giuliomoro@386 | 147 #	@echo 'Invoking: C++ Compiler $(CXX)' | 
| l@260 | 148 	@$(CXX) $(SYNTAX_FLAG) $(INCLUDES) $(CPP_FLAGS) -Wall -c -fmessage-length=0 -U_FORTIFY_SOURCE -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" | 
| l@260 | 149 	@echo ' ...done' | 
| giuliomoro@64 | 150 	@echo ' ' | 
| andrewm@68 | 151 | 
| andrewm@318 | 152 # Rule for Bela core ASM files | 
| andrewm@318 | 153 build/core/%.o: ./core/%.S | 
| andrewm@318 | 154 	@echo 'Building $(notdir $<)...' | 
| andrewm@318 | 155 #	@echo 'Invoking: GCC Assembler' | 
| andrewm@318 | 156 	@as  -o "$@" "$<" | 
| andrewm@318 | 157 	@echo ' ...done' | 
| andrewm@318 | 158 	@echo ' ' | 
| andrewm@318 | 159 | 
| giuliomoro@64 | 160 # Rule for user-supplied C++ files | 
| l@260 | 161 $(PROJECT_DIR)/build/%.o: $(PROJECT_DIR)/%.cpp | 
| l@260 | 162 	@echo 'Building $(notdir $<)...' | 
| l@389 | 163 #	@echo 'Invoking: C++ Compiler $(CXX)' | 
| l@260 | 164 	@$(CXX) $(SYNTAX_FLAG) $(INCLUDES) $(CPP_FLAGS) -Wall -c -fmessage-length=0 -U_FORTIFY_SOURCE -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" | 
| l@260 | 165 	@echo ' ...done' | 
| giuliomoro@64 | 166 	@echo ' ' | 
| andrewm@68 | 167 | 
| giuliomoro@64 | 168 # Rule for user-supplied C files | 
| l@260 | 169 $(PROJECT_DIR)/build/%.o: $(PROJECT_DIR)/%.c | 
| l@260 | 170 	@echo 'Building $(notdir $<)...' | 
| giuliomoro@386 | 171 #	@echo 'Invoking: C Compiler $(CC)' | 
| giuliomoro@287 | 172 	$(CC) $(SYNTAX_FLAG) $(INCLUDES) $(C_FLAGS) -Wall -c -fmessage-length=0 -U_FORTIFY_SOURCE -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" -std=c99 | 
| l@260 | 173 	@echo ' ...done' | 
| giuliomoro@64 | 174 	@echo ' ' | 
| andrewm@68 | 175 | 
| giuliomoro@64 | 176 # Rule for user-supplied assembly files | 
| l@260 | 177 $(PROJECT_DIR)/build/%.o: $(PROJECT_DIR)/%.S | 
| l@260 | 178 	@echo 'Building $(notdir $<)...' | 
| l@260 | 179 #	@echo 'Invoking: GCC Assembler' | 
| l@260 | 180 	@as  -o "$@" "$<" | 
| l@260 | 181 	@echo ' ...done' | 
| giuliomoro@64 | 182 	@echo ' ' | 
| giuliomoro@64 | 183 | 
| giuliomoro@64 | 184 # This is a nasty kludge: we want to be able to optionally link in a default | 
| giuliomoro@64 | 185 # main file if the user hasn't supplied one. We check for the presence of the main() | 
| giuliomoro@64 | 186 # function, and conditionally call one of two recursive make targets depending on whether | 
| giuliomoro@64 | 187 # we want to link in the default main file or not. The kludge is the mess of a shell script | 
| giuliomoro@64 | 188 # line below. Surely there's a better way to do this? | 
| giuliomoro@383 | 189 $(OUTPUT_FILE): $(CORE_ASM_OBJS) $(CORE_OBJS) $(PROJECT_OBJS) $(STATIC_LIBS) $(DEFAULT_MAIN_OBJS) | 
| giuliomoro@383 | 190 	$(eval DEFAULT_MAIN_CONDITIONAL := $(shell bash -c 'if [ `nm $(PROJECT_OBJS) | grep -w T | grep -w main | wc -l` == '0' ]; then echo "$(DEFAULT_MAIN_OBJS)"; else echo ""; fi')) | 
| l@387 | 191 	@echo 'Linking...' | 
| andrewm@318 | 192 	@$(CXX) $(SYNTAX_FLAG) -L/usr/xenomai/lib -L/usr/arm-linux-gnueabihf/lib -L/usr/arm-linux-gnueabihf/lib/xenomai -L/usr/lib/arm-linux-gnueabihf -pthread -Wpointer-arith -o "$(PROJECT_DIR)/$(PROJECT)" $(CORE_ASM_OBJS) $(CORE_OBJS) $(DEFAULT_MAIN_CONDITIONAL) $(ASM_OBJS) $(C_OBJS) $(CPP_OBJS) $(STATIC_LIBS) $(LIBS) | 
| l@387 | 193 	@echo ' ...done' | 
| l@387 | 194 | 
| l@260 | 195 # Other Targets: | 
| l@260 | 196 # This rule compiles c and c++ source files without output or linking | 
| l@260 | 197 SYNTAX: $(C_OBJS) $(CPP_OBJS) | 
| giuliomoro@64 | 198 | 
| giuliomoro@385 | 199 projectclean:## Remove the project's build objects & binary | 
| giuliomoro@326 | 200 	-$(RM) $(PROJECT_DIR)/build/* $(OUTPUT_FILE) | 
| giuliomoro@64 | 201 	-@echo ' ' | 
| giuliomoro@64 | 202 | 
| giuliomoro@386 | 203 clean: ## Same as projectclean | 
| giuliomoro@386 | 204 clean: projectclean | 
| giuliomoro@386 | 205 | 
| giuliomoro@386 | 206 coreclean: ## Remove the core's build objects | 
| giuliomoro@386 | 207 	-$(RM) build/* | 
| giuliomoro@386 | 208 | 
| giuliomoro@386 | 209 prompt: | 
| giuliomoro@386 | 210 	@printf "Warning: you are about to DELETE the projects/ folder and its content. This operation cannot be undone. Continue? (y/N) " | 
| giuliomoro@386 | 211 	@read REPLY; if [ $$REPLY !=  y ] && [ $$REPLY != Y ]; then echo "Aborting..."; exit 1; fi | 
| giuliomoro@386 | 212 | 
| giuliomoro@386 | 213 distclean: ## Restores the Bela folder to a pristine state: remove all the projects source and the built objects, including the core Bela objects. | 
| giuliomoro@386 | 214 distclean: prompt distcleannoprompt | 
| giuliomoro@386 | 215 | 
| giuliomoro@386 | 216 distcleannoprompt: ## Same as distclean, but does not prompt for confirmation. Use with care. | 
| giuliomoro@326 | 217 	-$(RM) build/source/* $(CORE_OBJS) $(CORE_CPP_DEPS) $(DEFAULT_MAIN_OBJS) $(DEFAULT_MAIN_CPP_DEPS) $(OUTPUT_FILE) | 
| giuliomoro@64 | 218 	-@echo ' ' | 
| giuliomoro@64 | 219 | 
| giuliomoro@302 | 220 runfg: run | 
| giuliomoro@334 | 221 run: ## Run PROJECT in the foreground | 
| giuliomoro@326 | 222 run: stop Bela | 
| giuliomoro@327 | 223 	@echo "Running $(RUN_COMMAND)" | 
| l@387 | 224 	@cd $(PROJECT_DIR) && sync& $(RUN_COMMAND) | 
| l@387 | 225 runide: ## Run PROJECT for IDE (foreground, without stop or build, suppressed output, no buffering) | 
| l@387 | 226 runide: Bela | 
| l@387 | 227 	@cd $(PROJECT_DIR) && sync& $(RUN_IDE_COMMAND) | 
| giuliomoro@334 | 228 runscreen: ## Run PROJECT in the background (detached screen) | 
| giuliomoro@302 | 229 runscreen: stop $(OUTPUT_FILE) | 
| giuliomoro@327 | 230 	@echo "Running $(RUN_COMMAND) in a screen" | 
| giuliomoro@327 | 231 	@cd $(PROJECT_DIR) && screen -S $(SCREEN_NAME) -d -m $(RUN_COMMAND) | 
| giuliomoro@334 | 232 runscreenfg: ## Run PROJECT in a screen in the foreground (can detach with ctrl-a ctrl-d) | 
| giuliomoro@313 | 233 runscreenfg: stop $(OUTPUT_FILE) | 
| giuliomoro@327 | 234 	@echo "Running $(RUN_COMMAND) in a screen" | 
| giuliomoro@327 | 235 	@cd $(PROJECT_DIR) && screen -S $(SCREEN_NAME) -m $(RUN_COMMAND) | 
| giuliomoro@313 | 236 FIFO_NAME=/tmp/belafifo | 
| giuliomoro@334 | 237 runscreenfifo: ## Same as runscreen, but stdout and stderr are piped to the foreground through a fifo | 
| giuliomoro@313 | 238 runscreenfifo: stop $(OUTPUT_FILE) | 
| giuliomoro@313 | 239 	@echo "Running $(RUN_COMMAND), piping output to $(FIFO_NAME)" | 
| giuliomoro@313 | 240 	@rm -rf $(FIFO_NAME) | 
| giuliomoro@313 | 241 	@mkfifo $(FIFO_NAME) | 
| giuliomoro@327 | 242 	@cd $(PROJECT_DIR) | 
| giuliomoro@315 | 243 	@screen -S $(SCREEN_NAME) -d -m stdbuf -e 0 -i 0 -o 0 bash -c "$(RUN_COMMAND) &>  $(FIFO_NAME)" | 
| giuliomoro@315 | 244 	@cat /tmp/belafifo | 
| giuliomoro@302 | 245 | 
| giuliomoro@331 | 246 STARTUP_COMMAND=printf "\#!/bin/sh\n\#\n\# This file is autogenerated by Bela. Do not edit!\n\necho Running Bela...\nscreen -S $(SCREEN_NAME) -d -m %s $(RUN_COMMAND) %s\n" | 
| giuliomoro@334 | 247 nostartup: ## No Bela project runs at startup | 
| giuliomoro@331 | 248 nostartup: | 
| andrewm@391 | 249 	@echo "Disabling Bela at startup..." | 
| giuliomoro@344 | 250 	@printf "#!/bin/sh\n#\n\n# This file is autogenerated by Bela. Do not edit!\n\n# Run on startup disabled -- nothing to do here\n" > $(BELA_STARTUP_SCRIPT) | 
| giuliomoro@331 | 251 | 
| giuliomoro@334 | 252 startuploop: ## Makes PROJECT run at startup and restarts it if it crashes | 
| giuliomoro@331 | 253 startuploop: Bela | 
| giuliomoro@331 | 254 	@echo "Enabling Bela at startup in a loop..." | 
| giuliomoro@331 | 255 	@$(STARTUP_COMMAND) 'bash -c "while sleep 0.5 ; do echo Running Bela...;' '; done"' > $(BELA_STARTUP_SCRIPT) | 
| giuliomoro@331 | 256 | 
| giuliomoro@334 | 257 startup: ## Makes PROJECT run at startup | 
| giuliomoro@331 | 258 startup: Bela | 
| giuliomoro@331 | 259 	@echo "Enabling Bela at startup..." | 
| giuliomoro@331 | 260 	@$(STARTUP_COMMAND) > $(BELA_STARTUP_SCRIPT) | 
| giuliomoro@331 | 261 | 
| giuliomoro@334 | 262 stop: ## Stops any Bela program that is currently running | 
| giuliomoro@302 | 263 stop: | 
| giuliomoro@302 | 264 	@PID=`grep $(BELA_AUDIO_THREAD_NAME) /proc/xenomai/stat | cut -d " " -f 5 | sed s/\s//g`; if [ -z $$PID ]; then echo "No process to kill"; else echo "Killing old Bela process $$PID"; kill -2 $$PID; fi; screen -X -S $(SCREEN_NAME) quit > /dev/null; exit 0; | 
| giuliomoro@64 | 265 | 
| giuliomoro@386 | 266 .PHONY: all clean distclean help projectclean nostartup startup startuploop debug run runfg runscreen runscreenfg runscreenfifo stop |