minimal-printf: Enable using a target configuration parameter

pull/11891/head
Hugues Kamba 2019-11-14 11:58:01 +00:00
parent 609612c1f2
commit d5aef28145
7 changed files with 140 additions and 11 deletions

View File

@ -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 <toolchain> -m <target> --profile release --profile mbed-os/tools/profiles/extensions/minimal-printf.json
```
## Size comparison

View File

@ -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.",

View File

@ -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"])

View File

@ -81,6 +81,8 @@ class ARM(mbedToolchain):
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 @@ class ARMC6(ARM_STD):
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 @@ class ARMC6(ARM_STD):
cmd.insert(1, "--ide=mbed")
return cmd

View File

@ -58,6 +58,26 @@ class GCC(mbedToolchain):
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

View File

@ -69,6 +69,8 @@ class IAR(mbedToolchain):
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",

View File

@ -1086,6 +1086,14 @@ class mbedToolchain:
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():