packages feed

bdcs-0.2.1: Setup.hs

-- Copyright (C) 2016-2017 Red Hat, Inc.
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with this library; if not, see <http://www.gnu.org/licenses/>.

{-# LANGUAGE CPP #-}

module Main(main)
 where

import Data.List(isPrefixOf)
import Distribution.PackageDescription(Executable(..), GenericPackageDescription(..), HookedBuildInfo, PackageDescription(..))
import Distribution.Simple(defaultMainWithHooks, simpleUserHooks)
import Distribution.Simple.InstallDirs(InstallDirs(..), fromPathTemplate, toPathTemplate)
import Distribution.Simple.LocalBuildInfo(LocalBuildInfo(..))
import Distribution.Simple.UserHooks(UserHooks(..))
import System.FilePath((</>))

#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2, 0, 0)
import Distribution.Types.UnqualComponentName(unUnqualComponentName)
import Distribution.Types.ExecutableScope(ExecutableScope(..))
import Distribution.Simple.Setup(ConfigFlags)
#else
import Distribution.Simple.Install(install)
import Distribution.Simple.Setup(ConfigFlags, CopyFlags)
#endif

main :: IO ()
main = defaultMainWithHooks bdcsHooks

-- Handle the libexec paths, and differences between Cabal-1.x and Cabal-2.x.
--
-- On Cabal-2.x, we can specify a scope of "private" on libexec executables.
-- This can be done directly in the .cabal file when we remove support for Cabal < 2.0.
#if defined(MIN_VERSION_Cabal) && MIN_VERSION_Cabal(2, 0, 0)
bdcsHooks :: UserHooks
bdcsHooks = simpleUserHooks { confHook = bdcsConf }

bdcsConf :: (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo
bdcsConf (descr, hbi) flags = do
    lbi <- confHook simpleUserHooks (descr, hbi) flags

    -- Modify the executable list to change the scope of the libexec executables
    let localDesc = localPkgDescr lbi
        scopedLbi = lbi { localPkgDescr = localDesc { executables = map mangleExec (executables localDesc) } }

    -- Add weldr/ to the libexecdir
    return $ addLibexecWeldr scopedLbi
 where
    mangleExec :: Executable -> Executable
    mangleExec exe =
        if isSubcommand (unUnqualComponentName $ exeName exe) then exe{exeScope = ExecutablePrivate}
        else exe

#else
-- On Cabal-1.x, change the destination directory of subcomponents during the copy step
bdcsHooks :: UserHooks
bdcsHooks = simpleUserHooks { confHook = bdcsConf,
                              copyHook = bdcsCopy }

bdcsConf :: (GenericPackageDescription, HookedBuildInfo) -> ConfigFlags -> IO LocalBuildInfo
bdcsConf (descr, hbi) flags = addLibexecWeldr <$> confHook simpleUserHooks (descr, hbi) flags

bdcsCopy :: PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO ()
bdcsCopy pkg lbi _ flags = do
    -- First, install everything that's not a subcommand.  That is almost everything
    -- listed in the cabal file.
    let (mainPkg, mainLbi) = extractMainComponents pkg lbi
    install mainPkg mainLbi flags

    -- Second, install only the subcommands into $prefix/libexec/weldr.
    let (subPkg, subLbi) = extractSubComponents pkg lbi
    install subPkg subLbi flags

extractMainComponents :: PackageDescription -> LocalBuildInfo -> (PackageDescription, LocalBuildInfo)
extractMainComponents pkg lbi = let
    pkg' = pkg { executables = filter (not . isSubcommand . exeName)
                                      (executables pkg) }
 in
    (pkg', lbi)

extractSubComponents :: PackageDescription -> LocalBuildInfo -> (PackageDescription, LocalBuildInfo)
extractSubComponents pkg lbi = let
    dest = libexecdir (installDirTemplates lbi)

    pkg' = pkg { executables = filter (isSubcommand . exeName)
                                      (executables pkg) }
    lbi' = lbi { installDirTemplates = (installDirTemplates lbi) { bindir = dest } }
 in
    (pkg', lbi')

#endif

isSubcommand :: String -> Bool
isSubcommand s = "inspect-" `isPrefixOf` s || "bdcs-" `isPrefixOf` s

-- Make sure $libexecdir gets "weldr/" appended to it.  This will affect both the installation location
-- for anything that should go into $libexecdir (like our subcommand programs) as well as the auto
-- generated Paths_bdcs.hs file.
--
-- This also means if you pass --libexecdir= to "cabal configure" or any other program, you should not
-- add "weldr/" to it.  Otherwise you'll get it in there twice.
addLibexecWeldr :: LocalBuildInfo -> LocalBuildInfo
addLibexecWeldr lbi =
    let dest = mangle $ libexecdir $ installDirTemplates lbi
    in lbi { installDirTemplates = (installDirTemplates lbi) { libexecdir = dest } }
 where
    mangle = toPathTemplate . (</> "weldr") . fromPathTemplate