Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixed languages and sub-projects with .NET Core

Tags:

c#

.net

build

f#

I have a project primarily written in F# that uses a component written in C#. It is building fine on Windows with Visual Studio and on Linux and OS X using Makefiles.

I'm trying to port it to .NET Core, which has its own build system, dotnet build. I'm having difficulty replicating the nested project handling of my existing build systems under it. That is, I want it to build the C# DLL, then build and link the F# executable project to it.

I tried to do without DLLs, but each project.json file can apparently only reference files in one language. If you try to add a C# file to the compileFiles list of an F# project file, dotnet build complains that it can't compile Foo.cs with fsc.

My C# project is in a subdirectory of the F# project, named after the namespace it implements, so I created a new .NET Core C# DLL project in that directory, but now I don't see how to tie the two projects together.

The dependencies feature of the project file format doesn't seem to solve this sort of problem. If the DLL project is in Foo/Bar and it implements the Foo.Bar namespace, dotnet restore fails to find it with this dependency reference:

"dependencies": {
    ...other stuff...
    "Foo.Bar": "*"
},

Apparently it can only search NuGet for dependencies. I don't want to ship the component to NuGet purely so that dotnet restore can find it.

I don't want to use bin syntax to reference the built DLL because that would require a 2-pass build and a third project.json file. (One for the F# project, one for the C# project, and one to reference the built DLL.) Even then, I still don't see how to tie the first project to the third.

Surely there's a simple way to have a nested build tree with dotnet build?

like image 333
Warren Young Avatar asked Mar 11 '16 11:03

Warren Young


1 Answers

Your problem is that one project is nested under the other. If you put them side by side (say, /src/RootProj and /src/Foo.Bar), you should be able to reference the Foo.Bar project with:

"dependencies": { 
  "Foo.Bar": "*" 
}

The dnx project system is cop..., ahem, heavily influenced by that of NodeJS, thus the reliance on directory structure to infer certain attributes.

The projects are expected to be located in subfolders of the root, and each is expected to have its own project.json file. The "root" itself comes from the global.json file located up the folder tree. The tooling traverses the folders up from the "current" one until it finds a global.json. The folder with global.json is then considered the "root of all roots". If you just create your solution from a template, you will have something like this:

/solution
   global.json
   /src
      /project1
         project.json
         File.cs
      /project2
         project.json
         File.cs
   /tests
      /testproject1
         project.json
         File.cs

When you are in any of the subfolders, the tooling will know the solution root by traversing the folders up. Similar to how git works.

If you look at the global.json file, you will probably see something like this:

{
    "projects": ["src", "tests"]
}

This means that the dnx tooling will expect to find projects under /src and /tests, that's it.

Now, from this, I can infer one other possible solution. Haven't tried it myself, but it just might work. Instead of moving your Foo.Bar project out to /src, you can add the path to it to projects in global.json:

{
    "projects": ["src", "tests", "src/Project1/Foo.Bar"]
}

Like I said, not sure if this will work or create some other subtle inconsistencies. Try it out.

like image 87
Fyodor Soikin Avatar answered Oct 16 '22 04:10

Fyodor Soikin