diff --git a/ChangeLog.md b/ChangeLog.md index 2e2db02d85..0356756128 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -36,6 +36,9 @@ Behavior changes: without an accompanying `-RTS`. * When auto-detecting `--ghc-build`, `tinfo6` is now preferred over `standard` if both versions of libtinfo are installed +* Addition of `stack build --copy-compiler-tool`, to allow tools like + intero to be installed globally for a particular compiler. + [#2643](https://github.com/commercialhaskell/stack/issues/2643) Other enhancements: diff --git a/src/Stack/Build/ConstructPlan.hs b/src/Stack/Build/ConstructPlan.hs index fbf03c5518..cf2b68edde 100644 --- a/src/Stack/Build/ConstructPlan.hs +++ b/src/Stack/Build/ConstructPlan.hs @@ -208,7 +208,8 @@ constructPlan ls0 baseConfigOpts0 locals extraToBuild0 localDumpPkgs loadPackage , planFinals = M.fromList finals , planUnregisterLocal = mkUnregisterLocal tasks dirtyReason localDumpPkgs sourceMap initialBuildSteps , planInstallExes = - if boptsInstallExes $ bcoBuildOpts baseConfigOpts0 + if boptsInstallExes (bcoBuildOpts baseConfigOpts0) || + boptsInstallCompilerTool (bcoBuildOpts baseConfigOpts0) then installExes else Map.empty } diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 22ddb03c96..7baa05ae4a 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -509,7 +509,10 @@ copyExecutables exes | Map.null exes = return () copyExecutables exes = do snapBin <- ( bindirSuffix) `liftM` installationRootDeps localBin <- ( bindirSuffix) `liftM` installationRootLocal - destDir <- view $ configL.to configLocalBin + compilerSpecific <- boptsInstallCompilerTool <$> view buildOptsL + destDir <- if compilerSpecific + then bindirCompilerTools + else view $ configL.to configLocalBin ensureDir destDir destDir' <- liftIO . D.canonicalizePath . toFilePath $ destDir @@ -560,7 +563,7 @@ copyExecutables exes = do , T.pack destDir' , ":"] forM_ installed $ \exe -> $logInfo ("- " <> exe) - warnInstallSearchPathIssues destDir' installed + unless compilerSpecific $ warnInstallSearchPathIssues destDir' installed -- | Windows can't write over the current executable. Instead, we rename the diff --git a/src/Stack/Config/Build.hs b/src/Stack/Config/Build.hs index 2091b244ae..45fbbca642 100644 --- a/src/Stack/Config/Build.hs +++ b/src/Stack/Config/Build.hs @@ -43,6 +43,9 @@ buildOptsFromMonoid BuildOptsMonoid{..} = BuildOpts , boptsInstallExes = fromFirst (boptsInstallExes defaultBuildOpts) buildMonoidInstallExes + , boptsInstallCompilerTool = fromFirst + (boptsInstallCompilerTool defaultBuildOpts) + buildMonoidInstallCompilerTool , boptsPreFetch = fromFirst (boptsPreFetch defaultBuildOpts) buildMonoidPreFetch diff --git a/src/Stack/Options/BuildMonoidParser.hs b/src/Stack/Options/BuildMonoidParser.hs index 973ac39139..aa401cf7b0 100644 --- a/src/Stack/Options/BuildMonoidParser.hs +++ b/src/Stack/Options/BuildMonoidParser.hs @@ -18,8 +18,9 @@ buildOptsMonoidParser hide0 = libProfiling <*> exeProfiling <*> libStripping <*> exeStripping <*> haddock <*> haddockOptsParser hideBool <*> openHaddocks <*> haddockDeps <*> haddockInternal <*> - haddockHyperlinkSource <*> copyBins <*> preFetch <*> keepGoing <*> - forceDirty <*> tests <*> testOptsParser hideBool <*> benches <*> + haddockHyperlinkSource <*> copyBins <*> copyCompilerTool <*> + preFetch <*> keepGoing <*> forceDirty <*> + tests <*> testOptsParser hideBool <*> benches <*> benchOptsParser hideBool <*> reconfigure <*> cabalVerbose <*> splitObjs <*> skipComponents where hideBool = hide0 /= BuildCmdGlobalOpts @@ -62,7 +63,6 @@ buildOptsMonoidParser hide0 = \debuggers/profiling tools/other utilities that use \ \debugging symbols." <> hideExceptGhci) - libProfiling = firstBoolFlags "library-profiling" @@ -110,6 +110,11 @@ buildOptsMonoidParser hide0 = "copy-bins" "copying binaries to the local-bin-path (see 'stack path')" hide + copyCompilerTool = + firstBoolFlags + "copy-compiler-tool" + "copying binaries of targets to compiler-tools-bin (see 'stack path')" + hide keepGoing = firstBoolFlags "keep-going" diff --git a/src/Stack/Path.hs b/src/Stack/Path.hs index 6c8669f2d7..d0ea3583b3 100644 --- a/src/Stack/Path.hs +++ b/src/Stack/Path.hs @@ -50,6 +50,7 @@ path keys = global <- GhcPkg.getGlobalDB menv whichCompiler snaproot <- installationRootDeps localroot <- installationRootLocal + toolsDir <- bindirCompilerTools distDir <- distRelativeDir hpcDir <- hpcReportDir compiler <- getCompilerPath whichCompiler @@ -83,6 +84,7 @@ path keys = global snaproot localroot + toolsDir distDir hpcDir extra @@ -107,6 +109,7 @@ data PathInfo = PathInfo , piGlobalDb :: Path Abs Dir , piSnapRoot :: Path Abs Dir , piLocalRoot :: Path Abs Dir + , piToolsDir :: Path Abs Dir , piDistDir :: Path Rel Dir , piHpcDir :: Path Abs Dir , piExtraDbs :: [Path Abs Dir] @@ -155,6 +158,9 @@ paths = , ( "Directory containing the compiler binary (e.g. ghc)" , "compiler-bin" , T.pack . toFilePathNoTrailingSep . parent . piCompiler ) + , ( "Directory containing binaries specific to a particular compiler (e.g. intero)" + , "compiler-tools-bin" + , T.pack . toFilePathNoTrailingSep . piToolsDir ) , ( "Local bin dir where stack installs executables (e.g. ~/.local/bin)" , "local-bin" , view $ configL.to configLocalBin.to toFilePathNoTrailingSep.to T.pack) diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs index 73d7170d96..51bd8576e4 100644 --- a/src/Stack/Types/Config.hs +++ b/src/Stack/Types/Config.hs @@ -116,6 +116,7 @@ module Stack.Types.Config ,hpcReportDir ,installationRootDeps ,installationRootLocal + ,bindirCompilerTools ,hoogleRoot ,hoogleDatabasePath ,packageDatabaseDeps @@ -1232,6 +1233,20 @@ installationRootLocal = do psc <- useShaPathOnWindows =<< platformSnapAndCompilerRel return $ workDir $(mkRelDir "install") psc +-- | Installation root for compiler tools +bindirCompilerTools :: (MonadThrow m, MonadReader env m, HasEnvConfig env) => m (Path Abs Dir) +bindirCompilerTools = do + config <- view configL + platform <- platformGhcRelDir + compilerVersion <- envConfigCompilerVersion <$> view envConfigL + compiler <- parseRelDir $ compilerVersionString compilerVersion + return $ + configStackRoot config + $(mkRelDir "compiler-tools") + platform + compiler + bindirSuffix + -- | Hoogle directory. hoogleRoot :: (MonadThrow m, MonadReader env m, HasEnvConfig env) => m (Path Abs Dir) hoogleRoot = do @@ -1376,9 +1391,10 @@ extraBinDirs :: (MonadThrow m, MonadReader env m, HasEnvConfig env) extraBinDirs = do deps <- installationRootDeps local <- installationRootLocal + tools <- bindirCompilerTools return $ \locals -> if locals - then [local bindirSuffix, deps bindirSuffix] - else [deps bindirSuffix] + then [local bindirSuffix, deps bindirSuffix, tools] + else [deps bindirSuffix, tools] -- | Get the minimal environment override, useful for just calling external -- processes like git or ghc diff --git a/src/Stack/Types/Config/Build.hs b/src/Stack/Types/Config/Build.hs index fcd231fc29..15301dae01 100644 --- a/src/Stack/Types/Config/Build.hs +++ b/src/Stack/Types/Config/Build.hs @@ -57,6 +57,8 @@ data BuildOpts = -- @hscolour@. Disable for no sources. ,boptsInstallExes :: !Bool -- ^ Install executables to user path after building? + ,boptsInstallCompilerTool :: !Bool + -- ^ Install executables to compiler tools path after building? ,boptsPreFetch :: !Bool -- ^ Fetch all packages immediately -- ^ Watch files for changes and automatically rebuild @@ -100,6 +102,7 @@ defaultBuildOpts = BuildOpts , boptsHaddockInternal = False , boptsHaddockHyperlinkSource = True , boptsInstallExes = False + , boptsInstallCompilerTool = False , boptsPreFetch = False , boptsKeepGoing = Nothing , boptsForceDirty = False @@ -166,6 +169,7 @@ data BuildOptsMonoid = BuildOptsMonoid , buildMonoidHaddockInternal :: !(First Bool) , buildMonoidHaddockHyperlinkSource :: !(First Bool) , buildMonoidInstallExes :: !(First Bool) + , buildMonoidInstallCompilerTool :: !(First Bool) , buildMonoidPreFetch :: !(First Bool) , buildMonoidKeepGoing :: !(First Bool) , buildMonoidForceDirty :: !(First Bool) @@ -195,6 +199,7 @@ instance FromJSON (WithJSONWarnings BuildOptsMonoid) where buildMonoidHaddockInternal <- First <$> o ..:? buildMonoidHaddockInternalArgName buildMonoidHaddockHyperlinkSource <- First <$> o ..:? buildMonoidHaddockHyperlinkSourceArgName buildMonoidInstallExes <- First <$> o ..:? buildMonoidInstallExesArgName + buildMonoidInstallCompilerTool <- First <$> o ..:? buildMonoidInstallCompilerToolArgName buildMonoidPreFetch <- First <$> o ..:? buildMonoidPreFetchArgName buildMonoidKeepGoing <- First <$> o ..:? buildMonoidKeepGoingArgName buildMonoidForceDirty <- First <$> o ..:? buildMonoidForceDirtyArgName @@ -241,6 +246,9 @@ buildMonoidHaddockHyperlinkSourceArgName = "haddock-hyperlink-source" buildMonoidInstallExesArgName :: Text buildMonoidInstallExesArgName = "copy-bins" +buildMonoidInstallCompilerToolArgName :: Text +buildMonoidInstallCompilerToolArgName = "copy-compiler-tool" + buildMonoidPreFetchArgName :: Text buildMonoidPreFetchArgName = "prefetch" diff --git a/test/integration/tests/2643-copy-compiler-tool/Main.hs b/test/integration/tests/2643-copy-compiler-tool/Main.hs new file mode 100644 index 0000000000..303ca4a5e2 --- /dev/null +++ b/test/integration/tests/2643-copy-compiler-tool/Main.hs @@ -0,0 +1,56 @@ +import StackTest +import System.Directory + +main :: IO () +main = do + -- init + stack ["init", defaultResolverArg] + + -- place to throw some exes + createDirectory "binny" + + -- check assumptions on exec and the build flags and clean + stack ["build", "--flag", "*:build-baz"] + stack ["exec", "--", "baz-exe" ++ exeExt] + stackErr ["exec", "--", "bar-exe" ++ exeExt] + stack ["clean", "--full"] + stackErr ["exec", "--", "baz-exe" ++ exeExt] + + -- install one exe normally + stack ["install", + "--local-bin-path", "./binny", + "--flag", "*:build-foo" + ] + + -- and install two compiler-tools, opposite ways + -- (build or install) + stack ["build", + "--local-bin-path", "./binny", + "--copy-compiler-tool", + "--flag", "*:build-bar" + ] + stack ["install", + "--local-bin-path", "./binny", + "--copy-compiler-tool", + "--flag", "*:build-baz" + ] + + -- nuke the built things that go in .stack-work/, so we can test if + -- the installed ones exist for sure + stack ["clean", "--full"] + + -- bar and baz were installed as compiler tools, should work fine + stack ["exec", "--", "bar-exe" ++ exeExt] + stack ["exec", "--", "baz-exe" ++ exeExt] + + -- foo was installed as a normal exe (in .binny/, which can't be on PATH), + -- so shouldn't + stackErr ["exec", "--", "foo-exe" ++ exeExt] + + -- check existences make sense + doesExist $ "./binny/foo-exe" ++ exeExt + doesNotExist $ "./binny/bar-exe" ++ exeExt + doesNotExist $ "./binny/baz-exe" ++ exeExt + + -- just check that this exists + stack ["path", "--compiler-tools-bin"] diff --git a/test/integration/tests/2643-copy-compiler-tool/files/Bar.hs b/test/integration/tests/2643-copy-compiler-tool/files/Bar.hs new file mode 100644 index 0000000000..7498d2965c --- /dev/null +++ b/test/integration/tests/2643-copy-compiler-tool/files/Bar.hs @@ -0,0 +1 @@ +main = putStrLn "twotwotwo" diff --git a/test/integration/tests/2643-copy-compiler-tool/files/Baz.hs b/test/integration/tests/2643-copy-compiler-tool/files/Baz.hs new file mode 100644 index 0000000000..3f276659c9 --- /dev/null +++ b/test/integration/tests/2643-copy-compiler-tool/files/Baz.hs @@ -0,0 +1 @@ +main = putStrLn "threethreethree" diff --git a/test/integration/tests/2643-copy-compiler-tool/files/Foo.hs b/test/integration/tests/2643-copy-compiler-tool/files/Foo.hs new file mode 100644 index 0000000000..8abe1be7d5 --- /dev/null +++ b/test/integration/tests/2643-copy-compiler-tool/files/Foo.hs @@ -0,0 +1 @@ +main = putStrLn "oneoneone" diff --git a/test/integration/tests/2643-copy-compiler-tool/files/LICENSE b/test/integration/tests/2643-copy-compiler-tool/files/LICENSE new file mode 100644 index 0000000000..08ca20674b --- /dev/null +++ b/test/integration/tests/2643-copy-compiler-tool/files/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2017 + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Your name here nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/test/integration/tests/2643-copy-compiler-tool/files/Setup.hs b/test/integration/tests/2643-copy-compiler-tool/files/Setup.hs new file mode 100644 index 0000000000..9a994af677 --- /dev/null +++ b/test/integration/tests/2643-copy-compiler-tool/files/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/test/integration/tests/2643-copy-compiler-tool/files/copy-compiler-tool-test.cabal b/test/integration/tests/2643-copy-compiler-tool/files/copy-compiler-tool-test.cabal new file mode 100644 index 0000000000..e1f66caf91 --- /dev/null +++ b/test/integration/tests/2643-copy-compiler-tool/files/copy-compiler-tool-test.cabal @@ -0,0 +1,54 @@ +name: copy-compiler-tool-test +version: 0.1.0.0 +synopsis: Initial project template from stack +description: Please see README.md +homepage: http://invalid/ +license: BSD3 +license-file: LICENSE +author: Your name here +maintainer: your.address@example.com +-- copyright: +category: Web +build-type: Simple +-- extra-source-files: +cabal-version: >=1.10 + +flag build-foo + manual: True + default: False + description: Build foo + +flag build-bar + manual: True + default: False + description: Build bar + +flag build-baz + manual: True + default: False + description: Build baz + +executable foo-exe + main-is: Foo.hs + build-depends: base + default-language: Haskell2010 + if !flag(build-foo) + buildable: False + +executable bar-exe + main-is: Bar.hs + build-depends: base + default-language: Haskell2010 + if !flag(build-bar) + buildable: False + +executable baz-exe + main-is: Baz.hs + build-depends: base + default-language: Haskell2010 + if !flag(build-baz) + buildable: False + +source-repository head + type: git + location: https://invalid/