Как правильно разделить проект Delphi на BPLs?
компания, в которой я работаю, разрабатывает систему в Delphi, которая содержит десятки exe-модулей, и каждый из них в определенной степени идентичен исходному коду. К сожалению, никто никогда не заботился об использовании библиотек для ввода общего кода. Это означает, что каждый раз, когда есть исправление ошибки в коде, все эти модули разделяют, программист должен внести исправления во всех из них отдельно! Это всегда занимает так много времени...
Я решил найти способ поставить общий код в библиотеки. Я рассматривал библиотеки DLL и BPLs. В этом случае BPLs казался гораздо более удобным для программиста и гораздо менее хлопотным, тем более, что код используется только в нашем программном обеспечении и только в Delphi.
Я поместил весь код, разделяемый всеми модулями exe, в BPLs, и все кажется прекрасным, но есть некоторые вещи, которые я не понимаю и был бы признателен, если бы вы объяснили их мне.
Что я ожидал после разделения кода на BPLs было бы достаточно развернуть exe-файлы с помощью bpls, которые я создал. Но оказалось, что им нужен rtl100.bpl и vcl100.БПЛ, а также. Почему это так? Я хочу развернуть exes и только мои BPLs. Я не хочу предоставлять конечным пользователям целую кучу библиотек, поставляемых Borland и сторонними компаниями :). Я хочу, чтобы они были скомпилированы в exes, как они были скомпилированы раньше. Возможно ли это сделать?
-
Что я сделал до сих пор было:
- Я поставил все общие единицы pas в BPLs. Каждый BPL содержит единицы, принадлежащие к той же категории, поэтому программистам ясно, какой код ожидать в данном BPL.
- каждый BPL является библиотекой" время выполнения и время разработки".
- каждый BPL "перестроен явно". Два последних являются настройками проекта по умолчанию для BPLs.
-
и если дело доходит до exe-проектов:
- Я удалил все блоки, которые я раньше ставил на BPLs.
- Я установил свой BPLs из меню Tools - >Install package в BDS 2006.
- в моих настройках проекта exe я проверил опцию "построить с пакетами времени выполнения", и я перечислил все мои пакеты BPL в поле редактирования ниже (только мои пакеты, поскольку я очистил все другие, которые там появились).
Это все, что я сделал. Проекты exe компилируются правильно, но у меня нет доступа к исходному коду BPLs (я не могу перемещаться в этот код из моих exe-проектов), хотя все BPLs хранятся вместе со своими файлами исходного кода. Почему? Мне это кажется странным.
Я всегда склонен писать длинные описания-извините за это:). Буду признателен за помощь. Мне просто нужно несколько слов объяснения тем пунктам, которые я упомянул: развертывание exe только с моими BPLs, правильность того, что я сделал в целом, и невозможность навигации по исходным кодам BPL. Большое спасибо вперед!
спасибо всем за обсуждение. Некоторые говорили, что подход, который я выбрал, не был хорошей идеей. Наше программное обеспечение состоит из более чем 100 модулей (большинство из них что-то вроде драйверов для разных устройств). Большинство из них имеют один и тот же код - в большинстве случаев классы. Проблема в том, что эти классы не всегда помещаются в отдельные, автономные единицы pas. Я имею в виду, что общий код часто помещается в блоки, содержащие код, специфичный для модуля. Это значит, что когда ты исправьте ошибку в общем классе, недостаточно скопировать pas-модуль, в котором он определен, во все программные модули и перекомпилировать их. К сожалению, вы должны скопировать и вставить фиксированные фрагменты кода в каждый модуль, один за другим, в соответствующий блок и класс. Это занимает много времени и это то, что я хотел бы устранить, подобрав правильный подход - пожалуйста, помогите мне.
Я думал, что использование BPLs будет хорошим решением, но у него есть некоторые недостатки, как некоторые из вас упоминали. Этот худшая проблема заключается в том, что если каждый EXE нуждается в нескольких BPLs, наша служба технической поддержки должна знать, какой EXE нуждается в каких BPLs, а затем предоставить конечным пользователям соответствующие файлы. До тех пор, пока у нас нет программы обновления, это будет много как для наших техников, так и для конечного пользователя. Они наверняка заблудятся и рассердятся : -/.
также могут возникнуть проблемы совместимости - если один BPL разделяется многими EXEs, модификация одного BPL может быть хорошей для одного EXE и плохой для некоторых других - @Уоррен П.
Что мне делать, чтобы быстрее исправлять ошибки во многих проектах? Я думаю об одном из следующих подходов. Если у вас есть идеи получше, пожалуйста, дайте мне знать.
- поместите общий код в отдельные и автономные блоки pas, поэтому, когда в одном из них есть исправление ошибки, достаточно скопировать его во все проекты (перезаписать старые файлы) и перекомпилировать их все.
Это решение, кажется, в порядке, насколько измененный код concrened. Но у нас также есть pas - блоки с функциями и процедурами общего пользования, которые часто не поддаются модификации-мы добавляем новые функции там, где это необходимо, но в отдельных проектах. Итак, представьте, что вы пишете новую функцию в одном из 100 модулей и помещаете ее в блок общего использования. Через месяц или два вы модифицируете другой модуль, и вы думаете, что вам нужна та же функция, которую вы написали 2 месяца назад. Вы должны найти модуль (это трудно, если вы не помните, какой one it was) и скопируйте функцию в свой код. И очевидно-единицы общего пользования становятся совершенно разными в каждом модуле, пока они хранятся в каждом проекте отдельно. И затем, если есть исправление ошибки... вся история повторяется.
- создайте BPLs для всего общего кода, но свяжите их в EXEs, чтобы EXEs были автономными.
для меня это кажется лучшим решением сейчас, но есть несколько минусов. Если я исправлю ошибку в BPL, каждый программист должен будет обновить BPLs на своем компьютере. Что, если они забудут? Но все же, я думаю, это небольшая проблема. Если мы позаботимся об информировании друг друга об изменениях, все должно быть хорошо.
- @CodeInChaos: не знаю, правильно ли я вас понял. Вы имеете в виду обмен файлами pas между проектами? Как это сделать? Мы храним исходные коды в SVN. Это означает, что нам придется хранить общий код в отдельной папке и выполнять поиск этого кода во всех проектах там, верно? И загрузите из SVN проект и все папки, от которых он зависит...
пожалуйста, помогите мне выбрать хорошее решение. Я просто не хочу, чтобы компания теряла намного больше времени и денег, чем необходимо, на исправлениях только из-за глупого подхода к разработке программного обеспечения.
большое спасибо.
4 ответов
несмотря на то, что этот вопрос имеет принятый ответ, я собираюсь его попробовать.
заголовок спрашивает, Как разделить проект на bpls, но реальный вопрос, похоже,: "Каков наилучший способ обмена кодом между проектами?"
есть несколько способов сделать это:
- общий подразделений
- библиотеки
- BPLs
независимо от того, в каком направлении вы идете, вам, вероятно, потребуется реструктурировать проекты. Из вашего описания кажется, что каждый проект разрабатывается в относительной изоляции. Код используется совместно с помощью copy / paste, который быстро выходит из синхронизации и приводит к большому количеству дублированных усилий. Итак, давайте рассмотрим каждый из методов совместного использования кода.
общий подразделений
Это самый простой подход. Вы создаете общее местоположение и код места, который вы хотите повторно использовать среди своих проектов в этом местоположении. Блоки статически связанные с вашими проектами, поэтому вам не нужно беспокоиться о развертывании дополнительных зависимостей вместе с основными исполняемыми файлами. Статически связанные блоки на сегодняшний день проще всего устранить неполадки и отладить.
компилятор должен иметь возможность находить ваши общие единицы. Существует 4 способа сообщить компилятору, где искать.
- добавить их в проект - SHIFT+F11 - добавляет ссылку на устройство в файлы проекта (dpr, dproj). интегрированная среда разработки обычно будут использоваться относительные пути, если устройство находится под тем же деревом каталогов, что и файлы проекта, в противном случае оно будет использовать абсолютные пути, что может быть проблематично, если машины разработчиков не настроены идентично.
- проекта Путь Поиска - CTRL+ SHIFT+F11 Delphi Compiler > Search path-добавьте каталог, и компилятор будет искать там единицы, упомянутые в предложении uses любой единицы в проект. Лучше всего использовать относительные пути, если вы можете. Вы также можете использовать переменные среды: $(MyPath)
- глобальный путь поиска-Инструменты > Параметры > параметры среды > параметры Delphi > библиотека-Win32 > путь к библиотеке - все пути, перечисленные здесь, доступны для всех проектов на компьютере. это зависит от машины
- Командная строка - если вы строите из скрипта или инструмента автоматизации сборки, вы можете установить путь поиска с помощью dcc32
-U
переключатель илипереключатель.
опции 1 и 2 будут наиболее полезными.
Что касается вашего репозитория SVN, у вас есть несколько вариантов организации проектов и общих блоков. Проще всего было бы разместить все проекты под одной магистралью вместе с общими блоками:
Projects
trunk
ProjectA
ProjectB
ProjectC
Library (shared units)
если по какой-то причине вышеуказанная структура невозможна, вы можете попробовать эту альтернативу:
ProjectA
trunk
Library (branch of main library)
ProjectB
trunk
Library (branch of main library)
ProjectC
trunk
Library (branch of main library)
Library
trunk (main library)
в этого настройки для каждого папка библиотеки проекта не будет сразу доступна для других проектов. Каждый проект должен будет регулярно синхронизировать изменения с основным проектом библиотеки. Побочным эффектом этого является то, что изменения, которые нарушают другие проекты, будут отложены до синхронизации других проектов. Считаете ли вы это хорошим или плохим зависит. С одной стороны, ошибки легче и дешевле исправить, когда код, который они включают, все еще свеж в сознании разработчика. С другой стороны, если вы не практикуете модульное тестирование (что я настоятельно рекомендую вам сделать), или код очень хрупкий, или у вас просто есть разработчики, склонные к безрассудным изменениям, которые вы можете контролировать, как часто эти изменения выталкиваются в другие проекты.
библиотеки
DLL позволяют обмениваться кодом, связываясь с ним во время выполнения. Они предоставляют функции, которые могут быть вызваны из основного исполняемого файла или другой dll.
в то время как DLL всегда связаны во время выполнения, вы решаете загружаются ли они при запуске приложения или только при необходимости. Загрузка при запуске называется статическая нагрузка и в Delphi выполняется с помощью
представьте, что у вас есть проект с EXE и двумя разными модулями BPL, и где-то в этой кодовой базе есть строка, которая говорит if MyObject is TStringList then DoSomething;
. The is
оператор работает, исследуя метаданные класса объекта, хранящиеся в VMT, а затем следуя цепочке VMTs через ClassParent
указатель, чтобы увидеть, соответствует ли какой-либо из них ссылке класса (также указателю VMT) для TStringList
. Чтобы убедиться, что это будет работать правильно, должен быть один единственный VMT для TStringList, который то же самое во всей вашей программе, независимо от того, на сколько BPLs она разделена, что означает, что она должна быть в своем собственном пакете. Вот почему системные среды выполнения, такие как rtl*.bpl и vcl*.bpl необходимы, и вы мало что можете с этим поделать. Это часть цены использования BPLs.
что касается невозможности отладки, вам нужно убедиться, что BPLs построены с включенной отладочной информацией и что отладчик знает, как найти папку, где DCP (файл, содержащий отладку информация для The BPL) находится. И вы не сможете отслеживать в system BPLs, потому что DCPs с поддержкой отладки не были отправлены с вашей версией. Они были добавлены совсем недавно, я думаю, в XE, но это могло быть в D2010.
почему я не могу просмотреть исходный код? Есть ли способ исправить это?
вы не можете просмотреть исходный код единиц, включенных в пакеты, потому что они не находятся ни в вашем проекте, ни в вашей библиотеке или пути поиска.
способ, которым я решаю это, добавляет каталоги в путь поиска проекта. Таким образом, компилятор не знает об этих файлах (и не пытается их перекомпилировать), но IDE позволяет вам просматривать их содержание и отладка в них.
"в моих настройках проекта exe я проверил опцию "построить с пакетами времени выполнения"
вот почему вы не можете развернуть без BPL и т. д. - Эта опция сбивает с толку многих разработчиков - "сборка с пакетами времени выполнения" означает, что вам понадобится присутствие bpl во время выполнения. снимите этот флажок, и пакеты будут связаны с вашим exe в compileTime. (Ваш exe будет g-r-o-w в размере.) Идея "сборки с пакетами времени выполнения" заключается в том, чтобы сохранить размер exe и позволяют нескольким приложениям делиться общими bpl, потому что они не связаны с exe @ compileTime - это вверх. Недостаток, который вы сейчас испытываете, - вы должны распространять свои bpl с помощью exe.