Combining C ++ Header Files

Is there an automatic way to capture a large number of C ++ header files and merge them into a single file?

This operation should, of course, concatenate the files in the correct order, to types, etc. were not defined before they will be used in the following classes and functions.

Basically, I'm looking for something that allows me to distribute my library in two files ( libfoo.h, libfoo.a ) instead of the current combination of include files + binary library.

+6
source share
7 answers

As your comment says:

.. I want this to be easier for library users, so they can just make one single #include and have it all.

Then you can just spend some time including all the headers in the wrapper header, in the correct order. 50 headings are not so many. Just do something like:

 // libfoo.h #include "header1.h" #include "header2.h" // .. #include "headerN.h" 

It will not take long if you do it manually.

Also, adding new headers later is a matter of seconds to add them to this shell header.

In my opinion, this is the simplest, cleanest and most effective solution.

+9
source

What do you want to do, "javascriptish" sounds to me :-). But if you insist, there is always "cat" (or the equivalent on Windows):

 $ cat file1.h file2.h file3.h > my_big_file.h 

Or, if you are using gcc, create the file my_decent_lib_header.h with the following contents:

 #include "file1.h" #include "file2.h" #include "file3.h" 

and then use

 $ gcc -C -E my_decent_lib_header.h -o my_big_file.h 

and in this way you even get file / line directives that will reference the source files (although this can be disabled if you want).

As for how automated this is for your file order, well, that’s not at all true; You must decide the order yourself. In fact, I would be surprised to see that a tool that organizes the header dependencies correctly in all cases for C / C ++ can be built.

+2
source

If you have a main include file that includes all the others, you can simply hack the re-implementation of the C preprocessor in Perl. The process only "" -style includes and recursively insert the contents of these files. There must be twenty liners.

If not, you should write or try at random. Automatic dependency tracking in C ++ is tough . As in "let them see if this instance of the template creates an implicit creation of the class of arguments". The only automatic way I see is to shuffle your included files in a random order, see if the whole package is compiled, and shuffle them until it compiles. What takes n! you can write better, including the file manually.

While the first option is simple enough for hacking, I doubt the sensitivity of this hacking because you want to distribute at the package level (source archive, deb package, Windows installer) instead of the file level.

+1
source

If your library is so large that you cannot create and maintain a single header file with a wrapper, as Cyril suggested, this may mean that it is not well designed.

So, if your library is really huge (over a million lines of source code), you can consider automating this with tools like

  • GCC create a dependency generator preprocessor parameters like -M -MD -MF etc. with another manual sort script / li>
  • expensive commercial static analysis tools like coverity
  • compiler configuration via plugins or (for GCC 4.6) MELT extensions

But I do not understand why you want an automated way to do this. If the library is reasonably sized, you should understand it and be able to write and maintain the package header manually. Automating this task will require several efforts (probably weeks, not minutes), so it’s worth using only for very large libraries.

+1
source

usually you don’t want to include every bit of information from all your headings in a special heading that allows a potential user to actually use your library. The non-trivial removal of type definitions, which additionally includes or defines which are not necessary for the user of your interface, cannot be automated. As far as I know.

A short answer to your main question:

  • Not.

My suggestions:

  • manually create a new header containing all the relevant information (no more, no less) for the user of your library interface. Add some nice documentation comments for each component it contains.

  • Use advanced declarations, if possible, rather than the full definitions included. Put the actual data in your implementation files. The fewer inclusions you have in the headings, the better.

  • Do not build a deeply nested inclusion hierarchy. This makes it extremely difficult to keep an overview of the contents of each bit you add. Your library user will look in the header to find out how to use it. And he probably will not be able to distinguish the corresponding code from irrelevant at first sight. You want to maximize the ratio of the corresponding code for the common code in the main header for your library.

EDIT

If you really have a library of tools, and the order of inclusion really does not matter, and you have a bunch of independent headers that you want to list for convenience only in one heading, then you can use a simple script. Like the following Python (untested):

 import glob with open("convenience_header.h", 'w') as f: for header in glob.glob("*.h"): f.write("#include \"%s\"\n" % header) 
0
source

You really need a build script to generate this when you work, and a preprocessor flag to disable the use of amalgam (this may be for your purposes).

To simplify this script / program, it helps to create header structures and incorporate hygiene into the upper form.

  • Your program / script should know your detection paths (hint: minimize the number of search paths to one, if possible).

  • Run the script or program (which you are creating) to replace the include directives with the contents of the header file.

  • Assuming your headers are protected, as is usually the case, you can keep track of which files you have already physically included, and do not take any action if there is another request to include them. If the header is not found, leave it as it is (as an include directive) - this is necessary for the headers of systems / third parties - unless you use a separate header for external inclusions (which is not a bad idea).

  • It is good to have a build / translation phase that includes only the header and generates zero warnings or errors (warnings like errors).

Alternatively, you can create a special distribution repository, so they don’t need to do more than extract from it from time to time.

0
source

A little late, but here it is. I recently came across this problem myself and coded this solution: https://github.com/rpvelloso/oneheader

How it works?

  • Your project folder is checked for C / C ++ headers and a list of found headers is created;

  • For each title in the list, it analyzes its #include directives and collects a dependency graph as follows:

    • If the included header is not inside the project folder, it is ignored (for example, if it is a system header);

    • If the included header is inside the project folder, an edge is created in the dependency graph that connects the included header to the current header, which is being analyzed;

  • The dependency graph is topologically sorted to determine the correct order to merge the headers into a single file. If a cycle is found on the graph, the process is interrupted (i.e. if it is not a DAG);

Limitations:

  • Currently, it only detects single-line #include directives (for example, #include);
  • It does not handle headers with the same name in different ways;
  • It gives you the correct order to merge all the headers, you still need to concatenate them (maybe you want to delete or change some of them before merging).

Compilation:

g ++ -Wall -ggdb -std = C ++ 1y -lstd ++ fs oneheader.cpp -o oneheader [.exe]

Using:

./oneheader [.exe] project_folder / "> file_sequence.txt

0
source

Source: https://habr.com/ru/post/903269/


All Articles