forked from readium/readium-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHACKING
111 lines (90 loc) · 4.96 KB
/
HACKING
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
This is a cross-platform project written in C++11. It was originally targeted
at the LLVM libc++ runtime library, which at the time was 95% complete
according to the spec (as of version 3.3 it's 100% feature-complete). This
leads to a few problems of compatibility, since on Android we have to build
against GNU libstdc++, which is maybe 80% feature-complete for C++11, and on
Windows we use MSVC 11, which is about 60% complete.
To aid in the creation of properly portable C++11 code, we took the liberty of
lifting some macro-filled headers from the WebKit project, which has similar
portability aims. These can be found in ePub3/_compiler.h and
ePub3/_platform.h. On top of this lies our own ePub3/_config.h, which defines a
few things specific to our own code.
In _config.h and _platform.h you'll find preprocessor macros which you can use
to determine the host operating system and platform along with the
implementation status of various C11 and C++11 features at the compiler or
runtime level.
Note that platform/os types can be combined; for example, EPUB_OS(UNIX) is true
if EPUB_OS(LINUX), EPUB_OS(FREEBSD), EPUB_OS(DARWIN), or a number of others are
true. Likewise, if EPUB_OS(DARWIN) is true, then EPUB_OS(FREEBSD) is also true,
since Darwin (Apple iOS and OS X) uses the FreeBSD userland and a lot of the
FreeBSD kernel.
The EPUB_PLATFORM(...) macros are a little higher level. On Darwin OS, the
platform could be MAC for the desktop or IOS for the iPod/iPhone/iPad. Note
that OS names and Platform names are designed to never conflict: on Windows,
you test the OS using EPUB_OS(WINDOWS) and the Platform using
EPUB_PLATFORM(WIN).
In general, you should only refer to platform or OS in very specific
situations. Examples include making use of the Android-specific ALooper type on
EPUB_OS(ANDROID), or using Windows APIs on EPUB_PLATFORM(WIN).
Most of the time you'll use macros like EPUB_HAVE(...), EPUB_USE(...), or
EPUB_COMPILER_SUPPORTS(...). Some examples include:
EPUB_USE(CF)
Platform agnostic CoreFoundation types are available
EPUB_HAVE(ACL)
Whether <acl.h> is available
EPUB_HAVE(CXX_MAP_EMPLACE)
Whether std::map has an emplace() function (true except on GCC)
The compiler macros appear in quite a few places, especially with Windows
support:
EPUB_COMPILER_SUPPORTS(CXX_DELETED_FUNCTIONS)
Whether 'SomeFunc() = delete;' is supported
EPUB_COMPILER_SUPPORTS(CXX_CONSTEXPR)
Whether 'constexpr' keyword is supported.
EPUB_COMPILER_SUPPORTS(CXX_DEFAULT_TEMPLATE_ARGS)
Whether default arguments for template parameters are supported on
functions as well as classes.
EPUB_COMPILER_SUPPORTS(ALIAS_TEMPLATES)
Whether you can do 'using [myType] - [otherType];'
EPUB_COMPILER_SUPPORTS(CXX_VARIADIC_TEMPLATES)
Whether templates can take variable numbers of arguments.
EPUB_COMPILER_SUPPORTS(CXX_INITIALIZER_LISTS)
Whether std::initializer_list is available and '{a, b, c}' will be compiled
into one.
Note that, for the most part, all of the above are FALSE on MSVC11, TRUE on GCC
and Clang.
Windows DLL Linkage
---------------------------------------
On Windows, the SDK builds into a DLL. In order to export or import methods,
they must be marked with __declspec(dllexport) or __declspec(dllimport)
respectively. We make the EPUB3_EXPORT macro available for this purpose; when
building the library itself, it is defined as __declspec(dllexport), otherwise
as __declspec(dllimport).
When working with classes, it is possible to mark the entire class with this attribute, for example:
class EPUB3_EXPORT MyClass : public BaseClass
{
...
};
There is a downside to this, however, which is that marking the *class* in this
way causes all members and superclasses (and thus all *their* members and
superclasses, etc.) to be marked in the same manner. Since Readium makes heavy
use of the C++ standard library, this has the effect of exporting a very large
number of classes and methods. Worse, it causes a massive number of compiler
warnings (and some errors!). Therefore, we do *not* export entire classes
unless there is a pressing reason to do so.
Instead, we export only the members of that class which need to be exported. This is done by prefixing each member with the EPUB3_EXPORT macro, like so:
class MyClass : public BaseClass
{
public:
EPUB3_EXPORT MyClass();
EPUB3_EXPORT operator=(MyClass&&);
...
};
This may at first seem like a lot of work, but there are some exceptions to
this rule:
1. Any virtual functions of a class do not need to be exported-- they are
called through the class's always-known virtual function table, and thus
don't need to be looked up in a DLL export table.
2. Any inline functions will be built into the calling function, including any
with inline definitions within the header file. These also don't need an
entry in the export table.
As a result, there are quite a few classes which remain usable with no (or almost none) of their members explicitly exported. This is, therefore, the preferred method of DLL exporting/importing for this project.