Skip to content

Latest commit

 

History

History
282 lines (191 loc) · 9.5 KB

manual.rst

File metadata and controls

282 lines (191 loc) · 9.5 KB

Pymake2 Manual

1   Guide

1.1   Configuring your project

To use pymake3 in your projects, download the latest pymake3 release and store the binary file in your project. Normally, pymake3 should be stored in a build directory in your project root, but this can be configured.

You also need to write a make script. To get started quickly, you could take a look at one of the examples

When you have saved pymake3 and your make script into your project directory, you can run it by invoking your make script in the project root. If, for example, you saved your script to make.py, begin making your project by typing python make.py in your project root. Alternatively, you can just type ./make.py if you're using Linux.

1.2   Writing make scripts

Make scripts for pymake3 are written in the Python programming language. For the sake of clarity, we discuss a few aspects of pymake3 individually before presenting a complete make script.

Firstly, you should place pymake3 in the build directory in your project root. Then, pymake3 can be imported into your make script in the following way:

import sys
sys.path.insert(0, 'build/pymake3')
from pymake3 import *

After this, we can start building the make script by defining our targets. Defining a target is trivial:

@target
def my_target(conf):
    print 'hello from my_target!'

That's it! That is all that is needed for pymake3 to register your target and be able to make it. Some targets need to be sure that other targets have been completed first. For example, before linking an executable, we need to compile it. This can be achieved easily by specifying dependencies on your targets:

@target
def compile(conf):
    print 'compiling', conf.name

@target
@depends_on('compile')
def link(conf):
    print 'linking', conf.name

By specifying dependencies, you ensure that they will always be completed before a target is made. In the case above, the compile target will always be made before the link target.

At the end of your make script, you need to begin the make process by calling the pymake3() function. Normally, you want to pass a configuration object to the function and use it in your targets. In this example, we pass in a name since we used it in the target examples above:

pymake3({ 'name': 'my_program' })

As we now have a basic understanding of how pymake3 operates, let's look at a more complex make script. Read the comments carefully.

#!/usr/bin/env python

import os, sys

# We need to insert the path to pymake3.py below to be able to import it.  In
# this script, pymake3 is expected to be located in build/pymake3/.
sys.path.insert(0, os.path.join('build', 'pymake3'))
from pymake3 import *

# Import the C# template for csc.exe.
from pymake3.template.csharp import csc

@target
def my_first_target(conf):
    # Pymake2 passes the configuration in the conf parameter, where each setting
    # is an attribute.  For example, we can print the name setting in the
    # following way:
    print 'name is', conf.name

    # Note that the attributes depend on the configuration passed to pymake3.
    # Pymake2 does not care about your configuration and will only pass it on to
    # your targets as you provided it.
    pass

# We can specify targets that depend on other targets, as below.  The
# dependencies will always be invoked before this target is invoked.
#     Although we use the @depends_on decorator below, we could also have typed
# @target(depends=[ 'my_first_target' ])
@target
@depends_on('my_first_target')
def my_second_target(conf):
    print 'my second target will always be invoked *after* my first target!'

# The csc template provides the target 'compile', among others.  If we wanted to
# replace it, we can specify it again here.  It will overwrite the target that
# we imported with 'import csc'.
@target
def compile(conf):
    # This target will replace the target in the csc template.  We can still
    # invoke the target from the template, if we, for example, wanted to wrap
    # the target with more functionality.
    print 'now calling csc.compile'
    csc.compile(conf)

# The configuration below depends on the backend used for the make process.  In
# this case, we're using csc, which uses the settings below, among others.
pymake3({
    'name': 'HelloWorld.exe',

    'flags': ['/target:exe',
              '/o',
              '/platform:anycpu'],

    # These are the libraries referenced by the program.  We can also add the
    # libdirs setting to add directories to look in for libraries during
    # compilation.  Again, this is dependent on your targets.
    'libs': ['System.dll'],

    # Output the executable into the current directory. If we changed this to
    # 'bin', a directory named bin would be created, and the compiled executable
    # would be stored in it.
    'bindir': '.',

    # We have our source files in the current directory in this example.  More
    # source could be added in the source directory, and they would all be
    # automatically compiled by pymake3.
    'srcdir': '.'
})

As you can tell by now, pymake3 is almost infinitely flexible and can be used for any kind of project.

1.3   Making your projects

When you have written your make script and saved pymake3 in your project build directory, you can make your project easily by invoking your make script.

If, for example, you saved your script to make.py in your project root, you can run it by typing python make.py to make the default target if there is one. If you want to specify what target to make, you can type python make.py my_target_name. Dependencies will automatically be resolved, so even if you attempt to invoke the link target from the examples above, the compile target will be invoked before it.

If you are unsure what targets are available, just type python make.py --targets to see a list of them.

2   Quick Reference

2.1   Copying files/directories

Copying files (for example, copying resource files to the bin directory when building an executable) can easily be done with the copy() function:

@target
def copy_assets(conf):
    num = copy(conf.assetsdir, conf.bindir, '*.wav')
    trace('{} files copied', num)

If a directory path is passed to the copy() function, that directory is copied recursively to the target path. If the source path is a file, that file will be copied. Optionally, a filename pattern can be specfied, as in the case above. Only files matching the pattern will be copied.

2.2   Creating directories

Directories are created with the create_dir() function:

@target
def compile(conf):
    create_dir(conf.bindir)
    # ...

The directory will be created if it does not already exist.

2.3   Defining a target

A pymake3 target is defined by applying the @target decorator to a function:

@target
def my_target(conf):
    # ...

A target function always takes in a conf argument containing the pymake3 configuration. The target's name is the name of the function, unless another name is specified:

@target(name='a_target')
def my_target(conf):
    # ...

The configuration can be set to a default for each target:

@target(conf={ text: 'foo'  })
def my_target(conf):
    print conf.text # Prints 'foo' unless the user provided configuration
                    # overrides it with some other value.

2.4   Deleting directories

Delete directories with the delete_dir() function:

@target
def clean(conf):
    delete_dir(conf.bindir)
    delete_dir(conf.objdir)

2.5   Deleting files

Files can be deleted with the delete_file() function:

@target
def clean(conf):
    delete_file('my_file.xyz')

2.6   Finding files

Files can be found with the find_files() function, when you, for example, need to find all source files to compile:

@target
def compile(conf):
    sources = find_files(conf.srcdir, '*.c')
    # ...

2.7   Running programs

Run programs with the run_program() function:

@target
def compile(conf):
    run_program('g++', ['hello.cpp', '-o', 'hello'])

2.8   Specifying dependencies

Pymake2 targets can depend on other targets. Dependencies are specified with the @depends_on decorator:

@target
@depends_on('my_target')
def my_other_target(conf):
    # my_target will always be invoked before we reach this point

3   Templates

Pymake2 comes with several ready-made templates for making different kinds of projects. The templates vary greatly depending on area of use, and therefore have their own documentation. Below is a list of the templates; click on one to read more about it.

3.1   C#

3.2   LaTeX

3.3   Utility