Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions core/include/kernel_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,84 @@
*/
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)]))

/**
* @def IS_ACTIVE(macro)
* @brief Allows to verify a macro definition outside the preprocessor.
*
* @details This macro is based on Linux's clever 'IS_BUILTIN'
* (https://github.com/torvalds/linux/blob/master/include/linux/kconfig.h).
* It takes a @p macro value that may be defined to 1 or not even
* defined (e.g. FEATURE_FOO) and then expands it to an expression
* that can be used in C code, either 1 or 0.
*
* The advantage of using this is that the compiler sees all the
* code, so checks can be performed, sections that would not be
* executed are removed during optimization. For example:
* ```
* if (IS_ACTIVE(FEATURE_FOO)) {
* do_something();
* }
* ```
* @param[in] macro Macro to evaluate
* @returns 1 if the macro is defined to 1
* @returns 0 if the macro is not defined, of if it is defined to something
* else than 1.
*
* @note This should only be used when macros are defined as 1, it will
* not work if the macro value is, for example, (1) or 1U.
*
* @note Although this may seem to work similarly to the preprocessor's
* 'defined', it is not entirely equal. If the given macro has
* been defined with no value, this will expand to 0. Also note
* that this is intended to be used with 'boolean' macros that act
* as switches, and usually will be defined as 1 or not defined.
*/
#define IS_ACTIVE(macro) __is_active(macro)

/**
* @def IS_USED(module)
* @brief Checks whether a module is being used or not. Can be used in C
* conditionals.
*
* @param[in] module Module to check
* @returns 1 if the module is being used
* @returns 0 if the module is not being used
*/
#define IS_USED(module) IS_ACTIVE(module)

/**
* @cond INTERNAL
*/
/* Here a prefix "__PREFIX_WHEN_" is added to the macro. So if it was a 1 we
* have "__PREFIX_WHEN_1", and if it was not defined we have "__PREFIX_WHEN_".
*/
#define __is_active(val) ___is_active(__PREFIX_WHEN_##val)

/* With this placeholder we turn the original value into two arguments when the
* original value was defined as 1 (note the comma).
*/
#define __PREFIX_WHEN_1 0,

/* Here we add two extra arguments, that way the next macro can accept varargs.
*
* If the original macro was defined as 1, this will have three arguments
* (__take_second_arg(0, 1, 0, 0)), otherwise it will have two
* (__take_second_arg(__PREFIX_WHEN_ 1, 0, 0)). The third zero is there just to
* be compliant with C99, which states that when a function-like macro ends
* with ellipsis (...) it should be called with at least one argument for the
* variable list.
*/
#define ___is_active(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0, 0)

/* Finally, we just always take the second argument, which will be either 1
* (when three arguments are passed, i.e. macro was defined as 1) or 0 (when
* only two arguments are passed).
*/
#define __take_second_arg(__ignored, val, ...) val
/**
* @endcond
*/

#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 3 additions & 0 deletions makefiles/modules.inc.mk
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
_ALLMODULES = $(sort $(USEMODULE) $(USEPKG))

# Define MODULE_MODULE_NAME preprocessor macros for all modules.
# Note: Some modules may be using the 'IS_USED' macro, defined in
# kernel_defines.h, please refer to its documentation if you change the way
# module macros are defined.
ED = $(addprefix MODULE_,$(_ALLMODULES))
# EXTDEFINES will be put in CFLAGS_WITH_MACROS
EXTDEFINES = $(addprefix -D,$(call uppercase_and_underscore,$(ED)))
Expand Down