Skip to content

Commit

Permalink
Add a library for looking up runfiles.
Browse files Browse the repository at this point in the history
Relevant Bazel issue: bazelbuild/bazel#4460.

I followed the approach documented here:
https://docs.google.com/document/d/e/2PACX-1vSDIrFnFvEYhKsCMdGdD40wZRBX3m3aZ5HhVj4CtHPmiXKDCxioTUbYsDydjKtFDAzER5eg7OjJWs3V/pub
Other than not bothing yet with `RUNFILES_MANIFEST`, which is only needed on
WINDOWS.
  • Loading branch information
judah committed Jun 8, 2018
1 parent 730d42c commit 60b9f8f
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 0 deletions.
42 changes: 42 additions & 0 deletions tools/runfiles/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
load(
"@io_tweag_rules_haskell//haskell:haskell.bzl",
"haskell_binary",
"haskell_library",
"haskell_test",
)

haskell_library(
name = "runfiles",
srcs = ["Bazel/Runfiles.hs"],
prebuilt_dependencies = [
"base",
"directory",
"filepath",
],
visibility = ["//visibility:public"],
)

haskell_binary(
name = "bin",
srcs = ["Bin.hs"],
main_file = "Bin.hs",
deps = [":runfiles"],
data = ["bin-data.txt"],
prebuilt_dependencies = [
"base",
"filepath",
],
testonly = 1,
)
haskell_test(
name = "test",
srcs = ["Test.hs"],
main_file = "Test.hs",
deps = [":runfiles"],
data = ["test-data.txt", ":bin"],
prebuilt_dependencies = [
"base",
"filepath",
"process",
],
)
63 changes: 63 additions & 0 deletions tools/runfiles/Bazel/Runfiles.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
-- | 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
, getRunfiles
, rlocation
, runfilesEnv
) 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@).
runfilesEnv :: Runfiles -> [(String, String)]
runfilesEnv (Runfiles f) = [(runfilesDirEnv, f)]

runfilesDirEnv :: String
runfilesDirEnv = "RUNFILES_DIR"

-- | Locate the runfiles directory for the current binary.
--
-- This behaves according ot 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.
getRunfiles :: IO Runfiles
getRunfiles = 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"



13 changes: 13 additions & 0 deletions tools/runfiles/Bin.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Main (main) where

import Bazel.Runfiles
import Control.Monad (when)
import System.FilePath ((</>))

main :: IO ()
main = do
r <- getRunfiles
bar <- readFile (rlocation r "io_tweag_rules_haskell/tools/runfiles/bin-data.txt")
when (lines bar /= ["bar"]) -- ignore trailing newline
$ error $ "Incorrect contents: got: " ++ show bar

15 changes: 15 additions & 0 deletions tools/runfiles/Test.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Main (main) where

import Bazel.Runfiles
import Control.Monad (when)
import System.FilePath ((</>))
import System.Process (callProcess)


main :: IO ()
main = do
r <- getRunfiles
foo <- readFile (rlocation r "io_tweag_rules_haskell/tools/runfiles/test-data.txt")
when (lines foo /= ["foo"]) -- ignore trailing newline
$ error $ "Incorrect contents: got: " ++ show foo
callProcess (rlocation r "io_tweag_rules_haskell/tools/runfiles/bin") []
1 change: 1 addition & 0 deletions tools/runfiles/bin-data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
1 change: 1 addition & 0 deletions tools/runfiles/test-data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo

0 comments on commit 60b9f8f

Please sign in to comment.