Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 735820 - cmake-multilib.eclass might install 32-bit binaries instead of 64-bit
Summary: cmake-multilib.eclass might install 32-bit binaries instead of 64-bit
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal
Assignee: Multilib team
URL:
Whiteboard: fixed in EAPI-8
Keywords: InOverlay, PullRequest
Depends on:
Blocks: 802786
  Show dependency tree
 
Reported: 2020-08-03 21:23 UTC by Azamat H. Hackimov
Modified: 2021-09-02 18:19 UTC (History)
5 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments
emerge --info (emerge-info.txt,6.62 KB, text/plain)
2020-08-03 21:24 UTC, Azamat H. Hackimov
Details
build.log (build.log,32.77 KB, text/x-log)
2020-08-04 15:49 UTC, Azamat H. Hackimov
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Azamat H. Hackimov 2020-08-03 21:23:49 UTC
cmake-multilib installs with 50% probability 32-bit executable. Here example:

eselect profile list | grep '*'
  [23]  default/linux/amd64/17.1/desktop/plasma (stable) *

emerge -av lz4

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild   R    ] app-arch/lz4-1.9.2:0/r132::gentoo  USE="-static-libs" ABI_X86="32 (64) (-x32)" 0 KiB

Total: 1 package (1 reinstall), Size of downloads: 0 KiB

...

>>> Install app-arch/lz4-1.9.2 into /var/tmp/portage/app-arch/lz4-1.9.2/image
 * abi_x86_32.x86: running multilib-minimal_abi_src_install
 * Working in BUILD_DIR: "/var/tmp/portage/app-arch/lz4-1.9.2/work/lz4-1.9.2_build-abi_x86_32.x86"
[0/1] Install the project...
-- Install configuration: "Gentoo"
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4
-- Set runtime path of "/var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4" to ""
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4c
-- Set runtime path of "/var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4c" to ""
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/lib/liblz4.so.1.9.2
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/lib/liblz4.so.1
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/lib/liblz4.so
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/include/lz4.h
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/include/lz4frame.h
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/include/lz4hc.h
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/share/man/man1/lz4.1
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/lib/pkgconfig/liblz4.pc
-- Symlinking: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4cat -> lz4
-- Symlinking: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/unlz4 -> lz4
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/share/man/man1/lz4cat.1
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/share/man/man1/unlz4.1
  
 * Working in BUILD_DIR: "/var/tmp/portage/app-arch/lz4-1.9.2/work/lz4-1.9.2_build-abi_x86_64.amd64"
[0/1] Install the project...
-- Install configuration: "Gentoo"
-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4
-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4c
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/lib64/liblz4.so.1.9.2
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/lib64/liblz4.so.1
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/lib64/liblz4.so
-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/include/lz4.h
-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/include/lz4frame.h
-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/include/lz4hc.h
-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/share/man/man1/lz4.1
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/lib64/pkgconfig/liblz4.pc
-- Symlinking: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4cat -> lz4
-- Symlinking: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/unlz4 -> lz4
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/share/man/man1/lz4cat.1
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/share/man/man1/unlz4.1
>>> Completed installing app-arch/lz4-1.9.2 into /var/tmp/portage/app-arch/lz4-1.9.2/image

Notice "-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4" in "* abi_x86_64.amd64: running multilib-minimal_abi_src_install"

file /usr/bin/lz4
/usr/bin/lz4: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, stripped
Comment 1 Azamat H. Hackimov 2020-08-03 21:24:19 UTC
Created attachment 652814 [details]
emerge --info
Comment 2 Azamat H. Hackimov 2020-08-03 21:37:57 UTC
Seems this is ccache issue. If I disable it, package installs right executable.
Comment 3 Jeroen Roovers (RETIRED) gentoo-dev 2020-08-04 10:45:07 UTC
So neither the eclass nor the ebuild had anything to do with this.
Comment 4 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2020-08-04 11:54:40 UTC
A full build log could be useful.

TBH, I don't see why ccache would misbehave here.  To build 32-bit executable you need to pass -m32, and that should cause a cache mismatch.
Comment 5 Azamat H. Hackimov 2020-08-04 15:49:53 UTC
Created attachment 652934 [details]
build.log

build.log with ccache enabled.

file /usr/bin/lz4
/usr/bin/lz4: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, stripped
Comment 6 Sergei Trofimovich (RETIRED) gentoo-dev 2020-08-04 17:00:40 UTC
I don't think ccache caches final executables. It only caches intermediate object files.

"""
$ CCACHE_LOGFILE=lf x86_64-pc-linux-gnu-gcc a.c -o a
$ fgrep -C3 -i failed lf
[2020-08-04T18:00:00.677593 1206896] Hostname: sf
[2020-08-04T18:00:00.677602 1206896] Working directory: /tmp
[2020-08-04T18:00:00.677617 1206896] No -c option found
[2020-08-04T18:00:00.677624 1206896] Failed; falling back to running the real compiler
[2020-08-04T18:00:00.677626 1206896] Executing /usr/bin/x86_64-pc-linux-gnu-gcc a.c -o a
[2020-08-04T18:00:00.677631 1206896] Result: called for link
[2020-08-04T18:00:00.677682 1206896] Acquired lock /gentoo/ccache/9/stats.lock
"""
Comment 7 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2020-08-04 17:02:20 UTC
Could you check types of executables in build directories?
Comment 8 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2020-08-04 17:02:43 UTC
Also what filesystem are you using, and what timestamp precision does it have?
Comment 9 Sergei Trofimovich (RETIRED) gentoo-dev 2020-08-04 17:44:34 UTC
(In reply to Azamat H. Hackimov from comment #5)
> Created attachment 652934 [details]
> build.log
> 
> build.log with ccache enabled.
> 
> file /usr/bin/lz4
> /usr/bin/lz4: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV),
> dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0,
> stripped

Build.log says amd64 binaries were not installed:

>>> Install app-arch/lz4-1.9.2 into /var/tmp/portage/app-arch/lz4-1.9.2/image
 * abi_x86_32.x86: running multilib-minimal_abi_src_install
 * Working in BUILD_DIR: "/var/tmp/portage/app-arch/lz4-1.9.2/work/lz4-1.9.2_build-abi_x86_32.x86"
[0/1] Install the project...
-- Install configuration: "Gentoo"
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4
-- Set runtime path of "/var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4" to ""
-- Installing: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4c
-- Set runtime path of "/var/tmp/portage/app-arch/
...
 * abi_x86_64.amd64: running multilib-minimal_abi_src_install
 * Working in BUILD_DIR: "/var/tmp/portage/app-arch/lz4-1.9.2/work/lz4-1.9.2_build-abi_x86_64.amd64"
[0/1] Install the project...
-- Install configuration: "Gentoo"
-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4
-- Up-to-date: /var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4c

Worth checking if '-- Set runtime path of "/var/tmp/portage/app-arch/lz4-1.9.2/image/usr/bin/lz4" to ""' operation preserves original timestamps before copying binary to image/.

Can you attach your ccache config as well?
Comment 10 Sergei Trofimovich (RETIRED) gentoo-dev 2020-08-04 18:06:57 UTC
I can reproduce it too on default ccache config with 'compression = true'. enabled.

Looking at a bad state build system indeed does not preserve timestamps when applies rpath changes. Note: image file is newer than any of two built binaries (which makes sense).

$ LANG=C stat ./work/lz4-1.9.2_build-abi_x86_32.x86/lz4 ./work/lz4-1.9.2_build-abi_x86_64.amd64/lz4 ./image/usr/
bin/lz4

  File: ./work/lz4-1.9.2_build-abi_x86_32.x86/lz4
  Size: 302152          Blocks: 592        IO Block: 4096   regular file
Device: 24h/36d Inode: 6369498     Links: 1
Access: (0775/-rwxrwxr-x)  Uid: ( 1000/  slyfox)   Gid: (  100/   users)
Access: 2020-08-04 19:01:36.267256510 +0100
Modify: 2020-08-04 19:01:35.427256022 +0100
Change: 2020-08-04 19:01:35.427256022 +0100
 Birth: -

  File: ./work/lz4-1.9.2_build-abi_x86_64.amd64/lz4
  Size: 115464          Blocks: 232        IO Block: 4096   regular file
Device: 24h/36d Inode: 6368701     Links: 1
Access: (0775/-rwxrwxr-x)  Uid: ( 1000/  slyfox)   Gid: (  100/   users)
Access: 2020-08-04 19:01:35.601256123 +0100
Modify: 2020-08-04 19:01:35.601256123 +0100
Change: 2020-08-04 19:01:35.601256123 +0100
 Birth: -

  File: ./image/usr/bin/lz4
  Size: 79532           Blocks: 160        IO Block: 4096   regular file
Device: 24h/36d Inode: 6369787     Links: 1
Access: (0755/-rwxr-xr-x)  Uid: ( 1000/  slyfox)   Gid: (  100/   users)
Access: 2020-08-04 19:01:38.102257574 +0100
Modify: 2020-08-04 19:01:38.078257560 +0100
Change: 2020-08-04 19:01:38.092257569 +0100
 Birth: -

$ LANG=C file ./work/lz4-1.9.2_build-abi_x86_32.x86/lz4 ./work/lz4-1.9.2_build-abi_x86_64.amd64/lz4 ./image/usr/
bin/lz4
./work/lz4-1.9.2_build-abi_x86_32.x86/lz4:   ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped
./work/lz4-1.9.2_build-abi_x86_64.amd64/lz4: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped
./image/usr/bin/lz4:                         ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, stripped

Now the question is how build system decides what is "Up-to-date". Because if it used timestamps only it would be broken for everyone.
Comment 11 Sergei Trofimovich (RETIRED) gentoo-dev 2020-08-04 18:41:03 UTC
(In reply to Sergei Trofimovich from comment #10)
> Now the question is how build system decides what is "Up-to-date". Because
> if it used timestamps only it would be broken for everyone.

Looks like the install path is:
- (?) DESTDIR=.../image ninja install
- (from build.ninja) /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
- (from cmake_install.cmake):

"""
if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT)
  if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/lz4c" AND
     NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/lz4c")
    file(RPATH_CHECK
         FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/lz4c"
         RPATH "")
  endif()
  file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/tmp/portage/app-arch/lz4-1.9.2/work/lz4-1.9.2_build-abi_x86_64.amd64/lz4c")
  if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/lz4c" AND
     NOT IS_SYMLINK "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/lz4c")
    file(RPATH_CHANGE
         FILE "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/lz4c"
         OLD_RPATH "/tmp/portage/app-arch/lz4-1.9.2/work/lz4-1.9.2_build-abi_x86_64.amd64:"
         NEW_RPATH "")
    if(CMAKE_INSTALL_DO_STRIP)
      execute_process(COMMAND "/usr/bin/x86_64-pc-linux-gnu-strip" "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/lz4c")
    endif()
  endif()
endif()
"""

Probably cmake's builtin command does all the work:
    file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" TYPE EXECUTABLE FILES "/tmp/portage/app-arch/lz4-1.9.2/work/lz4-1.9.2_build-abi_x86_64.amd64/lz4c")

https://cmake.org/cmake/help/v3.0/command/file.html?highlight=file%20install claims that precise timestamp match is required to elide COPY/INSTALL actions.

To make sure we can check cmake's source:
    https://github.com/Kitware/CMake/blob/master/Source/cmFileInstaller.cxx#L29

First, there is a CMAKE_INSTALL_ALWAYS which I don't see Gentoo sets anywhere.

Actual timestamp check is in https://github.com/Kitware/CMake/blob/master/Source/cmFileCopier.cxx#L588

  if (!this->Always) {
    // If both files exist with the same time do not copy.
    if (!this->FileTimes.DifferS(fromFile, toFile)) {
      copy = false;
    }
  }

And DifferS has a very peculiar implementation:
    https://github.com/Kitware/CMake/blob/master/Source/cmFileTime.h#L95

  bool DifferS(cmFileTime const& ftm) const
  {
    NSC diff = this->NS - ftm.NS;
    if (diff < 0) {
      diff = -diff;
    }
    return (diff >= cmFileTime::NsPerS);
  }

It actually returns if file is older than another more that 1 second, otherwise they are treated fresh enough and copying does not happen.

ccache might contribute to the failure as it makes both compilations under a second and thus tricks second ABI to never overwrite the files. But it does not introduce anything that fasm machine would not do on it's own.
Comment 12 Sergei Trofimovich (RETIRED) gentoo-dev 2020-08-04 18:50:55 UTC
(In reply to Sergei Trofimovich from comment #11)
> And DifferS has a very peculiar implementation:
>     https://github.com/Kitware/CMake/blob/master/Source/cmFileTime.h#L95
> 
>   bool DifferS(cmFileTime const& ftm) const
>   {
>     NSC diff = this->NS - ftm.NS;
>     if (diff < 0) {
>       diff = -diff;
>     }
>     return (diff >= cmFileTime::NsPerS);
>   }
> 
> It actually returns if file is older than another more that 1 second,
> otherwise they are treated fresh enough and copying does not happen.

The fix will have to be in any/all of:
- in cmake-multilib.eclass: +multilib@ maintainer

  Possible fix would be to set CMAKE_INSTALL_ALWAYS=ON knob.

- in dev-util/cmake itself: +kde@ maintainer

  Possible fix would be to always check strict ordering withou +/- 1s jitter.
Comment 13 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2020-08-04 18:55:00 UTC
(In reply to Sergei Trofimovich from comment #12)
> The fix will have to be in any/all of:
> - in cmake-multilib.eclass: +multilib@ maintainer
> 
>   Possible fix would be to set CMAKE_INSTALL_ALWAYS=ON knob.
> 

The eclass is not supposed to be different than using multilib-minimal+cmake, so the fix belongs in cmake.eclass + cmake-utils.eclass.  I don't see why not set it unconditionally there, the not-replacing behavior is weird anyway.
Comment 14 Andreas Sturmlechner gentoo-dev 2020-08-05 13:55:08 UTC
We can certainly add that switch if that fixes it, but I'm curious why this is happening only now. Was ccache on this system broken by the 17.1 profile switch?
Comment 15 Sergei Trofimovich (RETIRED) gentoo-dev 2020-08-05 17:54:41 UTC
I don't think it's related to any profile changes. Note that observing failure is not trivial as 32-bit binaries should just work in a system.

Worth checking cmake's history if it always had such an heuristic at install phase. But the bug will not be specific to cmake. I suspect 'make' whould be as broken if not more as it does '>= timestamp' by default.

I would say Gentoo's fundamental problem is to try to do two equivalents of 'make install' into the same directory and assume it does overriding effect. If 'make install' happens to mutate target (with strip, rpath change or libtool relinking) we are very likely not to copy binaries in second 'make install'.

Or to put it into pseudocode:
1. [expected case] 'make x86 && make x86-install && make amd64 && make amd64-install' should work as binaries only increase timestamps here. Regardless of 'install' implementation.
2. [gentoo's case] 'make x86 && make amd64 && make x86-install && make amd64-install' does not have to work if 'x86-install' updates target timestamps.

Another robust alternative would be to perform 'make install' to separate target directories and merge the result afterwards.
Comment 16 Azamat H. Hackimov 2020-11-25 21:34:25 UTC
Ping?
Comment 17 Azamat H. Hackimov 2021-07-05 16:58:26 UTC
Any updates?
Comment 18 Larry the Git Cow gentoo-dev 2021-08-21 13:11:31 UTC
The bug has been referenced in the following commit(s):

https://gitweb.gentoo.org/proj/kde.git/commit/?id=c4a09deca98a78649976f966fd6e8489e041e64c

commit c4a09deca98a78649976f966fd6e8489e041e64c
Author:     Andreas Sturmlechner <asturm@gentoo.org>
AuthorDate: 2021-08-16 19:31:36 +0000
Commit:     Andreas Sturmlechner <asturm@gentoo.org>
CommitDate: 2021-08-21 13:10:11 +0000

    cmake.eclass: Enable CMAKE_INSTALL_ALWAYS
    
    Bug: https://bugs.gentoo.org/735820
    Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>

 eclass/cmake.eclass | 5 +++++
 1 file changed, 5 insertions(+)
Comment 19 Larry the Git Cow gentoo-dev 2021-09-02 16:53:13 UTC
The bug has been referenced in the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=11a3001b4252f0991cd9bb4458c14e670b8750fc

commit 11a3001b4252f0991cd9bb4458c14e670b8750fc
Author:     Andreas Sturmlechner <asturm@gentoo.org>
AuthorDate: 2021-08-16 19:31:36 +0000
Commit:     Andreas Sturmlechner <asturm@gentoo.org>
CommitDate: 2021-09-02 16:46:22 +0000

    cmake.eclass: Enable CMAKE_INSTALL_ALWAYS
    
    Bug: https://bugs.gentoo.org/735820
    Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>

 eclass/cmake.eclass | 5 +++++
 1 file changed, 5 insertions(+)