Переключение между исходным кодом и предварительно скомпилированными двоичными файлами - PullRequest
5 голосов
/ 28 апреля 2020

В нашем приложении огромное количество библиотек. Библиотеки написаны либо на с ++, либо на c#. (Платформа:. net framework, windows, 64 bit) Компиляция всего, что и исходный код, занимает много времени. Мы думали о переходе на готовые двоичные файлы, но мы все еще хотели бы оставить возможность вернуться к исходному коду. В качестве системы контроля версий мы используем git, сборка может быть сделана с помощью azure devops. Можно настроить любой пользовательский сервер, если это необходимо.

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

Можно ли определить разрывы Api / abi?

Ответы [ 6 ]

3 голосов
/ 30 апреля 2020

Какие существуют готовые инструменты для управления пакетами и возможности простого переключения между исходным кодом и предварительно созданными двоичными файлами?

В Visual Studio вы можете добавить ссылку на другой проект ( исходный код ) или другая библиотека ( dll ), но вы не можете добавить ссылку на проект из другого решения .

Если вы хотите переключаться между source и dll , то вам нужно продолжать добавлять / удалять проект из вашего решения ... это не хорошее программное обеспечение архитектура ... предполагает, что эти компоненты тесно связаны , и вам требуется исходный код одного компонента для тестирования другого. Компоненты программного обеспечения должны быть независимы друг от друга.


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

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

Например, вы можете иметь 2 решения:

Your Solution-1 содержит ваши проекты библиотеки классов. Вы можете создать пакет nuget для каждого проекта в этом решении. (Обратите внимание, что пакет nuget представляет собой .nupkg файл )

В вашем Solution-2 есть оставшиеся проекты, и вы можете установить вышеупомянутые пакеты здесь.

Если вы когда-либо необходимо изменить библиотеку, вы можете изменить ее в Solution-1 и создать новую версию ... конечно, вам нужно будет обновить пакет в Solution-2.

Примечание: вам не нужно иметь два отдельных решения для создания пакета Nuget ... вы можете создать пакет nuget для любой библиотеки классов

Публикация пакета

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

Breaking Изменения

Допустим, вы создали собственный пакет nuget: my-inhouse-lib и хотите внести в него критические изменения:

  1. Откройте my-inhouse-lib исходный код, внесите изменения, соберите и создайте съел новый пакет nuget, это будет: my-inhouse-lib-ver-2

  2. Ваш другой проект зависит от этого пакета, установите my-inhouse-lib-ver-2 в этом проекте (это ваша среда разработки)

  3. Ваша среда разработки будет повреждена из-за нового критического изменения ... исправить среда разработки

  4. Выпуск фиксированного кода в среду Test / Prod ...

В этом нет ничего особенного .. Это похоже на обновление любого другого пакета nuget

1 голос
/ 06 мая 2020

Я прочитал ваш вопрос, как о том, что зависимости есть. Net или C ++; и ваши окончательные выходные сборки. Net. Вы знаете, что NuGet - это «стандартный» инструмент. Net для всех связанных с зависимостями вещей.

Сейчас. Это зависит от того, что точно вы хотите с мыслью о легком «переключении» между источником и двоичным файлом?

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

Вариант 1. Вы имеете в виду «получить скорость сборки двоичного файла, но опыт отладки исходного кода»

Этого можно добиться с помощью NuGet. Вы используете Azure, так что вы можете добавлять задачи в сборки вашей библиотеки для публикации sh прямо в частный Azure канал NuGet. Ваша отправная точка для этого является

, которая говорит вам через

  1. Настройка подачи
  2. Publi sh в фид
  3. Использование фида

Nuget может дать вам полный опыт «исходного кода при отладке», потому что Nuget publi sh может включать исходные символы . Это описано на той же странице на якоре,

На компьютере разработчика замените зависимости от проектов в решении с зависимостями от пакета NuGet. После этого вы получите обычный опыт работы с Nuget:

  • Скомпилированные кеши NuGet .dll из канала на вашем компьютере
  • NuGet сообщит вам, когда будут доступны обновления
  • You выбрать, когда получить последнюю версию; ИЛИ вы можете принудительно устанавливать всегда обновление при сборке; ИЛИ вы можете установить принудительное обновление при проверке.

Принудительное обновление при извлечении даст вам возможность в стиле исходного кода всегда смотреть на (почти) последний код, но при этом иметь самую быструю сборку из двоичного кода. Вы можете принудительно установить update-on- git -checkout, добавив git ловушку post-checkout для запуска nuget update, так что каждый git get last будет одновременно получать последние из nuget. https://ddg.gg/example%20git%20oncheckout%20hook%20windows.

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

Вариант 2. Вы имеете в виду «возможность легко переключаться между сборкой из источника и build from binary '

Нет готового решения для этого, потому что это необычное требование. «Простой» подход состоит в том, чтобы иметь отдельные проекты и решения. Вместо этого спросите еще раз, чего именно вы пытаетесь достичь 1070 *?

Если вы просто хотите быть уверенным в сборке из самых последних источников, то Вариант 1 уже решает эту проблему - дать или занять несколько секунд - как для сервера сборки, так и для машин разработчика, потому что ваш Azure nuget Фиды всегда будут содержать самые последние сборки.

(На самом деле, если вы используете автоматизированные тесты, вариант 1 будет лучше , чем сборка из источника, поскольку он использует «самый последний источник, который собирает и проходит тесты», а не «самый последний» что кто-то случайно проверил в. ')

Если вы хотите «полный исходный код в моем проекте, но быстрая сборка», это может произойти автоматически: msbuild, как и cmake, не будет перестраивать проект, если он уже своевременно. Тем не менее, разработчики визуальных студий обычно помнят нажатие клавиш для восстановления (= clean + build) вместо build. Если у вас есть куча зависимостей, то изучение того, как изменить это нажатие одной клавиши, может сэкономить вам все время ожидания. Загвоздка в том, что если другие разработчики вносят много изменений, нельзя избежать времени get-latest-source-and-rebuild.

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

У вас могут быть разные файлы проекта для сборки dev machine и build server. Поддержание этого будет склонным к ошибкам перетаскиванием, поэтому вы должны script автоматически генерировать файлы csproj сервера сборки из стандартных. Затем сервер сборки может получать зависимости от nuget, в то время как машина разработчика использует исходные тексты и и также помещает обновления успешно собранных библиотек в канал nuget.

Комментарий: как близко мы можем достичь лучшего из обоих миров?

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

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

0 голосов
/ 08 мая 2020

Эта проблема имеет несколько осей - сборка исходного кода, установка пакета, внешние репозитории, разрывы api / abi, сборка самой системы.

Прежде всего, ваши требования - вас интересует только упаковка и / или также установка.

Для самой упаковки можно использовать, например, следующие системы упаковки: nuget, conan, vcpkg, choco.

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

Для azure документация по публикации devops / debug символов может быть найдена, например, по следующим ссылкам:

https://azure.microsoft.com/en-us/blog/deep-dive-into-azure-artifacts/ https://docs.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg

В настоящее время Conan (упаковка c ++) не поддерживает публикацию символов: https://github.com/conan-io/conan/issues/4047

Для получения исходного кода можно использовать саму git. Подмодули Git позволяют создавать внешние ссылки на репозиторий git, но как только вы добавили внешний подмодуль, вам нужно использовать двойную фиксацию, чтобы изменить все - один git коммит в суб-репозиторий, один git коммит для обновления, на который ссылаются git га sh из главного репозитория.

Действительно, существуют некоторые способы решения этой проблемы, такие как: вложенные git без подмодулей:

вложенные git репозитории без подмодулей ?

=>

http://debuggable.com/posts/git-fake-submodules: 4b563ee4-f3 cc -4061-967e-0e48cbdd56cb

Если вы строите однако основной репозиторий с предварительно собранными двоичными файлами вместо исходных кодов - в идеальном решении вам не нужен этот внешний репозиторий git, а это означает, что не требуется git клонирование / извлечение внешнего репозитория.

Тогда это также можно иметь либо all-in-one solution, либо несколько решений, каждое из которых скомпилировано отдельно.

Действительно, проще иметь all-in-one solution, поскольку с зависимыми решениями меньше проблем ilation.

Для создания полностью динамического c решения можно, например, использовать cmake - он может генерировать решение в зависимости от предварительно сконфигурированных опций, используемых в cmake. (См. Cmake "option").

cmake действительно хорошая альтернатива для C ++ (поддерживает предварительно скомпилированный заголовок, ускоряет построение единиц), но может быть не так просто для C# (сложно найти необходимые параметры для настройки это правильно).

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

Тогда по поводу упаковки. choco, кажется, является подмножеством nuget - он расширяет unspe c своими собственными xml тегами, поддерживающими обновление программного обеспечения. (ссылки на веб-страницы: https://chocolatey.org/, https://docs.microsoft.com/en-us/nuget/reference/nuspec)

Если вы хотите опубликовать sh пакет nuget или даже пакет установщика, можно использовать хранилище nuget (без каких-либо дополнительных затрат).

Если этого недостаточно для вас, возможно также обновить сервер nuget до сервера choco, но это может стоить чего-то - см. шоколадные веб-страницы.

Api Разрывы / abi не могут наблюдаться на любом уровне, пока не произойдет ошибка компиляции / ссылки или не произойдет сбой приложения во время выполнения - единственная альтернатива, которую это возможно сделать, - это управление версионированием самой упаковки - так, чтобы версия основного пакета nuget (или choco) требуется более высокая версия зависимой версии nuget (или choco).

Если основной репозиторий разрабатывается теми же парнями, что и дочерний репозиторий, - то разрывы api / abi могут выполняться самим разработчиком, но если два git независимы от каждого другие и разрабатываются разными командами - тогда перерывы api / abi могут произойти в любой момент времени.

Лучший способ достичь То, что репозитории являются согласованными, - это проведение модульного тестирования в главном репозитории, которое будет проверять, не происходит ли разрыв api / abi.

Теоретически, если происходят разрывы api / abi - сама система сборки может продолжаться с двумя альтернативами сборки. -

  1. следовать за основным хранилищем с последним работающим дочерним хранилищем
  2. следовать за дочерним хранилищем без создания основного хранилища

Та же самая механика может быть применена с использованием веток, например

  1. "main git: основная ветка" + "child git: ветка release / 1.0 "
  2. " child git: ветка master "

Этот механизм может потребовать наблюдения не только двух репозиториев, но и переключения ветвей в случае длительных сбоев. (Например, команда разработчиков child git не заботится о сбоях сборки, происходящих в main git)

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

И последнее, но не менее важное - если вы хотите, чтобы ваше приложение поддерживало обновление программного обеспечения - тогда Загрузка дистрибутива nuget / choco может использоваться с дополнительным сервером nuget / choco.

Вот хороший пример части загрузки для пакета nuget: https://github.com/mwrock/NugetDownloadFeed

Установка сборки пакета немного более сложный вопрос - см., например, следующие ссылки:

(В порядке лучше-хуже на мой взгляд)

0 голосов
/ 07 мая 2020

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

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

project_folder
|-- lib
|   |-- LibA.cpp
|   |-- LibA.hpp
|-- tools
|   |-- conanfile.py
|   |-- conanfile.txt
|-- CMakeLists.txt
|-- main.cpp  

каковы они должны быть: CMakeLists.txt - это ваш cmake файл конфигурации для обработки

Можно ли определить разрывы Api / abi?

и conanfile.py - ваш рецепт, означает, что вам нужно пакет и создать ваши предварительно собранные библиотеки, а conanfile.txt - ваш требуемый файл для использования ваших предварительно собранных библиотек.

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

Теперь давайте рассмотрим мой пример и способы его использования: CMakeLists.txt :

cmake_minimum_required(VERSION 3.15)

project(my_project LANGUAGES CXX)

add_library(LibA lib/LibA.cpp)

add_executable(ExecutableA main.cpp)
target_link_libraries(ExecutableA LibA)

target_include_directories(LibA PUBLIC ${CMAKE_CURRENT_LIST_DIR}/lib)

Я буду придерживаться cpp в моем примере, но для вашей .net рамки вы можете проверить это или это

Таким образом, я просто определяю targets в этих файлах и объявляю его зависимости друг от друга со следующим содержанием: main. cpp:

#include <iostream>
#include "LibA.hpp"


int main()
{
  printTesting();
  std::cout << "Hello World! again" << std::endl;
  return 0;
}

LibA. cpp:

#include <iostream>
#include "LibA.hpp"

void printTesting(void)
{
  std::cout << "Testing Something" << std::endl;
}

LibA.hpp :

#include <iostream>

void printTesting(void);

Я просто предполагаю , вы не знакомы с cmake : мы позволим cmake сгенерировать Makefile для нас или для вас evtl. .vcxproj, если вы используете генератор .net, но я хочу, чтобы здесь все было просто, поэтому мы сконфигурируем проект и соберем двоичные файлы.

mkdir ../build && cd ../build
cmake ../project_folder && make

вы получите свои LibA и ExecutableA, так что ничего особенного здесь пока нет, просто теперь cmake позаботится о ваших зависимостях, и evtl. восстановите их, если что-то изменилось (например, новые коммиты в ваших проектах). с conanfile.py вот так:

from conans import ConanFile, tools


    class LibAConan(ConanFile):
        name = "libA"
        version = "0.1"
        settings = "os", "compiler", "build_type", "arch"
        description = "<Description of LibA here>"
        url = "None"
        license = "None"
        author = "None"
        topics = None

        def package(self):
            self.copy("*.a")

        def package_info(self):
            self.cpp_info.libs = tools.collect_libs(self)

вы хотите:

cp ../project_folder/tools/conanfile.py && conan export-pkg . libA/0.1@myuser/testing

с нашим именем пакета: libA в 0.1 версии. myuser/testing - это канал, который интересен, если вы выполняете кросс-компиляцию для нескольких целевых платформ.

Мы создали повторно используемый пакет, вызвав conan export-pkg, и он кэшируется в $HOME_DIR/.conan/data/libA/0.1/myuser/testing (или проверьте это в вашей среде: conan config home)

Евтл. сначала вы хотите установить conan, поэтому ознакомьтесь с этим указанием по установке или загрузками и для вашей специальной настройки: conan с azure devops

Таким образом, эти созданные пакеты также могут быть загружены в любой remote_server : $ conan upload libA/0.1@myuser/testing --all -r=my_remote_server (по аналогии: как git push после коммита в git).

Таким образом, у нас есть configured, built с cmake и created и uploaded пакетами, использующими conan , ваши коллеги могут повторно использовать предварительно собранные пакеты / двоичные файлы, определив их требования в pythonfile.txt :

[requires]
libA/0.1@myuser/testing

[generators]
cmake

, и они могут сделать:

mkdir ../build_using_prebuild && cd ../build_using_prebuild && cp ../project_folder/tools/conanfile.txt . && conan install -g deploy . -r my_remote_server

conan будет искать этот требуемый пакет и evlt. скачайте его с my_remote_server

Если теперь они запускают cmake ../project_folder && make, будут использоваться эти готовые пакеты вместо компиляции sr c с нуля.

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

0 голосов
/ 03 мая 2020

Для проектов C ++ вы можете проверить CMake для ваших целей. Вы можете сохранить различные параметры сборки, такие как: 1) сборка всего исходного кода; 2) сборка подмодулей в библиотеки один раз и повторное использование для основного проекта. Последний CMake также поддерживает предварительно скомпилированные заголовки. Вы также можете проверить это, чтобы сократить время компиляции.

Conan и vcpkg - два менеджера пакетов, доступные для модулей C ++

0 голосов
/ 03 мая 2020

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

Для C ++ вы можете использовать Conan (Я уверен, что есть и другие подобные инструменты, но я не использовал их). Вы можете загрузить свои предварительно собранные пакеты на сервер, и ваши разработчики могут установить их при необходимости. Это было бы так же просто, как добавить зависимости в список требований файла conanfile.py, который вы храните как часть своих проектов. А для сборки из источников (например, когда на вашем сервере отсутствуют двоичные файлы) вы можете добавить опцию --build к команде conan install (которая устанавливает зависимости вашего проекта).

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

Вы пытаетесь переключаться между сохранением зависимости в исходном дереве вашего проекта в отличие от связи с двоичным файлом? Я не вижу каких-либо долгосрочных преимуществ от наличия этого в вашем исходном дереве, если вы используете менеджер пакетов. Конечно, было бы немного удобнее изменить исходный код зависимости, если он является частью дерева исходных текстов (например, не нужно переключаться между каталогами), но я бы сказал, что он, вероятно, более организован и эффективен в долгосрочной перспективе. запустить, чтобы изменить зависимость отдельно в своем собственном проекте. (а в Конане вы можете использовать «пользователи» и «каналы» для управления этими пользовательскими версиями сторонних библиотек)

Можно ли идентифицировать разрывы Api / abi

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

Преимуществом использования Conan может быть то, что вы также можете добавлять зависимости сборки, которые вносят в вашу среду. Например, CMake может быть зависимостью сборки. Таким образом, ваш пакет сначала установит указанную версию CMake, а затем остальные ваши зависимости, созданные с помощью CMake. Это значительно упрощает управление DevOps.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...