From 9c13b192ae9f0eb3b445fa9d310b2b9f4197b735 Mon Sep 17 00:00:00 2001
From: Moritz Angermann <moritz.angermann@gmail.com>
Date: Sun, 19 Nov 2017 19:15:05 +0800
Subject: [PATCH] Add support for relative lookup of template-hsc.h (#2)

If the `IN_GHC_TREE` CPP macro is defined (controlled by the `in-ghc-tree` cabal flag),
as a last resort, we also try to locate the template relative to the location of the currently
executed `hsc2hs`. Note that this is a hack to work around
only partial relocatable support in cabal, and is here to allow the `hsc2hs`
built and shipped with ghc to be relocatable with the ghc
binary distribution it ships with.

Note that on Windows, `getExecutablePath` doesn't yet operate correctly
in the presence of symlinks; but this should note have any detrimental
effects. This will be fixed/improved in future `base` version.
---
 Main.hs      | 54 +++++++++++++++++++++++++++++++++++++++++++---------
 hsc2hs.cabal |  9 ++++++++-
 2 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/Main.hs b/Main.hs
index 08dab3f..fad7aac 100644
--- a/Main.hs
+++ b/Main.hs
@@ -13,6 +13,17 @@ import Control.Monad            ( liftM, forM_ )
 import Data.List                ( isSuffixOf )
 import System.Console.GetOpt
 
+-- If we ware building the hsc2hs
+-- binary for binary distribution
+-- in the GHC tree.  Obtain
+-- the path to the @$topdir/lib@
+-- folder, and try to locate the
+-- @template-hsc.h@ there.
+--
+-- XXX: Note this does not work
+--      on windows due to for
+--      symlinks. See Trac #14483.
+
 #if defined(mingw32_HOST_OS)
 import Foreign
 import Foreign.C.String
@@ -26,8 +37,11 @@ import System.IO
 #ifdef BUILD_NHC
 import System.Directory         ( getCurrentDirectory )
 #else
-import Data.Version             ( showVersion )
-import Paths_hsc2hs as Main     ( getDataFileName, version )
+import Paths_hsc2hs as Main     ( getDataFileName )
+#endif
+#if defined(IN_GHC_TREE)
+import System.Environment       ( getExecutablePath )
+import System.FilePath          ( takeDirectory, (</>) )
 #endif
 
 import Common
@@ -49,12 +63,10 @@ import HSCParser
 #ifdef BUILD_NHC
 getDataFileName s = do here <- getCurrentDirectory
                        return (here++"/"++s)
-version = "0.67" -- TODO!!!
-showVersion = id
 #endif
 
 versionString :: String
-versionString = "hsc2hs version " ++ showVersion version ++ "\n"
+versionString = "hsc2hs version " ++ CURRENT_PACKAGE_VERSION ++ "\n"
 
 main :: IO ()
 main = do
@@ -141,6 +153,13 @@ findTemplate usage mb_libdir config
      --
      -- Next we try the location we told Cabal about.
      --
+     -- If IN_GHC_TREE is defined (-fin-ghc-tree), we also try to locate
+     -- the template in the `baseDir`, as provided by the `ghc-boot`
+     -- library. Note that this is a hack to work around only partial
+     -- relocatable support in cabal, and is here to allow the hsc2hs
+     -- built and shipped with ghc to be relocatable with the ghc
+     -- binary distribution it ships with.
+     --
      -- If neither of the above work, then hopefully we're on Unix and
      -- there's a wrapper script which specifies an explicit template flag.
      mb_templ1 <-
@@ -157,14 +176,31 @@ findTemplate usage mb_libdir config
          if exists1
             then return $ Just (templ1, CompFlag ("-I" ++ incl))
             else return Nothing
-     case mb_templ1 of
+     mb_templ2 <- case mb_templ1 of
          Just (templ1, incl) ->
-             return (templ1, [incl])
+             return $ Just (templ1, [incl])
          Nothing -> do
              templ2 <- getDataFileName "template-hsc.h"
              exists2 <- doesFileExist templ2
-             if exists2 then return (templ2, [])
-                        else die ("No template specified, and template-hsc.h not located.\n\n" ++ usage)
+             if exists2
+                then return $ Just (templ2, [])
+                else return Nothing
+     case mb_templ2 of
+         Just x -> return x
+#if defined(IN_GHC_TREE)
+         Nothing -> do
+             -- XXX: this will *not* work on windows for symlinks, until `getExecutablePath` in `base` is
+             --      fixed. The alternative would be to bring the whole logic from the SysTools module in here
+             --      which is rather excessive. See Trac #14483.
+             let getBaseDir = Just . (\p -> p </> "lib") . takeDirectory . takeDirectory <$> getExecutablePath
+             mb_templ3 <- fmap (</> "template-hsc.h") <$> getBaseDir
+             mb_exists3 <- mapM doesFileExist mb_templ3
+             case (mb_templ3, mb_exists3) of
+                 (Just templ3, Just True) -> return (templ3, [])
+                 _ -> die ("No template specified, and template-hsc.h not located.\n\n" ++ usage)
+#else
+         Nothing -> die ("No template specified, and template-hsc.h not located.\n\n" ++ usage)
+#endif
 
 findCompiler :: Maybe FilePath -> ConfigM Maybe -> IO FilePath
 findCompiler mb_libdir config
diff --git a/hsc2hs.cabal b/hsc2hs.cabal
index c6ca492..99d5072 100644
--- a/hsc2hs.cabal
+++ b/hsc2hs.cabal
@@ -1,5 +1,5 @@
 Name: hsc2hs
-Version: 0.68.2
+Version: 0.68.3
 Copyright: 2000, Marcin Kowalczyk
 License: BSD3
 License-File: LICENSE
@@ -26,6 +26,11 @@ cabal-version: >=1.10
 extra-source-files: changelog.md
 tested-with: GHC==8.2.1, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2, GHC==7.0.4
 
+flag in-ghc-tree
+  description: Are we in a GHC tree?
+  default: False
+  manual: True
+
 source-repository head
     Type: git
     Location: http://git.haskell.org/hsc2hs.git
@@ -50,4 +55,6 @@ Executable hsc2hs
                    directory  >= 1   && < 1.4,
                    filepath   >= 1   && < 1.5,
                    process    >= 1.1 && < 1.7
+    if flag(in-ghc-tree)
+       cpp-options: -DIN_GHC_TREE
 
-- 
GitLab