My recent GCC 16 + LTO build on Fedora Rawhide exposed a long-existing deeper dependency issue in the plane-wave basis headers.
Currently, the base-class headers include their derived implementations after the include guard:
// pw_basis.h
#endif // PWBASIS_H
#include "pw_basis_sup.h"
#include "pw_basis_big.h" // temporary it will be removed
and similarly:
// pw_basis_k.h
#endif
#include "./pw_basis_k_big.h" // temporary it will be removed
This effectively reverses the normal dependency direction: including a base class also exposes derived classes and their dependencies.
One visible consequence is MODULE_CHARGE_extra. The test only provides a small mock implementation of PW_Basis, but including the relevant headers also introduces PW_Basis_Sup, PW_Basis_Big, PW_Basis_K, and PW_Basis_K_Big. With GCC 16 + LTO this results in unresolved RTTI/destructor references such as:
undefined reference to `ModulePW::PW_Basis_Sup::~PW_Basis_Sup()'
undefined reference to `ModulePW::PW_Basis_K::~PW_Basis_K()'
undefined reference to `typeinfo for ModulePW::PW_Basis_Sup'
undefined reference to `typeinfo for ModulePW::PW_Basis_K'
The linker failure itself can be worked around by adding more sources/libraries to the unit test, but that would leave the underlying architectural issue unchanged.
Problems
- Base-class headers implicitly expose derived classes.
- Translation units acquire dependencies that are not visible from their actual interfaces.
- Small unit tests and mocks become coupled to much larger parts of the PW implementation.
- CMake targets can appear to have sufficient dependencies while relying on accidental transitive includes.
- Changes to the PW class hierarchy can unexpectedly break unrelated users or tests.
- The current structure makes dependency analysis and future modularization unnecessarily difficult.
There are also headers such as stru_fac.h that include pw_basis_k.h while only using ModulePW::PW_Basis_K through pointers, where a forward declaration should be sufficient.
Suggested direction
The PW headers could gradually be made to follow a conventional one-way dependency structure:
PW_Basis
^
|
PW_Basis_Sup
^
|
PW_Basis_Big
and likewise for the k-point hierarchy.
In particular:
pw_basis.h should not include pw_basis_sup.h or pw_basis_big.h.
pw_basis_k.h should not include pw_basis_k_big.h.
- Users that actually need a derived class should include its header explicitly.
- Headers that only use PW classes through pointers/references should prefer forward declarations where possible.
- Unit-test targets should declare their real implementation dependencies explicitly rather than relying on transitive header exposure or accumulating additional mocks.
This does not necessarily need to be changed in one large patch. Removing the reverse includes incrementally and fixing the resulting explicit dependencies should make the PW module easier to maintain and make CMake target dependencies more reliable.
My recent GCC 16 + LTO build on Fedora Rawhide exposed a long-existing deeper dependency issue in the plane-wave basis headers.
Currently, the base-class headers include their derived implementations after the include guard:
and similarly:
This effectively reverses the normal dependency direction: including a base class also exposes derived classes and their dependencies.
One visible consequence is
MODULE_CHARGE_extra. The test only provides a small mock implementation ofPW_Basis, but including the relevant headers also introducesPW_Basis_Sup,PW_Basis_Big,PW_Basis_K, andPW_Basis_K_Big. With GCC 16 + LTO this results in unresolved RTTI/destructor references such as:The linker failure itself can be worked around by adding more sources/libraries to the unit test, but that would leave the underlying architectural issue unchanged.
Problems
There are also headers such as
stru_fac.hthat includepw_basis_k.hwhile only usingModulePW::PW_Basis_Kthrough pointers, where a forward declaration should be sufficient.Suggested direction
The PW headers could gradually be made to follow a conventional one-way dependency structure:
and likewise for the k-point hierarchy.
In particular:
pw_basis.hshould not includepw_basis_sup.horpw_basis_big.h.pw_basis_k.hshould not includepw_basis_k_big.h.This does not necessarily need to be changed in one large patch. Removing the reverse includes incrementally and fixing the resulting explicit dependencies should make the PW module easier to maintain and make CMake target dependencies more reliable.