Лучшие практики для многократного использования встроенного C? - PullRequest
11 голосов
/ 26 ноября 2009

Я пишу код на C для встроенной системы (платформа dsPIC33) и собираюсь создать библиотеку кода многократного использования для нескольких проектов.

Каковы наилучшие практики для привязки библиотеки к каждому проекту?

Очевидно, что библиотека будет иметь некоторые аппаратные (и, следовательно, зависящие от проекта) зависимости, поэтому разумно предположить, что она будет скомпилирована с каждым проектом (а не скомпонована в двоичной форме).

То, что я до сих пор придумал, - это чтобы библиотека находилась в центре, но для этого нужен специфический для проекта libraryConfig.h, который включает определения функций, макросы и т. Д. Для этого библиотека должна включать заголовок в свой собственный код Это означает, что исходный каталог проекта должен находиться в пути включения (а не только в исходном каталоге библиотеки). Такого рода путаница делает различие между #include "" и #include <>, не так ли?

Это как это обычно делается?

Ответы [ 4 ]

8 голосов
/ 27 ноября 2009

Очень хороший вопрос, и ответ не простой. Несколько вещей, чтобы рассмотреть. Вот несколько мнений из моего опыта.

Общий код и локальная копия проекта

Одним из важных решений является то, использовать ли «общий» код библиотеки, который автоматически обновляется из центрального расположения («библиотека повторного использования» вашей компании), или сохранять локальную копию проекта.

Это подробно обсуждается в этом вопросе .

Преимущество центральной библиотеки заключается в том, что однажды проделанная работа может принести пользу многим проектам. Сложность с локальной копией проекта заключается в том, что исправления и улучшения не вносятся обратно в центральную библиотеку, а исправления ошибок в центральной библиотеке могут не вноситься в ваш проект.

Но потенциальная трудность с использованием центральной библиотеки заключается в том, что люди, занимающиеся их конкретной деятельностью, изменяют ее неконтролируемым образом в соответствии со своим проектом, и она непреднамеренно нарушает другие проекты. Я видел это лично в «обычном» коде, который был полон #ifdefs и регулярно ломал другие проекты.

Чтобы получить хорошую выгоду от общего кода, также известного как центральная библиотека повторного использования:

Библиотека:

  • должен иметь четко определенные требования, API и модульные тесты
  • необходимо избегать кода, специфичного для проекта; оно должно быть универсальным
  • должен иметь механизм для точной настройки параметров проекта (это можно эффективно рассматривать как часть API)
  • должен иметь официальный процесс выпуска, с номерами версий и исправлениями, проблемы должны отслеживаться.

Индивидуальные проекты:

  • не должен автоматически и вслепую получать «последнюю версию», но должен иметь возможность получить конкретный «выпуск» с указанным номером версии. Тогда проекты должны контролировать, обновляются ли они до более новой версии. Проект должен иметь возможность четко отслеживать «мы используем версию 1.2.3 библиотеки xyz».
  • следует избегать "разветвления" кода библиотеки, если это возможно. Например. избегайте добавления специфичных для проекта «функций» в код библиотеки.
  • должен отслеживать любые локальные изменения кода библиотеки
  • должен рассматривать ошибки как ошибки библиотеки, которые должны быть исправлены в центральной библиотеке, если это вообще возможно. У компании должны быть процессы, чтобы исправить их в центральной библиотеке, протестировать библиотеку с помощью собственного набора модульных тестов (вероятно, улучшив модульные тесты, чтобы в будущем обнаружить ошибку). Затем выпустите новую версию центральной библиотеки по мере необходимости и разверните ее в других проектах, если / когда эти проекты сочтут нужным.

Если в компании нет такого процесса, то проект должен просто сделать локальную копию фрагмента кода (скажем, скопированного из предыдущего проекта), а затем взять на себя полную ответственность за проект. , Вы все еще получаете некоторую выгоду от повторного использования в этой ситуации, потому что вы не переписываете его с нуля.

Конфигурация для конкретного проекта

Если для кода требуется специфичная для проекта конфигурация, в идеале это должно быть как можно меньше, так как часть кода не должна быть разбросана по пачке исходных файлов. В идеале, один заголовочный файл. Но вполне возможно и файл .C (скажем, если вам нужно определить некоторые справочные таблицы). Библиотека должна предоставить шаблон с хорошо прокомментированными параметрами.

Хороший пример того, как это можно сделать, см. В ОСРВ µC / OS-II ( book ) от Jean Labrosse, от Micrium .

1 голос
/ 27 ноября 2009

Это действительно больше вопрос управления конфигурацией, чем вопрос Си. По моему опыту, использование хорошей программы контроля версий наиболее полезно. Найдите тот, который позволяет вам определить «проект», потянув исходный код из нескольких разных мест. Поймите, что определение «проекта» в вашей программе контроля версий станет важным элементом при создании проекта.

Также важно иметь возможность вносить изменения в код вашей библиотеки для ветви проекта и регистрировать их несколько раз в вашей системе контроля версий, не проверяя изменения в основном расположении библиотеки, пока изменения не будут подтверждены, так как они может повлиять на множество разных проектов.

Ваши библиотечные модули могут также получить файл, который определяет параметры библиотеки для каждого конкретного проекта. Практика, которую я принял, называет эти интерфейсные файлы _PAL.h, где _PAL указывает файл уровня абстракции проекта.

1 голос
/ 27 ноября 2009

номер
Обычно вы определяете путь к каталогу include вашей библиотеки, используя флаг команды в вашем компиляторе (обычно это флаг -I).

Скажем, если вы используете компилятор GCC, а заголовочные файлы вашей библиотеки находятся в

/usr/local/include/mylibheaders

тогда вы должны вызвать компилятор со следующей опцией:

-I/usr/local/include/mylibheader/mycurrentplatform

где mycurrentplatform Каталог отличается для каждого проекта и содержит специфичный для проекта libraryConfig.h

Таким образом, вы можете использовать #include<libraryConfig.h> в каждом проекте.

1 голос
/ 26 ноября 2009

Это не портит различие, которое в любом случае почти полностью определяется платформой. Единственное определенное поведение состоит в том, что если при включении, использующем "", не удается найти файл, он выполняет поиск снова, как если бы вы сказали <>.

Я думаю, вы поступаете правильно. По моему опыту, обычный способ обработки заголовка, специфичного для платформы, заключается в том, что вы даете ему имя, которое, насколько вы можете быть уверенным, никогда не столкнется с чем-либо еще, и #include его с помощью "". Затем вы указываете плательщику платформы делать все, что необходимо для компилятора, чтобы он был найден. Обычно это просто означает указание некоторого аргумента компилятора, например -I, для тех мест, где он хочет сохранить файл. Так что да, один из каталогов его проекта. Но если ничего не помогает, он всегда может скопировать свой файл в какое-то место, где его компилятор будет искать. Он мог бы даже скопировать его в свою локальную копию исходного кода вашей библиотеки, если его компилятору неоправданно сложно все это сделать.

Другим способом является создание в библиотеке файла selectplatform.h, который выглядит следующим образом:

// obviously WIN32 isn't an embedded platform, and GCC is too broad
// to be supported by a single header file. Replace with whatever platforms
// it is you do support out of the box.
#if _WIN32
    #include "platforms/msvc32.h"
#elif __GNUC__
    #include "platforms/gcc.h"
#else
    #error "You must add a new clause to selectplatform.h for your platform"
#endif

Это избавляет от необходимости настройки компилятора, но имеет недостаток, заключающийся в том, что каждый новый порт платформы должен изменять файл. Если вы единственный, кто занимается портированием, это определенно не проблема. В противном случае этот файл разветвляется третьими лицами. Затем, возможно, они добавят новый файл в platforms/ в вашей библиотеке, или, может быть, они поместят свой файл в другое место. Так что с третьими лицами, это только , вероятно, не проблема. Они могут внести свои изменения (возможно, включая заголовок своей платформы) обратно вверх по течению, если они и вы оба захотите.

...