jcmds build tool
================
``jcmds`` is a build tool. Its main inspiration is Cons, a Perl-based
"make-replacement" developed in the late 1990s. Common features are:
- MD5 checksums are used to reliably decide if files need to be rebuilt
- C/C++ #include file dependencies are automatically found by the tool
Differences are:
- ``jcmds`` can build in parallel (eg. -j8)
- ``jcmds`` uses no script language. Instead one just tells ``jcmds``
what command there is to run. ``jcmds`` then decides for itself which
commands may need to be run (this is a slight simplification; see below
for more details).
Examples
--------
::
$ cat > prog.cmds <<_END_
gcc -o prog prog.o mod.o
gcc -c prog.c -o prog.o
gcc -c mod.c -o mod.o
_END_
$ jcmds -f prog.cmds
gcc -c mod.c -o mod.o
gcc -c prog.c -o prog.o
gcc -o prog prog.o mod.o
$ jcmds -f prog.cmds
jcons: up-to-date: .
Two things can be seen here:
- the order of the commands given to ``jcmds`` does not matter.
All commands contribute to the building of the dependency graph.
The actual order of commands is determined by the structure of
the dependency graph.
- the second invocation detects that all target are up-to-date
so no commands get executed.
``jcmds`` has built-in knowledge of compiler/linker commands like those above,
but can of course not understand all possible commands. Say one command is::
process_file src.txt tgt1.txt tgt2.txt
``jcmds`` can't known by magic that ``src.txt`` is the input and that there are
two output files ``tgt1.txt`` and ``tgt2.txt``. To "help" ``jcmds`` extra information
can be given as "comments" before the command, like this::
# INPUT: src.txt
# OUTPUT: tgt1.txt
# OUTPUT: tgt2.txt
process_file src.txt tgt1.txt tgt2.txt
Using this extra information, ``jcmds`` can add the command to the
dependency graph.
Built-in knowledge
------------------
``jcmds`` has built-in understanding of a number of commands::
cp INPUT OUTPUT
gcc ... -c ... NAME.c ... -o NAME.o ...
gcc ... -o NAME ... NAME_1.o ... NAME_N.o ... LIBNAME_1.a ... LIBNAME_N.a
ar qc LIBNAME.a NAME_1.o ... NAME_N.o
Different compilers like CLANG is also recognized, and C++ is also
handled (ie. ``clang``, ``g++`` and ``clang++``).
A command can also be on the form::
cd some_dir && some_command ...
Then ``jcmds`` understands that file arguments to ``some_command`` are to be
evaluated relative to the directory ``some_dir``.
Extra information via comments
------------------------------
- ``# INPUT: <filename>``
one or more input files to the command
- ``# OUTPUT: <filename>``
one or more output files from the command
- ``# DEPEND: <filename>``
one or more extra "hidden" dependencies
- ``# EXE_DEPEND: <filename>``
one or more extra "hidden" dependencies of the command executable itself
... TODO: add more info ...
Jcmds and CMake
---------------
One way to use ``jcmds`` is in combination with ``cmake``. For example::
mkdir build
cd build
cmake -GNinja ..
ninja -t commands > commands.txt
jcmds -f commands.txt