Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ git clone https://github.com/DynamoDS/DynamoRevit.git
- Make sure you have the following installed on your computer:
- For Revit 2024 and older: [.Net Framework 4.8 SDK](https://dotnet.microsoft.com/download)
- For Revit 2025 and newer: [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) for Windows x64
- Run `restorepackages.bat` from a command prompt with administrative privileges (Located in your _Github\DynamoRevit\src folder_)
Note: `restorepackages.bat` employs the use of a legacy tool `aget.exe`, which requires VC++ 2010 redistributable installed, before you can run it. When missing you will get an `msvcr100.dll not found` error. Make sure to install the x86 version, not the x64 version!
- Copy `RevitAPI.dll`&`RevitAPIUI.dll` to the folder `DynamoRevit\lib\Revit Preview Release\net48`, these 2 dlls are in the folder same with `Revit.exe` installed on your computer
(if you want to build other branch of DynamoRevit, but corresponding version of Revit is not installed locally, you can get these dlls from https://www.nuget.org/ )
- Set the `RevitVersionNumber` environment variable to the Revit version you're building against (e.g. `2020`) either in the system environment or in the [user_locals.props](https://github.com/DynamoDS/DynamoRevit/blob/Revit2017/src/Config/user_local.props) file in your build folder.
Expand Down Expand Up @@ -80,9 +78,16 @@ where `<version>` is the version of Revit for which the addin is built. Notice t

Now you should be able to launch Revit and see the Dynamo and Dynamo Player icons on the Manage tab. If you experience issues, check the troubleshooting tips in the next section.

## Troubleshooting Build Issues
### Build dynamo revit against a local version of Dynamo

1. Build Dynamo locally
2. Run the Dynamo nuget script (more info [here](https://github.com/DynamoDS/Dynamo/blob/master/tools/NuGet/README.md))
```.\BuildPackages.bat "template-nuget" "...\GitHub\Dynamo\bin\AnyCPU\Release"```
This will locally produce all the dynamo nugets.
3. In you Visual Studio editor, add/change the nuget sources to point to your local nuget folder (where the local nugets are).
![alt text](images/local_dynamo_nugets.png)

* Make sure you ran [restorepackages.bat](https://github.com/DynamoDS/DynamoRevit/blob/Revit2017/src/restorepackages.bat) in a command prompt with administrator privileges. It creates soft links for all the NuGet packages folder dropping the version information so that the projects files don't need to be changed when package versions are changed. The package versions are defined in the [packages-template.aget](https://github.com/DynamoDS/DynamoRevit/blob/Revit2017/src/Config/packages-template.aget) file. LatestBeta is used for Dynamo specific packages to automatically download the latest beta packages.
## Troubleshooting Build Issues

* If you see errors like:

Expand Down
Binary file added images/local_dynamo_nugets.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<DebugSymbols>false</DebugSymbols>
<DebugType>None</DebugType>
<AssemblyTitle>AssemblyInfoGenerator</AssemblyTitle>
<OutputPath>bin\$(Configuration)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
Expand Down
106 changes: 106 additions & 0 deletions src/BUILDSYSTEM_TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Build System Cleanup — Open Questions & TODOs

These are known issues and open design questions in the build system that need
Copy link
Copy Markdown
Member

@mjkkirschner mjkkirschner Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you have go through this and note what is now done after this PR? Have an agent do this?

to be resolved, particularly for the `D4R_DA_2026` branch targeting Revit 2026 / net8.

---

## 1. Platform naming is confusing and redundant

`CS_SDK.props` defines three platforms:

| Platform | TargetFramework | Notes |
|------------|---------------------|-------|
| `NET80` | `net8.0-windows` | Interactive Revit build |
| `NET80_DA` | `net8.0-windows` | **Same as NET80 — name implies net10 but it's net8** |
| `NET100` | `net10.0-windows` | Future Revit targeting net10 |

For the `D4R_DA_2026` branch (Revit 2026), only `net8.0-windows` is relevant.
`NET100` adds noise and `NET80_DA` is actively misleading.

**Important:** `_DA` in the platform name is a meaningful build profile — it is not just a
TFM alias. Any platform whose name contains `_DA` triggers these behaviours across multiple projects:

| Project | What `_DA` removes |
|---|---|
| `CS_SDK.props` | Defines `DESIGN_AUTOMATION` compile constant |
| `DynamoRevit.csproj` | Removes `DynamoRevit.cs`, `DynamoRevitApp.cs`, entire `ViewModel/` (interactive startup + ribbon) |
| `RevitNodesUI.csproj` | Removes all WPF controls, selection dialogs, XAML pages |
| `RevitServices.csproj` | Removes `Threading/*.cs` (UI thread marshalling, not needed in headless DA) |

So the `_DA` suffix carries real semantic weight. The problem is solely the `NET10` prefix,
which implies net10 when the TFM is actually net8. Renaming `NET80_DA` → `NET80_DA` everywhere
would fix the confusion without changing any build behaviour.

**Questions:**
- Should `D4R_DA_2026` drop `NET100` entirely and only expose `NET80`?
- Was `NET80_DA` ever actually net10 and got downgraded, or has it always been net8?
- Should DA just use `NET80` with a separate property/flag to denote DA vs interactive,
rather than a separate platform name?
- If `NET80_DA` stays, should it be renamed (e.g. `NET80_DA`) to reflect actual TFM?

---

## 2. Solution file responsibilities are unclear

| Solution | Projects included | Typical build command |
|-----------------------|--------------------------------|-----------------------|
| `DynamoRevit.DA.sln` | DADynamoApp + deps only | `/p:Platform=NET80_DA` |
| `DynamoRevit.All.sln` | Everything incl. tests | `/p:Platform=NET80` or `NET100` |

`DADynamoApp` is **not** listed explicitly in `All.sln` — it is pulled in as a
transitive project reference from `RevitSystemTests`. This causes the solution to
build it without a proper platform mapping, which leads to build errors under
`dotnet build` with .NET SDK 10 (see issue 3 below).

A workaround was added: explicit `DADynamoApp` entry in `All.sln` mapping
`NET80`/`NET100` → `NET80_DA`. But this is a band-aid.

**Questions:**
- Should `DADynamoApp` be a first-class explicit project in `All.sln`?
- Should `DA.sln` be a proper subset configuration of `All.sln`, or kept fully separate?
- Is there a reason DA uses `NET80_DA` platform instead of `NET80`? If not, unify them
and remove the extra platform.

---

## 3. `dotnet build` vs VS MSBuild inconsistency

`DynamoRevit.All.sln` builds cleanly with VS MSBuild:
```
& "C:\Program Files\Microsoft Visual Studio\18\Professional\MSBuild\Current\Bin\MSBuild.exe" DynamoRevit.All.sln -p:Configuration=Debug -p:Platform=NET80 -m
```

But fails with `dotnet build` using .NET SDK 10:
```
dotnet build DynamoRevit.All.sln -c Debug /p:Platform=NET80
```

Two known `dotnet build`-only failures:

**a) `DADynamoApp` — `MSB3992: 'RootElementName' is not set`**
- Root cause: `EnableDynamicLoading=true` causes SDK 10 to set
`UseAttributeForTargetFrameworkInfoPropertyNames=true`, which requires
`RootElementName` to be set explicitly. VS MSBuild does not have this requirement.
- Possible fixes: set `<UseAttributeForTargetFrameworkInfoPropertyNames>false</UseAttributeForTargetFrameworkInfoPropertyNames>`,
or set `<RootElementName>DADynamoApp</RootElementName>` explicitly.

**b) `DynamoRevitIcons` — `ResGen.exe not supported on .NET Core MSBuild`**
- Pre-existing issue. The `.resx` code generation step uses ResGen.exe which is
not available in the .NET Core MSBuild toolchain.
- Possible fix: migrate resource generation to use `<EmbeddedResource>` without
ResGen, or exclude from `dotnet build` paths.

**Question:** Is `dotnet build` a supported/required path in CI, or does CI always
use VS MSBuild? The `Jenkinsfile` delegates to `DynamoRevitUtils` — need to check
those build scripts to confirm.

---

## 4. Research needed / action items

- [ ] Check `DynamoRevitUtils` Jenkins scripts: which solution, which platform, `dotnet` or VS MSBuild?
- [ ] Confirm whether `NET100` is used in any CI job for this branch
- [ ] Decide on NET80_DA rename/merge with NET80
- [ ] Decide whether All.sln should be the canonical "build everything" solution
- [ ] Fix `dotnet build` compatibility if CI requires it (MSB3992 + ResGen)
16 changes: 14 additions & 2 deletions src/Config/CS_SDK.props
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<Project>
<Import Project="$(SolutionDir)Config/user_local.props" />
<Import Project="$(SolutionDir)Config/packages_versions.props" />
<PropertyGroup>
<PlatformTarget >x64</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<Platforms>NET100</Platforms>
<Platforms>NET100;NET80_DA</Platforms>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm so confused, I thought for 2026 we would not be supporting net 10? Is this because of net10 back port?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YEs, I know
ANd yes, because of backport

<TargetFramework Condition="'$(Platform)' == 'NET100'">net10.0-windows</TargetFramework>
<DCoreLibSubFolder>net10.0</DCoreLibSubFolder>
<TargetFramework Condition="'$(Platform)' == 'NET80_DA'">net8.0-windows</TargetFramework>
<DCoreLibSubFolder Condition="'$(Platform)' == 'NET80_DA'">net8.0</DCoreLibSubFolder>
<DCoreLibSubFolder Condition="'$(Platform)' == 'NET100'">net8.0</DCoreLibSubFolder>
Copy link
Copy Markdown
Member

@mjkkirschner mjkkirschner Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

net10 points to net8?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is supposed to be net10. Will fix

<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">17.0</VisualStudioVersion>
<RevitVersionNumber Condition=" '$(RevitVersionNumber)' == '' ">2026</RevitVersionNumber>
<PACKAGESPATH>$(SolutionDir)packages</PACKAGESPATH>
Expand Down Expand Up @@ -39,4 +42,13 @@
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$(Platform.Contains('_DA'))">
<DefineConstants>$(DefineConstants);DESIGN_AUTOMATION</DefineConstants>
</PropertyGroup>
<ItemDefinitionGroup>
<ProjectReference>
<Private>false</Private>
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
</ItemDefinitionGroup>
</Project>
27 changes: 27 additions & 0 deletions src/Config/packages_versions.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- 3rd party package versions -->
<DYNAMOCORE_VERSION>3.6.2.11575</DYNAMOCORE_VERSION>

<DYNAMOWPFUI_VERSION Condition="'$(DYNAMOWPFUI_VERSION)' == ''">$(DYNAMOCORE_VERSION)</DYNAMOWPFUI_VERSION>
<DYNAMOCORENODES_VERSION Condition="'$(DYNAMOCORENODES_VERSION)' == ''">$(DYNAMOCORE_VERSION)</DYNAMOCORENODES_VERSION>
<DYNAMOTESTS_VERSION Condition="'$(DYNAMOTESTS_VERSION)' == ''">$(DYNAMOCORE_VERSION)</DYNAMOTESTS_VERSION>

<!-- These are useful when migrating to a new .NET while not all builds are available -->
<DCoreLibSubFolder Condition="'$(Platform)' == 'NET80'">net8.0</DCoreLibSubFolder>

<Greg_VERSION>3.0.1.4707</Greg_VERSION>
<GregRevitAuth_VERSION>3.0.8935.26399</GregRevitAuth_VERSION>
<DotnetVerSubFolder>net8.0</DotnetVerSubFolder>

<!-- Keep in sync with DynamoCore & TODO: check if still needed -->
<DynamicLanguageRuntime_VERSION>1.2.2</DynamicLanguageRuntime_VERSION>
<PYTHONNET_PY38_VERSION>2.5.1</PYTHONNET_PY38_VERSION>
<NewtonsoftJson_VERSION>13.0.1</NewtonsoftJson_VERSION> <!-- TODO: is this still needed? -->
<NUnit_VERSION>3.13.3</NUnit_VERSION>
<NUnit_Engine_VERSION>3.13.2</NUnit_Engine_VERSION>
<NUnit3TestAdapter_VERSION>5.0.0</NUnit3TestAdapter_VERSION>

</PropertyGroup>
</Project>
63 changes: 63 additions & 0 deletions src/DADynamoApp/DAApplication.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using System.Diagnostics;
using System.Reflection;

namespace DADynamoApp
{
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class DAApplication : IExternalDBApplication
{
private string ParentPath;
private string CurrentDirectory;
private readonly string PythonDllFolder = "pythonDependencies";

private DAEntrypoint daEntryPoint;

public ExternalDBApplicationResult OnShutdown(ControlledApplication application)
{
AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.ProcessExit -= CurrentDomain_ProcessExit;
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
return daEntryPoint.OnShutdown(application);
}

public ExternalDBApplicationResult OnStartup(ControlledApplication application)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

CurrentDirectory = Directory.GetCurrentDirectory();
ParentPath = Directory.GetParent(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)).FullName;

Console.WriteLine("<<!>> Starting to load DAEntrypoint");

daEntryPoint ??= new DAEntrypoint();

return daEntryPoint.OnStartup(application);
}

private static void CurrentDomain_ProcessExit(object? sender, EventArgs e)
{
Process proc = Process.GetCurrentProcess();
Console.WriteLine($"Dynamo exiting with Peak physical memory {proc.PeakWorkingSet64} bytes");
if (proc.HasExited)
{
Console.WriteLine($"Dynamo exiting with code {proc.ExitCode}");
}
}

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine($"Unhandled exception: {e}");
}

private Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args)
{
return DynamoRevitAssemblyResolver.ResolveDynamoAssembly(ParentPath, [Path.Combine(CurrentDirectory, PythonDllFolder)], args);
}
}
}
58 changes: 58 additions & 0 deletions src/DADynamoApp/DADynamoApp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<Project Sdk="Microsoft.NET.Sdk">
<ImportGroup Label="PropertySheets">
<Import Project="$(SolutionDir)Config\CS_SDK.props" />
</ImportGroup>

<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<!--EnableDynamicLoading prepares the project so that it can be used as a plugin -->
<!--https://learn.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support#simple-plugin-with-no-dependencies-->
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>

<ItemGroup>
<Compile Remove="obj\**" />
<EmbeddedResource Remove="obj\**" />
<None Remove="obj\**" />
</ItemGroup>

<ItemGroup>
<Reference Include="RevitAPI">
<HintPath>$(REVITAPI)\RevitAPI.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autodesk.Forge.DesignAutomation.Revit" Version="2026.0.0" />
<PackageReference Include="Autodesk.DataManagement" Version="2.0.0-beta4" />
<PackageReference Include="DynamoVisualProgramming.Core" Version="$(DYNAMOCORE_VERSION)" ExcludeAssets="runtime" GeneratePathProperty="true" />
<PackageReference Include="DynamoPlayer" Version="6.0.2" ExcludeAssets="runtime" GeneratePathProperty="true" />
<PackageReference Include="GregRevitAuth" Version="$(GregRevitAuth_VERSION)" GeneratePathProperty="true">
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DynamoRevit\DynamoRevit.csproj" />
<ProjectReference Include="..\Libraries\RevitNodes\RevitNodes.csproj" />
<ProjectReference Include="..\Libraries\RevitServices\RevitServices.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="DynamoPlayer.Models">
<HintPath>$(PkgDynamoPlayer)\bin\Release\net8.0\bin\DynamoPlayer.Models.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="DynamoPlayer.Server">
<HintPath>$(PkgDynamoPlayer)\bin\Release\net8.0\bin\DynamoPlayer.Server.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="DynamoPlayer.Workflows">
<HintPath>$(PkgDynamoPlayer)\bin\Release\net8.0\bin\DynamoPlayer.Workflows.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<Target Name="Copy dll" AfterTargets="Build">
<Copy SourceFiles="$(PkgGregRevitAuth)\lib\$(DotnetVerSubFolder)\GregRevitAuth.dll" DestinationFolder="$(OutputPath)" />
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we copy this because DA does not provide it?

</Target>
</Project>
Loading