diff mbox series

[3/4] python_pep517.bbclass: always export _PYTHON_HOST_PLATFORM for wheel tag

Message ID 20260804220456.2342710-3-alhe@linux.microsoft.com
State Changes Requested
Headers show
Series [1/4] libtool: strip build system triplet from installed libtool script | expand

Commit Message

Alejandro Hernandez Aug. 4, 2026, 10:04 p.m. UTC
python distutils/sysconfig.get_platform() falls back to
distutils.util.get_platform() when the _PYTHON_HOST_PLATFORM
environment variable is unset, and returns the *build host* arch.
The result is baked into the produced wheel's filename
(pkg-<ver>-cp3XX-cp3XX-<PLAT>.whl) and its <pkg>.dist-info/WHEEL
metadata.

Without this export, extension-module wheels tag themselves with
whichever arch the autobuilder worker happens to have, which makes
the resulting rpm non-reproducible across mixed-arch autobuilder
pools.

Since python 3.14 + wheel >=0.44 also rejects wheels with an empty
platform tag ("Bad wheel filename"), the value has to be non-empty
in every class scope. HOST_ARCH is class-scoped by bitbake
(target/native/cross/nativesdk), so `linux-${HOST_ARCH}` covers
every case with a single unconditional assignment. Setting per-class
overrides to "" (as an earlier draft did) trips the wheel filename
check and must be avoided.

Pure-python wheels ignore _PYTHON_HOST_PLATFORM and remain tagged
"any", so this change only affects wheels that ship compiled
extensions (cffi, cryptography, numpy, bcrypt, markupsafe, psutil,
rpds-py, websockets, ...).

Assisted-by: AI - OpenAI
Signed-off-by: Alejandro Hernandez <alhe@linux.microsoft.com>
---
 meta/classes-recipe/python_pep517.bbclass | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Comments

Richard Purdie Aug. 6, 2026, 12:26 p.m. UTC | #1
On Tue, 2026-08-04 at 22:04 +0000, Alejandro Hernandez Samaniego via lists.openembedded.org wrote:
> python distutils/sysconfig.get_platform() falls back to
> distutils.util.get_platform() when the _PYTHON_HOST_PLATFORM
> environment variable is unset, and returns the *build host* arch.
> The result is baked into the produced wheel's filename
> (pkg-<ver>-cp3XX-cp3XX-<PLAT>.whl) and its <pkg>.dist-info/WHEEL
> metadata.
> 
> Without this export, extension-module wheels tag themselves with
> whichever arch the autobuilder worker happens to have, which makes
> the resulting rpm non-reproducible across mixed-arch autobuilder
> pools.
> 
> Since python 3.14 + wheel >=0.44 also rejects wheels with an empty
> platform tag ("Bad wheel filename"), the value has to be non-empty
> in every class scope. HOST_ARCH is class-scoped by bitbake
> (target/native/cross/nativesdk), so `linux-${HOST_ARCH}` covers
> every case with a single unconditional assignment. Setting per-class
> overrides to "" (as an earlier draft did) trips the wheel filename
> check and must be avoided.
> 
> Pure-python wheels ignore _PYTHON_HOST_PLATFORM and remain tagged
> "any", so this change only affects wheels that ship compiled
> extensions (cffi, cryptography, numpy, bcrypt, markupsafe, psutil,
> rpds-py, websockets, ...).
> 
> Assisted-by: AI - OpenAI
> Signed-off-by: Alejandro Hernandez <alhe@linux.microsoft.com>
> ---
>  meta/classes-recipe/python_pep517.bbclass | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/meta/classes-recipe/python_pep517.bbclass b/meta/classes-recipe/python_pep517.bbclass
> index d6246af5c2..06b23d3cba 100644
> --- a/meta/classes-recipe/python_pep517.bbclass
> +++ b/meta/classes-recipe/python_pep517.bbclass
> @@ -30,6 +30,22 @@ PEP517_INSTALL_PYTHON:class-native = "nativepython3"
>  # pypa/installer option to control the bytecode compilation
>  INSTALL_WHEEL_COMPILE_BYTECODE ?= "--compile-bytecode=0"
>  
> +# Force the wheel's platform tag to reflect the target machine rather than the
> +# build host. Without this, extension-module wheels bake the build host's arch
> +# (e.g. linux_x86_64) into <pkg>.dist-info/WHEEL via distutils/sysconfig's
> +# get_platform(), which breaks reproducibility across autobuilder workers of
> +# different architectures. Pure-python wheels ignore this variable and remain
> +# tagged "any".
> +#
> +# HOST_ARCH is class-scoped by bitbake:
> +#   - target:     HOST_ARCH == TARGET_ARCH (reproducible across workers)
> +#   - native:     HOST_ARCH == BUILD_ARCH  (matches worker arch, unpackaged)
> +#   - cross:      HOST_ARCH == BUILD_ARCH
> +#   - nativesdk:  HOST_ARCH == SDK_ARCH
> +# so a single expression covers every class without producing an empty tag
> +# (which python 3.14 + wheel >=0.44 rejects with "Bad wheel filename").
> +export _PYTHON_HOST_PLATFORM = "linux-${HOST_ARCH}"

The fix looks right, thanks!

I'm not sure we need the 10+ lines of explanation from AI ;-) The
commit message could be more concise too. We're seening way too much
text being added by AI in general and it will make the codebase harder
to understand in the long run :(.

Cheers,

Richard
Alejandro Hernandez Aug. 6, 2026, 3:51 p.m. UTC | #2
On 8/6/2026 6:26 AM, Richard Purdie via lists.openembedded.org wrote:
> On Tue, 2026-08-04 at 22:04 +0000, Alejandro Hernandez Samaniego via lists.openembedded.org wrote:
>> python distutils/sysconfig.get_platform() falls back to
>> distutils.util.get_platform() when the _PYTHON_HOST_PLATFORM
>> environment variable is unset, and returns the *build host* arch.
>> The result is baked into the produced wheel's filename
>> (pkg-<ver>-cp3XX-cp3XX-<PLAT>.whl) and its <pkg>.dist-info/WHEEL
>> metadata.
>>
>> Without this export, extension-module wheels tag themselves with
>> whichever arch the autobuilder worker happens to have, which makes
>> the resulting rpm non-reproducible across mixed-arch autobuilder
>> pools.
>>
>> Since python 3.14 + wheel >=0.44 also rejects wheels with an empty
>> platform tag ("Bad wheel filename"), the value has to be non-empty
>> in every class scope. HOST_ARCH is class-scoped by bitbake
>> (target/native/cross/nativesdk), so `linux-${HOST_ARCH}` covers
>> every case with a single unconditional assignment. Setting per-class
>> overrides to "" (as an earlier draft did) trips the wheel filename
>> check and must be avoided.
>>
>> Pure-python wheels ignore _PYTHON_HOST_PLATFORM and remain tagged
>> "any", so this change only affects wheels that ship compiled
>> extensions (cffi, cryptography, numpy, bcrypt, markupsafe, psutil,
>> rpds-py, websockets, ...).
>>
>> Assisted-by: AI - OpenAI
>> Signed-off-by: Alejandro Hernandez<alhe@linux.microsoft.com>
>> ---
>>   meta/classes-recipe/python_pep517.bbclass | 16 ++++++++++++++++
>>   1 file changed, 16 insertions(+)
>>
>> diff --git a/meta/classes-recipe/python_pep517.bbclass b/meta/classes-recipe/python_pep517.bbclass
>> index d6246af5c2..06b23d3cba 100644
>> --- a/meta/classes-recipe/python_pep517.bbclass
>> +++ b/meta/classes-recipe/python_pep517.bbclass
>> @@ -30,6 +30,22 @@ PEP517_INSTALL_PYTHON:class-native = "nativepython3"
>>   # pypa/installer option to control the bytecode compilation
>>   INSTALL_WHEEL_COMPILE_BYTECODE ?= "--compile-bytecode=0"
>>   
>> +# Force the wheel's platform tag to reflect the target machine rather than the
>> +# build host. Without this, extension-module wheels bake the build host's arch
>> +# (e.g. linux_x86_64) into <pkg>.dist-info/WHEEL via distutils/sysconfig's
>> +# get_platform(), which breaks reproducibility across autobuilder workers of
>> +# different architectures. Pure-python wheels ignore this variable and remain
>> +# tagged "any".
>> +#
>> +# HOST_ARCH is class-scoped by bitbake:
>> +#   - target:     HOST_ARCH == TARGET_ARCH (reproducible across workers)
>> +#   - native:     HOST_ARCH == BUILD_ARCH  (matches worker arch, unpackaged)
>> +#   - cross:      HOST_ARCH == BUILD_ARCH
>> +#   - nativesdk:  HOST_ARCH == SDK_ARCH
>> +# so a single expression covers every class without producing an empty tag
>> +# (which python 3.14 + wheel >=0.44 rejects with "Bad wheel filename").
>> +export _PYTHON_HOST_PLATFORM = "linux-${HOST_ARCH}"
> The fix looks right, thanks!
>
> I'm not sure we need the 10+ lines of explanation from AI ;-) The
> commit message could be more concise too. We're seening way too much
> text being added by AI in general and it will make the codebase harder
> to understand in the long run :(.
>
> Cheers,
>
> Richard

I agree, I can send a v2 or just keep it in mind for next time, let me know.

Cheers,
Alejandro

>
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#242937):https://lists.openembedded.org/g/openembedded-core/message/242937
> Mute This Topic:https://lists.openembedded.org/mt/120602086/4354175
> Group Owner:openembedded-core+owner@lists.openembedded.org
> Unsubscribe:https://lists.openembedded.org/g/openembedded-core/unsub [alhe@linux.microsoft.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Richard Purdie Aug. 6, 2026, 4:09 p.m. UTC | #3
On Thu, 2026-08-06 at 09:51 -0600, Alejandro Hernandez wrote:
>  
> 
> 
>  
> 
>  
> 
> On 8/6/2026 6:26 AM, Richard Purdie via lists.openembedded.org wrote:
>  
> 
>  
> 
> >  
> > 
> > On Tue, 2026-08-04 at 22:04 +0000, Alejandro Hernandez Samaniego via lists.openembedded.org wrote:
> >  
> > 
> > >  
> > > 
> > > python distutils/sysconfig.get_platform() falls back to
> > > distutils.util.get_platform() when the _PYTHON_HOST_PLATFORM
> > > environment variable is unset, and returns the *build host* arch.
> > > The result is baked into the produced wheel's filename
> > > (pkg-<ver>-cp3XX-cp3XX-<PLAT>.whl) and its <pkg>.dist-info/WHEEL
> > > metadata.
> > > 
> > > Without this export, extension-module wheels tag themselves with
> > > whichever arch the autobuilder worker happens to have, which makes
> > > the resulting rpm non-reproducible across mixed-arch autobuilder
> > > pools.
> > > 
> > > Since python 3.14 + wheel >=0.44 also rejects wheels with an empty
> > > platform tag ("Bad wheel filename"), the value has to be non-empty
> > > in every class scope. HOST_ARCH is class-scoped by bitbake
> > > (target/native/cross/nativesdk), so `linux-${HOST_ARCH}` covers
> > > every case with a single unconditional assignment. Setting per-class
> > > overrides to "" (as an earlier draft did) trips the wheel filename
> > > check and must be avoided.
> > > 
> > > Pure-python wheels ignore _PYTHON_HOST_PLATFORM and remain tagged
> > > "any", so this change only affects wheels that ship compiled
> > > extensions (cffi, cryptography, numpy, bcrypt, markupsafe, psutil,
> > > rpds-py, websockets, ...).
> > > 
> > > Assisted-by: AI - OpenAI
> > > Signed-off-by: Alejandro Hernandez <alhe@linux.microsoft.com>
> > > ---
> > >  meta/classes-recipe/python_pep517.bbclass | 16 ++++++++++++++++
> > >  1 file changed, 16 insertions(+)
> > > 
> > > diff --git a/meta/classes-recipe/python_pep517.bbclass b/meta/classes-recipe/python_pep517.bbclass
> > > index d6246af5c2..06b23d3cba 100644
> > > --- a/meta/classes-recipe/python_pep517.bbclass
> > > +++ b/meta/classes-recipe/python_pep517.bbclass
> > > @@ -30,6 +30,22 @@ PEP517_INSTALL_PYTHON:class-native = "nativepython3"
> > >  # pypa/installer option to control the bytecode compilation
> > >  INSTALL_WHEEL_COMPILE_BYTECODE ?= "--compile-bytecode=0"
> > >  
> > > +# Force the wheel's platform tag to reflect the target machine rather than the
> > > +# build host. Without this, extension-module wheels bake the build host's arch
> > > +# (e.g. linux_x86_64) into <pkg>.dist-info/WHEEL via distutils/sysconfig's
> > > +# get_platform(), which breaks reproducibility across autobuilder workers of
> > > +# different architectures. Pure-python wheels ignore this variable and remain
> > > +# tagged "any".
> > > +#
> > > +# HOST_ARCH is class-scoped by bitbake:
> > > +#   - target:     HOST_ARCH == TARGET_ARCH (reproducible across workers)
> > > +#   - native:     HOST_ARCH == BUILD_ARCH  (matches worker arch, unpackaged)
> > > +#   - cross:      HOST_ARCH == BUILD_ARCH
> > > +#   - nativesdk:  HOST_ARCH == SDK_ARCH
> > > +# so a single expression covers every class without producing an empty tag
> > > +# (which python 3.14 + wheel >=0.44 rejects with "Bad wheel filename").
> > > +export _PYTHON_HOST_PLATFORM = "linux-${HOST_ARCH}"
> > >  
> > > 
> >  
> > 
> > The fix looks right, thanks!
> > 
> > I'm not sure we need the 10+ lines of explanation from AI ;-) The
> > commit message could be more concise too. We're seening way too much
> > text being added by AI in general and it will make the codebase harder
> > to understand in the long run :(.
> > 
> > Cheers,
> > 
> > Richard
> >  
> > 
>  
> 
> I agree, I can send a v2 or just keep it in mind for next time, let me know.

v2 please, it is too verbose and I would have to manually trim it...

Cheers,

Richard
Alejandro Hernandez Aug. 6, 2026, 5:28 p.m. UTC | #4
On 8/6/2026 10:09 AM, Richard Purdie via lists.openembedded.org wrote:
> On Thu, 2026-08-06 at 09:51 -0600, Alejandro Hernandez wrote:
>>   
>>
>>
>>   
>>
>>   
>>
>> On 8/6/2026 6:26 AM, Richard Purdie via lists.openembedded.org wrote:
>>   
>>
>>   
>>
>>>   
>>>
>>> On Tue, 2026-08-04 at 22:04 +0000, Alejandro Hernandez Samaniego via lists.openembedded.org wrote:
>>>   
>>>
>>>>   
>>>>
>>>> python distutils/sysconfig.get_platform() falls back to
>>>> distutils.util.get_platform() when the _PYTHON_HOST_PLATFORM
>>>> environment variable is unset, and returns the *build host* arch.
>>>> The result is baked into the produced wheel's filename
>>>> (pkg-<ver>-cp3XX-cp3XX-<PLAT>.whl) and its <pkg>.dist-info/WHEEL
>>>> metadata.
>>>>
>>>> Without this export, extension-module wheels tag themselves with
>>>> whichever arch the autobuilder worker happens to have, which makes
>>>> the resulting rpm non-reproducible across mixed-arch autobuilder
>>>> pools.
>>>>
>>>> Since python 3.14 + wheel >=0.44 also rejects wheels with an empty
>>>> platform tag ("Bad wheel filename"), the value has to be non-empty
>>>> in every class scope. HOST_ARCH is class-scoped by bitbake
>>>> (target/native/cross/nativesdk), so `linux-${HOST_ARCH}` covers
>>>> every case with a single unconditional assignment. Setting per-class
>>>> overrides to "" (as an earlier draft did) trips the wheel filename
>>>> check and must be avoided.
>>>>
>>>> Pure-python wheels ignore _PYTHON_HOST_PLATFORM and remain tagged
>>>> "any", so this change only affects wheels that ship compiled
>>>> extensions (cffi, cryptography, numpy, bcrypt, markupsafe, psutil,
>>>> rpds-py, websockets, ...).
>>>>
>>>> Assisted-by: AI - OpenAI
>>>> Signed-off-by: Alejandro Hernandez<alhe@linux.microsoft.com>
>>>> ---
>>>>   meta/classes-recipe/python_pep517.bbclass | 16 ++++++++++++++++
>>>>   1 file changed, 16 insertions(+)
>>>>
>>>> diff --git a/meta/classes-recipe/python_pep517.bbclass b/meta/classes-recipe/python_pep517.bbclass
>>>> index d6246af5c2..06b23d3cba 100644
>>>> --- a/meta/classes-recipe/python_pep517.bbclass
>>>> +++ b/meta/classes-recipe/python_pep517.bbclass
>>>> @@ -30,6 +30,22 @@ PEP517_INSTALL_PYTHON:class-native = "nativepython3"
>>>>   # pypa/installer option to control the bytecode compilation
>>>>   INSTALL_WHEEL_COMPILE_BYTECODE ?= "--compile-bytecode=0"
>>>>   
>>>> +# Force the wheel's platform tag to reflect the target machine rather than the
>>>> +# build host. Without this, extension-module wheels bake the build host's arch
>>>> +# (e.g. linux_x86_64) into <pkg>.dist-info/WHEEL via distutils/sysconfig's
>>>> +# get_platform(), which breaks reproducibility across autobuilder workers of
>>>> +# different architectures. Pure-python wheels ignore this variable and remain
>>>> +# tagged "any".
>>>> +#
>>>> +# HOST_ARCH is class-scoped by bitbake:
>>>> +#   - target:     HOST_ARCH == TARGET_ARCH (reproducible across workers)
>>>> +#   - native:     HOST_ARCH == BUILD_ARCH  (matches worker arch, unpackaged)
>>>> +#   - cross:      HOST_ARCH == BUILD_ARCH
>>>> +#   - nativesdk:  HOST_ARCH == SDK_ARCH
>>>> +# so a single expression covers every class without producing an empty tag
>>>> +# (which python 3.14 + wheel >=0.44 rejects with "Bad wheel filename").
>>>> +export _PYTHON_HOST_PLATFORM = "linux-${HOST_ARCH}"
>>>>   
>>>>
>>>   
>>>
>>> The fix looks right, thanks!
>>>
>>> I'm not sure we need the 10+ lines of explanation from AI ;-) The
>>> commit message could be more concise too. We're seening way too much
>>> text being added by AI in general and it will make the codebase harder
>>> to understand in the long run :(.
>>>
>>> Cheers,
>>>
>>> Richard
>>>   
>>>
>>   
>>
>> I agree, I can send a v2 or just keep it in mind for next time, let me know.
> v2 please, it is too verbose and I would have to manually trim it...
>
> Cheers,
>
> Richard

Sent v2

Cheers!

>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#242955):https://lists.openembedded.org/g/openembedded-core/message/242955
> Mute This Topic:https://lists.openembedded.org/mt/120602086/4354175
> Group Owner:openembedded-core+owner@lists.openembedded.org
> Unsubscribe:https://lists.openembedded.org/g/openembedded-core/unsub [alhe@linux.microsoft.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
diff mbox series

Patch

diff --git a/meta/classes-recipe/python_pep517.bbclass b/meta/classes-recipe/python_pep517.bbclass
index d6246af5c2..06b23d3cba 100644
--- a/meta/classes-recipe/python_pep517.bbclass
+++ b/meta/classes-recipe/python_pep517.bbclass
@@ -30,6 +30,22 @@  PEP517_INSTALL_PYTHON:class-native = "nativepython3"
 # pypa/installer option to control the bytecode compilation
 INSTALL_WHEEL_COMPILE_BYTECODE ?= "--compile-bytecode=0"
 
+# Force the wheel's platform tag to reflect the target machine rather than the
+# build host. Without this, extension-module wheels bake the build host's arch
+# (e.g. linux_x86_64) into <pkg>.dist-info/WHEEL via distutils/sysconfig's
+# get_platform(), which breaks reproducibility across autobuilder workers of
+# different architectures. Pure-python wheels ignore this variable and remain
+# tagged "any".
+#
+# HOST_ARCH is class-scoped by bitbake:
+#   - target:     HOST_ARCH == TARGET_ARCH (reproducible across workers)
+#   - native:     HOST_ARCH == BUILD_ARCH  (matches worker arch, unpackaged)
+#   - cross:      HOST_ARCH == BUILD_ARCH
+#   - nativesdk:  HOST_ARCH == SDK_ARCH
+# so a single expression covers every class without producing an empty tag
+# (which python 3.14 + wheel >=0.44 rejects with "Bad wheel filename").
+export _PYTHON_HOST_PLATFORM = "linux-${HOST_ARCH}"
+
 # PEP517 doesn't have a specific configure step, so set an empty do_configure to avoid
 # running base_do_configure.
 python_pep517_do_configure () {