sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Dotnet build and publish don't have parameters for platform

Open CanIGetaPR opened this issue 5 years ago • 20 comments

Steps to reproduce

Have a csproj file with conditional configs as such: <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">

Expected behavior

There's a configuration parameter (dotnet build -c Debug) (dotnet publish -c Debug) that fills in $(Configuration) so I expect there to be a parameter to fill in $(Platform)

Actual behavior

There is no parameter and specific configuration details don't get applied because Platform does not get set to x64

Current Work-around

Explicitly setting the Platform EV for the current command prompt using SET Platform=x64

CanIGetaPR avatar Dec 01 '18 20:12 CanIGetaPR

The Microsoft docs don't state anything about explicitly setting the platform EV

https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-build?tabs=netcore2x

CanIGetaPR avatar Dec 01 '18 20:12 CanIGetaPR

You can pass it using dotnet build /p:Platform=x64

livarcocc avatar Dec 01 '18 21:12 livarcocc

Shouldn't that be added to the documentation then?

Usage: dotnet build [options] <PROJECT>

Arguments:
  <PROJECT>   The project file to operate on. If a file is not specified, the command will search the current directory for one.

Options:
  -h, --help                            Show command line help.
  -o, --output <OUTPUT_DIR>             The output directory to place built artifacts in.
  -f, --framework <FRAMEWORK>           The target framework to build for. The target framework must also be specified in the project file.
  -c, --configuration <CONFIGURATION>   The configuration to use for building the project. The default for most projects is 'Debug'.
  -r, --runtime <RUNTIME_IDENTIFIER>    The target runtime to build for.
  --version-suffix <VERSION_SUFFIX>     Set the value of the $(VersionSuffix) property to use when building the project.
  --no-incremental                      Do not use incremental building.
  --no-dependencies                     Do not build project-to-project references and only build the specified project.
  --no-restore                          Do not restore the project before building.
  -v, --verbosity <LEVEL>               Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
  --force                               Force all dependencies to be resolved even if the last restore was successful.
                                        This is equivalent to deleting project.assets.json.

CanIGetaPR avatar Dec 01 '18 21:12 CanIGetaPR

Do you explicitly need the platform to be set? How did you end up with this condition? I suppose VS generated that..

I believe the guidance would/should be to create a RID-specific non-self-contained application. This will generate a native host that will run using the desired architecture in recent versions of the tooling. At least that's what I'm currently using for an app that depends on a third party DLL file that only runs on windows x86.

For portable applications, the runtime will resolve native assets from runtimes\ subfolder in the output that ideally come from NuGet so that even a RID-specific publish will select the right assets.

dasMulli avatar Dec 01 '18 21:12 dasMulli

For some reason IIS insists that it needs 64 bit files, even with the allow 32 bit option enabled. Otherwise I would get loading errors.

So I use visual studio generally but need tooling to properly deploy the application. I was expecting for dotnet cli to work out of the box with the configuration generated by visual studio. Specifically, it's a compiler flag I have set for different platforms, that I need added. VS puts it in the config conditional I shared above. I don't want to break anything by making a custom config because I tried already and it was pretty finicky.

CanIGetaPR avatar Dec 01 '18 22:12 CanIGetaPR

So you need the compiler flag? By default, AnyCPU would be neutral, so it would depend on the host dotnet.exe which bitness to use.

Personally I've been in situations where the web.config's default processPath="dotnet" would resolve to the bitness that I didn't need. Hardcoding the full path to either Program Files\dotnet\dotnet.exe or Program Files (x86)\… fixed this. But this was only important when any of the DLLs wasn't built for AnyCPU or there was a native assembly absolutely requiring a specific bitness.

But if you're not building a .NET Core project, this may be different. (although the same thing about AnyCPU applies to IIS: it won't complain if it loads AnyCPU DLLs either in 32 or 64 bit mode).

dasMulli avatar Dec 01 '18 22:12 dasMulli

That actually sounds like the solution I needed. Hard coding the process path. Some of the DLLs are native and can only be compiled to 32 bit or 64 bit :)

I don't know why but it's insanely difficult for me to get logging from of the application running in IIS. The console output goes no where, and Serilog works locally and not in IIS. The only times I've gotten some clues as to find the problem was when I remoted in and tried running the application outside of IIS.

The application is still having an issue with the /p:Platform=x64 and I have no logging to figure out why. My crazy work around has been replacing the binaries outputted by dotnet publish with ones my IDE built.

CanIGetaPR avatar Dec 01 '18 23:12 CanIGetaPR

So here's an update. I tried SET Platform=x64 and the application runs properly on the remote.

CanIGetaPR avatar Dec 01 '18 23:12 CanIGetaPR

you could also do a dotnet publish -p:Platform=x64.

Once the 2.2.100 based tooling versions are released (2.2 SDK, you don't have to use .NET Core / ASP.NET Core 2.2), you should be able to do dotnet publish -r win-x64 --self-contained false, which will generate a YourProjectName.exe and a matching web.config that sets the process path to that exe. This will not include the whole runtime (= not self-contained) but make sure that the process will run in the specified bitness.

In the meantime, it is hard to tell what is going on in your builds. If you care building native applications (C++ projects) as part of your project, then at some point you'll likely have to globally set Platform at some point. But I believe that this is a rare scenario and dotnet build / dotnet publish shouldn't have convenience arguments for all available msbuild properties, especially since .NET Core and NuGet have the concept of runtime identifiers which should be preferred over messing with Platform or PlatformTarget.

it's insanely difficult for me to get logging from of the application running in IIS

This is why ASP.NET Core is working on creating a new in-proc hosting model for IIS that will enable you to get better startup diagnostics.

I'm not sure if this made it into 2.2 or if it has been pushed back to 3.0. But you could try it in 2.2. by setting

<PropertyGroup>
  <AspNetCoreModuleHostingModel>InProcess</AspNetCoreModuleHostingModel>
</PropertyGroup>

which will change the generated web.config to set the required attributes.

dasMulli avatar Dec 01 '18 23:12 dasMulli

Thanks for all this information. I also randomly stumbled across an answer you gave on stack overflow so thank you for all the help you give.

Do most people replace in-IDE building with a custom written build script and therefore manually editing the .csproj?

I mean how do I make use of the compiler flag I set in the IDE?

https://i.imgur.com/di1pSKB.png

I was using this command: dotnet publish -c "Release" -r "win-x64" however it wasn't setting WIN64 and a dependant project was incorrectly compiling code for 32 bit.

I don't mind self contained, that just means the remote host can't possibly mess up by running the deployed binaries incorrectly ;)

I'm using a pre-built native binary as a library, not building it from scratch every time.

CanIGetaPR avatar Dec 02 '18 00:12 CanIGetaPR

interesting, does the dependent library set anything to x86 by default in the csproj? this may happen if you set Platform Target in that VS dialog.

Do most people replace in-IDE building with a custom written build script …

Friends don't let friends right-click publish. Build/publish should always be automated by CI/CD systems and not rely on developer knowledge or worse, things installed and configured on some developer's machine.

and therefore manually editing the .csproj?

Not necessarily, but a lot of the options for .NET Core are not accessible via any IDE and if you're using VS Code, you'll need to edit them manually. The new csproj format ("sdk-style") is much better for manually editing now.

I don't think most people do edit it manually but I think my life is 10x better now that I know how MSBuild works.

I'm currently teaching MSBuild knowledge at meetups and conferences, so I may be able to share conference recording links soon.. (but be prepared for a thick German accent ^^)

I mean how do I make use of the compiler flag I set in the IDE?

Some of them are documented at Common MSBuild project properties . Interestingly, all csc.exe arguments are well documented at C# Compiler Options . @mariaw may help with that (or maybe @svick since he probably knows all roslyn related docs by heart). If it doesn't exist, this may be a good feature request - create a document that shows both command line and msbuild options and also use the wording that is used inside Visual Studio.

Personally, I suggest trying out a few things in the dialog and checking your csproj file.

Also, you'll likely notice that you need to switch between debug/release configuration to set such properties for all configurations. My main use for doing things inside the csproj directly is to not have those properties inside Condition="'$(Configuration)]$(Platform) == …" conditions but set them in a global <PropertyGroup> without conditions so that I can make sure they are always used.

dasMulli avatar Dec 02 '18 05:12 dasMulli

I was using that until I realized it was using AnyCPU by default and I couldnt find how to change it. Then when I tried hacking the csproj file it broke altogether.

I'm glad you wouldn't let me click it again though :)

Yes... builds and tests should be automated by CI/CD. Though that's not the way my employer does it... Yet! Until I somehow introduce it in :)

Erm, how exactly do you use msbuild in a script locally? It seems to be randomly located on hard drives based on its version, and even the registry keys that give its location are located in versioned keys. If only there was one version and installers were aware of any currently installed ones to keep the most up to date one in PATH

the reason I use the compiler flag is to decide if I want to load the 32 bit native dll or 64 bit one

Is there some place we can chat?

CanIGetaPR avatar Dec 02 '18 06:12 CanIGetaPR

Looks like you need VSWhere (this is used by Azure DevOps agents to locate VS installations)

You probably also want to create a NuGet package that contains both the 32 and 64 bit assemblies in a special layout so that .NET Core could use it in any case. There are magic runtimes\RID\native native folders that will resolve to the right assets for RID-specific builds and create a layout for "portable" applications that allows the .NET Core runtime to load the right assemblies based on which bitness of the host you're using.

I'm on the .NET Core Community Slack if you're using Slack.. But Gitter is also possible.

dasMulli avatar Dec 02 '18 06:12 dasMulli

VSWhere looks very useful. Thank you

CanIGetaPR avatar Dec 03 '18 18:12 CanIGetaPR

Hi @CanIGetaPR. Did @dasMulli's feedback help resolve this issue for you?

peterhuene avatar Jan 14 '19 22:01 peterhuene

I've spent at least an hour on this issue, tracking it down to something not obvious from the beginning: dotnet build requires a minus - for -c and a slash / for /p. Many command line parses allow - and / to be used interchangeably.

dotnet build -c:"Debug" /p:Platform:"Any CPU"

Note for scripting: the Configuration and Platform names should be in quotes, as these are arbitrary names that can contain spaces. The defaults are "Debug"/"Release" and "Any CPU", but you could rename them to "Custom Configuration Name" and "Custom Platform Name".

Note: The "Any CPU" Platform by default produces AnyCPU (no space) output, but that can changed per project. The "Any CPU" Platform may produce one project as AnyCPU, one as x86 and another as x64. For more information, study the "Configuration Manager" in Visual Studio.

FuncLun avatar Feb 02 '19 23:02 FuncLun

That's works for me https://github.com/dotnet/sdk/issues/9966#issuecomment-443468788

But why it's not documented until now !!

CorrM avatar Jan 20 '21 04:01 CorrM

That's works for me #9966 (comment)

But why it's not documented until now !!

Valid question.

EDIT: it is documented, but not in an optimal way. I think the -p argument should be a part of the synopsis and also be added to the Arguments section.

aleks-ivanov avatar Apr 26 '21 13:04 aleks-ivanov

In .NET 6, you can use the -a|--arch argument to specify the architecture of your build/publish/etc. See detailed documentation here. This doesn't handle the general case where users might want an AnyCPU value for the Platform MSBuild property, however.

baronfel avatar Dec 02 '21 20:12 baronfel

I've spent at least an hour on this issue, tracking it down to something not obvious from the beginning: dotnet build requires a minus - for -c and a slash / for /p. Many command line parses allow - and / to be used interchangeably.

dotnet build -c:"Debug" /p:Platform:"Any CPU"

Note for scripting: the Configuration and Platform names should be in quotes, as these are arbitrary names that can contain spaces. The defaults are "Debug"/"Release" and "Any CPU", but you could rename them to "Custom Configuration Name" and "Custom Platform Name".

Note: The "Any CPU" Platform by default produces AnyCPU (no space) output, but that can changed per project. The "Any CPU" Platform may produce one project as AnyCPU, one as x86 and another as x64. For more information, study the "Configuration Manager" in Visual Studio.

What worked for me was /p:Platform= and not /p:Platform:

garfbradaz avatar Aug 10 '22 20:08 garfbradaz