Skip to content
Open
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ The change-detection and version-verification the workflow gates on live in the

The staged binary is written to `artifacts/native/<rid>/`. The LLVM release distribution bundles both the prebuilt `libclang` and the `lib/cmake/{llvm,clang}` config, headers, and import libraries used as `PATH_TO_LLVM` when building `libClangSharp`, so no from-source LLVM build is required (the manual [Building Native](#building-native) steps remain the way to reproduce a build locally). Because lifting `libclang` is just unpacking prebuilt binaries, the workflow does all five runtimes on a single Windows runner (its bundled `bsdtar` handles `.tar.xz`); `libClangSharp` is compiled per-runtime on native runners.

The `win-arm64` runtime is compiled with the LLVM release's own `clang-cl` (via `-G Ninja`) rather than MSVC. The official LLVM binaries are clang-built, and on Arm64 clang and MSVC disagree on the record layout of over-aligned non-POD base classes (e.g. `clang::TemplateSpecializationType`), so an MSVC-built shim reads members of clang-built types at the wrong offset. The other runtimes are unaffected (`win-x64` layouts agree between the two, and the Unix runtimes already use clang).

The jobs run when:

* **libclang** — the tracked LLVM major/minor version changes, or the workflow is dispatched manually with the `libclang` input set.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata minClientVersion="2.12">
<id>libClangSharp.runtime.linux-arm64</id>
<version>22.1.8.2</version>
<version>22.1.8.3</version>
<authors>.NET Foundation and Contributors</authors>
<owners>.NET Foundation and Contributors</owners>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata minClientVersion="2.12">
<id>libClangSharp.runtime.linux-x64</id>
<version>22.1.8.2</version>
<version>22.1.8.3</version>
<authors>.NET Foundation and Contributors</authors>
<owners>.NET Foundation and Contributors</owners>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata minClientVersion="2.12">
<id>libClangSharp.runtime.osx-arm64</id>
<version>22.1.8.2</version>
<version>22.1.8.3</version>
<authors>.NET Foundation and Contributors</authors>
<owners>.NET Foundation and Contributors</owners>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata minClientVersion="2.12">
<id>libClangSharp.runtime.win-arm64</id>
<version>22.1.8.2</version>
<version>22.1.8.3</version>
<authors>.NET Foundation and Contributors</authors>
<owners>.NET Foundation and Contributors</owners>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata minClientVersion="2.12">
<id>libClangSharp.runtime.win-x64</id>
<version>22.1.8.2</version>
<version>22.1.8.3</version>
<authors>.NET Foundation and Contributors</authors>
<owners>.NET Foundation and Contributors</owners>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
Expand Down
2 changes: 1 addition & 1 deletion packages/libClangSharp/libClangSharp/libClangSharp.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata minClientVersion="2.12">
<id>libClangSharp</id>
<version>22.1.8.2</version>
<version>22.1.8.3</version>
<authors>.NET Foundation and Contributors</authors>
<owners>.NET Foundation and Contributors</owners>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
Expand Down
10 changes: 5 additions & 5 deletions packages/libClangSharp/libClangSharp/runtime.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@
"runtimes": {
"linux-arm64": {
"libClangSharp": {
"libClangSharp.runtime.linux-arm64": "22.1.8.2"
"libClangSharp.runtime.linux-arm64": "22.1.8.3"
}
},
"linux-x64": {
"libClangSharp": {
"libClangSharp.runtime.linux-x64": "22.1.8.2"
"libClangSharp.runtime.linux-x64": "22.1.8.3"
}
},
"osx-arm64": {
"libClangSharp": {
"libClangSharp.runtime.osx-arm64": "22.1.8.2"
"libClangSharp.runtime.osx-arm64": "22.1.8.3"
}
},
"win-arm64": {
"libClangSharp": {
"libClangSharp.runtime.win-arm64": "22.1.8.2"
"libClangSharp.runtime.win-arm64": "22.1.8.3"
}
},
"win-x64": {
"libClangSharp": {
"libClangSharp.runtime.win-x64": "22.1.8.2"
"libClangSharp.runtime.win-x64": "22.1.8.3"
}
}
}
Expand Down
67 changes: 61 additions & 6 deletions scripts/build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -162,17 +162,72 @@ function Extract-Libclang([string] $runtime, [string] $source, [string] $destina
Copy-Item -Path $lib.FullName -Destination (Join-Path -Path $destination -ChildPath $name)
}

function Build-Libclangsharp([string] $runtime, [string] $source, [string] $destination) {
$arch = switch ($runtime) {
"win-x64" { "x64" }
"win-arm64" { "ARM64" }
default { throw "'$runtime' cannot build libClangSharp on Windows; use build.sh on the matching runner" }
function Get-VisualStudioInstallPath() {
$vswhere = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath "Microsoft Visual Studio\Installer\vswhere.exe"

if (-not (Test-Path -Path $vswhere)) {
throw "'vswhere.exe' was not found; a Visual Studio installation is required to build libClangSharp on Windows"
}

$vsPath = & $vswhere -latest -prerelease -products * -property installationPath | Select-Object -First 1

if (-not $vsPath) {
throw "No Visual Studio installation was found via 'vswhere.exe'"
}

return $vsPath
}

function Import-VisualStudioEnvironment([string] $vsPath, [string] $arch) {
$vcvars = Join-Path -Path $vsPath -ChildPath "VC\Auxiliary\Build\vcvarsall.bat"

if (-not (Test-Path -Path $vcvars)) {
throw "'vcvarsall.bat' was not found under '$vsPath'"
}

# clang-cl relies on the MSVC toolchain, Windows SDK, and linker being on
# INCLUDE/LIB/PATH; import the developer environment into this process so the
# subsequent cmake invocation inherits it.
& cmd /c "call `"$vcvars`" $arch > nul && set" | ForEach-Object {
$pair = $_ -split "=", 2
if ($pair.Count -eq 2) {
[System.Environment]::SetEnvironmentVariable($pair[0], $pair[1])
}
}
}

function Build-Libclangsharp([string] $runtime, [string] $source, [string] $destination) {
$nativeBuildDir = Join-Path -Path $ArtifactsDir -ChildPath "bin\native\$runtime"
$pathToLlvm = (Resolve-Path -Path $source).Path

& cmake -B "$nativeBuildDir" -S "$RepoRoot" -A "$arch" "-Thost=$arch" "-DPATH_TO_LLVM=$pathToLlvm"
if ($runtime -eq "win-arm64") {
# The official LLVM release binaries are built with clang. On win-arm64,
# clang and MSVC disagree on the record layout of over-aligned non-POD base
# classes (e.g. clang::TemplateSpecializationType), so an MSVC-built shim
# reads members of clang-built types at the wrong offset and returns garbage.
# Build the shim with the release's own clang-cl so the layouts match.
# win-x64 layouts agree between the two, so it keeps using MSVC.
$vsPath = Get-VisualStudioInstallPath
$hostArch = if ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq [System.Runtime.InteropServices.Architecture]::Arm64) { "arm64" } else { "amd64_arm64" }
Import-VisualStudioEnvironment -vsPath $vsPath -arch $hostArch

$env:PATH = "$pathToLlvm\bin;$env:PATH"

$ninja = (Get-Command -Name "ninja" -ErrorAction SilentlyContinue).Source
if (-not $ninja) {
$ninja = Join-Path -Path $vsPath -ChildPath "Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe"
}

& cmake -G Ninja -B "$nativeBuildDir" -S "$RepoRoot" "-DCMAKE_MAKE_PROGRAM=$ninja" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl "-DPATH_TO_LLVM=$pathToLlvm"
}
else {
$arch = switch ($runtime) {
"win-x64" { "x64" }
default { throw "'$runtime' cannot build libClangSharp on Windows; use build.sh on the matching runner" }
}

& cmake -B "$nativeBuildDir" -S "$RepoRoot" -A "$arch" "-Thost=$arch" "-DPATH_TO_LLVM=$pathToLlvm"
}

if ($LastExitCode -ne 0) {
throw "'cmake' configure failed for '$runtime'"
Expand Down
39 changes: 28 additions & 11 deletions sources/libClangSharp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,37 @@ find_package(Clang REQUIRED CONFIG
# into the imported LLVMDebugInfoPDB target in LLVMExports.cmake. That path
# won't exist on another machine (or a CI runner) with a different Visual
# Studio, causing LNK1181. Repoint it at the DIA SDK of the Visual Studio
# actually being used for this build.
if(MSVC AND CMAKE_GENERATOR_INSTANCE AND TARGET LLVMDebugInfoPDB)
if(CMAKE_GENERATOR_PLATFORM MATCHES "[Aa][Rr][Mm]64")
set(_clangsharp_diaguids "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/lib/arm64/diaguids.lib")
elseif(CMAKE_GENERATOR_PLATFORM MATCHES "[Ww]in32")
set(_clangsharp_diaguids "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/lib/diaguids.lib")
# actually being used for this build. The Visual Studio generator (win-x64)
# exposes its root and target as CMAKE_GENERATOR_INSTANCE/PLATFORM; Ninja +
# clang-cl (win-arm64) gets them from VSINSTALLDIR and the compiler arch id.
if(MSVC AND TARGET LLVMDebugInfoPDB)
if(CMAKE_GENERATOR_INSTANCE)
set(_clangsharp_vs "${CMAKE_GENERATOR_INSTANCE}")
else()
set(_clangsharp_diaguids "${CMAKE_GENERATOR_INSTANCE}/DIA SDK/lib/amd64/diaguids.lib")
file(TO_CMAKE_PATH "$ENV{VSINSTALLDIR}" _clangsharp_vs)
endif()
string(REGEX REPLACE "/+$" "" _clangsharp_vs "${_clangsharp_vs}")

get_target_property(_clangsharp_pdb_libs LLVMDebugInfoPDB INTERFACE_LINK_LIBRARIES)
if(EXISTS "${_clangsharp_diaguids}")
string(REGEX REPLACE "[^;]*[Dd][Ii][Aa] SDK[^;]*diaguids\\.lib" "${_clangsharp_diaguids}" _clangsharp_pdb_libs "${_clangsharp_pdb_libs}")
set_target_properties(LLVMDebugInfoPDB PROPERTIES INTERFACE_LINK_LIBRARIES "${_clangsharp_pdb_libs}")
if(CMAKE_GENERATOR_PLATFORM)
set(_clangsharp_arch "${CMAKE_GENERATOR_PLATFORM}")
else()
set(_clangsharp_arch "${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}")
endif()

if(_clangsharp_vs)
if(_clangsharp_arch MATCHES "[Aa][Rr][Mm]64")
set(_clangsharp_diaguids "${_clangsharp_vs}/DIA SDK/lib/arm64/diaguids.lib")
elseif(_clangsharp_arch MATCHES "[Ww]in32|[Xx]86")
set(_clangsharp_diaguids "${_clangsharp_vs}/DIA SDK/lib/diaguids.lib")
else()
set(_clangsharp_diaguids "${_clangsharp_vs}/DIA SDK/lib/amd64/diaguids.lib")
endif()

get_target_property(_clangsharp_pdb_libs LLVMDebugInfoPDB INTERFACE_LINK_LIBRARIES)
if(EXISTS "${_clangsharp_diaguids}")
string(REGEX REPLACE "[^;]*[Dd][Ii][Aa] SDK[^;]*diaguids\\.lib" "${_clangsharp_diaguids}" _clangsharp_pdb_libs "${_clangsharp_pdb_libs}")
set_target_properties(LLVMDebugInfoPDB PROPERTIES INTERFACE_LINK_LIBRARIES "${_clangsharp_pdb_libs}")
endif()
endif()
endif()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using NUnit.Framework;

Expand Down Expand Up @@ -169,6 +170,11 @@ typedef struct
[Test]
public Task DependentTemplateBaseTest()
{
if (OperatingSystem.IsWindows() && (RuntimeInformation.ProcessArchitecture == Architecture.Arm64))
{
Assert.Ignore("The win-arm64 libClangSharp prebuilt ships broken clangsharp shims. Remove this guard once the native lib is rebuilt. See https://github.com/dotnet/ClangSharp/issues/806.");
}

// A dependent template-specialization base (`Base<T>` within a class template) previously
// crashed `GetRecordDecl` with an `InvalidCastException` when both template bindings and
// empty-record exclusion were enabled, as the base resolves to a `ClassTemplateDecl`
Expand Down
6 changes: 6 additions & 0 deletions tests/ClangSharp.UnitTests/TypeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Linq;
using System.Runtime.InteropServices;
using ClangSharp.Interop;
using NUnit.Framework;

Expand Down Expand Up @@ -170,6 +171,11 @@ struct S { int field; void method(); };
[Test]
public void TemplateNameTest()
{
if (OperatingSystem.IsWindows() && (RuntimeInformation.ProcessArchitecture == Architecture.Arm64))
{
Assert.Ignore("The win-arm64 libClangSharp prebuilt ships broken clangsharp shims. Remove this guard once the native lib is rebuilt. See https://github.com/dotnet/ClangSharp/issues/806.");
}

var inputContents = """
template <typename T> struct Tmpl { T value; };
using SpecT = Tmpl<int>;
Expand Down