Skip to content

Automatically build dylib on macOS - #22147

Open
MrJul wants to merge 2 commits into
AvaloniaUI:mainfrom
MrJul:feature/auto-build-xcode
Open

Automatically build dylib on macOS#22147
MrJul wants to merge 2 commits into
AvaloniaUI:mainfrom
MrJul:feature/auto-build-xcode

Conversation

@MrJul

@MrJul MrJul commented Sep 4, 2026

Copy link
Copy Markdown
Member

What does the pull request do?

This PR automatically builds the native dylib on macOS whenever Avalonia.Native is built.

Previously, one needed to manually rebuild the native library using ./build.sh CompileNative, or build it in Xcode, then build the Avalonia.Native C# project to copy the new library.

Now, a modification in a .mm or .h file will automatically trigger a rebuild, allowing one to just press F5 in their IDE as usual, speeding up local iteration. Build errors are reported automatically by MSBuild. Warnings are ignored for now.

This PR also changes the native library to be built with the current configuration (Debug/Release) instead of forcing Release.

@MrJul MrJul added enhancement os-macos area-infrastructure Issues related to CI/tooling infrastructur labels Sep 4, 2026
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0069439-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

Comment on lines +38 to +43
<Target Name="CompileAvaloniaNativeXcodeProject"
Condition="'$(BuildAvaloniaNativeXcodeProject)' == 'true'"
BeforeTargets="DispatchToInnerBuilds;BeforeBuild"
Inputs="@(AvaloniaNativeSource)"
Outputs="$(AvaloniaNativeDylibPath)">
<Message Importance="high" Text="Building native library $([System.IO.Path]::GetFileName($(AvaloniaNativeDylibPath)))" />

@maxkatz6 maxkatz6 Sep 5, 2026

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 should be able to reuse the same task for CompileNative nuke target. I.e. dotnet msbuild -t:CompileAvaloniaNativeXcodeProject.

Keeping xcodeproj/CONFIGURATION_BUILD_DIR paths defined in one place (this csproj).

You might need to extract this target to be executable without BeforeTargets - shared one that can be called from the nuke.
And add a second one that depends on a shared CompileAvaloniaNativeXcodeProject and runs before BeforeBuild.

<Target Name="CompileAvaloniaNativeXcodeProject"
Condition="'$(BuildAvaloniaNativeXcodeProject)' == 'true'"
BeforeTargets="DispatchToInnerBuilds;BeforeBuild"
Inputs="@(AvaloniaNativeSource)"

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.

Please, use "inputs cache file" approach (see

<Target Name="_GenerateAvaloniaResourcesDependencyCache" BeforeTargets="GenerateAvaloniaResources">
<PropertyGroup>
<_AvaloniaResourcesInputsCacheFilePath>$(IntermediateOutputPath)/Avalonia/Resources.Inputs.cache</_AvaloniaResourcesInputsCacheFilePath>
</PropertyGroup>
<ItemGroup>
<CustomAdditionalGenerateAvaloniaResourcesInputs Include="$(_AvaloniaResourcesInputsCacheFilePath)" />
</ItemGroup>
<Hash ItemsToHash="@(AvaloniaResource);@(AvaloniaXaml);$(MSBuildAllProjects)">
<Output TaskParameter="HashResult" PropertyName="AvaloniaResourcesDependencyHash" />
</Hash>
<MakeDir Directories="$(IntermediateOutputPath)/Avalonia" />
<WriteLinesToFile Overwrite="true" File="$(_AvaloniaResourcesInputsCacheFilePath)" Lines="$(AvaloniaResourcesDependencyHash)" WriteOnlyWhenDifferent="True" />
<ItemGroup>
<FileWrites Include="$(_AvaloniaResourcesInputsCacheFilePath)" />
</ItemGroup>
</Target>
).

<BuildAvaloniaNativeXcodeProject Condition="'$(BuildAvaloniaNativeXcodeProject)' == ''">$([MSBuild]::IsOSPlatform(OSX))</BuildAvaloniaNativeXcodeProject>
<AvaloniaNativeSourceDir>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)../../native/Avalonia.Native))</AvaloniaNativeSourceDir>
<AvaloniaNativeXcodeProject>$(AvaloniaNativeSourceDir)/src/OSX/Avalonia.Native.OSX.xcodeproj</AvaloniaNativeXcodeProject>
<AvaloniaNativeBuildDir>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)../../Build/Products/$(Configuration)))</AvaloniaNativeBuildDir>

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.

this seems to be pointing to /build which contains our .targets/.props, am I reading this right?

Outputs="$(AvaloniaNativeDylibPath)">
<Message Importance="high" Text="Building native library $([System.IO.Path]::GetFileName($(AvaloniaNativeDylibPath)))" />
<!-- TODO: Don't ignore xcode warnings, fix them instead -->
<Exec Command="xcodebuild -quiet -project &quot;$(AvaloniaNativeXcodeProject)&quot; -configuration $(Configuration) CONFIGURATION_BUILD_DIR=&quot;$(AvaloniaNativeBuildDir)&quot; GCC_WARN_INHIBIT_ALL_WARNINGS=YES ONLY_ACTIVE_ARCH=NO"

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.

This doesn't re-generate native headers. Nuke target does.


<!-- On macOS, build the underlying Xcode project whenever one of its sources changed -->
<ItemGroup Condition="'$(BuildAvaloniaNativeXcodeProject)' == 'true'">
<AvaloniaNativeSource Include="$(AvaloniaNativeSourceDir)/**/*.mm;$(AvaloniaNativeSourceDir)/**/*.h" />

@kekekeks kekekeks Sep 7, 2026

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.

Conciser blanket $(AvaloniaNativeSourceDir)/**/* excluding avn.h (if it's built by the same target). Otherwise us adding .cpp file or someting else will break it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-infrastructure Issues related to CI/tooling infrastructur enhancement os-macos

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants