2016-10-28 10 views
0

Ситуация:Управление тонн 3rdParty зависимостей в PInvoke для повышения скорости компиляции

Я работаю над исследовательским проектом, который, из-за некоторых ограничений, имеет C# пользовательский интерфейс (используется в основном для визуализации), но выполняет большую часть обработки с помощью PInvoke и неуправляемого кода на C++. Неуправляемый код имеет TONS зависимостей от различных библиотек 3rdparty: Boost, PCL, OpenCV, CGAL, VTK, Eigen, FLANN, OpenMesh и т. Д. (Если вы можете назвать это, мы, вероятно, будем зависеть от этого!). Проект C# взаимодействует с проектом C++ (который я теперь называю «оберткой»). Очевидно, что оболочка - это то, где потребляются все зависимости 3rdparty и где указаны точки входа для PInvokes. Обертка компилируется в DLL и копируется в выходной каталог проекта C# через событие post-build.

Я являюсь единственным разработчиком проекта. Моя основная платформа разработки - Windows 10 с Visual Studio 2015, а Git - мой контроль версий. В основном я занимаюсь разработкой на 3 разных станках, но иногда мне приходится разрабатывать на других машинах, на которых установлена ​​только Visual Studio 2015.

Что я сделал до сих пор:

Obsiously, управление все эти 3rdParty зависимости хлопот для одного человека, и я не хотел бы, чтобы установить эти библиотеки на новых машинах развития. Я сделал то, что я скомпилировал все эти библиотеки 3rdparty из источника в статические файлы lib (за исключением явно только заголовков). Все источники построены один раз для конфигурации Debug и один раз для конфигурации Release. Я потратил некоторое время и включил их в мой проект оболочки (т. Е. Определил дополнительные каталоги include, используя множество #pragma comment (lib, "blah.lib"), которые ссылаются на разные сборки в зависимости от конфигурации сборки и т. Д.). Я также воспользовался некоторыми советами в Microsoft's linker best practices, чтобы сократить время ссылки. В частности, я использую инкрементный компоновщик, я отключил /LTCG и /OPT.

Теперь у меня есть эта гигантская папка «Зависимости» в моем VS-решении, которая составляет около 8 ГБ, и контролируется версиями отдельно от проекта (с использованием подмодуля Git). Проект-обертка статически привязан ко всем этим, и в результате и, как упоминалось выше, после создания проекта-обертки создается только одна DLL. Поверхность этого подхода заключается в том, что на любой новой машине разработки я клонирую основной репозиторий, клонирую подмодуль Зависимости, и я готов к работе! Но ...

Худшая часть:

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

Мой вопрос:

Очевидно, что я неопытная в этом! Как я должен поступать по-другому, особенно учитывая зависимости, упомянутые выше? Улучшалось ли создание библиотек DLL вместо статических библиотек? Но тогда мне пришлось бы добавлять зависимости к PATH каждый раз, когда запускалась программа C# (as mentioned here). Как вопрос, как вы оцениваете мой нынешний подход?

+0

Действительно ли вам нужны все эти зависимости в одном исполняемом файле? Можно ли разделить ваше приложение на разные «службы»? Таким образом, пользовательский интерфейс может получить доступ к другому исполняемому файлу в зависимости от задачи, или если задачи связаны, они могут связываться через IPC. Тогда у вас может быть несколько меньших исполняемых файлов с меньшим количеством зависимостей. – silverscania

+0

@silverscania Я делаю, и я не могу сломать исполняемый файл, к сожалению ... Дело в том, что исполняемый файл регулярно используется другой группой, и они используют его для части своей системы ... Легче отправить что-то в они работают из коробки ... – M2X

+2

Тогда я думаю, что если ваша проблема связана только со ссылками, тогда DLL - это путь. Вам не нужно изменять PATH, если они находятся в одном каталоге или в подкаталоге вашего приложения. – silverscania

ответ

1

Основываясь на комментарии от @silverscania, я решил просто взять DLL-маршрут. Было немного боли, восстанавливающей все зависимости, но теперь я очень доволен результатами.

Теперь, построение всего решения с нуля занимает 36 секунд! Раньше было около 4 минут, поэтому мне нечего жаловаться. Кроме того, изменение одного файла в проекте-обертке и создание снова занимает 3 секунды, что удивительно! Тот факт, что все скомпилированные зависимости теперь составляет около 1 ГБ (против ~ 8 ГБ со статическими библиотеками), является плюсом! Я не мог быть счастливее.

coupt нот:

  1. На главной машине, где я делаю большую часть своего развития, у меня есть SanDisk SSD. Я заметил, что по какой-то причине, кроме моего понимания, создание проекта на этом устройстве было способом медленнее по сравнению с обычным жестким диском. Я изучаю эту проблему, но не нашел причины для этого (TRIM включен и диск находится в режиме AHCI).
  2. Я играл с флагами немного больше. Я заметил, что флаг компилятора /GL (оптимизация всей программы) вызвал значительное замедление во время связывания. Я тоже отключил эту опцию.