building a helper binary with cabal

Evan Martin martine at
Thu Apr 3 00:07:32 EDT 2008

I got caught up in other things, so I'm also late to reply.

Here's the whole story now, so you don't have to reskim the archive.
My program has a helper executable that's built with gcc.  I want to
install it alongside my Haskell binary.  I can write a post-copy hook
like this:

> creplChildCopy :: Args -> CopyFlags -> PackageDescription
>                -> LocalBuildInfo -> IO ()
> creplChildCopy args flags desc buildinfo = do
>   print "copy hook"
>   let dirs = absoluteInstallDirs desc buildinfo (copyDest flags)
>   print ("copying child to ", libexecdir dirs </> creplChildName)
>   copyFileVerbose (copyVerbose flags) (creplChildPath buildinfo)
>                   (libexecdir dirs </> creplChildName)

And then run it like this:

$ ./Setup.lhs copy -v3
directory dist/doc/html/c-repl does exist: False
Creating /home/martine/.local/share/doc/c-repl-0.1 (and its parents)
copy LICENSE to /home/martine/.local/share/doc/c-repl-0.1/LICENSE
Installing: /home/martine/.local/bin
Creating /home/martine/.local/bin (and its parents)
copy dist/build/c-repl/c-repl to /home/martine/.local/bin/c-repl
"copy hook"
("copying child to ","/home/martine/.local/libexec/c-repl-child")
copy dist/build/c-repl-child to /home/martine/.local/libexec/c-repl-child
Setup.lhs: /home/martine/.local/libexec: copyFile: does not exist (No
such file or directory)

That fails because this "libexec" dir doesn't exist.

My questions are:
1) Is it my responsibility to create the libexec dir if it doesn't exist?
2) How can I get the "copy" phase to run as part of "install"?
3) Do you have advice on installed vs. uninstalled paths?  Currently
to facilitate development when getting the path to that executable I
do something like this (where "Paths" is the module generated by

findChildBinary :: IO (Either String FilePath)
findChildBinary = do
  let path = "dist/build/c-repl-child"
  ok1 <- isReadable path
  if ok1
    then return (Right path)
    else do
      libexecdir <- Paths_c_repl.getLibexecDir
      let path = libexecdir ++ "/c-repl-child"
      ok2 <- isReadable path
      if ok2
        then return (Right path)
        else return (throwError "can't find child executable")
  isReadable path =
      perms <- getPermissions path
      return $ readable perms
    `catch` \e -> return False

On Thu, Mar 20, 2008 at 7:29 AM, Duncan Coutts
<duncan.coutts at> wrote:
> Sorry, this dropped of my to-reply-to list, did you get this figured
>  out?
>  Duncan
>  On Sun, 2008-03-02 at 14:34 -0800, Evan Martin wrote:
>  > On Sun, Mar 2, 2008 at 10:11 AM, Duncan Coutts
>  > <duncan.coutts at> wrote:
>  > >  The install phase is really two phases, copy and register. The copy
>  > >  phase has the CopyDest param. The default install hook just runs the
>  > >  copy and register phases. So you probably want to override the copy hook
>  > >  and not the install one.
>  >
>  > It seems the default copy hook just runs the install hook, and that
>  > the install hook doesn't run the copy one... ?
>  >
>  >
>  >   copyHook  = \desc lbi _ f -> install desc lbi f, -- has correct
>  > 'copy' behavior with params
>  >
>  > I'm sure I'm just missing something here, but my "postCopy" hook
>  > doesn't seem to be running with "install -v3".
>  >
>  > >  The hooks stuff is all really very confusing and unsatisfactory.
>  >
>  > I agree, but I can also appreciate how difficult it must be to design,
>  > and can acknowledge that it may be the case that it really just needs
>  > to be this complicated.  Having used autoconf and friends before, one
>  > thing I really prefer about this system is that there are bazillion
>  > different types which helps prevent you from accidentally doing
>  > something like putting a intermediate object in the source dir or
>  > installing while ignoring the user's prefix.

More information about the Libraries mailing list