scripts: Parallel build with pattern rules (#1202)

Drop shell for loops in favor of makefile pattern rules,
so make can run targets in parallel using -j.
This doesn't affect Vivado's own settings.

As a benchmark, 12th Gen Intel(R) Core(TM) i9-12900H 5GHz(max):
	$ make -C projects/adrv9009/zcu102/ clean-all
	$ time make -C projects/adrv9009/zcu102/ -j$CORES lib
CORES=1:
	real    9m27.223s
	user    9m2.556s
	sys     0m32.358s
CORES=8:
	real    1m54.639s
	user    16m26.512s
	sys     1m2.317s
i.e. about 5 times faster to build IP core dependencies.

Signed-off-by: Liam Beguin <liambeguin@gmail.com>
Signed-off-by: Jorge Marques <jorge.marques@analog.com>
main
Liam Beguin 2023-12-14 12:27:23 -05:00 committed by GitHub
parent 940c3ccd35
commit 887ffac0ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 294 deletions

View File

@ -2,7 +2,6 @@
#################################################################################### ####################################################################################
## Copyright (c) 2018 - 2023 Analog Devices, Inc. ## Copyright (c) 2018 - 2023 Analog Devices, Inc.
### SPDX short identifier: BSD-1-Clause ### SPDX short identifier: BSD-1-Clause
## Auto-generated, do not modify!
#################################################################################### ####################################################################################
#################################################################################### ####################################################################################
@ -11,252 +10,22 @@ include ../quiet.mk
.PHONY: all lib clean clean-all .PHONY: all lib clean clean-all
all: lib all: lib
_LIBS := $(dir $(shell find . -mindepth 2 -name Makefile | sort))
clean: # Create virtual targets "$library/all", "$library/clean"
$(MAKE) -C ad463x_data_capture clean _LIBS_ALL := $(addsuffix all, $(_LIBS))
$(MAKE) -C axi_ad3552r clean _LIBS_CLEAN := $(addsuffix clean, $(_LIBS))
$(MAKE) -C axi_ad4858 clean
$(MAKE) -C axi_ad5766 clean
$(MAKE) -C axi_ad7606x clean
$(MAKE) -C axi_ad7616 clean
$(MAKE) -C axi_ad7768 clean
$(MAKE) -C axi_ad777x clean
$(MAKE) -C axi_ad9122 clean
$(MAKE) -C axi_ad9250 clean
$(MAKE) -C axi_ad9265 clean
$(MAKE) -C axi_ad9361 clean
$(MAKE) -C axi_ad9434 clean
$(MAKE) -C axi_ad9467 clean
$(MAKE) -C axi_ad9625 clean
$(MAKE) -C axi_ad9671 clean
$(MAKE) -C axi_ad9684 clean
$(MAKE) -C axi_ad9739a clean
$(MAKE) -C axi_ad9783 clean
$(MAKE) -C axi_ad9963 clean
$(MAKE) -C axi_adaq8092 clean
$(MAKE) -C axi_adc_decimate clean
$(MAKE) -C axi_adc_trigger clean
$(MAKE) -C axi_adrv9001 clean
$(MAKE) -C axi_clkgen clean
$(MAKE) -C axi_clock_monitor clean
$(MAKE) -C axi_dac_interpolate clean
$(MAKE) -C axi_dmac clean
$(MAKE) -C axi_fan_control clean
$(MAKE) -C axi_fmcadc5_sync clean
$(MAKE) -C axi_generic_adc clean
$(MAKE) -C axi_gpreg clean
$(MAKE) -C axi_hdmi_rx clean
$(MAKE) -C axi_hdmi_tx clean
$(MAKE) -C axi_i2s_adi clean
$(MAKE) -C axi_intr_monitor clean
$(MAKE) -C axi_laser_driver clean
$(MAKE) -C axi_logic_analyzer clean
$(MAKE) -C axi_ltc235x clean
$(MAKE) -C axi_ltc2387 clean
$(MAKE) -C axi_pulse_gen clean
$(MAKE) -C axi_pwm_gen clean
$(MAKE) -C axi_rd_wr_combiner clean
$(MAKE) -C axi_spdif_rx clean
$(MAKE) -C axi_spdif_tx clean
$(MAKE) -C axi_sysid clean
$(MAKE) -C axi_tdd clean
$(MAKE) -C cn0363/cn0363_dma_sequencer clean
$(MAKE) -C cn0363/cn0363_phase_data_sync clean
$(MAKE) -C cordic_demod clean
$(MAKE) -C data_offload clean
$(MAKE) -C intel/adi_jesd204 clean
$(MAKE) -C intel/avl_adxcfg clean
$(MAKE) -C intel/avl_adxcvr clean
$(MAKE) -C intel/avl_adxcvr_octet_swap clean
$(MAKE) -C intel/avl_adxphy clean
$(MAKE) -C intel/avl_dacfifo clean
$(MAKE) -C intel/axi_adxcvr clean
$(MAKE) -C intel/common/intel_mem_asym clean
$(MAKE) -C intel/common/intel_serdes clean
$(MAKE) -C intel/jesd204_phy clean
$(MAKE) -C intel/util_clkdiv clean
$(MAKE) -C jesd204/ad_ip_jesd204_tpl_adc clean
$(MAKE) -C jesd204/ad_ip_jesd204_tpl_dac clean
$(MAKE) -C jesd204/axi_jesd204_common clean
$(MAKE) -C jesd204/axi_jesd204_rx clean
$(MAKE) -C jesd204/axi_jesd204_tx clean
$(MAKE) -C jesd204/jesd204_common clean
$(MAKE) -C jesd204/jesd204_rx clean
$(MAKE) -C jesd204/jesd204_rx_static_config clean
$(MAKE) -C jesd204/jesd204_soft_pcs_rx clean
$(MAKE) -C jesd204/jesd204_soft_pcs_tx clean
$(MAKE) -C jesd204/jesd204_tx clean
$(MAKE) -C jesd204/jesd204_tx_static_config clean
$(MAKE) -C jesd204/jesd204_versal_gt_adapter_rx clean
$(MAKE) -C jesd204/jesd204_versal_gt_adapter_tx clean
$(MAKE) -C spi_engine/axi_spi_engine clean
$(MAKE) -C spi_engine/spi_axis_reorder clean
$(MAKE) -C spi_engine/spi_engine_execution clean
$(MAKE) -C spi_engine/spi_engine_interconnect clean
$(MAKE) -C spi_engine/spi_engine_offload clean
$(MAKE) -C sysid_rom clean
$(MAKE) -C util_adcfifo clean
$(MAKE) -C util_axis_fifo clean
$(MAKE) -C util_axis_fifo_asym clean
$(MAKE) -C util_axis_resize clean
$(MAKE) -C util_axis_upscale clean
$(MAKE) -C util_bsplit clean
$(MAKE) -C util_cdc clean
$(MAKE) -C util_cic clean
$(MAKE) -C util_dacfifo clean
$(MAKE) -C util_dec256sinc24b clean
$(MAKE) -C util_delay clean
$(MAKE) -C util_do_ram clean
$(MAKE) -C util_extract clean
$(MAKE) -C util_fir_dec clean
$(MAKE) -C util_fir_int clean
$(MAKE) -C util_gmii_to_rgmii clean
$(MAKE) -C util_hbm clean
$(MAKE) -C util_i2c_mixer clean
$(MAKE) -C util_mfifo clean
$(MAKE) -C util_mii_to_rmii clean
$(MAKE) -C util_pack/util_cpack2 clean
$(MAKE) -C util_pack/util_upack2 clean
$(MAKE) -C util_pad clean
$(MAKE) -C util_pulse_gen clean
$(MAKE) -C util_rfifo clean
$(MAKE) -C util_sigma_delta_spi clean
$(MAKE) -C util_tdd_sync clean
$(MAKE) -C util_var_fifo clean
$(MAKE) -C util_wfifo clean
$(MAKE) -C xilinx/axi_adcfifo clean
$(MAKE) -C xilinx/axi_adxcvr clean
$(MAKE) -C xilinx/axi_dacfifo clean
$(MAKE) -C xilinx/axi_xcvrlb clean
$(MAKE) -C xilinx/util_adxcvr clean
$(MAKE) -C xilinx/util_clkdiv clean
$(MAKE) -C interfaces clean $(_LIBS_ALL):
$(MAKE) -C $(@D) $(@F)
$(_LIBS_CLEAN):
$(MAKE) -C $(@D) $(@F)
clean-all:clean clean: $(_LIBS_CLEAN)
clean-all: clean
lib: $(_LIBS_ALL)
lib:
$(MAKE) -C ad463x_data_capture
$(MAKE) -C axi_ad3552r
$(MAKE) -C axi_ad4858
$(MAKE) -C axi_ad5766
$(MAKE) -C axi_ad7606x
$(MAKE) -C axi_ad7616
$(MAKE) -C axi_ad7768
$(MAKE) -C axi_ad777x
$(MAKE) -C axi_ad9122
$(MAKE) -C axi_ad9250
$(MAKE) -C axi_ad9265
$(MAKE) -C axi_ad9361
$(MAKE) -C axi_ad9434
$(MAKE) -C axi_ad9467
$(MAKE) -C axi_ad9625
$(MAKE) -C axi_ad9671
$(MAKE) -C axi_ad9684
$(MAKE) -C axi_ad9739a
$(MAKE) -C axi_ad9783
$(MAKE) -C axi_ad9963
$(MAKE) -C axi_adaq8092
$(MAKE) -C axi_adc_decimate
$(MAKE) -C axi_adc_trigger
$(MAKE) -C axi_adrv9001
$(MAKE) -C axi_clkgen
$(MAKE) -C axi_clock_monitor
$(MAKE) -C axi_dac_interpolate
$(MAKE) -C axi_dmac
$(MAKE) -C axi_fan_control
$(MAKE) -C axi_fmcadc5_sync
$(MAKE) -C axi_generic_adc
$(MAKE) -C axi_gpreg
$(MAKE) -C axi_hdmi_rx
$(MAKE) -C axi_hdmi_tx
$(MAKE) -C axi_i2s_adi
$(MAKE) -C axi_intr_monitor
$(MAKE) -C axi_laser_driver
$(MAKE) -C axi_logic_analyzer
$(MAKE) -C axi_ltc235x
$(MAKE) -C axi_ltc2387
$(MAKE) -C axi_pulse_gen
$(MAKE) -C axi_pwm_gen
$(MAKE) -C axi_rd_wr_combiner
$(MAKE) -C axi_spdif_rx
$(MAKE) -C axi_spdif_tx
$(MAKE) -C axi_sysid
$(MAKE) -C axi_tdd
$(MAKE) -C cn0363/cn0363_dma_sequencer
$(MAKE) -C cn0363/cn0363_phase_data_sync
$(MAKE) -C cordic_demod
$(MAKE) -C data_offload
$(MAKE) -C intel/adi_jesd204
$(MAKE) -C intel/avl_adxcfg
$(MAKE) -C intel/avl_adxcvr
$(MAKE) -C intel/avl_adxcvr_octet_swap
$(MAKE) -C intel/avl_adxphy
$(MAKE) -C intel/avl_dacfifo
$(MAKE) -C intel/axi_adxcvr
$(MAKE) -C intel/common/intel_mem_asym
$(MAKE) -C intel/common/intel_serdes
$(MAKE) -C intel/jesd204_phy
$(MAKE) -C intel/util_clkdiv
$(MAKE) -C jesd204/ad_ip_jesd204_tpl_adc
$(MAKE) -C jesd204/ad_ip_jesd204_tpl_dac
$(MAKE) -C jesd204/axi_jesd204_common
$(MAKE) -C jesd204/axi_jesd204_rx
$(MAKE) -C jesd204/axi_jesd204_tx
$(MAKE) -C jesd204/jesd204_common
$(MAKE) -C jesd204/jesd204_rx
$(MAKE) -C jesd204/jesd204_rx_static_config
$(MAKE) -C jesd204/jesd204_soft_pcs_rx
$(MAKE) -C jesd204/jesd204_soft_pcs_tx
$(MAKE) -C jesd204/jesd204_tx
$(MAKE) -C jesd204/jesd204_tx_static_config
$(MAKE) -C jesd204/jesd204_versal_gt_adapter_rx
$(MAKE) -C jesd204/jesd204_versal_gt_adapter_tx
$(MAKE) -C spi_engine/axi_spi_engine
$(MAKE) -C spi_engine/spi_axis_reorder
$(MAKE) -C spi_engine/spi_engine_execution
$(MAKE) -C spi_engine/spi_engine_interconnect
$(MAKE) -C spi_engine/spi_engine_offload
$(MAKE) -C sysid_rom
$(MAKE) -C util_adcfifo
$(MAKE) -C util_axis_fifo
$(MAKE) -C util_axis_fifo_asym
$(MAKE) -C util_axis_resize
$(MAKE) -C util_axis_upscale
$(MAKE) -C util_bsplit
$(MAKE) -C util_cdc
$(MAKE) -C util_cic
$(MAKE) -C util_dacfifo
$(MAKE) -C util_dec256sinc24b
$(MAKE) -C util_delay
$(MAKE) -C util_do_ram
$(MAKE) -C util_extract
$(MAKE) -C util_fir_dec
$(MAKE) -C util_fir_int
$(MAKE) -C util_gmii_to_rgmii
$(MAKE) -C util_hbm
$(MAKE) -C util_i2c_mixer
$(MAKE) -C util_mfifo
$(MAKE) -C util_mii_to_rmii
$(MAKE) -C util_pack/util_cpack2
$(MAKE) -C util_pack/util_upack2
$(MAKE) -C util_pad
$(MAKE) -C util_pulse_gen
$(MAKE) -C util_rfifo
$(MAKE) -C util_sigma_delta_spi
$(MAKE) -C util_tdd_sync
$(MAKE) -C util_var_fifo
$(MAKE) -C util_wfifo
$(MAKE) -C xilinx/axi_adcfifo
$(MAKE) -C xilinx/axi_adxcvr
$(MAKE) -C xilinx/axi_dacfifo
$(MAKE) -C xilinx/axi_xcvrlb
$(MAKE) -C xilinx/util_adxcvr
$(MAKE) -C xilinx/util_clkdiv
$(MAKE) -C interfaces
#################################################################################### ####################################################################################
#################################################################################### ####################################################################################

View File

@ -51,7 +51,7 @@ CLEAN_TARGET += tb/libraries
GENERIC_DEPS += $(HDL_LIBRARY_PATH)../scripts/adi_env.tcl GENERIC_DEPS += $(HDL_LIBRARY_PATH)../scripts/adi_env.tcl
.PHONY: all intel intel_dep xilinx xilinx_dep clean clean-all .PHONY: all intel xilinx clean clean-all
all: intel xilinx all: intel xilinx
@ -59,46 +59,49 @@ clean: clean-all
clean-all: clean-all:
$(call clean, \ $(call clean, \
$(CLEAN_TARGET), \ $(CLEAN_TARGET) .lock, \
$(HL)$(LIBRARY_NAME)$(NC) library) $(HL)$(LIBRARY_NAME)$(NC) library)
ifneq ($(INTEL_DEPS),) ifneq ($(INTEL_DEPS),)
INTEL_DEPS += $(GENERIC_DEPS) INTEL_DEPS += $(GENERIC_DEPS)
INTEL_DEPS += $(HDL_LIBRARY_PATH)scripts/adi_ip_intel.tcl INTEL_DEPS += $(HDL_LIBRARY_PATH)scripts/adi_ip_intel.tcl
INTEL_DEPS += $(foreach dep,$(INTEL_LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/.timestamp_intel) _INTEL_LIB_DEPS = $(foreach dep,$(INTEL_LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/.timestamp_intel)
intel: intel_dep .timestamp_intel intel: .timestamp_intel
.timestamp_intel: $(INTEL_DEPS) .timestamp_intel: $(INTEL_DEPS) $(_INTEL_LIB_DEPS)
touch $@ touch $@
intel_dep: $(_INTEL_LIB_DEPS):
@for lib in $(INTEL_LIB_DEPS); do \ $(MAKE) -C $(dir $@) intel
$(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} intel || exit $$?; \
done
endif endif
ifneq ($(XILINX_DEPS),) ifneq ($(XILINX_DEPS),)
XILINX_DEPS += $(GENERIC_DEPS) XILINX_DEPS += $(GENERIC_DEPS)
XILINX_DEPS += $(HDL_LIBRARY_PATH)scripts/adi_ip_xilinx.tcl XILINX_DEPS += $(HDL_LIBRARY_PATH)scripts/adi_ip_xilinx.tcl
XILINX_DEPS += $(foreach dep,$(XILINX_LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/component.xml) _XILINX_LIB_DEPS = $(foreach dep,$(XILINX_LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/component.xml)
_XILINX_INTF_DEPS = $(foreach dep,$(XILINX_INTERFACE_DEPS),$(HDL_LIBRARY_PATH)$(dep))
xilinx: xilinx_dep component.xml xilinx: component.xml
component.xml: $(XILINX_DEPS) .DELETE_ON_ERROR:
component.xml: $(XILINX_DEPS) $(_XILINX_INTF_DEPS) $(_XILINX_LIB_DEPS)
-rm -rf $(CLEAN_TARGET) -rm -rf $(CLEAN_TARGET)
$(call build, \ $(call build, \
$(VIVADO) $(LIBRARY_NAME)_ip.tcl, \ $(VIVADO) $(LIBRARY_NAME)_ip.tcl, \
$(LIBRARY_NAME)_ip.log, \ $(LIBRARY_NAME)_ip.log, \
$(HL)$(LIBRARY_NAME)$(NC) library) $(HL)$(LIBRARY_NAME)$(NC) library)
xilinx_dep: $(_XILINX_INTF_DEPS):
@for lib in $(XILINX_LIB_DEPS); do \ $(MAKE) -C $(dir $@) $(notdir $@)
$(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} xilinx || exit $$?; \
done $(_XILINX_LIB_DEPS):
@for intf in $(XILINX_INTERFACE_DEPS); do \ flock $(dir $@).lock -c "$(MAKE) -C $(dir $@) xilinx"; exit $$?
$(MAKE) -C $(HDL_LIBRARY_PATH)$${intf} xilinx || exit $$?; \
done %.xml:
$(MAKE) -C $(dir $@) $(notdir $@)
endif endif

View File

@ -105,7 +105,9 @@ M_DEPS += $(HDL_PROJECT_PATH)../scripts/adi_env.tcl
M_DEPS += $(foreach dep,$(LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/.timestamp_intel) M_DEPS += $(foreach dep,$(LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/.timestamp_intel)
.PHONY: all lib clean clean-all .PHONY: all lib clean clean-all
all: lib $(PROJECT_NAME).sof all: $(PROJECT_NAME).sof
lib: $(M_DEPS)
clean: clean:
$(call clean, \ $(call clean, \
@ -113,13 +115,9 @@ clean:
$(HL)$(PROJECT_NAME)$(NC) project) $(HL)$(PROJECT_NAME)$(NC) project)
-rm -Rf ${DIR_NAME} -rm -Rf ${DIR_NAME}
clean-all: clean clean-all: TARGET:=clean
@for lib in $(LIB_DEPS); do \ clean-all: clean $(M_DEPS)
$(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} clean; \ @rm -Rf $(CLEAN_DIRS)
done
@for dir in ${CLEAN_DIRS}; do \
rm -Rf $${dir}; \
done
$(PROJECT_NAME).sof: $(M_DEPS) $(PROJECT_NAME).sof: $(M_DEPS)
-rm -rf $(CLEAN_TARGET) -rm -rf $(CLEAN_TARGET)
@ -128,7 +126,7 @@ $(PROJECT_NAME).sof: $(M_DEPS)
$(PROJECT_NAME)_quartus.log, \ $(PROJECT_NAME)_quartus.log, \
$(HL)$(PROJECT_NAME)$(NC)) $(HL)$(PROJECT_NAME)$(NC))
lib: $(HDL_LIBRARY_PATH)%/.timestamp_intel: TARGET:=intel
@for lib in $(LIB_DEPS); do \ FORCE:
$(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} intel || exit $$?; \ $(HDL_LIBRARY_PATH)%/.timestamp_intel: FORCE
done $(MAKE) -C $(dir $@) $(TARGET) || exit $$?; \

View File

@ -3,7 +3,7 @@
## SPDX short identifier: BSD-1-Clause ## SPDX short identifier: BSD-1-Clause
#################################################################################### ####################################################################################
# Assumes this file is in prpojects/scripts/project-xilinx.mk # Assumes this file is in projects/scripts/project-xilinx.mk
HDL_PROJECT_PATH := $(subst scripts/project-xilinx.mk,,$(lastword $(MAKEFILE_LIST))) HDL_PROJECT_PATH := $(subst scripts/project-xilinx.mk,,$(lastword $(MAKEFILE_LIST)))
HDL_LIBRARY_PATH := $(HDL_PROJECT_PATH)../library/ HDL_LIBRARY_PATH := $(HDL_PROJECT_PATH)../library/
@ -78,7 +78,9 @@ M_DEPS += $(foreach dep,$(LIB_DEPS),$(HDL_LIBRARY_PATH)$(dep)/component.xml)
.PHONY: all lib clean clean-all .PHONY: all lib clean clean-all
all: lib $(PROJECT_NAME).sdk/system_top.xsa all: $(PROJECT_NAME).sdk/system_top.xsa
lib: $(M_DEPS)
clean: clean:
-rm -f reference.dcp -rm -f reference.dcp
@ -87,13 +89,9 @@ clean:
$(HL)$(PROJECT_NAME)$(NC) project) $(HL)$(PROJECT_NAME)$(NC) project)
-rm -Rf ${DIR_NAME} -rm -Rf ${DIR_NAME}
clean-all: clean clean-all: TARGET:=clean
@for lib in $(LIB_DEPS); do \ clean-all: clean $(M_DEPS)
$(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} clean; \ @rm -Rf $(CLEAN_DIRS)
done
@for dir in ${CLEAN_DIRS}; do \
rm -Rf $${dir}; \
done
MODE ?= "default" MODE ?= "default"
@ -115,12 +113,12 @@ $(PROJECT_NAME).sdk/system_top.xsa: $(M_DEPS)
$(PROJECT_NAME)_vivado.log, \ $(PROJECT_NAME)_vivado.log, \
$(HL)$(PROJECT_NAME)$(NC) project) $(HL)$(PROJECT_NAME)$(NC) project)
lib: $(HDL_LIBRARY_PATH)%/component.xml: TARGET:=xilinx
@for lib in $(LIB_DEPS); do \ FORCE:
if [ -n "${REQUIRED_VIVADO_VERSION}" ]; then \ $(HDL_LIBRARY_PATH)%/component.xml: FORCE
$(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} xilinx REQUIRED_VIVADO_VERSION=${REQUIRED_VIVADO_VERSION} || exit $$?; \ flock $(dir $@).lock -c " \
else \ if [ -n \"${REQUIRED_VIVADO_VERSION}\" ]; then \
$(MAKE) -C $(HDL_LIBRARY_PATH)$${lib} xilinx || exit $$?; \ $(MAKE) -C $(dir $@) $(TARGET) REQUIRED_VIVADO_VERSION=${REQUIRED_VIVADO_VERSION}; \
fi; \ else \
done $(MAKE) -C $(dir $@) $(TARGET); \
fi"; exit $$?

View File

@ -24,12 +24,12 @@ ifneq ($(VERBOSE),1)
# $(2): Logfile name # $(2): Logfile name
# $(3): Textual description of the task # $(3): Textual description of the task
define build define build
@echo -n "Building $(strip $(3)) [$(HL)$(CURDIR)/$(strip $(2))$(NC)] ..." @echo $(if $(filter -j%,$(MAKEFLAGS)),,-n) "Building $(strip $(3)) [$(HL)$(CURDIR)/$(strip $(2))$(NC)] ..."
$(strip $(1)) >> $(strip $(2)) 2>&1; \ $(strip $(1)) >> $(strip $(2)) 2>&1; \
(ERR=$$?; if [ $$ERR = 0 ]; then \ (ERR=$$?; if [ $$ERR = 0 ]; then \
echo " $(GREEN)OK$(NC)"; \ echo "$(if $(filter -j%,$(MAKEFLAGS)),Build $(strip $(3)) [$(HL)$(CURDIR)/$(strip $(2))$(NC)]) $(GREEN)OK$(NC)"; \
else \ else \
echo " $(RED)FAILED$(NC)"; \ echo "$(if $(filter -j%,$(MAKEFLAGS)),Build $(strip $(3)) [$(HL)$(CURDIR)/$(strip $(2))$(NC)]) $(RED)FAILED$(NC)"; \
echo "For details see $(HL)$(CURDIR)/$(strip $(2))$(NC)"; \ echo "For details see $(HL)$(CURDIR)/$(strip $(2))$(NC)"; \
echo ""; \ echo ""; \
fi; exit $$ERR) fi; exit $$ERR)