You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The path to the analyzer DLL files could be tricky to get right across a wide range of setups. Luckily, we can use a MSBuild custom target to take care of the path construction. Add [FSharp.Analyzers.Build](https://www.nuget.org/packages/FSharp.Analyzers.Build) to your project. This imports a new target to your project file (`AnalyzeFSharpProject`) and will allow us to easily run the analyzers for our project.
11
+
Finding the analyzer DLLs can be tricky across different environments. Luckily, MSBuild computes these paths after restore.
12
+
We can add a solution-level target that invokes the analyzer CLI with the correct paths.
12
13
13
-
### Installing Target via Nuget
14
+
##Solution targets
14
15
15
-
If you are using Nuget, add it to your `.fsproj` file:
16
+
MSBuild targets defined in `Directory.Solution.targets` can be invoked with `dotnet msbuild /t:YourTargetName`. We can create a target that reads the generated NuGet `*.nuget.g.props` file to discover analyzer package paths and collect all the projects we wish to analyze:
To locate the analyzer DLLs in the filesystem, we use the variable `$(PkgG-Research_FSharp_Analyzers)`. It's produced by NuGet and normalized to be usable by [MSBuild](https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#generatepathproperty).
53
-
In general, a `Pkg` prefix is added and dots in the package ID are replaced by underscores. But make sure to look at the [nuget.g.props](https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#restore-outputs) file in the `obj` folder for the exact string.
54
-
55
-
The `/analyzers/dotnet/fs` subpath is a convention analyzer authors should follow when creating their packages.
56
-
57
-
### Running the Build Target
58
-
59
-
At last, you can run the analyzer from the project folder:
60
-
61
-
```shell
62
-
dotnet msbuild /t:AnalyzeFSharpProject
63
-
```
64
-
65
-
📓 Note: If your project has multiple `TargetFrameworks` the tool will be invoked for each target framework.
66
-
67
-
## Using Analyzer Build Target in a Solution
68
-
69
-
Adding the custom target from above to all `.fsproj` files of a solution doesn't scale very well. We can use the MSBuild infrastructure to add the needed package reference and the MSBuild target to all projects in one go.
70
-
71
-
### Setting up Directory.Build.props
72
-
73
-
We start with adding the `PackageReference` pointing to your favorite analyzers to the [Directory.Build.props](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022) file.
74
-
This adds the package reference to all `.fsproj` files that are in a subfolder of the file location of `Directory.Build.props`:
Likewise we add the `FSharpAnalyzersOtherFlags` property to the [Directory.Build.targets](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory?view=vs-2022) file. For first time MSBuild users, this is effectively the same as adding a property to each `*proj` file which exists in a subfolder.
⚠️ We are adding the `FSharpAnalyzersOtherFlags` property to our **Directory.Build.targets** and **not to** any **Directory.Build.props** file! MSBuild will first evaluate `Directory.Build.props` which has no access to the generated nuget.g.props. `$(PkgG-Research_FSharp_Analyzers)` won't be known at this point. `Directory.Build.targets` is evaluated after the project file and has access to `Pkg` generated properties.
104
-
105
-
### Run Target for All Projects in the Solution
106
-
107
-
We can run the `AnalyzeFSharpProject` target against all projects in a solution
As we may not always want to target every project in a solution, we can create a second custom MSBuild target that calls the project-specific target for all relevant projects.
116
-
Add the following custom target to the [Directory.Solution.targets](https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-solution-build?view=vs-2022) file to be able to invoke analysis from all selected projects in one simple command:
At last, you can run the analyzer from the solution folder:
47
+
Run it with
147
48
148
49
```shell
149
50
dotnet msbuild /t:AnalyzeSolution
150
51
```
151
52
152
-
Note: we passed the `--code-root` flag so that the `*.sarif` report files will report file paths relative to this root. This can be imported for certain editors to function properly.
153
-
154
-
## MSBuild Tips and Tricks
155
-
156
-
MSBuild can be overwhelming for the uninitiated. Here are some tricks we've seen in the wild:
157
-
158
-
### Use Well-Known Properties
159
-
160
-
Checkout the [MSBuild reserved and well-known properties](https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-reserved-and-well-known-properties?view=vs-2022) to use existing variables like `$(MSBuildProjectFile)`.
161
-
162
-
### Wrap Path Arguments in Quotes
163
-
164
-
As MSBuild is all XML, you can use `"` to wrap evaluated values in quotes:
It can be a bit confusing to find out if a variable contains the value you think it does.
188
-
We often add a dummy target to a project to print out some values:
189
-
190
-
```xml
191
-
<TargetName="Dump">
192
-
<MessageImportance="high"Text="$(CodeRoot)" />
193
-
</Target>
194
-
```
53
+
Notes:
195
54
196
-
Run `dotnet msbuild YourProject.fsproj /t:Dump` and verify that `CodeRoot` has a value or not.
55
+
-`artifacts/obj/Telplin/Telplin.fsproj.nuget.g.props` is generated after `dotnet restore` runs.
56
+
The target depends on it, hence the `Condition="Exists('...nuget.g.props')"` check.
57
+
-`--code-root` is important for certain tooling to have the correct links from the problems found to your source code.
58
+
-`$(PkgG-Research_FSharp_Analyzers)` becomes available when your solution references the [G-Research.FSharp.Analyzers](https://www.nuget.org/packages/G-Research.FSharp.Analyzers) package. Expect a similar `$(Pkg...)` property for whichever analyzer package your project uses.
0 commit comments