Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I automatically generate / update header files from cpp files without using an IDE?

I am using VIM for C++ development for quite some years now and I don't want to debate the question whether to use an IDE or powerful text editor for software development. Up to now I've been involved mostly with a header-only template library where everything is either a template or declared inline, thus .cpp files don't play a major role.

Recently I'm more involved in "traditional" C++ development, facing the old issue of header / non-header file synchronization. I'm wondering if there are any command-line tools around that could be used in a make target or be integrated into VIM to handle this job, i.e. update header files based on .cpp files. Basically, declarations of classes / structs or (template and inline) implementations should be ignore int he header files, while function declarations should be added, removed or updated based on the .cpp file.

I'm aware of the lzz tool, however, that requires you to actually code in an additional, third file format that is then preprocessed to .h / .cpp files before the actual compilation.

Is there anything around that can do the job? How do other non-IDE developers handle this problem?

like image 862
barbaz Avatar asked Apr 06 '13 19:04

barbaz


People also ask

Are header files automatically generated?

Since the headers are automatically generated, it doesn't make sense to reuse the headers. Instead, each source file gets its own customized header file. The program puts in what is necessary and in the right order.

Can we create our own header files in C++?

Yes, you can create your own header file. Kindly go through thinking in c++ by bruce eckel vol 1. These files have declaration of user defined data structures and interfaces such has class declaration, function prototypes and etc.

Can you have a header file without a cpp file?

You don't need a cpp file. Including the header is enough. The preprocessor expands your defines with whatever is after it.

How do I create a custom header file in cpp?

You make the declarations in a header file, then use the #include directive in every . cpp file or other header file that requires that declaration. The #include directive inserts a copy of the header file directly into the . cpp file prior to compilation.


1 Answers

As I myself am very curious about answers to your first question unfortunately I am not able to give you any good advice here.

To at least give you an answer to your second question: This is the somewhat semi-automatic way I use to manually add missing or adjust changed declarations in out of sync header files.

use the compiler with warnings enabled (!) to spot missing / changed declarations:

Adjust declarations

After changing the signature of a function definition gcc will throw an error like the following one:

  • error: conflicting types for ‘....’
    note: previous declaration of ‘....’ was here

Fixing this one is relatively easy as both a reference to the definition and the corresponding declaration are already given in the error message.

As I am an emacs user I can't tell you the way this is done in vi, but I am quite sure there is an equally simple way to automatically jump to this spots. All that has to be done is:

  • jump to location one copy the line

  • jump to location two replace old line with the copy and add a trailing ;

Missing declarations

If on the other a new function was added without adding it's prototype to the corresponding header file gcc will throw something like:

  • warning: implicit declaration of function ...

Fixing this one a tag table comes in handy. Again I don't know for sure how this is handled in vi, but I am quite sure there is some way to quickly jump to the function definition given by its name in the compiler warning as well.

Workflow here looks like this:

  • jump to function ....'s definition, copy line

  • switch to header file, paste line and add a trailing ;

While this method is anything but elegant it has turned out to be working for those cases in which I forgot to adjust the header to keep it in sync with the source file, which can be done with a few keystrokes.

A broken Example

To demonstrate its application by example here a minmal program that needs it's headers to be fixed:

/* main.c */ #include "add.h"  int main (int argc, char *argv[]) {   int a=0, b=0;    add (a, b);   sub (a, b);    return 0; } 

Both functions add and sub are defined in add.c shown below:

/* add.c */ #include "add.h"  int add (int a, int b) {   return a + b; }  int sub (int a, int b) {   return a - b; } 

The culprit add.h shows both a signature mismatch of the function add and a missing declaration of the function sub:

/* add.h */ long add (long a, long b); 

Trying to compile will result in:

gcc -Wall main.c add.c main.c: In function ‘main’: main.c:7: warning: implicit declaration of function ‘sub’ add.c:3: error: conflicting types for ‘add’ add.h:2: note: previous declaration of ‘add’ was here 

Fixing the example

Missing declarations

The first problem:

  • main.c:7: warning: implicit declaration of function ‘sub’

Is due to the fact that a declaration of sub is missing in add.h

Finding the right signature:

  • C-x` (next-error) will jump to the location of the error
  • M-. (gtags-find-tag) will prompt for the tag to lookup
  • RET will jump to the definition of sub as the symbol at point is the default
  • M-z{ (zap-to-char) C-y (yank) to copy the signature

Up to here all steps could have also be done automatically by a keyboard macro as no intervention was needed. The next part will have to be done by hand:

  • open the "correct" header file
  • and navigate to the spot where the declaration should be entered

As the choice of "correct" header file and "correct" location most probably is a matter of taste in contrast to the steps taken so far I don't think there's much automation possible here.

Finally the last step is to paste the copied signature:

  • C-yM-y paste the copied signature
  • DEL; to replace { with ;

Adjusting declarations

Next the mismatch between adds declaration and definition has to be fixed.

add.c:3: error: conflicting types for ‘add’ add.h:2: note: previous declaration of ‘add’ was here 

To copy the new signature from the definition:

  • C-x` (next-error) will jump to the location of the definition
  • M-z{ (zap-to-char) C-y (yank) to copy the signature

To replace the declaration:

  • C-x` (next-error) will jump to the location of the declaration
  • M-z; (zap-to-char) to delete the old declaration
  • C-yM-y now paste the copied signature
  • DEL; to replace { with ;

And back again

Since two buffers have been poped:

  • M-2M-x burry-buffer should go back to buffer that was visited before

Summary

As you can see while not a too time consuming process constantly jumping back and forth to fix missing or wrong declarations using this approach is still a rather tedious task I only use it to fix up declarations that I mistyped or completely missed in the first run.

Manually placing the "correct" declarations into the header still is the main approach that I take.

As laying out the API prior to implementing it might not be the worst idea IMHO this strategy shouldn't be a choice too bad.

like image 130
mikyra Avatar answered Oct 11 '22 14:10

mikyra