mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #1957 from mbedmicro/config_headers
Configuration in header files - step 1pull/1959/head
commit
1e18ea230a
|
@ -232,8 +232,8 @@ def build_project(src_path, build_path, target, toolchain_name,
|
|||
prev_features = features
|
||||
config.validate_config()
|
||||
|
||||
# And add the configuration macros to the toolchain
|
||||
toolchain.add_macros(config.get_config_data_macros())
|
||||
# Set the toolchain's config header with the config data
|
||||
toolchain.set_config_header_content(config.get_config_data_header())
|
||||
|
||||
# Compile Sources
|
||||
objects = toolchain.compile_sources(resources, build_path, resources.inc_dirs)
|
||||
|
@ -391,8 +391,8 @@ def build_library(src_paths, build_path, target, toolchain_name,
|
|||
prev_features = features
|
||||
config.validate_config()
|
||||
|
||||
# And add the configuration macros to the toolchain
|
||||
toolchain.add_macros(config.get_config_data_macros())
|
||||
# Set the toolchain's config header with the config data
|
||||
toolchain.set_config_header_content(config.get_config_data_header())
|
||||
|
||||
# Copy headers, objects and static libraries - all files needed for static lib
|
||||
toolchain.copy_files(resources.headers, build_path, resources=resources)
|
||||
|
|
|
@ -132,8 +132,10 @@ class ConfigMacro:
|
|||
if len(tmp) != 2:
|
||||
raise ValueError("Invalid macro definition '%s' in '%s'" % (name, self.defined_by))
|
||||
self.macro_name = tmp[0]
|
||||
self.macro_value = tmp[1]
|
||||
else:
|
||||
self.macro_name = name
|
||||
self.macro_value = None
|
||||
|
||||
# 'Config' implements the mbed configuration mechanism
|
||||
class Config:
|
||||
|
@ -343,13 +345,13 @@ class Config:
|
|||
|
||||
# Return the configuration data in two parts:
|
||||
# - params: a dictionary with (name, ConfigParam) entries
|
||||
# - macros: the list of macros defined with "macros" in libraries and in the application
|
||||
# - macros: the list of macros defined with "macros" in libraries and in the application (as ConfigMacro instances)
|
||||
def get_config_data(self):
|
||||
all_params = self.get_target_config_data()
|
||||
lib_params, macros = self.get_lib_config_data()
|
||||
all_params.update(lib_params)
|
||||
self.get_app_config_data(all_params, macros)
|
||||
return all_params, [m.name for m in macros.values()]
|
||||
return all_params, macros
|
||||
|
||||
# Helper: verify if there are any required parameters without a value in 'params'
|
||||
def _check_required_parameters(self, params):
|
||||
|
@ -363,11 +365,17 @@ class Config:
|
|||
def parameters_to_macros(params):
|
||||
return ['%s=%s' % (m.macro_name, m.value) for m in params.values() if m.value is not None]
|
||||
|
||||
# Return the macro definitions generated for a dictionary of ConfigMacros (as returned by get_config_data)
|
||||
# params: a dictionary of (name, ConfigMacro instance) mappings
|
||||
@staticmethod
|
||||
def config_macros_to_macros(macros):
|
||||
return [m.name for m in macros.values()]
|
||||
|
||||
# Return the configuration data converted to a list of C macros
|
||||
def get_config_data_macros(self):
|
||||
params, macros = self.get_config_data()
|
||||
self._check_required_parameters(params)
|
||||
return macros + self.parameters_to_macros(params)
|
||||
return self.config_macros_to_macros(macros) + self.parameters_to_macros(params)
|
||||
|
||||
# Returns any features in the configuration data
|
||||
def get_features(self):
|
||||
|
@ -387,4 +395,43 @@ class Config:
|
|||
if self.config_errors:
|
||||
raise self.config_errors[0]
|
||||
return True
|
||||
|
||||
|
||||
# Return the configuration data converted to the content of a C header file,
|
||||
# meant to be included to a C/C++ file. The content is returned as a string.
|
||||
# If 'fname' is given, the content is also written to the file called "fname".
|
||||
# WARNING: if 'fname' names an existing file, that file will be overwritten!
|
||||
def get_config_data_header(self, fname = None):
|
||||
params, macros = self.get_config_data()
|
||||
self._check_required_parameters(params)
|
||||
header_data = "// Automatically generated configuration file.\n"
|
||||
header_data += "// DO NOT EDIT, content will be overwritten.\n\n"
|
||||
header_data += "#ifndef __MBED_CONFIG_DATA__\n"
|
||||
header_data += "#define __MBED_CONFIG_DATA__\n\n"
|
||||
# Compute maximum length of macro names for proper alignment
|
||||
max_param_macro_name_len = max([len(m.macro_name) for m in params.values() if m.value is not None]) if params else 0
|
||||
max_direct_macro_name_len = max([len(m.macro_name) for m in macros.values()]) if macros else 0
|
||||
max_macro_name_len = max(max_param_macro_name_len, max_direct_macro_name_len)
|
||||
# Compute maximum length of macro values for proper alignment
|
||||
max_param_macro_val_len = max([len(str(m.value)) for m in params.values() if m.value is not None]) if params else 0
|
||||
max_direct_macro_val_len = max([len(m.macro_value or "") for m in macros.values()]) if macros else 0
|
||||
max_macro_val_len = max(max_param_macro_val_len, max_direct_macro_val_len)
|
||||
# Generate config parameters first
|
||||
if params:
|
||||
header_data += "// Configuration parameters\n"
|
||||
for m in params.values():
|
||||
if m.value is not None:
|
||||
header_data += "#define {0:<{1}} {2!s:<{3}} // set by {4}\n".format(m.macro_name, max_macro_name_len, m.value, max_macro_val_len, m.set_by)
|
||||
# Then macros
|
||||
if macros:
|
||||
header_data += "// Macros\n"
|
||||
for m in macros.values():
|
||||
if m.macro_value:
|
||||
header_data += "#define {0:<{1}} {2!s:<{3}} // defined by {4}\n".format(m.macro_name, max_macro_name_len, m.macro_value, max_macro_val_len, m.defined_by)
|
||||
else:
|
||||
header_data += "#define {0:<{1}} // defined by {2}\n".format(m.macro_name, max_macro_name_len + max_macro_val_len + 1, m.defined_by)
|
||||
header_data += "\n#endif\n"
|
||||
# If fname is given, write "header_data" to it
|
||||
if fname:
|
||||
with open(fname, "wt") as f:
|
||||
f.write(header_data)
|
||||
return header_data
|
||||
|
|
|
@ -62,7 +62,7 @@ if __name__ == '__main__':
|
|||
options.prefix = options.prefix or [""]
|
||||
|
||||
try:
|
||||
params, macros = get_config(options.source_dir, target, toolchain)
|
||||
params, macros, features = get_config(options.source_dir, target, toolchain)
|
||||
if not params and not macros:
|
||||
print "No configuration data available."
|
||||
_exit(0)
|
||||
|
@ -79,7 +79,7 @@ if __name__ == '__main__':
|
|||
print "Macros"
|
||||
print "------"
|
||||
if macros:
|
||||
print 'Defined with "macros":', macros
|
||||
print 'Defined with "macros":', Config.config_macros_to_macros(macros)
|
||||
print "Generated from configuration parameters:", Config.parameters_to_macros(params)
|
||||
|
||||
except KeyboardInterrupt, e:
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
"""
|
||||
|
||||
from tools.build_api import get_config
|
||||
from tools.config import ConfigException
|
||||
from tools.config import ConfigException, Config
|
||||
import os, sys
|
||||
|
||||
# Compare the output of config against a dictionary of known good results
|
||||
|
@ -44,6 +44,7 @@ def test_tree(full_name, name):
|
|||
err_msg = None
|
||||
try:
|
||||
cfg, macros, features = get_config(full_name, target, "GCC_ARM")
|
||||
macros = Config.config_macros_to_macros(macros)
|
||||
except ConfigException as e:
|
||||
err_msg = e.message
|
||||
if err_msg:
|
||||
|
|
|
@ -270,6 +270,9 @@ class mbedToolchain:
|
|||
|
||||
self.flags = deepcopy(self.DEFAULT_FLAGS)
|
||||
|
||||
# config_header_content will hold the content of the config header (if used)
|
||||
self.config_header_content = None
|
||||
|
||||
def get_output(self):
|
||||
return self.output
|
||||
|
||||
|
@ -879,6 +882,26 @@ class mbedToolchain:
|
|||
map_csv = splitext(map)[0] + "_map.csv"
|
||||
memap.generate_output('csv-ci', map_csv)
|
||||
|
||||
# "Prefix headers" are automatically included by the compiler at the beginning of
|
||||
# each source file. They are used to provide configuration data.
|
||||
# header_content - the content of the config header file.
|
||||
def set_config_header_content(self, header_content):
|
||||
self.config_header_content = header_content
|
||||
|
||||
# Return the location of the config header. This function will create the config
|
||||
# header first if needed. The header will be written in a file called "mbed_conf.h"
|
||||
# located in the project's build directory.
|
||||
# If config headers are not used (self.config_header_content is None), the function
|
||||
# returns None
|
||||
def get_config_header(self):
|
||||
if self.config_header_content is None:
|
||||
return None
|
||||
config_file = join(self.build_dir, "mbed_conf.h")
|
||||
if not exists(config_file):
|
||||
with open(config_file, "wt") as f:
|
||||
f.write(self.config_header_content)
|
||||
return config_file
|
||||
|
||||
|
||||
from tools.settings import ARM_BIN
|
||||
from tools.settings import GCC_ARM_PATH, GCC_CR_PATH
|
||||
|
|
|
@ -115,7 +115,11 @@ class ARM(mbedToolchain):
|
|||
return ["--depend", dep_path]
|
||||
|
||||
def get_compile_options(self, defines, includes):
|
||||
return ['-D%s' % d for d in defines] + ['--via', self.get_inc_file(includes)]
|
||||
opts = ['-D%s' % d for d in defines] + ['--via', self.get_inc_file(includes)]
|
||||
config_header = self.get_config_header()
|
||||
if config_header is not None:
|
||||
opts = opts + ['--preinclude', config_header]
|
||||
return opts
|
||||
|
||||
@hook_tool
|
||||
def assemble(self, source, object, includes):
|
||||
|
|
|
@ -166,7 +166,11 @@ class GCC(mbedToolchain):
|
|||
return ["-MD", "-MF", dep_path]
|
||||
|
||||
def get_compile_options(self, defines, includes):
|
||||
return ['-D%s' % d for d in defines] + ['@%s' % self.get_inc_file(includes)]
|
||||
opts = ['-D%s' % d for d in defines] + ['@%s' % self.get_inc_file(includes)]
|
||||
config_header = self.get_config_header()
|
||||
if config_header is not None:
|
||||
opts = opts + ['-include', config_header]
|
||||
return opts
|
||||
|
||||
@hook_tool
|
||||
def assemble(self, source, object, includes):
|
||||
|
|
|
@ -127,7 +127,11 @@ class IAR(mbedToolchain):
|
|||
return ["-l", base + '.s.txt']
|
||||
|
||||
def get_compile_options(self, defines, includes):
|
||||
return ['-D%s' % d for d in defines] + ['-f', self.get_inc_file(includes)]
|
||||
opts = ['-D%s' % d for d in defines] + ['-f', self.get_inc_file(includes)]
|
||||
config_header = self.get_config_header()
|
||||
if config_header is not None:
|
||||
opts = opts + ['--preinclude', config_header]
|
||||
return opts
|
||||
|
||||
@hook_tool
|
||||
def assemble(self, source, object, includes):
|
||||
|
|
Loading…
Reference in New Issue