Skip to content

build: export headers with one rule instead of ten - #4452

Merged
BsAtHome merged 1 commit into
LinuxCNC:masterfrom
grandixximo:header-export-one-rule
Aug 23, 2026
Merged

build: export headers with one rule instead of ten#4452
BsAtHome merged 1 commit into
LinuxCNC:masterfrom
grandixximo:header-export-one-rule

Conversation

@grandixximo

@grandixximo grandixximo commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

@BsAtHome One variable, one rule, as you suggested.

Every exported header was declared twice, once in SRCHEADERS and once in a per-directory *INCS list or a one-off rule that carried the cp. SRCHEADERS is already the variable, so one rule copies from it and the ten recipes across eight Submakefiles go.

headersclean now empties ../include instead of removing $(HEADERS), so a header dropped from SRCHEADERS stops being exported. It removes *.h and *.hh rather than the directory, since include/.gitignore is tracked.

hal/drivers/mesa-hostmot2/Submakefile held nothing but its copy rule, so I deleted it rather than leave an empty file behind, and its SUBDIRS entry with it since SUBDIRS exists only to name the Submakefiles. The build still produces hostmot2.so and still exports hostmot2-serial.h.

The single rule also means two headers sharing a basename would collide on one target and make would say so, where before one cp quietly won. There are none today.

Ordering is untouched. build-software: headers userspace modules does not serialise under -j, but that is no different after this.

From a clean tree: configure and build with --enable-werror, 37 headers in include/, a planted stale.h gone after make headersclean with .gitignore still there, and make headers putting all 37 back.

@grandixximo

grandixximo commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

@BsAtHome One thing I am unsure about. hal/drivers/mesa-hostmot2/Submakefile had nothing left in it once its copy rule went, so I deleted it rather than leave it empty. That builds fine, since the Submakefiles come in through -include $(wildcard $(SUBMAKEFILES)) and a missing one is simply skipped.

But #3837 82f05bc left seven empty in the same situation, the six under libnml/ and emc/tp/, so I would rather ask than assume. Is keeping the path present deliberate, a placeholder for something coming back, or were they just left behind?

If deleting is right, those seven can go the same way in a follow-up.

@BsAtHome

Copy link
Copy Markdown
Contributor

The empty Submakefiles are just leftovers, I guess. They can be retired because they contribute nothing. If one is ever needed again, then we can just create it.

While looking at that, I discovered that the libnml.so.0 link depends on liblinuxcnchal.so (in libnml/Submakefile). But I cannot find any link to HAL in the sources. I think that is also something we need to check too.

@grandixximo

Copy link
Copy Markdown
Contributor Author

The link is load bearing, just not for HAL. Four libnml files call rtapi_strlcpy or rtapi_strxcpy, both static inline in rtapi_string.h and both bottoming out in rtapi_snprintf, which is a real function living in liblinuxcnchal.so.0. nm -D on libnml.so.0 shows no hal_ symbol and one U rtapi_snprintf. a1be83c added the prerequisite in 2018 for exactly that, and the reason still holds.

So the oddity is packaging: rtapi ships inside the HAL library. All 22 rtapi_* symbols come from one object, rtapi/uspace_ulapi.o, 85 lines, against 126 hal_* from the rest, so the seam is clean.

Two ways, your pick.

Split rtapi into its own library. 246 of 343 built artefacts reference rtapi_*, but 221 of those are rtlib/*.so, which are dlopened into rtapi_app and link nothing, so the real churn is about 25 link lines across bin/, lib/ and the Python modules. They cannot inherit it through the HAL library, an indirect DT_NEEDED will not resolve at link time. The part that is not mechanical is a new soname: debian/linuxcnc.lintian-overrides.in enumerates the current ones and it changes what linuxcnc-uspace ships.

Or take libnml out of the problem. Four files, eight call sites, all userspace only, where plain snprintf does the job. The prerequisite goes and nothing else moves. That does not fix the layering, it just stops libnml being an example of it.

Happy either way, and the empty Submakefiles I will retire regardless.

Every exported header was declared twice, once in SRCHEADERS and once in
a per-directory list or a one-off rule carrying the cp.  SRCHEADERS is the
list, so one rule now copies from it and the ten recipes go.

hal/drivers/mesa-hostmot2/Submakefile held nothing but its copy rule, so
it goes rather than being left empty, and its SUBDIRS entry with it since
SUBDIRS exists only to name the Submakefiles.

headersclean empties ../include rather than removing $(HEADERS).  A header
dropped from SRCHEADERS used to leave its copy behind, and a stale copy is
what an angled include resolves to.
@BsAtHome

Copy link
Copy Markdown
Contributor

Or take libnml out of the problem. Four files, eight call sites, all userspace only, where plain snprintf does the job. The prerequisite goes and nothing else moves. That does not fix the layering, it just stops libnml being an example of it.

That is the way to go. I already have a PR in the pipeline (#4457). But it is not as simple as a "plain snprintf". The compiler does a fantastic job at bugging you that the target space is too small for the %s pattern. It requires some, hm, adaptations. ;-)

Removing liblinuxcnchal.so from libnml also exposes an indirect dependency in linuxcnc.so (the Tcl lib) and one pulled in via liblinuxcnc.a. A real messy business...

@BsAtHome
BsAtHome merged commit 18e32ff into LinuxCNC:master Aug 23, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants