Skip to content

kuriboshi/m

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

-*- text -*-

M: A minimal build generator
============================

Designed for simple C or C++ projects which don't have fancy build
rules and depends on external header only libraries or libraries which
are simple enough to add an 'M' build script for.  It can download
these external libraries from a remote git repository.  'M' uses
'ninja' as the backend to do the actual build.

Only Unix and Unix-like systems have any chance of working at the
moment.  There is a proof of concept version written in ksh93 in the
'scripts' directory and a version written in C++ in the 'src'
directory.  They are roughly compatible with some slight variation in
the output for some cases.

Files named '_m' defines build rules and dependencies.  You can have
one or more '_m' files in sub directories with at least one in the top
level directory.  When using the ksh93 version of 'M' the config files
are actually ksh scripts.  Obviously this is not the case when using
the C++ version of 'M' to process the '_m' files.  See the '_m' file
in this directory for a sample config file.

I created 'M' as a simple build generator for my own personal
projects.  The goal was something simple with which I could quickly
describe how to compile a project without too much trouble.  I chose
convention over configuration.  The design is coloured by my
experience writing makefiles over many years.

With my makefiles I put a lot of effort into writing a set of
elaborate makefiles which hides all the complexities.  These makefiles
were then included in the project specific makefiles.  The project
specific makefiles would be very simple: A list of files to compile, a
list of libraries the project depended on, and sometimes some defines
needed for some special cases.

The common makefiles would handle system differences and would try to
automatically detect implicit dependencies.  For example, if you
included a library wrapping database calls the required client
libraries for the database would automatically be included in the link
line.

As the common makefiles grew more and more complex and as I realised
that some problems were difficult to solve in a nice way using only
make I started to consider other popular build generators.  The two
most prominent ones I looked at were CMake and Meson.

CMake is by many considered the industry standard for C++ projects and
is used by a wide range of high profile projects.  It's also widely
considered poorly documented (although work is ongoing trying to
address this problem).  It's hard for new users to write a CMake file
from scratch.  Personally I'm not a fan of the unusual syntax chosen
for the CMake language.  However, it's clearly very powerful and a
good example of how it can be leveraged is the vcpkg project by
Microsoft.  vcpkg is similar to the BSD ports system except using
CMake instead of make to handle the builds.

Meson is another build generator which is rapidly gaining popularity.
It seems to be much better designed and more solid foundation to
develop further compared to CMake.  The most questionable decision in
my view is the choice of implementation language: Python.  Not just
any Python but Pyton >= 3.5.  Python is a good language and it does
make sense to build a project like Meson in Python.  I just think it
would have been better to write it in C (or C++).  Such a fundamental
tool should really not have such a heavy dependency.  I know that in
principle someone could write a version in C based on the
specification for Meson.

Compared to CMake, Meson is much easier to get started with.  I could
put something together pretty quickly.  The documentation is much
better, helped by the fact that the syntax is much more main stream.
However, in my case I found myself in want of a Meson build file
generator which would negate some of its benefits.

In the end I decided that for my purpose a dependency on Python was
just too much.  Ideally I would want to use plain C but since I target
projects primarily written in C++ I don't feel bad about choosing C++
as the implementation language for 'M'.  Right now 'M' is so simple
that it could be quickly reimplemented in just about any language, as
proven by my initial POC implementaiton in ksh93.

The C++ version of 'M' requires C++-14.  Since my projects are almost
always in C++ and I aim to use the latest version of C++ if at all
possible it makes sense that my build system is also written in a
newer version of C++.

The reason I decided on a build generator instead of a 'make'
replacement is that it's really just the most practical solution.  I
have over my years of using make considered writing a better make.
I'm a big fan of make, but writing a better version of it seemed like
a waste of effort.

I picked ninja as the backend for 'M' because I liked the simplicity
of the build file language with its resemblance to make.  I also liked
how it dealt with things which traditionally has been annoying to do
well in make: out-of-tree builds, automatically creating intermediate
directories, the ease of dealing with header file dependencies, the
robustness of parallel builds, and I'm sure many other good reasons.

The claims of increased speed I'm not so sure of.  In all my
benchmarks my hand crafted makefiles performed as well as or, in some
cases, slightly better than the equivalent ninja build files.  Perhaps
it's because I compile C++ code and a build spends proportionally more
time compiling than deciding that to do next or perhaps my projects
are not big enough to reap the benefits of ninja.

I'm happy with my choice.  Generating the build.ninja file is almost
instantaneous, adding next to nothing to the overall build time of my
projects.  Compared to CMake or Meson it leaves a lot to be desired
and you quickly run into limitations when trying to write a 'M' config
file for any random project.  There is no handling of cross platform
builds and I'm sure there are a lot of cases where 'M' simply can't be
used in its current form.  Projects can really only consist of sets of
source files which need to be built into libraries or executables.

Copyright 2018 Krister Joas <krister@joas.jp>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

About

M: a minimal build generator

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published