-
Notifications
You must be signed in to change notification settings - Fork 69
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
mesonpy embeds random path into .o files for debug build #671
Comments
You are "holding it wrong": https://gitweb.gentoo.org/repo/gentoo.git/tree/eclass/distutils-r1.eclass#n1297 |
The line above is: meson-python/mesonpy/__init__.py Line 964 in 04e0066
... so set build dir if you don't want one chosen for you. |
So far our build-description just says A more deterministic default would still be appreciated. e.g. scipy is listed on https://github.com/mesonbuild/meson-python/blob/main/docs/projects-using-meson-python.rst as "known to be adhering to best practices" but seems to also not specify a Edit: docs suggest Now I got a reproducible build with
However, this is not so reassuring:
|
The "how-to-guides" link leads to an older version. https://mesonbuild.com/meson-python/reference/config-settings.html does not mention the at-own risk. We have a clean build directory for every package (and python flavor) built by rpmbuild, so I think we can handle the risk. |
That sounds like an excellent question to ask the rpm or other OpenSUSE developers. I don't think meson-python has any opinion or indeed knowledge at all about what rpm-specific mechanisms rpm is using to execute meson-python or pass options to meson-python.
It seems you are still confused about the option then? Why would scipy specify a builddir when it is the job of the build orchestration to decide whether a builddir makes sense? The default is carefully chosen -- the option is to "enable reproducibility and disable protections against clobbering manual user-configured build directories for people who don't use distro automation and just
Even for out of date documentation (which admittedly should be deleted) that is no longer referenced, it is marked as a TODO. It is vagueness upon vagueness. You shouldn't just take that with a grain of salt, you should take it with a whole bucket of salt. |
UX-wise there's a tradeoff here. With the extra tmpdir that meson-python creates:
(1) seems more critical than (2) and has a much larger number of users, so our current choice does look right. However, the other question I'd have is what exactly gets embedded in those I currently don't have much bandwidth, but if there's a fixable problem here I'd certainly want to prioritize fixing that for SciPy. |
I did a test and cannot actually reproduce the problem here with SciPy. Procedure:
|
It's the debug info in unstripped binaries. |
Ah that makes sense, thanks. It's not clear from the issue description or the links given there though. @bmwiedemann can you please confirm that all your regular package builds are fine, and it's only building debug packages that is showing non-reproducibility? |
Yes, building without debuginfo is reproducible. |
The build ID hash depending on an absolute path to a build directory that doesn't exist at runtime is a design problem in debuginfo it looks like. While you can work around it by using The program My patch adds the This is better than using |
Another way out could be the |
That looks like it's in the right direction too indeed. Not sure it can be made to work though, since you have to pass the name of the I'll include the description for When compiling files residing in directory |
mesonpy knows the name of the tmpdir, so could it add this option to |
Inserting fairly niche and GCC-specific compiler flags into a build seems like a big no no. It's likely to break something else, confuse users, and bloat the build logs. Also, while we know what |
All this is already handled by the built-in reproducibility tooling for every entity working on reproducible builds, as long as you follow the existing directions in the mesonpy docs and pass the build-dir setting like some other distros already do. |
To be fair, there's no real docs for this yet, so I learned something here about how debuginfo is handled (and that we support |
hmmm.... :) Mostly, SOURCE_DATE_EPOCH is supported by actual build tools e.g. build paths are discussed a bit at https://reproducible-builds.org/docs/build-path/ and it's a generic problem which is generically solved by one of:
(And using a stable build-dir option is also important, therefore.) |
Sure, it exists somewhere - all I meant is we need a page/section in https://mesonbuild.com/meson-python/ that mentions these things and then links to https://reproducible-builds.org and https://mesonbuild.com/Reproducible-builds.html.
Ah yes, that page covers exactly all that we've talked about in this issue. |
We solved this in openSUSE with https://build.opensuse.org/request/show/1204841 using a patch that sets a constant |
Hi folks - I'm a volunteer contributor to Reproducible Builds, and tend to focus on upstream and Debian patches; I began reading this while researching possible deterministic builds for Debian's Because I try to be a little circumspect about reading other projects' licensed code before writing my own patches (even in the context of mutual and compatible open source licenses), I haven't read the Gentoo or OpenSUSE approaches to fixing a I 100% agree with the idea of isolating temporary build directories during default But I'd also like to add some support for the As for what to set the As to whether that complexity is worthwhile compared to adding a compiler option, adding noise in build logs, etc: I think that's a very fair question. The best response I can offer is that I personally think that software, by default, should build reproducibly. We can't always guarantee it -- people can always add code that will vary at build-time -- but deterministic-by-default (even with debugging enabled) I think would provide a lot of benefits and simplifications. That said, I understand the caution about supporting this natively, and I think it's fairly reasonable to expect that build systems will handle this (some already are, and hopefully more will join). If I care about it enough, motivated self-interest should lead me to offer a pull request; I don't know whether I'll get around to that yet, but I'll consider it. Thanks for reading if you made it this far, and no problem otherwise -- perhaps there could've been a more concise way for me to share my line of thinking. |
Gentoo utilizes https://mesonbuild.com/meson-python/reference/config-settings.html OpenSUSE has patched the source code of meson-python to behave differently. I recommend following the mesonpy documentation on passing args equivalent to GNU autotools And debhelper defines at minimum, buildtype=plain which you are going to want to pass to mesonpy as well for policy reasons.
But not MSVC! :) And maybe or maybe not ccrx, compcert, xc16, nvc, pgcc, icc, icx, lcc, emscripten, armclang, armltdclang, elbrus, metrowerks... quite literally, I genuinely have no clue! :) Sure, some of those are derived from llvm. Are they new enough derivations to support fdebug-prefix-map, added practically yesterday as these things are reckoned -- in 2016? So actually adding compile args by default would have to be done with care. Do we do it in mesonpy? How do we juggle setting this, guaranteeing it is set even when the user passed in their own CFLAGS or a native file, without totally overwriting the user-passed arguments? Most of all, how do we know what compiler is used? I mean, granted, I highly doubt mesonpy needs to care about Metrowerks even if meson itself does support it, but mesonpy is used on AIX. Meson might add support for xlC if the AIX scientific community submits patches for it. Do we instead add fdebug-prefix-map inside meson? But meson is more low-level and doesn't choose a How does one opt out of this, if they are positive they want the original paths? I mean, there's a reason the compiler vendors haven't simply unilaterally declared that prefixes will always be mapped without specifying an option. Which brings us to: I would say that it is a moot point anyway because it cannot be added by default, only when it is specifically known that a reproducible build is desired...
... because this is unfortunately totally wrong. :( I mean, I do agree with my reproducible-builds hat on that many forms of reproducibility should simply be the default behavior. Stuff like But fdebug-prefix-map doesn't even affect This is why for reproducible builds we want to control the build-dir setting so we can ensure the debug info computes stable, reproducible paths, and we also want to inject fdebug-prefix-map outside of mesonpy, so that we can remap the extracted workdir to e.g.
No problem. It's a genuinely fascinating topic. :) Even if I have formed different conclusions than you have, I appreciate the thought that went into it as well as the opportunity to share the thoughts I have about it. |
I realize that I am unsure whether Debian packages "installed-sources" for debug packages. I know dbgsym exists... But fedora provides debuginfo and debugsource. Arch packages sources as part of debug packages. Gentoo provides FEATURES="splitdebug installsources". |
Thanks - I definitely concede the many-other-compilers argument, and am not familiar enough (and probably shouldn't have implied that I was, previously!) with the way debug resources are loaded to find a way past that (other than, a naive thought perhaps, that some kind of content-addressing scheme might make sense to retrieve debug resources, because that'd be path-agnostic). |
Hmm... I think the debug Build-ID essentially is the content-addressing scheme, already; it's how a binary is linked to the associated debug resources (as retrieved from a filesystem directory, What I don't get is the reasoning behind why some/any elements in the binary need to reference paths at all. For example, in the Debian reproducibility testing diffs at https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/diffoscope-results/contourpy.html the DWARF file contains a Directory Table entry in each comparative build for |
Build-ID is that for the associative link between two objects that possess a build ID: the binary executable and the binary debug fields stripped out of an executable.
Because it's not necessarily about what goes into a Debian package. Like I said, Debian doesn't actually distribute all the data that other people use and rely on. What is it conceptually? Well, I mentioned source code above. If you build a program without installing it (for example to This is a fundamental difference between building software and running it immediately vs building software and packaging it in a package manager. In the latter case, and only in the latter case, a program is run on the packaged binaries to postprocess them, move their debug info into separate packages, and include the program source code into that separate package as well. This program also can rewrite the debug info to refer to the locations that the separate package will install, rather than referring to build directories, but gcc has an option to do the rewrite at compilation time and then all you have to do is move the sources. (The program is appropriately called "debugedit".)
The build system can't know automatically which of the three is relevant, but CFLAGS can always know, or a specific option can be added. "Just automatically replace it with option 3" isn't on the table, since option 3 will break case 1 even if case 2 is superseded by a hashed content-addressable storage system. And the content-addressable storage system would have to be invented first and rolled out to existing toolchains by upgrading to new versions of gdb etc, I think. |
To your question about Debian: yes, as you know Most of what you say I agree with, but I still think that, to take the case of The first diff between two builds lists this difference in the output
So, first of all: the temporary build directory isn't actually relevant for debugging/source-stepping purposes. It provides build isolation, but the source files were outside of it anyway, in the In the corresponding DWARF
There is -- separately! -- a reference to the
So... it seems that the Does that imply a bug with a different component? I don't know. To me it seems that the DWARF file shouldn't contain the |
maybe this can be solved by referencing source files differently as |
debug info when faced with relative filenames passed on the command line must store the compiler's working directory as well, specifically because the It is an intentional part of the DWARF spec. I'm not familiar offhand with why this decision was chosen compared to e.g. performing canonicalization resolution and storing the computed realpath instead (maybe they didn't think it would matter? maybe they were concerned that a symlink destination would change and invalidate the computation? maybe they thought it did matter and actively wanted to be able to omit the comp_dir for display purposes?) but it is certainly the state of affairs as of today, so changing it would require a spec change conditional on consensus between various international stakeholders and is not a simple matter of declaring it a bug in the implementation. |
Hmm.. well, regardless of canonicalization, the current-working-directory entry really needs to be there, according to the DWARF v5 spec, page 157 (hyperlink fragment is not a typo; page 157 of the document is page 175 of the PDF...):
Which I suppose is an argument for specifying a constant I'll probably pause for a while, rather than being stubborn, but essentially what I'd like to achieve is: deterministic debug builds, with source-reference feasible at debugging-time (perhaps using path-based discovery of sources, or in rare cases, debugger config/command-line options.. though I'd prefer to avoid those), for both local development and on hosted/distro build infrastructure. I think the 'three options' described earlier is an effective summary of the practical status-quo today. |
Although I've learned a number of things during this thread: I think I am going to take a break from this and a few other topics and will unsubscribe. Maybe that's not entirely useful to comment about, but I'd prefer to make it apparent. I have some strong-ish opinions on what I believe should be possible here.. but not (yet? :)) the practical and detailed technical knowledge to back that up. Thanks for the discussion. |
While working on reproducible builds for openSUSE (sponsored by the NLnet NGI0 fund), I found that various python packages (python-pandas, python-scikit-learn, python-scipy, python-contourpy, python-gobject) have variations in every build.
I am pretty certain this comes from
meson-python/mesonpy/__init__.py
Line 965 in 04e0066
but don't know how to best make this deterministic.
Is there a variant of
tempfile.TemporaryDirectory
that does not add randomness? I tried withpathlib.Path(os.path.join(source_dir, '.mesonpy'))
but that lacks the automatic cleanup.Here is a typical diff:
The text was updated successfully, but these errors were encountered: