Skip to content
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

Building a specific target can cause bad state #2904

Closed
spikefoo opened this issue Jan 8, 2017 · 7 comments
Closed

Building a specific target can cause bad state #2904

spikefoo opened this issue Jan 8, 2017 · 7 comments

Comments

@spikefoo
Copy link
Contributor

spikefoo commented Jan 8, 2017

(Using stack-1.3.2 on Arch Linux)

Steps to reproduce

Clone this sample project with two libraries: LibA, and LibB which depends on LibA.

$ ls
lib-a lib-b stack.yaml

Build with stack build, and run with stack exec lib-a-exe and stack exec lib-b-exe.

Next, change a function (named value) in LibA, and rebuild LibA only using stack build lib-a. Now lib-a-exe uses the updated function, but lib-b-exe still uses the old one, as expected.

Now try to rebuild LibB with stack build lib-b or stack build.

Expected

stack should update (relink?) LibB to use the new version of LibA.

Actual

stack never rebuilds LibB, causing it to forever use the old LibA.

This was suprising for me, because I thought stack build lib-a && stack build lib-b was equivalent to stack build. Instead, I found out it can result in a bad state where LibB is never rebuilt, forcing me to use one of these workarounds:

Workaround

After making a change in LibA and running stack build lib-a, either:

  • Change a source file in LibB, forcing a rebuild. Or:
  • Remove lib-b/.stack-work.

Alternatively, never build a specific target (e.g. stack build lib-a) in the first place. Always run stack build to build all targets.

@decentral1se
Copy link
Member

decentral1se commented Jan 20, 2017

I believe this use case was covered with stack build --force-dirty ?

  --[no-]force-dirty       Enable/disable Force treating all local packages as
                           having dirty files (useful for cases where stack
                           can't detect a file change

@spikefoo
Copy link
Contributor Author

It looks like stack build --force-dirty is a nicer alternative to the workaround of manually removing .stack-work.

But the issue still exists: stack build fails to rebuild a package after a dependency is updated and built using stack build $DEPENDENCY.

@mgsloan
Copy link
Contributor

mgsloan commented Feb 1, 2017

I can indeed reproduce this, and I agree that it's a bug. Marking it as a P1 issue since it violates consistency that ought to be there.

@snoyberg
Copy link
Contributor

snoyberg commented Mar 7, 2017

This reminds me of haskell/cabal#2830. And in fact I'm seeing something very similar. When I do the initial stack build, I end up with the following package IDs:

id: lib-a-0.1.0.0-AeObfw0jAOe7kZzV2FkbDJ
key: lib-a-0.1.0.0-AeObfw0jAOe7kZzV2FkbDJ
id: lib-b-0.1.0.0-xc7uosuJA3EKtusB0zBjI
key: lib-b-0.1.0.0-xc7uosuJA3EKtusB0zBjI

If I modified the LibA.hs file and rebuild, I get exactly the same id and key. This is the cause of the problem here. When you run stack build lib-a, Stack unregisters lib-a, rebuilds it, and registers it. When you run stack build lib-b, the package looks valid, because its dependency (lib-a) is still present in the database with the same ID.

This is really a Cabal or GHC bug (it should generate unique package IDs if the package contents change). A simple workaround would be to aggressively unregister all users of a package when unregistering the dependency.

snoyberg added a commit that referenced this issue Mar 7, 2017
The previous commit (fixing #2904) made the Maybe layer confusing and
error-prone. It was too easy to end up accidentally skipping an
unregister based on the two levels of Maybe wrapping. This simplifies
the codebase, without any change in behavior.

It would be even nicer to be able to prove statically that we always
generate a dirty reason.
@snoyberg
Copy link
Contributor

snoyberg commented Mar 7, 2017

Please see #3047, which should fix this.

@snoyberg
Copy link
Contributor

snoyberg commented Mar 7, 2017

It looks like Cabal is using the package key as the package id as well. The key depends only on the dependencies of the build, not the output, which would explain this bug. I'll try to repro against latest cabal and report upstream.

@snoyberg
Copy link
Contributor

snoyberg commented Mar 8, 2017

Fixed by #3047. Cabal is saying what I thought they would: the meaning of package IDs has changed. I'm not too happy with that, but as usual we have no control over such things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants