Project System: Remove the cruft from project files and templates #40

Closed
davkean opened this Issue May 13, 2016 · 104 comments

Projects

None yet
@davkean
Member
davkean commented May 13, 2016

From @davkean on May 11, 2016 1:35

Want to go from something like:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>0a5fdbad-1d09-4833-a0b4-cf17a684fb2e</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>ClassLibrary1</RootNamespace>
    <AssemblyName>ClassLibrary1</AssemblyName>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System"/>

    <Reference Include="System.Core"/>
    <Reference Include="System.Xml.Linq"/>
    <Reference Include="System.Data.DataSetExtensions"/>


    <Reference Include="Microsoft.CSharp"/>

    <Reference Include="System.Data"/>

    <Reference Include="System.Net.Http"/>

    <Reference Include="System.Xml"/>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Class1.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->

 </Project>

To something like:

<?xml version="1.0" encoding="utf-8"?>
<Project>

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <RootNamespace>ClassLibrary22</RootNamespace>
    <AssemblyName>ClassLibrary22</AssemblyName>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="System"/>
    <Reference Include="System.Core"/>
    <Reference Include="System.Xml.Linq"/>
    <Reference Include="System.Net.Http"/>
    <Reference Include="System.Xml"/>
  </ItemGroup>

  <ItemGroup>
    <Compile Include="**\*.cs" />
  </ItemGroup>

  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

</Project>

Copied from original issue: dotnet/roslyn#11235

@davkean
Member
davkean commented May 13, 2016

Or even better, not even need the references - just reference everything by default, similar to what we did in UWP, Portable, etc

@davkean
Member
davkean commented May 13, 2016

image

@davkean
Member
davkean commented May 13, 2016
@davkean
Member
davkean commented May 13, 2016

From @onovotny on May 11, 2016 1:46

Why does the import targets need to be there, can a before targets be auto-included in the build system externally?

@davkean
Member
davkean commented May 13, 2016

Yep, good question.

@davkean
Member
davkean commented May 13, 2016

From @onovotny on May 11, 2016 1:50

How about the target framework version? What if I want to cross compile. That has to be a first-class scenario as that was a major benefit to project.json

@davkean
Member
davkean commented May 13, 2016

From @NickCraver on May 11, 2016 2:7

Cross-compile is a huge use case here too - I think an honest example here has to include that much more complicated scenario.

Also: what about all the package metadata? Another major benefit or project.json was one place for all of this. Either it's included here, or we'll be maintaining 2 files for the information (at a minimum, will we have the project name duplicated?). If we're talking about the first class experience that project.json offered being replicated here (e.g. very nice Intellisense on packages, dependencies, etc.).

Regardless, editing should be in one spot. Not in two spots across 2 file formats, that would be a terrible regression in usability. Everything in XML is better than half in XML and half in JSON.

@davkean
Member
davkean commented May 13, 2016

Just to set expectations, I quickly wrote this up internally September last year, and only got around to creating an issue on it. It's not factoring in cross-compile or anything from xproj yet. We're still discussing how best to bring those things across.

@davkean
Member
davkean commented May 13, 2016

From @onovotny on May 11, 2016 2:10

Is the goal to remove project.json as used in csproj today (as a packages.config replacement) or just that one's "big brother" as used in xproj?

@davkean
Member
davkean commented May 13, 2016

Two schools of thoughts, leave it today with just package refs, or replace it with "MSBuild equivalents" a la <PackageReference Include="FooBar" />, still completely up in the air.

@davkean
Member
davkean commented May 13, 2016

From @vbfox on May 11, 2016 7:59

Or even better, not even need the references - just reference everything by default.

Both references, and <Compile Include="**\*.cs" /> can have good defaults done by a "simplified" target, if anyone want them back, they can reference the normal target file.

Mixed with package references it might look like :

<?xml version="1.0" encoding="utf-8"?>
<Project>
  <PropertyGroup>
    <OutputType>Library</OutputType>
    <RootNamespace>ClassLibrary22</RootNamespace>
    <AssemblyName>ClassLibrary22</AssemblyName>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json"/>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.Simple.targets" />
</Project>
@davkean
Member
davkean commented May 13, 2016

From @isaacabraham on May 11, 2016 8:4

@davkean This is looking nice. Please can you also keep in mind (if this issue is appropriate for it) the .fsproj story which is very, very similar AFAIK but the main difference is the need to (somehow) specify file ordering / dependencies e.g. file1.fs comes "before" file2.fs in compilation order. @KevinRansom maybe has some thoughts on this.

@davkean
Member
davkean commented May 13, 2016

@isaacabraham Yep, we've got F# in mind when we start looking at these things, including sitting it on top of the new project system.

@davkean
Member
davkean commented May 13, 2016

From @opinionmachine on May 11, 2016 9:23

Keep it clean, if you need bizarre special cases, all those elements need to be optional and not present by default, and it doesn't harm anybody if you have to google, with bing, to find them that one time in your career you need them. 99% never do anything weird, all the cruft needs to go. If you insist on this XML way of doing things, despite no tangible upsite and so, so many downsides, at least be inspired by the millions of better solutions that are actually used in the world.

@davkean
Member
davkean commented May 13, 2016

From @pebezo on May 11, 2016 15:3

Coming from someone who rarely had to edit csproj: consider meaningful names for nodes. ItemGroup it's too abstract (group of what? items?...) "dependencies" like in project.json makes a lot more sense. Same with "PropertyGroup"... properties for what?

Also, aim for single words rather than compound words. If a compound word is the only thing that would fit then it's too abstract.

@davkean
Member
davkean commented May 13, 2016

Just to set expectations, this issue isn't tracking making sweeping changes to MSBuild itself, the MSBuild format or moving to a new build model. For those, you are better off starting threads over on https://github.com/microsoft/msbuild.

@davkean
Member
davkean commented May 13, 2016

From @benaadams on May 11, 2016 15:50

Without know too much about what MSBuild allows, would a x-compile for something like Microsoft.AspNetCore.Server.Kestrel/project.json look something like:

<?xml version="1.0" encoding="utf-8"?>
<Project>
  <PropertyGroup>
    <OutputType>Library</OutputType>
    <RootNamespace>Microsoft.AspNetCore.Server.Kestrel</RootNamespace>
    <AssemblyName>Microsoft.AspNetCore.Server.Kestrel</AssemblyName>
  </PropertyGroup>

  <PropertyGroup>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
    <TargetFrameworkVersion>netstandard1.3</TargetFrameworkVersion>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="System.Buffers" Version="4.0.0-*" />
    <Reference Include="System.Numerics.Vectors" Version="4.1.1-*" />
    <Reference Include="System.Threading.Tasks.Extensions" Version="4.0.0-*" />
    <Reference Include="Libuv" Version="1.9.0-*" />
    <Reference Include="Microsoft.AspNetCore.Hosting" Version="1.0.0-*" />
    <Reference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.0.0-*" />
    <Reference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.0.0-*" />
  </ItemGroup>

  <ItemGroup TargetFrameworkVersion="v4.5.2">
    <Reference Include="System"/>
    <Reference Include="System.Runtime"/>
    <Reference Include="System.Threading.Tasks"/>
  </ItemGroup>

  <ItemGroup TargetFrameworkVersion="netstandard1.3">
    <Reference Include="System.Collections" Version="4.0.11-*" />
    <Reference Include="System.Diagnostics.Debug" Version="4.0.11-*" />
    <Reference Include="System.Globalization" Version="4.0.11-*" />
    <Reference Include="System.IO" Version="4.1.0-*" />
    <Reference Include="System.Linq" Version="4.1.0-*" />
    <Reference Include="System.Net.Primitives" Version="4.0.11-*" />
    <Reference Include="System.Runtime.Extensions" Version="4.1.0-*" />
    <Reference Include="System.Runtime.InteropServices" Version="4.1.0-*" />
    <Reference Include="System.Text.Encoding" Version="4.0.11-*" />
    <Reference Include="System.Threading" Version="4.0.11-*" />
    <Reference Include="System.Threading.Tasks" Version="4.0.11-*" />
    <Reference Include="System.Threading.Thread" Version="4.0.0-*" />
    <Reference Include="System.Threading.ThreadPool" Version="4.0.10-*" />
    <Reference Include="System.Threading.Timer" Version="4.0.1-*" />
  </ItemGroup>

  <ItemGroup>
    <Compile Include="**\*.cs" />
  </ItemGroup>

  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@davkean
Member
davkean commented May 13, 2016

From @aelij on May 11, 2016 16:11

If package references are added to the .csproj, we should be able to easily edit the file without VS asking to reload the project. Plus the package IntelliSense from project.json.

@davkean
Member
davkean commented May 13, 2016

From @benaadams on May 11, 2016 16:14

@aelij shouldn't be beyond the realm of possibility as you can add references via ide without a reload

@davkean
Member
davkean commented May 13, 2016

From @pbolduc on May 11, 2016 16:28

It would be good if <Reference Include="" /> items were sorted alphabetically by name. This helps to avoid merge conflicts.

@davkean
Member
davkean commented May 13, 2016

From @blowdart on May 11, 2016 16:49

Not sure about referencing all the things by default, unless you mean everything that's part of that framework version. Even then I'd still want a way to exclude things I don't ever need that are slapped in by default.

@davkean
Member
davkean commented May 13, 2016

From @MarkPflug on May 11, 2016 17:0

I notice that the xmlns is removed in the proposed "clean" version. Is that really intentional? I know the first (maybe beta) version of MSBuild actually supported this, but if you try it now with MSBuild it is will tell you to add the xmlns back. Otherwise, that is already a valid project file. The only reason all that other cruft is needed is to satisfy Visual Studio project system. Specifically, the <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> sections are required so that the VS tooling doesn't lose its mind.

I'm actually delighted that things are going back to MSBuild and the project.json is being abandoned. MSBuild is very powerful and supported so many things that just didn't seem possible (or at least not straight forward) in the .json. Also, not being able to have commented out sections in json drove me nuts.

It would be really nice if Visual Studio would support naked .proj files too. A custom, hand-edited .proj file that I could right click on and "Build".

@davkean
Member
davkean commented May 13, 2016

From @fearthecowboy on May 11, 2016 17:4

It would be really nice if Visual Studio would support naked .proj files too. A custom, hand-edited .proj file that I could right click on and "Build".

This. A million times. THIS.

@davkean
Member
davkean commented May 13, 2016

From @luisrudge on May 11, 2016 17:6

I should be able to edit the file from VS without using vs tooling as well.. Will this be possible?

@davkean
Member
davkean commented May 13, 2016

From @terrajobst on May 11, 2016 18:0

Would something like this work as well?

  <ItemGroup>
    <Compile Include="**\*.cs"
             Exclude="**\*_*.cs" />
    <Compile Include="**\*_Linux.cs"
             Condition="'$(Platform)' == 'Linux'" />
    <Compile Include="**\*_OSX.cs"
             Condition="'$(Platform)' == 'OSX'" />
    <Compile Include="**\*_Win32.cs"
             Condition="'$(Platform)' == 'Win32'" />
  </ItemGroup>

This would allow me to come up with my own naming convention for shared projects that are compiled for multiple platforms.

@davkean
Member
davkean commented May 13, 2016

It would be really nice if Visual Studio would support naked .proj files too. A custom, hand-edited .proj file that I could right click on and "Build".

A little trick - it already does, via the new project system and it "works" in VS 2015. Create a C# project, rename to .msbuildproj, remove a bunch of targets - you've got a naked project. The experience isn't awesome right now - but its something I'm thinking about as I'm bringing up C#/VB on it.

@luisrudge Can you expand on on what you mean by that?

@terrajobst: We're going to add conditional support for items inside VS - so something like that would work.

@davkean
Member
davkean commented May 13, 2016

From @CoreyKaylor on May 11, 2016 18:21

I think it would help to see what a proposed sample would look like for a project producing a nuget targeting net45, sl5, UWP, etc. That was one of the major benefits to using project.json. I don't ever want to open up a solution like Caliburn.Micro and see see this kind of craziness again.

https://github.com/Caliburn-Micro/Caliburn.Micro/blob/master/src/Caliburn.Micro.sln

@davkean
Member
davkean commented May 13, 2016

From @MarkPflug on May 11, 2016 18:30

Thanks for the tip @davkean. In previous versions I had to use a somewhat hacky csproj file to achieve that, and it needed to contain some oddities to prevent the Configuration/Platform for the solution from getting confused. Looks much better now!

@davkean
Member
davkean commented May 13, 2016

From @CoreyKaylor

I think it would help to see what a proposed sample would look like for a project producing a nuget targeting net45, sl5, UWP, etc. That was one of the major benefits to using project.json. I don't ever want to open up a solution like Caliburn.Micro and see see this kind of craziness again.

https://github.com/Caliburn-Micro/Caliburn.Micro/blob/master/src/Caliburn.Micro.sln

@davkean
Member
davkean commented May 13, 2016

From MarkPflug

Thanks for the tip @davkean. In previous versions I had to use a somewhat hacky csproj file to achieve that, and it needed to contain some oddities to prevent the Configuration/Platform for the solution from getting confused. Looks much better now!

@davkean
Member
davkean commented May 13, 2016

From @MarkPflug

@terrajobst Your example would exclude all files with an "_", which would probably lead to some confusion.

I think you would want something more like this:


<Project 
    DefaultTargets="Build"
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
>

<PropertyGroup>
    <Platform>Win32</Platform>
</PropertyGroup>

<ItemGroup>
    <CompileLinux Include="**/*_Linux.cs"/>
    <CompileWin Include="**/*_Win.cs"/>
    <CompileOsx Include="**/*_OSX.cs"/>
    <Compile Include="**/*.cs" Exclude="@(CompileLinux);@(CompileWin);@(CompileOsx)"/>

    <Compile Condition="'$(Platform)' == 'Linux'" Include="@(CompileLinux)"/>
    <Compile Condition="'$(Platform)' == 'Win32'" Include="@(CompileWin)"/>
    <Compile Condition="'$(Platform)' == 'Osx'" Include="@(CompileOsx)"/>
</ItemGroup>

<Target Name="Build">
    <Message Text="@(Compile)"/>
</Target>


</Project>
@davkean
Member
davkean commented May 13, 2016

Just to set expectations again - above is not a design of what project.json in csproj looks like. I wrote this 6 months ago based on a tweet someone said to me, and just wanted to get a bug started for conversations.

@davkean
Member
davkean commented May 13, 2016

From @onovotny

@davkean Is there a place (shared one note, wherever) where interested external parties can participate in the feature design, including some meetings?

@davkean
Member
davkean commented May 13, 2016

From @luisrudge

@davkean I could edit the project.json file by hand using VS. But, today, I can't edit the .csproj file by hand, only using VS GUI, correct? So, my question is: Can I edit the .csproj file by hand with this new system?

@davkean
Member
davkean commented May 13, 2016 edited

From @bbarry

You can edit the csproj by hand today, you have to unload the project first. The intellisense in project.json is nicer though.

@davkean
Member
davkean commented May 13, 2016 edited

From @luisrudge

@bbarry yeah.. that's a shitty experience though

@davkean
Member
davkean commented May 13, 2016

@luisrudge We're tracking that somewhat via: #10065. Currently we use the "XML language service" to edit the project - but you could image that we'll probably end up creating a real language service for MSBuild for IntelliSense, etc. Combined with the debugger - I think we could make it much nicer to work with than today.

@davkean
Member
davkean commented May 13, 2016

@onovotny Right now that place (for the project system) is Roslyn. We're going to fire up issues over on the project system repo - but too be honest, we're trying to lock down RC2, and haven't started any design yet.

@davkean
Member
davkean commented May 13, 2016

From @MarkPflug

With the goal of simplifying things, why not have **\*.cs defaulted in by the Microsoft.CSharp.targets. This way a "default" csproj file wouldn't even need to specify what files it wants to compile, that would be defined by the imported targets file. The default would only be defined if the csproj didn't override it by attaching a Condition to the ItemGroup.

<ItemGroup Condition="'@(Compile)' ==''">
    <Compile Include="$(MSBuildProjectDirectory)\**\*.cs"/>
</ItemGroup>

If almost all csproj files are going to use this, it should just be the default behavior.

This same concept could be applied to References, and common properties. If all you wanted was a simple class library, the csproj could be made as simple as:

<Project
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

The default assembly/namespace name could be derived from the csproj filename. The platform could be defaulted. A standard set of references could be defaulted.

@davkean
Member
davkean commented May 13, 2016

From Slaks

@terrajobst Or, better yet,

    <Compile Include="**\*_$(Platform).cs" />
@davkean
Member
davkean commented May 13, 2016

From Mike-EEE

๐Ÿ‘ to @bbarry and @luisrudge. My primary concern here is: what is a <Project /> tag? Where can I go to see its properties and definition? Or an <ItemGroup /> tag? Or a <PropertyGroup /> tag? To this day I have yet to have been able to find the POCOs that these tags represent. ALL THE CONFUSE!

JSON did better with tooling, but what is that file actually describing? Here I go again to Xaml, as in a Xaml file, you see precisely where the namespace, assembly, and the name of the file is -- right in the file. Using ReSharper, I can hit CTRL-B on any property within the file and be taken straight into (decompiled) source for more information -- no guesswork or schema-hunting. As I am working with a file that is based on a class definition, this helps out with not only building the file, but also building tooling around building the file itself, as well.

(FWIW I am indeed promoting/suggesting/endorsing a Xaml-based project file format, but I am open to any format as long as the key qualities I list here are met.. :) )

Going back to the JSON design, while it was better than the XML format, it still did not at any point (that I know of -- please correct me if I am wrong!) point to an actual POCO, and its schema was "yet another JSON file/artifact" that you had to chase down somewhere (ala .NET configuration).

Whatever format or design decisions we land on, please please please make the file format represent an actual POCO with an actual .NET namespace location where we can actually go and get more information around it, instead of having to scratch our head over what the heck sort of arbitrarily-defined object we're working with. ๐Ÿ˜›

There should be a 1:1 mapping between the file we're describing and the object that ultimately gets deserialized into memory. That is, the class definition should be the schema of the file. This approach reduces complexity, number of required artifacts, and helps with designers/tooling in building around it.

In any case, I am glad to see this revisited and asking for the community's input. You've made the right call, and have done the right thing here. ๐Ÿ˜„

@davkean
Member
davkean commented May 13, 2016

From Mike-EEE

BTW/FWIW @davkean project format/improvement was brought up w/ MSBuild's repo a while ago and was shot down and dismissed.

@davkean
Member
davkean commented May 13, 2016

To set expectations up-front and clear for future replies to this issue - this isn't tracking a complete "redesign" of the project format. The reason xproj is moving to MSBuild is to unify existing assets, projects, infrastructure across the entire .NET stack, not for us to come up with something new.

What this issue is tracking, is the simplification of the project format and default templates - can we do things that enable developers to feel comfortable and understand what the project file does and contains, and remove things that only exist for VS purposes? We also have other issues that are tracking other ways we could change the tooling to get of your way. If you're looking for us to move away Items, Properties, Targets and Tasks, and ultimately from XML - this issue is not the one to track that.

@davkean
Member
davkean commented May 13, 2016

From @terrajobst

@SLaks

Not sure why this didn't occur to me ๐Ÿ˜„. Not enough โ˜•๏ธ maybe?

@davkean
Member
davkean commented May 13, 2016

From @bbarry

I think including Microsoft.CSharp by default is good. And if supporting multiple frameworks is expected to become a common practice it would be nice to have a defaulted compilation symbol or two per standard framework to drive common #ifdef patterns.

@davkean
Member
davkean commented May 13, 2016

From @shederman

Sorry, how can we trust anyone talking about the improvements that are going to be made to MSBuild/project system? How do we know the decisions won't just be undone without consultation? How do we know we won't get royally stuffed around at the last minute? Just like we are now?

@davkean davkean closed this May 13, 2016
@davkean davkean reopened this May 13, 2016
@davkean
Member
davkean commented May 13, 2016

From @shederman

Please take the survey at https://www.surveymonkey.com/r/H6Q88PP to weigh in.

@davkean
Member
davkean commented May 13, 2016

From @isaacabraham

@mike-eee Hmm. That issue seems to be talking about a JSON or YAML version of the project file; this is about simply trimming down what's already there rather than reformatting it.

@davkean
Member
davkean commented May 13, 2016

From Mike-EEE

@isaacabraham correct. My intent was to show @davkean after my rant (oops, sorry! ๐Ÿ˜„ ) that previous efforts have been made over @ the MSBuild group to improve its format and they fell on deaf ears. This was in reply to:

Just to set expectations, this issue isn't tracking making sweeping changes to MSBuild itself, the MSBuild format or moving to a new build model. For those, you are better off starting threads over on https://github.com/microsoft/msbuild.

So, I guess we aren't better off, in any case. ๐Ÿ˜› Anyways, thank you for your patience (I hope?) with me. I've created an issue from my post here: dotnet/roslyn#11263

@davkean
Member
davkean commented May 13, 2016

From Mike-EEE

Thanks for your patience all. After a little thought, I took @davkean's suggestion and have created a new issue on MSBuild's board to discuss project file/model changes: Microsoft/msbuild#613 Hopefully with the current climate of all the changes it will get a little more reception/dialogue. Please feel free to add your comments/feedback and votes/reactions.

Now @davkean has a location to direct angry/bombastic/impulsive developers such as myself to visit, rather than constantly posting on this thread to keep everyone on task/topic. ๐Ÿ˜„

@davkean
Member
davkean commented May 13, 2016

From @shederman

If you read the comments in that link you will see precisely why we need to move away from MSBuild. The developers on that thread do not even grasp the concept that MSBuild isn't the perfect solution to all build issues. Every suggested solution and link is about using MSBuild in different ways. They have one multi configurable hammer, and everything is a nail.

The basic feeling appears to be that if you don't want to use MSBuild then either:
a) You don't know MSBuild well enough
b) You're not a "Good Developer"

There's zero understanding that a great many people have used it, fought with it, hated it, and don't want it anymore.

@davkean
Member
davkean commented May 13, 2016 edited

From @Mike-EEE

Haha yeah I have to agree with @shederman ... not a whole lot of luv in the msbuild camp/repo it seems at the moment, but hopefully we can get to a place where everyone is happy. :)

@davkean
Member
davkean commented May 13, 2016

From @shederman

From aspnet/Home#1433:

@shederman
PS. If you are going to carry on ignoring opposition, can you please provide the following:

How we'd gain access to the build tools developer slack channels
A high level view of the current architecture and code, and where the changes to move to MSBuild/xproj are going to be made so we can plan our approach to keep the bits we want and integrate well.
Assurance that pull requests baking in project.json based tooling will be accepted if meet the quality criteria
Assurance that if quality criteria are met, we can include "dotnet build" support for full project.json, as well as ASP.NET Simple templates, and potentially some templates for more standard project types as well.
"Be constructive", "don't contribute, don't get a voice". Well, you get what you ask for...

@Mike-EEE, wanna do Xaml serializations for SimpleUseCaseBuild?

@luisrudge

Wow, that was a hell of a spam in my mailbox

@davkean
Member
davkean commented May 13, 2016

@luisrudge Apologies for that - there should be no more, we've moved all the bugs. Should have probably planned the move better. :(

@luisrudge

np at all!

@eerhardt
Member

Note: You don't NEED the "RootNamespace" property. It can just be inferred from the AssemblyName if it isn't set.

Similarly, you don't NEED AssemblyName - it can be inferred from the containing folder name - just like it was in project.json.

@davkean
Member
davkean commented May 16, 2016

๐Ÿ‘

@davkean
Member
davkean commented May 17, 2016

I've start a list of elements that I know with 100% certainty can be removed from the project file: #158.

@davkean davkean removed the New Feature label May 19, 2016
@srivatsn srivatsn added this to the 1.0 (RC) milestone May 24, 2016
@asbjornu

With comments from @eerhardt and others above, and by making the format more consistent in its handling of simple values (i.e. values that don't need its own XML sub-tree), it would be nice if we could end up with something like this:

<?xml version="1.0" encoding="utf-8"?>
<Project>
  <PropertyGroup OutputType="Library" TargetFrameworkVersion="v4.5.2" />
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.Simple.targets" />
</Project>

I know OutputType and TargetFrameworkVersion is currently not supported as attributes on PropertyGroup, but since they are simple values that have no (current, nor future) requirement for its own complex XML structure, the values can (and should) be attributes.

The above .csproj file is something even I could enjoy authoring. By hand. From scratch. In nano.

@gulbanana
gulbanana commented May 25, 2016 edited

one of the biggest functional rather than aesthetic wins would be to get package references out of the project file. at the moment, synchronising of nuget references across two files (packages.config and .csproj) is its biggest source of failures and merge conflicts.

@gulbanana

(moving everything FROM packages.config/project.json to .csproj would work fine too, but that doesn't seem to be on the cards)

@isaacabraham

@gulbanana I think actually moving out of .csproj would be far better as the risk of e.g. nasty merge conflicts would be reduced - one file for the project stuff and another for dependencies + references.

@gulbanana

bit of a pain to not be able to easily switch between projects and references, though.
i build internal libraries, so i have solutions which are like
foo.core
foo.bar
foo.baz

with bar and baz depending on core. all three get turned into nuget packages. sometimes it makes sense to have the depending projects reference as projects, because they version together; sometimes they're independent version sets and really want to be detached.

@davkean
Member
davkean commented May 25, 2016

With regards to dependencies, here's a couple of high-level goals we have:

  1. We want one place to put all of your dependencies; package, project, assembly, etc
  2. Similar to project.json, we want you to be able to swap package/assembly references with source

Packages.config does not live in this world; we've already had experience with project.json both in csproj world (notice we ourselves use project.json in the project system projects) and in the xproj world, and we like the model. We just want/need it to be a little more closely integrated with MSBuild, so that restore isn't an afterthought.

@eerhardt
Member

@davkean - one great thing about project.json that I don't see people mentioning is how it brought in the graph of dependencies. ex. I depend on Newtonsoft.Json, and Newtonsoft.Json depends on System.Runtime.Serialization.Primitives. I don't need to directly reference System.Runtime.Serialization.Primitives. Since I depend on Newtonsoft.Json, I get all its dependencies as well.

This is crucial in the .NET Core world, where the base class libraries are split into ~50 packages. I just need to reference Microsoft.NETCore.App, and I get all of the base class libraries.

It is also needed for the dotnet/cli in order to publish "self-contained" apps. The CLI needs to walk all the dependencies recursively and put all the runtime assemblies in your 'publish' folder.

I don't want to go back to a flat list of dependencies/references like we have in .csproj currently.

@davkean
Member
davkean commented May 25, 2016

@eerhardt Flowing dependencies will continue to work, it's exactly what we already do with NuGet v3 in csproj today. For example, see: https://github.com/dotnet/roslyn-project-system/blob/master/src/DeployTestDependencies/project.json, this project "inherits" every single package from every project it references.

@eerhardt
Member

Great! I just didn't see it listed in the "high-level" goals, so I wanted to make sure this was still a goal, as it is very important.

@asbjornu

@davkean Since you seem to be required to invent a new solution to the dependency problem anyway, is it thinkable that both NuGet and MSBuild use .csproj for this? If the format of the XML required to add and remove dependencies is comparable to that of project.json and the editor experience for it improves with autocompletion, automatic state refresh, etc., I think that would be a great compromise.

@MarkPflug

you don't NEED AssemblyName - it can be inferred from the containing folder name

I agree with the sentiment, but I would suggest that it be inferred from the project file name instead of the folder name.

<PropertyGroup>
<AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
</PropertyGroup>
@asbjornu

@MarkPflug While that fallback strategy is a good idea, I really hope we can rip it out of the .csproj file (and have it as internal MSBuild logic) if it's going to be the default fallback strategy for all project files anyway. The smaller the .csproj can be, the better.

@MarkPflug

@asbjornu If you read back in this thread you will see that I've mentioned that is entirely possible (in a comment that @davkean moved). Basically, I would be just an empty .csproj file that simply imports Microsoft.CSharp.targets; though it would probably be Microsoft.CSharpCore.targets or some such, since Microsoft.CSharp.targets can only be changed in ways that maintain compatibility with existing projects that depend on it.

The real problem is to get VS to be able to do what it needs to do while having such a minimal csproj. It is already possible, today, to have a very minimal csproj file by including a custom .targets file, VS just won't be able to handle like we've come to expect.

I don't think we can get rid of the csproj altogether. MSBuild gives you 100% control over how your project is built. By importing Microsoft.CSharp.targets 99% of the problem is taken care of for you; you just need to define the Compile and References items, and a few required properties. I think by having sane defaults an imported targets file could end up taking care of 99.9% of the problem for you, at least for a "simple" project, while still giving you the ability to customize the build steps when you need more control.

@enricosada enricosada referenced this issue Jun 8, 2016
Open

F# support #219

@davkean
Member
davkean commented Jun 15, 2016 edited

I've started an issue that tracks the properties, items and attributes we've 100% confirmed can be removed: #158. This is a work in progress and we'll keep it updated as identify or do work to remove the other unneeded elements.

@davkean
Member
davkean commented Jun 15, 2016

Filed #233 for assembly name, root namespace defaults.

@enricosada enricosada referenced this issue in Microsoft/msbuild Jun 21, 2016
Closed

Building existing .fsproj with xplat MSBuild #709

@malylemire1
malylemire1 commented Jun 23, 2016 edited

Will the MSBuild Choose instruction be supported :

<Choose>
    <When Condition="'$(Platform)' == 'Win32'">
      <ItemGroup>
        <Compile Include="**\*_Win32.cs"/>
      </ItemGroup>
    </When>
    <Otherwise>
      <ItemGroup>
        <Compile Include="**\*_OSX.cs"/>
      </ItemGroup>
    </Otherwise>
</Choose>

There also a problem with current Choose instruction. You cannot use project reference in When and assembly reference in Otherwise with a $(Configuration) condition. Visual studio mess up when reloading the project reference vs the assembly reference when switching solution configurations.

@srivatsn srivatsn modified the milestone: 1.1, 1.0 RC Jul 15, 2016
@VanCoding
VanCoding commented Sep 22, 2016 edited

Is this discussion still ongoing?

I'd like to express my wishes as well (even though I'm late).

First, I've seen your first example how a cleaned up csproj file could look like:

<?xml version="1.0" encoding="utf-8"?>
<Project>

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <RootNamespace>ClassLibrary22</RootNamespace>
    <AssemblyName>ClassLibrary22</AssemblyName>
    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="System"/>
    <Reference Include="System.Core"/>
    <Reference Include="System.Xml.Linq"/>
    <Reference Include="System.Net.Http"/>
    <Reference Include="System.Xml"/>
  </ItemGroup>

  <ItemGroup>
    <Compile Include="**\*.cs" />
  </ItemGroup>

  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

</Project>

I think this is exactly the reason why many people got angry when you announced you move away from the project.json file. It's still WAY to bloated. Here's how it should look like in my opinion:

<?xml version="1.0" encoding="utf-8"?>
<Project OutputType="Library" RootNamespace="ClassLibrary22" AssemblyName="ClassLibrary22" TargetFrameworkVersion="v4.5.2">
    <Reference Include="System"/>
    <Reference Include="System.Core"/>
    <Reference Include="System.Xml.Linq"/>
    <Reference Include="System.Net.Http"/>
    <Reference Include="System.Xml"/>
    <Compile Include="**\*.cs" />
</Project>

Or even better

<?xml version="1.0" encoding="utf-8"?>
<Project OutputType="Library" RootNamespace="ClassLibrary22" AssemblyName="ClassLibrary22" TargetFrameworkVersion="v4.5.2">
    <Reference Include="**\*.dll"/>
    <Compile Include="**\*.cs" />
</Project>

I don't know what ItemGroup and PropertyGroup is even good for & I'm sure I'm not the only one.
I can only guess it has something to do with making things dynamic.

And that brings me to the next topic:
The current csproj files are extremly mighty. You can almost see it as a primitive programming language, based on XML. But that's not what people want. You are mixing two different things together here: The compiler & the build system.

In my opinion, we should completely separate those 2 things.
First, we should let the people use the build system they want. For me it would be gulp, because programming the build process in JavaScript makes much more sense than doing it in some strange XML programming language thingy.

Second, we should make the compiler as dumb as possible. I give it the files & references, tell it the output name, and it generates my binary. No need for it to provide dynamic features, I can do this in gulp or any other build system of my choice.

So what should the project file be in the end? Just parameters for the compiler, nothing more.
And I don't really care how that looks like in the end. XML? JSON? Doesn't matter, as long as it's as minimal and dumb as possible, and gives the users freedom to use the tool they want.

@chrisaut

Here's a nice short presentation of what the current (a few weeks) ago state is/was. https://www.youtube.com/watch?v=2jfuDD9_BTw

Would be nice if these presentations and talks could be linked in relevant issues IMO :-)

@Mike-EEE

You said it, @chrisaut !

@VanCoding

Okay, from the video, it already looks much better.

2 questions remain, though:

  1. do you consider getting rid of "ItemGroup" and "PropertyGroup" as well?
  2. will MSBuild be needed to compile a .NETCore project, or will the dotnet CLI be able to read .csproj files?
    2.1) If dotnet CLI will be able to read .csproj files, will it also be able to read csproj files in the old format? Wouldn't that mean a LOT of code, because .csproj files can be very dynamic?
    2.2) If it won't be able to read .csproj files, doesn't that mean, that the format is still way too complex and we should maybe remove all the dynamic parts from it completely and create some sort of non-dynamic subset of the format. And as long as you only use that subset only, all tools (including MSBuild & Visual Studio) will be able to read it. And if you need more, you can use all features, but limit yourself to MSBuild and Visual Studio.
@gulbanana
gulbanana commented Sep 30, 2016 edited

some of those questions have already been answered in other places. some answers i've picked up from spectating:

  1. ItemGroup and PropertyGroup are a core part of how msbuild works and will not go away. some other parts of the file will though. and item/property groups might become smaller, for example, by turning property sub-elements into attributes

  2. msbuild, as a nuget package, will be a dependency of the dotnet cli. you will continue to run "dotnet compile" and so on but internally it will be using msbuild

2.1) see above - it will be able to read csproj files with old/extra bits, yes. this won't be extra code in the CLI itself because it just uses the msbuild APIs.

@VanCoding

@gulbanana Thank you.

This leads to a few more questions:

  • Wasn't dotnet cli able to compile c# without MsBuild?
  • Where can I find the C#-compiler itself? Is it built into MsBuild?

What I don't get is, why do you want to force a build system upon us? To me MsBuild seems to be extactly that, only a build system. I mean, it can also be used to build C++ projects, so it cant be just a compiler.

Why don't you decouple MsBuild (the build system) from the compilers? Wouldn't it be cool, if I could use MsBuild to compile a C++ project with GCC, or C# using the Mono compiler?
And of course, wouldn't it be cool if I could use your C# compiler without MsBuild?

I have so many questions and am not sure if they really fit here or should be answered here. So, I'm sorry if they don't.

@davkean
Member
davkean commented Sep 30, 2016 edited

@VanCoding Compilers and MSBuild are not tightly coupled. MSBuild effectively calls "csc.exe" to compile C# code. You can call it directly if you would like.

C# using the Mono compiler?

That's exactly what happens today.

@benaadams

@VanCoding the Roslyn C# compiler is over here: https://github.com/dotnet/roslyn though there are other compilers.

The dotnet cli uses MsBuild to build the project as it tells it how it fits together.

You can use the C# compiler by itself https://msdn.microsoft.com/en-us/library/78f4aasd.aspx but then you'd need to add your own build system around it.

@VanCoding
VanCoding commented Sep 30, 2016 edited

@davkean cool! That explains a lot.
So that should allow us to compile our C# projects without MsBuild.
If so, I think I'll no longer disturb you here, because I'll be able use my own solution in the case that the slimmed down .csproj files don't make me happy :)

Thank you guys, btw!

@chrisaut
chrisaut commented Oct 1, 2016
do you consider getting rid of "ItemGroup" and "PropertyGroup" as well?

I have to agree with others here. These are horrible names and I always hate seeing them in proj files. Why can these grouping tags not have some proper name, eg. <References> for the "Itemgroup containing the references?

@gulbanana

those groupings are actually arbitrary - you can rearrange them or put everything in a big group if you like.

@chrisaut
chrisaut commented Oct 1, 2016

Really? So what's the difference between PropertyGroup and ItemGroup? Are they interchangeable?

@Mike-EEE
Mike-EEE commented Oct 1, 2016 edited

I have to agree with others here. These are horrible names and I always hate seeing them in proj files.

Really? So what's the difference between PropertyGroup and ItemGroup?

Time for me to be the squeaky wheel here and kindly remind everyone that the ask/request for a POCO-based model and system would remedy these sorts of ambiguous dilemmas and frustrations ("and much much more!").

Please take a second to upvote for this issue if you haven't already. It is currently the highest voted item in this repo: #37

Thank you for your past and continued support!

@chrisaut
chrisaut commented Oct 1, 2016

@Mike-EEE I agree with you, but I don't think its realistic at this point that they'll do something like that. Maybe in the long run. I'm trying to get them to make it less painful in the meantime. And I have to admit I didn't know property/itemgroup don't really do anything. I still think they are horrible names.

@Mike-EEE
Mike-EEE commented Oct 1, 2016

Haha sounds good, @chrisaut. I have been suffering through this mire for over a decade now, and am in total agreement with your assessment, hence the ideas. You can cover the short/medium-term of all the angst, and I will cover the longer-term. ๐Ÿ˜„

@vbfox
vbfox commented Oct 1, 2016

@chrisaut PropertyGroup contains assignation (a = b) and ItemGroup are for appending (a += b).

You can't interchange because they essentially point to 2 different collection of variables.
You can have just one of each if you wish. Except that visual studio will force his own structure upon you each time you save the project :)

But that's the current design, Microsoft could well allow property and items under Project if they wanted, at the price of msbuild debugging (Misnaming a task is currently an error but could silently be considered a property or item if they were allowed to be mixed) that would make simple projects a lot more readable.

@gulbanana

this stuff is all documented at https://msdn.microsoft.com/en-us/library/ms171453.aspx# - it's actually not that complicated - certainly not compared to maven or ant. historically it's seemed like this arcane obtuse thing because visual studio hides it away from you, but my hope is that if we're all hand-editing csproj files for .net core 1.1 or whatever then it will stop scaring people.

@gulbanana
gulbanana commented Oct 2, 2016 edited

fwiw, @Mike-EEE, msbuild IS just an object model. you could totally have a project file that looked like this

{
    'ItemGroup': [
        { 'Item': 'Compile', 'Include': 'dir1/*.cs' }
        { 'Item': 'Compile', 'Include': 'specialfile.cs' }
    ],
    'DefaultTarget': {
        'Task': 'Exec',
        'Command': 'csc %(Compile.Identity)'
    }
}

and load it into the api with a basic wrapper frontend. however, nobody bothers to do this because there is no particular value in typing a different kind of bracket.

@Mike-EEE
Mike-EEE commented Oct 2, 2016

Are you sure @gulbanana ? Last we checked the entire API was/is entrenched in XML. Example:
https://github.com/Microsoft/msbuild/tree/master/src/XMakeBuildEngine/Construction

I would be really interested in hearing what you mean here.

Additionally, to be sure, the goal here is to have full POCO objects, not representations/DTO/mapper entities like what ItemGroup/PropertyGroup certainly are. Would you be able to define those objects in a Xaml file? No, as they aren't CLR objects, with a namespace, etc. Once you are in POCO land you gain instant tooling support as well (sort of the biggest motivator here :) ).

@gulbanana

that is more xml-tied than i expected - i've used this api
https://github.com/Microsoft/msbuild/blob/master/src/XMakeBuildEngine/Definition/ProjectItem.cs
and didn't realise it was stored internally as backing XML rather than anything more abstract.

still, since the whole thing's declarative it'd be pretty trivial to have a frontend that converts from (other serialisation format) to xml..

@Mike-EEE
Mike-EEE commented Oct 2, 2016

... it'd be pretty trivial ...

Sounds like someone is volunteering for a quick PR to prove it. ๐Ÿ˜‰

@NickCraver
NickCraver commented Oct 2, 2016 edited

What is the scope of changes here? It seems like MSBuild is getting some changes...or I am misunderstanding what's required on the consumption side of the new format? Can someone clarify what (if anything) is happening to MSBuild itself to consume this new format? @davkean?

The references I see in this thread are:

Just to set expectations, this issue isn't tracking making sweeping changes to MSBuild

and

If you're looking for us to move away Items, Properties, Targets and Tasks, and ultimately from XML - this issue is not the one to track that.

...does that mean there are zero changes, or are there some minor changes required for MSBuild to work correctly with the current proposed format? If that set of changes is non-zero and consuming this new format requires updates to MSBuild anyway, what's the impact of a more modest proposal of simply aliasing ItemGroup or PropertyGroup with more intuitive names if we can come up with such? You could have simple aliases, e.g. <References>, <Files>, etc. (I'm sure people can make better names than me), all of which make the format far more approachable, intuitive, and hand editable. Of course maybe there's a blocker there I'm unaware of that makes the suggestion moot.

I would imagine that if we're doing a set of changes that require an updated MSBuild release to consume and breaking compatibility, it's extremely unlikely for that to happen again (as it should be) and we need to pair any changes that require an updated MSBuild together in this one upgrade pain point. If we have to pay the cost of deploying a new MSBuild anyway, why not fix the issues we keep coming back to with these extremely unintuitive elements?

If I'm an idiot and the current proposal requires exactly zero changes to MSBuild itself...nevermind then. Not requiring an updated build tools deployment is, IMO, a marginally bigger win overall.

@davkean
Member
davkean commented Oct 3, 2016 edited

This issue represents changes that we are making to the project template/format itself. There are some MSBuild changes that we're making to simplify the project file - however, they are being tracked by separate issues.

My comment was not push back on aliasing PropertyGroup/ItemGroup - it was about the fact that we're sticking with existing MSBuild concepts (there will always be properties, items, tasks and targets). The aliasing suggestion is a great one, and should add your thoughts to Microsoft/msbuild#820.

@eyalsk
eyalsk commented Nov 3, 2016 edited

@davkean I haven't seen any blog post about the changes that comes to MsBuild and to the project files is there any plans for it? I'm watching the repo but it's nice to have a detailed post about it or least a summary about it.

@eyalsk
eyalsk commented Nov 3, 2016

@rainersigwald Thank you. :)

@davkean
Member
davkean commented Jan 19, 2017 edited

Okay folks, I'm ready to mark this as completed. For the new SDK-based templates, we've got them down to simply the following by default, starting in the next public release of Visual Studio:

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

  <PropertyGroup>
    <TargetFramework>netcoreapp1.0</TargetFramework>
  </PropertyGroup>

</Project>

This includes enough information to:

  1. Pick up the right NuGet package for framework bits, or default set of framework assemblies if targeting .NET Framework

  2. Pick up all the source files, content files, and resources inside the "project cone" (ie everything under the project directory recursively)

  3. Pulls in the default set of tasks and targets that lets you build and publish

  4. Setup a set of defaults for namespace, assembly name, output path, etc

These project types will be created by default when targeting .NET Core and .NET Standard projects (console, web and library). We'll be enabling this types of projects for .NET Framework, and other project types in a future release of Visual Studio past VS 2017.

If you would like to see more changes, or you find issues in the current changes, I'll ask that you create a new unique bug to for us to track the work.

@davkean davkean closed this Jan 19, 2017
@NickCraver

@davkean Thanks for all the progress! It really is far, far better - and I've been using this daily.

Some links for others following along:

  • Intellisense issue is here: #1249
  • Making .csproj more readable (e.g. <References> being an alias for <PropertyGroup>) is here: Microsoft/msbuild#820
@Mike-EEE
Mike-EEE commented Jan 19, 2017 edited

Wow, that is really impressive, actually. I for one would have a bit different impression of MSBuild/VS/developer experience if that was the type of file that we were introduced to work with when creating a new project.

Granted, all the advanced spelunking would probably still result in the sourpuss around the MSBuild development experience that I am now. ;) But first impressions are important and still matter. Really great to see all the work to make this happen. ๐Ÿ‘

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment