/ .NET

Handling Multiple Projects with Visual Studio Code

As the porting of the B-tree code continues and I randomly select methods to address, I run into Daxat.Ess.Utils.Collections.LiteralOccurrence. What's interesting about this class is not what it does or how it's implemented (it's a very simple class -- maybe should be a struct); what's interesting about it is that it is defined within a different class library.

As I've noted before, the Daxat Extensible Search Engine was a very large application -- spanning multiple Visual Studio projects. And that generally implies that there was a Visual Studio solution file bringing them all together. But what's the equivalent of a solution for VS Code?

note that much of the information below could become rendered useless once the RTM tooling for .NET Core 1.0 is releases, and the move from project.json files to .csproj files is complete.

Although there are different ways to use VS Code, the most common and natural way is to simply treat a directory as the rough equivalent to a traditional Visual Studio project. As such, a collection of peer directories can be thought of as a solution -- with a global.json file essentially bringing them all together.

Here's a simple (yet common) global.json file:

{
    "projects": [
        "src",
        "test"
    ],    
    "sdk": { "version": "1.0.0-preview2-003121" }
}

The "projects" value lists the top-level directories which contain the project directories. So, in this example, both the src and test directories are assumed to contain individual project folders. And each of these can contain multiple project folders.

So, for Bobo, we simply need to move all of the individual project folders into the src directory, and we'll make use of the `test directory for adding unit test projects.

We already had started to migrate Daxat.Ess.Engine to Bobo by dropping the entire project folder under src. Now let's do the same for FTx Server Library, which is where we find the needed LiteralOccurrence class.

Bobo
  src
    Daxat.Ess.Engine
    FTx Server Library
  test
    Daxat.Ess.Engine.Tests

With this layout and with the global.json file, we can now open the top-level Bobo directory with VS Code and treat it similar to a solution in Visual Studio:

"solution" folder in vscode

If we now navigate to a file, for example the BTree.cs file we been porting within the Daxat.Ess.Engine project, note that in the lower right-hand corner of VS Code we are asked to 'Select project':

Select project in VS Code

If we click on that, VS Code gives us a list of the project.json files it has found (following the projects information from global.json) and asks us to which project this file belongs:

Pick the project

Select Daxat.Ess.Engine, and now VS Code is operating in the context of that project.

If you next navigate to Daxat.Ess.Utils.Collections.LiteralOccurrence in FTx Server Library, the prompt changes to 'Switch projects', for VS Code now realizes that you are really in the directory structure of a different project and is giving you the option to set the context of VS Code to that project (for compiling and debugging purposes).

But more importantly, we can now add FTx Server Library as a project dependency to Daxat.Ess.Engine, and the dotnet compiler will be able to find it (and build it, if necessary). Compared to Visual Studio, this is similar to the "Add Project Reference" capability when you have a solution with two or more projects. To accomplish this, add "FTx Server Library": "1.0.0" to the dependencies in project.json for Daxat.Ess.Engine. If we attempt a command-line build from that directory, note that dotnet determines that (1) FTx Server Library is a dependency, (2) it needs to be built and (3) it can find it so it can build it. Mind you, we've still got hundreds of compilation errors, but at least this is yet another step forward.

dotnet can find the dependency

If you try to build from VS Code with CTRL+SHIFT+B, VS Code will complain that no task runner has been set:

No Task Runner

Now, this may strike you as odd or broken -- the build command worked when VS Code opened the Daxat.Ess.Engine folder, after all, so why not now when that project is set as the 'current' project?

Well, that's just not the way VS Code works; each directory, even a top-level one, needs to have its own configuration for tasks and the like. This is actually a very powerful feature.

To deal with it for now, click 'Configure Task Runner' and select .NET Core:

Configure task runner

This will create a default tasks.json file, but it still will not be correct. In this file, find the args for the build task and put in the path to the project.json for the project you wish to build. Think of this sort of like the Start Up Project feature in Visual Studio.

...
"tasks": [
    {
        "taskName": "build",
        "args": [ "src/Daxat.Ess.Engine/project.json" ],
        "isBuildCommand": true,
        "showOutput": "silent",
        "problemMatcher": "$msCompile"
    }
]
...

Press CTRL+SHIFT+B one more time, and note that VS Code attempts to run the build -- including detecting FTx Server Library as a dependency needing to be built.

it works! sort of