-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix to find dotnet root using architecture name #41
Fix to find dotnet root using architecture name #41
Conversation
LeeDongGeon1996
commented
Nov 11, 2022
- Fix to find dotnet root using architecture name
- Fixes Could not find a suitable hostfxr library #40
This removes the detection of 32bit binaries, though, is that intended? |
Actually, it seems that we don't need that part because dotnet does not have any separate installer for 32bits.🤯 |
I have a concern about this. This Pull Request updates the logic to: elif sys.platform == "darwin":
if "ARM" in platform.machine().upper():
dotnet_root = Path("/usr/local/share/dotnet")
else:
dotnet_root = Path("/usr/local/share/dotnet/x64") However on my Intel based mac, the .NET runtimes are installed to: /usr/local/share/dotnet/ |
@DareDevilDenis Can you let me know which dotnet version you are using?
|
@LeeDongGeon1996, I'm using .NET runtime 6.0.3. The following page: https://learn.microsoft.com/en-us/dotnet/core/install/macos says:
So it looks like the folder is:
|
@DareDevilDenis Sorry, but I don't think so. In my understanding, it's saying that x64 SDK has its own folder named with Please have a look at the next section, you mentioned |
Hi @LeeDongGeon1996. I politely disagree. In https://learn.microsoft.com/en-us/dotnet/core/install/macos, the sections "Path differences" and "Path conflicts" are under the section "Arm-based Macs" where it says "The following sections describe things you should consider when installing .NET on an Arm-based Mac." So for .NET 6 onwards I still think that my statement above is true:
For .NET prior to version 6, I think the path is always /usr/local/share/dotnet/ I have just tested this on an Intel mac and an Arm mac, and I can confirm that the above paths are correct. |
@DareDevilDenis Ah, thank you for correcting. I'll change the code, applying the path you figured out. |
Hi, @DareDevilDenis . I have a question. Do we need to detect x64 SDK on ARM machine? I mean does it work on ARM machine even if it can be installed? |
Hi @LeeDongGeon1996. Sorry for the delay. I will check this and let you know. |
Hi @LeeDongGeon1996. I ran the following tests on an Arm based mac, with x64 .NET runtime v6.0.11 (not Arm64):
Both tests worked fine. Maybe the logic in find_dotnet_root, under 'elif sys.platform == "darwin":' should be:
|
I'm ready to merge and release whatever you two decide, I just can't test it myself ;) |
Hi @LeeDongGeon1996, you could use the following: elif sys.platform == "darwin":
dotnet_root = Path("/usr/local/share/dotnet")
# Special case when 'Intel-only' Python is running on an Arm based mac.
if 'ARM' not in platform.machine().upper():
result = subprocess.run(['sysctl', '-n', 'machdep.cpu.brand_string'], stdout=subprocess.PIPE, text=True)
if 'Apple' in result.stdout:
dotnet_root = Path("/usr/local/share/dotnet/x64") Running the 'sysctl' command as a subprocess is not very elegant but I couldn't find a nice built-in Python function to determine if this is an Arm based mac. I tried the following. As you can see, the results on an Intel mac were the same as for the Intel version of Python on an M1 mac:
The 'sysctl' command returns what we need:
If anyone can think of a cleaner way to determine if this is Intel based Python running on an Arm mac please shout. https://www.youtube.com/watch?v=_uzZ5vD4uNw The main issue with the current clr-loader v0.2.4, using 'universal2' Python installation is that if the user has both x64 .NET and Arm64 .NET installed it will fail with exception This is because the code gets the wrong path '/usr/local/share/dotnet/x64': elif sys.platform == "darwin":
if sys.maxsize > 2**32: # is_64bits
dotnet_root = Path("/usr/local/share/dotnet/x64")
else:
dotnet_root = Path("/usr/local/share/dotnet") If the user only has Arm64 .NET installed it will work because, even though it gets the wrong path '/usr/local/share/dotnet/x64' if dotnet_root is not None and dotnet_root.is_dir():
return dotnet_root
# Try to discover dotnet from PATH otherwise
dotnet_cli = find_dotnet_cli() |
Hi, @DareDevilDenis . Sorry for late. I have thought about applying your amazing workaround and no doubt that it's the most precise way to find dotnet root. But I think it is too much, so how about this way (c29d3af)? |
Hi @LeeDongGeon1996 I’m not sure how important this limitation is though. Python 3.9 was the last version that had an ‘Intel only’ installer. From Python 3.10 it’s a ‘universal2’ installer which will work fine with your solution. |
@DareDevilDenis Thank you for the answer. If Intel-only Python users persist to keep both .Net versions, they can explicitly select dotnet root by passing |
Hi @LeeDongGeon1996 |
Hi, @filmor . If you're okay, we'd like to merge this PR. Before that, Could you check why test failed? |
I'm not quite sure I follow the latest simplification. Depending on the .NET 6 structure is fine by me, but I don't want to have people knocking here (and in particular on Python.NET) over and over because their x64-Python fails to load .NET on their Apple Silicon install. In summary:
elif sys.platform == "darwin":
if "ARM64" in os.uname().version:
# Apple Silicon
if platform.machine() == 'x86_64':
# Running in Rosetta 2 mode
dotnet_root = Path("/usr/local/share/dotnet/x64")
else:
dotnet_root = Path("/usr/local/share/dotnet")
else:
# Intel Silicon
if sys.maxsize > 2**32: # is_64bits
dotnet_root = Path("/usr/local/share/dotnet/x64")
else:
dotnet_root = Path("/usr/local/share/dotnet") What do you say, does this work? |
@filmor, I can try your code in a few days (I don't have access to a mac at the moment as I'm on holiday). I did notice that https://docs.python.org/3/library/os.html#os.uname says "Availability: Unix" so I'm not sure if it works on macOS. |
@filmor, in the code in your last comment, and in clr-loader 0.2.4, I don't think the following logic is correct: if sys.maxsize > 2**32: # is_64bits
dotnet_root = Path("/usr/local/share/dotnet/x64")
else:
dotnet_root = Path("/usr/local/share/dotnet") For macOS .NET 6.0 onwards is only available in x64 and Arm64 versions. Previous to .NET 6 it's only available in x64. As far as I can see there is no 32 bit 'x86' version of .NET for macOS. As we've discussed above, on macOS, .NET gets installed to: .NET 6 onwards:
Before .NET 6:
On a 64 bit Python installation, the ' if dotnet_root is not None and dotnet_root.is_dir():
return dotnet_root
# Try to discover dotnet from PATH otherwise
dotnet_cli = find_dotnet_cli() So I don't think we need the ' |
Okay, then I'd suggest: elif sys.platform == "darwin":
if "ARM64" in os.uname().version and platform.machine() == 'x86_64':
# Apple Silicon in Rosetta 2 mode
dotnet_root = Path("/usr/local/share/dotnet/x64")
else:
dotnet_root = Path("/usr/local/share/dotnet") This should work in all cases you listed, right? |
Yes, I think that will be perfect :) I tried |
@filmor, I tried on an M1 mac and got the expected output from
So your logic is good 😀 One small suggestion: I think that we should switch the clauses in the if "ARM64" in os.uname().version and platform.machine() == 'x86_64': To: if platform.machine() == 'x86_64' and "ARM64" in os.uname().version: The reason is that since Apple have moved to using their own silicon that will soon become the processor used on most mac machines. Our |
Superceded by #45, thank you both for your efforts :) |