Build problem: Failed to resolve "System.Diagnostics.PerformanceCounter"

KeithBoyntonKeithBoynton GBMember ✭✭

Build fails for my application when building for the AppStore target with the following error:
MMP : error MM2002: Failed to resolve "System.Diagnostics.PerformanceCounter" reference from "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

Obviously it's a linking problem, I'm wondering if something has changed in a recent update because this has been working fine up until this build and I haven't knowingly made any changes involving System.Diagnostics.

I've attached verbose build output and version info of my environment in the hope that someone can help.

Answers

  • KeithBoyntonKeithBoynton GBMember ✭✭

    I should probably add that the target framework is Xamarin.Mac Modern!

  • ChrisHamonsChrisHamons USXamarin Team Xamurai

    This is because Modern does not ship PerformanceCounter at all.

    Full:

    $ monop -r:/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/4.5/System.dll  | grep PerformanceCounter
    System.Diagnostics.PerformanceCounter
    System.Diagnostics.PerformanceCounterCategory
    System.Diagnostics.PerformanceCounterCategoryType
    System.Diagnostics.PerformanceCounterInstanceLifetime
    System.Diagnostics.PerformanceCounterManager
    System.Diagnostics.PerformanceCounterPermission
    System.Diagnostics.PerformanceCounterPermissionAccess
    System.Diagnostics.PerformanceCounterPermissionAttribute
    System.Diagnostics.PerformanceCounterPermissionEntry
    System.Diagnostics.PerformanceCounterPermissionEntryCollection
    System.Diagnostics.PerformanceCounterType
    System.Net.Configuration.PerformanceCountersElement
    

    Modern:

    $ monop -r:/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/lib/mono/Xamarin.Mac/System.dll  | grep PerformanceCounter
    $
    

    The linker, enabled in Release and AppStore in Modern, is letting you know that if you try to use it then you'll crash.

    You have a few options:

    • Disable the linker in that build configuration and hope you'll never hit that code.
    • Switch to Full from Modern
    • You could possibly hack in a stub PerformanceCounter that no-ops to stay on Modern, depending on how it is used in your (or libraries you depend upon).
  • KeithBoyntonKeithBoynton GBMember ✭✭

    Thanks @ChrisHamons for your timely reply.

    Disabling the linker I think from memory could introduce some AppStore delivery problems around the AVFoundation headers.
    Switching to Full while is the quickest, again I have a feeling there were problems with that and Modern is probably the best/recommended way forward if at all possible.
    Which leaves me thinking I should research your stub suggestion especially as I'm not aware it's actually being used.

    Could you point me to a resource where I could research how exactly I would go about stubbing PerformanceCounter so I can stay on Modern?

  • ChrisHamonsChrisHamons USXamarin Team Xamurai

    You can likely get away with Platform Linking (https://docs.microsoft.com/en-us/xamarin/mac/deploy-test/linker#platform-linking) if you swap to full.

    To be honest, I have no idea how you ended up in the state where a Modern application was able to even reference a library that depended on PerformanceCounter, so I can't try it locally but maybe you could add something like this:

    https://gist.github.com/chamons/8adf553f1c4daedfe990e97326bc5f09

    to your project, which is a skeleton definition of the type in the correct namespace. Depending on how the type is referenced, that might satisfy the linker.

    It's a pretty obscure/hacky idea, the better solution is to either fix the library in question or move to Full / platform linking but it might work.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Thank you @ChrisHamons I'm going to investigate based on that. I'd like to fix the library in question if possible so first I'll investigate if I can trace which is the offending library being referenced. What I find strange is that I haven't seen this before because I've not changed any library references over the last at least 5 releases to the AppStore and it's always built with SDK only linking successfully.

    Anyhow, it's a problem so I'll try to trace which referenced library is depending on PerformanceCounter and update my progress here in case the process helps anyone else.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Ok so here's where I've gotten to so far...

    1) Disabling the linker, while works ended up with the binary getting rejected on the grounds of "Your app links against the GameKit framework but does not appear to include Game Center functionality." - I forgot about that old chestnut.

    2) Switching to full, brought back an old log4net and XmlConfigurator issue that I remember having problems with before! I'd rather stay on Modern so didn't pursue that any further for now.

    3) I tried the skeleton definition type you kindly put on GitHub for me, thank you for that. It didn't work, there were some types in that skeleton there also couldn't be resolved. It seemed like it might have led me down a rabbit-hole and as you say it's an obscure/hacky idea anyway so that's on hold.

    4) I switched to linking everything (Link All) and did a --linkskip on all the assemblies apart from Xamarin.Mac. Interestingly that built successfully, seems to run just fine and a otool -L MyApp.app/Contents/MacOS/MyApp | grep GameKit gleaned nothing! So, for now I've submitted that binary to the AppStore and fingers crossed.

    I understand that's a workaround and not a fix. I was struggling to find a way to identify which assembly which causing the reference to PerformanceCounter but I'm guess my next steps could be to remove the --linkskip's one by one until the PerformanceCounter issue comes back and that could be (one of) the offending assemblies.

    Sound feasible/sensible or is there a better way to trace the offending assembly? I probably don't understand the MMP tool and process well enough. I haven't managed to get much info via. Google/StackOverflow yet but I will continue in the hope of a real fix.

  • ChrisHamonsChrisHamons USXamarin Team Xamurai

    Link skipping on all assemblies but Xamarin.Mac.dll would very likely work, and is pretty much equivalent to --linkplatform

    If I was debugging this issue and wanted to dig deeper, I'd take the "brute force" approach and just do

    monodis foo.dll > foo.dis

    on every one of your dependencies and search each disassembly for usages of PerformanceCounter. Depending on how many assemblies that is, you could write up a one liner like this:

    find . -name '*.dll' -exec monodis {} \; > ~/tmp/all.dis after cleaning your project (so you don't get duplicates from obj and bin).

    but the output may be very large and hang some text editors (vim handles super large files fine).

  • KeithBoyntonKeithBoynton GBMember ✭✭

    So, update....

    The submitted binary (using method 4 from my previous post) was accepted by Apple and I've had no reports of crashing on the Mac version.

    I've now done some further digging based on your recommendations and a monodis on all the dependencies gleaning nothing about PerformanceCounter. The closest I got to were the following lines from mscorlib.dll

    .field private static literal  string PerformanceCounterPermissionClass = "System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
    IL_00e6:  ldstr "System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
    

    So I tried removing the --linkskip on mscorlib expecting it to break and nope it didn't.

    Then I thought I'll try the next "brute force" and just remove each --linkskip one at a time until it breaks...

    Eventually I got to no --linkskips at all and it was still building with no errors.

    Then I tried to run it and I got an error about a missing constructor for log4net which I presume the linker took away because it's discovered by reflection or something along those lines at runtime. So I added a --linkskip for the log4net dll and it runs successfully.

    So then I thought hmm maybe it's not linking anything away so I compared the package size before removing the --linkskips and afterwards and before it's 10.1mb and with the skips removed it's 7.1mb

    Completely confused now!

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Hey @ChrisHamons not sure if you saw my post above, just wondering if you had any thoughts on it?

  • ChrisHamonsChrisHamons USXamarin Team Xamurai

    Your story has confused me somewhat. Without spending some time trying to reproduce it locally, I'm not sure I can wrap my mind around your exist issue.

    If you think it's a bug on our end, can you file an issue (https://github.com/xamarin/xamarin-macios/issues/new) with both steps to reproduce and describing what you expect/what you are seeing.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    Thanks @ChrisHamons confused me too!

  • marcolerma1312marcolerma1312 Member ✭✭

    @KeithBoynton
    Did you find any solution? I have the same problem.

  • KeithBoyntonKeithBoynton GBMember ✭✭

    @marcolerma1312 I didn't as yet, I haven't re-visited it since this thread. When I do I will be sure to update the thread. The workaround is still in place at the moment.

  • JamesClossJamesCloss GBMember ✭✭

    Same issue here on a build for iOS. Setting link options to 'Link All' fixes it but breaks other stuff for me so I can't use that solution.

    Can't find any reference to System.Performance.Diagnostics in any linked libraries - even imported the source only from said libraries and (eventually) rebuilt successfully. Same error. No reference to System.Performance.Diagnostics.

    Stub method didn't work.

    FWIW I'm trying to use the .net apis supplied by campaignmonitor.com.

  • rpdomingo_18rpdomingo_18 Member ✭✭
    edited September 17

    @JamesCloss Do you have a solution on this? I also face this issue. Thanks

  • JamesClossJamesCloss GBMember ✭✭

    @rpdomingo_18 Unfortunately not.

    I spent around half a day going down blind alleys - including building the libraries I was trying to import from source as I said. These libraries referenced no other third party stuff (other than Newtonsoft.Json which I use all the time) and there's definitely no reference to PerformanceMetrics in there yet, whatever I did, I still ran into that same issue.

    In the end I had to tell my client they couldn't do what they wanted to do within Xamarin.

    Maybe some from @XamarinHQ could comment?

    The only thing I could think of is that maybe that class is mistakenly linked from the mono build of one of the System namespaces that I don't normally use that was referenced from these libraries, that seems like a long shot though...

    System.Collections.Specialized;
    System.Globalization;
    System.Reflection;
    System.Net.Mail;

  • ChrisHamonsChrisHamons USXamarin Team Xamurai

    Without an actual sample project or binary or something the best I or anyone else could do is wildly guess here.

    Things I'd personally try:

    • For each assembly in your final bundle, monop --refs it for something that might contain System.Performance.Diagnostics
    • For each assembly in your final bundle, monodis and grep for PerformanceMetrics

    If you believe this is a bug, please consider filing it at https://github.com/xamarin/xamarin-macios/issues/new and provide an example project or binary, something to look at.

Sign In or Register to comment.