2013-07-30 3 views
3

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

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

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

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

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

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

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

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

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

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

+0

Файлы библиотеки в основном являются стандартными. Если у вас есть оговорки в отношении создания библиотек, подумайте о них.Это проще в использовании, чем make, и не привяжет ваш код к пути configure/make. Это также упрощает работу портов в Windows. – Jiminion

ответ

0

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

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

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

  • библиотека папку
    • Класс A
      • classA.h
      • classA.test. ч
    • класс В
      • classB.h
      • classB.test.h
    • класс С
    • ...

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

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

0

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

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

0

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

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

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

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

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

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

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

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

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