... for Android, BSDs, Linux, macOS, SunOS, Windows (MinGW, WSL)
mulle-craft builds two things:
- your project using mulle-make
- the dependencies of your project as specified by a craftorder file. This file can be generated by mulle-sourcetree.
mulle-craft is unaware of the build tool to use (e.g. cmake or xcodebuild). That is determined by mulle-make, which gets called from mulle-craft.
Release Version | Release Notes |
---|---|
RELEASENOTES |
Essentially, mulle-craft
is a shortcut for typing:
# Build the dependencies
for project in `mulle-sourcetree craftorder`
do
for sdk in ${MULLE_CRAFT_SDKS}
do
for platform in ${MULLE_CRAFT_PLATFORMS}
do
for configuration in ${MULLE_CRAFT_CONFIGURATIONS}
do
mulle-make install --sdk "${sdk}" \
--platform "${platform}" \
--configuration "${configuration}" \
--definition-dir ".mulle/share/craft/definition" \
--definition-dir "dependency/${sdk}-${platform}/${configuration}/share/mulle-craft/${project}/definition" \
--prefix "${tmpdir}" \
"${project}"
mulle-dispense "${tmpdir}" "dependency/${sdk}-${platform}/${configuration}"
done
done
done
done
# Build the project
mulle-make craft "${PWD}"
So it's conceptually fairly simple, if you know how mulle-sourcetree and mulle-make and mulle-dispense work.
But then there are also variations and options :)
mulle-make accepts a so called definition-folder, which contains compile flags and environment variables "definitions" to craft a project. These definitions can be supplemented and overridden by an auxiliary definition folder.
In a typical mulle-sde project the main definition-folder is located in the
.main/<share|etc>/craft
folder. The auxiliary definition folder is
found inside dependency/share/mulle-craft/${projectname}
.
This location is called the "craftinfo" as it can also contain other craft
related information besides the definitions..
These definitions can be platform specific. A folder suffix distinguishes between the definitions for the various platforms. It is one of mulle-craft tasks to pick the right definition-folders and feed them to mulle-make.
First the dependency/share/mulle-craft
folder will be searched
for matching folders. A match is made if the name of the to-be-built
project is the same as the craftinfo name (without extension).
Inside the craftinfo folder there are the "definitions". A definition-folder
may have an extension (one of the platform specific.mulle-craft uname
outputs. A definition-folder with a matching extension is preferred over a
matching name with no extension.
If mulle-craft finds no info-folder there then a project specific
.mulle/etc/craft
or .mulle/share/craft
folder is searched if present.
mulle-craft builds dependencies in various configuration such as unoptimized (Debug) or optimized (Release). It can also craft for multiple SDKs and platforms. If only a single depedency folder destination were to be used the outputs of the various configurations would clobber each other. That's where the dispense style comes into play.
The easiest to understand is the strict style.
In this picture for simplicity it is assumed that there is only one platform. Otherwise the "sdk" folders would be multiplied by the number of platforms to craft for (with the platform name appended)
The auto
style is the default and it is somewhat more convenient in actual
usage:
Here the contents of the "Release" folders are moved upwards and the "Release" folder itself is deleted.
A craftorder file contains the project to craft and a list of marks that determine how to craft it:
These are the marks understood by mulle-craft:
Mark | Description |
---|---|
no-craft-configuration-<c> |
Ignore dependency for this configuration. |
no-craft-os-<os> |
Ignore dependency when the host run this OS. |
no-craft-platform-<os> |
Ignore dependency for this platform. |
no-craft-sdk-<sdk> |
Ignore dependency for this sdk. |
no-dependency |
Dont't build this if --no-dependency was specified. (1) |
no-dynamic-link |
Call mulle-make with --library-style static . |
no-inplace |
Call mulle-dispense after the build. |
no-mainproject |
Marks a subproject. (1) |
no-memo |
Ignore build result value (only used by subprojects). (1) |
no-require-configuration-<c> |
Ignore if missing for this configuration (e.g. Release). |
no-require-os-<os> |
Ignore if missing and host runs this particular OS. |
no-require-platform-<os> |
Ignore if missing and destination platform is this OS. |
no-require-sdk-<sdk> |
Ignore if missing and sdk is this SDK. |
no-require |
Ignore if missing. |
no-rootheader |
Call mulle-dispense with --header-dir 'include/${name}' . |
no-static-link |
Call mulle-make with --library-style dynamic . |
only-liftheaders |
Call mulle-dispense with --lift-headers . |
only-standalone |
Call mulle-make with --library-style standalone . (2) |
version-max-<version> |
Maximum version of the SDK allowed. (3) |
version-min-<version> |
Minimum version of the SDK needed. (3) |
(1) Used by subproject builds only. These marks are generally not useful.
(2) Standalone shared library builds are (currently?) not used anymore.
(3) Functionality is present, but it's unused so far.
See mulle-sde-developer how to install mulle-sde, which will also install mulle-craft with required dependencies.
The command to install only the latest mulle-craft into
/usr/local
(with sudo) is:
curl -L 'https://github.com/mulle-sde/mulle-craft/archive/latest.tar.gz' \
| tar xfz - && cd 'mulle-craft-latest' && sudo ./bin/installer /usr/local
Nat! for Mulle kybernetiK