README
¶
HyperMake
HyperMake helps you build projects without installing pre-requisites in your local environment. It uses containers to build projects, all pre-requisites can be pre-installed inside the container.
A similar project is drone which is built to be a service. While HyperMake is built as a handy tool with a few special features:
- Brings in the target concept from traditional GNU make, targets can be defined in one HyperMake file or multiple, and targets have dependencies, can be built selectively.
- Concurrent builds, targets without explicit dependencies can be built concurrently.
Getting Started
The Simplest Way
Download the binary from github release:
curl -s https://github.com/evo-cloud/hmake/archive/hmake-1.0.0-alpha1-linux-amd64.gz | gunzip >/usr/local/bin/hmake
chmod a+rx /usr/local/bin/hmake
With Go installed
go get github.com/evo-cloud/hmake
Build from source
git clone https://github.com/evo-cloud/hmake
cd hmake
# first do a bootstrap
go get
go install
# do a full build
hmake
Note: if you want to use hmake
to do a full build, make sure docker is running.
You want tests?
After build, hmake test
.
If you want run test with coverage, hmake cover
.
Setup Development Environment
In fact with hmake
installed, you don't this local development environment.
Install
go get https://github.com/FiloSottile/gvt
go get https://github.com/onsi/ginkgo/ginkgo
go get https://github.com/onsi/gomega
gvt restore
ginkgo test ./test
# or
go test ./test
go test -coverprofile=cover.out -coverpkg=./project ./test
How it works
hmake expects a HyperMake
file in root of the project,
and you can run hmake
from any sub-directory inside the project,
the command will figure out project root by locating HyperMake
file.
From the top-level HyperMake
file, use includes
section to include any
*.hmake
files inside project tree.
It can't access any files outside project tree.
File Format
In HyperMake
or *.hmake
, define any of the following things:
- Format: the format presents the current file, should always be
hypermake.v0
; - Name and description: only defined in top-level
HyperMake
file; - Targets: the target to build, including dependencies and commands;
- Settings: the settings applies to hmake;
- Includes: include more
*.hmake
files.
Here's the schema in example (this is actually the HyperMake
file of hmake
project):
---
format: hypermake.v0 # this indicates this is a HyperMake file
# project name and description
name: hmake
description: HyperMake builds your project without pre-requisites
# define targets
targets:
builder:
description: build the docker image including toolchain
build: builder/Dockerfile
image: hmake-builder:latest
watches:
- builder
hmake-linux-amd64:
description: static linked hmake binary for Linux AMD64
after:
- vendor
watches:
- '**/**/*.go'
cmds:
- ./build.sh linux amd64
hmake-darwin-amd64:
description: static linked hmake binary for Mac OS
after:
- vendor
watches:
- '**/**/*.go'
cmds:
- ./build.sh darwin amd64
vendor:
description: pull all vendor packages
after:
- builder
watches:
- vendor/manifest
envs:
- HMAKE_VER_SUFFIX
- HMAKE_RELEASE
cmds:
- gvt restore
- mkdir -p bin
- ./build.sh genver
test:
description: run tests
after:
- vendor
watches:
- '**/**/*.go'
- test
cmds:
- ginkgo ./test
cover:
description: run tests with coverage
after:
- vendor
watches:
- '**/**/*.go'
- test
cmds:
- >
go test -coverprofile cover.out
-coverpkg ./project
./test
all:
description: the default make target
after:
- hmake-linux-amd64
- hmake-darwin-amd64
# settings shared across targets
settings:
default-targets:
- all
docker:
image: hmake-builder:latest
src-volume: /go/src/github.com/evo-cloud/hmake
includes:
- build/**/**/*.hmake
Dependencies
Dependencies can be specified using:
after
: the target is executed when the depended tasks succeed or are skippedbefore
: the target must succeed or skip before the specified tasks get executed.
In most cases, after
is enough in a single file.
before
is mostly used to inject dependencies in the files included.
Include files
In includes
section, specify files to be included.
The files included can provide more targets and also override settings.
Pre-defined Environment Variables
HMAKE_PROJECT_NAME
: the name of the projectHMAKE_PROJECT_DIR
: the directory containingHyperMake
(aka. project root)HMAKE_PROJECT_FILE
: the full path toHyperMake
HMAKE_WORK_DIR
:$HMAKE_PROJECT_DIR/.hmake
HMAKE_LAUNCH_PATH
: the relative path under$HMAKE_PROJECT_DIR
wherehmake
launchesHMAKE_REQUIRED_TARGETS
: the names of targets explicitly required from command line, separate by spaceHMAKE_TARGET
: the name of the target currently in executionHMAKE_VERSION
: version of hmakeHMAKE_OS
: operating systemHMAKE_ARCH
: CPU architecture
Global Setting Properties
default-targets
: a list of targets to build when no targets are specified inhmake
commandexec-driver
: the name of driver which parses properties in target and executes the target, the default value isdocker
, and supported drivers aredocker
andshell
. This property can also be specified in target instead of globalsettings
section.
Common Properties in Target
description
: description of the targetbefore
: a list of names of targets which can only execute after this targetafter
: a list of names of targets on which this targets dependsexec-driver
: same as insettings
section, but only specify the driver for this targetenvs
: a list of environment variables (the formNAME=VALUE
) to be used for executionscript
: a multi-line string represents a full script to execute for the targetcmds
: whenscript
is not specified, this is a list of commands to execute for the targetwatches
: a list of path/filenames (wildcard supported) whose mtime will be checked to determine if the target is out-of-date, without specifying this property, the target is always executed (the.PHONY
target inmake
).
Other properties are driver specific, and will be parsed by driver.
State Directory
hmake creates a state directory $HMAKE_PROJECT_DIR/.hmake
to store logs and state files.
The output (stdout and stderr combined) of each target is stored in files TARGET.log
.
Execution Drivers
The shell
driver
This is simplest driver which inteprets script
or cmds
as shell script/commands.
The list of cmds
will be merged as a shell script.
And the intepreter is /bin/sh
.
set -e
is inserted as the first line to fail-fast.
The docker
driver
This driver generates the same script as shell
driver but run it inside a docker container.
The following properties are supported:
build
: path toDockerfile
, when specified, this target builds a docker image first.image
property specifies the image name and tag. It's strongly recommended to putDockerfile
and any related files towatches
list.build-from
: the build path fordocker build
. Without this property, the build path is derived from path ofDockerfile
specified inbuild
.image
: withbuild
it's the image name and tag to build, withoutbuild
, it's the image used to create the container.src-volume
: the full path inside container where project root is mapped to. Default is/root/src
.envs
: list environment variables passed to container, can beNAME=VALUE
orNAME
.env-files
: list of files providing environment variables, see--env-files
ofdocker run
privileged
: run container in privileged mode, default isfalse
net
: when specified, only allowed value ishost
, when specified, run container with--net=host --uts=host
user
: passed todocker run --user...
, by default, currentuid:gid
are passed It must be explicitly specifiedroot
if the script is executed as root inside container.volumes
: a list of volume mappings passed to-v
option ofdocker run
.
The following properties maps to docker run
options:
cap-add
,cap-drop
devices
hosts
: mapped to--add-host
dns
,dns-opts
,dns-search
blkio-weight
,blkio-weight-devices
device-read-bps
,device-write-bps
,device-read-iops
,device-write-iops
cpu-shares
,cpu-period
,cpu-quota
,cpuset-cpus
,cpuset-mems
kernel-memory
,memory
,memory-swap
,memory-swappiness
,shm-size
All above properties can also be specified in global settings
under docker
section:
settings:
docker:
property: value
By default the current project root is mapped into container at src-volume
,
default value is /root/src
.
And it's also the current working directory when script starts.
As the script is a shell script, the executable /bin/sh
must be present in the container.
By default hmake
uses current user (NOT root) to run inside container,
which make sure any file change has the same permission as the environment outside.
If root is required, it can be explicitly specified user: root
,
however, all files created inside container will show up being owned by root
outside,
and you may end up seeing some error messages like permission denied
when you do something later.
Command Usage
Usage
hmake [OPTIONS] [TARGETS]
Options
--chdir=PATH, -C PATH
: Chdir to specified PATH first before doing anything--include=FILE, -I FILE
: Include additional files (must be relative path under project root), can be specified multiple times--define=key=value, -D key=value
: Define property in globalsettings
section,key
may include.
to specify the hierarchy--parallel=N, -p N
: Set maximum number of targets executed in parallel, 0 for auto, -1 for unlimited--rebuild-all, -R
: Force rebuild all needed targets--rebuild TARGET, -r TARGET
: Force rebuild specified target, this can repeat--skip TARGET, -S TARGET
: Skip specified target (mark as Skipped), this can repeat--json
: Dump execution events to stdout each encoded in single line json--summary, -s
: Show execution summary before exit--verbose, -v
: Show execution output to stderr for each target--color|--no-color
: Explicitly specify print with color/no-color--emoji|--no-emoji
: Explicitly specify print with emoji/no-emoji--debug
: Write a debug loghmake.debug.log
in hmake state directory--show-summary
: When specified, print previous execution summary and exit--targets
: When specified, print list of target names and exit--dryrun
: When specified, run targets as normal but without invoking execution drivers (simply mark task Success)--version
: When specified, print version and exit
License
MIT
Documentation
¶
There is no documentation for this package.