MsBuild покорён

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

При сборке, а точнее в самом её конце, перед PostBuildEvent, выполняется таск IncrementalClean, суть которого заключается в том, чтобы удалить все файлы, которые не были произведены текущей сборкой. Задумка простая и очень хорошая, таким образом мы решаем проблему того, что файл поудалял или переименовал файлы в проекте, а вот реализация, как всегда, подкачала.
Выглядит это приблизительно так:
Мы начинаем сборку, у нас компилируются исходники, получаются объектники, потом линковка и вуаля – исполняемый файл – все счастливы. Но оно заканчивается на второй сборке – очень умный msbuild видит, что файлы не менялись, поэтому компиляцию и линковку пропускает и вот тут-то нас и ждёт коварный IncrementalClean – он удаляет obj файлы, которые мы получили на прошлой сборке. Ещё он должен удалять и исполняемый файл, но этого, замечу, не делает.
Поиски по форумам и задавание вопросов специалистам из microsoft успехом не увенчались, поэтому пришлось копаться в потрохах msbuild и его сборочных скриптов. Попытки переопределить метод IncrementalClean успехом не увенчались, т.к. перестал даже простой clean работать. В конце-концов я попытался до конца разобраться, почему не удалялся исполняемый файл, ведь линковка тоже пропускалась. Оказалось, потому что переменная, в которой я хранил имя OutputName было magic. У msbuild есть волшебный таск, _CheckForCompileOutput, который проверяет существует ли “выход” компилятора, и если да, то пишет его в тот самый файл, по которому потом производится очистка, или не очистка. Но он, сцуко, работает только с одиночными файлами на входе (не забываем, что эта ацкая система ориентирована на .NET и С# в частности), а у сишарпа компилятор и линкер в одном лице работают. Попытки использовать какое-нить ещё резервированное имя не увенчались успехом.
Сегодня на меня снизошло озарение – почему бы не сделать _CheckForGccCompileOutput, после копи-паста, понятное дело, оно не заработало, но зато стало ясно, что идея очень даже сможет жить, после некоторых мучений и ковыряний, я, таки, сумел заставить его работать. Ура.

Вот, собсно, этот ацкий таргет:


<Target
Name=”_CheckForGccCompileOutputs”
>
<CreateItem Include=”@(Compile->’$(IntermediateOutputPath)%(filename).o’)”>
<Output
TaskParameter=”Include”
ItemName=”ObjFileList”
/>
</CreateItem>
<!–Record the main compile outputs.–>
<CreateItem Include=”%(ObjFileList.Identity)” Condition=”Exists(%(ObjFileList.Identity))”>
<Output TaskParameter=”Include” ItemName=”FileWrites”/>
</CreateItem>
</Target>

Поясню детальней: первая фаза создаёт новый массив, в котором содержатся имена obj файлов, вторая, собсно, по ним проходится и вносит их в магический массив FileWrites, по которому, в дальнейшем и будет проводиться анализ – что нужно удалять, а что нет.

Similar Posts

  • Я заболел

    Я стал одной из первых жертв весеннего тепла (ведь уже можно считать, что пришла весна 🙂 ). Разрадовавшись теплу я снял пуховик и одел кожанку с подстежкой, шапку снял. И намочил голову – на улице пошел дождь, а у кожанки нету капюшона. Теперь я сижу дома с квадратной головой и сильным насморком, жру таблетки и…

  • VirtualKD + Windows 10

    Если вдруг нужно, чтобы взлетел VirtualKD с гостевой Windows 10, то после инсталляции оного внутри машины, нужно ещё обязательно выполнить bcdedit /dbgsettings serial, иначе кина не будет. Сэкономит часик времени на рисчёрч “а чо оно не работает”. Share this post: Share on X (Twitter) Share on Facebook Share on LinkedIn Share on Email Share on…

  • Концерт Apocalyptica

    Вчера ходил на концерт апокалиптики. Ниче так, круто 🙂 Сначала был разогрев – в течении получаса выступали непонятные наши группы. Определенно им это удалось лучше чем группе “Supermax” перед концертом ДДТ пару лет назад, когда ее выгнали со сцены бутылками 🙂 А потом было полчаса затишья – разогрев закончился, а апокалиптика еще не вышла. От…

  • OpenVPN DNS order

    Иногда, при подключении к VPN оказывается, что тамошний DNS не резолвит местные имена. Это не потому что он плохой, а потому что винда странная (7). Есть два пункта, которые помогают этот вопрос урегулировать. Для начала нужно в настройках сети поднять приоритет VPN сети повыше: control panel -> network and sharing -> change adapter settings ->…

  • Отпускное

    Остаются считанные часы, до момента, когда наступит долгожданный "ОН"! Я загружусь в машину и мы отправимся на побережье адриатики в Хорватии. На машине. Шенгенский транзит открыт, вещи упакованы, маршрут составлен, надеюсь получится совместить и увлекательно путешествие по Европе, и тупой до банальности матрас на пляже – надо же всё-таки и отлёживаться когда-то 🙂  Share this post: Share on X…

  • OpenMP

    Попробовал тут, намедни, OpenMP (Open Multi-Processing – это набор директив компилятора, библиотечных процедур и переменных окружения, которые предназначены для программирования многопоточных приложений на многопроцессорных системах с разделяемой памятью на языках C, C++ и Fortran). И, можно сказать, прозрел. Добавил в существующие исходники всего две строчки кода и время экспорта тестового фрагмента уровня уменьшилось почти в…