Skip to content

rogual/csaw

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 

Repository files navigation

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 [email protected] $^
       cp -n [email protected] $@

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.

About

Life's too short to write header files.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages