Skip to content

bpo-35920: Windows 10 ARM32 platform support #11774

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

Merged
merged 8 commits into from
Apr 25, 2019

Conversation

paulmon
Copy link
Contributor

@paulmon paulmon commented Feb 6, 2019

At a minimum this code needs to be refactored to take into account removing libffi_msvc and moving to the current libffi implementation based on #3806.

https://bugs.python.org/issue35920

@paulmon paulmon requested review from rhettinger, skrah and a team as code owners February 6, 2019 19:40
@the-knights-who-say-ni
Copy link

Hello, and thanks for your contribution!

I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed the PSF contributor agreement (CLA).

Unfortunately we couldn't find an account corresponding to your GitHub username on bugs.python.org (b.p.o) to verify you have signed the CLA (this might be simply due to a missing "GitHub Name" entry in your b.p.o account settings). This is necessary for legal reasons before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue.

You can check yourself to see if the CLA has been received.

Thanks again for your contribution, we look forward to reviewing it!

@@ -92,6 +94,23 @@ def get_platform ():

# get_platform ()

def get_target_platform ():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this needs to replace most uses of get_platform except when detecting whether we are cross-compiling, can we just update get_platform (and avoid all the renames above) and provide a new API for generating the tag?

On second reading, we probably aren't properly handling the --plat-name option in build_ext properly already, and that would be the better way to specify that "arm" is the target. It can select a default based on the environment variable, but it should also work when passed -p win-arm and going via the vcvarsall.bat path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_target_platform returns the target platform when cross-compiling.
get_platform returns the host platform.
ARM32 binaries can only be cross-compiled using the MSVC toolset.
Also when a module like numpy overrides the build files --target-plat doesn't get always passed through in the attributes like it should

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the docs, it already returns the target platform on macOS, as well as already being wrong for Windows ("non-POSIX platforms … return sys.platform"), so I think changing it on Windows to also return the distutils target is fine.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll start a post on python-dev to clarify and see what people think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the PR to use get_platform and get_host_platform. Testing is still needed

Lib/platform.py Outdated
return True
return False

def win32_editionId(editionId=''):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need documentation (Doc/library/platform.rst)

@zooba
Copy link
Member

zooba commented Feb 6, 2019

To help make the reviews simpler, I'm inclined to say it's okay to merge most of the .vcxproj and .vcxproj.filters changes immediately. Specifically, those that:

  • just add the platform/configuration values for ARM32
  • add conditions for ARM32 platform that don't impact Win32/x64 platforms
  • update the .filters files to match what's actually in there

Obviously the impactful ctypes and OpenSSL changes should not be included yet, and I mentioned a few things that I would like to see reverted, but most of the project changes are mechanical and otherwise unused unless explicitly enabled through build.bat -p ARM32 (which already works as that parameter just passes whatever value through).

@zware @skrah any thoughts?

@skrah
Copy link
Contributor

skrah commented Feb 6, 2019 via email

@paulmon
Copy link
Contributor Author

paulmon commented Feb 6, 2019

@skrah I was agreeing that your comment made sense.
MSVC uses armasm.exe to build ARM assembler files. There is no masm.exe for ARM32 so checking MASM when building for ARM32 wasn't seem obvious to me, but I understand now.
Thanks for the additional explanation.

@skrah
Copy link
Contributor

skrah commented Feb 6, 2019

@zooba I also think anything under PCBuild that is conditional on ARM32 is fine to merge. The files do get a bit in the way when reviewing.

@skrah
Copy link
Contributor

skrah commented Feb 6, 2019

@paulmon Yes, I should have used /DMASM_AND_INTRINSICS; I agree that the use of MASM is not really obvious, it really just sounds nicer and shortens the command line.

@nascheme
Copy link
Member

nascheme commented Feb 7, 2019

I didn't look at the mountains of XML-like stuff in PCBuild, looks like gobblygook to me. However, I briefly looked over the rest and it looks relatively sensible to me.

One style note, I generally don't like portability code like this:

@unittest.skipUnless(sys.platform == 'win32', 'these tests require Windows')
SKIP_MESSAGE = (None if sys.platform == 'win32' and not platform.win32_is_iot() else
                "These tests require Windows x86 or x64.  Windows IoT Core and nanoserver are not supported")

@unittest.skipUnless(SKIP_MESSAGE is None, SKIP_MESSAGE)
class BDistMSITestCase(support.TempdirManager,
                       support.LoggingSilencer,
                       unittest.TestCase):

You are testing for specific versions or platform identifiers, etc. It is better to test for "capabilities". I don't know where it would make sense to put the code (perhaps not in platform.py), but I think it would be clearer to define individual boolean flags for these things. So, the unit test code can do:

@unittest.skipUnless(platform_flags.have_win32_msi)
...

Where have_win32_msi is defined (probably not the correct name), you have have a substantial comment string that explains exactly what that flag means.

Maybe that's not too clear. Let me try to explain in another way. Say you have code throughout Python that works differently if the platform supports case-insensitive filenames. Rather than open code the test (e.g. "if plaform-x or platform-y or platform-z"), you define a global variable in one spot (e.g "have_case_insenstive_files = plaform-x or ..."). Then all the different places you need to check that, you just check that global.

@nascheme
Copy link
Member

nascheme commented Feb 7, 2019

If the boolean flags for indicating if the platform supports some feature are only used by tests, it looks like Lib/test/support/__init__py is the place for that. We have skip_unless_symlink(), for example. Most of these ARM32 platform skips could be done that way I think.

@paulmon
Copy link
Contributor Author

paulmon commented Feb 12, 2019

I'm working on a seperate PR for the PCBuild directory changes next so that we can separate the mechanical build changes from the code changes.

@paulmon paulmon force-pushed the win-arm32-proof-of-concept branch from d4bcb80 to 278b786 Compare February 14, 2019 18:39
@paulmon
Copy link
Contributor Author

paulmon commented Feb 14, 2019

This PR has been rebased on the merged PCBuild changes

@paulmon
Copy link
Contributor Author

paulmon commented Feb 14, 2019

I am currently working on refactoring the changes to ctypes for ARM to match #11797

g['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
# if cross-compiling replace hardcoded platform-specific EXT_SUFFIX
# with an EXT_SUFFIX that matches the target platform
if get_platform() == get_target_platform():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we change the definition of get_platform as per my post to python-dev, then to handle this I'd add a get_host_platform which is only used for this check.

@paulmon paulmon force-pushed the win-arm32-proof-of-concept branch 2 times, most recently from 766fd54 to 6daef76 Compare February 27, 2019 22:43
@paulmon paulmon force-pushed the win-arm32-proof-of-concept branch from 6f0d72b to 2c2d75e Compare April 12, 2019 23:58
@paulmon
Copy link
Contributor Author

paulmon commented Apr 13, 2019

Rebased on master and cleaned up.
Most of the changes from the original PR have been refactored into seperate PRs.
These remaining changes should be refactored into mergable PRs, the current state of this PR is not mergable.

@zooba
Copy link
Member

zooba commented Apr 22, 2019

Also, please try to avoid force pushing changes - it's much easier to review new commits. We'll squash merge at the end, so the history will disappear anyway.

@paulmon
Copy link
Contributor Author

paulmon commented Apr 22, 2019

Sorry, I'll try to avoid force-pushing.

It was getting hard to merge these changes with the other arm changes for testing purposes because of the long list of commits here. There were a lot of conflicts because the other commits were lifted out of this one.


if targetPlatformFromEnvironment != None and targetPlatformFromEnvironment in TARGET_TO_PLAT:
targetPlatform = TARGET_TO_PLAT[targetPlatformFromEnvironment]
if os.name == 'nt':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's only define TARGET_TO_PLAT for Windows as well. Even though it's static, it still gets constructed on each call and it doesn't have any meaning on other OS's.

@zooba
Copy link
Member

zooba commented Apr 22, 2019

Force pushing to reset when you've done a big refactor or rebase is fine, since re-reviewing from the start is probably necessary. But for fix-ups we get a "view changes since last review" button when you just add new commits, which makes things much easier on our side.

If there isn't already a NEWS file for bpo-35920, please add one, and hopefully the macOS failure is transient and the rebuild will succeed. If so, I think this is ready to merge.

@paulmon paulmon changed the title bpo-35920: CPython for Windows ARM32 proof of concept bpo-35920: Windows 10 ARM32 platform support Apr 22, 2019
@@ -38,7 +38,7 @@ def get_host_platform():
if os.name == 'nt':
if 'amd64' in sys.version.lower():
return 'win-amd64'
if 'arm32' in sys.version.lower():
if 'arm' in sys.version.lower():
Copy link
Contributor Author

@paulmon paulmon Apr 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sys.version() returns ARM not arm32

sys.version
'3.8.0a3+ (heads/test:5145ef5d65, Apr 19 2019, 14:58:01) [MSC v.1916 32 bit (ARM)]'

@zooba
Copy link
Member

zooba commented Apr 23, 2019

@paulmon It looks like the macOS build issue is a real issue - circular dependency within distutils

Traceback (most recent call last):
  File "./setup.py", line 14, in <module>
    from distutils.command.build_ext import build_ext
  File "/Users/vsts/agent/2.150.0/work/1/s/Lib/distutils/command/build_ext.py", line 11, in <module>
    from distutils.core import Command
  File "/Users/vsts/agent/2.150.0/work/1/s/Lib/distutils/core.py", line 16, in <module>
    from distutils.dist import Distribution
  File "/Users/vsts/agent/2.150.0/work/1/s/Lib/distutils/dist.py", line 19, in <module>
    from distutils.util import check_environ, strtobool, rfc822_escape
  File "/Users/vsts/agent/2.150.0/work/1/s/Lib/distutils/util.py", line 14, in <module>
    from distutils.spawn import spawn
  File "/Users/vsts/agent/2.150.0/work/1/s/Lib/distutils/spawn.py", line 84, in <module>
    from distutils import sysconfig
  File "/Users/vsts/agent/2.150.0/work/1/s/Lib/distutils/sysconfig.py", line 18, in <module>
    from .util import get_platform, get_host_platform
ImportError: cannot import name 'get_platform' from 'distutils.util' (/Users/vsts/agent/2.150.0/work/1/s/Lib/distutils/util.py)

Probably best to move the from distutils import sysconfig line in spawn.py into the _spawn_posix function right before it's used.

@paulmon
Copy link
Contributor Author

paulmon commented Apr 24, 2019

That line is spawn.py hasn't changed in a long time.

I think the problem is sysconfig.py line 18. I can't see a reason for the "from .util import get_platform, get_host_platform" to be there, it looks like it might an incomplete refactoring.

I've removed it and I'm doing some testing to make sure the standard tests still pass on PC and ARM.

@zooba
Copy link
Member

zooba commented Apr 24, 2019

I think the problem is sysconfig.py line 18. I can't see a reason for the "from .util import get_platform, get_host_platform" to be there, it looks like it might an incomplete refactoring.

I'd worry that get_platform may be being used as distutils.sysconfig.get_platform, especially since the original sysconfig module has get_platform as well. Changing spawn.py will have a smaller impact on users.

@paulmon
Copy link
Contributor Author

paulmon commented Apr 24, 2019

Is the Azure pipelines PR build missing now? I think that's where the MacOS failure was showing up.

@zooba
Copy link
Member

zooba commented Apr 24, 2019

Hmm... guess the webhook got lost? Close/reopen is normally the best way. I'll do it.

@zooba zooba closed this Apr 24, 2019
@zooba zooba reopened this Apr 24, 2019
@paulmon paulmon closed this Apr 24, 2019
@paulmon paulmon reopened this Apr 24, 2019
@paulmon
Copy link
Contributor Author

paulmon commented Apr 24, 2019

Waited an hour and tried again. Stills seems like the webhook is missing

@zooba
Copy link
Member

zooba commented Apr 24, 2019

I started a build manually at https://dev.azure.com/python/cpython/_build/results?buildId=41266

Other PRs seem to be working, so not sure what's going on here.

@paulmon
Copy link
Contributor Author

paulmon commented Apr 24, 2019

Thanks. It looks like all of the builds passed now, including macOS.

@zooba zooba merged commit 62dfd7d into python:master Apr 25, 2019
@zooba
Copy link
Member

zooba commented Apr 25, 2019

Indeed. Congrats!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants