# # Top level Makefile for the OpenPilot project build system. # Copyright (c) 2010-2013, The OpenPilot Team, http://www.openpilot.org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # This top level Makefile passes down some variables to sub-makes through # the environment. They are explicitly exported using the export keyword. # Lower level makefiles assume that these variables are defined. To ensure # that a special magic variable is exported here. It must be checked for # existance by each sub-make. export OPENPILOT_IS_COOL := Fuck Yeah! # Set up a default goal .DEFAULT_GOAL := help # Set up some macros for common directories within the tree export ROOT_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) export TOOLS_DIR := $(ROOT_DIR)/tools export BUILD_DIR := $(ROOT_DIR)/build export DL_DIR := $(ROOT_DIR)/downloads # Set up default build configurations (debug | release) UAVOGEN_BUILD_CONF ?= debug GCS_BUILD_CONF ?= debug ANDROIDGCS_BUILD_CONF ?= debug GOOGLE_API_VERSION ?= 14 # Function for converting an absolute path to one relative # to the top of the source tree. toprel = $(subst $(realpath $(ROOT_DIR))/,,$(abspath $(1))) # Clean out undesirable variables from the environment and command-line # to remove the chance that they will cause problems with our build define SANITIZE_VAR $(if $(filter-out undefined,$(origin $(1))), $(info *NOTE* Sanitized $(2) variable '$(1)' from $(origin $(1))) MAKEOVERRIDES = $(filter-out $(1)=%,$(MAKEOVERRIDES)) override $(1) := unexport $(1) ) endef # These specific variables can influence gcc in unexpected (and undesirable) ways SANITIZE_GCC_VARS := TMPDIR GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH SANITIZE_GCC_VARS += CFLAGS CPATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH OBJC_INCLUDE_PATH DEPENDENCIES_OUTPUT $(foreach var, $(SANITIZE_GCC_VARS), $(eval $(call SANITIZE_VAR,$(var),disallowed))) # These specific variables used to be valid but now they make no sense SANITIZE_DEPRECATED_VARS := USE_BOOTLOADER $(foreach var, $(SANITIZE_DEPRECATED_VARS), $(eval $(call SANITIZE_VAR,$(var),deprecated))) # Make sure this isn't being run as root (no whoami on Windows, but that is ok here) ifeq ($(shell whoami 2>/dev/null),root) $(error You should not be running this as root) endif # Decide on a verbosity level based on the V= parameter export AT := @ ifndef V export V0 := export V1 := $(AT) else ifeq ($(V), 0) export V0 := $(AT) export V1 := $(AT) else ifeq ($(V), 1) endif # Make sure we know few things about the architecture before including # the tools.mk to ensure that we download/install the right tools. UNAME := $(shell uname) ARCH := $(shell uname -m) # Here and everywhere if not Linux or OSX then assume Windows ifeq ($(filter Linux Darwin, $(UNAME)), ) UNAME := Windows endif # Set up misc host tools export ECHO := echo export MKDIR := mkdir export RM := rm export LN := ln export CAT := cat export SED := sed export TAR := tar export ANT := ant export JAVAC := javac export JAR := jar export GIT := git export PYTHON := python export INSTALL := install # version-info cmd to extract some repository data export VERSION_INFO := $(PYTHON) "$(ROOT_DIR)/make/scripts/version-info.py" --path="$(ROOT_DIR)" # Test if quotes are needed for the echo-command ifeq (${shell $(ECHO) "test"}, test) export QUOTE := ' # This line is just to clear out the single quote above ' else export QUOTE := endif # The tools.mk uses wget to fetch tarballs or packages ifeq ($(shell [ -x "$(TOOLS_DIR)/bin/wget" ] && $(ECHO) "exists"), exists) WGET := $(TOOLS_DIR)/bin/wget else # not installed, hope it's in the path... WGET ?= wget endif # Include tools installers include $(ROOT_DIR)/make/tools.mk # Set up paths to tools ifeq ($(shell [ -d "$(QT_SDK_DIR)" ] && $(ECHO) "exists"), exists) QMAKE := $(QT_SDK_QMAKE_PATH) else # not installed, hope it's in the path... QMAKE ?= qmake endif ifeq ($(shell [ -d "$(ARM_SDK_DIR)" ] && $(ECHO) "exists"), exists) export ARM_SDK_PREFIX := $(ARM_SDK_DIR)/bin/arm-none-eabi- else # not installed, hope it's in the path... export ARM_SDK_PREFIX ?= arm-none-eabi- endif ifeq ($(shell [ -d "$(OPENOCD_DIR)" ] && $(ECHO) "exists"), exists) export OPENOCD := $(OPENOCD_DIR)/bin/openocd else # not installed, hope it's in the path... export OPENOCD ?= openocd endif ifeq ($(shell [ -d "$(ANDROID_SDK_DIR)" ] && $(ECHO) "exists"), exists) ANDROID := $(ANDROID_SDK_DIR)/tools/android ANDROID_DX := $(ANDROID_SDK_DIR)/platform-tools/dx else # not installed, hope it's in the path... ANDROID ?= android ANDROID_DX ?= dx endif # We almost need to consider autoconf/automake instead of this ifeq ($(UNAME), Linux) QT_SPEC = linux-g++ UAVOBJGENERATOR = "$(BUILD_DIR)/ground/uavobjgenerator/uavobjgenerator" else ifeq ($(UNAME), Darwin) QT_SPEC = macx-g++ UAVOBJGENERATOR = "$(BUILD_DIR)/ground/uavobjgenerator/uavobjgenerator" else QT_SPEC = win32-g++ UAVOBJGENERATOR = "$(BUILD_DIR)/ground/uavobjgenerator/$(UAVOGEN_BUILD_CONF)/uavobjgenerator.exe" endif ############################## # # All targets # ############################## .PHONY: all all: uavobjects all_ground all_flight .PHONY: all_clean all_clean: [ ! -d "$(BUILD_DIR)" ] || $(RM) -rf "$(BUILD_DIR)" $(DL_DIR): $(MKDIR) -p $@ $(TOOLS_DIR): $(MKDIR) -p $@ $(BUILD_DIR): $(MKDIR) -p $@ ############################## # # UAVObjects # ############################## ifeq ($(V), 1) UAVOGEN_SILENT := else UAVOGEN_SILENT := silent endif .PHONY: uavobjgenerator uavobjgenerator: $(V1) $(MKDIR) -p $(BUILD_DIR)/ground/$@ $(V1) ( cd $(BUILD_DIR)/ground/$@ && \ $(QMAKE) $(ROOT_DIR)/ground/uavobjgenerator/uavobjgenerator.pro -spec $(QT_SPEC) -r CONFIG+="$(UAVOGEN_BUILD_CONF) $(UAVOGEN_SILENT)" && \ $(MAKE) --no-print-directory -w ; \ ) UAVOBJ_TARGETS := gcs flight python matlab java wireshark .PHONY: uavobjects uavobjects: $(addprefix uavobjects_, $(UAVOBJ_TARGETS)) UAVOBJ_XML_DIR := $(ROOT_DIR)/shared/uavobjectdefinition UAVOBJ_OUT_DIR := $(BUILD_DIR)/uavobject-synthetics $(UAVOBJ_OUT_DIR): $(V1) $(MKDIR) -p $@ uavobjects_%: $(UAVOBJ_OUT_DIR) uavobjgenerator $(V1) ( cd $(UAVOBJ_OUT_DIR) && \ $(UAVOBJGENERATOR) -$* $(UAVOBJ_XML_DIR) $(ROOT_DIR) ; \ ) uavobjects_test: $(UAVOBJ_OUT_DIR) uavobjgenerator $(V1) $(UAVOBJGENERATOR) -v -none $(UAVOBJ_XML_DIR) $(ROOT_DIR) uavobjects_clean: $(V0) @$(ECHO) " CLEAN $@" $(V1) [ ! -d "$(UAVOBJ_OUT_DIR)" ] || $(RM) -r "$(UAVOBJ_OUT_DIR)" ############################## # # GCS related components # ############################## .PHONY: all_ground all_ground: openpilotgcs # Convenience target for the GCS .PHONY: gcs gcs_clean gcs: openpilotgcs gcs_clean: openpilotgcs_clean ifeq ($(V), 1) GCS_SILENT := else GCS_SILENT := silent endif .PHONY: openpilotgcs openpilotgcs: uavobjects_gcs $(V1) $(MKDIR) -p $(BUILD_DIR)/ground/$@ $(V1) ( cd $(BUILD_DIR)/ground/$@ && \ $(QMAKE) $(ROOT_DIR)/ground/openpilotgcs/openpilotgcs.pro -spec $(QT_SPEC) -r CONFIG+="$(GCS_BUILD_CONF) $(GCS_SILENT)" $(GCS_QMAKE_OPTS) && \ $(MAKE) -w ; \ ) .PHONY: openpilotgcs_clean openpilotgcs_clean: $(V0) @$(ECHO) " CLEAN $@" $(V1) [ ! -d "$(BUILD_DIR)/ground/openpilotgcs" ] || $(RM) -r "$(BUILD_DIR)/ground/openpilotgcs" ################################ # # Android GCS related components # ################################ # Build the output directory for the Android GCS build ANDROIDGCS_OUT_DIR := $(BUILD_DIR)/androidgcs $(ANDROIDGCS_OUT_DIR): $(V1) $(MKDIR) -p $@ # Build the asset directory for the android assets ANDROIDGCS_ASSETS_DIR := $(ANDROIDGCS_OUT_DIR)/assets $(ANDROIDGCS_ASSETS_DIR)/uavos: $(V1) $(MKDIR) -p $@ ifeq ($(V), 1) ANT_QUIET := ANDROID_SILENT := else ANT_QUIET := -q ANDROID_SILENT := -s endif .PHONY: androidgcs androidgcs: uavo-collections_java $(V0) @$(ECHO) " ANDROID $(call toprel, $(ANDROIDGCS_OUT_DIR))" $(V1) $(MKDIR) -p $(ANDROIDGCS_OUT_DIR) $(V1) $(ANDROID) $(ANDROID_SILENT) update project \ --target "Google Inc.:Google APIs:$(GOOGLE_API_VERSION)" \ --name androidgcs \ --path ./androidgcs $(V1) $(ANT) -f ./androidgcs/build.xml \ $(ANT_QUIET) \ -Dout.dir="../$(call toprel, $(ANDROIDGCS_OUT_DIR)/bin)" \ -Dgen.absolute.dir="$(ANDROIDGCS_OUT_DIR)/gen" \ $(ANDROIDGCS_BUILD_CONF) .PHONY: androidgcs_clean androidgcs_clean: $(V0) @$(ECHO) " CLEAN $@" $(V1) [ ! -d "$(ANDROIDGCS_OUT_DIR)" ] || $(RM) -r "$(ANDROIDGCS_OUT_DIR)" # We want to take snapshots of the UAVOs at each point that they change # to allow the GCS to be compatible with as many versions as possible. # We always include a pseudo collection called "srctree" which represents # the UAVOs in the source tree. So not necessary to add current tree UAVO # hash here, it is always included. # Find the git hashes of each commit that changes uavobjects with: # git log --format=%h -- shared/uavobjectdefinition/ | head -n 2 # List only UAVO hashes of past releases, do not list current hash. UAVO_GIT_VERSIONS := 5e14f53 # All versions includes also the current source tree UAVO hash UAVO_ALL_VERSIONS := $(UAVO_GIT_VERSIONS) srctree # This is where the UAVO collections are stored UAVO_COLLECTION_DIR := $(BUILD_DIR)/uavo-collections # $(1) git hash of a UAVO snapshot define UAVO_COLLECTION_GIT_TEMPLATE # Make the output directory that will contain all of the synthetics for the # uavo collection referenced by the git hash $(1) $$(UAVO_COLLECTION_DIR)/$(1): $$(V1) $(MKDIR) -p $$(UAVO_COLLECTION_DIR)/$(1) # Extract the snapshot of shared/uavobjectdefinition from git hash $(1) $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar: | $$(UAVO_COLLECTION_DIR)/$(1) $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar: $$(V0) @$(ECHO) " UAVOTAR $(1)" $$(V1) $(GIT) archive $(1) -o $$@ -- shared/uavobjectdefinition/ # Extract the uavo xml files from our snapshot $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml: $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml.tar $$(V0) @$(ECHO) " UAVOUNTAR $(1)" $$(V1) $(RM) -rf $$@ $$(V1) $(MKDIR) -p $$@ $$(V1) $(TAR) -C $$(call toprel, $$@) -xf $$(call toprel, $$<) || $(RM) -rf $$@ endef # Map the current working directory into the set of UAVO collections $(UAVO_COLLECTION_DIR)/srctree: $(V1) $(MKDIR) -p $@ $(UAVO_COLLECTION_DIR)/srctree/uavo-xml: | $(UAVO_COLLECTION_DIR)/srctree $(UAVO_COLLECTION_DIR)/srctree/uavo-xml: $(UAVOBJ_XML_DIR) $(V1) $(LN) -sf $(ROOT_DIR) $(UAVO_COLLECTION_DIR)/srctree/uavo-xml # $(1) git hash (or symbolic name) of a UAVO snapshot define UAVO_COLLECTION_BUILD_TEMPLATE # This leaves us with a (broken) symlink that points to the full sha1sum of the collection $$(UAVO_COLLECTION_DIR)/$(1)/uavohash: $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml # Compute the sha1 hash for this UAVO collection # The sed bit truncates the UAVO hash to 16 hex digits $$(V1) $$(VERSION_INFO) \ --uavodir=$$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml/shared/uavobjectdefinition \ --format='$$$${UAVOSHA1TXT}' | \ $(SED) -e 's|\(................\).*|\1|' > $$@ $$(V0) @$(ECHO) " UAVOHASH $(1) ->" $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash) # Generate the java uavobjects for this UAVO collection $$(UAVO_COLLECTION_DIR)/$(1)/java-build/java: $$(UAVO_COLLECTION_DIR)/$(1)/uavohash $$(V0) @$(ECHO) " UAVOJAVA $(1) " $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash) $$(V1) $(MKDIR) -p $$@ $$(V1) ( \ cd $$(UAVO_COLLECTION_DIR)/$(1)/java-build && \ $$(UAVOBJGENERATOR) -java $$(UAVO_COLLECTION_DIR)/$(1)/uavo-xml/shared/uavobjectdefinition $$(ROOT_DIR) ; \ ) # Build a jar file for this UAVO collection $$(UAVO_COLLECTION_DIR)/$(1)/java-build/uavobjects.jar: | $$(ANDROIDGCS_ASSETS_DIR)/uavos $$(UAVO_COLLECTION_DIR)/$(1)/java-build/uavobjects.jar: $$(UAVO_COLLECTION_DIR)/$(1)/java-build/java $$(V0) @$(ECHO) " UAVOJAR $(1) " $$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash) $$(V1) ( \ HASH=$$$$(cat $$(UAVO_COLLECTION_DIR)/$(1)/uavohash) && \ cd $$(UAVO_COLLECTION_DIR)/$(1)/java-build && \ $(JAVAC) java/*.java \ $$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVDataObject.java \ $$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVObject*.java \ $$(ROOT_DIR)/androidgcs/src/org/openpilot/uavtalk/UAVMetaObject.java \ -d . && \ find ./org/openpilot/uavtalk/uavobjects -type f -name '*.class' > classlist.txt && \ $(JAR) cf tmp_uavobjects.jar @classlist.txt && \ $$(ANDROID_DX) \ --dex \ --output $$(ANDROIDGCS_ASSETS_DIR)/uavos/$$$${HASH}.jar \ tmp_uavobjects.jar && \ $(LN) -sf $$(ANDROIDGCS_ASSETS_DIR)/uavos/$$$${HASH}.jar uavobjects.jar \ ) endef # One of these for each element of UAVO_GIT_VERSIONS so we can extract the UAVOs from git $(foreach githash, $(UAVO_GIT_VERSIONS), $(eval $(call UAVO_COLLECTION_GIT_TEMPLATE,$(githash)))) # One of these for each UAVO_ALL_VERSIONS which includes the ones in the srctree $(foreach githash, $(UAVO_ALL_VERSIONS), $(eval $(call UAVO_COLLECTION_BUILD_TEMPLATE,$(githash)))) .PHONY: uavo-collections_java uavo-collections_java: $(foreach githash, $(UAVO_ALL_VERSIONS), $(UAVO_COLLECTION_DIR)/$(githash)/java-build/uavobjects.jar) .PHONY: uavo-collections uavo-collections: uavo-collections_java .PHONY: uavo-collections_clean uavo-collections_clean: $(V0) @$(ECHO) " CLEAN $(UAVO_COLLECTION_DIR)" $(V1) [ ! -d "$(UAVO_COLLECTION_DIR)" ] || $(RM) -r $(UAVO_COLLECTION_DIR) ############################## # # Flight related components # ############################## # Define some pointers to the various important pieces of the flight code # to prevent these being repeated in every sub makefile export PIOS := $(ROOT_DIR)/flight/PiOS export FLIGHTLIB := $(ROOT_DIR)/flight/Libraries export OPMODULEDIR := $(ROOT_DIR)/flight/Modules export OPUAVOBJ := $(ROOT_DIR)/flight/targets/UAVObjects export OPUAVTALK := $(ROOT_DIR)/flight/targets/UAVTalk export HWDEFS := $(ROOT_DIR)/flight/targets/board_hw_defs export DOXYGENDIR := $(ROOT_DIR)/flight/Doc/Doxygen export OPUAVSYNTHDIR := $(BUILD_DIR)/uavobject-synthetics/flight # $(1) = Canonical board name all in lower case (e.g. coptercontrol) # $(2) = Name of board used in source tree (e.g. CopterControl) # $(3) = Short name for board (e.g CC) define FW_TEMPLATE .PHONY: $(1) fw_$(1) $(1): fw_$(1)_opfw fw_$(1): fw_$(1)_opfw fw_$(1)_%: uavobjects_flight $(V1) $(MKDIR) -p $(BUILD_DIR)/fw_$(1)/dep $(V1) cd $(ROOT_DIR)/flight/targets/$(2) && \ $$(MAKE) -r --no-print-directory \ BOARD_NAME=$(1) \ BOARD_SHORT_NAME=$(3) \ BUILD_TYPE=fw \ HWDEFSINC=$(HWDEFS)/$(1) \ TOPDIR=$(ROOT_DIR)/flight/targets/$(2) \ OUTDIR=$(BUILD_DIR)/fw_$(1) \ TARGET=fw_$(1) \ $$* .PHONY: $(1)_clean $(1)_clean: fw_$(1)_clean fw_$(1)_clean: $(V0) @$(ECHO) " CLEAN $$@" $(V1) $(RM) -fr $(BUILD_DIR)/fw_$(1) endef # $(1) = Canonical board name all in lower case (e.g. coptercontrol) # $(2) = Name of board used in source tree (e.g. CopterControl) define BL_TEMPLATE .PHONY: bl_$(1) bl_$(1): bl_$(1)_bin bl_$(1)_bino: bl_$(1)_bin bl_$(1)_%: $(V1) $(MKDIR) -p $(BUILD_DIR)/bl_$(1)/dep $(V1) cd $(ROOT_DIR)/flight/targets/Bootloaders/$(2) && \ $$(MAKE) -r --no-print-directory \ BOARD_NAME=$(1) \ BOARD_SHORT_NAME=$(3) \ BUILD_TYPE=bl \ HWDEFSINC=$(HWDEFS)/$(1) \ TOPDIR=$(ROOT_DIR)/flight/targets/Bootloaders/$(2) \ OUTDIR=$(BUILD_DIR)/bl_$(1) \ TARGET=bl_$(1) \ $$* .PHONY: unbrick_$(1) unbrick_$(1): bl_$(1)_hex $(if $(filter-out undefined,$(origin UNBRICK_TTY)), $(V0) @$(ECHO) " UNBRICK $(1) via $$(UNBRICK_TTY)" $(V1) $(STM32FLASH_DIR)/stm32flash \ -w $(BUILD_DIR)/bl_$(1)/bl_$(1).hex \ -g 0x0 \ $$(UNBRICK_TTY) , $(V0) @$(ECHO) $(V0) @$(ECHO) "ERROR: You must specify UNBRICK_TTY= to use for unbricking." $(V0) @$(ECHO) " eg. $$(MAKE) $$@ UNBRICK_TTY=/dev/ttyUSB0" ) .PHONY: bl_$(1)_clean bl_$(1)_clean: $(V0) @$(ECHO) " CLEAN $$@" $(V1) $(RM) -fr $(BUILD_DIR)/bl_$(1) endef # $(1) = Canonical board name all in lower case (e.g. coptercontrol) define BU_TEMPLATE .PHONY: bu_$(1) bu_$(1): bu_$(1)_opfw bu_$(1)_%: bl_$(1)_bino $(V1) $(MKDIR) -p $(BUILD_DIR)/bu_$(1)/dep $(V1) cd $(ROOT_DIR)/flight/targets/Bootloaders/BootloaderUpdater && \ $$(MAKE) -r --no-print-directory \ BOARD_NAME=$(1) \ BOARD_SHORT_NAME=$(3) \ BUILD_TYPE=bu \ TCHAIN_PREFIX="$(ARM_SDK_PREFIX)" \ REMOVE_CMD="$(RM)" OOCD_EXE="$(OPENOCD)" \ \ TARGET=bu_$(1) \ OUTDIR=$(BUILD_DIR)/bu_$(1) \ \ PIOS=$(PIOS) \ FLIGHTLIB=$(FLIGHTLIB) \ OPMODULEDIR=$(OPMODULEDIR) \ OPUAVOBJ=$(OPUAVOBJ) \ OPUAVTALK=$(OPUAVTALK) \ HWDEFSINC=$(HWDEFS)/$(1) \ OPUAVSYNTHDIR=$(OPUAVSYNTHDIR) \ DOXYGENDIR=$(DOXYGENDIR) \ \ $$* .PHONY: bu_$(1)_clean bu_$(1)_clean: $(V0) @$(ECHO) " CLEAN $$@" $(V1) $(RM) -fr $(BUILD_DIR)/bu_$(1) endef # $(1) = Canonical board name all in lower case (e.g. coptercontrol) define EF_TEMPLATE .PHONY: ef_$(1) ef_$(1): ef_$(1)_bin ef_$(1)_%: bl_$(1)_bin fw_$(1)_opfw $(V1) $(MKDIR) -p $(BUILD_DIR)/ef_$(1)/dep $(V1) cd $(ROOT_DIR)/flight/targets/EntireFlash && \ $$(MAKE) -r --no-print-directory \ BOARD_NAME=$(1) \ BOARD_SHORT_NAME=$(3) \ BUILD_TYPE=ef \ TCHAIN_PREFIX="$(ARM_SDK_PREFIX)" \ DFU_CMD="$(DFUUTIL_DIR)/bin/dfu-util" \ \ TARGET=ef_$(1) \ OUTDIR=$(BUILD_DIR)/ef_$(1) \ \ $$* .PHONY: ef_$(1)_clean ef_$(1)_clean: $(V0) @$(ECHO) " CLEAN $$@" $(V1) $(RM) -fr $(BUILD_DIR)/ef_$(1) endef # When building any of the "all_*" targets, tell all sub makefiles to display # additional details on each line of output to describe which build and target # that each line applies to. ifneq ($(strip $(filter all_%,$(MAKECMDGOALS))),) export ENABLE_MSG_EXTRA := yes endif # When building more than one goal in a single make invocation, also # enable the extra context for each output line ifneq ($(word 2,$(MAKECMDGOALS)),) export ENABLE_MSG_EXTRA := yes endif # $(1) = Canonical board name all in lower case (e.g. coptercontrol) define BOARD_PHONY_TEMPLATE .PHONY: all_$(1) all_$(1): $$(filter fw_$(1), $$(FW_TARGETS)) all_$(1): $$(filter bl_$(1), $$(BL_TARGETS)) all_$(1): $$(filter bu_$(1), $$(BU_TARGETS)) all_$(1): $$(filter ef_$(1), $$(EF_TARGETS)) .PHONY: all_$(1)_clean all_$(1)_clean: $$(addsuffix _clean, $$(filter fw_$(1), $$(FW_TARGETS))) all_$(1)_clean: $$(addsuffix _clean, $$(filter bl_$(1), $$(BL_TARGETS))) all_$(1)_clean: $$(addsuffix _clean, $$(filter bu_$(1), $$(BU_TARGETS))) all_$(1)_clean: $$(addsuffix _clean, $$(filter ef_$(1), $$(EF_TARGETS))) endef ALL_BOARDS := coptercontrol pipxtreme simposix revolution revomini osd ALL_BOARDS_BU := coptercontrol pipxtreme simposix # SimPosix only builds on Linux so drop it from the list for # all other platforms. ifneq ($(UNAME), Linux) ALL_BOARDS := $(filter-out simposix, $(ALL_BOARDS)) ALL_BOARDS_BU := $(filter-out simposix, $(ALL_BOARDS_BU)) endif # Friendly names of each board (used to find source tree) coptercontrol_friendly := CopterControl pipxtreme_friendly := PipXtreme revolution_friendly := Revolution revomini_friendly := RevoMini simposix_friendly := SimPosix osd_friendly := OSD # Short names of each board (used to display board name in parallel builds) coptercontrol_short := 'cc ' pipxtreme_short := 'pipx' revolution_short := 'revo' revomini_short := 'rm ' simposix_short := 'posx' osd_short := 'osd ' # Start out assuming that we'll build fw, bl and bu for all boards FW_BOARDS := $(ALL_BOARDS) BL_BOARDS := $(ALL_BOARDS) BU_BOARDS := $(ALL_BOARDS_BU) EF_BOARDS := $(ALL_BOARDS) # SimPosix doesn't have a BL, BU or EF target so we need to # filter them out to prevent errors on the all_flight target. BL_BOARDS := $(filter-out simposix, $(BL_BOARDS)) BU_BOARDS := $(filter-out simposix, $(BU_BOARDS)) EF_BOARDS := $(filter-out simposix, $(EF_BOARDS)) # Generate the targets for whatever boards are left in each list FW_TARGETS := $(addprefix fw_, $(FW_BOARDS)) BL_TARGETS := $(addprefix bl_, $(BL_BOARDS)) BU_TARGETS := $(addprefix bu_, $(BU_BOARDS)) EF_TARGETS := $(addprefix ef_, $(EF_BOARDS)) .PHONY: all_fw all_fw_clean all_fw: $(addsuffix _opfw, $(FW_TARGETS)) all_fw_clean: $(addsuffix _clean, $(FW_TARGETS)) .PHONY: all_bl all_bl_clean all_bl: $(addsuffix _bin, $(BL_TARGETS)) all_bl_clean: $(addsuffix _clean, $(BL_TARGETS)) .PHONY: all_bu all_bu_clean all_bu: $(addsuffix _opfw, $(BU_TARGETS)) all_bu_clean: $(addsuffix _clean, $(BU_TARGETS)) .PHONY: all_ef all_ef_clean all_ef: $(EF_TARGETS) all_ef_clean: $(addsuffix _clean, $(EF_TARGETS)) .PHONY: all_flight all_flight_clean all_flight: all_fw all_bl all_bu all_ef all_flight_clean: all_fw_clean all_bl_clean all_bu_clean all_ef_clean # Expand the groups of targets for each board $(foreach board, $(ALL_BOARDS), $(eval $(call BOARD_PHONY_TEMPLATE,$(board)))) # Expand the bootloader updater rules $(foreach board, $(ALL_BOARDS), $(eval $(call BU_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short)))) # Expand the firmware rules $(foreach board, $(ALL_BOARDS), $(eval $(call FW_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short)))) # Expand the bootloader rules $(foreach board, $(ALL_BOARDS), $(eval $(call BL_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short)))) # Expand the entire-flash rules $(foreach board, $(ALL_BOARDS), $(eval $(call EF_TEMPLATE,$(board),$($(board)_friendly),$($(board)_short)))) .PHONY: sim_win32 sim_win32: sim_win32_exe sim_win32_%: uavobjects_flight $(V1) $(MKDIR) -p $(BUILD_DIR)/sitl_win32 $(V1) $(MAKE) --no-print-directory \ -C $(ROOT_DIR)/flight/targets/OpenPilot --file=$(ROOT_DIR)/flight/targets/OpenPilot/Makefile.win32 $* .PHONY: sim_osx sim_osx: sim_osx_elf sim_osx_%: uavobjects_flight $(V1) $(MKDIR) -p $(BUILD_DIR)/sim_osx $(V1) $(MAKE) --no-print-directory \ -C $(ROOT_DIR)/flight/targets/Revolution --file=$(ROOT_DIR)/flight/targets/Revolution/Makefile.osx $* ############################## # # Unit Tests # ############################## ALL_UNITTESTS := logfs # Build the directory for the unit tests UT_OUT_DIR := $(BUILD_DIR)/unit_tests $(UT_OUT_DIR): $(V1) $(MKDIR) -p $@ .PHONY: all_ut all_ut: $(addsuffix _elf, $(addprefix ut_, $(ALL_UNITTESTS))) .PHONY: all_ut_xml all_ut_xml: $(addsuffix _xml, $(addprefix ut_, $(ALL_UNITTESTS))) .PHONY: all_ut_run all_ut_run: $(addsuffix _run, $(addprefix ut_, $(ALL_UNITTESTS))) .PHONY: all_ut_clean all_ut_clean: $(V0) @$(ECHO) " CLEAN $@" $(V1) [ ! -d "$(UT_OUT_DIR)" ] || $(RM) -r "$(UT_OUT_DIR)" # $(1) = Unit test name define UT_TEMPLATE .PHONY: ut_$(1) ut_$(1): ut_$(1)_run ut_$(1)_%: $$(UT_OUT_DIR) $(V1) $(MKDIR) -p $(UT_OUT_DIR)/$(1) $(V1) cd $(ROOT_DIR)/flight/tests/$(1) && \ $$(MAKE) -r --no-print-directory \ BUILD_TYPE=ut \ BOARD_SHORT_NAME=$(1) \ TCHAIN_PREFIX="" \ REMOVE_CMD="$(RM)" \ \ TARGET=$(1) \ OUTDIR="$(UT_OUT_DIR)/$(1)" \ \ PIOS=$(PIOS) \ OPUAVOBJ=$(OPUAVOBJ) \ OPUAVTALK=$(OPUAVTALK) \ FLIGHTLIB=$(FLIGHTLIB) \ \ GTEST_DIR=$(GTEST_DIR) \ \ $$* .PHONY: ut_$(1)_clean ut_$(1)_clean: $(V0) @$(ECHO) " CLEAN $(1)" $(V1) [ ! -d "$(UT_OUT_DIR)/$(1)" ] || $(RM) -r "$(UT_OUT_DIR)/$(1)" endef # Expand the unittest rules $(foreach ut, $(ALL_UNITTESTS), $(eval $(call UT_TEMPLATE,$(ut)))) # Disable parallel make when the all_ut_run target is requested otherwise the TAP # output is interleaved with the rest of the make output. ifneq ($(strip $(filter all_ut_run,$(MAKECMDGOALS))),) .NOTPARALLEL: $(info *NOTE* Parallel make disabled by all_ut_run target so we have sane console output) endif ############################## # # Packaging components # ############################## .PHONY: package package: $(V1) cd $@ && $(MAKE) --no-print-directory $@ .PHONY: package_resources package_resources: $(V1) cd package && $(MAKE) --no-print-directory opfw_resource ############################## # # Build info # ############################## .PHONY: build-info build-info: $(V1) $(MKDIR) -p $(BUILD_DIR) $(V1) $(VERSION_INFO) \ --uavodir=$(ROOT_DIR)/shared/uavobjectdefinition \ --template="make/templates/$@.txt" \ --outfile="$(BUILD_DIR)/$@.txt" ############################## # # Help message, the default Makefile goal # ############################## .PHONY: help help: @$(ECHO) @$(ECHO) " This Makefile is known to work on Linux and Mac in a standard shell environment." @$(ECHO) " It also works on Windows by following the instructions in make/winx86/README.txt." @$(ECHO) @$(ECHO) " Here is a summary of the available targets:" @$(ECHO) @$(ECHO) " [Tool Installers]" @$(ECHO) " qt_sdk_install - Install the QT v4.7.3 tools" @$(ECHO) " arm_sdk_install - Install the GNU ARM gcc toolchain" @$(ECHO) " openocd_install - Install the OpenOCD JTAG daemon" @$(ECHO) " stm32flash_install - Install the stm32flash tool for unbricking boards" @$(ECHO) " dfuutil_install - Install the dfu-util tool for unbricking F4-based boards" @$(ECHO) " android_sdk_install - Install the Android SDK tools" @$(ECHO) @$(ECHO) " [Big Hammer]" @$(ECHO) " all - Generate UAVObjects, build openpilot firmware and gcs" @$(ECHO) " all_flight - Build all firmware, bootloaders and bootloader updaters" @$(ECHO) " all_fw - Build only firmware for all boards" @$(ECHO) " all_bl - Build only bootloaders for all boards" @$(ECHO) " all_bu - Build only bootloader updaters for all boards" @$(ECHO) @$(ECHO) " all_clean - Remove your build directory ($(BUILD_DIR))" @$(ECHO) " all_flight_clean - Remove all firmware, bootloaders and bootloader updaters" @$(ECHO) " all_fw_clean - Remove firmware for all boards" @$(ECHO) " all_bl_clean - Remove bootlaoders for all boards" @$(ECHO) " all_bu_clean - Remove bootloader updaters for all boards" @$(ECHO) @$(ECHO) " all_ - Build all available images for " @$(ECHO) " all__clean - Remove all available images for " @$(ECHO) @$(ECHO) " all_ut - Build all unit tests" @$(ECHO) " all_ut_tap - Run all unit tests and capture all TAP output to files" @$(ECHO) " all_ut_run - Run all unit tests and dump TAP output to console" @$(ECHO) @$(ECHO) " [Firmware]" @$(ECHO) " - Build firmware for " @$(ECHO) " supported boards are ($(ALL_BOARDS))" @$(ECHO) " fw_ - Build firmware for " @$(ECHO) " supported boards are ($(FW_BOARDS))" @$(ECHO) " fw__clean - Remove firmware for " @$(ECHO) " fw__program - Use OpenOCD + JTAG to write firmware to " @$(ECHO) @$(ECHO) " [Bootloader]" @$(ECHO) " bl_ - Build bootloader for " @$(ECHO) " supported boards are ($(BL_BOARDS))" @$(ECHO) " bl__clean - Remove bootloader for " @$(ECHO) " bl__program - Use OpenOCD + JTAG to write bootloader to " @$(ECHO) @$(ECHO) " [Bootloader Updater]" @$(ECHO) " bu_ - Build bootloader updater for " @$(ECHO) " supported boards are ($(BU_BOARDS))" @$(ECHO) " bu__clean - Remove bootloader updater for " @$(ECHO) @$(ECHO) " [Unbrick a board]" @$(ECHO) " unbrick_ - Use the STM32's built in boot ROM to write a bootloader to " @$(ECHO) " supported boards are ($(BL_BOARDS))" @$(ECHO) " [Unittests]" @$(ECHO) " ut_ - Build unit test " @$(ECHO) " ut__tap - Run test and capture TAP output into a file" @$(ECHO) " ut__run - Run test and dump TAP output to console" @$(ECHO) @$(ECHO) " [Simulation]" @$(ECHO) " sim_osx - Build OpenPilot simulation firmware for OSX" @$(ECHO) " sim_osx_clean - Delete all build output for the osx simulation" @$(ECHO) " sim_win32 - Build OpenPilot simulation firmware for" @$(ECHO) " Windows using mingw and msys" @$(ECHO) " sim_win32_clean - Delete all build output for the win32 simulation" @$(ECHO) @$(ECHO) " [GCS]" @$(ECHO) " gcs - Build the Ground Control System (GCS) application" @$(ECHO) " gcs_clean - Remove the Ground Control System (GCS) application" @$(ECHO) @$(ECHO) " [UAVObjects]" @$(ECHO) " uavobjects - Generate source files from the UAVObject definition XML files" @$(ECHO) " uavobjects_test - parse xml-files - check for valid, duplicate ObjId's, ... " @$(ECHO) " uavobjects_ - Generate source files from a subset of the UAVObject definition XML files" @$(ECHO) " supported groups are ($(UAVOBJ_TARGETS))" @$(ECHO) @$(ECHO) " Hint: Add V=1 to your command line to see verbose build output." @$(ECHO) @$(ECHO) " Note: All tools will be installed into $(TOOLS_DIR)" @$(ECHO) " All build output will be placed in $(BUILD_DIR)" @$(ECHO)