On 18/09/2026 15:53, Thiago Adams wrote:
I want to improve my existing one and then share it.
Do you have a link to the existing one?
Does it work? If so then you must already be taking care of most
problems, so what doesn't it do?
I will write down some items that I think are necessary.
Basic stuff
ÿÿÿ 1. Follow `#include` directives (except system includes) and add each
ÿÿÿ file only once.
I'm not sure what this means. Does the amalgamator flatten all the
nested includes?
ÿÿÿ 2. Preserve the original order.
ÿÿÿ 3. Allow exceptions for files that should not be appended.
How does it know what files should be included anyway; is there some
sort of list?
More...
ÿÿÿ 4. Remove #pragma once since it does not make sense in the amalgamated
ÿÿÿ source file. Preserve other pragmas.
ÿÿÿ 5. #undef macros that were defined inside the source file before
ÿÿÿ appending the next source file. Keep macro definitions from headers.
More advanced...
ÿÿÿ 6. Detect when a `static` function or variable is appended more than
ÿÿÿ once. Auto-rename?
Do you mean clashes of the same local identifier between modules? How
does that work now?
(Not quite the same but when I transpile all modules in my language to
C, all top-level names have their module-name plus prepended.)
ÿÿÿ 7. I was thinking about adding `static` in front of functions that are
ÿÿÿ not `extern`.
So, is this amalgamator meant to work for any arbitrary C project? Then ideally you don't want to have to change anything.
This could be an alternative to the workaround of using
ÿÿÿ `PUBLIC`/`PRIVATE` macros, where programmers define `PRIVATE` as
ÿÿÿ `static` in the amalgamated file. Then, for example, if you want a
ÿÿÿ function to be public, you write `extern` in front of it.
ÿÿÿ 8. A header file containing the public interface for the amalgamator
ÿÿÿ could be read first. This could also help define what should be made
ÿÿÿ `static`. It could be interesting to optionally add a prefix to all
ÿÿÿ public functions, etc. This would work like a namespace.
ÿÿÿ 9. Optionally add `#line` directives referring to the original source
ÿÿÿ files.
ÿÿÿ 10. Deduplicate system includes, such as `#include <stdio.h>`, so each
ÿÿÿ one appears only once.
Those are usually guarded, if they stay as includes. But if flattened
into the amalgamation, then yes they ought to be omitted even if harmless.
ÿÿÿ 11. Handle header macro collisions. I think this is uncommon, but two
ÿÿÿ headers could define the same macro name.
Suppose the program uses files a.c and b.c. Both include a.h and b.h. A
simple concatenation would produce:
#include "a.h"
#include "b.h"
<body of a.c>
#include "a.h"
#include "b.h"
<body of b.c>
The same macro defined in a.h and b.h would already have thrown up
problems. But there might be macros local to a.c which clash with the
same names in b.c
ÿÿÿ 12. Maybe put all system includes at the top.
ÿÿÿ 13. Maybe add an `-ignore` block to ignore `#ifdef` blocks that should
ÿÿÿ not be included. For example, if a library has `#ifdef TEST` code that
ÿÿÿ is only needed for testing, this code could be excluded from the
ÿÿÿ published amalgamated version.
Did I forget anything?
There's a few things but if you have some working version they should
have come up. Hence my question at the top.
There are projects which are amalgamations, such as SQLite3, and the
one-file version of Lua. It might be worth looking at any approaches
they use. However both are for a specific project, which is a simpler task.
--- PyGate Linux v1.5.19
* Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)