Skip to content

Make header-only builds work from any number of translation units - #104

Open
susilehtola wants to merge 1 commit into
wavefunction91:masterfrom
susilehtola:fix/inline-generator-impl
Open

Make header-only builds work from any number of translation units#104
susilehtola wants to merge 1 commit into
wavefunction91:masterfrom
susilehtola:fix/inline-generator-impl

Conversation

@susilehtola

Copy link
Copy Markdown
Collaborator

The runtime generator's definitions in generators/impl/ had external
linkage, so including impl.hpp from two translation units produced
duplicate symbols. The README documented the constraint honestly --
include it "exactly once per project" -- but that is not something a
downstream project can enforce across its own dependencies.

Marking the definitions unconditionally inline does not work either: an
inline function that is not odr-used in a translation unit is never
emitted, so the precompiled libintegratorxx would export nothing and the
default build would fail to link. The two modes genuinely want different
linkage, and the whole point of the precompiled default is to keep the
large angular dispatch out of consumer translation units.

Give them different linkage explicitly:

  • INTEGRATORXX_GENERATOR_LINKAGE (impl/linkage.hpp) expands to inline
    when INTEGRATORXX_HEADER_ONLY is defined and to nothing otherwise.
  • The CMake header-only branch now defines INTEGRATORXX_HEADER_ONLY on
    the interface target; previously the option only changed the target
    type, so nothing in the sources could tell the modes apart.
  • In header-only mode the public generator headers include their own
    implementations at the end of the file, where the declarations are
    already visible. The impl headers include the public ones back, which
    #pragma once reduces to a no-op.
  • test/lib_impl.cxx existed only to instantiate the generator once for
    the header-only test build, and is no longer needed.

impl.hpp had no include guard at all; add one.

Verified both ways: the default build still exports the generator symbols
from libintegratorxx.a and passes 9/9 tests, the header-only build passes
9/9 tests, and two translation units that both include impl.hpp now link.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01FDTFYJMQ76iujDFNHzZyXF

The runtime generator's definitions in generators/impl/ had external
linkage, so including impl.hpp from two translation units produced
duplicate symbols. The README documented the constraint honestly --
include it "exactly once per project" -- but that is not something a
downstream project can enforce across its own dependencies.

Marking the definitions unconditionally inline does not work either: an
inline function that is not odr-used in a translation unit is never
emitted, so the precompiled libintegratorxx would export nothing and the
default build would fail to link. The two modes genuinely want different
linkage, and the whole point of the precompiled default is to keep the
large angular dispatch out of consumer translation units.

Give them different linkage explicitly:

* INTEGRATORXX_GENERATOR_LINKAGE (impl/linkage.hpp) expands to `inline`
  when INTEGRATORXX_HEADER_ONLY is defined and to nothing otherwise.
* The CMake header-only branch now defines INTEGRATORXX_HEADER_ONLY on
  the interface target; previously the option only changed the target
  type, so nothing in the sources could tell the modes apart.
* In header-only mode the public generator headers include their own
  implementations at the end of the file, where the declarations are
  already visible. The impl headers include the public ones back, which
  #pragma once reduces to a no-op.
* test/lib_impl.cxx existed only to instantiate the generator once for
  the header-only test build, and is no longer needed.

impl.hpp had no include guard at all; add one.

Verified both ways: the default build still exports the generator symbols
from libintegratorxx.a and passes 9/9 tests, the header-only build passes
9/9 tests, and two translation units that both include impl.hpp now link.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FDTFYJMQ76iujDFNHzZyXF
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.

1 participant