# Hey Emacs, this is a -*- makefile -*-
#
#   Copyright (C) 2003-2014  The Paparazzi Team
#
# This file is part of paparazzi.
#
# paparazzi 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 2, or (at your option)
# any later version.
#
# paparazzi 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 paparazzi; see the file COPYING.  If not, write to
# the Free Software Foundation, 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

# Preprocessing of XML configuration files

PAPARAZZI_SRC ?= $(shell pwd)

include conf/Makefile.local

# main directory where the generated files and compilation results for an aircraft are stored
AIRCRAFT_BUILD_DIR = $(PAPARAZZI_HOME)/var/aircrafts/$(AIRCRAFT)
CONF=$(PAPARAZZI_HOME)/conf
CONF_XML ?= $(CONF)/conf.xml
AIRBORNE=sw/airborne
MESSAGES_XML = $(CONF)/messages.xml

# make sure the TARGET variable is set if needed for current make target
ifneq (,$(findstring $(MAKECMDGOALS),all_ac_h radio_ac_h flight_plan_ac_h))
ifeq ($(TARGET),)
$(warning No TARGET specified! Defaulting to "TARGET=ap")
override TARGET=ap
endif
endif

AIRCRAFT_CONF_DIR = $(AIRCRAFT_BUILD_DIR)/conf
AC_GENERATED = $(AIRCRAFT_BUILD_DIR)/$(TARGET)/generated

AIRFRAME_H=$(AC_GENERATED)/airframe.h
PERIODIC_H=$(AC_GENERATED)/periodic_telemetry.h
RADIO_H=$(AC_GENERATED)/radio.h
FLIGHT_PLAN_H=$(AC_GENERATED)/flight_plan.h
FLIGHT_PLAN_XML=$(AIRCRAFT_BUILD_DIR)/flight_plan.xml
SETTINGS_H=$(AC_GENERATED)/settings.h
SETTINGS_XMLS=$(patsubst %,$(CONF)/%,$(SETTINGS))
SETTINGS_XMLS_DEP=$(filter-out %~,$(SETTINGS_XMLS))
SETTINGS_XML=$(AIRCRAFT_BUILD_DIR)/settings.xml
SETTINGS_MODULES=$(AIRCRAFT_BUILD_DIR)/settings_modules.xml
SETTINGS_TELEMETRY=$(AIRCRAFT_BUILD_DIR)/settings_telemetry.xml
SETTINGS_AUTOPILOT=$(AIRCRAFT_BUILD_DIR)/settings_autopilot.xml
MAKEFILE_AC=$(AIRCRAFT_BUILD_DIR)/Makefile.ac
MODULES_H=$(AC_GENERATED)/modules.h
MODULES_DIR=$(PAPARAZZI_HOME)/conf/modules/
AUTOPILOT_DIR=$(AC_GENERATED)/
AIRCRAFT_MD5=$(AIRCRAFT_CONF_DIR)/aircraft.md5

UNAME = $(shell uname -s)
ifeq ("$(UNAME)","Darwin")
	MKTEMP = gmktemp
else
	MKTEMP = mktemp
endif

# By default, detect number of processors for parallel compilation
# same as passing J=AUTO from toplevel make.
# Number of processes can also be explicitly set with e.g. J=4
# For serial compilation, call make with J=1
NPROCS := 1
J ?= AUTO
ifeq ($J,AUTO)
ifeq ($(UNAME),Linux)
  NPROCS := $(shell grep -c ^processor /proc/cpuinfo)
else ifeq ($(UNAME),Darwin)
  NPROCS := $(shell sysctl hw.ncpu | awk '{print $$2}')
endif # $(UNAME)
else # not auto, explicitly specified
  NPROCS := $J
endif

#
# export paparazzi version
#
GIT_SHA1 := $(shell git log -1 --pretty=format:%H 2> /dev/null)
ifneq ($(words $(GIT_SHA1)),1)
GIT_SHA1 := "UNKNOWN"
endif
GIT_DESC := $(shell ./paparazzi_version)
BUILD_DESC := $(shell cat $(PAPARAZZI_HOME)/var/build_version.txt 2> /dev/null || echo UNKNOWN)
# extract only version number in format <major>.<minor>.<patch>
PPRZ_VER := $(shell echo $(GIT_DESC) | sed 's/[^0-9.]*\([0-9.]*\).*/\1/')
PPRZ_VER_MAJOR := $(shell echo $(GIT_DESC) | sed 's/v\([0-9]*\).*/\1/')
PPRZ_VER_MINOR := $(shell echo $(GIT_DESC) | sed 's/v[0-9]*.\([0-9]*\).*/\1/')
PPRZ_VER_PATCH := $(shell echo $(GIT_DESC) | sed 's/v[0-9]*.[0-9]*.\([0-9]*\).*/\1/')
ifneq ($(words $(PPRZ_VER_PATCH)),1)
PPRZ_VER_PATCH := 0
endif
export GIT_DESC
export BUILD_DESC
export GIT_SHA1
export PPRZ_VER_MAJOR
export PPRZ_VER_MINOR
export PPRZ_VER_PATCH

# show warning with print_version if PPRZ_VER (e.g. 5.3.2) is not part of the BUILD_DESC string
VERSION_MATCH = ""
ifeq (,$(findstring $(PPRZ_VER),$(BUILD_DESC)))
VERSION_MATCH = "\nWarning: version differs from build version ($(BUILD_DESC)), you might want to run the toplevel make."
endif

# "make Q=''" to get full echo
Q=@

#
# include the generated airframe makefile
#
ifeq ($(MAKECMDGOALS),all_ac_h)
-include $(MAKEFILE_AC)

ifdef PERIODIC_FREQUENCY
# telemetry and module periodic frequency default to PERIODIC_FREQUENCY
TELEMETRY_FREQUENCY ?= $(PERIODIC_FREQUENCY)
DEFAULT_MODULES_FREQUENCY = $(PERIODIC_FREQUENCY)
else
$(warning Info: PERIODIC_FREQUENCY not configured, defaulting to 60Hz for modules and telemetry)
TELEMETRY_FREQUENCY ?= 60
DEFAULT_MODULES_FREQUENCY = 60
endif

endif


init:
	@[ -d $(PAPARAZZI_HOME) ] || (echo "Copying config example in your $(PAPARAZZI_HOME) directory"; mkdir -p $(PAPARAZZI_HOME); cp -a conf $(PAPARAZZI_HOME); cp -a data $(PAPARAZZI_HOME); mkdir -p $(PAPARAZZI_HOME)/var/maps; mkdir -p $(PAPARAZZI_HOME)/var/include)


print_version:
	@echo "-----------------------------------------------------------------------"
	@echo "Paparazzi version" $(GIT_DESC)$(VERSION_MATCH)
	@echo "-----------------------------------------------------------------------"


all_ac_h: $(AIRFRAME_H) $(MODULES_H) $(SETTINGS_H) $(MAKEFILE_AC) $(PERIODIC_H) autopilot_h
	@echo "TARGET: " $(TARGET)"\n" > $(AIRCRAFT_BUILD_DIR)/$(TARGET)_srcs.list
	@echo "CFLAGS: " $($(TARGET).CFLAGS)"\n"  >> $(AIRCRAFT_BUILD_DIR)/$(TARGET)_srcs.list
	@echo "LDFLAGS: " $($(TARGET).LDFLAGS)"\n"  >> $(AIRCRAFT_BUILD_DIR)/$(TARGET)_srcs.list
	@echo "srcs: " $($(TARGET).srcs) >> $(AIRCRAFT_BUILD_DIR)/$(TARGET)_srcs.list

radio_ac_h : $(RADIO_H)

flight_plan_ac_h : $(FLIGHT_PLAN_H) $(FLIGHT_PLAN_XML)

makefile_ac: $(MAKEFILE_AC)

$(AIRFRAME_H) : $(CONF)/$(AIRFRAME_XML) $(CONF_XML) $(AIRCRAFT_MD5)
	$(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED)
	@echo GENERATE $@ from $(AIRFRAME_XML)
	$(eval $@_TMP := $(shell $(MKTEMP)))
	$(Q)$(GENERATORS)/gen_airframe.out $(AC_ID) $(AIRCRAFT) $(MD5SUM) $< > $($@_TMP)
	$(Q)mv $($@_TMP) $@
	$(Q)chmod a+r $@
	$(Q)cp $(CONF)/airframes/airframe.dtd $(AIRCRAFT_CONF_DIR)/airframes

$(RADIO_H) : $(CONF)/$(RADIO) $(CONF_XML) $(GENERATORS)/gen_radio.out
	$(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED)
	@echo GENERATE $@ from $(RADIO)
	$(eval $@_TMP := $(shell $(MKTEMP)))
	$(Q)$(GENERATORS)/gen_radio.out $< > $($@_TMP)
	$(Q)mv $($@_TMP) $@
	$(Q)chmod a+r $@
	$(Q)cp $< $(AIRCRAFT_CONF_DIR)/radios

$(PERIODIC_H) : $(CONF)/$(AIRFRAME_XML) $(MESSAGES_XML) $(CONF_XML) $(CONF)/$(TELEMETRY) $(MAKEFILE_AC)
	$(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED)
	@echo GENERATE $@ from $(TELEMETRY)
	$(eval $@_TMP := $(shell $(MKTEMP)))
	$(Q)$(GENERATORS)/gen_periodic.out $(CONF)/$(AIRFRAME_XML) $(MESSAGES_XML) $(CONF)/$(TELEMETRY) $(TELEMETRY_FREQUENCY) $(SETTINGS_TELEMETRY) > $($@_TMP)
	$(Q)mv $($@_TMP) $@
	$(Q)chmod a+r $@
	$(Q)cp $(CONF)/$(TELEMETRY) $(AIRCRAFT_CONF_DIR)/telemetry

$(FLIGHT_PLAN_H) : $(CONF)/$(FLIGHT_PLAN) $(CONF_XML) $(GENERATORS)/gen_flight_plan.out
	$(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED)
	@echo GENERATE $@ from $(FLIGHT_PLAN)
	$(eval $@_TMP := $(shell $(MKTEMP)))
	$(Q)$(GENERATORS)/gen_flight_plan.out $< > $($@_TMP)
	$(Q)mv $($@_TMP) $@
	$(Q)chmod a+r $@
	$(Q)cp $< $(AIRCRAFT_CONF_DIR)/flight_plans

$(FLIGHT_PLAN_XML) : $(CONF)/$(FLIGHT_PLAN) $(CONF_XML) $(GENERATORS)/gen_flight_plan.out
	@echo GENERATE $@ from $(FLIGHT_PLAN)
	$(eval $@_TMP := $(shell $(MKTEMP)))
	$(Q)$(GENERATORS)/gen_flight_plan.out -dump $< > $($@_TMP)
	$(Q)mv $($@_TMP) $@
	$(Q)chmod a+r $@

$(SETTINGS_H) : $(SETTINGS_XMLS_DEP) $(CONF_XML) $(SETTINGS_MODULES) $(SETTINGS_TELEMETRY) $(GENERATORS)/gen_settings.out
	$(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED)
	@echo GENERATE $@
	$(eval $@_TMP := $(shell $(MKTEMP)))
	$(Q)$(GENERATORS)/gen_settings.out $(SETTINGS_XML) $(SETTINGS_TELEMETRY) $(SETTINGS_XMLS) $(SETTINGS_MODULES) > $($@_TMP)
	$(Q)mv $($@_TMP) $@
	$(Q)chmod a+r $@
	$(Q)cp $(SETTINGS_XMLS_DEP) $(AIRCRAFT_CONF_DIR)/settings

$(MODULES_H) : $(CONF)/$(AIRFRAME_XML) $(GENERATORS)/gen_modules.out $(CONF)/modules/*.xml
	$(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED)
	@echo GENERATE $@
	$(eval $@_TMP := $(shell $(MKTEMP)))
	$(Q)$(GENERATORS)/gen_modules.out $(SETTINGS_MODULES) $(DEFAULT_MODULES_FREQUENCY) $< > $($@_TMP)
	$(Q)mv $($@_TMP) $@
	$(Q)chmod a+r $@

autopilot_h : $(CONF)/$(AIRFRAME_XML) $(GENERATORS)/gen_autopilot.out $(CONF)/autopilot/*.xml
	$(Q)test -d $(AC_GENERATED) || mkdir -p $(AC_GENERATED)
	@echo GENERATE autopilots in $(AUTOPILOT_DIR)
	$(Q)$(GENERATORS)/gen_autopilot.out $(CONF)/$(AIRFRAME_XML) $(AUTOPILOT_DIR) $(SETTINGS_AUTOPILOT)

$(SETTINGS_MODULES) : $(MODULES_H)
$(SETTINGS_TELEMETRY) : $(PERIODIC_H)

%.ac_h : $(GENERATORS)/gen_aircraft.out
	$(Q)if (expr "$(AIRCRAFT)") > /dev/null; then : ; else echo "AIRCRAFT undefined: type 'make AIRCRAFT=AircraftName ...'"; exit 1; fi
	@echo "#######################################"
	@echo "# BUILD AIRCRAFT=$(AIRCRAFT), TARGET $*"
	@echo "#######################################"
	$(Q)PAPARAZZI_SRC=$(PAPARAZZI_SRC) PAPARAZZI_HOME=$(PAPARAZZI_HOME) TARGET=$* Q=$(Q) $(GENERATORS)/gen_aircraft.out $(AIRCRAFT) $(CONF_XML)

%.compile: %.ac_h | print_version
	cd $(AIRBORNE); $(MAKE) -j$(NPROCS) TARGET=$* all

%.upload: %.compile
	cd $(AIRBORNE); $(MAKE) TARGET=$* upload

jsbsim jsbsim.compile: jsbsim.ac_h print_version
	cd $(AIRBORNE); $(MAKE) TARGET=jsbsim ARCHI=jsbsim ARCH=jsbsim all

sim sim.compile: sim.ac_h print_version
	cd $(AIRBORNE); $(MAKE) TARGET=sim ARCHI=sim ARCH=sim all

# Rules for backward compatibility (old guys are used to !)
fbw : fbw.compile
ap: ap.compile

clean_ac :
	$(Q)if (expr "$(AIRCRAFT)") > /dev/null; then : ; else echo "AIRCRAFT undefined: type 'make AIRCRAFT=AircraftName ...'"; exit 1; fi
	@echo "CLEANING $(AIRCRAFT)"
	$(Q)rm -fr $(AIRCRAFT_BUILD_DIR)

.PHONY: init all_ac_h radio_ac_h flight_plan_ac_h makefile_ac clean_ac print_version
