Skip to content

Commit

Permalink
Add documentation on writing custom DMBS modules.
Browse files Browse the repository at this point in the history
  • Loading branch information
abcminiuser committed Apr 4, 2016
1 parent 5419382 commit 6ee9c3d
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 9 deletions.
20 changes: 16 additions & 4 deletions DMBS/Modules.md → DMBS/ModulesOverview.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ DMBS - Dean's Makefile Build System


Modules Overview
---------------
----------------

The following modules are currently included:

Expand All @@ -16,11 +16,23 @@ The following modules are currently included:
- [GCC](gcc.md) - Compiling/Assembling/Linking with GCC
- [HID](hid.md) - Device Programming

To use a module, you will need to add the following boilerplate to your
## Importing modules into your project makefile

To use a module, it is recommended to add the following boilerplate to your
makefile:

# Include DMBS build script makefiles
DMBS_PATH ?= ../DMBS

Which is then used to indicate the location of your DMBS installation, relative
to the current directory.
Which can then used to indicate the location of your DMBS installation, relative
to the current directory, when importing modules. For example:

DMBS_PATH ?= ../DMBS
include $(DMBS_PATH)/core.mk
include $(DMBS_PATH)/gcc.mk

Imports the `CORE` and `GCC` modules from DMBS using a single path relative to
your project's makefile.

If you wish to write your own DMBS module(s),
[see the documentation here for more details.](WritingYourOwnModules.md)
94 changes: 94 additions & 0 deletions DMBS/WritingYourOwnModules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
DMBS - Dean's Makefile Build System
===================================


Writing Your Own Modules
------------------------

A DMBS module consists of the several boilerplate sections, explained below.

## The DMBS module hooks

Your module needs to advertise to DMBS its name, its makefile targets, the
required and optional variables, and the variables and macros the module
provides for use elsewhere. This is achieved with the following section:

DMBS_BUILD_MODULES += EXAMPLE
DMBS_BUILD_TARGETS += example-target another-target
DMBS_BUILD_MANDATORY_VARS += MANDATORY_NAME ALSO_MANDATORY
DMBS_BUILD_OPTIONAL_VARS += OPTIONAL_NAME ALSO_OPTIONAL
DMBS_BUILD_PROVIDED_VARS += MEANING_OF_LIFE
DMBS_BUILD_PROVIDED_MACROS += STRIP_WHITESPACE

The example above declares that this module is called `EXAMPLE`, and exposes the
listed targets, variable requirements and provides variables and macros.

Your module name and provided variable/macro names must be unique, however you
can (and should) re-use variable names where appropriate if they apply to
several modules (such as `ARCH` to specify the project's microcontroller
architecture). Re-using targets is not recommended, but can be used to extend
the dependencies of another module's targets.

## Importing the CORE module

Next, your module should always import the DMBS `CORE` module, via the
following:

# Conditionally import the CORE module of DMBS if it is not already imported
DMBS_MODULE_PATH := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
ifeq ($(findstring CORE, $(DMBS_BUILD_MODULES)),)
include $(DMBS_MODULE_PATH)/core.mk
endif

This ensures that the `make help` target is always available. In addition, the
`CORE` module exposes some [commonly used macros and variables](core.md) to
your module.

## Setting optional variable's defaults

If a variable is optional, you should provide a default value. Do this via the
`?=` operator of `make`, which sets a variable's value if it has not yet been
set:

MY_OPTIONAL_VARIABLE ?= some_default_value

## Sanity checking user input

Sanity checks are what make DMBS useful. Where possible, validate user input and
convert generated errors to human-friendly messages. This can be achieved by
enforcing that all the declared module mandatory variables have been set by the
user:

# Sanity-check values of mandatory user-supplied variables
$(foreach MANDATORY_VAR, $(DMBS_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))

As well as complaining if they are set, but currently empty:
$(call ERROR_IF_EMPTY, SOME_MANDATORY_VARIABLE)
$(call ERROR_IF_EMPTY, SOME_OPTIONAL_BUT_NON_EMPTY_VARIABLE)

Or even if they are boolean (`Y` or `N`) variables that have an invalid value:

$(call ERROR_IF_NONBOOL, SOME_BOOL_VARIABLE)

## Adding targets

The meat of a DMBS module is the targets, which are run when the user types
`make {target name}` from the command line. These can be as complex or simple
as you like. See the GNU make manual for information on writing make targets.

example-target:
echo "Your DMBS module works!"

## And finally, list the PHONYs

Important in GNU Make is the concept of phony targets; this special directive
tells make that a given target should never be considered a valid file. Listing
phonies ensures that, for example, if your module had a target called `build`,
it would always run when the user types `make build` from the command line, even
if a file called `build` existed in the user project folder.

You can list module-internal targets here, as well as mark all public targets
via the module header's `DMBS_BUILD_TARGETS` variable.

# Phony build targets for this module
.PHONY: $(DMBS_BUILD_TARGETS) some-module-internal-target another-internal-target
8 changes: 4 additions & 4 deletions DMBS/core.mk
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ DMBS_BUILD_PROVIDED_MACROS += DMBS_CHECK_VERSION ERROR_IF_UNSET ERROR_IF_EMPTY E
SHELL = /bin/sh

# Current DMBS release version
DMBS_VERSION = 20160403
DMBS_VERSION := 20160403

# Macro to check the DMBS version, aborts if the given DMBS version is below the current version
DMBS_CHECK_VERSION ?= $(if $(filter-out 0, $(shell test $(DMBS_VERSION) -lt $(1); echo $$?)), , $(error DMBS version $(1) or newer required, current version is $(DMBS_VERSION)))

# Macros to use in other modules to check various conditions
ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))

# Converts a given input to a printable output using "(None)" if no items are in the list
CONVERT_TO_PRINTABLE = $(if $(strip $(1)), $(1), (None))
Expand Down
18 changes: 17 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ are included via a GNU Make `include` directive. While the DMBS `core` module is
always required, you can pick and choose what other modules you wish to add to
your user project.

[See here for the documentation on the individual modules provided by DMBS.](DMBS/Modules.md)
[See here for the documentation on the individual modules provided by DMBS.](DMBS/ModulesOverview.md)
If you're interested in writing your own DMBS module(s), [see here.](DMBS/WritingYourOwnModules.md)

Here's an example user makefile:

Expand Down Expand Up @@ -72,6 +73,21 @@ As modules are added, you can get a list of available targets by simply typing
as well as mandatory and optional variables and exposed variables and macros.


Distribution
----------------

You can embed DMBS in your project any way you like - some options are:
1. A git submodule
2. A source tarball
3. A manually copied extracted archive

The intention of DMBS is that users can just import it from whatever source
they like. If your project needs to extend the existing modules in an unusual
manner, or if you want to provide your own modules, you can include them in
your project repository (or submit a patch to DMBS if your module is generic
enough to warrant wide use).


License
----------------

Expand Down

0 comments on commit 6ee9c3d

Please sign in to comment.