Dotnet создает две копии исполняемого файла

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

Например. в простом консольном проекте:

dotnet publish --configuration Release производит bin/Release/net8.0/FizzBuzz и bin/Release/net8.0/publish/FizzBuzz, которые идентичны.

Я хочу создать один оптимизированный исполняемый файл и один кроссплатформенный исполняемый файл. Как мне это сделать?


Обновлено: Благодаря @winscripter я понял следующее:

dotnet publish -c . изготовим:

bin/net8.0/
├── FizzBuzz (executable)
├── FizzBuzz.deps.json (not sure)
├── FizzBuzz.dll (cross-platform IL code)
├── FizzBuzz.pdb (debug symbols)
├── FizzBuzz.runtimeconfig.json (required for non stand-alone)
└── publish/ (a copy of the above files)

FizzBuzz.dll и FizzBuzz.runtimeconfig.json необходимы для исполняемого файла FizzBuzz, который можно запустить непосредственно с помощью ./bin/net8.0/publish/FizzBuzz.

FizzBuzz.dll можно запускать кроссплатформенно с помощью dotnet bin/net8.0/publish/FizzBuzz.dll. Для этого требуется только FizzBuzz.runtimeconfig.json.

Остальные сгенерированные файлы для запуска программы не нужны.

Я почти уверен, что без указания опции runtime для dotnet оптимизированная сборка по умолчанию предназначена для моей платформы, т.е. Linux.

Because ldd reports linux specific dependencies:
ldd bin/net8.0/publish/FizzBuzz
    linux-vdso.so.1 (0x00007ffd260e0000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe955acd000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe955ac8000)
    libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fe955800000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe95571e000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe955a9b000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe955539000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fe955b05000)

Я знаю, что существуют разные цели сборки (специфичные для ОС, SDK для dotnet и т. д.), но меня смущает множество вариантов.

Если вы дадите ссылку на https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-publish, предоставьте, пожалуйста, описание минусов вариантов, так как я их не понимаю.

Мой файл FizzBuzz.csproj:

<Project Sdk = "Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <AssemblyName>FizzBuzz</AssemblyName>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <!-- I added ErrorOnDuplicatePublishOutputFiles -->
    <ErrorOnDuplicatePublishOutputFiles>true</ErrorOnDuplicatePublishOutputFiles>
  </PropertyGroup>

</Project>

Я добавил <ErrorOnDuplicatePublishOutputFiles>, чтобы посмотреть, изменит ли это что-нибудь. Это не так.

dotnet --version
8.0.301

uname -a
Linux kali 6.8.11-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.8.11-1kali2 (2024-05-30) x86_64 GNU/Linux
stackoverflow.com/questions/49939630/…
winscripter 29.06.2024 13:35

Спасибо @winscripter. Это отвечает на часть моего вопроса. dotnet build --configuration Release создаст кроссплатформенный (но не оптимизированный для ОС) dll-файл (не исполняемый), который может быть запущен программой dotnet. И это отвечает, почему существуют дубликаты. Теперь, как мне создать один оптимизированный исполняемый файл? Я полагаю, это означает, что я не могу создать кроссплатформенный исполняемый файл, но мне нужно использовать программу dotnet для выполнения файла .dll.

dotnetCarpenter 29.06.2024 13:40

Я не уверен, возможно ли опубликовать исполняемый файл, который может работать на нескольких системах одновременно. В этом случае вам нужно будет использовать dotnet publish для публикации нескольких исполняемых файлов для нескольких систем. Итак, dotnet publish --runtime win-x64 для 64-разрядной версии Windows, dotnet publish --runtime linux-x64 для 64-разрядной версии Linux и т. д. С другой стороны, dotnet build приводит к созданию dll, содержащей IL-код, который может работать в нескольких системах одновременно, но его необходимо выполнить с помощью команды dotnet.

winscripter 29.06.2024 13:52

Это происходит по касательной, но вы предоставляете полезную информацию :) Единственный известный мне способ выполнить код IL в файле .dll — это использовать программу dotnet. Какие еще варианты есть? Я использую Linux, поэтому это может помешать мне опробовать Windows. Тем не менее я хотел бы получить ответ на оставшуюся часть моего вопроса: как мне создать оптимизированный исполняемый файл для конкретной ОС? Скажем, для Linux, если это поможет. Теперь я знаю, что могу сделать это с помощью dotnet publish, но не думаю, что мне действительно нужно все, что нужно опубликовать — могу ли я как-то минимизировать вывод?

dotnetCarpenter 29.06.2024 13:57

На самом деле! Извини, @winscripter, после твоего последнего комментария мне следовало постараться немного усерднее. Думаю, я понял. Спасибо! Я все еще получаю много артефактов, но начинаю понимать, что они делают. Если вы превратите эти два пункта в ответ, я приму его.

dotnetCarpenter 29.06.2024 14:03

На самом деле сейчас я начал использовать компилятор csc из Mono. Он намного проще, чем dotnet, но идеально подходит для моего случая использования. Это ускоряет освоение C#, потому что я мало что писал со времен C# 2.0 (много лет назад).

dotnetCarpenter 30.06.2024 17:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Что касается того, почему существует две копии исполняемого файла, см. этот ответ:

dotnet publish собирает проект перед копированием двоичных файлов в выходной каталог. Файлы, которые вы видите в каталоге bin\Release\netcoreapp2.0\win-x64, являются результатом команды dotnet build. Вы можете проверить это, выполнив следующую команду: dotnet build --configuration Release --runtime win-x64

Что касается того, как опубликовать исполняемый файл для одновременного запуска на нескольких системах: я не думаю, что это возможно. Когда вы используете команду dotnet publish, она генерирует исполняемый файл, специфичный для ОС (поэтому он будет работать только в одной операционной системе). Таким образом, вам потребуется опубликовать несколько исполняемых файлов, чтобы сделать приложение кроссплатформенным, например dotnet publish --runtime win-x64 для 64-разрядная версия Windows или dotnet publish --runtime linux-x64 для 64-разрядной версии Linux. Или используйте dotnet build для создания dll-файла, содержащего IL-код, который может работать в нескольких системах одновременно, но может потребоваться его выполнение с помощью команды dotnet.

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

dotnetCarpenter 29.06.2024 17:27

Документ здесь — Обзор публикации приложений .NET. Прежде всего, существует два основных режима публикации: зависящий от платформы («по умолчанию») и автономный:

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

Вы приказываете — dotnet publish --configuration Release результаты в зависимом от платформы исполняемом файле для текущей платформы:

Публикация приложения как зависимого от платформы создает кросс-платформенный двоичный файл в виде dll-файла и исполняемый файл для конкретной платформы, предназначенный для вашей текущей платформы. Dll является кроссплатформенной, а исполняемый файл — нет. Например, если вы публикуете приложение с именем word_reader и предназначено для Windows, вместе с word_reader.dll создается исполняемый файл word_reader.exe. При использовании Linux или macOS вместе с word_reader.dll создается исполняемый файл word_reader.

Таким образом, у вас будет исполняемый файл FizzBuzz (для конкретной ОС) и FizzBuzz.dll, который на самом деле является кроссплатформенным и может запускаться с помощью команды dotnet.

Обратите внимание, что .dll на самом деле будет содержать CIL (общий промежуточный язык) код , который будет фактически скомпилирован в код, специфичный для платформы, когда приложение будет запускаться ( через JIT-компилятор , который является частью время выполнения). Бывают случаи, когда это нежелательно («одноразовые» консольные приложения, возможно, лямбды AWS и т. д.). В этом случае вы можете рассмотреть либо компиляцию ReadyToRun , либо собственное развертывание AOT (в настоящее время поддерживаются не все типы приложений).

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

Другие вопросы по теме