# List of available make goals: # # all Default target, builds the project # clean Clean up the project # rebuild Rebuild the project # # doc Build the documentation # cleandoc Clean up the documentation # rebuilddoc Rebuild the documentation # # # Copyright (c) 2009 - 2013 Atmel Corporation. All rights reserved. # # \asf_license_start # # \page License # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # 3. The name of Atmel may not be used to endorse or promote products derived # from this software without specific prior written permission. # # 4. This software may only be redistributed and used in connection with an # Atmel microcontroller product. # # THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE # EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # \asf_license_stop # # Include the config.mk file from the current working path, e.g., where the # user called make. include config.mk # Tool to use to generate documentation from the source code DOCGEN ?= doxygen # Look for source files relative to the top-level source directory VPATH := $(PRJ_PATH) # Output target file target := $(TARGET) # Output project name (target name minus suffix) project := $(basename $(target)) # Output target file (typically ELF or static library) ifeq ($(suffix $(target)),.a) target_type := lib else ifeq ($(suffix $(target)),.elf) target_type := elf else $(error "Target type $(target_type) is not supported") endif endif # Allow override of operating system detection. The user can add OS=Linux or # OS=Windows on the command line to explicit set the host OS. # # This allows to work around broken uname utility on certain systems. ifdef OS ifeq ($(strip $(OS)), Linux) os_type := Linux endif ifeq ($(strip $(OS)), Windows) os_type := windows32_64 endif endif os_type ?= $(strip $(shell uname)) ifeq ($(os_type),windows32) os := Windows else ifeq ($(os_type),windows64) os := Windows else ifeq ($(os_type),windows32_64) os ?= Windows else ifeq ($(os_type),) os := Windows else # Default to Linux style operating system. Both Cygwin and mingw are fully # compatible (for this Makefile) with Linux. os := Linux endif endif endif endif # Output documentation directory and configuration file. docdir := ../doxygen/html doccfg := ../doxygen/doxyfile.doxygen CROSS ?= avr- AR := $(CROSS)ar AS := $(CROSS)as CC := $(CROSS)gcc CPP := $(CROSS)gcc -E CXX := $(CROSS)g++ LD := $(CROSS)gcc NM := $(CROSS)nm OBJCOPY := $(CROSS)objcopy OBJDUMP := $(CROSS)objdump SIZE := $(CROSS)size RM := rm ifeq ($(os),Windows) RMDIR := rmdir /S /Q else RMDIR := rmdir -p --ignore-fail-on-non-empty endif # On Windows, we need to override the shell to force the use of cmd.exe ifeq ($(os),Windows) SHELL := cmd endif # Strings for beautifying output MSG_CLEAN_FILES = "RM *.o *.d" MSG_CLEAN_DIRS = "RMDIR $(strip $(clean-dirs))" MSG_CLEAN_DOC = "RMDIR $(docdir)" MSG_MKDIR = "MKDIR $(dir $@)" MSG_INFO = "INFO " MSG_PREBUILD = "PREBUILD $(PREBUILD_CMD)" MSG_POSTBUILD = "POSTBUILD $(POSTBUILD_CMD)" MSG_ARCHIVING = "AR $@" MSG_ASSEMBLING = "AS $@" MSG_BINARY_IMAGE = "OBJCOPY $@" MSG_COMPILING = "CC $@" MSG_COMPILING_CXX = "CXX $@" MSG_EEPROM_IMAGE = "OBJCOPY $@" MSG_EXTENDED_LISTING = "OBJDUMP $@" MSG_IHEX_IMAGE = "OBJCOPY $@" MSG_LINKING = "LN $@" MSG_PREPROCESSING = "CPP $@" MSG_SIZE = "SIZE $@" MSG_SYMBOL_TABLE = "NM $@" MSG_GENERATING_DOC = "DOXYGEN $(docdir)" # Don't use make's built-in rules and variables MAKEFLAGS += -rR # Don't print 'Entering directory ...' MAKEFLAGS += --no-print-directory # Function for reversing the order of a list reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1)) # Hide command output by default, but allow the user to override this # by adding V=1 on the command line. # # This is inspired by the Kbuild system used by the Linux kernel. ifdef V ifeq ("$(origin V)", "command line") VERBOSE = $(V) endif endif ifndef VERBOSE VERBOSE = 0 endif ifeq ($(VERBOSE), 1) Q = else Q = @ endif arflags-gnu-y := $(ARFLAGS) asflags-gnu-y := $(ASFLAGS) cflags-gnu-y := $(CFLAGS) cxxflags-gnu-y := $(CXXFLAGS) cppflags-gnu-y := $(CPPFLAGS) cpuflags-gnu-y := dbgflags-gnu-y := $(DBGFLAGS) libflags-gnu-y := $(foreach LIB,$(LIBS),-l$(LIB)) ldflags-gnu-y := $(LDFLAGS) flashflags-gnu-y := $(FLASHFLAGS) eepromflags-gnu-y := $(EEPROMFLAGS) clean-files := clean-dirs := clean-files += $(wildcard $(target) $(project).map) clean-files += $(wildcard $(project).hex $(project).eep) clean-files += $(wildcard $(project).lss $(project).sym) clean-files += $(wildcard $(build)) # Use pipes instead of temporary files for communication between processes cflags-gnu-y += -pipe asflags-gnu-y += -pipe ldflags-gnu-y += -pipe # Archiver flags. arflags-gnu-y += rcs # Always enable warnings. And be very careful about implicit # declarations. cflags-gnu-y += -Wall -Wstrict-prototypes -Wmissing-prototypes cflags-gnu-y += -Werror-implicit-function-declaration cxxflags-gnu-y += -Wall # IAR doesn't allow arithmetic on void pointers, so warn about that. cflags-gnu-y += -Wpointer-arith cxxflags-gnu-y += -Wpointer-arith # Preprocessor flags. cppflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),-I$(INC)) asflags-gnu-y += $(foreach INC,$(addprefix $(PRJ_PATH)/,$(INC_PATH)),'-Wa,-I$(INC)') # CPU specific flags. cpuflags-gnu-y += -mmcu=$(MCU) # Dependency file flags. depflags = -MD -MP -MQ $@ # Debug specific flags. ifdef BUILD_DEBUG_LEVEL dbgflags-gnu-y += -g$(BUILD_DEBUG_LEVEL) else dbgflags-gnu-y += -gdwarf-2 endif # Optimization specific flags. ifdef BUILD_OPTIMIZATION optflags-gnu-y = -O$(BUILD_OPTIMIZATION) else optflags-gnu-y = $(OPTIMIZATION) endif # Relax compilation and linking. cflags-gnu-y += -mrelax cxxflags-gnu-y += -mrelax asflags-gnu-y += -mrelax ldflags-gnu-y += -Wl,--relax # Always preprocess assembler files. asflags-gnu-y += -x assembler-with-cpp # Compile C files using the GNU99 standard. cflags-gnu-y += -std=gnu99 # Compile C++ files using the GNU++98 standard. cxxflags-gnu-y += -std=gnu++98 # Use unsigned character type when compiling. cflags-gnu-y += -funsigned-char cxxflags-gnu-y += -funsigned-char # Don't use strict aliasing (very common in embedded applications). cflags-gnu-y += -fno-strict-aliasing cxxflags-gnu-y += -fno-strict-aliasing # Separate each function and data into its own separate section to allow # garbage collection of unused sections. cflags-gnu-y += -ffunction-sections -fdata-sections cxxflags-gnu-y += -ffunction-sections -fdata-sections # Garbage collect unreferred sections when linking. ldflags-gnu-y += -Wl,--gc-sections # Output a link map file and a cross reference table ldflags-gnu-y += -Wl,-Map=$(project).map,--cref # Add library search paths relative to the top level directory. ldflags-gnu-y += $(foreach _LIB_PATH,$(addprefix $(PRJ_PATH)/,$(LIB_PATH)),-L$(_LIB_PATH)) a_flags = $(cpuflags-gnu-y) $(depflags) $(cppflags-gnu-y) $(asflags-gnu-y) -D__ASSEMBLY__ c_flags = $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cflags-gnu-y) cxx_flags= $(cpuflags-gnu-y) $(dbgflags-gnu-y) $(depflags) $(optflags-gnu-y) $(cppflags-gnu-y) $(cxxflags-gnu-y) l_flags = $(cpuflags-gnu-y) $(optflags-gnu-y) $(ldflags-gnu-y) ar_flags = $(arflags-gnu-y) # Intel Hex file production flags flashflags-gnu-y += -R .eeprom -R .usb_descriptor_table # Eeprom file production flags eepromflags-gnu-y += -j .eeprom eepromflags-gnu-y += --set-section-flags=.eeprom="alloc,load" eepromflags-gnu-y += --change-section-lma .eeprom=0 # Source files list and part informations must already be included before # running this makefile # If a custom build directory is specified, use it -- force trailing / in directory name. ifdef BUILD_DIR build-dir := $(dir $(BUILD_DIR))$(if $(notdir $(BUILD_DIR)),$(notdir $(BUILD_DIR))/) else build-dir = endif # Create object files list from source files list. obj-y := $(addprefix $(build-dir), $(addsuffix .o,$(basename $(CSRCS) $(ASSRCS)))) # Create dependency files list from source files list. dep-files := $(wildcard $(foreach f,$(obj-y),$(basename $(f)).d)) clean-files += $(wildcard $(obj-y)) clean-files += $(dep-files) clean-dirs += $(call reverse,$(sort $(wildcard $(dir $(obj-y))))) # Default target. .PHONY: all ifeq ($(target_type),lib) all: $(target) $(project).lss $(project).sym else ifeq ($(target_type),elf) all: prebuild $(target) $(project).lss $(project).sym $(project).hex $(project).bin postbuild endif endif prebuild: ifneq ($(strip $(PREBUILD_CMD)),) @echo $(MSG_PREBUILD) $(Q)$(PREBUILD_CMD) endif postbuild: ifneq ($(strip $(POSTBUILD_CMD)),) @echo $(MSG_POSTBUILD) $(Q)$(POSTBUILD_CMD) endif # Clean up the project. .PHONY: clean clean: @$(if $(strip $(clean-files)),echo $(MSG_CLEAN_FILES)) $(if $(strip $(clean-files)),$(Q)$(RM) $(clean-files),) @$(if $(strip $(clean-dirs)),echo $(MSG_CLEAN_DIRS)) # Remove created directories, and make sure we only remove existing # directories, since recursive rmdir might help us a bit on the way. ifeq ($(os),Windows) $(Q)$(if $(strip $(clean-dirs)), \ $(RMDIR) $(strip $(subst /,\,$(clean-dirs)))) else $(Q)$(if $(strip $(clean-dirs)), \ for directory in $(strip $(clean-dirs)); do \ if [ -d "$$directory" ]; then \ $(RMDIR) $$directory; \ fi \ done \ ) endif # Rebuild the project. .PHONY: rebuild rebuild: clean all .PHONY: objfiles objfiles: $(obj-y) # Create object files from C source files. $(build-dir)%.o: %.c $(MAKEFILE_PATH) config.mk $(Q)test -d $(dir $@) || echo $(MSG_MKDIR) ifeq ($(os),Windows) $(Q)test -d $(patsubst %/,%,$(dir $@)) || mkdir $(subst /,\,$(dir $@)) else $(Q)test -d $(dir $@) || mkdir -p $(dir $@) endif @echo $(MSG_COMPILING) $(Q)$(CC) $(c_flags) -c $< -o $@ # Create object files from C++ source files. $(build-dir)%.o: %.cpp $(MAKEFILE_PATH) config.mk $(Q)test -d $(dir $@) || echo $(MSG_MKDIR) ifeq ($(os),Windows) $(Q)test -d $(patsubst %/,%,$(dir $@)) || mkdir $(subst /,\,$(dir $@)) else $(Q)test -d $(dir $@) || mkdir -p $(dir $@) endif @echo $(MSG_COMPILING_CXX) $(Q)$(CXX) $(cxx_flags) -c $< -o $@ # Preprocess and assemble: create object files from assembler source files. $(build-dir)%.o: %.s $(MAKEFILE_PATH) config.mk $(Q)test -d $(dir $@) || echo $(MSG_MKDIR) ifeq ($(os),Windows) $(Q)test -d $(patsubst %/,%,$(dir $@)) || mkdir $(subst /,\,$(dir $@)) else $(Q)test -d $(dir $@) || mkdir -p $(dir $@) endif @echo $(MSG_ASSEMBLING) $(Q)$(CC) $(a_flags) -c $< -o $@ # Preprocess and assemble: create object files from assembler source files. $(build-dir)%.o: %.S $(MAKEFILE_PATH) config.mk $(Q)test -d $(dir $@) || echo $(MSG_MKDIR) ifeq ($(os),Windows) $(Q)test -d $(patsubst %/,%,$(dir $@)) || mkdir $(subst /,\,$(dir $@)) else $(Q)test -d $(dir $@) || mkdir -p $(dir $@) endif @echo $(MSG_ASSEMBLING) $(Q)$(CC) $(a_flags) -c $< -o $@ # Include all dependency files to add depedency to all header files in use. include $(dep-files) ifeq ($(target_type),lib) # Archive object files into an archive $(target): $(MAKEFILE_PATH) config.mk $(obj-y) @echo $(MSG_ARCHIVING) $(Q)$(AR) $(ar_flags) $@ $(obj-y) @echo $(MSG_SIZE) $(Q)$(SIZE) -Bxt $@ else ifeq ($(target_type),elf) # Link the object files into an ELF file. Also make sure the target is rebuilt # if the common Makefile.avr.in or project config.mk is changed. $(target): $(MAKEFILE_PATH) config.mk $(obj-y) @echo $(MSG_LINKING) $(Q)$(LD) $(l_flags) $(obj-y) $(libflags-gnu-y) -o $@ @echo $(MSG_SIZE) $(Q)$(SIZE) -Ax $@ $(Q)$(SIZE) -Bx $@ endif endif # Create extended function listing from target output file. %.lss: $(target) @echo $(MSG_EXTENDED_LISTING) $(Q)$(OBJDUMP) -h -S $< > $@ # Create symbol table from target output file. %.sym: $(target) @echo $(MSG_SYMBOL_TABLE) $(Q)$(NM) -n $< > $@ # Create Intel HEX image from ELF output file. %.hex: $(target) @echo $(MSG_IHEX_IMAGE) $(Q)$(OBJCOPY) -O ihex $(flashflags-gnu-y) $< $@ # Create EEPROM Intel HEX image from ELF output file. %.eep: $(target) @echo $(MSG_EEPROM_IMAGE) $(Q)$(OBJCOPY) $(eepromflags-gnu-y) -O ihex $< $@ || exit 0 # Create binary image from ELF output file. %.bin: $(target) @echo $(MSG_BINARY_IMAGE) $(Q)$(OBJCOPY) -O binary $< $@ # Provide information about the detected host operating system. .SECONDARY: info-os info-os: @echo $(MSG_INFO)$(os) build host detected # Build Doxygen generated documentation. .PHONY: doc doc: @echo $(MSG_GENERATING_DOC) $(Q)cd $(dir $(doccfg)) && $(DOCGEN) $(notdir $(doccfg)) # Clean Doxygen generated documentation. .PHONY: cleandoc cleandoc: @$(if $(wildcard $(docdir)),echo $(MSG_CLEAN_DOC)) $(Q)$(if $(wildcard $(docdir)),$(RM) --recursive $(docdir)) # Rebuild the Doxygen generated documentation. .PHONY: rebuilddoc rebuilddoc: cleandoc doc