-
Notifications
You must be signed in to change notification settings - Fork 0
/
README.txt
229 lines (152 loc) · 5.9 KB
/
README.txt
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
csaw: life's too short to write header files
--------------------------------------------
What It Is
----------
A preprocessor for C++ which saves you from having to write
header files or forward declarations.
Why?
----
I want to be able to write code as a set of files, each file
containing some arbitrary declarations, not write any #include
or #imports, not write anything twice (like .c/.h files) and
have the computer sort it all out.
Basic Usage
-----------
csaw -oc <output_src> -oh <output_h> <input_files>
You give csaw a set of input files. Each input file contains
one or more C++ declarations. Think of each file as a module.
You don't need to #include or otherwise import anything; if
a module references an identifier defined in another module,
the dependency is resolved automatically.
Csaw outputs a single C++ source file containing all
your code. Interfaces and implementations are split apart
automatically and written to the file in dependency order.
Optionally, you can ask for a separate .h file containing
only the interfaces, and omitting most function bodies. This
is useful if you're compiling a library and you want to
distribute a normal .h file to your users, or if you have
a large program which you'd like to compile in several
translation units. In that case, you'd call csaw once for
each unit, compile each to its own .o file, and link them
together as usual.
Features
--------
Supports C, C++ and Objective-C.
Libraries
---------
Csaw is not designed to process arbitrary C or C++ code and you
shouldn't feed libraries to it. Instead, process only your own
code with csaw, and #include your libraries using csaw's -i option
or your compiler's command-line switches.
Preprocessor
------------
Csaw doesn't implement a preprocessor or understand preprocessor
directives. If you use the preprocessor, you should run it first
and pass the processed source to csaw.
Limitations: General
--------------------
* The whole thing is a massive hack, and is very much "works for
me". It understands enough of C++ to be useful for my own projects,
but I'm sure there are large gaps beyond even what is documented
here. PRs are welcome!
Limitation: Nested Names
------------------------
Nested classes are not fully supported. The difficulty comes from the
fact that nested classes cannot be forward-declared outside of their
containing class.
This causes two problems; one fixable, one not.
1. We rely on blanket forward-declaring all classes at the
top of the output file, so we know the names will be there
for the rest of the file. This means we don't have to think
about "soft dependencies" (requiring forward-declaration),
only "interface dependencies" (requiring full declaration).
But, since there is no forward-declaration of nested
classes, we must consider ANY reference at all to the name
of a nested class to introduce an interface dependency. This
is MUCH more work, since names can appear basically anywhere.
2. The situation is not even solvable in the general case.
For example, it is not possible in C++ to order these
definitions in a way that will satisfy a conformant compiler:
class A {
class AA {};
void f(B::BB) {}
};
class B {
class BB {};
void f(A::AA) {}
};
Avoid using nested names from outside their containing class.
Limitation: Anonymous namespaces
--------------------------------
Anonymous namespaces are not supported.
Limitation: Static const member variables
-----------------------------------------
C++ allows static const integral member variables to be used
as constants; csaw supports this but requires you to define
them 'constexpr'.
Example:
class MyClass {
static const int sz = 16;
// ^ csaw requires 'constexpr' here
int array[sz];
}
Rationale: This so csaw doesn't have to figure out what is
an integer and what isn't (C++ rules only make this provision
for integral types)
Enhancement: Classes
--------------------
Class member functions should always be defined in the class
body. In C++ this also makes them inline, but with csaw this
will only happen if you explicity mark them 'inline'.
Rationale: Saves you writing the function signature twice.
Enhancement: Static member variables
------------------------------------
C++ requires (most) static member variables to be initialized
out-of-line. With csaw, you can always initialize them inline.
Example:
class MyClass {
static const char *word = "hippo"; // OK; would be invalid C++
};
Rationale: Saves you declaring the variable twice.
Limitation: Objective-C
-----------------------
Ech Objective-C class must be written as an @interface block with its
@implementation immediately following it.
Limitation: Templates
---------------------
Templates are supported, but some conservative estimates are
made about what depends on what. For example, with:
class my_class {
my_template<my_type> my_var;
};
my_class will be considered to depend on my_type being fully
defined, though that won't necessarily be the case; my_template
could instantiate only a pointer to it, or not use it at all.
(my_class will also be considered to depend on my_template,
but that is always correct.)
It doesn't seem feasible to automatically do the right thing
in this case, though we could probably have csaw take hints
on what to do for a particular template.
Fast Incremental Compiles
-------------------------
all.h: src/*.cc
csaw -oh $@.1 $^
cp -n $@.1 $@
all.pch: all.h
$(MAKE_PCH) -o $@ $<
%.mod.cc: src/%.cc all.pch
csaw -oc $@ $<
%.o: $.mod.cc:
$(CC) -c -o $@ $<
Q&A
---
Q: Why are you parsing C++ by hand? Are you insane? Do you know
libclang exists?
A: Clang only reliably parses correct C++, and the whole point
of csaw is to save you from having to write correct C++. In
particular, clang requires type information to be declared
before names are referenced, which we don't want to require.
See Also
--------
Lazy C++ <https://www.lazycplusplus.com> : Another project
with a similar goal.