makefile — Как структурировать «библиотеку» источника C ++?

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

Варианты, которые я видел, включают:

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

В настоящее время я использую третий вариант, в котором для каждого класса я хочу включить символическую ссылку на каждый класс заголовков и исходные файлы (например, ln -s <path_to_class folder>/myclass.cpp) Это работает хорошо, за исключением того, что я не могу переместить местоположение папки проекта (оно разрывает все символические ссылки), и мне нужно, чтобы все эти символические ссылки оставались рядом.

Мне нравится второй вариант (он имеет вид Java), но я беспокоюсь о раздувании размера кода, если все объявлено встроенным.

Пользователь коллекции будет где-то создавать папку проекта и каким-то образом включать коллекцию в процесс компиляции.

Я хотел бы, чтобы было возможно несколько вещей:

  1. Простая компиляция (что-то вроде gcc *.cpp из папки проекта)
  2. Простое распространение библиотеки в некомпилированном виде.
  3. Организация библиотеки по модулю.
  4. Размер скомпилированного кода не раздут.

Меня не волнует документация (об этом позаботится Doxygen) или время компиляции: общие модули невелики, и даже самые крупные проекты на самых медленных машинах не будут компилироваться более чем за несколько секунд.

Я использую компилятор GCC, если это имеет какое-либо значение.

3

Решение

Библиотека — лучший вариант (на мой взгляд) из трех, которые вы подняли. Затем укажите заголовочные файлы в пути включения и библиотеку в пути компоновщика.

Поскольку вы также хотите распространять библиотеку в форме исходного кода, я был бы склонен предоставить сжатый архив (gzip, 7-zip, tarball или другой предпочтительный формат) в центральном хранилище.

0

Другие решения

Если я правильно понимаю, вы не хотите, чтобы пользователи включали файлы .cpp в свою сборку, а вместо этого просто хотите, чтобы они использовали либо: (i) заголовки напрямую, (ii) использование скомпилированной формы библиотеки lib.

Ваши требования немного необычны, но они могут быть выполнены. Мне кажется, что вы могли бы организовать свой код следующим образом. Во-первых, имейте глобальное определение, которое определяет, компилируете ли вы библиотеку:

// global.h
// ...
#define LIB_SOURCE
// ...

Затем в каждом заголовочном файле вы проверяете, установлено ли это определение: если библиотека распространяется как статическая / разделяемая библиотека, определения не включаются, в противном случае файл .cpp включается из заголовочного файла.

// A.h
#ifndef _A_H
#include "global.h"#ifdef LIB_SOURCE
#include "A.cpp"#endif
// ...
#endif

где «A.cpp» будет содержать фактическую реализацию.

Опять же, это очень странный способ ведения дел, и я бы на самом деле советовал против такой практики. Лучший способ (но тот, который требует больше работы) — всегда распространять разделяемую библиотеку. Но чтобы сохранить независимость от компилятора, напишите слой C вокруг него. Таким образом, у вас есть переносимая, поддерживаемая библиотека.

Что касается некоторых других требований:

  • Сделайте процесс сборки простым, предоставив Makefile
  • Если вас беспокоит размер кода скомпилированной библиотеки, посмотрите параметры оптимизации gcc (-Os). Если вы беспокоитесь о размере кода библиотеки при распределении в виде исходного кода в заголовках, это более сложно. Поскольку (встроенный) код будет фактически в заголовках, код, очевидно, будет увеличиваться с каждым включением пользователем в файл .cpp.
0

Я закончил тем, что использовал встроенные заголовки для всего кода. Вы можете увидеть библиотеку здесь:

https://github.com/libpropeller/libpropeller/tree/master/libpropeller

Библиотека структурирована как:

  • папка библиотеки
    • класс А
      • classA.h
      • classA.test.h
    • класс B
      • classB.h
      • classB.test.h
    • класс С

С этой структурой я могу распространять библиотеку как источник, и все, что нужно сделать пользователю, это включить -I/path/to/library в их makefile, и #include "library/classA/classA.h" в их исходных файлах.

И, как оказалось, наличие встроенных заголовков на самом деле уменьшает размер кода. Я сделал полный анализ этого, и оказывается, что встроенный код в заголовках позволяет компилятору сделать окончательный двоичный файл примерно на 5% меньше.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector