Хотя я умею кодировать, у меня пока нет опыта работы над большими проектами. До сих пор я занимался написанием небольших программ, которые компилируются за считанные секунды (различные упражнения на языке c / c ++, такие как алгоритмы, принципы программирования, идеи, парадигмы, или просто тестирование API-интерфейсов ...) или работой над небольшими проектами, которые были сделано на скриптовом языке (ах) (python, php, js), где компиляция не требуется.
Дело в том, что при кодировании на языке сценариев, когда я хочу попробовать, если что-то работает, я просто запускаю сценарий и вижу, что происходит. Если что-то не работает, я могу просто изменить код и попробовать его снова, запустив скрипт снова и продолжая делать это, пока не получу желаемый результат ... Я хочу сказать, что вам не нужно ждать что-нибудь для компиляции, и из-за этого довольно легко взять большую базу кода, изменить ее, добавить что-то к ней или просто поиграть с ней - вы можете увидеть изменения мгновенно.
В качестве примера я возьму Wordpress. Это довольно легко попытаться понять, как создать плагин для него. Сначала вы создаете простой плагин «Hello World», затем создаете простой интерфейс для админ-панели, чтобы познакомиться с API, затем создаете его и делаете что-то более сложное, в то же время изменяя его внешний вид. раз ... Идея перекомпилировать что-то такое большое, как WP, снова и снова, после каждого незначительного изменения, пытаясь "если это работает" и "как это работает / чувствует", кажется неэффективной, медленной и неправильной.
Теперь, как я могу сделать это с проектом, который написан на скомпилированном языке? Я хотел бы внести свой вклад в некоторые проекты с открытым исходным кодом, и этот вопрос продолжает меня беспокоить. Ситуация, вероятно, отличается от проекта к проекту, где некоторые из них, которые были заранее продуманы, будут в некотором роде «модульными», в то время как другие будут просто одним большим двоичным объектом, который необходимо перекомпилировать снова и снова.
Я хотел бы узнать больше о том, как это делается правильно. Каковы некоторые общие практики, подходы и проекты (шаблоны), чтобы справиться с этим? Как эта «модульность» называется в мире программистов и для чего мне нужно поискать в Google? Часто ли проекты вырастают из своих первых масштабов, что через некоторое время становится проблематичным? Есть ли способ избежать долгой компиляции не очень хорошо разработанных проектов? Способ как-то их модульно (возможно, исключить не жизненно важные части программы при разработке (какие-либо другие идеи?))?
Спасибо.
источник
Ответы:
Как было сказано, вы никогда не перекомпилируете весь проект каждый раз, когда вносите небольшие изменения. Вместо этого вы перекомпилируете только часть измененного кода, а также весь код, зависящий от него.
В C / C ++ компиляция довольно проста. Вы компилируете, переводите каждый исходный файл в машинный код (мы называем их объектными файлами * .o) и затем связываете все свои объектные файлы в один большой исполняемый файл.
Как упоминалось в MainMa, некоторые библиотеки встроены в отдельные файлы, которые будут динамически связаны во время выполнения с исполняемым файлом. Эти библиотеки называются общими объектами (* .so) в Unix и динамически связанными библиотеками (DLL) в Windows. Динамические библиотеки имеют много преимуществ, одним из которых является то, что вам не нужно их компилировать / связывать, если только их исходный код не изменится.
Существуют инструменты автоматизации сборки, которые помогут вам:
Самые известные из них (make, ant, maven, ...) могут автоматически определять, какие части кода были изменены с момента последней компиляции, и какой именно объект / двоичный файл необходимо обновить.
Однако это связано с (относительно небольшими) затратами на написание «сценария сборки». Это файл, содержащий всю информацию о вашей сборке, например определение целей и их зависимостей, определение компилятора, который вы хотите и какие параметры использовать, определение среды сборки, путей к библиотекам, ... Возможно, вы слышали о файлах Makefile (очень распространенный в мире Unix), или build.xml (очень популярный в мире Java). Это то, что они делают.
источник
build.xml
файлеВы не перекомпилируете весь проект каждый раз. Например, если это приложение на C / C ++, есть вероятность, что оно будет разделено на библиотеки (библиотеки DLL в Windows), каждая библиотека будет скомпилирована отдельно.
Сам проект обычно компилируется ежедневно на выделенном сервере: это ночные сборки. Этот процесс может занять много времени, поскольку он включает в себя не только время компиляции, но также время, потраченное на выполнение модульных тестов, других тестов и других процессов.
источник
Я думаю, что все ответы до сих пор тоже намекали на то, что крупные программные проекты почти всегда разбиты на гораздо более мелкие части. Каждый кусок обычно хранится в своем собственном файле.
Эти части индивидуально скомпилированы для создания объектов. Объекты затем связываются вместе, чтобы сформировать конечный продукт. [В каком-то смысле это похоже на создание чего-то из Легоса. Вы не пытаетесь изготовить окончательную вещь из одного большого куска пластика, вместо этого вы комбинируете кучу меньших кусков, чтобы сделать это.]
Разбиение проекта на части, которые скомпилированы по отдельности, позволяет делать некоторые интересные вещи.
Инкрементное здание
Прежде всего, когда вы меняете одну часть, вам обычно не нужно перекомпилировать все части. Вообще говоря, до тех пор, пока вы не измените, как другие части взаимодействуют с вашей частью, другие не нужно перекомпилировать.
Это порождает идею постепенного наращивания . При инкрементной сборке перекомпилируются только части, на которые повлияло изменение. Это значительно ускоряет время разработки. Правда, вам, возможно, все еще придется ждать, пока все будет перекомпоновано, но это все равно экономия на необходимости перекомпилировать и перекомпоновывать все. (Кстати: некоторые системы / языки поддерживают инкрементное связывание, поэтому необходимо пересвязывать только те вещи, которые изменились. Обычно это связано с низкой производительностью и размером кода.)
Модульное тестирование
Второе, что позволяют делать маленькие кусочки, это посмотреть на индивидуальное тестирование кусочков до их объединения. Это известно как модульное тестирование . В модульном тестировании каждый модуль тестируется индивидуально, прежде чем он интегрируется (комбинируется) с остальной частью системы. Модульные тесты обычно пишутся так, чтобы их можно было быстро запускать без участия остальной системы.
Ограничительный случай применения тестирования можно увидеть в Test Driven Development (TDD). В этой модели разработки ни один код не написан / изменен, если он не предназначен для исправления неудачного теста.
Делать это проще
Так что разбивать вещи кажется хорошим, но также кажется, что для создания проекта требуется много работы: вам нужно выяснить, какие части изменились и что зависит от этих частей, скомпилировать каждую часть, а затем связать все вместе.
К счастью, программисты ленивы *, поэтому они изобретают множество инструментов, чтобы облегчить их работу. Для этого было написано много инструментов для автоматизации вышеуказанной задачи. Самые известные из них уже были упомянуты (make, ant, maven). Эти инструменты позволяют вам определить, какие части должны быть собраны вместе, чтобы сделать ваш окончательный проект и как части зависят друг от друга (то есть, если вы измените это, это необходимо перекомпилировать). В результате, если выполнить только одну команду, выясняется, что нужно перекомпилировать, компилирует и связывает все заново.
Но это все еще не позволяет понять, как вещи связаны друг с другом. Это большая работа, и, как я уже говорил, программисты ленивы. Таким образом, они придумали другой класс инструментов. Эти инструменты были написаны, чтобы определить зависимости для вас! Часто инструменты являются частью интегрированных сред разработки (IDE), таких как Eclipse и Visual Studio, но есть и некоторые автономные, используемые как для универсальных, так и для специальных приложений (makedep, QMake для программ Qt).
* На самом деле, программисты не очень ленивы, они просто любят тратить свое время на работу над проблемами, а не на выполнение повторяющихся задач, которые могут быть автоматизированы программой.
источник
Вот мой список вещей, которые вы можете попробовать ускорить сборку C / C ++:
источник
Выполнение чего-то интерпретируемого также очень неэффективно и медленно, и (возможно) неправильно. Вы жалуетесь на требования к времени на компьютере разработчика, но не компилируете, что требует времени на компьютере пользователя , что, возможно, намного хуже.
Что еще более важно, современные системы могут выполнять довольно сложные инкрементные перестройки, и нередко перекомпилировать все это для незначительных изменений - скомпилированные системы могут включать компоненты сценариев, особенно общие для таких вещей, как пользовательский интерфейс.
источник
Если в проекте реализована правильная DAG-зависимость для компиляции, вы можете избежать перекомпиляции только тех объектных файлов, на которые влияют ваши изменения.
Также при условии правильной зависимости DAG от компиляции вы можете компилировать, используя несколько процессов. Одна работа на ядро / процессор является нормой.
Вы можете создать несколько исполняемых файлов для тестирования, которые связывают только определенные объектные файлы.
источник
В дополнение к ответу MainMa, мы также только что обновили машины, на которых работаем. Одной из лучших покупок, которые мы сделали, был SSD, когда вы не можете не перекомпилировать весь проект.
Другим предложением было бы попробовать другой компилятор. Когда-то мы перешли от компилятора Java к Jikes, и теперь мы перешли к использованию компилятора, поставляемого в комплекте с Eclipse (не знаю, есть ли у него имя), который использует преимущества многоядерных процессоров.
Наш 37000 файловый проект занял около 15 минут, чтобы скомпилировать с нуля, прежде чем мы внесли эти изменения. После изменений его сократили до 2-3 минут.
Конечно, стоит еще раз упомянуть точку зрения MainMa. Не перекомпилируйте весь проект каждый раз, когда вы хотите увидеть изменения.
источник