On Fri, Jul 14, 2017 at 4:00 AM, Nick Coghlan <ncogh...@gmail.com> wrote:
> On 14 July 2017 at 20:18, Nathaniel Smith <n...@pobox.com> wrote:
>> On Fri, Jul 7, 2017 at 8:27 PM, Nick Coghlan <ncogh...@gmail.com> wrote:
>> Some possible problems that I've seen mentioned in the thread include:
>>
>> - pip doesn't trust build systems to properly support incremental
>> builds, so it wants to force it to throw away the build artifacts
>> after every build
>
> It's less that, and more pip wanting to ensure that the default
> publisher experience is reasonable close to the default end user
> experience, in order to increase the likelihood that publishers ship
> working sdists and wheel files, even if they haven't learned about the
> full suite of available pre-release testing tools yet (or have chosen
> not to use them).

This is exactly the opposite of what Paul says in his message posted
at about the same time as yours... AFAICT his argument is that build
artifact leakage is exactly what pip is worried about, and if anything
he's annoyed at me because he thinks I'm downplaying the problem :-).
(My impression is that Donald's position might be closer to what you
wrote, though.)

>> - pip wants to enforce builds going via sdists
>
> This isn't a requirement, just an option we want to enable (and can't
> avoid enabling).

Donald sure seemed to be insisting on it as a requirement earlier, at
least. And the *entire cause* of this whole discussion was conflict
between this requirement and flit not wanting to support building
sdists from unpacked sdists, so characterizing it as some automatic
thing that doesn't even need to be talked about seems really weird.

>> - Thomas / Ralf / I are frustrated at the idea of not supporting
>> incremental builds
>
> This is why we're allowing frontends to request in-place builds.

Wait, what? That's not what any of us asked for at all. Ralf and I
want incremental builds, which is orthogonal to the in-place versus
out-of-place distinction, and Thomas wants pip not to call sdist due
to some combination of inefficiency and lack-of-support-in-some-cases,
which is also orthogonal to the in-place versus out-of-place
distinction. (In retrospect I probably shouldn't have lumped Thomas /
Ralf / I together there, those really are different motivations,
though they lead to similar places.)

You're trying to shut me down by making these pronouncements about
what PEP 517 is going to be, and yet you don't seem to even understand
what requirements people are talking about. I'm sorry if that's rude,
and I'm not angry at you personally or anything, but I am frustrated
and I don't understand why I seem to have to keep throwing myself in
front of these ideas that seem so poorly motivated.

> And that's been the main discovery of the last round of discussions -
> we'd been talking past each other, and what we actually wanted was for
> the backend interface to accurately model the in-place/out-of-tree
> discussion that has been common to most build systems at least since
> autotools (hence my catalog of them earlier in the thread).

This statement seems just... completely wrong to me. I can't see any
way that the in-place/out-of-place distinction matches anything we
were talking about earlier. Have we been reading the same threads?
There was the whole thing about pip copying trees, of course, but
that's a completely different thing. The motivation there is that they
want to make sure that two builds don't accidentally influence each
other. If they don't trust the build system, then this requires
copying to a new tree (either via copytree or sdist). If they do trust
the build system, then there are other options -- you can do an
in-place build, or have a flag saying "please 'make clean' before this
build", or something. So out-of-place builds are either insufficient
or unnecessary for what pip wants. Copying the source tree and
out-of-place builds are completely different things with different use
cases; they happen to both involve external directories, but that's
mostly a false similarity I think.

And as for flit, it doesn't even have a distinction between in-place
and out-of-place builds...

> This means we're no longer attempting to invent anything new, we're
> just copying the extensive prior art around out-of-tree builds, and
> will deal with the consequences.

Forcing all build systems to support both in-place builds and
out-of-place builds adds substantial additional complexity, introduces
multiple new failure modes, and AFAICT is not very well suited to the
problems people have been worrying about.

> Regarding your questions:
>
> 1. What if backends get their out-of-tree support wrong?
>
> That's fine, it can be reported as a bug, fixed, and frontends and
> redistributors can use pip constraint files to enforce minimum
> versions even if publishers don't update their pyproject.toml files
> (plus frontends will grab the latest version of build backends by
> default).
>
> 2. What happens if re-using build directories isn't tested properly?
>
> I'd be genuinely surprised if any frontend ever did this by default
> (excluding in-place builds). Instead, it would be application
> integrators doing it as part of something like BitBucket Pipelines or
> OpenShift ImageStreams, and if it didn't work properly, they'd stop
> caching that particular directory.
>
> 3. What happens if an upgrade breaks incremental builds?
>
> The same thing that happens if an upgrade straight-up breaks: either
> it gets reported as a bug and fixed, or else end users figure out a
> workaround and move on.
>
> 4. Do we enforce not modifying the source directory?
>
> No. We don't even enforce backends not doing "rm -rf ~". If folks want
> anything like that enforced, then they still need to use ephemeral
> build servers.

These first 4 answers might be reasonable if it wasn't for the fact
that the *entire alleged motivation* for this feature is to reduce the
chance of accidental breakage. You can't justify it like that and then
hand-wave away all the new potential sources of accidental breakage
that it introduces...

> 5. What happens if you try to switch from in-place to out-of-place in
> one tree and it breaks?
>
> Don't do that, then (this is a publisher-only issue that won't impact
> end users).

This will certainly affect developers. The symptom is that you do the
equivalent of 'python setup.py build' in a source tree, and then later
do 'pip install .' in a source tree, and get screwy undefined behavior
because you're using a mainstream build system like cmake. At the very
least the PEP needs some language like "Frontends MUST NOT assume that
a given source tree can switch between in-place and out-of-place
builds; once they've issued one type of build against a given source
tree, they MUST stick with that type. One consequence of this is that
when given an arbitrary pre-existing source tree whose history is
unknown, frontends MUST NOT assume that they can perform either
in-place or out-of-place builds using that tree. In practice, this
means that frontends MUST explicitly query the user for which type of
build to use, because anything else risks either producing corrupt
builds or breaking the user's source tree with common build systems."

Or, well, that sounds pretty unusable, so maybe instead we would want
to go with the alternative: "Backends MUST support free switching
between in-place and out-of-place builds in the same directory" -- but
that's a whole 'nother likely source of weird problems, and breaks the
idea that this is something that existing build systems all support
already.

But IMO the one thing the PEP can't do is just stay silent on this and
pretend that everything will work out even if frontends and backends
are using incompatible interpretations. That'd be, like, malpractice.

> 6. Is native out-of-tree build support common in practice?
>
> Yes, as they're a requirement for inclusion in Debian.

Huh, interesting! Do you have a cite for this? I tried to find more
information, and all I found this advice for upstreams, which
explicitly discusses what they need from build systems that don't
support out-of-tree builds. It would be odd to include that if such
build systems were forbidden:
https://wiki.debian.org/UpstreamGuide#Cleaning_the_Tree

In any case, there's a huge difference between Debian wanting to take
a single static snapshot and build it several times from scratch, and
what's specified in the PEP right now which apparently allows for
incrementally re-using the same build tree while also incrementally
evolving the source being built. Most of the underspecified edge cases
that I brought up are ones that simply don't arise in Debian's use
case, but do arise in the PEP. This is why I'm unconvinced by the
argument that we're just adopting some old well-known idea -- when you
look at the details this proposal as written is much more ambitious
than any deployed system I'm aware of.

> 7. Why include in-place support in the API then?
>
> Because some folks (including you) would like to include incremental
> build support, and because if we don't support it explicitly backends
> will still have to deal with the "wheel_directory == build_directory"
> case.

Out-of-tree builds as currently specified are required to handle
incremental out-of-tree builds... maybe that's a mistake, but that's
what the text says.

I don't understand the second half of your sentence.

> 8. But what if we make a design mistake and can't fix it?
>
> Like all other recent PyPA specifications, PEP 517 will go through a
> Provisional acceptance period where it is accepted for implementation
> in the default toolset, but explicitly subject to revision based on
> that real world feedback.
>
> But even if something does still get through that second period of
> review, the whole reason we opted for the Python backend API over the
> CLI based one is that it's much easier to evolve (since we can do
> getattr checks and so forth, as well as straight up declarations of
> API version support)

It's *dramatically* easier to add than to remove, though.

> 9. Why not wait and then add a new backend capability requirement later?
>
> Waiting to add the requirement won't provide us with any more data
> than we already have, but may give backend implementors the impression
> they don't need to care about out-of-tree build support. This is also
> our first, last, and only chance to make out-of-tree build support a
> *mandatory* backend requirement that frontends can rely on - if we add
> it later, it will necessarily only be optional.

AFAICT making it optional is better for everyone, so not sure why
that's seen as a bad thing.

Analysis:
- If you're an eager backend dev who loves this stuff, you'll
implement it anyway, so it doesn't matter whether it's optional
- If you're a just-trying-to-hack-something-together backend dev maybe
constrained by some ugly legacy build system, then you'd much rather
it be optional because then you don't have to deal with hacking up
some fake "out-of-tree build" using copytree, and maybe getting it
wrong
- If you're pip, then AFAICT you're more worried about lazy backend
devs screwing things up than anything else, in which case you don't
want them hacking up their own fake "out-of-tree build" using
copytree, you want to take responsibility for that so you know that
you get it right
- If you're an automatic building pipeline, then knowing which
backends support "real" out-of-tree builds is *super valuable
information* because it means you don't have to waste disk/bandwidth
caching the "build tree" for backends that are just going to throw it
all away anyway

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
_______________________________________________
Distutils-SIG maillist  -  Distutils-SIG@python.org
https://mail.python.org/mailman/listinfo/distutils-sig

Reply via email to