Blazing Fast. Sub scecond Modification detection. Few seconds for cached compilation
UMake is a build system that building your projects.
influenced by tup
.
- local cache - disk cache
- remote cache - minio
- auto dependency discovery using strace
- simple configuration language
git clone https://github.com/grisha85/umake.git
cd umake
docker build -t umake .
docker run --rm -it -v`pwd`/example:/example -w/example umake bash
umake --no-remote-cache
./hello_world
-
loading compilation graph (DAG) from previous build (graph is empty when built first time)
-
scannig filesytem using the loaded graph to check for changes
modified
- if file was modified on filesystem it marked as modified on the graphdeleted
- if file was deleted from the filesystem, successor target deleted as well from the filesystem and the graph
-
parsing UMakefile and creating new commands or updating the existing
deleted
- if command deleted, targets of this command deleted as well from both graph and filesystemupdated
- if command is updated, UMake will handle it asdelete
andcreate
. so, target of the old command will be deleted and new target will be created when graph will be executed
-
executing the graph in parallel
auto dependency detection
- updating the graph with accessed files by parsing strace logscache
- saving to cache. more details: Cache System
-
saving the build graph
Note: by automatically deleting targets
when no longer needed (either command
is delete or source file was the deleted for this target
) UMake implementing clean
by design. So clean
no longer need to be mainained.
A single command
is generated for this rule
:
source |
manual-deps >
cmd >
target
manual-deps
- targets the this target depends on, helps keep a correct build order
cmd
- bash command
target
- the output of the command
{filename}
- full path filename of the source /my/path/filename.a
{dir}
- directory containing the source /my/path/
{noext}
- filename without extension filename
{target}
- expanded target helloworld.a
Example:
: *.o > gcc {filename} -o {target} > helloworld.a
recursice dependancies are support
root\
a\
a.a\
a.a.a
a.a.b
a.b.a
a.b\
a.b.a
a.b.b
b\
b
root/**
-> (a.a.a
,a.a.b
,b
)root/a/**/*.b
-> (a.a.b
,a.b.b
)
In order to maintain a correct build order (that is executed in parallel), there are use cases where manual depndecy is needed. for example: if there are generated headers
(like when using protobuf
) that are being later used by another command
to generate a different target.
Same as :
but will create command
for each source
file existing on filesystem (like when we match the pettern *.o in the example above)
Macros are expanded immediately (like using #define X "hello"
in c/cpp)
Macros can accept input parameters (again, similar to using c/cpp macros)
Example:
!c(includes, flags) : gcc -g -O2 -Wall -fPIC -c {filename} $includes $flags -o {target} > {dir}/{noext}.o
Macro
supports default values, by default they are ""
:
!c(includes, flags=-O3) : gcc -g -O2 -Wall -fPIC -c {filename} $includes $flags -o {target} > {dir}/{noext}.o
now !c
can be called as following:
!c(-Iinclude) # includes = -Iinclude, flags=-O3
!c(-Iinclude, -O0) # includes = -Iinclude, flags=-O0
!c() # includes = "", flags=-O3
Consts are like macros, and can be used to parametrize calls to macros Example:
$libs = -lpthread
!so($libs)
Configs allow to configure and changing umake execution.
Default: <root>
Change the current working directory.
relative paths
will now be relative to the new working dir.
Absoulte paths
will now be relative to the root
(the directory where UMakefile exists).
Example:
Relative path my_dir_a/my_dir_b
will be evaluated as <workdir>/my_dir_a/my_dir_b
.
However /my_dir_a/my_dir_b
will be evaluated as <root>/my_dir_a/my_dir_b
regardless of what our workdir
is.
The following rules are similar:
: src/packages/a > gcc > src/packages/b
[workdir:src/packages]
: a > gcc > b
Return to root
[workdir:/]
Defult: "default"
The ability to generate diffrent variants from the same sources. For example: debug/release compilations. variant terminated
with a newline
# varaint is terminated with newline
[variant:default]
$cflags = -O3
[variant:debug]
$cflags = -O0
: my.c > !c($cflags) > my.o
now compile with umake
for default variant
umake
or
umake --variant debug
for debug
variant.
Default: -
include another UMakefile
into the current one.
[include:somedir/umakefile]
will open and parse somedir/umakefile
in the current working dir context.
Targets are being cached after creation, and checked if the target is in cache just before executing a command
. There are two types of cache that UMake is using local(filesystem) and remote (minio).
sha1
of the target sources (those that were generated from UMakefile) are being calculated andsha1
of thecommand
itself. All dependecies files (also those that were auto detected) Saved tomd-<calculated_hash>
file.sha1
of all dependecies are calculated and the just created target is saved to<all_dependecies_hash>/<target_name_hash>
sha1
of the target sources (those that were generated from UMakefile) are being calculated andsha1
of thecommand
itself. Readingmd-<calculated_hash>
for all the file dependecies- calculating
sha1
of all of the target dependecies (from the files system) and copying<all_dependecies_hash>/<target_name_hash>
to the project directory as it was generated by thecommand
The local cache is stored in ~/.umake/build-cache
.
TBD
usage: umake [-h] [--details] [--json JSON_FILE] [--no-remote-cache]
[--no-local-cache]
[target]
positional arguments:
target target path
optional arguments:
-h, --help show this help message and exit
--details details about the target
--json JSON_FILE output as json
--no-remote-cache don't use remote cache
--no-local-cache don't use local cache