Headers – Working with Multiple Files
Pre-waffle: What headers are for
Multiple source files can included in one shared libraryAn executable file containing definitions (function/variables/...) but no main method. just by passing
more than one source file to cslug.CSlug. The namespace for each source
file will be merged (clashes cause a build error). If you want to be able to use
functions from one file in another file then you need a header file.
To demonstrate how to do this we'll be using the following uninspired example:
int do_nothing(int x) {
return x;
}
int uses_do_nothing(int x) {
/* Calls ``do_nothing()`` from ``file1.c``. */
return do_nothing(x);
}
This refuses to compile because there is a reference to do_nothing() from
file1.c inside file2.c (although some compiler versions let you off with
just a warning):
from cslug import CSlug
slug = CSlug("lib_nothing", "file1.c", "file2.c")
slug.make()
To keep the compiler happy we need to put a function prototype for
do_nothing() somewhere visible to file2.c. In this simple case it's enough
to just put int do_nothing(int x); at the top of file2.c but if a third
file also needed do_nothing() then this would require duplicating the
prototype. The more general solution is to put function prototypes in a header
file which any other file can #include.
Auto-generating header files
Writing header files is boring and generally devolves to copy/paste (bad).
cslug.Header tries to do it for you. The following writes a header file
containing prototypes for every function from file1.c and file2.c.
from cslug import Header, CSlug
header = Header("my-header.h", "file1.c", "file2.c")
slug = CSlug("lib_nothing", "file1.c", "file2.c", headers=header)
Passing the header to CSlug means that calling
slug.make() will implicitly call header.make() so that you still only have one make() command
(although you may use header.make() directly or
header.write() to experiment with
Headers without going through a CSlug).
The resulting header file looks something like:
// Header file generated automatically by cslug.
// Do not modify this file directly as your changes will be overwritten.
#ifndef MY_HEADER_H
#define MY_HEADER_H
// file1.c
int do_nothing(int x);
// file2.c
int uses_do_nothing(int x);
#endif
Now any file which references anything from either file1.c or file2.c need
only #include "my-header.h".
Note
You don't need to pass header files (automatically generated or otherwise)
to cslug.CSlug, although there is no harm in doing so.
Add #includes to generated headers
If you use types which are defined in other header files such as wchar_t
then you need to #include those headers to the generated header. For local
headers use:
Header(..., includes='some-header.h')
or for system-wide ones libraries enclose with angle brackets:
Header(..., includes='<stddef.h>')
Pass a list if you have more than one:
Header(..., includes=['<stddef.h>', '<stdint.h>'])
Add arbitrary code to generated headers
This is intentionally not supported. If you want custom code in an automatically
generated header then put your code in a separate file which either
#includes or is #included by the generated one.