]> granicus.if.org Git - esp-idf/commitdiff
Add cleaner way to conditionally compile files
authorJeroen Domburg <jeroen@espressif.com>
Tue, 25 Apr 2017 07:36:45 +0000 (15:36 +0800)
committerJeroen Domburg <jeroen@espressif.com>
Thu, 25 May 2017 08:12:27 +0000 (16:12 +0800)
docs/api-guides/build-system.rst
make/common.mk
make/component_wrapper.mk

index aa4a670326ebe8897101b2cbfafd84af3262e1fd..9c16a5507cf4d38fe610c96f55088429501f217a 100644 (file)
@@ -396,7 +396,8 @@ Adding conditional configuration
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 The configuration system can be used to conditionally compile some files
-depending on the options selected in ``make menuconfig``:
+depending on the options selected in ``make menuconfig``. For this, ESP-IDF
+has the compile_only_if and compile_only_if_not macros:
 
 ``Kconfig``::
 
@@ -407,14 +408,56 @@ depending on the options selected in ``make menuconfig``:
 
 ``component.mk``::
 
-    COMPONENT_OBJS := foo_a.o foo_b.o
+    $(call compile_only_if,$(CONFIG_FOO_ENABLE_BAR),bar.o)
 
-    ifdef CONFIG_FOO_BAR
-    COMPONENT_OBJS += foo_bar.o foo_bar_interface.o
-    endif
 
-See the `GNU Make Manual` for conditional syntax that can be used use in makefiles.
+As can be seen in the example, the ``compile_only_if`` macro takes a condition and a 
+list of object files as parameters. If the condition is true (in this case: if the
+BAR feature is enabled in menuconfig) the object files (in this case: bar.o) will
+always be compiled. The opposite goes as well: if the condition is not true, bar.o 
+will never be compiled. ``compile_only_if_not`` does the opposite: compile if the 
+condition is false, not compile if the condition is true.
 
+This can also be used to select or stub out an implementation, as such:
+
+``Kconfig``::
+
+    config ENABLE_LCD_OUTPUT
+        bool "Enable LCD output."
+        help
+            Select this if your board has a LCD.
+
+    config ENABLE_LCD_CONSOLE
+        bool "Output console text to LCD"
+        depends on ENABLE_LCD_OUTPUT
+        help
+            Select this to output debugging output to the lcd
+
+    config ENABLE_LCD_PLOT
+        bool "Output temperature plots to LCD"
+        depends on ENABLE_LCD_OUTPUT
+        help
+            Select this to output temperature plots
+
+
+``component.mk``::
+
+    # If LCD is enabled, compile interface to it, otherwise compile dummy interface
+    $(call compile_only_if,$(CONFIG_ENABLE_LCD_OUTPUT),lcd-real.o lcd-spi.o)
+    $(call compile_only_if_not,$(CONFIG_ENABLE_LCD_OUTPUT),lcd-dummy.o)
+
+    #We need font if either console or plot is enabled
+    $(call compile_only_if,$(or $(CONFIG_ENABLE_LCD_CONSOLE),$(CONFIG_ENABLE_LCD_PLOT)), font.o)
+
+Note the use of the Make 'or' function to include the font file. Other substitution functions,
+like 'and' and 'if' will also work here. Variables that do not come from menuconfig can also 
+be used: ESP-IDF uses the default Make policy of judging a variable which is empty or contains 
+only whitespace to be false while a variable with any non-whitespace in it is true.
+
+(Note: Older versions of this document advised conditionally adding object file names to
+``COMPONENT_OBJS``. While this still is possible, this will only work when all object 
+files for a component are named explicitely, and will not clean up deselected object files
+in a ``make clean`` pass.)
 
 Source Code Generation
 ^^^^^^^^^^^^^^^^^^^^^^
index 24aebb4cce216b266c77215f4e3664d79881fc10..82652e63d75430a687bb507a6888b5c466357d87 100644 (file)
@@ -73,3 +73,11 @@ endef
 define prereq_if_explicit
 $(filter $(1),$(MAKECMDGOALS))
 endef
+
+# macro to kill duplicate items in a list without messing up the sort order of the list.
+# Will only keep the unique items; if there are non-unique items in the list, it will remove
+# the later recurring ones so only the first one remains.
+# Copied from http://stackoverflow.com/questions/16144115/makefile-remove-duplicate-words-without-sorting
+define uniq
+$(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
+endef
index 87c05479add2cfa039eeeec3c286a40454442835..30269b60175f070e004adb3d7e395cb86396f53e 100644 (file)
@@ -46,6 +46,23 @@ COMPONENT_EMBED_TXTFILES ?=
 COMPONENT_ADD_INCLUDEDIRS = include
 COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME)
 
+# Define optional compiling macros
+define compile_exclude 
+COMPONENT_OBJEXCLUDE += $(1)
+endef
+
+define compile_include
+COMPONENT_OBJINCLUDE += $(1)
+endef
+
+define compile_only_if
+$(eval $(if $(1), $(call compile_include, $(2)), $(call compile_exclude, $(2))))
+endef
+
+define compile_only_if_not 
+$(eval $(if $(1), $(call compile_exclude, $(2)), $(call compile_include, $(2))))
+endef
+
 
 ################################################################################
 # 2) Include the component.mk for the specific component (COMPONENT_MAKEFILE) to
@@ -68,7 +85,16 @@ COMPONENT_OBJS += $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.cpp,%.o
 COMPONENT_OBJS += $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.S,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.S)))
 # Make relative by removing COMPONENT_PATH from all found object paths
 COMPONENT_OBJS := $(patsubst $(COMPONENT_PATH)/%,%,$(COMPONENT_OBJS))
+else
+# Add in components defined by conditional compiling macros
+COMPONENT_OBJS += $(COMPONENT_OBJINCLUDE)
 endif
+# Remove items disabled by optional compilation
+COMPONENT_OBJS := $(foreach obj,$(COMPONENT_OBJS),$(if $(filter $(realpath $(obj)),$(realpath $(COMPONENT_OBJEXCLUDE))), ,$(obj)))
+
+# Remove duplicates
+COMPONENT_OBJS := $(call uniq,$(COMPONENT_OBJS))
+
 
 # Object files with embedded binaries to add to the component library
 # Correspond to the files named in COMPONENT_EMBED_FILES & COMPONENT_EMBED_TXTFILES
@@ -142,7 +168,7 @@ endif
 
 # If COMPONENT_OWNCLEANTARGET is not set, define a phony clean target
 ifndef COMPONENT_OWNCLEANTARGET
-CLEAN_FILES = $(COMPONENT_LIBRARY) $(COMPONENT_OBJS) $(COMPONENT_OBJS:.o=.d) $(COMPONENT_EMBED_OBJS) $(COMPONENT_EXTRA_CLEAN) component_project_vars.mk
+CLEAN_FILES := $(COMPONENT_LIBRARY) $(COMPONENT_OBJS) $(COMPONENT_OBJS:.o=.d) $(COMPONENT_OBJEXCLUDE) $(COMPONENT_OBJEXCLUDE:.o=.d) $(COMPONENT_EMBED_OBJS) $(COMPONENT_EXTRA_CLEAN) component_project_vars.mk
 .PHONY: clean
 clean:
        $(summary) RM $(CLEAN_FILES)