diff mbox series

[2/2] sstate.bbclass: fix cleanup when sysroot in manifest != RECIPE_SYSROOT

Message ID 20230227154230.3566400-2-ovidiu.panait@eng.windriver.com
State New
Headers show
Series [1/2] sstate.bbclass: factor out manifest cleanup code from sstate_clean_manifest() | expand

Commit Message

Ovidiu Panait Feb. 27, 2023, 3:42 p.m. UTC
The following scenario currently fails:
git clone git://git.yoctoproject.org/poky
cd poky; . oe-init-build-env

add to local.conf:
require conf/multilib.conf
MACHINE = "qemuarm64"
MULTILIBS = "multilib:lib32"
DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"

bitbake gcc-cross-canadian-arm

update local.conf to force a rebuild:
GCCPIE = "--disable-default-pie"

bitbake gcc-cross-canadian-arm

Failure log:
The stack trace of python calls that resulted in this exception/failure was:
File: 'exec_func_python() autogenerated', lineno: 2, function: <module>
     0001:
 *** 0002:extend_recipe_sysroot(d)
     0003:
File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: staging_copyfile
     0160:        os.symlink(linkto, dest)
     0161:        #bb.warn(c)
     0162:    else:
     0163:        try:
 *** 0164:            os.link(c, dest)
     0165:        except OSError as err:
     0166:            if err.errno == errno.EXDEV:
     0167:                bb.utils.copyfile(c, dest)
     0168:            else:
Exception: FileExistsError: [Errno 17] File exists: 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' -> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'

In this particular case, the paths in lib32-linux-libc-headers manifest file
are prefixed with lib32-recipe-sysroot:
$ cat build/tmp/sysroots-components/manifests/lib32-linux-libc-headers.xxx
lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
...

When gcc-cross-canadian-arm is built, the actual files get copied to
recipe-sysroot directory during do_prepare_recipe_sysroot().

Because of this mismatch, on rebuild, sstate_clean_manifest() will not clean
the files in recipe-sysroot, but will instead try to delete the non-existent
files in lib32-recipe-sysroot. This will trigger the FileExists errors later.

Add checks in sstate_clean_manifest() for this corner case, so that
RECIPE_SYSROOT gets cleaned up properly.

This fixes BZ#15045.

Signed-off-by: Ovidiu Panait <ovidiu.panait@eng.windriver.com>
---
 meta/classes-global/sstate.bbclass | 11 +++++++++++
 1 file changed, 11 insertions(+)

Comments

Richard Purdie Feb. 27, 2023, 3:56 p.m. UTC | #1
On Mon, 2023-02-27 at 17:42 +0200, Ovidiu Panait wrote:
> The following scenario currently fails:
> git clone git://git.yoctoproject.org/poky
> cd poky; . oe-init-build-env
> 
> add to local.conf:
> require conf/multilib.conf
> MACHINE = "qemuarm64"
> MULTILIBS = "multilib:lib32"
> DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"
> 
> bitbake gcc-cross-canadian-arm
> 
> update local.conf to force a rebuild:
> GCCPIE = "--disable-default-pie"
> 
> bitbake gcc-cross-canadian-arm
> 
> Failure log:
> The stack trace of python calls that resulted in this exception/failure was:
> File: 'exec_func_python() autogenerated', lineno: 2, function: <module>
>      0001:
>  *** 0002:extend_recipe_sysroot(d)
>      0003:
> File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: staging_copyfile
>      0160:        os.symlink(linkto, dest)
>      0161:        #bb.warn(c)
>      0162:    else:
>      0163:        try:
>  *** 0164:            os.link(c, dest)
>      0165:        except OSError as err:
>      0166:            if err.errno == errno.EXDEV:
>      0167:                bb.utils.copyfile(c, dest)
>      0168:            else:
> Exception: FileExistsError: [Errno 17] File exists: 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' -> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'
> 
> In this particular case, the paths in lib32-linux-libc-headers manifest file
> are prefixed with lib32-recipe-sysroot:
> $ cat build/tmp/sysroots-components/manifests/lib32-linux-libc-headers.xxx
> lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
> lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
> ...
> 
> When gcc-cross-canadian-arm is built, the actual files get copied to
> recipe-sysroot directory during do_prepare_recipe_sysroot().
> 
> Because of this mismatch, on rebuild, sstate_clean_manifest() will not clean
> the files in recipe-sysroot, but will instead try to delete the non-existent
> files in lib32-recipe-sysroot. This will trigger the FileExists errors later.
> 
> Add checks in sstate_clean_manifest() for this corner case, so that
> RECIPE_SYSROOT gets cleaned up properly.
> 
> This fixes BZ#15045.
> 
> Signed-off-by: Ovidiu Panait <ovidiu.panait@eng.windriver.com>
> ---
>  meta/classes-global/sstate.bbclass | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
> index af93546b04..edf5c7fb65 100644
> --- a/meta/classes-global/sstate.bbclass
> +++ b/meta/classes-global/sstate.bbclass
> @@ -529,9 +529,20 @@ def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
>      entries = mfile.readlines()
>      mfile.close()
>  
> +    recipe_sysroot = d.getVar("RECIPE_SYSROOT").rstrip("/").rsplit('/', 1)[-1]
> +
>      for entry in entries:
>          sstate_clean_entry(entry, canrace, prefix)
>  
> +        # The sysroot directory stored in the manifest file might not be the
> +        # same as RECIPE_SYSROOT, so the real sysroot will not be properly
> +        # cleaned up on rebuild. Handle the cleanup here in order to avoid
> +        # "File exists" errors during do_prepare_recipe_sysroot().
> +        manifest_sysroot = entry.split("/", 1)[0] or None
> +        if manifest_sysroot and manifest_sysroot != recipe_sysroot and not manifest_sysroot.endswith("-native"):
> +            sysroot_entry = recipe_sysroot + "/" + entry.split("/", 1)[1]
> +            sstate_clean_entry(sysroot_entry, canrace, prefix)
> +
>      postrm = manifest + ".postrm"
>      if os.path.exists(manifest + ".postrm"):
>          import subprocess

How many recipe-sysroots are there for gcc-cross-canadian-arm ? This
feels like a workaround for some other issue which should probably be
fixed properly instead?

Cheers,

Richard
Ovidiu Panait Feb. 27, 2023, 5:17 p.m. UTC | #2
Hi Richard,

On 2/27/23 17:56, Richard Purdie wrote:
> CAUTION: This email comes from a non Wind River email account!
> Do not click links or open attachments unless you recognize the sender and know the content is safe.
>
> On Mon, 2023-02-27 at 17:42 +0200, Ovidiu Panait wrote:
>> The following scenario currently fails:
>> git clone git://git.yoctoproject.org/poky
>> cd poky; . oe-init-build-env
>>
>> add to local.conf:
>> require conf/multilib.conf
>> MACHINE = "qemuarm64"
>> MULTILIBS = "multilib:lib32"
>> DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"
>>
>> bitbake gcc-cross-canadian-arm
>>
>> update local.conf to force a rebuild:
>> GCCPIE = "--disable-default-pie"
>>
>> bitbake gcc-cross-canadian-arm
>>
>> Failure log:
>> The stack trace of python calls that resulted in this exception/failure was:
>> File: 'exec_func_python() autogenerated', lineno: 2, function: <module>
>>       0001:
>>   *** 0002:extend_recipe_sysroot(d)
>>       0003:
>> File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: staging_copyfile
>>       0160:        os.symlink(linkto, dest)
>>       0161:        #bb.warn(c)
>>       0162:    else:
>>       0163:        try:
>>   *** 0164:            os.link(c, dest)
>>       0165:        except OSError as err:
>>       0166:            if err.errno == errno.EXDEV:
>>       0167:                bb.utils.copyfile(c, dest)
>>       0168:            else:
>> Exception: FileExistsError: [Errno 17] File exists: 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' -> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'
>>
>> In this particular case, the paths in lib32-linux-libc-headers manifest file
>> are prefixed with lib32-recipe-sysroot:
>> $ cat build/tmp/sysroots-components/manifests/lib32-linux-libc-headers.xxx
>> lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
>> lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
>> ...
>>
>> When gcc-cross-canadian-arm is built, the actual files get copied to
>> recipe-sysroot directory during do_prepare_recipe_sysroot().
>>
>> Because of this mismatch, on rebuild, sstate_clean_manifest() will not clean
>> the files in recipe-sysroot, but will instead try to delete the non-existent
>> files in lib32-recipe-sysroot. This will trigger the FileExists errors later.
>>
>> Add checks in sstate_clean_manifest() for this corner case, so that
>> RECIPE_SYSROOT gets cleaned up properly.
>>
>> This fixes BZ#15045.
>>
>> Signed-off-by: Ovidiu Panait <ovidiu.panait@eng.windriver.com>
>> ---
>>   meta/classes-global/sstate.bbclass | 11 +++++++++++
>>   1 file changed, 11 insertions(+)
>>
>> diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
>> index af93546b04..edf5c7fb65 100644
>> --- a/meta/classes-global/sstate.bbclass
>> +++ b/meta/classes-global/sstate.bbclass
>> @@ -529,9 +529,20 @@ def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
>>       entries = mfile.readlines()
>>       mfile.close()
>>
>> +    recipe_sysroot = d.getVar("RECIPE_SYSROOT").rstrip("/").rsplit('/', 1)[-1]
>> +
>>       for entry in entries:
>>           sstate_clean_entry(entry, canrace, prefix)
>>
>> +        # The sysroot directory stored in the manifest file might not be the
>> +        # same as RECIPE_SYSROOT, so the real sysroot will not be properly
>> +        # cleaned up on rebuild. Handle the cleanup here in order to avoid
>> +        # "File exists" errors during do_prepare_recipe_sysroot().
>> +        manifest_sysroot = entry.split("/", 1)[0] or None
>> +        if manifest_sysroot and manifest_sysroot != recipe_sysroot and not manifest_sysroot.endswith("-native"):
>> +            sysroot_entry = recipe_sysroot + "/" + entry.split("/", 1)[1]
>> +            sstate_clean_entry(sysroot_entry, canrace, prefix)
>> +
>>       postrm = manifest + ".postrm"
>>       if os.path.exists(manifest + ".postrm"):
>>           import subprocess
> How many recipe-sysroots are there for gcc-cross-canadian-arm ? This
> feels like a workaround for some other issue which should probably be
> fixed properly instead?
(resending, as the first reply didn't actually made it to the list)

There are "recipe-sysroot" and "recipe-sysroot-native" sysroots in 
gcc-cross-canadian-arm WORKDIR, but no lib32-recipe-sysroot.


Ovidiu
> Cheers,
>
> Richard
>
>
Richard Purdie March 6, 2023, 5:59 p.m. UTC | #3
On Mon, 2023-02-27 at 17:42 +0200, Ovidiu Panait wrote:
> The following scenario currently fails:
> git clone git://git.yoctoproject.org/poky
> cd poky; . oe-init-build-env
> 
> add to local.conf:
> require conf/multilib.conf
> MACHINE = "qemuarm64"
> MULTILIBS = "multilib:lib32"
> DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"
> 
> bitbake gcc-cross-canadian-arm
> 
> update local.conf to force a rebuild:
> GCCPIE = "--disable-default-pie"
> 
> bitbake gcc-cross-canadian-arm
> 
> Failure log:
> The stack trace of python calls that resulted in this exception/failure was:
> File: 'exec_func_python() autogenerated', lineno: 2, function: <module>
>      0001:
>  *** 0002:extend_recipe_sysroot(d)
>      0003:
> File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: staging_copyfile
>      0160:        os.symlink(linkto, dest)
>      0161:        #bb.warn(c)
>      0162:    else:
>      0163:        try:
>  *** 0164:            os.link(c, dest)
>      0165:        except OSError as err:
>      0166:            if err.errno == errno.EXDEV:
>      0167:                bb.utils.copyfile(c, dest)
>      0168:            else:
> Exception: FileExistsError: [Errno 17] File exists: 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' -> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'
> 
> In this particular case, the paths in lib32-linux-libc-headers manifest file
> are prefixed with lib32-recipe-sysroot:
> $ cat build/tmp/sysroots-components/manifests/lib32-linux-libc-headers.xxx
> lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
> lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
> ...
> 
> When gcc-cross-canadian-arm is built, the actual files get copied to
> recipe-sysroot directory during do_prepare_recipe_sysroot().
> 
> Because of this mismatch, on rebuild, sstate_clean_manifest() will not clean
> the files in recipe-sysroot, but will instead try to delete the non-existent
> files in lib32-recipe-sysroot. This will trigger the FileExists errors later.
> 
> Add checks in sstate_clean_manifest() for this corner case, so that
> RECIPE_SYSROOT gets cleaned up properly.
> 
> This fixes BZ#15045.
> 
> Signed-off-by: Ovidiu Panait <ovidiu.panait@eng.windriver.com>
> ---
>  meta/classes-global/sstate.bbclass | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
> index af93546b04..edf5c7fb65 100644
> --- a/meta/classes-global/sstate.bbclass
> +++ b/meta/classes-global/sstate.bbclass
> @@ -529,9 +529,20 @@ def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
>      entries = mfile.readlines()
>      mfile.close()
>  
> +    recipe_sysroot = d.getVar("RECIPE_SYSROOT").rstrip("/").rsplit('/', 1)[-1]
> +
>      for entry in entries:
>          sstate_clean_entry(entry, canrace, prefix)
>  
> +        # The sysroot directory stored in the manifest file might not be the
> +        # same as RECIPE_SYSROOT, so the real sysroot will not be properly
> +        # cleaned up on rebuild. Handle the cleanup here in order to avoid
> +        # "File exists" errors during do_prepare_recipe_sysroot().
> +        manifest_sysroot = entry.split("/", 1)[0] or None
> +        if manifest_sysroot and manifest_sysroot != recipe_sysroot and not manifest_sysroot.endswith("-native"):
> +            sysroot_entry = recipe_sysroot + "/" + entry.split("/", 1)[1]
> +            sstate_clean_entry(sysroot_entry, canrace, prefix)
> +
>      postrm = manifest + ".postrm"
>      if os.path.exists(manifest + ".postrm"):
>          import subprocess

I looked into this and as I suspected, the bug is elsewhere. I've sent
a different patch to the staging.bbclass code which should fix this
problem.

Cheers,

Richard
Ovidiu Panait March 7, 2023, 7:04 p.m. UTC | #4
Hi Richard,

On 3/6/23 19:59, Richard Purdie wrote:
> CAUTION: This email comes from a non Wind River email account!
> Do not click links or open attachments unless you recognize the sender and know the content is safe.
>
> On Mon, 2023-02-27 at 17:42 +0200, Ovidiu Panait wrote:
>> The following scenario currently fails:
>> git clone git://git.yoctoproject.org/poky
>> cd poky; . oe-init-build-env
>>
>> add to local.conf:
>> require conf/multilib.conf
>> MACHINE = "qemuarm64"
>> MULTILIBS = "multilib:lib32"
>> DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"
>>
>> bitbake gcc-cross-canadian-arm
>>
>> update local.conf to force a rebuild:
>> GCCPIE = "--disable-default-pie"
>>
>> bitbake gcc-cross-canadian-arm
>>
>> Failure log:
>> The stack trace of python calls that resulted in this exception/failure was:
>> File: 'exec_func_python() autogenerated', lineno: 2, function: <module>
>>       0001:
>>   *** 0002:extend_recipe_sysroot(d)
>>       0003:
>> File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: staging_copyfile
>>       0160:        os.symlink(linkto, dest)
>>       0161:        #bb.warn(c)
>>       0162:    else:
>>       0163:        try:
>>   *** 0164:            os.link(c, dest)
>>       0165:        except OSError as err:
>>       0166:            if err.errno == errno.EXDEV:
>>       0167:                bb.utils.copyfile(c, dest)
>>       0168:            else:
>> Exception: FileExistsError: [Errno 17] File exists: 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' -> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'
>>
>> In this particular case, the paths in lib32-linux-libc-headers manifest file
>> are prefixed with lib32-recipe-sysroot:
>> $ cat build/tmp/sysroots-components/manifests/lib32-linux-libc-headers.xxx
>> lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
>> lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
>> ...
>>
>> When gcc-cross-canadian-arm is built, the actual files get copied to
>> recipe-sysroot directory during do_prepare_recipe_sysroot().
>>
>> Because of this mismatch, on rebuild, sstate_clean_manifest() will not clean
>> the files in recipe-sysroot, but will instead try to delete the non-existent
>> files in lib32-recipe-sysroot. This will trigger the FileExists errors later.
>>
>> Add checks in sstate_clean_manifest() for this corner case, so that
>> RECIPE_SYSROOT gets cleaned up properly.
>>
>> This fixes BZ#15045.
>>
>> Signed-off-by: Ovidiu Panait <ovidiu.panait@eng.windriver.com>
>> ---
>>   meta/classes-global/sstate.bbclass | 11 +++++++++++
>>   1 file changed, 11 insertions(+)
>>
>> diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
>> index af93546b04..edf5c7fb65 100644
>> --- a/meta/classes-global/sstate.bbclass
>> +++ b/meta/classes-global/sstate.bbclass
>> @@ -529,9 +529,20 @@ def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
>>       entries = mfile.readlines()
>>       mfile.close()
>>
>> +    recipe_sysroot = d.getVar("RECIPE_SYSROOT").rstrip("/").rsplit('/', 1)[-1]
>> +
>>       for entry in entries:
>>           sstate_clean_entry(entry, canrace, prefix)
>>
>> +        # The sysroot directory stored in the manifest file might not be the
>> +        # same as RECIPE_SYSROOT, so the real sysroot will not be properly
>> +        # cleaned up on rebuild. Handle the cleanup here in order to avoid
>> +        # "File exists" errors during do_prepare_recipe_sysroot().
>> +        manifest_sysroot = entry.split("/", 1)[0] or None
>> +        if manifest_sysroot and manifest_sysroot != recipe_sysroot and not manifest_sysroot.endswith("-native"):
>> +            sysroot_entry = recipe_sysroot + "/" + entry.split("/", 1)[1]
>> +            sstate_clean_entry(sysroot_entry, canrace, prefix)
>> +
>>       postrm = manifest + ".postrm"
>>       if os.path.exists(manifest + ".postrm"):
>>           import subprocess
> I looked into this and as I suspected, the bug is elsewhere. I've sent
> a different patch to the staging.bbclass code which should fix this
> problem.

I tested with latest poky sources (with commit "staging: Separate out 
different multiconfig manifests" present), but the same error is still 
triggered on rebuild:

File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: 
staging_copyfile
      0160:        os.symlink(linkto, dest)
      0161:        #bb.warn(c)
      0162:    else:
      0163:        try:
  *** 0164:            os.link(c, dest)
      0165:        except OSError as err:
      0166:            if err.errno == errno.EXDEV:
      0167:                bb.utils.copyfile(c, dest)
      0168:            else:
Exception: FileExistsError: [Errno 17] File exists: 
'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' 
-> 
'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'

The manifest files still show lib32-recipe-sysroot instead of 
recipe-sysroot (the manifest file seems to have already been cached by 
lib32-gcc-cross-arm):
$ head -2 
tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot-native/installeddeps/lib32-linux-libc-headers
lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h

MLPREFIX is set to lib32- for gcc-cross-canadian-arm, so the existing 
manifest file with lib32-recipe-sysroot paths is used:
$ bitbake -e gcc-cross-canadian-arm | grep ^MLPREFIX
MLPREFIX="lib32-"

Adding an exception for cross-canadian to the the mlprefix code added 
earlier seems to make it work:

diff --git a/meta/classes-global/staging.bbclass 
b/meta/classes-global/staging.bbclass
index e6d0d1d55c..a9142ce780 100644
--- a/meta/classes-global/staging.bbclass
+++ b/meta/classes-global/staging.bbclass
@@ -276,6 +276,10 @@ python extend_recipe_sysroot() {
      stagingdir = d.getVar("STAGING_DIR")
      sharedmanifests = d.getVar("COMPONENTS_DIR") + "/manifests"
      mlprefix = d.getVar("MLPREFIX")
+    if "-cross-canadian" in pn:
+        mlprefix = "nativesdk-"
      if mlprefix:
          sharedmanifests = sharedmanifests + "/" + mlprefix
      recipesysroot = d.getVar("RECIPE_SYSROOT")

Ovidiu

> Cheers,
>
> Richard
>
>
Richard Purdie March 7, 2023, 8:45 p.m. UTC | #5
On Tue, 2023-03-07 at 21:04 +0200, Ovidiu Panait wrote:
> Hi Richard,
> 
> On 3/6/23 19:59, Richard Purdie wrote:
> > CAUTION: This email comes from a non Wind River email account!
> > Do not click links or open attachments unless you recognize the sender and know the content is safe.
> > 
> > On Mon, 2023-02-27 at 17:42 +0200, Ovidiu Panait wrote:
> > > The following scenario currently fails:
> > > git clone git://git.yoctoproject.org/poky
> > > cd poky; . oe-init-build-env
> > > 
> > > add to local.conf:
> > > require conf/multilib.conf
> > > MACHINE = "qemuarm64"
> > > MULTILIBS = "multilib:lib32"
> > > DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"
> > > 
> > > bitbake gcc-cross-canadian-arm
> > > 
> > > update local.conf to force a rebuild:
> > > GCCPIE = "--disable-default-pie"
> > > 
> > > bitbake gcc-cross-canadian-arm
> > > 
> > > Failure log:
> > > The stack trace of python calls that resulted in this exception/failure was:
> > > File: 'exec_func_python() autogenerated', lineno: 2, function: <module>
> > >       0001:
> > >   *** 0002:extend_recipe_sysroot(d)
> > >       0003:
> > > File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: staging_copyfile
> > >       0160:        os.symlink(linkto, dest)
> > >       0161:        #bb.warn(c)
> > >       0162:    else:
> > >       0163:        try:
> > >   *** 0164:            os.link(c, dest)
> > >       0165:        except OSError as err:
> > >       0166:            if err.errno == errno.EXDEV:
> > >       0167:                bb.utils.copyfile(c, dest)
> > >       0168:            else:
> > > Exception: FileExistsError: [Errno 17] File exists: 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' -> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'
> > > 
> > > In this particular case, the paths in lib32-linux-libc-headers manifest file
> > > are prefixed with lib32-recipe-sysroot:
> > > $ cat build/tmp/sysroots-components/manifests/lib32-linux-libc-headers.xxx
> > > lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
> > > lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
> > > ...
> > > 
> > > When gcc-cross-canadian-arm is built, the actual files get copied to
> > > recipe-sysroot directory during do_prepare_recipe_sysroot().
> > > 
> > > Because of this mismatch, on rebuild, sstate_clean_manifest() will not clean
> > > the files in recipe-sysroot, but will instead try to delete the non-existent
> > > files in lib32-recipe-sysroot. This will trigger the FileExists errors later.
> > > 
> > > Add checks in sstate_clean_manifest() for this corner case, so that
> > > RECIPE_SYSROOT gets cleaned up properly.
> > > 
> > > This fixes BZ#15045.
> > > 
> > > Signed-off-by: Ovidiu Panait <ovidiu.panait@eng.windriver.com>
> > > ---
> > >   meta/classes-global/sstate.bbclass | 11 +++++++++++
> > >   1 file changed, 11 insertions(+)
> > > 
> > > diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
> > > index af93546b04..edf5c7fb65 100644
> > > --- a/meta/classes-global/sstate.bbclass
> > > +++ b/meta/classes-global/sstate.bbclass
> > > @@ -529,9 +529,20 @@ def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
> > >       entries = mfile.readlines()
> > >       mfile.close()
> > > 
> > > +    recipe_sysroot = d.getVar("RECIPE_SYSROOT").rstrip("/").rsplit('/', 1)[-1]
> > > +
> > >       for entry in entries:
> > >           sstate_clean_entry(entry, canrace, prefix)
> > > 
> > > +        # The sysroot directory stored in the manifest file might not be the
> > > +        # same as RECIPE_SYSROOT, so the real sysroot will not be properly
> > > +        # cleaned up on rebuild. Handle the cleanup here in order to avoid
> > > +        # "File exists" errors during do_prepare_recipe_sysroot().
> > > +        manifest_sysroot = entry.split("/", 1)[0] or None
> > > +        if manifest_sysroot and manifest_sysroot != recipe_sysroot and not manifest_sysroot.endswith("-native"):
> > > +            sysroot_entry = recipe_sysroot + "/" + entry.split("/", 1)[1]
> > > +            sstate_clean_entry(sysroot_entry, canrace, prefix)
> > > +
> > >       postrm = manifest + ".postrm"
> > >       if os.path.exists(manifest + ".postrm"):
> > >           import subprocess
> > I looked into this and as I suspected, the bug is elsewhere. I've sent
> > a different patch to the staging.bbclass code which should fix this
> > problem.
> 
> I tested with latest poky sources (with commit "staging: Separate out 
> different multiconfig manifests" present), but the same error is still 
> triggered on rebuild:
> 
> File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: 
> staging_copyfile
>       0160:        os.symlink(linkto, dest)
>       0161:        #bb.warn(c)
>       0162:    else:
>       0163:        try:
>   *** 0164:            os.link(c, dest)
>       0165:        except OSError as err:
>       0166:            if err.errno == errno.EXDEV:
>       0167:                bb.utils.copyfile(c, dest)
>       0168:            else:
> Exception: FileExistsError: [Errno 17] File exists: 
> 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' 
> -> 
> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'
> 
> The manifest files still show lib32-recipe-sysroot instead of 
> recipe-sysroot (the manifest file seems to have already been cached by 
> lib32-gcc-cross-arm):
> $ head -2 
> tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot-native/installeddeps/lib32-linux-libc-headers
> lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
> lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
> 
> MLPREFIX is set to lib32- for gcc-cross-canadian-arm, so the existing 
> manifest file with lib32-recipe-sysroot paths is used:
> $ bitbake -e gcc-cross-canadian-arm | grep ^MLPREFIX
> MLPREFIX="lib32-"
> 
> Adding an exception for cross-canadian to the the mlprefix code added 
> earlier seems to make it work:
> 
> diff --git a/meta/classes-global/staging.bbclass 
> b/meta/classes-global/staging.bbclass
> index e6d0d1d55c..a9142ce780 100644
> --- a/meta/classes-global/staging.bbclass
> +++ b/meta/classes-global/staging.bbclass
> @@ -276,6 +276,10 @@ python extend_recipe_sysroot() {
>       stagingdir = d.getVar("STAGING_DIR")
>       sharedmanifests = d.getVar("COMPONENTS_DIR") + "/manifests"
>       mlprefix = d.getVar("MLPREFIX")
> +    if "-cross-canadian" in pn:
> +        mlprefix = "nativesdk-"
>       if mlprefix:
>           sharedmanifests = sharedmanifests + "/" + mlprefix
>       recipesysroot = d.getVar("RECIPE_SYSROOT")

Was this in a clean build? The change will need a clean TMPDIR to
properly take effect. I didn't force everyone to rebuild since the
issue is reported so rarely and has been present for a long time.

Cheers,

Richard
Ovidiu Panait March 8, 2023, 6:52 a.m. UTC | #6
Hi Richard,

On 3/7/23 22:45, Richard Purdie wrote:
> CAUTION: This email comes from a non Wind River email account!
> Do not click links or open attachments unless you recognize the sender and know the content is safe.
>
> On Tue, 2023-03-07 at 21:04 +0200, Ovidiu Panait wrote:
>> Hi Richard,
>>
>> On 3/6/23 19:59, Richard Purdie wrote:
>>> CAUTION: This email comes from a non Wind River email account!
>>> Do not click links or open attachments unless you recognize the sender and know the content is safe.
>>>
>>> On Mon, 2023-02-27 at 17:42 +0200, Ovidiu Panait wrote:
>>>> The following scenario currently fails:
>>>> git clone git://git.yoctoproject.org/poky
>>>> cd poky; . oe-init-build-env
>>>>
>>>> add to local.conf:
>>>> require conf/multilib.conf
>>>> MACHINE = "qemuarm64"
>>>> MULTILIBS = "multilib:lib32"
>>>> DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"
>>>>
>>>> bitbake gcc-cross-canadian-arm
>>>>
>>>> update local.conf to force a rebuild:
>>>> GCCPIE = "--disable-default-pie"
>>>>
>>>> bitbake gcc-cross-canadian-arm
>>>>
>>>> Failure log:
>>>> The stack trace of python calls that resulted in this exception/failure was:
>>>> File: 'exec_func_python() autogenerated', lineno: 2, function: <module>
>>>>        0001:
>>>>    *** 0002:extend_recipe_sysroot(d)
>>>>        0003:
>>>> File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function: staging_copyfile
>>>>        0160:        os.symlink(linkto, dest)
>>>>        0161:        #bb.warn(c)
>>>>        0162:    else:
>>>>        0163:        try:
>>>>    *** 0164:            os.link(c, dest)
>>>>        0165:        except OSError as err:
>>>>        0166:            if err.errno == errno.EXDEV:
>>>>        0167:                bb.utils.copyfile(c, dest)
>>>>        0168:            else:
>>>> Exception: FileExistsError: [Errno 17] File exists: 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h' -> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'
>>>>
>>>> In this particular case, the paths in lib32-linux-libc-headers manifest file
>>>> are prefixed with lib32-recipe-sysroot:
>>>> $ cat build/tmp/sysroots-components/manifests/lib32-linux-libc-headers.xxx
>>>> lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
>>>> lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
>>>> ...
>>>>
>>>> When gcc-cross-canadian-arm is built, the actual files get copied to
>>>> recipe-sysroot directory during do_prepare_recipe_sysroot().
>>>>
>>>> Because of this mismatch, on rebuild, sstate_clean_manifest() will not clean
>>>> the files in recipe-sysroot, but will instead try to delete the non-existent
>>>> files in lib32-recipe-sysroot. This will trigger the FileExists errors later.
>>>>
>>>> Add checks in sstate_clean_manifest() for this corner case, so that
>>>> RECIPE_SYSROOT gets cleaned up properly.
>>>>
>>>> This fixes BZ#15045.
>>>>
>>>> Signed-off-by: Ovidiu Panait <ovidiu.panait@eng.windriver.com>
>>>> ---
>>>>    meta/classes-global/sstate.bbclass | 11 +++++++++++
>>>>    1 file changed, 11 insertions(+)
>>>>
>>>> diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
>>>> index af93546b04..edf5c7fb65 100644
>>>> --- a/meta/classes-global/sstate.bbclass
>>>> +++ b/meta/classes-global/sstate.bbclass
>>>> @@ -529,9 +529,20 @@ def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
>>>>        entries = mfile.readlines()
>>>>        mfile.close()
>>>>
>>>> +    recipe_sysroot = d.getVar("RECIPE_SYSROOT").rstrip("/").rsplit('/', 1)[-1]
>>>> +
>>>>        for entry in entries:
>>>>            sstate_clean_entry(entry, canrace, prefix)
>>>>
>>>> +        # The sysroot directory stored in the manifest file might not be the
>>>> +        # same as RECIPE_SYSROOT, so the real sysroot will not be properly
>>>> +        # cleaned up on rebuild. Handle the cleanup here in order to avoid
>>>> +        # "File exists" errors during do_prepare_recipe_sysroot().
>>>> +        manifest_sysroot = entry.split("/", 1)[0] or None
>>>> +        if manifest_sysroot and manifest_sysroot != recipe_sysroot and not manifest_sysroot.endswith("-native"):
>>>> +            sysroot_entry = recipe_sysroot + "/" + entry.split("/", 1)[1]
>>>> +            sstate_clean_entry(sysroot_entry, canrace, prefix)
>>>> +
>>>>        postrm = manifest + ".postrm"
>>>>        if os.path.exists(manifest + ".postrm"):
>>>>            import subprocess
>>> I looked into this and as I suspected, the bug is elsewhere. I've sent
>>> a different patch to the staging.bbclass code which should fix this
>>> problem.
>> I tested with latest poky sources (with commit "staging: Separate out
>> different multiconfig manifests" present), but the same error is still
>> triggered on rebuild:
>>
>> File: 'poky/meta/classes-global/staging.bbclass', lineno: 164, function:
>> staging_copyfile
>>        0160:        os.symlink(linkto, dest)
>>        0161:        #bb.warn(c)
>>        0162:    else:
>>        0163:        try:
>>    *** 0164:            os.link(c, dest)
>>        0165:        except OSError as err:
>>        0166:            if err.errno == errno.EXDEV:
>>        0167:                bb.utils.copyfile(c, dest)
>>        0168:            else:
>> Exception: FileExistsError: [Errno 17] File exists:
>> 'poky/build/tmp/sysroots-components/armv7at2hf-neon/lib32-linux-libc-headers/usr/include/asm/byteorder-32.h'
>> ->
>> 'poky/build/tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot/usr/include/asm/byteorder-32.h'
>>
>> The manifest files still show lib32-recipe-sysroot instead of
>> recipe-sysroot (the manifest file seems to have already been cached by
>> lib32-gcc-cross-arm):
>> $ head -2
>> tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot-native/installeddeps/lib32-linux-libc-headers
>> lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
>> lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
>>
>> MLPREFIX is set to lib32- for gcc-cross-canadian-arm, so the existing
>> manifest file with lib32-recipe-sysroot paths is used:
>> $ bitbake -e gcc-cross-canadian-arm | grep ^MLPREFIX
>> MLPREFIX="lib32-"
>>
>> Adding an exception for cross-canadian to the the mlprefix code added
>> earlier seems to make it work:
>>
>> diff --git a/meta/classes-global/staging.bbclass
>> b/meta/classes-global/staging.bbclass
>> index e6d0d1d55c..a9142ce780 100644
>> --- a/meta/classes-global/staging.bbclass
>> +++ b/meta/classes-global/staging.bbclass
>> @@ -276,6 +276,10 @@ python extend_recipe_sysroot() {
>>        stagingdir = d.getVar("STAGING_DIR")
>>        sharedmanifests = d.getVar("COMPONENTS_DIR") + "/manifests"
>>        mlprefix = d.getVar("MLPREFIX")
>> +    if "-cross-canadian" in pn:
>> +        mlprefix = "nativesdk-"
>>        if mlprefix:
>>            sharedmanifests = sharedmanifests + "/" + mlprefix
>>        recipesysroot = d.getVar("RECIPE_SYSROOT")
> Was this in a clean build? The change will need a clean TMPDIR to
> properly take effect. I didn't force everyone to rebuild since the
> issue is reported so rarely and has been present for a long time.
Yes, this is still reproducible in a clean build, with a fresh poky 
clone. Same steps as before:

git clone https://github.com/yoctoproject/poky.git;  cd poky/; . 
oe-init-build-env


add to local.conf:
require conf/multilib.conf
MACHINE = "qemuarm64"
MULTILIBS = "multilib:lib32"
DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"

bitbake gcc-cross-canadian-arm

update local.conf to force a rebuild:
GCCPIE = "--disable-default-pie"

bitbake gcc-cross-canadian-arm


Ovidiu
Richard Purdie March 8, 2023, 10:18 a.m. UTC | #7
On Wed, 2023-03-08 at 08:52 +0200, Ovidiu Panait wrote:
> On 3/7/23 22:45, Richard Purdie wrote:
> > CAUTION: This email comes from a non Wind River email account!
> > Do not click links or open attachments unless you recognize the sender and know the content is safe.
> > 
> > On Tue, 2023-03-07 at 21:04 +0200, Ovidiu Panait wrote:
> > > 
> > > The manifest files still show lib32-recipe-sysroot instead of
> > > recipe-sysroot (the manifest file seems to have already been cached by
> > > lib32-gcc-cross-arm):
> > > $ head -2
> > > tmp/work/x86_64-nativesdk-pokysdk-linux/gcc-cross-canadian-arm/12.2.0-r0/recipe-sysroot-native/installeddeps/lib32-linux-libc-headers
> > > lib32-recipe-sysroot/usr/include/asm/byteorder-32.h
> > > lib32-recipe-sysroot/usr/include/asm/sigcontext-32.h
> > > 
> > > MLPREFIX is set to lib32- for gcc-cross-canadian-arm, so the existing
> > > manifest file with lib32-recipe-sysroot paths is used:
> > > $ bitbake -e gcc-cross-canadian-arm | grep ^MLPREFIX
> > > MLPREFIX="lib32-"
> > > 
> > > Adding an exception for cross-canadian to the the mlprefix code added
> > > earlier seems to make it work:
> > > 
> > > diff --git a/meta/classes-global/staging.bbclass
> > > b/meta/classes-global/staging.bbclass
> > > index e6d0d1d55c..a9142ce780 100644
> > > --- a/meta/classes-global/staging.bbclass
> > > +++ b/meta/classes-global/staging.bbclass
> > > @@ -276,6 +276,10 @@ python extend_recipe_sysroot() {
> > >        stagingdir = d.getVar("STAGING_DIR")
> > >        sharedmanifests = d.getVar("COMPONENTS_DIR") + "/manifests"
> > >        mlprefix = d.getVar("MLPREFIX")
> > > +    if "-cross-canadian" in pn:
> > > +        mlprefix = "nativesdk-"
> > >        if mlprefix:
> > >            sharedmanifests = sharedmanifests + "/" + mlprefix
> > >        recipesysroot = d.getVar("RECIPE_SYSROOT")
> > Was this in a clean build? The change will need a clean TMPDIR to
> > properly take effect. I didn't force everyone to rebuild since the
> > issue is reported so rarely and has been present for a long time.
> Yes, this is still reproducible in a clean build, with a fresh poky 
> clone. Same steps as before:
> 
> git clone https://github.com/yoctoproject/poky.git;  cd poky/; . 
> oe-init-build-env
> 
> 
> add to local.conf:
> require conf/multilib.conf
> MACHINE = "qemuarm64"
> MULTILIBS = "multilib:lib32"
> DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"
> 
> bitbake gcc-cross-canadian-arm
> 
> update local.conf to force a rebuild:
> GCCPIE = "--disable-default-pie"
> 
> bitbake gcc-cross-canadian-arm
> 

Sorry, it looks like I messed something up in testing. The approach is
the right one but as you mention, it isn't quite working.

I've sent another patch which does work with the steps above. We can't
just use nativesdk since the file lists of the different canadian
targets may be different and would cause a different kind of failure. I
therefore tweaked the prefix accordingly and made the fix multilib
specific at the call site that triggers the issue.

Cheers,

Richard
Ovidiu Panait March 8, 2023, 11:35 a.m. UTC | #8
On 08.03.2023 12:18, Richard Purdie wrote:
>> Yes, this is still reproducible in a clean build, with a fresh poky
>> clone. Same steps as before:
>>
>> git clone https://github.com/yoctoproject/poky.git;  cd poky/; .
>> oe-init-build-env
>>
>>
>> add to local.conf:
>> require conf/multilib.conf
>> MACHINE = "qemuarm64"
>> MULTILIBS = "multilib:lib32"
>> DEFAULTTUNE:virtclass-multilib-lib32 = "armv7athf-neon"
>>
>> bitbake gcc-cross-canadian-arm
>>
>> update local.conf to force a rebuild:
>> GCCPIE = "--disable-default-pie"
>>
>> bitbake gcc-cross-canadian-arm
>>
> Sorry, it looks like I messed something up in testing. The approach is
> the right one but as you mention, it isn't quite working.
>
> I've sent another patch which does work with the steps above. We can't
> just use nativesdk since the file lists of the different canadian
> targets may be different and would cause a different kind of failure. I
> therefore tweaked the prefix accordingly and made the fix multilib
> specific at the call site that triggers the issue.

The new patch fixes the build for me as well, thanks a lot!


Ovidiu

> Cheers,
>
> Richard
>
diff mbox series

Patch

diff --git a/meta/classes-global/sstate.bbclass b/meta/classes-global/sstate.bbclass
index af93546b04..edf5c7fb65 100644
--- a/meta/classes-global/sstate.bbclass
+++ b/meta/classes-global/sstate.bbclass
@@ -529,9 +529,20 @@  def sstate_clean_manifest(manifest, d, canrace=False, prefix=None):
     entries = mfile.readlines()
     mfile.close()
 
+    recipe_sysroot = d.getVar("RECIPE_SYSROOT").rstrip("/").rsplit('/', 1)[-1]
+
     for entry in entries:
         sstate_clean_entry(entry, canrace, prefix)
 
+        # The sysroot directory stored in the manifest file might not be the
+        # same as RECIPE_SYSROOT, so the real sysroot will not be properly
+        # cleaned up on rebuild. Handle the cleanup here in order to avoid
+        # "File exists" errors during do_prepare_recipe_sysroot().
+        manifest_sysroot = entry.split("/", 1)[0] or None
+        if manifest_sysroot and manifest_sysroot != recipe_sysroot and not manifest_sysroot.endswith("-native"):
+            sysroot_entry = recipe_sysroot + "/" + entry.split("/", 1)[1]
+            sstate_clean_entry(sysroot_entry, canrace, prefix)
+
     postrm = manifest + ".postrm"
     if os.path.exists(manifest + ".postrm"):
         import subprocess