Skip to content

ENH: Store ITK_AUTOLOAD_PATH in ObjectFactoryBase globals - #6985

Draft
blowekamp wants to merge 2 commits into
InsightSoftwareConsortium:mainfrom
blowekamp:ObjectFactoryAutoloadPath
Draft

blowekamp wants to merge 2 commits into
InsightSoftwareConsortium:mainfrom
blowekamp:ObjectFactoryAutoloadPath

Conversation

@blowekamp

@blowekamp blowekamp commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Store the ITK_AUTOLOAD_PATH value in the ObjectFactoryBase globals and add ObjectFactoryBase::SetAutoloadPath() / GetAutoloadPath(), so the factory search path can be configured at runtime, before the factories are dynamically loaded.

Related: #6982 (decouple the autoload scan from ITK_WRAPPING); builds on #6975 (merged), which introduced ITK_USE_AUTOLOAD_PATH.

Change
  • The path is initialized from the ITK_AUTOLOAD_PATH environment variable when the ObjectFactoryBase globals are created, and is held there instead of being read from the environment inside LoadDynamicFactories().
  • New public static SetAutoloadPath(const std::string &) and GetAutoloadPath(). The setter takes effect if called before the first Initialize() / CreateInstance(), or followed by ReHash().
  • ReHash() now uses the stored path rather than re-reading the environment. Code that changes ITK_AUTOLOAD_PATH with putenv after startup and then calls ReHash() must call SetAutoloadPath() instead; itkObjectFactoryTest2 is updated accordingly.
  • New standalone test itkObjectFactoryAutoloadPathTest, run two ways: itkObjectFactoryAutoloadPathEnvTest (CTest sets ITK_AUTOLOAD_PATH, nothing configured in main()) and itkObjectFactoryAutoloadPathApiTest (variable unset, SetAutoloadPath() called in main()). Both check that FactoryTestLib is loaded on first use and not loaded after the path is cleared and ReHash() is called.
How this relates to #6982 and #6975

#6982 asks to replace the compile-time NOT ITK_WRAPPING rule with a control that lives where the hazard is: two ITK builds sharing one process, e.g. an ITK wheel imported inside 3D Slicer whose ITK_AUTOLOAD_PATH names plugins built against Slicer's ITK. This PR does not change when the scan happens. It supplies a runtime control that those options can build on:

  • Option 3 (move the control to the host): the host can call SetAutoloadPath("") (or its own plugin directory) before ITK is first used, instead of relying on the process environment. ObjectFactoryBase is already wrapped, so the statics should also be reachable from Python (not yet verified in a wrapped build). In wrapped builds ITK_USE_AUTOLOAD_PATH is off, so the setter only stores the value and no plugins are loaded. It does not require clearing or renaming the environment variable, which other tools in the process may read.
  • Option 2 (user-settable control): once the scan is no longer excluded at compile time for wrapped builds, a wrapped build can opt in by setting the path at runtime rather than by a build option.
  • Option 1 (refuse mismatched plugins): independent of this PR, but a setter lets an application restrict the search to directories it knows are compatible.

For #6975 (merged), the plugin tests it guards with ITK_USE_AUTOLOAD_PATH rely on ITK_AUTOLOAD_PATH being read by the scan. With a setter, tests no longer need to mutate the process environment to point at a plugin directory.

The new tests are registered inside the ITK_BUILD_SHARED_LIBS AND ITK_USE_AUTOLOAD_PATH block from #6975, so they are skipped in builds where ObjectFactoryBase does not scan the autoload path (e.g. Python-wrapped builds).

Backport: the ENH commit is self-contained and avoids CMake features newer than 3.16.3 (the api test unsets the variable in-process rather than using ENVIRONMENT_MODIFICATION), so it can be cherry-picked to release-5.4; the test guard needs adapting there since ITK_USE_AUTOLOAD_PATH is not on that branch. The ITK 6 migration note is a separate DOC commit that stays on main.

Local verification (Linux x86_64, gcc)

Rebased onto main including #6975. Shared build (BUILD_SHARED_LIBS=ON, ITKCommon only), ctest -R ObjectFactory:

  • itkObjectFactoryAutoloadPathEnvTest: passed
  • itkObjectFactoryAutoloadPathApiTest: passed
  • itkObjectFactoryTest2: passed
  • itkObjectFactoryTest3: passed
  • itkObjectFactoryOnlyNewTest: passed

Temporary logging confirmed the order in both modes: globals created, then (API mode) SetAutoloadPath(), then the first Initialize() / LoadDynamicFactories() with the configured path. Not run: itkObjectFactoryTest (target not built), static build with the final change, Python-wrapped build, other platforms.

AI assistance

Implemented with an AI coding assistant (Copilot) under the author's direction.

PR Checklist

  • No API changes were made (or the changes have been approved) — only adds two public static methods; the one behavior change (ReHash() no longer re-reads the environment) is documented in the header and the ITK 6 migration guide
  • No major design changes were made (or the changes have been approved)
  • Added test (or behavior not changed)
  • Updated API documentation (or API not changed)
  • Added license to new files (if any)
  • Added Python wrapping to new files (if any) as described in ITK Software Guide Section 9.5 — no new files; the new statics are on the already-wrapped ObjectFactoryBase
  • Added ITK examples for all new major features (if any) — not a major feature

@github-actions github-actions Bot added type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Enhancement Improvement of existing methods or implementation type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct area:Core Issues affecting the Core module labels Oct 22, 2026
@dzenanz

dzenanz commented Oct 22, 2026

Copy link
Copy Markdown
Member

#6975 was recently merged. This PR should be rebased and adjusted. I will wait for that before reviewing.

@hjmjohnson hjmjohnson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested end to end in 3D Slicer against this PR's head (09199c4) on macOS: Slicer calls SetAutoloadPath(<Slicer_ITKFACTORIES_DIR>) followed by ReHash() in its application init, the launcher stops exporting ITK_AUTOLOAD_PATH, and the MRMLIDImageIO plugin loads in-process. The Slicer side, gated on a compile probe so ITK 5.4.x keeps the environment-variable path, is at hjmjohnson/Slicer#1. The implementation needs no change for that use; the inline notes are documentation and migration items.

The rebase onto #6975 that @dzenanz asked for is in place (the branch contains 4a643d8 and the tests sit inside the ITK_USE_AUTOLOAD_PATH block), so this looks ready to come out of draft.

Two more items without a natural inline anchor
  • The PR body says Python exposure is unverified. ObjectFactoryBase is in ITKCommonBase.wrap, so the two statics should appear, but wrapped builds have ITK_USE_AUTOLOAD_PATH off, which makes the setter a stored no-op there. One sentence in the body would save a Python user from expecting it to load plugins.
  • Slicer needed ReHash() because ITK's factory list is already initialized by the time the application's init runs; SetAutoloadPath() alone only stores the string. The header already says so, and it held in practice.

Comment thread Modules/Core/Common/include/itkObjectFactoryBase.h
Comment thread Modules/Core/Common/src/itkObjectFactoryBase.cxx
Comment thread Modules/Core/Common/test/CMakeLists.txt Outdated
Comment thread Modules/Core/Common/include/itkObjectFactoryBase.h
@hjmjohnson

Copy link
Copy Markdown
Member

@blowekamp I created an initial set of slicer builds against this PR and asked for an extensive code review with various compile options to find corner-case failure modes.

I think this PR is a great step forward, and I'd approve it as is, but the overnight builds and explorations identified a few items that should at least be noted in an ISSUE for future consideration.

See the potential slicer changes at hjmjohnson/Slicer#1.

Comment thread Modules/Core/Common/test/CMakeLists.txt Outdated
Initialize the autoload path from the environment once, when the
ObjectFactoryBase globals are created, and expose
ObjectFactoryBase::SetAutoloadPath()/GetAutoloadPath() so a host can
set it at runtime before the factories are first loaded. ReHash() uses
the stored path instead of re-reading the environment.

Add standalone tests for setting the path by environment and by API,
and use the setter in itkObjectFactoryTest2. The tests use only
CMake and ITK facilities available on release-5.4 so the change can
be backported; the CMake guard needs adapting there.

Relates to InsightSoftwareConsortium#6982 and InsightSoftwareConsortium#6975.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@blowekamp
blowekamp force-pushed the ObjectFactoryAutoloadPath branch from 811244c to 7ec3021 Compare October 23, 2026 14:33
ReHash() no longer re-reads ITK_AUTOLOAD_PATH; callers changing the
path after startup must use ObjectFactoryBase::SetAutoloadPath().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@blowekamp
blowekamp force-pushed the ObjectFactoryAutoloadPath branch from 7ec3021 to 32419f3 Compare October 23, 2026 14:48

@dzenanz dzenanz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not taken a good look at the tests. The rest looks good on a glance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:Core Issues affecting the Core module area:Documentation Issues affecting the Documentation module type:Enhancement Improvement of existing methods or implementation type:Infrastructure Infrastructure/ecosystem related changes, such as CMake or buildbots type:Testing Ensure that the purpose of a class is met/the results on a wide set of test cases are correct

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants