• Perfect c amalgamator tool requirements

    From Thiago Adams@3:633/10 to All on Fri Sep 18 11:53:56 2026

    I want to improve my existing one and then share it.

    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.

    2. Preserve the original order.

    3. Allow exceptions for files that should not be appended.

    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?

    7. I was thinking about adding `static` in front of functions that are
    not `extern`. 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.

    11. Handle header macro collisions. I think this is uncommon, but two
    headers could define the same macro name.

    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?

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann "Myrkraverk" Oskarsson@3:633/10 to All on Sun Sep 20 05:09:24 2026
    On 9/18/2026 10:53 PM, Thiago Adams wrote:

    I want to improve my existing one and then share it.

    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.

    ÿÿÿ 2. Preserve the original order.

    ÿÿÿ 3. Allow exceptions for files that should not be appended.

    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?

    ÿÿÿ 7. I was thinking about adding `static` in front of functions that are
    ÿÿÿ not `extern`. 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.

    ÿÿÿ 11. Handle header macro collisions. I think this is uncommon, but two
    ÿÿÿ headers could define the same macro name.

    ÿÿÿ 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?

    Yes. If you want a /perfect/ amaglamation tool, you need to deal with
    these two /edge cases/,

    1. Libraries like the Miniaudio that has everything in the header,
    and you need to include the implementation exactly once.

    https://miniaud.io/

    2. You need to deal with people defining _POSIX_C_SOURCE on the com-
    piler command line, and with people defining it in the source
    files.

    What are you going to do, if the same project has different defi-
    nitions in different .c files?

    So my advice, is to just forge ahead, and make a tool that's /good
    enough/ for your use cases, and forget about trying to make it per-
    fect.


    Best wishes, and happy amalgamation!

    Side note, why did none of the standard thumpers reply to you? Are they
    lazy, or ignorant, or something?
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From bart@3:633/10 to All on Sat Sep 19 22:50:57 2026
    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)