• Perfect c amalgamator tool requirements

    From Thiago Adams@thiago.adams@gmail.com to comp.lang.c on Fri Sep 18 11:53:56 2026
    From Newsgroup: comp.lang.c


    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?
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Johann \@johann@myrkraverk.invalid to comp.lang.c on Sun Sep 20 05:09:24 2026
    From Newsgroup: comp.lang.c

    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

    -a-a-a 1. Follow `#include` directives (except system includes) and add each
    -a-a-a file only once.

    -a-a-a 2. Preserve the original order.

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

    More...

    -a-a-a 4. Remove #pragma once since it does not make sense in the amalgamated
    -a-a-a source file. Preserve other pragmas.

    -a-a-a 5. #undef macros that were defined inside the source file before
    -a-a-a appending the next source file. Keep macro definitions from headers.

    More advanced...

    -a-a-a 6. Detect when a `static` function or variable is appended more than
    -a-a-a once. Auto-rename?

    -a-a-a 7. I was thinking about adding `static` in front of functions that are
    -a-a-a not `extern`. This could be an alternative to the workaround of using
    -a-a-a `PUBLIC`/`PRIVATE` macros, where programmers define `PRIVATE` as
    -a-a-a `static` in the amalgamated file. Then, for example, if you want a
    -a-a-a function to be public, you write `extern` in front of it.

    -a-a-a 8. A header file containing the public interface for the amalgamator
    -a-a-a could be read first. This could also help define what should be made
    -a-a-a `static`. It could be interesting to optionally add a prefix to all
    -a-a-a public functions, etc. This would work like a namespace.

    -a-a-a 9. Optionally add `#line` directives referring to the original source
    -a-a-a files.

    -a-a-a 10. Deduplicate system includes, such as `#include <stdio.h>`, so each
    -a-a-a one appears only once.

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

    -a-a-a 12. Maybe put all system includes at the top.

    -a-a-a 13. Maybe add an `-ignore` block to ignore `#ifdef` blocks that should
    -a-a-a not be included. For example, if a library has `#ifdef TEST` code that
    -a-a-a is only needed for testing, this code could be excluded from the
    -a-a-a 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 ( ;; ) _:;
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From bart@bc@freeuk.com to comp.lang.c on Sat Sep 19 22:50:57 2026
    From Newsgroup: comp.lang.c

    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

    -a-a-a 1. Follow `#include` directives (except system includes) and add each
    -a-a-a file only once.

    I'm not sure what this means. Does the amalgamator flatten all the
    nested includes?


    -a-a-a 2. Preserve the original order.

    -a-a-a 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...

    -a-a-a 4. Remove #pragma once since it does not make sense in the amalgamated
    -a-a-a source file. Preserve other pragmas.

    -a-a-a 5. #undef macros that were defined inside the source file before
    -a-a-a appending the next source file. Keep macro definitions from headers.

    More advanced...

    -a-a-a 6. Detect when a `static` function or variable is appended more than
    -a-a-a 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.)

    -a-a-a 7. I was thinking about adding `static` in front of functions that are
    -a-a-a 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
    -a-a-a `PUBLIC`/`PRIVATE` macros, where programmers define `PRIVATE` as
    -a-a-a `static` in the amalgamated file. Then, for example, if you want a
    -a-a-a function to be public, you write `extern` in front of it.

    -a-a-a 8. A header file containing the public interface for the amalgamator
    -a-a-a could be read first. This could also help define what should be made
    -a-a-a `static`. It could be interesting to optionally add a prefix to all
    -a-a-a public functions, etc. This would work like a namespace.

    -a-a-a 9. Optionally add `#line` directives referring to the original source
    -a-a-a files.

    -a-a-a 10. Deduplicate system includes, such as `#include <stdio.h>`, so each
    -a-a-a 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.


    -a-a-a 11. Handle header macro collisions. I think this is uncommon, but two
    -a-a-a 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

    -a-a-a 12. Maybe put all system includes at the top.

    -a-a-a 13. Maybe add an `-ignore` block to ignore `#ifdef` blocks that should
    -a-a-a not be included. For example, if a library has `#ifdef TEST` code that
    -a-a-a is only needed for testing, this code could be excluded from the
    -a-a-a 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.
    --- Synchronet 3.22a-Linux NewsLink 1.2
  • From Thiago Adams@thiago.adams@gmail.com to comp.lang.c on Mon Sep 21 08:23:41 2026
    From Newsgroup: comp.lang.c

    On 9/19/2026 6:50 PM, bart wrote:
    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?

    https://github.com/thradams/cake/blob/main/src/tools/amalgamator.c

    What it does:
    - It does #undef.
    - It comments #pragma once.

    What it does not do:

    - Requires unique static names.
    - does not group system (that is more of visual cleanup)
    - It does not do "statification", if someone want that it need to use
    macros like PUBLIC/PRIVATE.

    I also have more tools like one to collect unit tests and write a single function that calls them all. I was thinking in to unify these two
    tools and any other tools that depends on a tokenizer for the C code.


    Thiago

    --- Synchronet 3.22a-Linux NewsLink 1.2