Open chosl opened 2 years ago
Looking at the header files, I don't believe this is a bug, clang is correctly telling you that this library does not work on macatalyst.
You can see that it's a macOS library by doing:
find /Applications/Xcode_13.3.0.app | grep PCSC.tbd
/Applications/Xcode_13.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/PCSC.framework/Versions/A/PCSC.tbd
/Applications/Xcode_13.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/PCSC.framework/PCSC.tbd
for example.
Also, if you dig into that file, you'll see:
targets: [ x86_64-macos, arm64-macos, arm64e-macos ]
uuids:
- target: x86_64-macos
value: DE48AA20-C352-3A0C-9DA1-883F6E56A2FC
- target: arm64-macos
value: 00000000-0000-0000-0000-000000000000
- target: arm64e-macos
value: 40238A1D-06C4-3721-8168-4FD4E8A63976
3 different platforms of macOS, but no catalyst.
I am finding it difficult to find online documentation from Apple to confirm this, as the library appears poorly documented line, but given that I believe net6.0-maccatalyst will not be able to access this library.
Thank you @chamons for the detailed explanation! I'm still trying to put the pieces together and find some logic in the inconsistent behaviour through the maui preview/RC bits. It was fully possible to use the library in the Maui preview 14 bundling but I cannot be certain if it stopped working in RC1 or RC2. I haven't been able to reproduce a successful build with the preview 14 bundle with workload maui since it does't seem to exist in the nuget feeds any longer. Other libraries (pkcs11interop) has also had breaking behaviour during this period but I haven't investigated this further.
Do you have any theory of why it was possible in preview 14 workload (and possibly rc1)?
Hmm, that's really strange that it worked differently in previous previews. Maybe there is some reuse between catalyst and macos libraries that I don't know about, I'm not an expert here.
Let me reopen and have @rolfbjarne review it next week.
This seems to be a bug in Apple's native linker, this should either work for us, or not work for Xcode projects.
The problem is that the native linker complains when passed -framework PCSC
, because it thinks the PCSC
framework is only available on macOS. The reason it works when using Xcode, is because the linker receives the -framework PCSS
argument in a different manner (as a LC_LINKER_OPTION load argument in the object file, instead of on the command line), and in that case the native linker doesn't complain.
This is the result of compiling a *.m
file with Xcode:
#include <PCSC/PCSC.h>
int main(int argc, char * argv[]) {
SCardIsValidContext (0);
}
$ otool -l /Users/rolf/Library/Developer/Xcode/DerivedData/.../main.o | grep PCSC -B 5
Load command 29
cmd LC_LINKER_OPTION
cmdsize 32
count 2
string #1 -framework
string #2 PCSC
Now the question becomes: can we somehow replicate this?
--linker-option
flag.Let's try compiling our main.*.mm file with this flag:
$ clang [...]/main.x86_64.mm -Xclang "--linker-option=-framework PCSC"
but unfortunately that doesn't work, because -framework PCSC
ends up being a single argument to the linker:
ld: warning: unknown linker option from object file ignored: '-framework PCSC' in [...]/main.x86_64.o
$ otool -l /Users/rolf/Downloads/Maui/obj/Debug/net6.0-maccatalyst/maccatalyst-x64/nativelibraries/main.x86_64.o | grep PCSC -B 4
Load command 4
cmd LC_LINKER_OPTION
cmdsize 32
count 1
string #1 -framework PCSC
Using passing the two strings as two different arguments doesn't work either:
$ clang [...]/main.x86_64.mm -Xclang --linker-option=-framework -Xclang --linker-option=PCSC"
ld: warning: unknown linker option from object file ignored: '-framework' in [...]/main.x86_64.o ld: warning: unknown linker option from object file ignored: 'PCSC' in [...]/main.x86_64.o
$ otool -l /Users/rolf/Downloads/Maui/obj/Debug/net6.0-maccatalyst/maccatalyst-x64/nativelibraries/main.x86_64.o | grep PCSC -B 4
Load command 5
cmd LC_LINKER_OPTION
cmdsize 24
count 1
string #1 PCSC
And looking at clang's source code, I couldn't find a way to make clang do the right thing.
Let's add the -fms-extensions
flag to the clang commend line, and add this to our main.x86_64.mm
file:
#pragma comment(lib, "-framework PCSC")
but that results in:
$ $ otool -l /Users/rolf/Downloads/Maui/obj/Debug/net6.0-maccatalyst/maccatalyst-x64/nativelibraries/main.x86_64.o | grep PCSC -B 4
Load command 4
cmd LC_LINKER_OPTION
cmdsize 32
count 1
string #1 -l-framework PCSC
clang prepends -l
before writing the linker flag in the object file (but even without it it would still be a single argument instead of two arguments).
This seems to work, with a few notable findings:
-fmodules
must be passed to clang.[1]: Sidenote: this means that you can't use the PCSC framework from an Objective-C++ file in Xcode, because you run into the same problem this issue is describing.
Thank you @rolfbjarne, the explanation is very impressive and greatly appreciated.
I haven't examined the the PCSC-sharp in great detail but it's a cross-platform library built for netstandard2.0, changing target to net6.0/net6.0-maccatalyst changes nothing though. It's using DllImport and I'm definitely missing a few pieces when it comes to knowledge of the toolchain but...
Am I correct in assuming having .framework
in DllImport
causes the -framework
parameter?
Unfortunately I don't have any build logs for the successful build when using maui-preview14 bundle, but could the reason for it working in preview 14 (and possibly RC1) be that the -framework
parameter was not passed? The dynamic loading and native methods worked as expected.
I will reach out to danm-de, the owner of PCSC-sharp but I would be very grateful for any possible workarounds.
Relevant parts of PCSC-sharp: https://github.com/danm-de/pcsc-sharp/blob/7a0398f9221c91735150958d09ad83a5be47fe4d/src/PCSC/Interop/MacOSX/MacOsxNativeMethods.cs#L10
private const string PCSC_LIB = "PCSC.framework/PCSC";
[DllImport(PCSC_LIB)] internal static extern int SCardReleaseContext( [In] int hContext);
The PCSC library itself is dynamically loaded with:
if (_libHandle == IntPtr.Zero) { _libHandle = dlopen(PCSC_LIB, (int) DLOPEN_FLAGS.RTLD_LAZY);
Note: Referencing the full path, for example /System/Library/Frameworks/PCSC.framework/PCSC doesn't seem to make any difference, '/Applications/Xcode.app/Co....works//PCSC.framework/PCSC.tbd' is still referenced in the errorcode.
Am I correct in assuming having
.framework
inDllImport
causes the-framework
parameter?
Correct:
Linking with the framework PCSC because it's referenced by a module reference in PCSC.dll
I will reach out to danm-de, the owner of PCSC-sharp but I would be very grateful for any possible workarounds.
It looks like adding this to your csproj would work:
<Target Name="RemovePCSC" BeforeTargets="_ComputeLinkNativeExecutableInputs" AfterTargets="_LoadLinkerOutput">
<ItemGroup>
<_LinkerFrameworks Remove="PCSC" />
</ItemGroup>
</Target>
Sweeeeeeet success 🥳, it's working perfectly! Thank you very much for making my day @rolfbjarne
More info about LC_LINKER_OPTION: https://www.smileykeith.com/2022/02/23/lc-linker-option/
Hi. I used that workaround in my .NET 7 app. However after I updated in .NET 8 and trying to use that nugget, I am getting:
System.DllNotFoundException: PCSC.framework/PCSC at PCSC.Interop.MacOSX.PCSCliteMacOsX.EstablishContext(SCardScope dwScope, IntPtr pvReserved1, IntPtr pvReserved2, IntPtr& phContext)
Also I noticed that now the app builds even without this workaround:
`
`
@chosl are you getting the same issue?
@DesmondMilez I too have observed this.. but... I was behind on all version so in order to try .NET 8 I had to upgrade to macOS 14.1.1 and XCode 15.0.1. After getting System.DllNotFoundException: PCSC.framework/PCSC
in .NET 8 I first tried to lock the .NET version with global.json file and later uninstalling .NET 8 all together. Surprisingly, I still got the same error.
So this seems to happen even in .NET7 when compiled for debug under macOS 14.1.1.
As an additional test, I tested a previously compiled (under macOS 13 Microsoft hosted agent in Azure DevOps) and packaged version of our application. This packaged version works well under macOS 14.1.1, it is signed built as a universal app (arm64+x64) so there's also the possibility of arm64, x64 and signing in debug and release mode.
@rolfbjarne I've observed changes in CCID driver handling in macOS 14.0 and 14.1. Ludovic wrote a good post at https://blog.apdu.fr/posts/2023/11/apple-own-ccid-driver-in-sonoma/. Do you have some insight how or if this can be related to the loading of PCSC.framework/PCSC?
Have a great one!
@rolfbjarne I've observed changes in CCID driver handling in macOS 14.0 and 14.1. Ludovic wrote a good post at blog.apdu.fr/posts/2023/11/apple-own-ccid-driver-in-sonoma. Do you have some insight how or if this can be related to the loading of PCSC.framework/PCSC?
No idea whatsoever, but my guess is that it's unrelated. This bug report describes an issue entirely within the native linker (ld), what the code in the frameworks in question actually do is irrelevant.
When trying to use PCSC 6.0.0 nuget ( https://www.nuget.org/packages/PCSC/ https://github.com/danm-de/pcsc-sharp) in a MAUI MacCatalyst project build will fail with clang error 1. With Maui preview 14 it was possible to successfully build (with same project and same PCSC nuget version)
Steps to Reproduce
Expected Behavior
Successful build
Actual Behavior
Build fails in the linking stage
Environment
Version information
Visual Studio Enterprise 2022 for Mac Preview Version 17.3 Preview (17.3 build 191) Installation UUID: f7a2a130-2329-430a-8fcc-3d90486174aa Runtime .NET 6.0.3 (64-bit) Architecture: Arm64 Roslyn (Language Service) 4.2.0-3.22181.8+a59a22c6f3c2cc1883e20cece412209f18f4a29f NuGet Version: 6.0.0.262 .NET SDK (Arm64) SDK: /usr/local/share/dotnet/sdk/6.0.300/Sdks SDK Version: 6.0.300 MSBuild SDKs: /usr/local/share/dotnet/sdk/6.0.300/Sdks .NET SDK (x64) SDK Version: 3.1.419 .NET Runtime (Arm64) Runtime: /usr/local/share/dotnet/dotnet Runtime Version: 6.0.5 .NET Runtime (x64) Runtime: /usr/local/share/dotnet/x64/dotnet Runtime Versions: 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 5.0.17 5.0.16 5.0.15 5.0.14 5.0.13 3.1.25 3.1.24 3.1.23 3.1.22 Xamarin.Profiler Version: 1.8.0.19 Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler Updater Version: 11 Apple Developer Tools Xcode 13.4 (20503) Build 13F17a Xamarin.Mac Version: 8.10.0.1 (Visual Studio Enterprise) Hash: 568bdb24e Branch: d17-2 Build date: 2022-04-08 18:52:56-0400 Xamarin Designer Version: 17.3.0.70 Hash: 4cf1a2208 Branch: remotes/origin/d17-3 Build date: 2022-05-19 16:00:39 UTC Xamarin.iOS Version: 15.10.0.1 (Visual Studio Enterprise) Hash: 568bdb24e Branch: d17-2 Build date: 2022-04-08 18:52:57-0400 Xamarin.Android Version: 12.3.99.58 (Visual Studio Enterprise) Commit: xamarin-android/main/64b22fc Android SDK: /Users/olssonch/Library/Xamarin/android-sdk-macosx Supported Android versions: 12.0 (API level 31) 11.0 (API level 30) SDK Command-line Tools Version: 5.0 SDK Platform Tools Version: 31.0.3 SDK Build Tools Version: 30.0.3 Build Information: Mono: adf1bc4 Java.Interop: xamarin/java.interop/release/6.0.3xx@2a882d2d ProGuard: Guardsquare/proguard/v7.0.1@912d149 SQLite: xamarin/sqlite/3.38.2@7b1e016 Xamarin.Android Tools: xamarin/xamarin-android-tools/main@fc3c2ac Microsoft Build of OpenJDK Java SDK: /Library/Java/JavaVirtualMachines/microsoft-11.jdk 11.0.12 Android Designer EPL code available here: https://github.com/xamarin/AndroidDesigner.EPL Eclipse Temurin JDK Java SDK: /Library/Java/JavaVirtualMachines/temurin-8.jdk 1.8.0.302 Android Designer EPL code available here: https://github.com/xamarin/AndroidDesigner.EPL Android SDK Manager Version: 17.2.0.47 Hash: d6dd135 Branch: remotes/origin/dev/tondat/main-1512059~2 Build date: 2022-05-19 16:00:33 UTC Android Device Manager Version: 0.0.0.1127 Hash: 4bb4d48 Branch: remotes/origin/dev/tondat/main-1536295~1 Build date: 2022-05-19 16:00:33 UTC Build Information Release ID: 1703000191 Git revision: 6e028abf3763bf8fde618c0de2c24b1091eb76d8 Build date: 2022-05-19 15:58:40+00 Build branch: release-17.3 Build lane: release-17.3 Operating System Mac OS X 12.3.1 Darwin 21.4.0 Darwin Kernel Version 21.4.0 Fri Mar 18 00:46:32 PDT 2022 root:xnu-8020.101.4~15/RELEASE_ARM64_T6000 arm64Build Logs
msbuild.binlog.zip
Example Project (If Possible)
MauiPCSC.zip