Pull to refresh

Собрать проект Visual Studio в один файл с помощью ILMerge

Reading time3 min
Views105K
app.exe, d1.dll d2.dll = app.exeОбычно результатом компиляции проекта является сборка (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.


Исходники
Инструменты

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

Материалы по теме
Tags:
Hubs:
+39
Comments29

Articles

Change theme settings