]> Creatis software - gdcm.git/blob - DEVELOPPER
Memo for gcc flags added.
[gdcm.git] / DEVELOPPER
1 The following comments are intended for core gdcm developpers.
2
3 * Compiling gdcm:
4   - Checkout the sources to an arbitrary directory noted GDCM (e.g. ~/cvs/gdcm).
5   - Checkout the test images to an arbitrary directory noted GDCMDATA
6     (e.g. ~/cvs/gdcm/gdcmData).
7   - Optionally create a temporary installation directory GDCMINSTALL e.g.
8     mkdir /tmp/gdcminstall
9   - Create a target directory GDCMBIN e.g.
10     mkdir /tmp/gdcmbin
11   - Configure cmake from GDCMBIN:
12     cd GDCMBIN
13     ccmake GDCM
14       * Toggle and adjust the required options and parameters, mainly
15         -- GDCM_DATA_ROOT should be set to GDCMDATA
16         -- CMAKE_INSTALL_PREFIX (equivalent of --prefix of the autotools)
17            should be set to GDCMINSTALL
18         -- CMAKE_BUILD_TYPE set to Debug or Release
19         -- GDCM_DOXYGEN 
20         -- GDCM_VTK When this option is on VTK_DIR might require manual
21            configuration
22         -- GDCM_WRAP_PYTHON
23         -- CMAKE_CXX_FLAGS (when working with gcc of course) should be set to
24            -g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter
25            -Wunused-function -Wunused -Wno-system-headers -Wno-deprecated
26            -Woverloaded-virtual
27            (this is to avoid spurious problems with overloading)
28       * Configure cmake: hit c
29       * Generate the makefiles (or dsw): hit g
30   - Compile gdcm
31     make  
32   - Run the tests manually (optional):
33     Caveat: if you run the tests before installing, you NEED to positionate
34             the environment variable GDCM_DICT_PATH to GDCM/Dicts e.g.
35             export GDCM_DICT_PATH=~/cvs/gdcm/Dicts
36     Assuming your cwd is GDCMBIN, three modes are then available:
37     -- 1/ acces to a by number:
38           ./Test/gdcmCxxTests
39     -- 2/ acces to a test by it's name, by passing it as argument to
40           gdcmCxxTests e.g.
41           ./Test/gdcmCxxTests hashtest
42     -- 3/ launch all the full test suite (again we assume cwd is GDCMBIN):
43           ctest
44           This is equivalent to "make test".
45           Note: ctest supports the argument filtering with regexp and
46                 the verbose mode e.g.
47                    ctest -R print -V
48                 proposes the tests containing "print" in their name and
49                 makes a verbose output. For other options refer to the
50                 documentation at http://www.cmake.org.
51
52 * Sending the result to kitware's dashboard (optional)
53   ctest -D Experimental
54   The results should appear in
55      http://public.kitware.com/dashboard.php?name=public
56      under the name of your machine (uname), but for ease of use you can
57      change the SITE variable in your CMakeCache.txt to something more 
58      accurate such as: GDCM-my_machine_name. The entry will then be within 
59      the "Experimental Builds" entry.
60
61 * Install gdcm (as specified by CMAKE_INSTALL_PREFIX)
62   make install
63   Note: the dictionaries used by gdcm are now located in
64         CMAKE_INSTALL_PREFIX + /share/ (i.e. GDCMINSTALL + /share/ if you
65         followed the above instructions).
66
67 * Python related section.
68   Depending on the cmake flags you used in order to compile gdcm could
69   be wrapped in two ways:
70   - the first python wrappers of gdcm uses Swig (http://www.swig.org). These
71     are the one generated when using autogen.sh --enable-python. 
72     The entry point here is the file gdcmPython/gdcm.i which uses the
73     Swig syntax. As the last lines of this file (the ones starting
74     with the %include directive) only some classes are wrapped for python.
75     In theory only the library interface (basically the classes gdcmHeader
76     and gdcmFile) should be wrapped, but the time being some additional
77     classes are added (just to make sure those classes are Swig compatible:
78     swig is here used as some link checker!?).
79     Since gdcm is written in C++, Swig will produce two different outputs:
80       -- some C based low level wrapper (see gdcmPython/gdcm_wrap.c)
81       -- some Python based object oriented so called "shadow classes" (see
82          file gdcmPython/gdcm.py)
83     We also added the file gdcmPython/__init__.py which is the one that
84     actually gets loaded when one uses the gdcmPython Python package.
85     The file __init__.py loads the Swig generated shadow classes (gdcm.py)
86     but will only re-export the interface of gdcm which corresponds to
87     the lines :
88        gdcmHeader = gdcm.gdcmHeader
89        gdcmDictSet = gdcm.gdcmDictSet
90        gdcmFile = gdcm.gdcmFile
91        [etc.]
92     Hence this whole Swig wrapping process is quite odd since we shall
93     wrap more classes (%include in swig.i) that eventually get exported to
94     the final user by gdcmPython/__init__.py.
95   - the second python wrappers uses the vtk (http://public.kitware.com/VTK/)
96     native wrappers i.e. the binary vtkWrapPython. But it should be noticed
97     that the purpose is here a bit different than the one of the Swig
98     generated Python wrappers. When using vtkWrapPython the goal is to
99     wrap a single vtk class namely vtkGdcmReader as defined in files
100     vtk/vtkGdcmReader.h and vtk/vtkGdcmReader.cxx (and of course those
101     files are hand made vtk oriented wrappers of gdcm).
102     Those wrappers are the one generated when using
103        autogen.sh --enable-python --enable-vtk
104   - In order to understand the difference between both wrappers you should 
105     compare both demo scripts gdcmPython/demo/vtkGdcmDemo.py and
106     gdcmPython/demo/vtkGdcmReader.py. The first one only uses the
107     Swig wrapped classes ("from gdcmPython import gdcmHeader') as opposed
108     to vtkGdcmReader.py which also uses vtkWrapPython wrapped classes
109     ("from gdcmPython.vtkgdcmPython import *").
110     
111 ------------------------------------------------------------------------------
112 gdcm coding style and religious/agnostic beliefs (proposition)
113    
114 * Introduction:
115    The following coding style intends to ease the work of developpers
116    themselves but also of users who will study, maintain, fix, and extend
117    the code. Any bread crumbs that you can drop in the way of explanatory
118    names and comments will go a long way towards helping other readers and
119    developers.
120    Keep in mind that to a large extent the structure of code directly
121    expresses its implementation.
122
123 * Language:
124  - C++ (for the kernel) and Python (for the wrappers).
125  - all the names (variables, members, methods, functions) and comments
126    should be based on English. Documentation, guides, web site and other
127    informations should be in English.
128    Make sure you use correct (basic) English and complete, grammatically
129    correct sentences for comments and documentation.
130
131 * General layout:
132  - Each line of code should take no more than 79 characters. Break the code
133    across multiple lines as necessary. 
134  - Methods and functions should keep a reasonable number of lines when
135    possible (a typical editor displays 50 lines). Avoid code duplication.
136    Always prefer creating a new method or function to duplication.
137    A high indentation level generally suggests the need for a new
138    method or function.
139  - All the code should be properly indented. The appropriate indentation
140    level is three spaces for each level of indentation. DO NOT USE TABS.
141    Set up your editor to insert spaces. Using tabs may look good in your
142    editor but will wreak havoc in others, or in external tools (e.g. side
143    by side diffs).
144  - The declaration of variables within classes, methods, and functions
145    should be one declaration per line. Provide them with default values
146    and don't rely on compilers for default initialization.
147
148 * Naming conventions:
149  - Generalities:
150    In general, names are constructued by using case change to indicate
151    separate words, as in ImageDataSize (standing for "image data size").
152    Underscores are not used. Variable names are chosen carefully with the
153    intention to convey the meaning behind the code. Names are generally
154    spelled out; use of abbreviations is discouraged.
155    [Note: abbreviation are allowable when in common use, and should be in
156     uppercase as in LUT or RGBA.]
157    While this does result in long names, it self-documents the code.
158  - Naming Files:
159    Files should have the same name as the class, with a "gdcm" prepended.
160    Header files are named .h, while implementation files are named either
161    .cxx or .txx, depending on whether they are implementations of templated
162    classes. For example, the class gdcm::Document is declared and defined
163    in the files gdcmDocument.h and gdcmDocument.cxx.
164  - Naming Class Data Members, Methods, and Functions:
165    Class data members are named beginning with a capital letter as in
166    GroupPixel.
167    Global functions and class methods, either static or class members, are
168    named beginning with a capital letter, as in GetImageDataSize().
169  - Naming Local Variables:
170    Local variables begin in lowercase. There is more flexibility in the
171    naming of local variables although they still should convey some
172    semantics.
173
174 * Classes:
175  - Don't use the inline keyword when defining an inline function
176    within a class definition.
177  - Do not repeat the virtual keyword when overriding virtual base methods
178    in declaration of subclasses:
179      class A 
180      {
181         virtual void foo(...);
182      };
183      class B: public A
184      {
185         void foo(...);          // and not: virtual void foo(...);
186      };
187  - The public, protected, private declarations should be at the
188    same indent level as the class. Use
189      class A 
190      {
191      private:
192         void foo(...);
193      public:
194         void bar(...);
195      };
196  - Method and functions devoided of arguments should not use the void
197    notation. Use
198      SomeType Header::GetPixelData()
199    and not
200      SomeType Header::GetPixelData(void).
201
202 * Use of braces:
203  - Braces must be used to delimit the scope of an if, for, while, switch, or
204    other control structure. Braces are placed on a line by themselves, and
205    at the same indentation level as the control structure to which they
206    belong:
207       for (i=0; * i<3; i++)
208       {
209          ...
210       }
211    or when using an if:
212       if ( condition )
213       {
214          ...
215       }
216       else if ( other condition )
217       {
218          ...
219       }
220       else
221       {
222          ....
223       }
224    You can choose to use braces on a line with a code block when
225    the block consists of a single line:
226       if ( condition ) { foo=1; }
227       else if ( condition2 ) { foo=3; }
228       else { return; }
229    or
230       for (i=0; i<3; ++i) {x[i]=0.0;}
231    Methods and functions should follow the same usage of braces:
232       void File::ParsePixelData()
233       {
234          ...
235       }
236
237 * Special layout:
238  - Avoid code mixed with comments on a single line. Instead, prepend the
239    logical blocks of code with the concerned comments.
240  - Use parantheses around conditions e.g. with an if statement: 
241       if ( someLocalVariable == 2 ) { ... }
242  - Add spaces around parantheses, or braces. Use
243       if ( someLocalVariable == 2 ) { ClassMenber += 1; }
244    and not
245       if (someLocalVariable == 2) {ClassMenber += 1;}
246  - Add spaces around each side of the assignement operator, and
247    around binary operators used in boolean expression. Use
248       someLocalVariable = ClassMember * 2;
249       if ( someLocalVariable == 2 || ClassMember == 2 ) ...
250    and not
251       someLocalVariable=ClassMember*2;
252       if ( someLocalVariable==2||ClassMember==2 ) ...
253
254 * Miscelaneous:
255  - Don't use underscores. Don't use tabs. Don't use control characters
256    like ^M. Anyhow, cvs is configured to reject such commits.
257  - Comments should be in C++ style ("// ...", two slashes, per line). Don't
258    use C style comments ("/* ... */").
259  - The last line of a file should terminate with "\n".
260  - Returned arguments of methods and functions should not be wrapped with
261    parantheses. Use 
262       return iter->second;
263    but do not use
264       return ( iter->second );
265
266 * Debugging and Verbose modes:
267    Never use std::cout. Instead use the gdcmDebug class through the
268    global instance dbg. Example:
269       #include "gdcmDebug.h"
270       ...
271       {
272          dbg.Verbose(3, "Local function name: entering.");
273          ...
274       }
275     will send the message to std::cout when dbg.Debug() is called
276     in your main.
277
278 * Documentation:
279    The Doxygen open-source system is used to generate on-line documentation.
280    Doxygen requires the embedding of simple comments in the code which is in
281    turn extracted and formatted into documentation. See
282       http://www.stack.nl/ dimitri/doxygen/
283    for more information about Doxygen.
284  - Documenting a class:
285    Classes should be documented using the class and brief doxygen commands,
286    followed by the detailed class description:
287       /**
288        * \class Header
289        * \brief Header acts as container of Dicom elements of an image.
290        *
291        * Detailed description of the class is provided here
292        * ...
293        */
294    The key here is that the comment starts with /**, each subsequent line has
295    an aligned *, and the comment block terminates with a */.
296  - Documenting class members and inline methods:
297    All the members and the inline methods should be documented within
298    the class declaration as shown in the following example:
299       class Header
300       {
301          /// True when parsing was succefull. False otherwise.
302          bool Readable = false;
303
304          /// \brief The number of lines of the image as interpreted from
305          /// the various elements encountered at header parsing.
306          int NumberOfLines = -1;
307
308          /// Predicate implemented as accessor around \ref Readable.
309          bool IsReadable() { return Readable; }
310       };
311  - Documenting a Method:
312    Methods should be documented using the following comment block style
313    as shown in the following example:
314
315       /**
316        * \brief  Within the Dicom Elements (parsed with the public and private
317        *         dictionaries), look for the element value representation of
318        *         a given tag.
319        * @param  group Group number of the searched tag.
320        * @param  element Element number of the searched tag.
321        * @return Corresponding element value representation when it exists,
322        *         and the string "gdcm::Unfound" otherwise.
323        */
324       std::string Document::GetEntryByNumber(guint16 group, guint16 element)
325       {
326          ...
327       }
328
329 * External includes and C style:
330  - Only the C++ standard library and the STL includes should be used.
331    When including don't use the .h extension (use #include <iostream>
332    instead of #include <iostream.h>).
333  - Don't use the C standard library. Don't include stdio.h, ctype.h...
334    Don't use printf(), sprinf(), FILE*...
335  - Don't use the NULL notation (either as macro, or as const int NULL=0).
336    A pointer that doesn't refer to an object should simply be defined as
337       DataPointer* MyDataPointer = 0;
338
339 * Basic types:
340  - Assume T is a given type. When declaring or defining with the 
341    "pointer to T" notation, the * character must be adjacent to
342    the type and not the variable. That is use
343       T* foo = 0;
344    and not 
345       T *foo = 0;
346  - Always define a typedef for a new type and be consistent in usage.
347    Use
348       typedef Header* HeaderPointer;
349       HeaderPointer MyHeaderPointer;
350  - One notorious counter example for non using C style inclusion concerns
351    exact-width integers (since there seem to be no equivalent for C++).
352    When using exact-width integers use the typedef names defined by
353    the Basic ISO C99: 7.18 Integer types i.e.
354       int8_t     int16_t     int32_t     int64_t (signed integers)
355    and
356       uint8_t    uint16_t    uint32_t    uint64_t (unsigned integers).
357    Conversion table is then:
358     unsigned char       -> uint8_t;
359     unsigned short      -> uint16_t;
360     unsigned int        -> uint32_t;
361     unsigned long       -> uint32_t;
362     unsigned long long  -> uint64_t;
363     (signed) char       -> int8_t; 
364     short               -> int16_t; 
365     int                 -> int32_t; 
366     long                -> int32_t; 
367     long long           -> int64_t;
368    Hence do not use declarations like "unsigned int".
369    With g++, accessing those typedef is achieved by the following
370       #include <stdint.h>
371 ------------------------------------------------
372 CVS policy
373 * All the commits should be atomic. They must preserve the compilation
374   in order to prevent checkouts with broken code.
375 * All the commits must correspond to a stade of the code where ctest
376   runs and has no failing subtest. Always run ctest before commiting.
377   Note: * you can start ctest in verbose mode through the command
378              ctest -V >& log
379         * you can start a single test through ctest with
380              ctest -R FailingTestName -V >& log
381 ------------------------------------------------
382 Compiler flags policy:
383  When working with gcc please use the flags specified in DEVELOPPER file
384  (in order to avoid difficult overloading problems).
385 ------------------------------------------------