File: HACKING

package info (click to toggle)
coin3 4.0.3%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 54,428 kB
  • sloc: cpp: 256,086; ansic: 21,309; makefile: 8,661; sh: 3,141; perl: 1,504; lex: 1,372; lisp: 1,247; pascal: 961; xml: 604; yacc: 387; sed: 68
file content (1252 lines) | stat: -rw-r--r-- 48,704 bytes parent folder | download | duplicates (2)
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
If you want to work _with_ the Coin sourcecode (not just writing
applications _using_ the Coin library) -- for helping us fixing bugs,
improve performance, or whatever reasons -- this file contains some
hints and tips for you.

==============================================================================

1 The Bleeding Edge
===================

First of all, you should make sure you are building from the latest
sources from the Mercurial repository you want to work with. This is
done by using the Mercurial for staying in sync with the sourcecode
repository we at Kongsberg Oil & Gas Technologies are using. Follow
the instructions on the webpages at
<URL:http://www.coin3d.org/doc/mercurial_access>.

Be aware that Coin has three source repositories. "Coin" is the head
development repository which is unstable and may contain unportable
code and break binary compatibility from time to time. "Coin-1" is the
repository that contains the code for the latest Coin-1.* release.
"Coin-2" is the repository we release the Coin 2.* releases from and
will always contain stable code that does not break upwards binary
compatibility. You can hack on either, but for your application
development efforts' sake you might want to follow Coin-2.

If you are not familiar with Mercurial, check out the Mercurial
homepages at <URL:http://mercurial.selenic.com/> and specifically the
Mercurial documentation in the available online book at
<URL:http://hgbook.red-bean.com/>.


2 Surviving a Large C++ Project
===============================

The main problem all large C or C++ projects bump into sooner or later
is that the turn-around time for doing compile, link and run gets too
long for development to be efficient. When we're talking re-linking of
library files of >30MB (with debug information), its gonna get painful
to do rapid incremental bugfixing / testing cycles.

So I'm going to explain now how we at SIM have (more or less
fundamentally) solved this problem for our core Coin library. First of
all: use a "UNIX-like" system. MSWindows systems are no good for
working with the kind of setup we have, we do all new development on
UNIX systems (mostly Linux and SGI IRIX) and so the build process have
been tuned for these platforms.

A typical set-up session for me for doing Coin development on a virgin
machine looks like this (I'm using SoXt as the GUI library for
demonstration purposes):

  $ cd $HOME
  $ mkdir code
  $ cd code
  $ hg clone http://hg.sim.no/simage/default simage
  [Mercurial doing its thing]
  $ hg clone http://hg.sim.no/Coin/default Coin
  [Mercurial doing its thing]
  $ hg clone http://hg.sim.no/SoXt/default SoXt
  [Mercurial doing its thing]

        Note: you might want to work with a particular branch from
        Mercurial, if so use the "branches" instead of "default"
        repository above.

        Note2: if you have already checked out the sources at an
        earlier point in time, you just ``cd'' to the sourcecode
        directories and do

        $ hg pull -u

        instead of the full checkout.


  $ export WORKDIR=<somewhere on a local disc>
  $ mkdir compile install
  $ cd $WORKDIR/compile
  $ mkdir simage Coin SoXt

  $ cd $WORKDIR/compile/simage
  $ $HOME/code/simage/configure --prefix=$WORKDIR/install
  [configure running]
  $ make install
  [build should complete quickly]

  $ cd $WORKDIR/compile/Coin
  $ $HOME/code/Coin/configure --prefix=$WORKDIR/install --enable-hacking
  [configure running]

        Note the "--enable-hacking" option to configure. This is the
        brilliant part. What happens with this option is that instead
        of making one monolithic libCoin.so file, the Coin library
        will be linked into many shared libraries, one for each
        subdirectory under $WORKDIR/compile/Coin/src/. The brilliance of
        this little trick will be explained later in the walk-through.

        Note for Mac OS X users: --enable-hacking requires Mac OS
        version 10.3 or higher. It also works with the Mac OS X
        framework build, however note that you'll need to set your
        DYLD_LIBRARY_PATH to include Inventor.framework/Libraries.
        Universal Binaries are not supported.

  $ make install

        Building will take quite some time, go for a coffee.

        The build process should complete without any compiler
        warnings or errors -- if you see any, please notify us.

        Shared library files for all sub-dirs in the Coin sourcecode
        tree should now have been installed in $WORKDIR/install, along
        with a top-level libCoin.so file.

        Now, Libtool's .la-scheme for storing information about
        installed libraries doesn't work too well when trying to build
        further Libtool-based libraries or executables with the
        "hacking enabled" Coin sub-library files. But we don't really
        lose anything important without the .la-files, so we just
        remove them:

  $ cd $WORKDIR/install/lib
  $ rm lib*LINKHACK*.la

        Next step is to configure and build an interface library which
        "connects" Coin with an underlying native 2D GUI toolkit. We
        use SoXt in the example walk-through, but you can also use
        SoQt (for TrollTech's Qt), SoGtk (for gtk+) or SoWin (for
        interfacing against "pure" Win32 API under MSWindows).

  $ cd $WORKDIR/compile/SoXt
  $ $HOME/code/SoXt/configure --prefix=$WORKDIR/install
  [configure running]
  $ make install
  [build shouldn't take long]

Ok, that's it. You should now have libsimage, libCoin and libSoXt
built and installed under $WORKDIR/install/lib/.

If you go look in the $WORKDIR/install/lib/ directory, you will see a
bunch of files named lib**something**LINKHACK.so. For each of the
"submodules" in Coin where you will be working, you should now remove
the relevant .so-files and instead symlink them directly from the
build directory. I.e., if you are going to work with the node classes,
execute the following:

  $ cd $WORKDIR/install/lib
  $ ls -c1 *nodesLINKHACK*
  libnodesLINKHACK.la*
  libnodesLINKHACK.so@
  libnodesLINKHACK.so.0@
  libnodesLINKHACK.so.0.0.0*
  $ rm libnodesLINKHACK.so.0.0.0
  $ ln -s $WORKDIR/compile/Coin/src/nodes/.libs/libnodesLINKHACK.so.0.0.0 libnodesLINKHACK.so.0.0.0

(The other two .so-files are just symlinks to the .so.0.0.0 file, so
we don't need to do anything about those.)

You should now be able to do development with very short compile &
link turn-around cycles on the classes in the $HOME/code/Coin/nodes/
directory. Each time you have made a change to the sourcecode, just

  $ cd $WORKDIR/compile/Coin/src/nodes
  $ make

Only the relevant .cpp will now be re-compiled and only the
libnodesLINKHACK.so sub-library will be re-linked. And the
libnodesLINKHACK.so in the install directory which client applications
are using is a symlink pointing to the one in your build directory, so
no re-installation need to happen.


One caveat emptor: if any of the class-definitions change in a non-ABI
compatible way in any of the corresponding .h files, you need to
recompile and relink _all_ sourcecode depending on this class, not
just the class itself. Or core dumps will happen. (See footnote 1 at
the end of this document for an explanation of the term "ABI".)

There are many, many ways to break ABI compatibility in C++:

  - variables being added or removed from / to a class, making it's
    sizeof() change
  - functions added or removed
  - functions made virtual or "un-made" from virtual
  - function signatures changed in general

  ...etc. See footnote 1 at the end of this document for more
  discussion on the issue. Anyway, as long as you're only changing the
  .cpp files, you should be home free.


Right after we implemented this scheme, there was an article called
"Pseudo-Incremental Linking For C/C++" in the Dr Dobb's Journal. The
article is available at

    <URL:http://www.ddj.com/articles/1999/9910/9910d/9910d.htm>

and explains the principles applied fairly well.


3 Debugging Tricks
==================

* COIN_DEBUG_BREAK

  All calls to SoDebugError::post*() have the first argument (the
  function name) compared to the $COIN_DEBUG_BREAK environment variable.
  If they match, an assert will fail, and you can then inspect the stack
  backtrace (if symbol/debugging information was built into the library).
  This can be very useful and is not limited to Coin usage - all client
  programs can take advantage of this functionality too.

  Example:

    $ env COIN_DEBUG_BREAK="SoAction::apply" ./mytestprogram

  [using 'env var=val prog ...' is the most portable syntax for this kind
  of thing, which is why the example uses it instead of the Bourne syntax]


* Make yourself familiar with the Valgrind tool, which is *extremely*
  useful for tracking down memory corruption problems. A link to
  Valgrind can be found on <URL:http://freshmeat.net>.

  Note that Valgrind, can also be used for profiling code _without_
  having to re-compile everything (like what is necessary for gprof,
  for instance).

  Another interesting feature of Valgrind is that it has a skin called
  "helgrind" which supposedly can do analysis of code to see if it's
  re-entrant / thread-safe. I (mortene) haven't tested it yet, but if
  it works, it would be extremely useful for debugging hard to find
  bugs suspected to be due to synchronization problems over multiple
  threads.


* OpenGL debugging:

   - Useful environment variables for the Mesa OpenGL implementation:

        * LIBGL_ALWAYS_INDIRECT=yes

          (Avoids any use of hardware acceleration -- useful for
          running Coin-on-Mesa under Valgrind.)

        * LIBGL_DEBUG=yes
        * MESA_DEBUG=yes


   - To turn off SSE/MMX use in the NVidia Linux drivers, which avoids
     problems with at least pre-2.0 Valgrind version:

        * __GL_FORCE_GENERIC_CPU=1



4 Misc Configurations
=====================

* Mercurial

  In order to allow the storage of your Mercurial password with the
  standard Mercurial command line client in a convenient but secure
  fashion have a look at the Keyring Extension:

  http://mercurial.selenic.com/wiki/KeyringExtension

  As the default on Mercurial is to prompt you for a password it is
  somewhat safe apart from the regular caveats to check in outside of
  your trusted workstation.

* emacs

  To enable C++ mode for the template *.in source files, add this to
  your ~/.emacs file:

    (setq auto-mode-alist (cons '("\\.h\\.in\\'" . c++-mode) auto-mode-alist))
    (setq auto-mode-alist (cons '("\\.cpp\\.in\\'" . c++-mode) auto-mode-alist))
    (setq auto-mode-alist (cons '("\\.icc\\'" . c++-mode) auto-mode-alist))

  Also, to make emacs insert spaces instead of tabulator characters when
  indenting (we don't want any tabulators):

    (let ((loadhook (lambda () (setq indent-tabs-mode nil))))
      (add-hook 'find-file-hooks loadhook)
      (add-hook 'find-file-not-found-hooks loadhook))

* vim

  To insert spaces instead of tab characters (using 2 space characters
  every time you press 'tab', and also using 2 spaces for
  auto-indentation), add the following to your ~/.vimrc file:

    set expandtab
    set tabstop=2
    set shiftwidth=2

* MS Visual Studio

  Under tools -> options, choose the Tabs group and check the radio button
  that says "insert spaces" and choose tab size 2.


5 The Build Environment
=======================

* Defines

  HAVE_CONFIG_H

    This define should always be defined, but if it isn't, then the
    config.h header will not be included.  Lots of features will then be
    disabled.  Lots of files will probably not even compile since we do
    not test this case.  Anyways, this case is usually the case when
    someone tries building the library without using the Autoconf setup.

  COIN_INTERNAL

    This is a define that is set when the Coin library is being compiled.
    Setting it when compiling things outside the Coin library is a
    mistake.

  COIN_DEBUG

    This define should be set to either 0 or 1.  It is therefore used
    with the #if directive, not the #ifdef directive.  Actually, this define
    is now preferably used as an if-condition to avoid littering the source
    code with too many preprocessing directives.

  COIN_EXTRA_DEBUG

    This define is ordinarily not used, but can be defined to enable some
    extra sanity checks that may detect obvious, but otherwise hard to
    detect bugs like specifying indexes out of an arrays range, etc.
    Enabling this define may slow things down considerably, depending on
    how heavily the parts of Coin you use most are instrumented.


6 The Run-Time Environment
==========================

  * See So@Gui@/src/Inventor/@Gui@/common/HACKING for debugging hints.


7 How To Add / Modify A Class In Coin
=====================================

  * Implement the class.

  * Write Doxygen documentation for the class. Remember to tag the doc
    with \since YYYY-MM-DD, either for the class itself or for any
    functions with a new or changed API.

  * Update cross-references from other documentation if necessary.

  * If new source files were introduced:

        * Add them to the Mercurial repository.

        * Add the header and any generated doc files for the class to
          build/coin.spec.in (for RPM generation).

        * Add the source files to docs/coin.doxygen.in (for
          documentation generation).

        * If we are a subtype of SoBase, update the correct files for
          initializing the class (i.e. src/nodes/SoNode.cpp).

        * Add the source files to the corresponding all.cpp file.

        * Add the header file to the corresponding common include file
          (i.e. include/Inventor/nodes/SoNodes.h)

        * Add the source files to the Makefile.am file in the source
          file directory (for building).

        * If the class is public, add the header file to
          src/Makefile.am or any of src/*/Makefile.am (for
          installation).

        * Remember to rerun bootstrap when changing any
          Makefile.am. See below.



8 Bootstrapping
===============

"Bootstrapping" is the process of making or updating the
program-generated files of the Coin library (and other SIM modules),
typically those used for configuration and building.

Bootstrapping needs to at least be done when changes or additions are
done on configure.ac, or any of its dependencies (like the *.m4 files
mentioned below), or to any of the Makefile.am files. Bootstrapping
will run the GNU Autotools; Autoconf, Automake and Libtool, which will
use the aforementioned configure.ac, *.m4 files and Makefile.am files
to make shell scripts and "true" Makefile-files for configuration and
build.

To be able to bootstrap the Coin repository (or any other SIM code
repository), you need to check out the "simacros" modules from Coin's
Mercurial main repository. Then, in a UNIX shell, ''cd'' to the base
directory of the Coin module (where the source code for Coin is
located) and run ''<simacrosdir>/bin/bootstrap''.

Note that bootstrapping before committing changes to
Autotools-generated files should _always_ happen on the internal
valhalla.trh.sim.no server. There are several reasons for this:

  - When trying to trace down bugs related to the configure and / or
    the build process, it helps a _lot_ to only have to do this for
    one particular version of Autoconf / Automake / Libtool.

  - Sometimes we have to patch up one or more of the Autotools. Doing
    this in a centralized manner on valhalla.trh.sim.no is of course
    time-saving, and not prone to sync'ing errors.

  - We don't want to have _heaps_ of differences in bootstrapped,
    generated files for each commit -- which we would get if we all
    used slightly different versions of the Autotools.

Note that it can be a bit of a hassle to *always* bootstrap on
valhalla.trh.sim.no, and that is not necessary either. What we advice
when valhalla.trh.sim.no is somewhat out of reach is: install
Autoconf, Automake and Libtool on your local development
box. Bootstrap locally when developing. When done, commit all changes
_except_ files generated by Autoconf, Automake and Libtool. Then ssh
into valhalla.trh.sim.no, bootstrap, then commit the freshly
bootstrapped, generated files.


9 How To Backport Development-Branch Extensions to Coin-2
=========================================================

You are not allowed to break forward ABI compatibility with versions
of Coin-2 (or Coin-1, for that matter) when you backport extensions
which have been added to the Coin development branch.  Virtual methods
is one of the biggest problems with regards to this.

* Backporting Virtualism

  If you need to packport virtualism from Coin to Coin-2, one suggestion
  is to add a non-virtual callback handler system on the lowest level in
  the class hierarchy that needs this virtual function, and then the
  deriving classes can register their overriding functions in the
  constructor.  If they need to emulate invoking the inherited::*
  function, they must of course store the callback/closure pair locally in
  the class (private part) that was already set by the parent class when
  they register the overriding function.


10 Include Files
================

A few points about include files.

* Include as few files as possible in header files, but not so few
  that the header file depends on other headers having been included
  before it.  Including a header on it's own should not produce
  syntax errors.

  The techniques used to do that is mainly to pre-declare class types,
  and to hide class internals with the Cheshire Cat / Bridge pattern.

* When setting up which include files to include in source files,
  keep the order structured.  Follow this pattern:

  <config.h>, if included, should be the first header.

  Start with the most basic / standard libraries, and work your way
  down through non-standard external libraries and optional libraries
  (and do it library by library), before finally including headers
  internal in the current project.

  * libc/CRT includes first
  * other ANSI / POSIX libraries (pthreads++)
  * X libraries (or other GUI stuff)
  * optional libraries (for instance audio)
  * Open Inventor *core* headers
  * Open Inventor toolkit headers
  * Open Inventor extensions headers
  * internal headers
  * "inline" source files

  If for some reason you can't follow this ordering, it's most likely
  a design problem on your behalf, which you should fix sooner, rather
  than later...

=======================================================================
XXX FIXME: complete doc. XXX

* Building Coin for development (UNIX)
        - solutions applied in Coin
                o make install-data
                o make *-am

* Differences, MSWin

* Build hacking, bootstrap/Autoconf/Automake/Libtool

* Submitting patches
        - technical walk-through
        - legal aspects

==============================================================================

Library versioning
==================

When making releases, we follow these rules:

* If there has been made any incompatible changes to the ABI (see
  footnote 1 at end of document for an explanation of the term "ABI"):

    COIN_MAJOR_VERSION += 1,
    COIN_MINOR_VERSION = 0,
    COIN_MICRO_VERSION = 0.

   (If you don't know if the changes that have been made since last
   release is binary incompatible with the last ABI, you shouldn't
   be making releases.)

  Typical cases: public interfaces have been changed in a manner that
  is not compatible with old code. Classes have add private data
  members added or removed.

  We might also have just simply added many new significant major
  features to the library, which in itself justifies increasing the
  major version number.


* If there has been made additions to the API (see footnote 2 at the
  end of the document for an explanation of the term "API"), but the
  ABI is still backwards compatible:

    COIN_MAJOR_VERSION unchanged,
    COIN_MINOR_VERSION += 1,
    COIN_MICRO_VERSION = 0.

  Typical cases: new functionality has been added through new C
  functions, new C++ class member functions have been added (but not
  virtual functions, as that changes the sizeof() value of a class),
  or completely new classes have been added.


* For bugfix releases and other changes which do not change the interface
  at all:

    COIN_MAJOR_VERSION unchanged,
    COIN_MINOR_VERSION unchanged,
    COIN_MICRO_VERSION += 1.

==

The following text pertains to the versioning that is set up in
configure.ac, with regard to Libtool library versioning:

Note that our MAJOR.MINOR.MICRO versioning scheme differs somewhat from
the idea of library versioning applied by Libtool. According to Libtool,
libraries should be versioned according to a CURRENT.AGE.REVISION scheme.
Here CURRENT is supposed to be increased by 1 each time the API changes,
and AGE increased by 1 along with CURRENT each time the API changes in a
way which keeps the ABI backwards compatible. If compatibility is broken,
AGE is set to 0 (while CURRENT is still increased by 1). The REVISION
number has the same semantics as our MICRO number.

To cooperate in a painless way with Libtool, we choose to "convert" our
MAJOR.MINOR.MICRO scheme to Libtool's idea of versioning like this:

* Libtool's CURRENT number is increased when the MAJOR or MINOR number is
  changed.  If development and releases were done in a linear fashion, we
  would just have to increase CURRENT by one when the above happens, but
  since we intend to continue to support Coin 1.* after the release of
  Coin 2.* we have had to make up a different scheme.  What we have done is
  to reserve room for 20 minor releases between each major release.  This
  should hopefully be more than enough.  With this premise, we can calculate
  CURRENT with the formula MAJOR * 20 + MINOR.  This will ensure that
  CURRENT for 2.0 will be greater than CURRENT for 1.3 (and 1.17 for that
  matter).

  Note that this scheme has the "strange" (it's actually completely natural)
  effect that Coin 1.0 will be found as /usr/local/lib/libCoin.so.20.*
  (for Linux) and Coin 2.0 will be libCoin.so.40.*.

* Libtool's AGE number is the number of previous CURRENT version numbers
  that the library is binary compatible with.  This should always be the same
  number as MINOR is - when we make a new release with a new MAJOR number
  and 0 as MINOR number, ABI compatibility *will* be broken.

* Libtool's REVISION number is the number of the release with the exact same
  API/ABI as the previous release.  This is typical for patch-releases
  where some implementation bugs are fixed without touching anything in the
  library API.  In other words, when we up the MICRO number.  This means
  REVISION = MICRO.

==============================================================================

Mercurial maintenance
======================

New "Coin-MAJOR" repositories will be branched off the head "Coin"
repository. "Branching" in this context means to clone the "default/"
subdirectory to the "Coin/" directory through the standard
Mercurial "clone" command.

When this happens, the Coin repository should be tagged with the
symbolic name "coin-MAJOR.MINOR".

All releases will be made from the Coin-MAJOR.MINOR repositories.
When a new release is made from one of those, the sources will be
tagged with the symbolic name "Coin-MAJOR.MINOR.MICRO". This was
forgotten for the Coin-1.0.0 release, but for MAJOR.0.0 releases this
is not very important as it will coincide with the initial import of
the repository.

Releases made from Coin-MAJOR repositories will be in sequence. When
the MINOR version number is increased, no more releases of the MINOR -
1 branch will be made.


Making Releases
===============

Make sure to consult Coin/docs/RELEASE.txt for detailed and up2date
release procedures.

When a new release is to be made, configure.ac must be updated with
new version information. Make sure COIN_BETA is set to [] (empty), and
the release version number is set up. Run bootstrap and check that
"make distcheck" works. Commit the changes with a message about
setting the version number to MAJOR.MINOR.MICRO.

Add a Mercurial tag on the new version number.

  $ hg tag Coin-MAJOR.MINOR.MICRO \
      -m "Tagging the MAJOR.MINOR.MICRO release of the 'Coin' project."

Edit configure.ac again and increase micro (unless a new minor will be
the next release) and set COIN_BETA to [a]. Rerun bootstrap, and
commit the new setup with a message about setting the version number
again.

These two version-increment commits should happen without getting any
unrelated commits in between them so there won't be multiple states of
the Mercurial repository with a release version number.

Then go back to the tag (hg update -rCoin-MAJOR.MINOR.MICRO) and
prepare the release.

Source release tarballs are created with:

  $ hg archive -tzip Coin-MAJOR.MINOR.MICRO.zip
  $ hg archive -ttgz Coin-MAJOR.MINOR.MICRO.tar.gz

Binary releases are created from the source release tarball combining
the respective the buildbot output from the binary snapshot directory.


Correcting Erroneous Log Messages
=================================

Sometimes commits ends up with incorrect log messages due to the
committer being a bit too trigger-happy. The following Mercurial book
chapter describes how to achieve that:

  http://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html

Do this instead of reversing and reapplying, or other round-about and
confusing techniques...


==============================================================================

Coin Code Standards
===================

The main goal is of course to write good, bugfree, portable C++ code,
in a way that clearly expresses the intent of what is attempted
accomplished.

First, the larger issues:

   I. PORTABILITY.

      Some specific remarks about portability: this is very far from
      being a trivial matter with C++, as not only is system
      portability difficult (due to differences in core libraries for
      various platforms), but _compiler_ portability is also a big
      issue with C++. The main reason behind this is that the ISO C++
      standard evolved gradually and slowly, and many C++ compilers
      that are still around on much used platforms were written before
      the standard was complete. And even today, it is actually
      doubtful if any C++ compiler around implements the full
      standard, as it is so huge and complex.

      To keep everything as portable as possible, we basically use the
      C++ language as more or less a "C with classes".

      For the full monty on C++ portability, please read the C++
      portability guide written for the Mozilla browser project:

        <URL:http://www.mozilla.org/hacking/portable-cpp.html>

      We consider this a must read for any internal resources writing
      production C++ code. One issue it's particularly easy to "sin"
      against is the following:

      Use the ``SbBool'' type instead of bool, and ``TRUE'' and
      ``FALSE'' keywords instead of ``true'' and ``false''. Compilers
      that do not support the ``bool'' type is still in widespread use
      (SGI MIPSPro v7.30 is but one example), so we are using the more
      portable ``SbBool'' instead to make sure our code build on those
      systems.


  II. THE CHESHIRE CAT / THE BRIDGE PATTERN

      There is one important "trick" to apply to C++ classes when they
      are part of a library with a public API where binary
      compatibility (i.e. a stable ABI (see footnote 1 at end of
      document)) between releases are important -- as it is for the
      Coin library. The trick is to hide all the private
      implementation data within an internal class, only visible to
      the .cpp-file of the "real" class.

      This is a common design pattern that goes under many different
      names; the Bridge pattern (from «Design Patterns», Gamma et al),
      the Cheshire Cat (from the character in Lewis Carroll's «Alice's
      Adventures in Wonderland»), pimpl (short for "private
      implementation") or the d-pointer (for "data-pointer"). For
      consistency, it will be called "Cheshire Cat" from now on in
      this explanation.

      The main advantage of applying the Cheshire Cat is that one can
      add new data members to the implementation of a class without
      breaking it's ABI -- which avoids the need to hold back new
      features, new functionality or even bugfixes to the next major
      release of the library.

      The general idea of the Cheshire Cat is as follows:

      <APublicClass.h>:

      ---8<------8<------8<------8<------8<------8<------8<------8<---

      class APublicClass {
        public:
          // [public API here]

        protected:
          // [protected API here]

        private:
          class APublicClassP * pimpl; // contains internal implementation data
      };

      ---8<------8<------8<------8<------8<------8<------8<------8<---

      ..where the "APublicClassP" (notice the trailing "P" for
      "Private") declaration could be embedded in the APublicClass.cpp
      file, for simplicity:

      <APublicClass.cpp>:

      ---8<------8<------8<------8<------8<------8<------8<------8<---

      #include "APublicClass.h"

      class APublicClassP {
        public: // all data publicly available for "owner" APublicClass
          int number1;
          float number2;
          // [etc]
      };

      // [then follows the implementation of APublicClass]

      APublicClass::APublicClass()
      {
         // set up internal data class
         this->pimpl = new APublicClassP;
         // ...
      }

      APublicClass::~APublicClass()
      {
         // ...
         delete this->pimpl;
      }

      // [for other code, all data are accessed through the "pimpl" pointer]
        this->pimpl->number2 = obj->doSomeThing(this->pimpl->number1);
      // ...

      ---8<------8<------8<------8<------8<------8<------8<------8<---

      If we then noticed that we need more data members for new
      features or to fix bugs in APublicClass, we can just add those
      to the internal class without breaking the ABI compatibility.

      For a real example of how to use this pattern, see for instance
      the declaration and implementation of the SoExtSelection node
      class or the SoRayPickAction class (among many others), or any
      class in the So* libraries (where the pattern has been used most
      extensively).

      There are basically just a few cases where the Cheshire Cat
      should /not/ be applied: for very light-weight small classes, we
      don't want the extra overhead it introduces in memory usage and
      time to redirect all data request to the internal class. So the
      Sb* base classes are for instance not using the pattern, and
      neither are SoBase and SoField -- which both permeates library
      usage at run-time, so we want to keep them as slim as possible.

      The preferred way to access the pimpl pointer, and to access the
      "real" class (in the public interface) back from the private
      class, is to set up a couple of macros:

        #define PRIVATE(p) ((p)->pimpl)
        #define PUBLIC(p) ((p)->master)


      ..and then use it in statements like this:

        PRIVATE(this)->number2 = obj->doSomeThing(PRIVATE(this)->number1);

      Specifically, don't use the "THIS" define which we used to do in
      earlier times:

        #define THIS this->pimpl

      ..as it clashes with a define for "THIS" made somewhere in the
      header files of Microsoft Visual Studio.


 III. GLOBAL NAMESPACE POLLUTION

      Don't you ever dare pollute the global namespace unnecessary!

      That goes for: defines, macros, enums, typedefs, function names,
      etc etc. If you *have* to make something global, you should at
      least prefix it with "COIN_" (or some such) that minimizes the
      chances of clashes with client code, system / compiler symbols,
      or symbols from Coin's dependencies.

      One common mistake you should in particular be careful to avoid
      is to specify stand-alone functions in source code
      implementations like this:

        void
        myhelperfunc(int a, int b)
        {
           // ...
        }

      Use the "static" keyword to make sure the function symbol is
      *truly* local, to exclude such functions from the global
      namespace!:

        static void
        myhelperfunc(int a, int b)
        {
           // ...
        }


 IV.  C++ FEATURES UNAVAILABLE TO COIN PROGRAMMERS

      Because we want to support fairly old C++ compilers, there are a
      number of C++ features that are forbidden to use for Coin source
      code. What follows may not be a comprehensive list, more items
      will likely be added. Anyway, one must at least avoid these:

      - Don't use functionality out of the Standard Template Library
        ("STL") -- the implementation and compatibility of this seems
        to be sub-par on a lot of C++ compiler systems.

      - Don't use functionality out of the C++ library, like e.g. file
        streams -- we don't want to force a link dependency on
        libstdc++, since it has been (and still is?) very unstable
        with regard to binary compatibility, making it harder to make
        binary distributions for e.g. Linux systems.

      - Don't use namespaces. They are not supported on some older
        compilers we want the code to be compatible with.

      - Don't use exceptions.


Enough about the larger issues, now for the mucky details that has
been written down to guide the Coin programmers in being consistent
versus the code "layout" (to make it more easily readable):

 0) If the code you write is not 100% complete;

    - Leave a "FIXME" message if you believe the code is fairly
      correct, but you are unsure and have not checked the correctness
      yet, or if there are known deficiencies. This includes cases
      like ambiguities in the OIV docs that will require some
      investigation to resolve, error-cases or places where one should
      be more robust that haven't been fixed yet due to time
      constraints, etc.

    - Insert "COIN_STUB();" statements if the code lacks certain
      important functionality, so situations where unimplemented
      features are used will be detected at run-time.

    - Leave FIXMEs if you see obvious cases for performance
      improvements which should be explored.

    A FIXME-message must include a description of the problem, who
    wrote the message, and when.  Please include whatever you have
    already found out about the problem in the FIXME text, so your
    next of kin don't have to painstakingly re-do all the thought-work
    you already have laid down.  Example:

      // FIXME: should be possible to simplify cylinder test, since this
      // cylinder is aligned with the y-axis. 19991110 pederb.

    or

      // FIXME: this action seems completely bogus, as if something fails,
      // all bets are off and we should simply terminate the import
      // operation. (flushInput() continues to read and scans for a
      // closing brace). Run with this code disabled for a while and axe
      // it if nothing bad seems to come from it. 20020531 mortene.
      //
      // if (!ret && flush) SoBase::flushInput(in);

    This goes also for other keywords in comments (see below).  It
    makes it much easier when others try to fix code that doesn't
    work.  You will know who to ask if you don't understand the
    problem, and the date could indicate among other things the
    urgency of the problem.

    If you have postponed implementing something, which has to
    be implemented before Coin is officially released again, put a
    section like this in the code to assert that it won't be
    forgotten:

      #ifndef COIN_BETA_VERSION
      #error implementation missing: something or other
      #endif // !COIN_BETA_VERSION

    Don't use this trick more than absolutely necessary.  The release
    master will be pretty pissed off each time a planned release has
    to be aborted.

 1) If blocks of code are commented out (obsoleted) to make place for
    new code, or because it has become superfluous, one should mark it
    like the example below if it is a large block of code, if the new
    code is very experimental, or if the new code is obfuscated
    (e.g. because of optimizations).

    #if 0// OBSOLETE: <textual description>. <yyyymmdd userid>.
    ...old code...
    #else // short description of new code
    ...new code...
    #endif // newcode

    See also the next rule.

 2) Under *no* circumstances should developers leave any code which
    has been commented out with the language constructs "// ..." or
    "/* ... */" in anything you check into the repository, at least
    not without commenting _why_ the code is still present.

    It's often very time-consuming and just a bloody pain in the ass
    and a waste of resources trying to figure out why commented-out
    code is still present in a source file (is it new code which
    *might* fix a bug, but which haven't been tested yet?  is it old
    code found to be buggy which have been removed? is it commented
    out because it is a new feature which is yet to be completed? etc
    etc etc).

    Programmers who continues to sin against this rule after having
    this pointed out to them should be taken out behind the barn to be
    shot.

 3) During debugging, write debug code like this:

    #if COIN_DEBUG && 1 // debug
      SoDebugError::postInfo(...
    #endif // debug

    Then, flip the "#if COIN_DEBUG && 1" to "#if COIN_DEBUG && 0" if
    there is a chance that the debug information might be useful
    later.  If not, remove it before making a patch or checking in.

    If there are many debug statements in the same category, use a
    define for that category (#if DEBUG_<category>) and define it to 0
    at the top of the file before checking in the code.  See
    src/sensors/SoSensorManager.cpp for examples of how this should be
    done.

    UPDATE 2001-11-21 larsa: Actually, we now prefer that you use this
    define as an if-condition instead, because of the cleaner look the
    source code gets when it is not littered with preprocessing
    directives.  For permanent debugging code, write therefore source
    code like this instead:

    if ( COIN_DEBUG ) {
      SoDebugError::postInfo("SoDB::funnyRabbit", "follow the white rabbit");
    }

    UPDATE 2002-06-17 mortene: this decision has been reversed, at
    least temporarily, as we can't seem to get a definitive answer to
    whether or not code and data within an "if (0) { ... }" construct
    is still taking up space in the generated object and library
    files.

 4) Do not under any circumstances use printf() / fprintf() / puts()
    or related functions for output.  It should not be necessary --
    the Coin class SoDebugError (and SoReadError) was implemented for
    a reason.  Debug messages with printf() / fprintf() is extremely
    uncool when you use Coin as a DLL under Windows (it's likely to
    cause mysterious crashes), and besides it's bloody irritating to
    walk through the code later to remove them.

 5) Don't use any variablename, classname, define, functionname or any
    other identifier that starts with an underscore. That namespace is
    per the C and C++ specs fully reserved for the compiler
    implementation.

    Identifier names with double underscores anywhere in the name is
    also reserved.

    For more information about this than you really want to know, see
    Section 17.4.3.1 "Reserved names" and its subsections in the C++
    language spec.

 6) Prefix with the "this" keyword for dynamic functions and member
    variables, prefix with the classname for static functions and
    variables.

    The rationale for doing this extra typing is that it makes the
    code immensely more easily readable when skimming it. If the
    prefixes are missing, one has often to scroll back and forth to
    find out if variables are input arguments to methods or stack
    variables -- with "this->" or "ClassName::" prefixes there is
    immediately no doubt where the variable comes from.

 7) Code formatting rules. The default is to use Kernighan and Ritchie style.

   a) Braces: keep opening braces on the end of the line, and closing
      braces at the start. Like this:

      if (...) {
        ...
      }

      And not like this:

      if (...)
      {
        ...
      }

      The exception from this rule is functions, which should have the
      opening brace on the next line.

   b) Indentation: use 2 spaces extra for each level of nesting.

      *Never* use tabulator characters (ie ASCII code 0x09), as
      editors expands them differently. The code indentation will
      therefore more often than not look like crap with the default
      settings of any other editor than the one you happen to be using
      yourself.

   c) Spacing: use 1 space after commas and around operators (like +,
      -, *, /, ==, &&, etc), but not after or before parentheses.

      Like this:

      if (val) { i = sqrt(a) * func(b, c); }

      Not like this:

      if ( val ) { i=sqrt(a)*func(b,c); }

   d) Naming: class names should be uppercased for each word, function
      names for each word except the first one, variable names should
      be all lowercase, and defines, enums and constants should be all
      uppercase. Example:

      float
      MathClass::calculateValue(float in)
      {
        const float FACTOR = 2.78;
        ...
        ...
      }

      For C functions and C++ functions that doesn't belong to any
      particular class, name them with underscores between words, in
      all lowercase.

      NOTE: do *not* use Hungarian-style naming, ie prefixing names
      with indicators about type. So don't for instance name classes
      with a leading "c", or member variables with an "m", or integers
      with an "i" and so on and so on. You're better off in the
      readability-department by using the "this" prefix, as explained
      above, and then the Hungarian naming style just obfuscates the
      code.

   e) Pointer types and references: use a space on each side of the
      '*' and '&' operators, like this

        SoNode * mynode = NULL;

      not like this

        SoNode *mynode = NULL;

      because it makes it look like the '*' "belongs" to the variable
      name (which of course is wrong -- it's part of the type), and
      not like this either

        SoNode* mynode = NULL;

      because it's ugly and unusual. So for consistency, _please_
      stick with the space-on-both-sides convention in Coin code.

   f) Use
                   return x;
      and not
                   return (x);

      (Since "return" is not a function with arguments, the latter
      just looks plain wrong.)

==============================================================================

API Documentation Guidelines
============================

Documentation of the Coin API is done with a setup and syntax
compatible with the Doxygen tool. For general information and detailed
documentation about the Doxygen syntax, see
<URL:http://www.doxygen.org>.

We allow documentation to be done in a rather free-form manner, as
long as it conforms to the valid syntax of Doxygen. There is basically
just one rule which is an absolute must:

        * New functions and classes in the API have to be tagged with
          "\since", to make it possible for application programmers to
          know when the API was extended -- in case they want to
          support a range of older versions of the library, for
          instance. Valid parameters to "\since" are:
          * Coin x.y              - What Coin version it first occurred in.
          * TGS Inventor x.y[.z]  - What TGS OIV version it first occurred in.
          * Inventor x.y[.z]      - What SGI OIV version it first occurred in.
          * YYYY-MM-DD            - What date it was added to Coin. Will be
                                    converted to the correct COIN-x.y for each
                                    Coin release.
          Use ',' as a separator if more than one implementation supports
          the extension. If an extension is introduced in two branches of
          Coin, tag both in cases as (COIN-1.1, COIN-2.1) but only once if
          you mean COIN-1.1 and later (e.g. all 2.x releases support the
          extension). The z release numbers should normally never be used
          as adding features between patchlevel releases would break binary
          compatibility, but at least TGS is known to break this "rule".

Other than this, use your common sense and look at the already
existing documentation that is available.

A few hints:

        * We never started using the common "JavaDoc"-style way of
          forcing tags and documentation on all arguments and return
          types with "\param" and "\return" -- so there's no point in
          doing that for the functions you write.

        * Cross-reference to other functions and / or classes with the
          "\sa" ("see also") tag where it seems helpful for the
          application programmer. Remember that Doxygen automatically
          finds and cross-references class or function names found in
          the doc anyway, so don't overuse the "\sa" tag.

        * We do not force a third-person vs an imperative style, or
          vice versa. Use the same style as "nearby" documentation.

        * Make sure *all* important aspects of a class or a function
          is documented properly -- _don't_ expect the application
          programmer to ever having to resort to the header files or
          implementation sourcecode.

        * Use "\e" in front of words you want to emphasize, "\c" in
          front of words that should be shown in a font appropriate
          for code keywords (like "TRUE" or "FALSE") and "\a" in front
          of function argument names.

==============================================================================

Footnotes
=========

[1] "ABI" is short for "Application Binary Interface". The ABI of a
    software component of object code (usually a dynamic or static
    library) covers any publicly exposed functions, function
    signatures, structures (and classes for C++ code). If any
    functions has been removed or changed, or if any
    structures/classes has been modified in any way, the ABI has most
    likely been made incompatible with earlier releases.

    What this means for practical purposes is that application
    programs (or other client code, like other libraries using the
    library in question) must be relinked when ABI compatibility is
    broken.

    A quick example of why re-building is necessary when the ABI is
    made incompatible with the previous version: let's say that a
    class has gotten a few new member variables added. This breaks the
    ABI in a manner which is neither upwards nor downwards compatible,
    as the statement

        AClass * anobject = new AClass;

    ...in client code will allocate a chunk of memory with the size
    sizeof(AClass). Adding member variables will increase
    sizeof(AClass) in the /library/ object code, but the compiled
    /client code/ will still use the old sizeof(AClass), with the
    boundary overwrites and other "interesting" effects that may come
    out of it if the client code is not re-compiled.

    Documentation on ABI- and API-compatiblity
    ------------------------------------------

    Matthias Ettrich and Lubos Lunak have published a document called
    Binary Compatibility Issues With C++. It deals with the details a
    developer should know about when working on APIs and
    RPC-Interfaces.

    Certain compiler flags may change the ABI of the resulting code
    and should be used with care. Such flags are marked with text
    indicating compatibility problems in the compiler manuals.

    <URL:http://developer.kde.org/documentation/other/binarycompatibility.html>

    (It's the "You frequently say that you cannot add this or that
    feature because it would break binary compatibility. What does
    this mean, really?" question.)



[2] Application Programmer's Interface. This is the functions and data
    structures/classes exposed to the application programmer for
    interaction with the library.

==============================================================================