0

I have a very special problem, but I hope here is someone who can help me. I am writing a C/C++ program, but I have to deal with legacy libraries written in Structured Text (ST, IEC 61131-3). In ST everything is accessible from nearly everywhere, so nobody did ever care for library dependencies in the past. My IDE automatically generates a C-Header for each legacy ST library. But this results in many hundred C-Header files, with crazy dependencies and a lot of forward declarations. If I try to include any single header from this mess, I end up searching endlessly for the required other headers to include.

Does anybody knows a way to analyze the C-header files to find all necessary files for a given type/file and the correct include order? I already found this tool here: rpvelloso/oneheader But this does not resolve the forward declarations. My compiler (gcc) complains hundred times about incomplete types. I would even accept something monstrous like "LegacyAllInOneHeader.h" which includes all legacy libraries, if I only find a way to use the legacy code.

Additional Info:

  1. I have no influence on the header file generation
  2. Header files will have always the same name after each regeneration
  3. Many headers have circular dependencies

Many thanks in advance for your help.

Example:

ST_Lib1 might result in such a header:

typedef struct type1
{   struct type2 data1[7];
    struct type3 data2[7];
} type1;

ST_Lib2 might result in such a header:

typedef struct type2
{   struct int data1[7];
    struct type4 data2[7];
} type2;

In my C-Program I need to figure out, which headers are all necessary and the correct order:

//Still need to look up "type3" and "type 4"
#include <ST_Lib2.h>
#include <ST_Lib1.h>

main()
{
    //do something
}
Spinoza
  • 5
  • 3
  • 2
    The principle that I try to use is: **include what you use**. So all my header files and source files `#include` all their dependencies if they use them, or forward declare (or use header-header files that forward declare) the identifiers that are referred to but are not *used*. That approach has worked well for me, and scales well (I have about 500,000 files in my project, covering 57 million lines of code). – Eljay Mar 21 '23 at 13:14
  • I totally agree with you. But here I have to deal with a huge mess of header files, which I am not allowed/able to change. So either I need to work through this pile of headers every time I need something from it (last time, this took me half a day), or I am able to build a "all in one header" once (or someone has another idea?) – Spinoza Mar 21 '23 at 13:18
  • Please [edit] your question and add a few examples what problems you have to solve with these header files. Is the legacy library still being modified? If not I would suggest to modify the generated header files manually to add the required `#include`s once and save this modification in your SCM to allow automatically modifying headers for a modified library. Maybe see https://gernotklingler.com/blog/open-source-tools-examine-and-adjust-include-dependencies/ and the referenced https://github.com/include-what-you-use/include-what-you-use – Bodo Mar 21 '23 at 13:35
  • It sounds like your problem is you have a number of header files and want to automatically find the dependencies between them. If so, you should edit your post to say that. However, there are prior questions on this, such as [this one](https://stackoverflow.com/questions/10863285/tool-to-find-all-header-and-source-file-dependencies-in-c). – Eric Postpischil Mar 21 '23 at 13:40
  • I would make a 'master' header file which `#include`s all those itty-bitty little header files and then make it a precompiled header. By doing that, you should get fast compile times without breaking your back trying to figure out what to include and what not on a case-by-case basis. – Paul Sanders Mar 21 '23 at 13:45
  • 2
    I'd do this: make an "LegacyAllInOneHeader.h" that has all those ST header files listed with their `#include "blah.h"` one-by-one, alphabetically. Compile that meta-header file, and every time the compiler complains about a missing dependency, move that `#include` to the bottom of the list. You could probably write a script, and have that done automatically, until that meta-header file compiles to completion. (A bubble sort. A slow, slow bubble sort.) – Eljay Mar 21 '23 at 13:51
  • "My IDE automatically generates a C-Header for each legacy ST library." How does this process work, what IDE and tools are used, and most importantly: is there a way to configure this process? – Thomas Mar 21 '23 at 13:55
  • @Thomas: It is a proprietary IDE from a big PLC manufacturer. I have no influence on the C-Header generation. – Spinoza Mar 21 '23 at 14:00
  • @Bodo: The legacy code might change a couple of times per year, but not on daily basis – Spinoza Mar 21 '23 at 14:03
  • @Spinoza Please add all requested information/clarification to the question. Will the generated header files have the same names when re-generated after changing the library? If not you might have the same amount of work on every chang. Otherwise choose between the sorted `LegacyAllInOneHeader.h` or modified IWYU copies of all generated headers. (`ST_Lib1.h` will contain `#include "ST_Lib2.h"` and similar for `type3` and `ST_Lib2.h` will `#include` the file for `type4` etc.) In both variants you will have less work to adapt the modified copies or the all-in-one file to a changed lib. – Bodo Mar 21 '23 at 14:39
  • I just tried Eljay's proposal to do the "bubble sort" with a small subset of headers. During that I found out, circular dependencies are also possible. I am despairing... Maybe it is simply not possible to do what I want with this header mess. – Spinoza Mar 21 '23 at 15:12
  • 1
    How bad are the circular dependencies? Obviously it is impossible for C struct types to mutually include each other, but it is common for one struct type to include a pointer to another struct type, perhaps mutually (e.g. `struct A` contains a `struct B *b;` member and `struct B` contains a `struct A *a;` member). That sort of circular dependency can be solved by adding incomplete, forward declarations of the problematic `struct` types to the "all-in-one" header. – Ian Abbott Mar 21 '23 at 15:36
  • I have pointers and other struct types with circular dependencies. I think nobody ever used the C-Header files for anything. Otherwise someone had already noticed this problem. I am currently thinking of a script which re-arrange the headers. But I think this is a big thing to do. – Spinoza Mar 21 '23 at 16:14

0 Answers0