summaryrefslogtreecommitdiff
path: root/docs/source/buildfile.rst
blob: 8200fff6838d83cb67722da2d3359f4fc968df3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
First Build File
================

Hello World Example
-------------------

Writing your first ``build.py`` file is actually quite simple. It's just
Python!::

    #!/usr/bin/env python

    def helloworld():
        print("Hello World")

Running this, we should see something similar to::

    $ xnt helloworld
    Hello World

Adding Xnt to the Mix
---------------------

Let's start to add some of the features provided by Xnt::

    #!/usr/bin/env python

    from xnt import target #For describing targets
    import xnt             #For built-in tasks

    @target
    def init():
        """
        Initialize Project Build Directories
        """
        xnt.mkdir("build")

That may be a lot to take in initially. Let's step through it.

In the first section::

    #!/usr/bin/env python

    from xnt import target #For describing targets
    import xnt             #For built-in tasks

If you're familiar with Python, you will notice there is nothing special
happening with this file yet. We are simply defining the file as a Python file,
including the ``target`` attribute from the ``xnt`` module, and importing the
``xnt`` module.

A change from previous versions: importing ``xnt`` will now implicitly import
``xnt.tasks``.

Next, we will look at a new target::

    @target
    def init():
        """
        Initialize Project Build Directories
        """
        xnt.mkdir("build")

This is a standard definition of a Python function with a decorator.

First, the ``target`` decorator marks the function definition as a target (to
be used by the ``list-targets`` command, see :ref:`otherCommands`). Next, we
define the function; this function name *is* the name of the target. That is,
the name given to the function will be the name given to the command to invoke
this target.  Further, we have the docstring; (this is also used by the
``list-targets`` command) the docstring provides a quick description of the
purpose of the target, or what the target accomplishes when ran. Finally, we
call ``mkdir`` of the ``xnt`` (internally of the ``xnt.tasks``) module. This
function, if not obvious by the name, creates a directory named 'build' (see
:doc:`taskreference`).

Return Values
=============

The targets you define can return an error code (or '0' for success) however
you see fit. Xnt will emit 'Failure' if the status code is *not* zero and will
otherwise remain silent if the code is zero. Further, the status code returned
by your target will be returned as the exit code of Xnt when finished
executing.

*Notice*, this allows Xnt to fail fast when attempting to execute multiple
targets. That is, if you specify more than one target, Xnt will stop at the
first failure.

If you don't define a return value for a target, Xnt will assume success and
return '0'.

Examples
--------

Not defining the return value::

    @target
    def foo():
        pass

Will result in (no success message; other output may be shown)::

    ...

Returning success (no success message; other output may be shown)::

    @target
    def foo():
        return 0

Will result in::

    ...

Returning failure (not 0)::

    @target
    def foo():
        return 1

Will result in::

    ...
    Failure

Most tasks have been updated to return error codes as well so that you can
return what it returns. If you find any tasks that can be updated to behave
this way, please create an issue for it.

.. _buildProperties:

Build Properties
================

As mentioned in :ref:`xntPropertiesParameters`, Xnt can accept parameters from
the command line and pass them into the build file. Xnt doesn't necessarily
expect the dictionary (named `PROPERTIES`) to exist; but if you ever intend to
use it, it will have to be defined one way or another (either to an empty
dictionary or actually hold values). For example, to define an empty
`PROPERTIES` dictionary, one could write their build file as such::

    #!/usr/bin/env python

    from xnt import target

    PROPERTIES = {}

    @target
    def foo():
        #uses properties somehow
        return 0

The hope for this feature is that it is easy to use because it borrows syntax
from other build tools that you may already be familiar with.