Miezhiko / hake

This thing is designed to write scripts with depending on each other actions. It's syntax slightly common to Makefile but on haskell, generally it's some EDSL.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Haskell CI

Hake

Scripty thing designed to write scripts with depending on each other actions.

HakeScriptUsageDesignInstallBuildNotes

HakeScript

{-# LANGUAGE MultiWayIf    #-}
{-# LANGUAGE UnicodeSyntax #-}

import           Hake

main  IO ()
main = hake $ do

  "clean | clean the project" 
    cargo ["clean"] ?> removeDirIfExists targetPath

  "update | update dependencies"  cargo ["update"]

  salieriExecutable 
    cargo <| "build" : buildFlagsSalieri False

  amadeusExecutable  [salieriExecutable] ♯♯
    cargo <| "build" : buildFlagsAmadeus False

  "fat | build Amadeus and Salieri with fat LTO" 
       cargo <| "build" : buildFlagsSalieri True
    >> cargo <| "build" : buildFlagsAmadeus True

  "install | install to system"  [ "fat" ] 
    cargo <| "install" : buildFlagsAmadeus True

  "test | build and test"  [amadeusExecutable]  do
    cargo ["test"]
    cargo ["clippy"]
    rawSystem amadeusExecutable ["--version"]
      >>= checkExitCode

  "restart | restart services"  [ salieriExecutable
                                 , amadeusExecutable ]  do
    systemctl ["restart", appNameSalieri]
    systemctl ["restart", appNameAmadeus]

  "run | run Amadeus"  [ amadeusExecutable ]  do
    cargo . (("run" : buildFlagsAmadeus False) ++) . ("--" :) =<< getHakeArgs

 where
  appNameSalieri  String
  appNameSalieri = "salieri"

  appNameAmadeus  String
  appNameAmadeus = "amadeus"

  targetPath  FilePath
  targetPath = "target"

  buildPath  FilePath
  buildPath = targetPath </> "release"

  salieriFeatures  [String]
  salieriFeatures = [ "kafka" ]

  amadeusFeatures  [String]
  amadeusFeatures = [ "trackers"
                    , "torch" ]

  fatArgs  [String]
  fatArgs = [ "--profile"
            , "fat-release" ]

  buildFlagsSalieri  Bool -> [String]
  buildFlagsSalieri fat =
    let defaultFlags = [ "-p", appNameSalieri
                       , "--release", "--features"
                       , intercalate "," salieriFeatures ]
    in if fat then defaultFlags ++ fatArgs
              else defaultFlags

  buildFlagsAmadeus  Bool -> [String]
  buildFlagsAmadeus fat =
    let defaultFlags = [ "-p", appNameAmadeus
                       , "--release", "--features"
                       , intercalate "," amadeusFeatures ]
    in if fat then defaultFlags ++ fatArgs
              else defaultFlags

  salieriExecutable  FilePath
  salieriExecutable =
    {- HLINT ignore "Redundant multi-way if" -}
    if | os  ["win32", "mingw32", "cygwin32"]  buildPath </> appNameSalieri ++ ".exe"
       | otherwise  buildPath </> appNameSalieri

  amadeusExecutable  FilePath
  amadeusExecutable =
    {- HLINT ignore "Redundant multi-way if" -}
    if | os  ["win32", "mingw32", "cygwin32"]  buildPath </> appNameAmadeus ++ ".exe"
       | otherwise  buildPath </> appNameAmadeus

Usage

> hake --help
hake
  -v  --version  Display Version
  -h  --help     Display Help
  -f  --force    force script rebuild
  -P  --pretend  pretend building (testing hake script)

Current HakeScript options:
  clean   : clean the project
  fat     : build Amadeus and Salieri with fat LTO
  install : install to system
  restart : restart services
  test    : build and test
  update  : update dependencies

Current HakeScript objects:
  amadeus (salieri)
  salieri

In root of your project you create file hake.hs then you run hake or hake clean or whatever other options you add to the script, please use src/Hake.hs to learn about all the operators, I will add more examples another time.

Design

Design of this thing is imperative. At first hake will compile (if not compiled) hakescript file (which is basically haskell file with Hake library and wrapper right after main) so we have actual actions compiled and we don't parse them. After that hake will execute compiled hakescript file (aka hake) with passing arguments, when hake is executing we gather objects and phony (same terms as in Makefile but with optional syntax sugar and operators) strings into Data.IORef structure where we connect actions with obj and phony stuff, next we know what is our target action is (based on passed arguments) and we execute all it's dependencencies (dependencencies of dependencencies first) etc, recursively starting from needed ones without dependencencies. Once action has executed we drop it from IORef structure and check for new action without dependencencies, eventually we execute target action in the very end.

Install

just cabal install should install library and executable to userspace

or you can use my .ebuild from Overlay and

emerge hake

Build

simplest:

stack build

complicated:

some cabal commands

with hake installed:

hake

Notes

About

This thing is designed to write scripts with depending on each other actions. It's syntax slightly common to Makefile but on haskell, generally it's some EDSL.

License:GNU Lesser General Public License v2.1


Languages

Language:Haskell 100.0%