Dep tracking fails to detect changed build-tools
- Dominant language
- Haskell
- Stars
- 1.7k
- Forks
- 750
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 28
Description
TLDR: `new-build` doesn't properly track build-tool version as input-dependency for generation
Consider the following package:
```
name: issue4609
version: 0
build-type: Simple
cabal-version: >=1.10
flag broken
default: True
manual: True
executable exe1
hs-source-dirs: src
other-modules: Double
main-is: Main.hs
build-depends: base, array, bytestring
if flag(broken)
build-tools: alex == 3.2.1
else
build-tools: alex == 3.1.4
default-language: Haskell2010
```
```hs
-- src/Double.x
{
module Double (readDouble) where
-- stolen from bytestring-lexing
import qualified Data.ByteString as B
import qualified Data.ByteString.Unsafe as B
}
%wrapper "strict-bytestring"
$space = [\ \t\xa0]
$digit = 0-9
$octit = 0-7
$hexit = [$digit A-F a-f]
@sign = [\-\+]
@decimal = $digit+
@octal = $octit+
@hexadecimal = $hexit+
@exponent = [eE] [\-\+]? @decimal
@number = @decimal
| @decimal \. @decimal @exponent?
| @decimal @exponent
| 0[oO] @octal
| 0[xX] @hexadecimal
lex :-
@sign? @number { strtod }
{
readDouble :: B.ByteString -> Maybe (Double, B.ByteString)
readDouble str = case alexScan (AlexInput '\n' str) 0 of
AlexEOF -> Nothing
AlexError _ -> Nothing
AlexToken (AlexInput _ rest) n _ ->
case strtod (B.unsafeTake n str) of d -> d `seq` Just $! (d , rest)
strtod :: B.ByteString -> Double
strtod = undefined
}
```
```hs
-- src/Main.hs
import Double ()
main :: IO ()
main = return ()
```
----
The package defined above is expected to
- succeed building whenever the `broken` flag is unset, and
- fail building whenever the `broken` flag is set.
In fact, compiling this package for the first time with broken=True fails as expected:
```
$ cabal new-build --flag=+broken
Resolving dependencies...
Build profile: with-compiler: ghc-8.0.2, optimisation: NormalOptimisation
In order, the following will be built (use -v for more details):
- issue4609-0 {issue4609-0-inplace-exe1} (exe:exe1) (first run)
Configuring executable 'exe1' for issue4609-0..
Preprocessing executable 'exe1' for issue4609-0..
Building executable 'exe1' for issue4609-0..
[1 of 2] Compiling Double ( /tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1-tmp/Double.hs, /tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1-tmp/Double.o )
src/Double.x:37:16: error:
• The constructor ‘AlexInput’ should have 3 arguments, but has been given 2
• In the pattern: AlexInput _ rest
In the pattern: AlexToken (AlexInput _ rest) n _
In a case alternative:
AlexToken (AlexInput _ rest) n _
-> case strtod (ByteString.unsafeTake n str) of {
d -> d `seq` Just $! (d, rest) }
```
However, switching the `broken` flag off doesn't have the expected effect:
```
$ cabal new-build --flag=-broken
Resolving dependencies...
Build profile: with-compiler: ghc-8.0.2, optimisation: NormalOptimisation
In order, the following will be built (use -v for more details):
- issue4609-0 {issue4609-0-inplace-exe1} (exe:exe1) -broken (configuration changed)
Configuring executable 'exe1' for issue4609-0..
Preprocessing executable 'exe1' for issue4609-0..
Building executable 'exe1' for issue4609-0..
[1 of 2] Compiling Double ( /tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1-tmp/Double.hs, /tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1-tmp/Double.o )
src/Double.x:37:16: error:
• The constructor ‘AlexInput’ should have 3 arguments, but has been given 2
• In the pattern: AlexInput _ rest
In the pattern: AlexToken (AlexInput _ rest) n _
In a case alternative:
AlexToken (AlexInput _ rest) n _
-> case strtod (ByteString.unsafeTake n str) of {
d -> d `seq` Just $! (d, rest) }
```
However, if we remove the `dist-newstyle` folder, and retry, the `Double.hs` file gets regenerated with the proper version of Alex, and things work as expected:
```
$ rm -rf dist-newstyle/; cabal new-build --flag=-broken
Resolving dependencies...
Build profile: with-compiler: ghc-8.0.2, optimisation: NormalOptimisation
In order, the following will be built (use -v for more details):
- issue4609-0 {issue4609-0-inplace-exe1} (exe:exe1) -broken (first run)
Configuring executable 'exe1' for issue4609-0..
Preprocessing executable 'exe1' for issue4609-0..
Building executable 'exe1' for issue4609-0..
[1 of 2] Compiling Double ( /tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1-tmp/Double.hs, /tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1-tmp/Double.o )
/tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1-tmp/Double.hs:412:1: warning: [-Wtabs]
Tab character found here, and in 44 further locations.
Please use spaces instead.
[2 of 2] Compiling Main ( src/Main.hs, /tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1-tmp/Main.o )
Linking /tmp/yyy/dist-newstyle/build/x86_64-linux/ghc-8.0.2/issue4609-0/c/exe1/build/exe1/exe1 ...
```
However, if we switch on `broken` again, then again the Double.hs lexer doesn't get regenerated as it should, and `new-build` succeeds even though it should not have succeded:
```
$ cabal new-build --flag=+broken
Resolving dependencies...
Build profile: with-compiler: ghc-8.0.2, optimisation: NormalOptimisation
In order, the following will be built (use -v for more details):
- issue4609-0 {issue4609-0-inplace-exe1} (exe:exe1) (configuration changed)
Configuring executable 'exe1' for issue4609-0..
Preprocessing executable 'exe1' for issue4609-0..
Building executable 'exe1' for issue4609-0..
```
Contributor guide
Assessment
This issue has not been assessed yet.