Replace small with std C lib if not supported by a target's toolchain

Display a post-build warning indicating to the user that the standard C
library was used instead of the small C library if the former is not
supported.
pull/12691/head
Hugues Kamba 2020-03-20 14:54:35 +00:00
parent b090065dec
commit 0e5b71fdd7
6 changed files with 127 additions and 16 deletions

View File

@ -48,6 +48,7 @@ from .targets import TARGET_NAMES, TARGET_MAP, CORE_ARCH, Target
from .libraries import Library from .libraries import Library
from .toolchains import TOOLCHAIN_CLASSES, TOOLCHAIN_PATHS from .toolchains import TOOLCHAIN_CLASSES, TOOLCHAIN_PATHS
from .toolchains.arm import UARM_TOOLCHAIN_WARNING from .toolchains.arm import UARM_TOOLCHAIN_WARNING
from .toolchains.mbed_toolchain import should_replace_small_c_lib
from .config import Config from .config import Config
RELEASE_VERSIONS = ['2', '5'] RELEASE_VERSIONS = ['2', '5']
@ -205,6 +206,7 @@ def get_toolchain_name(target, toolchain_name):
return toolchain_name return toolchain_name
def find_valid_toolchain(target, toolchain): def find_valid_toolchain(target, toolchain):
"""Given a target and toolchain, get the names for the appropriate """Given a target and toolchain, get the names for the appropriate
toolchain to use. The environment is also checked to see if the corresponding toolchain to use. The environment is also checked to see if the corresponding
@ -250,6 +252,15 @@ def find_valid_toolchain(target, toolchain):
and "uARM" in {toolchain_name, target.default_toolchain} and "uARM" in {toolchain_name, target.default_toolchain}
): ):
end_warnings.append(UARM_TOOLCHAIN_WARNING) end_warnings.append(UARM_TOOLCHAIN_WARNING)
if should_replace_small_c_lib(target, toolchain):
warning = (
"Warning: We noticed that target.c_lib is set to small.\n"
"As the {} target does not support a small C library for the {} toolchain,\n"
"we are using the standard C library instead. "
).format(target.name, toolchain)
end_warnings.append(warning)
return toolchain_name, internal_tc_name, end_warnings return toolchain_name, internal_tc_name, end_warnings
else: else:
if last_error: if last_error:

View File

@ -83,12 +83,12 @@ class TestArmToolchain(TestCase):
def test_arm_c_lib_small_exception(self): def test_arm_c_lib_small_exception(self):
"""Test that an exception is raised if the small C library is not supported for a target on the ARM toolchain.""" """Test that an exception is raised if the small and std C library are not supported for a target on the ARM toolchain."""
mock_target = mock.MagicMock() mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4" mock_target.core = "Cortex-M4"
mock_target.c_lib = "small" mock_target.c_lib = "small"
del mock_target.default_lib del mock_target.default_lib
mock_target.supported_c_libs = {"arm": ["std"]} mock_target.supported_c_libs = {"arm": [""]}
mock_target.default_toolchain = "ARM" mock_target.default_toolchain = "ARM"
mock_target.supported_toolchains = ["ARM", "uARM", "ARMC5"] mock_target.supported_toolchains = ["ARM", "uARM", "ARMC5"]
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)): with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
@ -97,6 +97,27 @@ class TestArmToolchain(TestCase):
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)): with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
ARMC6(mock_target) ARMC6(mock_target)
def test_arm_small_c_lib_swap_std_lib(self):
"""Test that no exception is raised when small c lib is not supported but std lib is supported."""
mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4"
mock_target.c_lib = "small"
del mock_target.default_lib
mock_target.supported_c_libs = {"arm": ["std"]}
mock_target.supported_toolchains = ["ARM", "uARM", "ARMC5"]
mock_target.default_toolchain = "ARM"
try:
ARM_STD(mock_target)
except NotSupportedException:
self.fail(UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib))
mock_target.default_toolchain = "ARMC6"
try:
ARMC6(mock_target)
except NotSupportedException:
self.fail(UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib))
class TestGccToolchain(TestCase): class TestGccToolchain(TestCase):
"""Test the GCC class.""" """Test the GCC class."""
@ -147,25 +168,39 @@ class TestGccToolchain(TestCase):
"""Test that an exception is raised if the std C library is not supported for a target on the GCC_ARM toolchain.""" """Test that an exception is raised if the std C library is not supported for a target on the GCC_ARM toolchain."""
mock_target = mock.MagicMock() mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4" mock_target.core = "Cortex-M4"
mock_target.default_toolchain = "ARM" mock_target.default_toolchain = "GCC_ARM"
mock_target.c_lib = "std" mock_target.c_lib = "std"
del mock_target.default_lib del mock_target.default_lib
mock_target.supported_c_libs = {"arm": ["small"]} mock_target.supported_c_libs = {"gcc_arm": ["small"]}
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)): with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
GCC_ARM(mock_target) GCC_ARM(mock_target)
def test_gcc_arm_c_lib_small_exception(self): def test_gcc_arm_c_lib_small_exception(self):
"""Test that an exception is raised if the small C library is not supported for a target on the GCC_ARM toolchain.""" """Test that an exception is raised if the small and std C library are not supported for a target on the GCC_ARM toolchain."""
mock_target = mock.MagicMock() mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4" mock_target.core = "Cortex-M4"
mock_target.c_lib = "small" mock_target.c_lib = "small"
del mock_target.default_lib del mock_target.default_lib
mock_target.supported_c_libs = {"arm": ["std"]} mock_target.supported_c_libs = {"gcc_arm": [""]}
mock_target.default_toolchain = "ARM" mock_target.default_toolchain = "GCC_ARM"
mock_target.supported_toolchains = ["ARM", "uARM", "ARMC5"] mock_target.supported_toolchains = ["GCC_ARM"]
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)): with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
GCC_ARM(mock_target) GCC_ARM(mock_target)
def test_gcc_arm_small_c_lib_swap_std_lib(self):
"""Test that no exception is raised when small c lib is not supported but std lib is supported."""
mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4"
mock_target.supported_c_libs = {"gcc_arm": ["std"]}
mock_target.c_lib = "small"
del mock_target.default_lib
mock_target.supported_toolchains = ["GCC_ARM"]
mock_target.is_TrustZone_secure_target = False
mock_target.default_toolchain = "GCC_ARM"
try:
GCC_ARM(mock_target)
except NotSupportedException:
self.fail(UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib))
class TestIarToolchain(TestCase): class TestIarToolchain(TestCase):
"""Test the IAR class.""" """Test the IAR class."""
@ -210,12 +245,26 @@ class TestIarToolchain(TestCase):
IAR(mock_target) IAR(mock_target)
def test_iar_c_lib_small_exception(self): def test_iar_c_lib_small_exception(self):
"""Test that an exception is raised if the small C library is not supported for a target on the IAR toolchain.""" """Test that an exception is raised if the small and std C library are not supported for a target on the IAR toolchain."""
mock_target = mock.MagicMock() mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4" mock_target.core = "Cortex-M4"
mock_target.c_lib = "small" mock_target.c_lib = "small"
del mock_target.default_lib del mock_target.default_lib
mock_target.supported_c_libs = {"iar": ["std"]} mock_target.supported_c_libs = {"iar": [""]}
mock_target.supported_toolchains = ["IAR"] mock_target.supported_toolchains = ["IAR"]
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)): with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
IAR(mock_target) IAR(mock_target)
def test_iar_small_c_lib_swap_std_lib(self):
"""Test that no exception is raised when small c lib is not supported but std lib is supported."""
mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4"
mock_target.supported_c_libs = {"iar": ["std"]}
mock_target.c_lib = "small"
del mock_target.default_lib
mock_target.supported_toolchains = ["IAR"]
mock_target.is_TrustZone_secure_target = False
try:
IAR(mock_target)
except NotSupportedException:
self.fail(UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib))

View File

@ -26,7 +26,9 @@ from tempfile import mkstemp
from shutil import rmtree from shutil import rmtree
from distutils.version import LooseVersion from distutils.version import LooseVersion
from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS from tools.toolchains.mbed_toolchain import (
mbedToolchain, TOOLCHAIN_PATHS, should_replace_small_c_lib
)
from tools.utils import mkdir, NotSupportedException, run_cmd from tools.utils import mkdir, NotSupportedException, run_cmd
from tools.resources import FileRef from tools.resources import FileRef
@ -70,7 +72,12 @@ class ARM(mbedToolchain):
raise NotSupportedException( raise NotSupportedException(
"this compiler does not support the core %s" % target.core) "this compiler does not support the core %s" % target.core)
self.check_c_lib_supported(target, "arm") toolchain = "arm"
if should_replace_small_c_lib(target, toolchain):
target.c_lib = "std"
self.check_c_lib_supported(target, toolchain)
if ( if (
getattr(target, "default_toolchain", "ARM") == "uARM" getattr(target, "default_toolchain", "ARM") == "uARM"
@ -562,7 +569,12 @@ class ARMC6(ARM_STD):
"ARM/ARMC6 compiler support is required for ARMC6 build" "ARM/ARMC6 compiler support is required for ARMC6 build"
) )
self.check_c_lib_supported(target, "arm") toolchain = "arm"
if should_replace_small_c_lib(target, toolchain):
target.c_lib = "std"
self.check_c_lib_supported(target, toolchain)
if ( if (
getattr(target, "default_toolchain", "ARMC6") == "uARM" getattr(target, "default_toolchain", "ARMC6") == "uARM"

View File

@ -22,7 +22,9 @@ from os import getcwd, getenv
from distutils.spawn import find_executable from distutils.spawn import find_executable
from distutils.version import LooseVersion from distutils.version import LooseVersion
from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS from tools.toolchains.mbed_toolchain import (
mbedToolchain, TOOLCHAIN_PATHS, should_replace_small_c_lib
)
from tools.utils import run_cmd from tools.utils import run_cmd
@ -54,7 +56,12 @@ class GCC(mbedToolchain):
# Add flags for current size setting # Add flags for current size setting
c_lib = "std" c_lib = "std"
if hasattr(target, "c_lib"): if hasattr(target, "c_lib"):
self.check_c_lib_supported(target, "gcc_arm") toolchain = "gcc_arm"
if should_replace_small_c_lib(target, toolchain):
target.c_lib = "std"
self.check_c_lib_supported(target, toolchain)
c_lib = target.c_lib c_lib = target.c_lib
elif hasattr(target, "default_build"): elif hasattr(target, "default_build"):
c_lib = target.default_build c_lib = target.default_build

View File

@ -20,7 +20,9 @@ from os import remove
from os.path import join, splitext, exists from os.path import join, splitext, exists
from distutils.version import LooseVersion from distutils.version import LooseVersion
from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS from tools.toolchains.mbed_toolchain import (
mbedToolchain, TOOLCHAIN_PATHS, should_replace_small_c_lib
)
from tools.utils import run_cmd from tools.utils import run_cmd
class IAR(mbedToolchain): class IAR(mbedToolchain):
@ -54,6 +56,11 @@ class IAR(mbedToolchain):
build_profile=build_profile build_profile=build_profile
) )
toolchain = "iar"
if should_replace_small_c_lib(target, toolchain):
target.c_lib = "std"
self.check_c_lib_supported(target, "iar") self.check_c_lib_supported(target, "iar")
if target.is_TrustZone_secure_target: if target.is_TrustZone_secure_target:

View File

@ -1393,3 +1393,28 @@ class mbedToolchain(with_metaclass(ABCMeta, object)):
to_ret['linker'] = {'flags': copy(self.flags['ld'])} to_ret['linker'] = {'flags': copy(self.flags['ld'])}
to_ret.update(self.config.report) to_ret.update(self.config.report)
return to_ret return to_ret
def should_replace_small_c_lib(target, toolchain):
"""
Check if the small C lib should be replaced with the standard C lib.
Return True if the replacement occurs otherwise return False.
"""
return (
not is_library_supported("small", target, toolchain)
and is_library_supported("std", target, toolchain)
and target.c_lib == "small"
)
def is_library_supported(lib_type, target, toolchain):
"""
Check if a library type is supported by a toolchain for a given target.
Return True if the library type is supported, False if not supported or
the target does not have an supported_c_libs attribute.
"""
return (
hasattr(target, "supported_c_libs")
and toolchain.lower() in target.supported_c_libs
and lib_type in target.supported_c_libs[toolchain.lower()]
)