about summary refs log tree commit diff
path: root/third_party/bazel/rules_haskell/tools/runfiles/src/Bazel/Runfiles.hs
blob: 8dfb980e1801b74f51358597e9d46c5e14341d9f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
-- | This module enables finding data dependencies ("runfiles") of Haskell
-- binaries at runtime.
--
-- For more information, see: https://github.com/bazelbuild/bazel/issues/4460
--
-- Note: this does not currently support the RUNFILES_MANIFEST environmental
-- variable.  However, that's only necessary on Windows, which rules_haskell
-- doesn't support yet.
--
-- Additionally, this is not yet supported by the REPL.
module Bazel.Runfiles
    ( Runfiles
    , create
    , rlocation
    , env
    ) where

import System.Directory (doesDirectoryExist)
import System.Environment (getExecutablePath, lookupEnv)
import System.FilePath (FilePath, (</>), (<.>))

-- | A path to a directory tree containing runfiles for the given
newtype Runfiles = Runfiles FilePath
    deriving Show

-- | Construct a path to a data dependency within the given runfiles.
--
-- For example: @rlocation \"myworkspace/mypackage/myfile.txt\"@
rlocation :: Runfiles -> FilePath -> FilePath
rlocation (Runfiles f) g = f </> g

-- | Set environmental variables for locating the given runfiles directory.
--
-- Note that Bazel will set these automatically when it runs tests
-- (@bazel test@).  However, it will not automatically set them
-- during "bazel run"; thus, non-test binaries should set the
-- environment manually for processes that they call.
env :: Runfiles -> [(String, String)]
env (Runfiles f) = [(runfilesDirEnv, f)]

runfilesDirEnv :: String
runfilesDirEnv = "RUNFILES_DIR"

-- | Locate the runfiles directory for the current binary.
--
-- This behaves according to the specification in:
-- https://docs.google.com/document/d/e/2PACX-1vSDIrFnFvEYhKsCMdGdD40wZRBX3m3aZ5HhVj4CtHPmiXKDCxioTUbYsDydjKtFDAzER5eg7OjJWs3V/pub
--
-- Note: it does not currently support the @RUNFILES_MANIFEST@ environmental
-- variable.  However, that's only necessary on Windows, which rules_haskell
-- doesn't support yet anyway.
create :: IO Runfiles
create = do
    exeRunfilesPath <- fmap (<.> "runfiles") getExecutablePath
    exeRunfilesExists <- doesDirectoryExist exeRunfilesPath
    if exeRunfilesExists
      then return $ Runfiles exeRunfilesPath
      else do
        envDir <- lookupEnv runfilesDirEnv
        case envDir of
            Just f -> return $ Runfiles f
            Nothing -> error "Unable to locate runfiles directory"