From d5aef28145fe6d5c403d56810aad8053b6db6c75 Mon Sep 17 00:00:00 2001 From: Hugues Kamba Date: Thu, 14 Nov 2019 11:58:01 +0000 Subject: [PATCH] minimal-printf: Enable using a target configuration parameter --- platform/source/minimal-printf/README.md | 28 +++++--- targets/targets.json | 1 + tools/test/toolchains/test_toolchains.py | 87 ++++++++++++++++++++++++ tools/toolchains/arm.py | 5 ++ tools/toolchains/gcc.py | 20 ++++++ tools/toolchains/iar.py | 2 + tools/toolchains/mbed_toolchain.py | 8 +++ 7 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 tools/test/toolchains/test_toolchains.py diff --git a/platform/source/minimal-printf/README.md b/platform/source/minimal-printf/README.md index 7c287e78a34..7fc40fc4c16 100644 --- a/platform/source/minimal-printf/README.md +++ b/platform/source/minimal-printf/README.md @@ -26,6 +26,22 @@ Floating point limitations: * All floating points are treated as %f. * No support for inf, infinity or nan +## Usage + + +To replace the standard implementation of the printf functions with the ones in this library: + +Modify your application configuration file to override the parameter `target.printf` with the value `minimal-printf` as shown below: + +```json + "target_overrides": { + "*": { + "target.printf": "minimal-printf", + } + } +``` + + ## Configuration @@ -60,6 +76,7 @@ In mbed_app.json: ```json "target_overrides": { "*": { + "target.printf": "minimal-printf", "platform.minimal-printf-enable-floating-point": false, "platform.minimal-printf-set-floating-point-max-decimals": 6, "platform.minimal-printf-enable-64-bit": false @@ -67,17 +84,6 @@ In mbed_app.json: } ``` -## Usage - - -To replace the standard implementation of the printf functions with the ones in this library: - -Compile with mbed-cli using the custom `minimal-printf` profile. For example, to compile in release mode: - -``` -$ mbed compile -t -m --profile release --profile mbed-os/tools/profiles/extensions/minimal-printf.json -``` - ## Size comparison diff --git a/targets/targets.json b/targets/targets.json index e7c1ab980d8..837114e612e 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -15,6 +15,7 @@ "default_lib": "std", "bootloader_supported": false, "static_memory_defines": true, + "printf_lib": "std", "config": { "console-uart": { "help": "Target has UART console on pins STDIO_UART_TX, STDIO_UART_RX. Value is only significant if target has SERIAL device.", diff --git a/tools/test/toolchains/test_toolchains.py b/tools/test/toolchains/test_toolchains.py new file mode 100644 index 00000000000..0a8dca2675e --- /dev/null +++ b/tools/test/toolchains/test_toolchains.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# Copyright (c) 2019 Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +"""Test the arm toolchain.""" + +import os +import sys +from unittest import TestCase + +import mock + + +ROOT = os.path.abspath( + os.path.join(os.path.dirname(__file__), "..", "..", "..") +) +sys.path.insert(0, ROOT) + +from tools.toolchains.arm import ARM_STD, ARM_MICRO, ARMC6 +from tools.toolchains.gcc import GCC_ARM +from tools.toolchains.iar import IAR + + +class TestArmToolchain(TestCase): + """Test Arm classes.""" + + def test_arm_minimal_printf(self): + """Test that linker flags are correctly added to an instance of ARM.""" + mock_target = mock.MagicMock() + mock_target.core = "Cortex-M4" + mock_target.printf_lib = "minimal-printf" + mock_target.supported_toolchains = ["ARM", "uARM", "ARMC5"] + + arm_std_obj = ARM_STD(mock_target) + arm_micro_obj = ARM_MICRO(mock_target) + arm_c6_obj = ARMC6(mock_target) + + self.assertIn("-DMBED_MINIMAL_PRINTF", arm_std_obj.flags["common"]) + self.assertIn("-DMBED_MINIMAL_PRINTF", arm_micro_obj.flags["common"]) + self.assertIn("-DMBED_MINIMAL_PRINTF", arm_c6_obj.flags["common"]) + + +class TestGccToolchain(TestCase): + """Test the GCC class.""" + + def test_gcc_minimal_printf(self): + """Test that linker flags are correctly added to an instance of GCC_ARM.""" + mock_target = mock.MagicMock() + mock_target.core = "Cortex-M4" + mock_target.printf_lib = "minimal-printf" + mock_target.supported_toolchains = ["GCC_ARM"] + mock_target.is_TrustZone_secure_target = False + + gcc_obj = GCC_ARM(mock_target) + + self.assertIn("-DMBED_MINIMAL_PRINTF", gcc_obj.flags["common"]) + + minimal_printf_wraps = [ + "-Wl,--wrap,printf", + "-Wl,--wrap,sprintf", + "-Wl,--wrap,snprintf", + "-Wl,--wrap,vprintf", + "-Wl,--wrap,vsprintf", + "-Wl,--wrap,vsnprintf", + "-Wl,--wrap,fprintf", + "-Wl,--wrap,vfprintf", + ] + + for i in minimal_printf_wraps: + self.assertIn(i, gcc_obj.flags["ld"]) + + +class TestIarToolchain(TestCase): + """Test the IAR class.""" + + def test_iar_minimal_printf(self): + """Test that linker flags are correctly added to an instance of GCC_ARM.""" + mock_target = mock.MagicMock() + mock_target.core = "Cortex-M4" + mock_target.printf_lib = "minimal-printf" + mock_target.supported_toolchains = ["IAR"] + mock_target.is_TrustZone_secure_target = False + + iar_obj = IAR(mock_target) + var = "-DMBED_MINIMAL_PRINTF" + self.assertIn("-DMBED_MINIMAL_PRINTF", iar_obj.flags["common"]) diff --git a/tools/toolchains/arm.py b/tools/toolchains/arm.py index 8aed902faf9..f83bc855054 100644 --- a/tools/toolchains/arm.py +++ b/tools/toolchains/arm.py @@ -81,6 +81,8 @@ def __init__(self, target, notify=None, macros=None, if "--library_type=microlib" not in self.flags['common']: self.flags['common'].append("--library_type=microlib") + self.check_and_add_minimal_printf(target) + cpu = { "Cortex-M0+": "Cortex-M0plus", "Cortex-M4F": "Cortex-M4.fp.sp", @@ -568,6 +570,8 @@ def __init__(self, target, *args, **kwargs): if "--library_type=microlib" not in self.flags['asm']: self.flags['asm'].append("--library_type=microlib") + self.check_and_add_minimal_printf(target) + if target.is_TrustZone_secure_target: if kwargs.get('build_dir', False): # Output secure import library @@ -767,3 +771,4 @@ def get_binary_commands(self, bin_arg, bin, elf): cmd.insert(1, "--ide=mbed") return cmd + diff --git a/tools/toolchains/gcc.py b/tools/toolchains/gcc.py index 24568d7c528..22c796917cc 100644 --- a/tools/toolchains/gcc.py +++ b/tools/toolchains/gcc.py @@ -58,6 +58,26 @@ def __init__(self, target, notify=None, macros=None, build_profile=None, self.flags["common"].append("-DMBED_RTOS_SINGLE_THREAD") self.flags["ld"].append("--specs=nano.specs") + self.check_and_add_minimal_printf(target) + + if getattr(target, "printf_lib", "std") == "minimal-printf": + minimal_printf_wraps = [ + "-Wl,--wrap,printf", + "-Wl,--wrap,sprintf", + "-Wl,--wrap,snprintf", + "-Wl,--wrap,vprintf", + "-Wl,--wrap,vsprintf", + "-Wl,--wrap,vsnprintf", + "-Wl,--wrap,fprintf", + "-Wl,--wrap,vfprintf", + ] + + # Add the linker option to wrap the f\v\s\printf functions if not + # already added. + for minimal_printf_wrap in minimal_printf_wraps: + if minimal_printf_wrap not in self.flags["ld"]: + self.flags["ld"].append(minimal_printf_wrap) + self.cpu = [] if target.is_TrustZone_secure_target: # Enable compiler security extensions diff --git a/tools/toolchains/iar.py b/tools/toolchains/iar.py index b2a5d4d8fca..8d80e4040a4 100644 --- a/tools/toolchains/iar.py +++ b/tools/toolchains/iar.py @@ -69,6 +69,8 @@ def __init__(self, target, notify=None, macros=None, build_profile=None, define_string = self.make_ld_define("DOMAIN_NS", "0x1") self.flags["ld"].append(define_string) + self.check_and_add_minimal_printf(target) + core = target.core_without_NS cpu = { "Cortex-M7F": "Cortex-M7.fp.sp", diff --git a/tools/toolchains/mbed_toolchain.py b/tools/toolchains/mbed_toolchain.py index e216c579795..897df7a3bae 100755 --- a/tools/toolchains/mbed_toolchain.py +++ b/tools/toolchains/mbed_toolchain.py @@ -1086,6 +1086,14 @@ def dump_build_profile(self): self._overwrite_when_not_equal(where, json.dumps( to_dump, sort_keys=True, indent=4)) + def check_and_add_minimal_printf(self, target): + """Add toolchain flag if minimal-printf is selected.""" + if ( + getattr(target, "printf_lib", "std") == "minimal-printf" + and "-DMBED_MINIMAL_PRINTF" not in self.flags["common"] + ): + self.flags["common"].append("-DMBED_MINIMAL_PRINTF") + @staticmethod def _overwrite_when_not_equal(filename, content): if not exists(filename) or content != open(filename).read():