cmake: zephyr modules: sanitize all module name when used as variable

The introduction of Zephyr module glue code in the Zephyr repository
introduces a Kconfig variable in the form of:
`config ZEPHYR_<MODULE_NAME>_MODULE`.

All Kconfig variables go into `autoconf.h`, therefore it is necessary
to sanitize the Kconfig variable, so that it does not contain special
characters. To ensure consistent variable name, then the module name
will be sanitized in all variable use in both Kconfig and CMake.
The sanitization is done be replacing all special characters with an
underscore, `_`.

Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit is contained in:
Torsten Rasmussen 2021-01-19 12:01:38 +01:00 committed by Carles Cufí
parent 0ce0f63036
commit 3d88083bf1
8 changed files with 68 additions and 12 deletions

View file

@ -454,7 +454,7 @@ foreach(module_name ${ZEPHYR_MODULE_NAMES})
# this binary_dir is created but stays empty. Object files land in
# the main binary dir instead.
# https://cmake.org/pipermail/cmake/2019-June/069547.html
string(TOUPPER ${module_name} MODULE_NAME_UPPER)
zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name})
if(NOT ${ZEPHYR_${MODULE_NAME_UPPER}_CMAKE_DIR} STREQUAL "")
set(ZEPHYR_CURRENT_MODULE_DIR ${ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR})
set(ZEPHYR_CURRENT_CMAKE_DIR ${ZEPHYR_${MODULE_NAME_UPPER}_CMAKE_DIR})

View file

@ -1960,6 +1960,47 @@ Relative paths are only allowed with `-D${ARGV1}=<path>`")
endif()
endfunction()
# Usage:
# zephyr_string(<mode> <out-var> <input> ...)
#
# Zephyr string function extension.
# This function extends the CMake string function by providing additional
# manipulation arguments to CMake string.
#
# SANITIZE: Ensure that the output string does not contain any special
# characters. Special characters, such as -, +, =, $, etc. are
# converted to underscores '_'.
#
# SANITIZE TOUPPER: Ensure that the output string does not contain any special
# characters. Special characters, such as -, +, =, $, etc. are
# converted to underscores '_'.
# The sanitized string will be returned in UPPER case.
#
# returns the updated string
function(zephyr_string)
set(options SANITIZE TOUPPER)
cmake_parse_arguments(ZEPHYR_STRING "${options}" "" "" ${ARGN})
if (NOT ZEPHYR_STRING_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Function zephyr_string() called without a return variable")
endif()
list(GET ZEPHYR_STRING_UNPARSED_ARGUMENTS 0 return_arg)
list(REMOVE_AT ZEPHYR_STRING_UNPARSED_ARGUMENTS 0)
list(JOIN ZEPHYR_STRING_UNPARSED_ARGUMENTS "" work_string)
if(ZEPHYR_STRING_SANITIZE)
string(REGEX REPLACE "[^a-zA-Z0-9_]" "_" work_string ${work_string})
endif()
if(ZEPHYR_STRING_TOUPPER)
string(TOUPPER ${work_string} work_string)
endif()
set(${return_arg} ${work_string} PARENT_SCOPE)
endfunction()
# Usage:
# zephyr_check_cache(<variable> [REQUIRED])
#

View file

@ -69,7 +69,7 @@ string(REPLACE ";" "?" DTS_ROOT_BINDINGS "${DTS_ROOT_BINDINGS}")
# This allows Kconfig files to refer relative from a modules root as:
# source "$(ZEPHYR_FOO_MODULE_DIR)/Kconfig"
foreach(module_name ${ZEPHYR_MODULE_NAMES})
string(TOUPPER ${module_name} MODULE_NAME_UPPER)
zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name})
list(APPEND
ZEPHYR_KCONFIG_MODULES_DIR
"ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR=${ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR}"

View file

@ -104,7 +104,7 @@ if(WEST OR ZEPHYR_MODULES)
list(APPEND ZEPHYR_MODULE_NAMES ${module_name})
string(TOUPPER ${module_name} MODULE_NAME_UPPER)
zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name})
if(NOT ${MODULE_NAME_UPPER} STREQUAL CURRENT)
set(ZEPHYR_${MODULE_NAME_UPPER}_MODULE_DIR ${module_path})
set(ZEPHYR_${MODULE_NAME_UPPER}_CMAKE_DIR ${cmake_path})

View file

@ -421,6 +421,13 @@ CMake variable ``ZEPHYR_<MODULE_NAME>_MODULE_DIR`` and the variable
``ZEPHYR_<MODULE_NAME>_CMAKE_DIR`` holds the location of the directory
containing the module's :file:`CMakeLists.txt` file.
.. note::
When used for CMake and Kconfig variables, all letters in module names are
converted to uppercase and all non-alphanumeric characters are converted
to underscores (_).
As example, the module ``foo-bar`` must be referred to as
``ZEPHYR_FOO_BAR_MODULE_DIR`` in CMake and Kconfig.
Here is an example for the Zephyr module ``foo``:
.. code-block:: yaml

View file

@ -5,7 +5,8 @@ file(GLOB cmake_modules "${CMAKE_CURRENT_LIST_DIR}/*/CMakeLists.txt")
foreach(module ${cmake_modules})
get_filename_component(module_dir ${module} DIRECTORY)
get_filename_component(module_name ${module_dir} NAME)
string(TOUPPER ${module_name} MODULE_NAME_UPPER)
zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name})
set(ZEPHYR_${MODULE_NAME_UPPER}_CMAKE_DIR ${module_dir})
endforeach()
@ -14,6 +15,7 @@ file(GLOB kconfig_modules "${CMAKE_CURRENT_LIST_DIR}/*/Kconfig")
foreach(module ${kconfig_modules})
get_filename_component(module_dir ${module} DIRECTORY)
get_filename_component(module_name ${module_dir} NAME)
string(TOUPPER ${module_name} MODULE_NAME_UPPER)
zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name})
set(ZEPHYR_${MODULE_NAME_UPPER}_KCONFIG ${module_dir}/Kconfig)
endforeach()

View file

@ -262,7 +262,7 @@ class KconfigCheck(ComplianceTest):
with open(modules_file, 'w') as fp_module_file:
for module in modules:
fp_module_file.write("ZEPHYR_{}_KCONFIG = {}\n".format(
module.upper(),
re.sub('[^a-zA-Z0-9]', '_', module).upper(),
modules_dir + '/' + module + '/Kconfig'
))
fp_module_file.write(content)

View file

@ -19,6 +19,7 @@ maintained in modules in addition to what is available in the main Zephyr tree.
import argparse
import os
import re
import sys
import yaml
import pykwalify.core
@ -128,11 +129,13 @@ def process_module(module):
.format(module_yml.as_posix(), e))
meta['name'] = meta.get('name', module_path.name)
meta['name-sanitized'] = re.sub('[^a-zA-Z0-9]', '_', meta['name'])
return meta
if Path(module_path.joinpath('zephyr/CMakeLists.txt')).is_file() and \
Path(module_path.joinpath('zephyr/Kconfig')).is_file():
return {'name': module_path.name,
'name-sanitized': re.sub('[^a-zA-Z0-9]', '_', module_path.name),
'build': {'cmake': 'zephyr', 'kconfig': 'zephyr/Kconfig'}}
return None
@ -148,7 +151,7 @@ def process_cmake(module, meta):
return('\"{}\":\"{}\":\"{}\"\n'
.format(meta['name'],
module_path.as_posix(),
"${ZEPHYR_" + meta['name'].upper() + "_CMAKE_DIR}"))
"${ZEPHYR_" + meta['name-sanitized'].upper() + "_CMAKE_DIR}"))
cmake_setting = section.get('cmake', None)
if not validate_setting(cmake_setting, module, 'CMakeLists.txt'):
@ -185,11 +188,14 @@ def process_settings(module, meta):
return out_text
def kconfig_snippet(name, path, kconfig_file=None):
def kconfig_snippet(meta, path, kconfig_file=None):
name = meta['name']
name_sanitized = meta['name-sanitized']
snippet = (f'menu "{name} ({path})"',
f'osource "{kconfig_file.resolve().as_posix()}"' if kconfig_file
else f'osource "$(ZEPHYR_{name.upper()}_KCONFIG)"',
f'config ZEPHYR_{name.upper()}_MODULE',
else f'osource "$(ZEPHYR_{name_sanitized.upper()}_KCONFIG)"',
f'config ZEPHYR_{name_sanitized.upper()}_MODULE',
' bool',
' default y',
'endmenu\n')
@ -202,7 +208,7 @@ def process_kconfig(module, meta):
module_yml = module_path.joinpath('zephyr/module.yml')
kconfig_extern = section.get('kconfig-ext', False)
if kconfig_extern:
return kconfig_snippet(meta['name'], module_path)
return kconfig_snippet(meta, module_path)
kconfig_setting = section.get('kconfig', None)
if not validate_setting(kconfig_setting, module):
@ -212,7 +218,7 @@ def process_kconfig(module, meta):
kconfig_file = os.path.join(module, kconfig_setting or 'zephyr/Kconfig')
if os.path.isfile(kconfig_file):
return kconfig_snippet(meta['name'], module_path, Path(kconfig_file))
return kconfig_snippet(meta, module_path, Path(kconfig_file))
else:
return ""