Fixing C header file dependency issues - Page 1
Forum section: electronics / general

author: 741
author_rank: Frequent Contributor
timestamp: November 19, 2020, 11:43:55 am
content: In 2017, I used the Microchip usb framework code to make a HID keyboard. Now, when I try to compile, I see an error that is related to some #define. I can't think why it now gives errors, given it compiled last time (in 2017). It should be said that in the mean time I have done an OS re-install etc.There are no "file not found messages" above the error, and I can fix the error by manually defining the missing items:Code://These 2 lines are in "usb_hal_pic16f1.h", and are not being seen now...//#define BDT_BASE_ADDR 0x2000//#define BDT_BASE_ADDR_TAG @ BDT_BASE_ADDRvolatile BDT_ENTRY BDT BDT_BASE_ADDR_TAG;--> ../../../../../../microchip_solutions/framework/usb/src/usb_device.c:177:40:error: expected ';' after top level declaratorThe problem is a depressingly familiar one: Somewhere, a header file #ifndef is preventing the file being included, because elsewhere the header file has already been included. From experience this can take days to track down.Is there a nice windows based tool that can track header file inter-dependencies?Note: There is an ideal rule that states a header file should not itself include other headers. This rule is broken - but that is true in the Microchip code, and it would take forever to re-write it. I am already conciously not using the latest USB framework as I know the project did work as it was.

author: golden_labels
author_rank: Super Contributor
timestamp: November 19, 2020, 06:13:48 pm
content: If a properly used header is producing an error, this is a bug and should be reported to the right people. That should be fixed, not circumvented. A temporary solution may be applied and if you can use GCC,gcc -Hwill print inclusion tree. But this is just a makeshift fix.I don’t know where the “header should not include another headers” rule comes from, but this is bullshit. It’s quite opposite: for headers to be usable, they must include headers providing declarations/definitions they themselves require. They should be self-contained and under normal circumstances the order of inclusion should not be important.(1)____(1)Exceptions include preprocessor “procedures” and preprocessor metaprogramming. Sometimes tricks may be needed if different feature macros are required for different headers, but that alone is a sign of a larger problem that will bite later.

author: AntiProtonBoy
author_rank: Frequent Contributor
timestamp: November 20, 2020, 12:39:43 am
content: QuoteThat doesn't make sense to me. Properly implemented include guards should prevent each header file from getting included more than onceper compilation unit(in this caseusb_device.c). Therefore, if a header was included already, then its contents should be visible by the compilation unit.So your situation could be one of the following:* The required header file is never included in the first place.* Include guard for one header has a duplicate#ifndef foothat is also present in some other header file. Easy mistake to make when you Save As... a header to a different file.* The macros you are trying to use has been undefined somewhere else, ie.#undef BDT_BASE_ADDRQuote from: 741 on November 19, 2020, 11:43:55 amThis is not true. There is nothing wrong with including other headers inside headers, as long as each and every header file has an include guard properly implemented.

author: andersm
author_rank: Super Contributor
timestamp: November 20, 2020, 10:52:09 am
content: Quote from: golden_labels on November 19, 2020, 06:13:48 pmBecause usually little thought is put into the structure of header files, and you end up with the situation where the whole project will be rebuilt any time a header is modified.Anyway, for the OP I would be on the lookout for duplicated include guard labels, either from copying another header file and forgetting to change it, or just from being unlucky when picking it.

author: golden_labels
author_rank: Super Contributor
timestamp: November 20, 2020, 11:23:52 am
content: Quote from: andersm on November 20, 2020, 10:52:09 amI see it as a natural consequence of what C and C++ preprocessors are. Remember that the “header files” are abstractions of human brain. For the compiler and build tools they areeffectivelya part of the final source files that are built. Those tools do not know that some definition from a header is not really used in that particular source file. It may be remedied, but it’s usually too much work for anyone to bother. Still, even with those workarounds, the headers still should include everything that is needed by them.In more recent languages the compiler has an idea of other compiled units, so it can query them for information. That eliminates the need for various constructs needed by C and C++, which are the reason most of headers is used in the first place. Though even those are not always perfect: see the infamous problem with Java’s public static primitive type fields, which are baked in into dependent class files.

author: andersm
author_rank: Super Contributor
timestamp: November 20, 2020, 11:55:03 am
content: Quote from: golden_labels on November 20, 2020, 11:23:52 amMost issues can be avoided by simple refactoring, eg. moving type declarations into separate files, and not including function declaration headers into other headers. Another typical error is getting the declarations you really want via long include chains, instead of only including the file you actually need.

author: golden_labels
author_rank: Super Contributor
timestamp: November 20, 2020, 03:56:42 pm
content: I believe we’re talking about two separate issues. Based one your last post, I must assume you’re speaking about simple lack of granularity in headers. Which indeed may be a problem for larger projects. OTOH I was speaking about a situation in which granularity is sufficient, but unused declarations and definitions are pulled in. The definition is quantitative. However, neither of those is related to OP’s issue or the rule they’ve mentioned.