Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
11 changes: 11 additions & 0 deletions tools/build_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from .libraries import Library
from .toolchains import TOOLCHAIN_CLASSES, TOOLCHAIN_PATHS
from .toolchains.arm import UARM_TOOLCHAIN_WARNING
from .toolchains.mbed_toolchain import should_replace_small_c_lib
from .config import Config

RELEASE_VERSIONS = ['2', '5']
Expand Down Expand Up @@ -205,6 +206,7 @@ def get_toolchain_name(target, toolchain_name):

return toolchain_name


def find_valid_toolchain(target, toolchain):
"""Given a target and toolchain, get the names for the appropriate
toolchain to use. The environment is also checked to see if the corresponding
Expand Down Expand Up @@ -250,6 +252,15 @@ def find_valid_toolchain(target, toolchain):
and "uARM" in {toolchain_name, target.default_toolchain}
):
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
else:
if last_error:
Expand Down
69 changes: 59 additions & 10 deletions tools/test/toolchains/test_toolchains.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@ def test_arm_c_lib_std_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.core = "Cortex-M4"
mock_target.c_lib = "small"
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.supported_toolchains = ["ARM", "uARM", "ARMC5"]
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
Expand All @@ -97,6 +97,27 @@ def test_arm_c_lib_small_exception(self):
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
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):
"""Test the GCC class."""

Expand Down Expand Up @@ -147,25 +168,39 @@ def test_gcc_arm_c_lib_std_exception(self):
"""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.core = "Cortex-M4"
mock_target.default_toolchain = "ARM"
mock_target.default_toolchain = "GCC_ARM"
mock_target.c_lib = "std"
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)):
GCC_ARM(mock_target)

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.core = "Cortex-M4"
mock_target.c_lib = "small"
del mock_target.default_lib
mock_target.supported_c_libs = {"arm": ["std"]}
mock_target.default_toolchain = "ARM"
mock_target.supported_toolchains = ["ARM", "uARM", "ARMC5"]
mock_target.supported_c_libs = {"gcc_arm": [""]}
mock_target.default_toolchain = "GCC_ARM"
mock_target.supported_toolchains = ["GCC_ARM"]
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
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):
"""Test the IAR class."""

Expand Down Expand Up @@ -210,12 +245,26 @@ def test_iar_c_lib_std_exception(self):
IAR(mock_target)

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.core = "Cortex-M4"
mock_target.c_lib = "small"
del mock_target.default_lib
mock_target.supported_c_libs = {"iar": ["std"]}
mock_target.supported_c_libs = {"iar": [""]}
mock_target.supported_toolchains = ["IAR"]
with self.assertRaisesRegexp(NotSupportedException, UNSUPPORTED_C_LIB_EXCEPTION_STRING.format(mock_target.c_lib)):
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))
18 changes: 15 additions & 3 deletions tools/toolchains/arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
from shutil import rmtree
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.resources import FileRef

Expand Down Expand Up @@ -70,7 +72,12 @@ def __init__(self, target, notify=None, macros=None,
raise NotSupportedException(
"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 (
getattr(target, "default_toolchain", "ARM") == "uARM"
Expand Down Expand Up @@ -562,7 +569,12 @@ def __init__(self, target, *args, **kwargs):
"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 (
getattr(target, "default_toolchain", "ARMC6") == "uARM"
Expand Down
11 changes: 9 additions & 2 deletions tools/toolchains/gcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
from distutils.spawn import find_executable
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


Expand Down Expand Up @@ -54,7 +56,12 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
# Add flags for current size setting
c_lib = "std"
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
elif hasattr(target, "default_build"):
c_lib = target.default_build
Expand Down
9 changes: 8 additions & 1 deletion tools/toolchains/iar.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
from os.path import join, splitext, exists
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

class IAR(mbedToolchain):
Expand Down Expand Up @@ -54,6 +56,11 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
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")

if target.is_TrustZone_secure_target:
Expand Down
25 changes: 25 additions & 0 deletions tools/toolchains/mbed_toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1393,3 +1393,28 @@ def report(self):
to_ret['linker'] = {'flags': copy(self.flags['ld'])}
to_ret.update(self.config.report)
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()]
)