added stb, more binaryout changes"
[henge/apc.git] / stb / docs / stb_howto.txt
1 Lessons learned about how to make a header-file library
2 V1.0
3 September 2013 Sean Barrett
4
5 Things to do in an stb-style header-file library,
6 and rationales:
7
8
9 1. #define LIBRARYNAME_IMPLEMENTATION
10
11 Use a symbol like the above to control creating
12 the implementation. (I used a far-less-clear name
13 in my first header-file library; it became
14 clear that was a mistake once I had multiple
15 libraries.)
16
17 Include a "header-file" section with header-file
18 guards and declarations for all the functions,
19 but only guard the implementation with LIBRARYNAME_IMPLEMENTATION,
20 not the header-file guard. That way, if client's
21 header file X includes your header file for
22 declarations, they can still include header file X
23 in the source file that creates the implementation;
24 if you guard the implementation too, then the first
25 include (before the #define) creates the declarations,
26 and the second one (after the #define) does nothing.
27
28
29 2. AVOID DEPENDENCIES
30
31 Don't rely on anything other than the C standard libraries.
32
33 (If you're creating a library specifically to leverage/wrap
34 some other library, then obviously you can rely on that
35 library. But if that library is public domain, you might
36 be better off directly embedding the source, to reduce
37 dependencies for your clients. But of course now you have
38 to update whenever that library updates.)
39
40 If you use stdlib, consider wrapping all stdlib calls in
41 macros, and then conditionally define those macros to the
42 stdlib function, allowing the user to replace them.
43
44 For functions with side effects, like memory allocations,
45 consider letting the user pass in a context and pass
46 that in to the macros. (The stdlib versions will ignore
47 the parameter.) Otherwise, users may have to use global
48 or thread-local variables to achieve the same effect.
49
50
51 3. AVOID MALLOC
52
53 You can't always do this, but when you can, embedded developers
54 will appreciate it. I almost never bother avoiding, as it's
55 too much work (and in some cases is pretty infeasible;
56 see http://nothings.org/gamedev/font_rendering_malloc.txt ).
57 But it's definitely something one of the things I've gotten
58 the most pushback on from potential users.
59
60
61 4. ALLOW STATIC IMPLEMENTATION
62
63 Have a #define which makes function declarations and
64 function definitions static. This makes the implementation
65 private to the source file that creates it. This allows
66 people to use your library multiple times in their project
67 without collision. (This is only necessary if your library
68 has configuration macros or global state, or if your
69 library has multiple versions that are not backwards
70 compatible. I've run into both of those cases.)
71
72
73 5. MAKE ACCESSIBLE FROM C
74
75 Making your code accessible from C instead of C++ (i.e.
76 either coding in C, or using extern "C") makes it more
77 straightforward to be used in C and in other languages,
78 which often only have support for C bindings, not C++.
79 (One of the earliest results I found in googling for
80 stb_image was a Haskell wrapper.) Otherwise, people
81 have to wrap it in another set of function calls, and
82 the whole point here is to make it convenient for people
83 to use, isn't it? (See below.)
84
85 I prefer to code entirely in C, so the source file that
86 instantiates the implementation can be C itself, for
87 those crazy people out there who are programming in C.
88 But it's probably not a big hardship for a C programmer
89 to create a single C++ source file to instantiate your
90 library.
91
92
93 6. NAMESPACE PRIVATE FUNCTIONS
94
95 Try to avoid having names in your source code that
96 will cause conflicts with identical names in client
97 code. You can do this either by namespacing in C++,
98 or prefixing with your library name in C.
99
100 In C, generally, I use the same prefix for API
101 functions and private symbols, such as "stbtt_"
102 for stb_truetype; but private functions (and
103 static globals) use a second underscore as
104 in "stbtt__" to further minimize the chance of
105 additional collisions in the unlikely but not
106 impossible event that users write wrapper
107 functions that have names of the form "stbtt_".
108 (Consider the user that has used "stbtt_foo"
109 *successfully*, and then upgrades to a new
110 version of your library which has a new private
111 function named either "stbtt_foo" or "stbtt__foo".)
112
113 Note that the double-underscore is reserved for
114 use by the compiler, but (1) there is nothing
115 reserved for "middleware", i.e. libraries
116 desiring to avoid conflicts with user symbols
117 have no other good options, and (2) in practice
118 no compilers use double-underscore in the middle
119 rather than the beginning/end. (Unfortunately,
120 there is at least one videogame-console compiler that
121 will warn about double-underscores by default.)
122
123
124 7. EASY-TO-COMPLY LICENSE
125
126 I make my libraries public domain. You don't have to.
127 But my goal in releasing stb-style libraries is to
128 reduce friction for potential users as much as
129 possible. That means:
130
131 a. easy to build (what this file is mostly about)
132 b. easy to invoke (which requires good API design)
133 c. easy to deploy (which is about licensing)
134
135 I choose to place all my libraries in the public
136 domain, abjuring copyright, rather than license
137 the libraries. This has some benefits and some
138 drawbacks.
139
140 Any license which is "viral" to modifications
141 causes worries for lawyers, even if their programmers
142 aren't modifying it.
143
144 Any license which requires crediting in documentation
145 adds friction which can add up. Valve used to have
146 a page with a list of all of these on their web site,
147 and it was insane, and obviously nobody ever looked
148 at it so why would you care whether your credit appeared
149 there?
150
151 Permissive licenses like zlib and BSD license are
152 perfectly reasonable, but they are very wordy and
153 have only two benefits over public domain: legally-mandated
154 attribution and liability-control. I do not believe these
155 are worth the excessive verbosity and user-unfriendliness
156 these licenses induce, especially in the single-file
157 case where those licenses tend to be at the top of
158 the file, the first thing you see. (To the specific
159 points, I have had no trouble receiving attribution
160 for my libraries; liability in the face of no explicit
161 disclaimer of liability is an open question.)
162
163 However, public domain has frictions of its own, because
164 public domain declarations aren't necessary recognized
165 in the USA and some other locations. For that reason,
166 I recommend a declaration along these lines:
167
168 // This software is dual-licensed to the public domain and under the following
169 // license: you are granted a perpetual, irrevocable license to copy, modify,
170 // publish, and distribute this file as you see fit.
171
172 I typically place this declaration at the end of the initial
173 comment block of the file and just say 'public domain'
174 at the top.
175
176 I have had people say they couldn't use one of my
177 libraries because it was only "public domain" and didn't
178 have the additional fallback clause, who asked if
179 I could dual-license it under a traditional license.
180
181 My answer: they can create a derivative work by
182 modifying one character, and then license that however
183 they like. (Indeed, *adding* the zlib or BSD license
184 would be such a modification!) Unfortunately, their
185 lawyers reportedly didn't like that answer. :(