HACKING 9.18 KB
Newer Older
1
Bootstraping from GIT:
2
======================
3
4
5

Some files in SPOT's source tree are generated.  They are distributed
so that users do not need to tools to rebuild them, but we don't keep
6
all of them under GIT because it can generate lots of changes or
7
8
conflicts.

9
Here are the tools you need to bootstrap the GIT tree, or more
10
generally if you plan to regenerate some of the generated files.
11

12
  GNU Autoconf >= 2.61
13
  GNU Automake >= 1.11
14
  GNU Libtool >= 2.2
15
16
  GNU Flex (the version seems to matters, we used 2.5.35)
  GNU Bison >= 2.4.2
17
  SWIG >= 1.3.31
18
  Doxygen >= 1.4.0
19

20
Bootstrap the GIT tree by running
21

22
  autoreconf -vfi
23

24
and then go on with the usual
25
26
27
28

  ./configure
  make

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
Tricks
======

Avoiding Doxygen runs
---------------------

When there is no documentation built (e.g., after a fresh checkout
of the GIT tree), when the configure.ac file has changed, or when
the Doxygen configuration has changed, the doc will be rebuilt.

This can take quite some time, even though recent version of Doxygen
have started to parallelize things.  If you have no interest
in generating the documentation, just use the "magic touch":

  touch doc/stamp

Do that right before running make.  The timestamp of doc/stamp
is compared to configure.ac and Doxygen.in to decide if the
documentation is out-of-date.  The above command pretends the
documentation has just been built.


Debugging Libtool executables
-----------------------------

The executable generated in the various testsuite directories of Spot,
are not real binaries.  Because we use libtool to compile the spot
library in a portable manner, these executable are just script that
run the actual binary after setting some environment variable so that
the OS can find the library in the build tree.

A consequence is that tools like gdb or valgrind, that expect to
work on a binary, will be confused by the script.  Example:

  % cd src/tgbatest
  % file ltl2tgba
  ltl2tgba: POSIX shell script text executable
  % gdb -q ltl2tgba
  "/home/adl/git/spot/src/tgbatest/ltl2tgba": not in executable format: File format not recognized
  (gdb) quit

The proper way to work on these libtool scripts is via the libtool
command:

  % ../../libtool --mode=execute file ltl2tgba
  /home/adl/git/spot/src/tgbatest/.libs/lt-ltl2tgba: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
  % ../../libtool --mode=execute gdb -q ltl2tgba
  Reading symbols from /home/adl/git/spot/src/tgbatest/.libs/lt-ltl2tgba...done.
  (gdb) quit

If you are building Spot from the GIT repository the libtool script
generated the root of the build tree should be the same as the libtool
script that is installed on your system.  So you can simply run
libtool instead of ../../libtool.

You might also find conveniant to define a alias, a function, or a
script to shorten the invocation of "libtool --mode=execute".

Also there is an undocumented feature of libtool that allows you to
shorthand "libtool --mode=execute" as "libtool execute" or even
"libtool e".


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
Running coverage tests
----------------------

First, compile (and link) Spot with coverage enabled.

  % ./configure CXX='gcc --coverage'
  % make

Then run the test suite (or any program you want to study).

  % make check

Executing programs using Spot will generate a lot of *.gc* files
everywhere.  Collect these using lcov:

  % lcov --capture --directory src --output spot.info

Finally generate a coverage report in HTML:

  % genhtml --legend --demangle-cpp --output-directory html spot.info

This should create the directory html/.


117
118
119
120
Coding conventions:
===================

Here are the conventions we follow in Spot, so that the code looks
121
122
123
124
125
126
homogeneous.  Please follow these strictly.  Since this is free
software, uniformity of the code matters a lot.  Most of these
conventions are derived from the GNU Coding Standards
(http://www.gnu.org/prep/standards.html) with the notable exception
that we do not put a space before the opening parenthesis in function
calls (this is hardly readable when chaining method calls).
127
128
129
130
131
132
133
134
135
136

Comments
--------

  * The language to use is American.

  * When comments are sentences, they should start with a capital and
    end with a dot.  Dots that end sentences should be followed by two
    spaces (i.e., American typing convention), like in this paragraph.

137
138
139
  * Prefer C++-style comments (// foo) to C-style comments (/* foo */).
    Use /// for Doxygen comments.

140
141
142
Formating
---------

143
  * Braces are always on their own line.
144
145
146
147
148

  * Text within braces is two-space indented.

    {
      f(12);
149

150
151
152
153
154
155
156
157
158
159
160
161
    }

  * Anything after a control statement is two-space indented.  This
    includes braces.

    if (test)
      {
        f(123);
	while (test2)
	  g(456);
      }

162
  * Braces from function/structure/enum/class/namespace definitions
163
164
165
166
167
168
169
170
171
172
173
    are not indented.

    class foo
    {
    public:
      Foo();
    protected:
      static int get_mumble();
    };

  * The above corresponds to the `gnu' indentation style under Emacs.
174
175
176

  * Put return types and linkage specifiers on their own line in
    function/method _definitions_:
177
178
179
180
181
182
183
184
185

    static int
    Foo::get_mumble()
    {
      return 2;
    }

    This makes it easier to grep functions in the code.

186
187
188
    Function/method declaration are usually written on one line:

    int get_bar(int i);
189

190
  * Put a space before the opening parenthesis in control statements
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

    if (test)
      {
        do
	  {
	    something();
	  }
	while (0);
      }

  * No space before parentheses in function calls.
    (`some()->foo()->bar()' is far more readable than
    `some ()->foo ()->bar ()' is)

  * No space after opening or before closing parentheses, however
    put a space after commas (as in english).
207

208
    func(arg1, arg2, arg3);
209

210
211
212
213
214
215
216
217
218
  * No useless parentheses in return statements.

    return 2;    (not `return (2);')

  * Spaces around infix binary or ternary operators:

    2 + 2;
    a = b;
    a <<= (3 + 5) * 3 + f(67 + (really ? 45 : 0));
219

Alexandre Duret-Lutz's avatar
typo    
Alexandre Duret-Lutz committed
220
221
  * No space after prefix unary operators, or before postfix unary
    operators:
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

    if (!test && y++ != 0)
      {
        ++x;
      }

  * When an expression spans over several lines, split it before
    operators.  If it's inside a parenthesis, the following lines
    should be 1-indented w.r.t. the opening parenthesis.

    if (foo_this_is_long && bar > win(x, y, z)
        && !remaining_condition)
      {
        ...
      }

238
239
  * `else if' can be put as-is on a single line.

240
241
  * No line should be larger than 80 columns.
    If a line takes more than 80 columns, split it or rethink it.
242

243
  * Labels or case statements are back-indented by two spaces,
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
244
    without space before the `:'.
245

Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
    if (something)
      {
      top:
        bar = foo();
        switch (something_else)
	  {
	  case first_case:
	    f();
	    break;
	  case second_case:
	    g();
	    break;
	  default:
	    goto top;
	  }
      }

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  * Pointers and references are part of the type, and should be put
    near the type, not near the variable.

      int* p;        // not `int *p;'
      list& l;       // not `list &l;'
      void* magic(); // not `void *magic();'

  * Do not declare many variables on one line.
    Use
      int* p;
      int* q;
    instead of
      int *p, *q;
    The former declarations also allow you to describe each variable.

  * The include guard for src/somedir/foo.hh is
    SPOT_SOMEDIR_FOO_HH


282
283
284
285
286
287
288
289
290
Naming
======

  * Functions, methods, types, classes, etc. are named with lowercase
    letters, using an underscore to separate words.

      int compute_this_and_that();

      class this_is_a_class;
291

292
293
294
295
      typedef int int_array[];

    That is the style used in STL.

296
  * Private members end with an underscore.
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317

    class my_class
    {
    public:
      ...
      int get_val() const;
    private:
      int name_;
    };

  * Identifiers (even internal) starting with `_' are best avoided
    to limit clashes with system definitions.

  * Template arguments use capitalized name, with joined words.

    template <class T, int NumberOfThings>
    class foo
    {
      ...
    };

318
  * Enum members also use capitalized name, with joined words.
319
320
321

  * C Macros are all uppercase.

322
323
  * Use *.hxx for the implementation of templates that are private
    to Spot (i.e. not installed) and need to be included multiple times.
324

325
326
Other style recommandations
===========================
327

328
329
  * Do not use the NULL macro, it is not always implemented in a way
    which is compatible with all pointer types.  Always use 0 instead.
330

331
332
333
334
335
  * Limit the scope of local variables by defining them as late as
    possible.  Do not reuse a local variables for two different things.

  * Do not systematically initialise local variables with 0 or other
    meaningless values.  This hides errors to valgrind.
336
337
338
339
340

  * Avoid <iostream>, <ostream>, etc. in headers whenever possible.
    Prefer <iosfwd> when predeclarations are sufficient, and then
    use for instance use just <ostream> in the corresponding .cc file.
    (A plain <iostream> is needed when using std::cout, std::cerr, etc.)
341
342
343
344
345
346

  * Always declare helper functions and other local class definitions
    (used in a single .cc files) in anonymous namespaces.  (The risk
    otherwise is to declare two classes with the same name: the linker
    will ignore one of the two silently.  The resulting bugs are often
    difficult to understand.)