source: trunk/synergy/doc/PORTING@ 3003

Last change on this file since 3003 was 2749, checked in by bird, 19 years ago

synergy v1.3.1 sources (zip).

File size: 17.0 KB
Line 
1Synergy Developer and Porting Guide
2===================================
3
4This document is under development.
5
6Code Organization
7-----------------
8
9The synergy source code organization is:
10
11. -- root makefiles, some standard documentation
12cmd -- program source code
13 launcher -- synergy launcher for Windows
14 synergyc -- synergy client
15 synergys -- synergy server
16config -- stuff for autoconf/automake
17dist -- files for creating distributions
18 nullsoft -- files for creating Nullsoft NSIS installer (Windows)
19 rpm -- files for creating RPMs
20doc -- placeholder for documentation
21examples -- example files
22lib -- library source code
23 arch -- platform dependent utility library
24 base -- simple utilities
25 client -- synergy client library
26 common -- commonly needed header files
27 io -- I/O
28 mt -- multithreading
29 net -- networking
30 platform -- platform dependent display/window/event stuff
31 server -- synergy server library
32 synergy -- synergy shared client/server code library
33
34Note how the utility code required by the programs is placed into
35separate library directories. This makes the makefiles a little
36more awkward but makes for a cleaner organization. The top level
37directory has only the standard documentation files and the files
38necessary to configure and build the rest of the project.
39
40
41Coding Style Guide
42------------------
43
44Synergy uses many coding conventions. Contributed code should
45following these guidelines.
46
47- Symbol Naming
48 Names always begin with a letter (never an underscore). The first
49 letter of interior names are always capitalized. Acronyms should
50 be all uppercase. For example: myTextAsASCII.
51
52 Names come it two flavors: leading capital and leading lowercase.
53 The former have the first character capitalized and the latter
54 don't. In the following table, leading capital names are indicated
55 by `Name' and leading lowercase names by `name'.
56
57 The naming convention for various things are:
58
59 * Exceptions -- X + Name XMyException
60 * Interfaces -- I + Name IMyInterface
61 * Template Classes -- T + Name TMyTemplate<>
62 * Other Classes -- C + Name CMyClass
63 * Enumerations -- E + Name EMyEnumeration
64 * Constants -- k + Name kMyConstant
65 * Data Members -- m_ + name m_myDataMember
66 * Methods -- name myMethod
67 * Functions -- name myFunction
68 * Variables -- name myVariable
69
70 Exceptions are types that get thrown and are generally derived
71 (possibly indirectly) from XBase. Interfaces are derived (possibly
72 indirectly) from IInterface and have only pure virtual functions.
73 Other classes are classes that aren't exceptions or interfaces.
74 Constants include global constants and enumerants.
75
76 Method names should usually have the form `verbObject'. For example:
77 * isGameOn()
78 * getBeer()
79 * pressPowerButton()
80 * setChannel()
81 In general, use `get' and `set' to read and write state but use `is'
82 to read boolean state. Note that classes that contain only `is',
83 `get', and `set' are probably plain old data; you might want to
84 consider using public data members only or, better, refactor your
85 design to have classes that actually do something more than just
86 hold data.
87
88- File Naming
89 Each class should have one source and one header file. If the
90 class is named `CMyClass' then the source file should be named
91 `CMyClass.cpp' and the header file `CMyClass.h'.
92
93 Headers files not containing a class should have some meaningful
94 name with a leading capital (e.g. `Version.h').
95
96 Source files without a header file have a leading lowercase name.
97 Only files containing the entry point for an application should
98 lack a header file.
99
100- Dependencies
101 * No circular library dependencies
102 Library dependencies form an acyclic graph. Conceptually
103 libraries can be arranged in layers where each library only
104 references libraries in layers below it, not in the same layer
105 or layers above it. The makefiles build the lowest layer
106 libraries first and work upwards.
107
108 * Avoid circular uses-a relationships
109 When possible, design classes with one-way uses-a relationships
110 and avoid cycles. This makes it easier to understand the code.
111 However, sometimes it's not always practical so it is permitted.
112
113 * Included files in headers
114 Headers should #include only the necessary headers. In
115 particular, if a class is referenced in a header file only as a
116 pointer or a reference then use `class COtherClass;' instead of
117 `#include "COtherClass.h".'
118
119 * #include syntax
120 Non-synergy header files must be included using angle brackets
121 while synergy header files must be included using double quotes.
122 #include "CSynergyHeader.h"
123 #include <systemheader.h>
124 The file name in a #include must not be a relative path unless
125 it's a system header file and it's customary to use a relative
126 path, e.g. `#include <sys/types.h>'. Use compiler options to
127 add necessary directories to the include search path.
128
129 * Included file ordering
130 Files should be included in the following order:
131 * Header for source file
132 The first include for CMyClass.cpp must be CMyClass.h.
133 * Other headers in directory, sorted alphabetically
134 * Headers for each library, sorted alphabetically per library
135 Include headers from the library closest in the dependency graph
136 first, then the next farthest, etc. Sort alphabetically within
137 each library.
138 * System headers
139
140- C++
141 * C++ features
142 Synergy uses the following more recent C++ features:
143 * bool
144 * templates
145 * exceptions
146 * mutable
147 * new scoping rules
148 * the standard C++ library
149
150 Do not use the following C++ features:
151 * dynamic_cast
152 * run time type information
153 * namespaces and using (use std:: where necessary)
154
155 The new scoping rules say that the scope of a variable declared
156 in a for statement is limited to the for loop. For example:
157
158 for (int i = 0; i < 10; ++i) {
159 // i is in scope here
160 }
161 // i is not in scope here
162
163 for (int i = -10; i < 0; ++i) {
164 // an entirely new i is in scope here
165 }
166 // i is not in scope here
167
168 This is used routinely in synergy, but only in for loops. There
169 is a macro for `for' in lib/base/common.h when building under
170 Microsoft Visual C++ that works around the fact that that compiler
171 doesn't follow the new scoping rules. Use the macro if your
172 compiler uses the old scoping rules.
173
174 * Standard C++ library
175 The standard C++ library containers should always be used in favor
176 of custom containers wherever reasonable. std::string is used
177 throughout synergy but only as the CString typedef; always use
178 CString, never std::string except in the arch library. Synergy
179 avoids using auto_ptr due to some portability problems. Synergy
180 makes limited use of standard algorithms and streams but they can
181 be freely used in new code.
182
183 * Limited multiple inheritance
184 Classes should inherit implementation from at most one superclass.
185 Inheriting implementation from multiple classes can have unpleasant
186 consequences in C++ due to it's limited capabilities. Classes can
187 inherit from any number of interface classes. An interface class
188 provides only pure virtual methods. Synergy breaks this rule in
189 IInterface which implements the virtual destructor for convenience.
190
191 * No globals
192 Avoid global variables. All global variables must be static, making
193 it visible only with its source file. Most uses of global variables
194 are better served by static data members of a class. Global
195 constants are permitted in some circumstances.
196
197 Also avoid global functions. Use public static member functions in
198 a class instead.
199
200 These rules are violated by the main source file for each program
201 (except that the globals are still static). They could easily be
202 rewritten to put all the variables and functions into a class but
203 there's little to be gained by that.
204
205 * Private data only
206 If a class is plain-old-data (i.e. it has no methods) all of its
207 data members should be public. Otherwise all of its data members
208 should be private, not public or protected. This makes it much
209 easier to track the use of a member when reading code. Protected
210 data is not allowed because `protected' is a synonym for `public
211 to my subclasses' and public data is a Bad Thing. While it might
212 seem okay in this limited situation, the situation is not at all
213 limited since an arbitrary number of classes can be derived,
214 directly or indirectly, from the class and any of those classes
215 have full access to the protected data.
216
217 * Plain old data
218 A class that merely contains data and doesn't perform operations
219 on that data (other than reads and writes) is plain old data (POD).
220 POD should have only public data members and non-copy constructors.
221 It must not have any methods other than constructors, not even a
222 destructor or assignment operators, nor protected or private data.
223 Note that this definition of POD is not the definition used in the
224 C++ standard, which limits the contained data types to types that
225 have no constructors, destructors, or methods.
226
227 * Avoid using friend
228 Avoid declaring friend functions or classes. They're sometimes
229 necessary for operator overloading. If you find it necessary to
230 add friends to some class C, consider creating a utility class U.
231 A utility class is declared as the only friend of C and provides
232 only static methods. Each method forwards to a private method on
233 an object of C type (passed as a parameter to the U's method).
234 This makes maintenance easier since only U has friend access to C
235 and finding any call to U is trivial (they're prefixed by U::).
236
237 * Don't test for NULL when using `delete' or `delete[]'
238 It's unnecessary since delete does it anyway.
239
240- Makefiles
241 Automake's makefiles (named Makefile.am) have a few requirements:
242 * Define the following macro at the top of the file:
243 NULL =
244 * Lists should have one item per line and end in $(NULL). For
245 example:
246 EXTRA_DIST = \
247 kiwi.txt \
248 mango.cpp \
249 papaya.h \
250 $(NULL)
251 Indentation must use tabs in a makefile. Line continuations
252 (backslashes) should be aligned using tabs.
253 * Lists of files should be sorted alphabetically in groups (e..g
254 source files, header files, then other files). Lists of
255 subdirectories must be in the desired build order.
256
257- Source Formatting
258 Every project has its own formatting style and no style satisfies
259 everyone. New code should be consistent with existing code:
260
261 * All files should include the copyright and license notice
262 * Use tabs to indent
263 * Tabs are 4 columns
264 * Lines should not extend past the 80th column
265 * Open braces ({) go on same line as introducing statement
266 `for (i = 0; i < 10; ++i) {' not
267 for (i = 0; i < 10; ++i)
268 {
269 * Close braces line up with introducing statement
270 * Open brace for function is on a line by itself in first column
271 * Close brace for function lines up with open brace
272 * Always use braces on: if, else, for, while, do, switch
273 * `else {' goes on its own line
274 * Always explicitly test pointers against NULL
275 e.g. `if (ptr == NULL)' not `if (ptr)'
276 * Always explicitly test integral values against 0
277 e.g. `if (i == 0)' not `if (i)'
278 * Put spaces around binary operators and after statements
279 e.g. `if (a == b) {' not `if(a==b){'
280 * C'tor initializers are one per line, indented one tab stop
281 * Other indentation should follow existing practice
282 * Use Qt style comments for extraction by doxygen (i.e. //! and /*!)
283 * Mark incomplete or buggy code with `FIXME'
284
285- Other
286 * calls to LOG() should always be all on one line (even past column 80)
287
288
289Class Relationships
290-------------------
291
292The doxygen documentation can help in understanding the relationships
293between objects. Use `make doxygen' in the top level directory to
294create the doxygen documentation into doc/doxygen/html. You must have
295doxygen installed, of course.
296
297FIXME -- high level overview of class relationships
298
299
300Portability
301-----------
302
303Synergy is mostly platform independent code but necessarily has
304platform dependent parts. The mundane platform dependent parts
305come from the usual suspects: networking, multithreading, file
306system, high resolution clocks, system logging, etc. Porting
307these parts is relatively straightforward.
308
309Synergy also has more esoteric platform dependent code. The
310functions for low-level event interception and insertion,
311warping the cursor position, character to keyboard event
312translation, clipboard manipulation, and screen saver control
313are often obscure and poorly documented. Unfortunately, these
314are exactly the functions synergy requires to do its magic.
315
316Porting synergy to a new platform requires the following steps:
317
318- Setting up the build
319- Adjusting lib/common/common.h
320- Implementing lib/arch
321- Implementing lib/platform
322- Tweaks
323
324Setting up the build:
325
326The first phase is simply to create the files necessary to build the
327other files. On Unix, synergy uses autoconf/automake which produces
328a `configure' script that generates makefiles. On Windows, synergy
329uses Visual C++ workspace and project files. If you're porting to
330another Unix variant, you may need to adjust `configure.in',
331`acinclude.m4', and Unix flavor dependent code in lib/arch. Note
332especially the SYSAPI_* and WINAPI_* macro definitions in
333ARCH_CFLAGS. Exactly one of each must be defined. It should also
334add AM_CONDITIONALs if a new SYSAPI_* or WINAPI_* was added.
335
336Adjusting lib/common/common.h:
337
338The lib/common/common.h header file is included directly or indirectly
339by every other file. Its primary job is to include config.h, which
340defines macros depending on what the 'configure' script discovered
341about the system. If the platform does not use the 'configure' script
342it must define the appropriate SYSAPI_* and WINAPI_* macro. It may
343also do other platform specific setup.
344
345Adjusting lib/common/BasicTypes.h:
346
347No changes should be necessary in BasicTypes.h. However, if the
348platform's system header files define SInt8, et al. you may need
349to adjust the typedefs to match the system's definitions.
350
351Implementing lib/arch:
352
353Much platform dependent code lives in lib/arch. There are several
354interface classes there and they must all be implemented for each
355platform. See the interface header files for more information.
356
357Platforms requiring special functions should create a class named
358CArchMiscXXX where XXX is the platform name. The class should have
359only static methods. Clients can include the appropriate header
360file and make calls directly, surrounded by a suitable #ifdef/#endif.
361
362If using automake, the Makefile.am should list the system specific
363files in a XXX_SOURCE_FILES macro where XXX matches the appropriate
364AM_CONDITIONAL symbol. XXX_SOURCE_FILES must be added to EXTRA_DIST
365and the following added above the INCLUDES macro:
366
367 if XXX
368 libarch_a_SOURCES = \
369 $(COMMON_SOURCE_FILES) \
370 $(XXX_SOURCE_FILES) \
371 $(NULL)
372 endif
373
374Implementing lib/platform:
375
376Most of the remaining platform dependent code lives in lib/platform.
377The code there implements platform dependent window, clipboard, keyboard
378and screen saver handling. If a platform is named XXX then the following
379classes should be derived and implemented:
380
381 * CXXXClipboard : IClipboard
382 Provides clipboard operations. Typically, this class will
383 have helper classes for converting between various clipboard
384 data formats.
385
386 * CXXXEventQueueBuffer : IEventQueueBuffer
387 Provides operations for waiting for, posting and retrieving events.
388 Also provides operations for creating and deleting timers.
389
390 * CXXXKeyState : CKeyState
391 Provides operations for synthesizing key events and for mapping a
392 key ID to a sequence of events to generate that key.
393
394 * CXXXScreen : IScreen, IPrimaryScreen, ISecondaryScreen, IPlatformScreen
395 Provides screen operations.
396
397 * CXXXScreenSaver : IScreenSaver
398 Provides screen saver operations.
399
400If using automake, the Makefile.am should list the window system
401specific files in a XXX_SOURCE_FILES macro where XXX matches the
402appropriate AM_CONDITIONAL symbol. XXX_SOURCE_FILES must be added
403to EXTRA_DIST and the following added above the INCLUDES macro:
404
405 if XXX
406 libplatform_a_SOURCES = $(XXX_SOURCE_FILES)
407 endif
408
409Tweaks:
410
411Finally, each platform typically requires various adjustments here
412and there. In particular, synergyc.cpp and synergys.cpp usually
413require platform dependent code for the main entry point, parsing
414arguments, and reporting errors. Also, some platforms may benefit
415from a graphical user interface front end. These are generally
416not portable and synergy doesn't provide any infrastructure for
417the code common to any platform, though it may do so someday.
418There is, however, an implementation of a GUI front end for Windows
419that serves as an example.
Note: See TracBrowser for help on using the repository browser.