-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DSL based generic project format with remotely acquirable plugins #1289
Comments
Solid post, @gulshan. Thank you for your contribution to the community. 👍 |
@gulshan Would love to see a sample of this DSL that you are suggesting. Not as in "design me a DSL" but more of a "Here's how it could look like". Would help gather support for your cause. Thanks to @Mike-EEE for moving me from one issue to the other. 😉 |
Haha right, @MaximRouiller? My baby has already grown a little long in the tooth for only being around 6 months, haha. But, it's nice to capture the history, sentiment and dialogue, IMO. Hopefully along with issues like this one it will lead to consensus, direction, and most importantly action towards improving MSBuild. |
@Mike-EEE My belief is, it will end up like ASP.NET. It will get rewritten. 😉 Thing is... you don't want to rewrite the build system while Xamarin has just been bought and you just rewrote ASP.NET. From scratch. Too many moving pieces and too many customers who will have a "Taco Bell bathroom experience" but with bricks. So you change one piece at a time. First, ASP.NET. Once everything is relatively stable and you stop re-inventing the framework, then you can move to a bigger project. I already see investments being made to the project system with dotnet/roslyn-project-system. Now, whether my prediction about an MSBUILD rewrite is to hold true or not... that's a WHOLE different story. May never happen. The only thing I know is that there were always one constant in our domain. Change. |
@Mike-EEE Thanks for the support! [ Example moved to top post to accumulate votes 😄 ] And I am not proposing to fully rewrite MSBuild with all its internals. I am just proposing a DSL frontend with some new features. Let's see what happens. |
@MaximRouiller I have a little more faith in this than you do, I suppose. We are not asking for sweeping changes to the internals, but how input is fed into those internals. @gulshan you have inspired me. Along with @jnm2's challenge in the other thread I am going try to assemble something that looks remotely close to what I am after here. 👍 |
@Mike-EEE Thread carefully. We may find ourselves with a 25th build system. Something similar already exist with Cake. |
Yeah, but with MSBuild idioms and entities. Like @gulshan says, let's see what happens. 😄 |
Hey actually guys, Cake is not like msbuild. Cake is build orchestration, exactly like the new TFS build definitions. Both Cake and TFS call into msbuild, or vstest, or NuGet publish, etc. Neither Cake nor TFS build actually call (Cake is frickin awesome though...) |
If you're writing a new build system, the most important factor to me is that you cleanly isolate the project definition from the build script. The project definition must absolutely be treated as data and be readable and writable by tooling. The build script will then gather the information it needs through a project definition format adapter which reads the project definition. (You should have multiple pluggable format adapters so that the build system can gather the same information from an XML csproj or a project.json or your own custom format that you like. That way people can continue using Visual Studio csprojs which is an important capability for the new build system.) The build script itself could be a full DSL though. |
That pretty much sums up my position on this as well. The project file is simply an input data file (which is described in POCOs, that way it can leverage tooling greatness) which is then used by the build process. In my ideal world, the process file(s) are also comprised of serialized POCOs and can also be described in different formats as well. Figuring out how to do this would involve some work, as there would have to be a registry of sorts to know all supported formats and to select the appropriate serializer to load it into memory. But, for the sake of discussion we can keep it simple and say that it is simply XML. Or simply JSON. I lied. Nothing is simple here. 😛 |
Just to be clear... I know what you mean, but I would consider POCO an implementation detail of the format adapter. If I was writing such an adapter, I would not want to use POCOs because they would be slow and heap overhead. I'd prefer to do fast forward-only reading of the XML or JSON or other text, as or if the build system needs it, rather than construct a massive single universe of every possible setting in the linked project files. |
@jnm2 Initially, I was also in that camp. But, this is what changed my mind. Generally there are a lot of types of projects supported by a build system like MSBUILD. So, it can be a C# asp.net app, a VB Windows Forms app, a F# Xamarin app or C++ server app, but will have different project properties. If we have separate project definition file, be the format JSON, XML or POCO, either you go with a generic and lenient schema, or you have multiple project types with strongly enforced schema. (Current MSBuild is probably worst of both worlds- multiple project formats- Here I am proposing not only a DSL but also a plugin based architecture. So, all the project types are actually plugins of MSBuild. And they will define their own format of project description. And DSL will be used to provide that description, with strongly-typed support. Plugins can easily update or even change their project format, which will be carried to the developers by errors or warnings in DSL. BTW, plugins are all versioned, so no worry of breaking projects if plugin version not updated. Multiple plugins can be used in same project. Using Typescript with asp.net will be just setting up plugins. This kind of flexibility is very hard(even if possible) with simple data formats. Another thing is, most of the projects do not use custom build logic. So, even if build logic is allowed in DSL based format, very few people will use/see it. And one can always separate the custom build logic into a separate file and include that in the project file. And lastly, Gradle is using DSL very successfully for project description. You rarely hear or see any complain about the project format. So, as I have said, MSBuild can just be like Gradle. Oh, MSBuild also allows project description from build logic in same file! |
I would prefer something like the above, except idiomatic C# rather than something gradle-y. Better yet, why not just ask for a C# file (with a special name, i.e. This would also provide an avenue for easy backwards-compatibility with existing build systems like the existing MSBuild |
Ah that's the thing, the XML and JSON are describing objects that the build process understands, correct? Alright, I took some time to provide a VERY rough sketch of what I am thinking of, and have posted that here: #613 (comment) Please let me know if you have any questions. Sorry for the cross-posting. Now I'm confused more than usual. 😛 |
@Mike-EEE Making |
Yes @gulshan, Xaml is chatty and verbose, and that is a valid criticism of the format. There are new flavors emerging such as OmniXaml that are tackling that aspect. However, what is important here is the features that are gleaned from this, which I hope the screenshot successfully captures. Again, the idea here is that the content that you see in |
I got a comment on this proposal on Twitter saying-
And I that quite true- a language already known to user will be better than a new DSL. In fact, Gradle do not made a new DSL, they used Groovy and now Kotlin scripts. So, I thought, how about using C# Script in this case. So, my DSL example in the top post became this in C# Script #r "nuget: Microsoft.CSharp/1.0.1"
using Microsoft.Build;
using Microsoft.CSharp;
Project = new CSharp.ConsoleApplication{
TargetFramework = TargetFrameworks.Netstandard16,
FileIncludePattern = "**\*.cs",
ProjectInformation = new Information{
ApplicationName = "My Console App",
VersionName = "1.0",
Author = "Mr. Awesome"
},
BuildTypes = new List<BuildType>{
new BuildType{
Name = BuildType.Debug,
LogEnabled = true,
LogLevel = Log.Debug
},
new BuildType{
Name = BuildType.Release,
LogEnabled = false,
Native = true
}
},
Dependencies = new List<Dependency>{
new ProjectDependency{ Name = "ExternalProject", Path = "../ExternalProject" },
new AssemblyDependency{ Name = "ExternalLib", Path = "../ExternalLib.dll" },
new NugetDependency{ Name = "Microsoft.NETCore.App", Version = "1.0.0" },
new NugetDependency{ Name = "Microsoft.NET.SDK", Version = "1.0.0" },
new NugetDependency{
Name = "Microsoft.NET.Tools-pre", Version = "1.0.0",
SourcePath="https://www.myget.org/F/Microsoft.NET.Tools-pre" // For Myget
}
//new NPMDependency{}
}
};
Task<Artifact> async CleanBuild()
{
if (BuildDirectory.Exists())
{
await Clean();
}
return Build();
} The pros in this case is-
|
Yessss.... you got it, @gulshan. This is why POCO is the best-o. Ha ha. Once you are using plain ol' CLR objects, you can do anything with them, which then means:
Lower TCO is the way to go, yo. 😛
Yeah, that issue has unfortunately been butchered by conversation and misunderstandings. I've actually been working to flesh out the POC above that demonstrates more of what we're after here. I will try to incorporate more of your modelling efforts. 👍 |
@gulshan My only problem with this is how does the NuGet package manager work? How do plugins like ReSharper add or remove references automatically? And how do PowerShell scripts work that are intended to have the same effect on each project, like installing NuGet packages or adding files to the compilation? In every case the changes would not be persisted without editing the script you wrote, which could be as hard as solving the halting problem. |
@gulshan I read the whole page and see nothing about modifying the script, only about executing and monitoring and querying. I'm not sure what their approach would be, but you can't get around the halting problem without severely limiting the freedom of the language. |
@jnm2 Actually, as I have used, IDE do change the script, if I change something from GUI. May be some custom API is in use. After some searching it seems Gradle do have the possibility of Halting problem. Some links about it-
And it seems, Gradle went the way of using existing language instead of building a new restricted one. As mentioned in the first link, limiting the language from indefinite looping is the solution. Can that be done using Roslyn analyzer? |
Not without solving the halting problem. :D |
To be fair, you can warn if you encounter To be even fairer the halting problem isn't the immediate problem, though it could become part of it. The immediate problem is along the lines of, how does a tool add references if I'm generating the references list using linq off some JSON.NET object I read in from another whole file? It's the same problem any time you move from a declarative format to a scripting format. |
I would rather make these constructs(recursion, And I fail to see the problem with adding reference within a script. Is it impossible or source of other problems like halting problem? If it were impossible, Gradle could not have done that. |
Well, here's what I'm thinking. How does NuGet package manager or command line deal with installing a new package into this? Project = new CSharp.ConsoleApplication
{
Dependencies = ReadDependencyFile("customformat")
};
IReadOnlyCollection<Dependency> ReadDependencyFile(string path)
{
using (var file = File.OpenText(path))
return new JsonSerializer().Deserialize<IReadOnlyCollection<Dependency>>(file);
} |
I think, tools should be working with convention. In this case the convention is- defining the dependencies within actual project file. There can even be multiple conventions. Then a tool has to build support for each of the conventions separately. So, keeping the dependencies in a separate file can be another convention, which has to be supported by tools separately. But if user goes out of convention, then s/he cannot expect support from tooling and has to assume responsibility for that. For example, now MSBuild is introducing new features in the project file/format. So, other tools like Resharper has to build support for them. There is no automatic support. |
#1392 , #1436 , #1439 and dotnet/sdk#436 all are discussing SDKs and other build time tools and how they can plug into MSBuild. These SDKs and tools are similar to my proposed plugins. Just there shuold be a lot more scope of programmability for them. |
A very nice clean suggestion by @galich https://gist.github.com/danfma/c45087b2464cfb10e4f9935921f1acd7#gistcomment-1907390 Project
.UseCSharp(6)
.WithPackage("Microsoft.NETCore.App", "1.0.0")
.WithPackage("Microsoft.NET.SDK", "1.0.0")
.WithFramework("netcoreapp1.0", dependencies: framework => framework.AddSomething())
.Compile("**/*.cs")
.OutputExe(); |
Following different discussions, I am starting to envision the high level architecture of my proposal-
A slightly changed version of the project class file according to this architecture- #r "nuget: Microsoft.CSharp/1.0.1"
using Microsoft.Build;
using Microsoft.CSharp;
public class MyConsoleApp : CSharp.ConsoleApplication
{
public MyConsoleApp()
{
TargetFramework = TargetFrameworks.Netstandard16;
FileIncludePattern = @"**\*.cs";
ProjectInformation = new Information{
ApplicationName = "My Console App",
VersionName = "1.0",
Author = "Mr. Awesome"
};
BuildTypes[BuildType.Debug] = new BuildType{ LogEnabled = true, LogLevel = Log.Debug };
BuildTypes[BuildType.Release] = new BuildType{ LogEnabled = false, IsNative = true };
Dependencies.AddRange(new List<Dependency>{
new ProjectDependency{ Name = "ExternalProject", Path = "../ExternalProject" },
new AssemblyDependency{ Name = "ExternalLib", Path = "../ExternalLib.dll" },
new NugetDependency{ Name = "Microsoft.NETCore.App", Version = "1.0.0" },
new NugetDependency{ Name = "Microsoft.NET.SDK", Version = "1.0.0" },
new NugetDependency{ // For Myget
Name = "Microsoft.NET.Tools-pre", Version = "1.0.0",
SourcePath="https://www.myget.org/F/Microsoft.NET.Tools-pre"
}
//new NPMDependency{}
});
}
[MSBuildTask]
public async Task<Artifact> CleanBuild()
{
if (BuildDirectory.Exists())
{
await Clean();
}
return Build();
}
} Any thoughts? |
Add to recursion prevention that you can't invoke a delegate. As a corollary, you also can't use LINQ. I think that a better idea is to time out after a second (by default) if the code hasn't finished running. |
Why is it up to the build system to prevent halting? Developers should be
allowed to break their build this way if they want to IMO. It should also
be up to them to not break it, if that's what they want.
…On Thu, Dec 8, 2016 at 10:16 AM, Joseph Musser ***@***.***> wrote:
I think that a better idea is to time out after a second (by default) if
the code hasn't finished running.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#1289 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AA2j38HFr0XUok6CVDbmQ2ldVo8qYWbyks5rGC11gaJpZM4Kl-Za>
.
|
The minimal project file according to #1289 (comment) - #r "nuget: Microsoft.Build.CSharp/1.1.0"
using Microsoft.Build;
public class MyConsoleApp : CSharp.ConsoleApplication
{
public MyConsoleApp()
{
TargetFramework = TargetFrameworks.Netstandard16;
FileIncludePattern = @"**\*.cs";
}
} |
@gulshan I'd think that file include pattern would be a good safe default value (considering you declared it as a CSharp.ConsoleApplication) so you probably shouldn't even need to specify it. |
Do I hear a ONE LINE PROJECT??? :) |
@laurencee @Mike-EEE Going all default in minimal project? Sounds good to me. 😄 #r "nuget: Microsoft.Build.CSharp/1.1.0"
public class MyConsoleApp : Microsoft.Build.CSharp.ConsoleApplication {} |
As long as minimalistic build tool compiles and runs C# app that performs actual build - I'm ready to grow 3rd hand to say 👍 ! @gulshan version is a good one and can be built on top of minimalistic build tool. As well as many others, people tend to have different opinions and ideas are changing over time. Look at ORM, DI or ASP.NET - some prefer attributed syntax, some prefer fluent, some load models from config files. Keep the door open for alternative ideas. |
@galich As this is just .net code, one can make a plugin to inherit or extend a project type and provide all sorts of things. All the doors are wide open! |
Some more description of upcoming SDKs is provided in #1493 . An programmatically implementable .net interface |
Team triage: We don't plan language overhauls in the foreseeable future. |
TL;DR: Gradle is good. Be like Gradle.
Modern build tools are not just build tools, but they require complete project management tooling capability. This includes-
Currently MSBuild has most of these capabilities. But those capabilities are obscured behind it's XML based file format IMHO. I do not see these as short term goals. But as a long term vision, I think MSBuild can look at other successful build tools like Gradle and incorporate some of their good things. I shall try to describe a few such points comparing MSBuild with Gradle-
.*proj
files are like opaque binary files to developers- no hand-editing, only edit through Visual studio dialog. Hand-editing a DSL will be trivial. Ant and Maven was XML based and Gradle choose a DSL, which was good for them. With Powershell going cross-platform, I feel DSL can be based on it. DSL from Cake project can be another option. But others may have different choices. And this can be discussed later.*.*proj
file extensions for different kind of projects. Even the full project file name can be generic and constant likeproject.msbuild
orproject.build
. And plugins can be used to manage project types. Gradle usesproject.gradle
files and plugin specifies the project type. And, these plugins should reside in a repository in web with a qualified name and a specific version can be pulled by MSBuild over Internet on demand- just like Gradle. And the good thing is- multiple plugins can be applied to same project. So, different language files like C# and F# will be able to share same project. And MSBuild should not be tightly coupled with Nuget or even Visual Studio. I should easily be able to use MSBuild without any IDE, by just hand-editing project files and invoking commands from terminal. Visual studio will be just internally using MSBuild for its project management and provide a GUI for editing project file. Some more thoughts about project format in this comment.I know many of the things I am proposing are long shot. Some of these capabilities are currently managed by others tools like Dotnet CLI or Common Project System of Visual studio. But this is what I feel the future of MSBuild should be like. And this may solve many current dissatisfactions with MSBuild.
What I am proposing may look like this
project.build
file (which replacesConsoleProject.csproj
file)-Another format using .net class can be found here.
The text was updated successfully, but these errors were encountered: