Обычно результатом компиляции проекта является сборка (assembly) проекта, а также его зависимости (Referenced Assemblies). Однако иногда нужно чтобы результатом был один файл единственный файл, независимый от других сборок. Например простая утилита, которую можно будет куда угодно скопировать и она будет работать.Пример
Условно говоря после:
compile App\App.csproj
dir App\bin\Release Получаются:
App.exe
dep1.dll
dep2.dll Нам же нужно лишь один самодостаточный
App.exe То есть содержащий в себе dep1.dll и dep2.dllНа Хабре уже присутствует решение со встраиванием зависимостей в ресурсы, здесь я покажу как это сделать с помощью ILMerge и Post Build Event в Visual Studio.
Исходники
- github: github.com/gzvulon/ILMerge-Example
- Solution archive: github.com/gzvulon/ILMerge-Example/zipball/v1.0.0
- bat file: github.com/gzvulon/ILMerge-Example/blob/master/ILMerge/merge_all.bat
Инструменты
ILMerge — Программа от Microsoft Research, которая собственно и обладает требуемой функциональностью.
merge_all.bat — им мы воспользуемся в Post-build event.
Подготовка
Скачать и установить ILMerge.
Положить
%PROGRAMFILES%\ILMerge\ILMerge.exe в папку ${SolutionDir}ILMerge\Там же создать файл merge_all.bat
Добавить строчку в [Project->Properties->Build Events->Post-build event]:
"$(SolutionDir)\ILMerge\merge_all.bat" "$(SolutionDir)" "$(TargetPath)" $(ConfigurationName) Содержание merge_all.bat
Все сборки из $output будут сливаться в одну. Если конфигурация Debug то в $output\Output, если Release то в результате в $output будет только один файл. Информация как прошло слияние и какие были проблемы пишется в Visual Studio Output. Комментарии объясняют, что происходит внутри. Например в данном случае происходит выбор платформы .NET 4.
@ECHO OFF rem # set .NET version and output folder name set net="v4, C:\Windows\Microsoft.NET\Framework\v4.0.30319" set output=Output rem # process arguments set ILMergeSolution=%1ILMerge\ILMerge.exe rem # determine programm files of x86 for 32 and 64 Platform IF EXIST "%PROGRAMFILES(x86)%" set prorgammFiles=%PROGRAMFILES(x86)% IF NOT EXIST "%PROGRAMFILES(x86)%" set prorgammFiles=%PROGRAMFILES% rem # if ILMerge.exe not in the $(SolutionDir)ILMerge\ rem # then try to use installed in prorgammFiles IF EXIST %ILMergeSolution% set ILMerge="%ILMergeSolution%" IF NOT EXIST %ILMergeSolution% set ILMerge=%prorgammFiles%\Microsoft\ILMerge\ILMerge.exe set target_path=%2 set target_file=%~nx2 set target_dir=%~dp2 set ConfigurationName=%3 rem # set output path and result file path set outdir=%target_dir%%output% set result=%outdir%\%target_file% rem # print info @echo Start %ConfigurationName% Merging %target_file%. @echo Target: %target_path% @echo target_dir: %target_dir% @echo Config: %ConfigurationName% rem # recreate outdir IF EXIST "%outdir%" rmdir /S /Q "%outdir%" md "%outdir%" rem # run merge cmd @echo Merging: '"%ILMerge%" /wildcards /targetplatform:%net% /out:"%result%" %target_path% "%target_dir%*.dll"' "%ILMerge%" /wildcards /targetplatform:%net% /out:"%result%" %target_path% "%target_dir%*.dll" rem # if succeded IF %ErrorLevel% EQU 0 ( rem # clear real output folder and put there result assembly IF %ConfigurationName%==Release ( del %target_dir%*.* del %target_dir%*.dll del %target_dir%*.pdb del %target_dir%*.xml del %target_dir%*.* copy %result% %target_dir% rmdir /S /Q %outdir% set result=%target_path% @echo Result: %target_file% "-> %target_path%" ) ELSE ( @echo Result: %target_file% "-> %result%" ) set status=succeded set errlvl=0 ) ELSE ( set status=failed set errlvl=1 ) @echo Merge %status% exit %errlvl%
UPD:
Лицензия
С сайта ILMerge:
Commercial use permitted:
The language of ILMerge's license has raised many questions. In a nutshell: commercial use is permitted, redistribution is not. Read the license carefully for full details since I am not (nor do I wish to be!) a lawyer.
То есть встраивать в процесс сборки можно, а распространять со своим продуктом — нельзя.
Открытым остался вопрос про лиценции объединяемых dll.
Минусы
- beliakov: ILMerge память жрет как бегемот… На большом количестве сборок
- braindamaged: игнорирует ключик, который заставляет её, в свою очередь, игнорировать сборки и неймспейсы, оказавшиеся в зависимостях.
Схожие инструменты
- aspnet_merge Для ASP.NET
- NGen Создает локальный кэш с dll
Материалы по теме
- Встраивание в ресурсы — habrahabr.ru/blogs/personal/67836
- As Visual Studio Project Target — http://www.hanselman.com/blog/MixingLanguag...
- Eще Target — http://blogs.clariusconsulting.net/kzu/how-to-merge-your-referenced-assemblies-into-the-output-assembly-for-improved-usability/
- Best practices — stackoverflow.com/questions/9376/ilmerge-best-practices
- Simplest .bat — peyotest.blogspot.com/2010/03/using-ilmerge-in-post-build-step.html
- Advanced .bat — www.tanguay.info/web2008/codeExample.php?id=671
