diff --git a/README.md b/README.md index a0166bed..ef842dc5 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,135 @@ -# JW-Build Build System +# JW-Build -The JW-Build package basically is a bunch of scripts and GNU makefile snippets. -You can install it to its standard location /opt/jw-build, or put it anywhere +## Features + +The JW-Build package is basically a bunch of scripts and GNU makefile snippets +for organizing software builds and releases. + +You can install it to its standard location `/opt/jw-build`, or put it anywhere you want in your file system, typically next to your own projects in the same -directory. You then include JW-Build's makefiles from within your own project -to organize your build. +directory. To organize their respective builds, you can then include JW-Build's +makefile snippets from your own projects' makefiles, like so: -JW-Build is small. You can install the package with your distribution's package -manager, but you can also keep it within your version system, alongside your -own code. It's also meant to be the lightest possible touch on any given source -code package, in terms of needed prerequisites, and also in terms of code you -need to put into those packages. This way, it's easily introduced - but it -also allows you to easily opt out of JW-Build at any time. +```gmake +include $(JWBDIR)/make/cpp.mk +``` -A package using JW-Build only needs three-liners as makefiles. This buys you -convenience, minimal, clean, humanly digestable code, and a structured way to -customize builds involving multiple packages - you can override any of -JW-Build's default variables centrally for many projects, for an entire -project, or inside any subdirectory of any project, at your option. It avoids -makefile generation as done by CMake or GNU Autotools, to keep the running code -small and readable to facilitate debugging. To achieve this, it has to detect a -couple of things in every directory, but there's a caching mechanism in place, -which keeps builds reasonably fast. +where `JWBDIR` needs to point to jw-build's installation directory. In this +example the snippet `cpp.mk` would by default take all C++ files it finds in +the directory where its included, compile them and and add them to a shared +package library. `js.mk` would by default minify all JavaSript it finds, +`java.mk` jar up .java files into classes and jar-files, and so on. JW-Build +also handles installation and packaging of all of these files, to customizable +locations with standardish defaults. -JW-Build honours some environment variables to control the build. It builds -libraries and executables, outputs object code from C/C++, Python and Java, and -is easily extendible to support any given programming language. It provides -targets to produce Debian, RPM and IPK packages, install them, or feed them -into a DevOps pipeline, taking note within GIT, SVN or CVS. It supports a -simple configuration file per project, containing the project's metadata, e.g. -their dependencies, license, description or the like. It has a SAT-solver built -in, for building multiple projects in the right order, including packages that -are not organized with jw-build. It automatically generates BitBake recipes and -organizes Yocto-builds incorporating your software. It supports cross -compilation with MinGW and the GNU toolchain. It's tested on Debian, OpenSUSE, -Fedora / CentOS / RHEL, Mint and many Unices. +JW-Build is small. It's small enough to be self-documenting. Well, okay, +somewhat self-documenting. You have to know GNU Makefile syntax to understand +what it does. You can install it with your distribution's package manager, or +you can keep it within your code versioning system, alongside your own code. +It's also designed to be the lightest possible touch on any given source code +package, in terms of code you need to add to a package you want to build with +it, and also in terms of needed prerequisite software packages. This way, it's +easily introduced - and it's also easy to get rid of, should you choose to do +so at some point in time. You will then have all your settings and compiler +flags in well-defined places already. -JW-Build is designed to be friendly to both developers and integrators. You can -cd into any given directory, run make, and expect the resulting code to work -and be testable. It has built-in support for remote Git repositories and -collaboration. Of course, it can build and package itself. +JW-Build runs a recursive make, so, with a few exceptions such as submodules, +you will need a makefile in every directory with source code. Most, if not all +of these makefiles can be three-liners. This buys you convenience, minimal, +clean, humanly digestable code, and a structured way to customize builds +involving multiple packages - as centrally or as locally as you want. You can +override any of JW-Build's default variables - for many packages, for an entire +package, or for any subdirectory of a given package, at your option. You can +write your own snippets and reuse them in multiple places. You can keep +overrides in your versioning system or add them to a `local.mk` which only your +machine knows about. Or you can use environment variables, of course. JW-Build +avoids makefile code generation as seen with CMake or GNU Autotools. This keeps +the code small and readable for easy debugging. Okay, for relatively easy +debugging. To achieve this, JW-Build has to detect a couple of things in every +directory it enters, but it uses various caching mechanisms to keep builds +still reasonably fast. + +JW-Build has makefile snippets for building libraries and executables, snippets +that output code compiled from C/C++, Python, Java, JavaScript and LaTeX, and +it's easily extendible to support any given programming language or task. It's +in use at janware for managing sub-builds of Maven, Ant, CMake and others, and +for packaging the results. It provides targets to produce Debian, RPM and IPK +packages, install them locally or remotely, or feed them into a DevOps +pipeline, taking note of released versions within GIT, SVN or CVS. It detects +if a package needs to be re-released because its source code changed. Or because +a package it depends on has changed incompatibly. JW-Build has built-in +support for collaboration over a set of remote Git repositories. It supports a +simple configuration file per package for specifying package metadata, e.g. its +dependencies, license, description, pre- and postinstall scriptlets, and so on. +It has a SAT-solver built in, for building multiple packages in the right +order, including packages that are not organized with jw-build, based on that +metadata. With the same metadata, it can also automatically generate BitBake +recipes and run Yocto-builds incorporating your software. It generates runtime, +development and source code package variants. It supports cross compilation +with MinGW and the GNU toolchain. It's tested on Debian, Ubuntu, OpenSUSE, +Fedora / CentOS / RHEL, and many Unices. + +JW-Build is designed to be friendly to both developers and integrators. +Developers can cd into any given directory, edit the source code, run `make`, +and expect the resulting binaries to work and be immediately testable, for a +workflow that lets you focus on coding in your target language. For integrators +on the other hand, a hotfix on a server or an embedded host can be as simple as + +``` +TARGET_HOST=myserver.acme.com make pkg-remote-install +``` + +And of course, it can build, package and release itself. Without being +installed, which is a Good Thing (TM). + +## Documentation + +See https://janware.com/wiki/pub/sw/build/ for documentation on how to get +and use JW-Build within a janware build tree. + +If you want to use it standalone, OTOH, do the following to get a minimal +working example: + +First, add a `make` subdirectory to the toplevel directory of your package, +containing two files: + +1. `proj.mk`, containing a definition of `JWBDIR`, pointing to the JW-Build + installation directory, e.g. like so: + + ```gmake + JWBDIR ?= $(firstword $(wildcard $(addsuffix /jw-build,$(TOPDIR)/.. /opt))) + ``` + + `TOPDIR` points to, you guessed it, the toplevel directory of your package. + You will have defined it yourself, see the next point. Note that all + directory paths can be relative, which is nice if you want to organize + trees. + +2. `project.conf`, containing + + ``` + [description] + A frobnicator library + ``` + +Then, add files named `Makefile` to the directories of your project, +containing, e.g., in a C++ directory: + +```gmake +TOPDIR = ../.. + +include $(TOPDIR)/make/proj.mk +include $(JWBDIR)/make/cpp.mk +``` + +Done. Well, in principle. Other notable snippets are `topdir.mk` for the +toplevel directory, `dirs.mk` for other directories with subdirectories, +`lib.mk` for `$(TOPDIR)/lib`, `include.mk` for `$(TOPDIR)/include`, and +`make.mk` for `$(TOPDIR)/make`. You should add them in the same manner. Once +you add those makefiles, running `make` will do - something. Try and see what +happens. Every snippet supports at least the targets `all`, `install`, `clean` +and `distclean`. `make echo-makefiles` shows you all included snippets, +`cat-makefiles` concatenates them. Hitting TAB should show you all targets +supported in a particular directory. Good luck! + +[logo]: https://janware.com/janware/images/logo-janware/logo-janware-200.png