Skip to content

Formula Development Guide

peterl94 edited this page Oct 23, 2014 · 1 revision

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

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.

Dependencies

Other formulas can be specified as dependencies using the add_deps function in the constructor.

self.add_deps("python", "qt")

Build

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"])

Install

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)

Formula Options

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'.

Patches

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

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
Clone this wiki locally