classicladder: give the headers include guards and their own dependencies - #4430
Conversation
|
Adding to the noise: is there a reason not to use #pragma once? While not in any C/C++ standard it is probably even rarer for a compiler to not support that than non-two's complement int representation. |
|
Include guards are de facto standard. No reason to to use pragmas. FWIW, pragmas should only be used when there is no other option. |
|
@rmu75 There is a concrete reason here beyond convention, so worth a measurement. The build ships every exported header twice: Same two includes, one resolving to each copy:
gcc saves pragma-once files by content hash, so it only breaks once the two copies drift. clang keys on the file entry, so identical bytes are not enough. Not hypothetical: scanning the Under For balance, guards do have the failure the pragma avoids: None of those headers are touched here, so this PR is unaffected either way. |
|
There are now conflicts... Should be trivial to fix. |
|
keep in mind that classicladder is an external project, that has been copied into linuxcnc, and added hal stuff. |
…cies 30 of the 34 headers in hal/classicladder have no include guard, and 12 do not compile on their own. They name StrRung, StrSection, StrSymbol, StrStep, cairo_t or the gtk types without including whatever declares them, and build only because the file that included them had already got there. Guards go in first, since including classicladder.h from twelve places without them redefines everything. Then the twelve name what they use: classicladder.h for the ladder types, sequential.h for StrStep and StrTransition in drawing_sequential.h, <gtk/gtk.h> for the five _gtk headers, <cairo.h> and <stddef.h> for drawing.h, and <stdio.h> for the FILE * in files.h. The guards are named CLASSICLADDER_<FILE>_H. The four headers here that had one already used a leading underscore, which is reserved to the implementation, so they are renamed to match rather than left as a second convention in the same directory. Plain uppercase with no underscore is what most of the tree uses; the prefix is because names like FILES_H, CALC_H and GLOBAL_H are too general to leave unqualified. All 34 compile standalone afterwards, one translation unit per header against the userspace include path, where 22 did before. Full build clean, no errors and no warnings. The stdio.h line in files.h is also in LinuxCNC#4425, which reaches it from the other direction; the two overlap by that one line and nothing else.
4ff0b0f to
eb0ef6f
Compare
|
I wonder if this "same include file lives in 2 locations" doesn't also throw off functionality like "show all references" in tools like ccls / clangd. |
|
@rene-dev Fair, and the history backs it. The copy here is upstream v0.8.10 (December 2010) per Your point still lands on one part of this PR. Of the four guards I renamed, @rmu75 Probably, though I have not measured it, so I will not claim a specific behaviour. What is certain is that the If the whole thing reads as churn against a vendored tree, I am happy to close it. |
|
If they resolve includes properly and actually understand the logic, then they should not. However, many tools make assumptions or do not understand it and will fail (miserably). If you must know, then you should test. There is a reason why the includes are setup as they are, also the copying of several of them into the include/ directory. It is to align in-tree and out-of-tree builds. Many tools make assumptions that may or may not be valid. Users of the tools should be very aware of that. |
The classicladder in the LCNC tree is ancient and very misaligned with the upstream version. It would be a complete project to re-align the two. But it would only be worth it if there is a (significant) user base. We have been patching and plugging holes in the LCNC copy for quite some time and this is no exception. Sure, you can also upstream the changes, but with the current misalignment I don't think it is worth the effort. But keeping our copy working with our tree is more important. Therefore, update this in our tree? Yes. |
|
@grandixximo don't bother, I know that it doesn't work 100% correctly. I usually generate compile_commands with "build ear" bear [1], and that records accurate compiler invocations for each translation unit. Depending on what code you look at "go to..." sometimes jumps in the /include dir and sometimes in the src. CCLS and clangd are actually using clang so behaviour will be like clang (in other words, symbols declared via including /include/file.hh ... are treated as different from symbols declared by including file.hh in the source dir) At least now I know what's going on... |
That is because the compile is showing you the include file it used. That is always the one from the include/ directory when it is a "foreign" (for out-of-tree build exportable) include for the code being compiled and it used |
30 of the 34 headers in
hal/classicladderhave no include guard, and 12 do not compile on their own. They nameStrRung,StrStep,cairo_tor the gtk types without including whatever declares them, and build only because the file that included them had already got there.Guards go in first, since including
classicladder.hfrom twelve places without them redefines everything. Then the twelve name what they use.The guards are
CLASSICLADDER_<FILE>_H. The four that had one already used a leading underscore, which is reserved to the implementation, so they are renamed rather than left as a second convention in one directory.Testing. All 34 compile standalone afterwards, one translation unit per header, where 22 did before. Built clean with
--with-realtime=uspace, no errors and no warnings.Is it worth having? @BsAtHome this is your point from #4425, that a header needing something should be the one to say so, applied to a subsystem you did not ask about. classicladder is old code nobody is working on, so if 34 files of churn reads as noise, say so and I will close it.
Independent of #4425, overlapping by one line, the
<stdio.h>infiles.h.