Skip to content

Conversation

@Fuzzbawls
Copy link
Contributor

With the update to Qt 5.9 having been merged, Qt's rcc tool now embeds a file's last modified time in it's output. Since the build system generates temporary files for all locale translations (*.qm files) at build time, the resulting qrc_bitcoin_locale.cpp file was always being generated in a non-deterministic way.

This is a backport of https://bugreports.qt.io/browse/QTBUG-62511, which is included in Qt versions 5.11+, that allows for an environment variable (QT_RCC_SOURCE_DATE_OVERRIDE) to override the behavior described above. This environment variable is in turn set in the gitian descriptors, as that is where determinism is vital for release purposes.

Prior to this, the qt_libbitcoinqt_a-qrc_bitcoin_locale.o object file (included into libbitcoinqt.a) was returning a different sha256sum for each and every build, regardless of file contents change, thus breaking determinism in the resulting binaries.

This should fix #13731

@fanquake fanquake requested a review from theuni July 21, 2018 14:03
@fanquake fanquake added this to the 0.17.0 milestone Jul 21, 2018
@ken2812221
Copy link
Contributor

I assume that this can be solved by adding rcc into faketime wrapper.

@maflcko
Copy link
Member

maflcko commented Jul 21, 2018

@DrahtBot Have some fun here!

@practicalswift
Copy link
Contributor

practicalswift commented Jul 21, 2018

Concept ACK. Nice first time-contribution. Thanks!

Determinism is our friend!

@Fuzzbawls
Copy link
Contributor Author

adding rcc to the list of faketime wrapped binaries is problematic in that the rcc binary location is also defined in the share/config.site file that gets used for gitian builds, which does not use the $PATH environment variable, and the build system isn't really set up to allow for separate paths for each individual Qt tool.

I don't think that would be a viable alternative anyways, as we would then need to ensure that the last modified timestamp of every generated *.qm file is static (faketime again?).

There is an alternative that is less code than this, but I'm not sure if it would be acceptable either as it could potentially interfere with non-gitian builds:

--- src/Makefile.qt.include
+++ src/Makefile.qt.include
@@ -430,7 +430,7 @@
 $(QT_QRC_LOCALE_CPP): $(QT_QRC_LOCALE) $(QT_QM)
 	@test -f $(RCC)
 	@cp -f $< $(@D)/temp_$(<F)
-	$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) -name bitcoin_locale $(@D)/temp_$(<F) | \
+	$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(RCC) --format-version 1 -name bitcoin_locale $(@D)/temp_$(<F) | \
 	  $(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
 	@rm $(@D)/temp_$(<F)
 

This is a runtime option to rcc that forces the older format version to be used, which specifically does not encode file timestamps into the result. There was some concern about using such an override however in the Qt bug report's discussion thread.

@maflcko
Copy link
Member

maflcko commented Jul 22, 2018

Indeed, looks like the results are stable now.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jul 22, 2018

Note to reviewers: This pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

@laanwj
Copy link
Member

laanwj commented Jul 22, 2018

Concept ACK
Thanks a lot for figuring this out.!
In the longer run, it would be a good idea to get deterministic-build support pushed upstream (@theuni has some experience doing this for binutils).

@Fuzzbawls
Copy link
Contributor Author

@laanwj In this particular case, upstream Qt did indeed "fix" the issue, but only for versions 5.11+. Even though the QTBUG was closed and marked invalid, a proposed change addressing the issue was merged. (qt/qtbase@38271e9)

I agree though, it would be great if the patch made it into Qt's 5.9 branch and a 5.9.7 version released so it wouldn't need to be explicitely applied in depends here. Until then, however, I think this is the best that can be done while still keeping Qt 5.9.

Copy link
Member

Choose a reason for hiding this comment

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

We need to export the variable here as well so that non-gitian builds get stable results. See below where QT_RCC_TEST is set to 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Noted, will add this soon

Copy link
Contributor Author

Choose a reason for hiding this comment

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

swapped out the build_env variable further up in this file and didn't notice any break in gitian results determinism.

Copy link
Member

Choose a reason for hiding this comment

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

QT_RCC_TEST was the variable for this in the past. If QT_RCC_SOURCE_DATE_OVERRIDE is the new one, let's just replace QT_RCC_TEST. I assume there's no need for both.

Same goes for the other descriptors as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed QT_RCC_TEST=1 from gitian descriptors and didn't notice any break in gitian results determinism.

@theuni
Copy link
Member

theuni commented Jul 22, 2018

@laanwj Yes, ideally qt's configure would have an option for disabling timestamps by default, which is quickly becoming the norm for host-side build tools.

@Fuzzbawls Fuzzbawls force-pushed the btc_fix-rcc-determinism branch from 927bb45 to cc4a5d1 Compare July 24, 2018 08:11
@Fuzzbawls
Copy link
Contributor Author

Fuzzbawls commented Jul 24, 2018

Rebased and pushed to incorporate feedback from @theuni.

One thing of note: While gitian builds are now deterministic, non-gitian builds that use --prefix= or CONFIG_SITE= pointing at a depends path are only deterministic if they also set QT_RCC_SOURCE_DATE_OVERRIDE=1 at compile time

CONFIG_SITE=/home/fuzzbawls/bitcoin/depends/x86_64-unknown-linux/share/config.site ./configure
QT_RCC_SOURCE_DATE_OVERRIDE=1 make

some further tweaking to depends/config.site.in and/or depends/funcs.mk...or configure.ac may be in order to automatically export that environment variable for non-gitian builds, but that may be broadening the scope just a bit too much here given the upcoming release cycle.

@theuni
Copy link
Member

theuni commented Jul 24, 2018

@Fuzzbawls Sorry to do this to you, but I just had a look at the qt source, and it turns out that RCC_TEST has a totally different function: it serves as the seed for a hash function that ends up dictating the order of file entries. So my request above was completely wrong, we need both :(

Would you mind putting it back? utACK after that.

@Fuzzbawls Fuzzbawls force-pushed the btc_fix-rcc-determinism branch from cc4a5d1 to 6b5506a Compare July 25, 2018 23:19
@Fuzzbawls
Copy link
Contributor Author

@theuni Thanks...I had a feeling it may still be needed...just hadn't had the time to do extensive build testing. I've reverted to re-add the QT_RCC_TEST=1 env vars where appropriate and so far gitian builds are looking nice and consistent.

There is still an outstanding issue of non-gitian builds (that use a depends target) producing inconsistent results with RCC...perhaps that can be it's own issue/PR?

@jonasschnelli
Copy link
Contributor

Looks good.
Gitian Build:
https://bitcoin.jonasschnelli.ch/build/719

@bitcoin bitcoin deleted a comment from DrahtBot Jul 28, 2018
@bitcoin bitcoin deleted a comment from DrahtBot Jul 28, 2018
@DrahtBot
Copy link
Contributor

Gitian builds for commit ef4fac0 (master):

Gitian builds for commit c2fbdcd7d926841e34d5d5b24be3da781fbc48fc (master and this pull):

@maflcko
Copy link
Member

maflcko commented Jul 29, 2018

utACK 6b5506a

@DrahtBot
Copy link
Contributor

Gitian builds for commit ef4fac0 (master):

Gitian builds for commit c2fbdcd7d926841e34d5d5b24be3da781fbc48fc (master and this pull):

@maflcko maflcko merged commit 6b5506a into bitcoin:master Jul 29, 2018
maflcko pushed a commit that referenced this pull request Jul 29, 2018
6b5506a Fix Qt's rcc determinism for depends/gitian (Fuzzbawls)

Pull request description:

  With the update to Qt 5.9 having been merged, Qt's `rcc` tool now embeds a file's last modified time in it's output. Since the build system generates temporary files for all locale translations (`*.qm` files) at build time, the resulting `qrc_bitcoin_locale.cpp` file was always being generated in a non-deterministic way.

  This is a backport of https://bugreports.qt.io/browse/QTBUG-62511, which is included in Qt versions 5.11+, that allows for an environment variable (`QT_RCC_SOURCE_DATE_OVERRIDE`) to override the behavior described above. This environment variable is in turn set in the gitian descriptors, as that is where determinism is vital for release purposes.

  Prior to this, the `qt_libbitcoinqt_a-qrc_bitcoin_locale.o` object file (included into `libbitcoinqt.a`) was returning a different `sha256sum` for each and every build, regardless of file contents change, thus breaking determinism in the resulting binaries.

  This should fix #13731

Tree-SHA512: 174017e41f9afc3950ef54a9419de81577ec900db9aec3c78ccd3d879c6aecaaeb944fde0615b933f43e6ca9d7898a27ec071cdd0b91cb772755a3012de96725
@Fuzzbawls Fuzzbawls deleted the btc_fix-rcc-determinism branch January 10, 2020 00:31
UdjinM6 pushed a commit to UdjinM6/dash that referenced this pull request Dec 17, 2020
fanquake added a commit that referenced this pull request Jun 3, 2021
a58868d build: Makes rcc output always deterministic (Hennadii Stepanov)

Pull request description:

  The Qt Resource Compiler ([rcc](https://doc.qt.io/qt-5/rcc.html)) has a command-line option `--format-version` which has the [default value](https://code.qt.io/cgit/qt/qtbase.git/tree/src/tools/rcc/main.cpp?h=5.12.10#n172) 2.

  The only difference from `--format-version 1` is adding a [last modified timestamp](https://code.qt.io/cgit/qt/qtbase.git/tree/src/tools/rcc/rcc.cpp?h=5.12.10#n207) to the output file ([credits](#21654 (comment)) to **fanquake**). That, in turn, forces us to use `QT_RCC_SOURCE_DATE_OVERRIDE=1` to get deterministic builds (#13732).

  This change makes rcc output always deterministic by using `--format-version 1` option that makes usage of the
  `QT_RCC_SOURCE_DATE_OVERRIDE` needless.

  ---

  Also it improves interaction with ccache:

  On master (f6c44e9):
  ```
  $ make && make clean && ccache --zero-stats && make && ccache --show-stats
  ...
  cache directory                     /home/hebasto/.ccache
  primary config                      /home/hebasto/.ccache/ccache.conf
  secondary config      (readonly)    /etc/ccache.conf
  stats updated                       Sun Apr 11 15:45:43 2021
  stats zeroed                        Sun Apr 11 15:45:05 2021
  cache hit (direct)                   638
  cache hit (preprocessed)               0
  cache miss                             1
  cache hit rate                     99.84 %
  called for link                       10
  cleanups performed                     0
  files in cache                     20023
  cache size                          13.2 GB
  max cache size                      15.0 GB
  ```

  The missed file is always `qt/libbitcoinqt_a-qrc_bitcoin_locale.o`.

  With this PR:
  ```
  $ make && make clean && ccache --zero-stats && make && ccache --show-stats
  ...
  cache directory                     /home/hebasto/.ccache
  primary config                      /home/hebasto/.ccache/ccache.conf
  secondary config      (readonly)    /etc/ccache.conf
  stats updated                       Sun Apr 11 15:28:46 2021
  stats zeroed                        Sun Apr 11 15:28:21 2021
  cache hit (direct)                   639
  cache hit (preprocessed)               0
  cache miss                             0
  cache hit rate                    100.00 %
  called for link                       10
  cleanups performed                     0
  files in cache                     20012
  cache size                          13.2 GB
  max cache size                      15.0 GB
  ```

ACKs for top commit:
  fanquake:
    ACK a58868d

Tree-SHA512: 52f4a3267f41883d13025c0de79b6da22e92d60c729e01b986935c6812bbfe7fadc40b742bd715bfdf09df94af6838d4fbbe8208c6123f366108e38c8e1121c5
gades pushed a commit to cosanta/cosanta-core that referenced this pull request Jun 24, 2021
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gitian builds no longer deterministic

9 participants