Компиляция - это минимум. Примечательно, что большинство встроенных систем - это автономные системы , такие как приложения для микроконтроллеров и RTOS. Компиляторы для автономных систем не обязательно должны содержать все стандартные заголовки библиотек, единственными обязательными являются (C17 4/6):
<float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>,
<stddef.h>, <stdint.h>, <stdnoreturn.h>
Кроме того, встроенная система не должна поддерживать арифметику с плавающей запятой. В некоторых системах реализована программная поддержка с плавающей запятой, но это очень плохая практика. Если ваш MCU не имеет FPU, вы не должны использовать арифметику с плавающей запятой, или вы выбрали неправильный MCU для задачи, точка.
«Мне нужно представить это число внутренне или пользователю с десятичными знаками» - недопустимая причина для использования числа с плавающей запятой. Для этого следует использовать арифметику с фиксированной точкой. Вам только нужна плавающая точка, если вы хотите использовать математические библиотеки, такие как math.h и более сложные математические.
Традиционно компиляторы встроенных систем медленно адаптировались к последнему стандарту Си. Прошло довольно много времени с момента выпуска C11, поэтому на данный момент все полезные компиляторы догнали его (C17 содержит только незначительные изменения, поэтому мы, вероятно, можем его игнорировать). Исторически, встроенные компиляторы были ужасно плохи в этом, так что оставайтесь скептиками. Не должно быть никаких причин выбирать компилятор без поддержки C11 для разработки нового продукта.
Сводка для получения библиотеки для компиляции (минимум):
- Использует ли библиотека размещенные системные заголовки, и если да, то поддерживает ли их встроенный компилятор?
- Использует ли библиотека с плавающей запятой и, если да, имеет ли целевая система FPU или, по крайней мере, программную библиотеку с плавающей запятой?
- Использует ли библиотека последние стандарты C и поддерживает ли их встроенный компилятор?
Учитывая все это, вы должны подумать, написана ли библиотека вообще как переносимая. Они заботились о таких вещах, как целочисленные типы, перечисления и выравнивание? Используют ли они stdint.h
или "небрежный ввод" int
повсюду? Считали ли они порядком байтов? Использует ли библиотека динамическое размещение, что запрещено в большинстве встроенных систем? Совместимо ли это с отраслевыми стандартами, такими как MISRA-C? И так далее.
Тогда есть оптимизация, которую нужно рассмотреть в дополнение к этому. Оптимизация кода для микроконтроллеров сильно отличается от оптимизации кода для процессоров ПК.
Краткий взгляд на различные «переключатели компилятора» (#ifdef
) обычно дает представление о том, насколько переносим код. Глядя (очень кратко) на эту виолончельную библиотеку, они, похоже, подумали о портировании между основными системами x86, но это все. Вам пришлось бы переписать почти всю библиотеку, если бы вы перенесли ее на встроенную систему. Трудозатраты зависят от того, насколько чужой целевой процессор сравнивается с x86. Портирование на high-end Cortex-A с Little Endian может не потребовать особых усилий. Портирование на какой-нибудь дешевый MCU потребует огромных усилий.
Переносимость кода - большая тема и требует очень компетентных программистов на Си. Выполнение одного и того же кода, например, на x86-64 и дрянном 8-битном MCU не является тривиальной задачей.
Профессиональные библиотеки, такие как стеки протоколов, обычно поставляются с системным портом для определенного MCU, где они учитывают не только общую переносимость, но и конкретную систему.