Formula Development Guide
A CLbundler formula is a Python script containing a class that inherits the Formula class. See libpng.py for a good example of a complete formula. The following code is the required boilerplate.
from clbundler.formula import *
class example(Formula):
version = ""
source = {
"type":"",
"url":""
}
supported = {}
def __init__(self, context, options={}):
super(example, self).__init__(context, options)
def build(self):
files = FileSet()
return files
version
This can be any string, but it must not be empty.
source
The value of 'type' can be 'archive', 'git', 'hg', or 'svn'. The value of 'url' should be a valid url for the given type. Additionally, when type is a VCS, the 'revision' key can be used to specify a revision understood by that VCS.
supported
This defines what toolchains and architectures can be used. For example, supported = {"vc9":["x86", "x64"]}
means that the formula can only build the software package using the Visual Studio 2008 x86 or x64 toolchains.
The context passed to the formula constructor is stored as an instance variable, and has the following attributes:
-
os_name
Either 'win' or 'mac' -
toolchain
The current toolchain being used (e.g. 'vc9') -
arch
The architecture of the output of the toolchain ('x86' or 'x64') -
env
The environment being used (a copy of os.environ) -
bundle_path
The bundle directory path -
build_dir
The path of the directory where packages are built -
install_dir
The path to a temporary install location.
Other formulas can be specified as dependencies using the add_deps function in the constructor.
self.add_deps("python", "qt")
Depending on what build system the software package uses, there might be a convenience function that can be used. See buildtools.py for all the available build tool functions. Otherwise, use system.run_cmd to run the needed executable. Note: the current working directory will be the top-level source directory.
cmake(self.context, {"CMAKE_DEBUG_POSTFIX":"d"})
vcbuild(self.context, "cmake_build\\qhull.sln", "Release")
system.run_cmd("nmake", ["/f", "makefile.vc"])
Do not directly copy files into the bundle directory. Instead, add the file paths to a FileSet object. If the build files have an install operation, you may want to first install the files to self.context.install_dir
.
FileSet.add(patterns, dest, exclude=[], category=Categories.run)
patterns
A list of paths to copy to dest. All fnmatch wildcards can be used as well as the recursive wildcard **
. Note: pattern matching is done per path component. Also, relative paths are made absolute using the working directory at the time add was called.
dest
A subdirectory of the bundle that the given files will be copied to.
exclude
A list of files that should not be copied
category
Describes when the files will be needed. Can be Categories.run, Categories.run_dbg, Categories.build, or Categories.buid_dbg
The following example illustrates some commonly used patterns.
#matches everything in 'include' except .pri files
files.add(["include/*"], "include", exclude=["**/*.pri"], category=Categories.build)
#matches all .h files in 'tools'
files.add(["tools/**/*.h"], "tools", category=Categories.build)
files.add(["lib/*.lib", "lib/*.pdb"], "lib", category=Categories.build)
files.add(["bin/*[!d].dll"], "bin", category=Categories.run)
files.add(["bin/*d.dll"], "bin", category=Categories.run_dbg)
Every formula has a variant attribute whose value can be set using the --variant command line option. The variant option is used to specify what configuration should be built. The value can be either 'release', 'debug', or 'release+debug'.
If a package needs to be patched, add the names of the patches (with no extension) to the patches attribute in the formula's constructor.
self.patches = ["msvc9_fix"]
In order for the patches to be found, they need to have a .diff extension and need to be in a directory with same name as the formula. Additionally, this directory needs to be inside a directory named patches that is at the same level as the formula.
formulas/
qhull.py
patches/
qhull/
msvc9_fix.diff
Note: patches are applied using -p1 so the the path should include the top-level directory.
--- pcl-1.7.2/tools/gp3_surface.cpp Wed Sep 10 14:22:57 2014
+++ pcl-1.7.2_new/tools/gp3_surface.cpp Sun Oct 19 23:12:20 2014
Formula kits are a way to group together formulas into one meta formula. They are implemented as Python packages. The init.py is what defines the kit, and has to contain a Formula class with self.is_kit = True
.
from clbundler.formula import *
class freecad(Formula):
def __init__(self, context, options={}):
super(freecad, self).__init__(context, options)
self.is_kit = True
self.add_deps("python", "qt")
An example kit directory structure is as follows. Notice that formulas and patches can be put in platform specific directories.
freecad/
__init__.py
patches
mac/
python.py
win/
patches
python.py
qt.py