You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ITK_USE_64BITS_IDS selects the width of SizeValueType, IdentifierType, IndexValueType and OffsetValueType. It is
inert on Linux and macOS, load-bearing on Windows and WebAssembly,
untested in one of its two states, and it caused a live wrapping
defect (#6772). This issue asks whether it should still exist.
This is a deliberate parking issue. No action is proposed for now —
the decision needs a proper ABI/downstream impact assessment that
nobody currently has time to do, and the deciding facts are not in the
repository. Everything needed to pick this up cold is recorded below,
so a future reader needs no other context.
Raised by @N-Dekker on #6772: "Is it still useful nowadays? Why would
some users still want to switch off ITK_USE_64BITS_IDS on Windows,
nowadays?"
The one-paragraph version
OFF is not a Windows state — it is the default everywhere except
64-bit Windows. The option only changes any type where long and long long differ in width, which is Windows LLP64 and 32-bit
targets (today: WebAssembly); on LP64 Linux/macOS it is a no-op in
both positions. Forcing it ON globally would therefore change nothing
on Linux, macOS, or default Windows, and would land its entire cost on
WebAssembly — while still not producing a uniform type. Genuine
uniformity requires a wider change that carries a non-obvious ABI trap
on macOS (below).
Mechanics — exactly what the option does, with file:line
Declaration — CMakeLists.txt:668-678. Declared for all platforms;
only the default is platform-dependent:
set(ITK_USE_64BITS_IDS_DEFAULT "OFF")
# Note WIN32 is true when targeting any windows systemif(CMAKE_SIZEOF_VOID_PEQUAL"8"ANDWIN32)
set(ITK_USE_64BITS_IDS_DEFAULT "ON")
endif()
option(
ITK_USE_64BITS_IDS"When ON, ITK will use 64-bit integer types instead of long types for sizes and indexes. This is needed for managing images larger than 4Gb in some platforms.""${ITK_USE_64BITS_IDS_DEFAULT}"
)
mark_as_advanced(ITK_USE_64BITS_IDS)
#if defined(ITK_USE_64BITS_IDS) && ((ULLONG_MAX != ULONG_MAX) || (LLONG_MAX != LONG_MAX))
using SizeValueType = uint64_t; // IdentifierType = SizeValueTypeusing IndexValueType = int64_t;
using OffsetValueType = int64_t;
#elseusing SizeValueType = unsignedlong;
using IndexValueType = long;
using OffsetValueType = long;
#endif
The second clause is the crux: the 64-bit branch is taken only
where long and long long differ in width.
Data model
Platforms
long
Option's effect
LP64
Linux, macOS (64-bit)
64
Inert — both settings give 64-bit SizeValueType
LLP64
Windows (64-bit)
32
Live — OFF = 32-bit ids, ON = 64-bit. Default ON
ILP32
WebAssembly (wasm32, wasm32-wasi), 32-bit targets
32
Live — ON = 64-bit ids on a 32-bit address space. Default OFF
That inertness on LP64 is why the #6772 mismatch survived from #3502
(July 2022) undetected: every platform where Python wrapping is
routinely built resolves ITKM_IT to UL either way.
WebAssembly is a live, actively-developed ITK target, not a
hypothetical — ITK's own CMakeLists.txt:316 branches on if(WASI OR EMSCRIPTEN), and ITK-Wasm is
current.
History — why the option exists
Commit
Change
feb637c0b09
ENH: Restore ITK_USE_64BITS_IDS option
fca71585536
COMP: Enable the correct integer types for 64bits Ids
07dfd5b9bd4
COMP: Prevent ITK_USE_64BITS_IDS with Wrapping on Windows (ITK 4.4)
8bb8c743267
ENH: Use ITK_USE_64BITS_IDS for windows 64 by default (ITK 4.10)
Release notes also record COMP: Fix HDF5IO with ITK_USE_64BITS_IDS on Windows (4.3). The arc: the option existed; wrapping could not cope
with it on Windows so it was prevented there in 4.4; it was then made
the Windows default in 4.10 once >4 GB image support outweighed the
wrapping friction.
@N-Dekker (opener) — proposed SizeValueType = std::size_t and
dropping the option, because the profusion of size/offset types makes
narrowing bugs hard to find. His PR BUG: Fix possible loss of data on type conversion #1087 fixed a batch; "this is
just a tip of the iceberg." Follow-up: std::ptrdiff_t for IndexValueType/OffsetValueType.
@dzenanz — "This is very much overdue. I support this change."
@blowekamp — named the two use cases the option actually serves:
(1) Win64 compatibility with code historically assuming unsigned long; (2) 32-bit architectures streaming large images.
Noted the option's name is inaccurate and that he was unsure either
case was still relevant. Suggested adding ITK_USE_SIZE_T_IDS to
experiment rather than making a breaking change during 5.0
maintenance.
@matt.mccormick — objected that size_t is 32-bit on 32-bit ARM
and ITK wanted to keep processing large images there via streaming.
@dzenanz — the cited ARM porting guide was from 2011; 64-bit ARM
has 64-bit size_t. @matt.mccormick partly conceded: "most of
the newer and high performance systems are 64-bit ARM … so size_t
could be fine in practice."
Rough agreement in principle, then it stopped. ITK_USE_SIZE_T_IDS was
never added. Seven years on, the 32-bit-ARM premise that anchored the
main objection is weaker — but WebAssembly has since arrived as a new
ILP32 target, so the category of 32-bit concern is not empty.
What the option costs today
1. A wrapping-visible type divergence. Wrapping/WrapBasicTypes.cmake:222 is the sole place the mangled
identifier type is chosen:
Note it keys on the CMake option and WIN32, never on the actual C++
type. #6772 exists solely because itk/support/types.py re-derived
this independently and disagreed on Windows with the option OFF.
2. A filter silently missing from the Windows Python package. Modules/Segmentation/Watersheds/wrapping/itkTobogganImageFilter.wrap:
# The itk::IdentifierType, which is unsigned long on Unix but can# be unsigned long long on Windows when ITK_USE_64BITS_IDS is# enabled, is not wrapped in the supporting classes on Windows.if(NOTWIN32ORNOT ITK_USE_64BITS_IDS)
itk_wrap_class("itk::TobogganImageFilter"POINTER)
Because the Windows default is ON, itk.TobogganImageFilter is absent from the standard Windows Python package — a
platform-dependent API gap with no diagnostic.
3. A configuration nothing tests. No CI job builds Python wrapping
on Windows with ITK_USE_64BITS_IDS=OFF. #6772's defect was findable
only by reading CMake, never by running anything.
Options and trade-offs
A. Remove the option; IdentifierType follows the platform.
Removes the divergence, the Toboggan carve-out and the untested
configuration. But the Windows choice then has to be made for users:
hard-wiring 64-bit ids is an ABI break for anyone building OFF;
following long silently caps Windows at 32-bit ids — a functional
regression, and precisely what 4.10 fixed. Neither is free.
B. Remove only the ability to set OFF on 64-bit Windows.
Answers Niels' question directly and kills the divergence, the Toboggan
carve-out and the #6772 defect class in one step, while leaving the
option meaningful on ILP32/WASM. Narrowest blast radius. Cost: an ABI
break for any Windows consumer deliberately building OFF — existence
currently unknown. Cheapest real improvement, contingent on the
open question below.
C. SizeValueType = std::size_t, Index/Offset = std::ptrdiff_t
(the 2019 proposal). The only route to genuine uniformity and removes a
whole class of narrowing bugs. But see the ABI trap below — it is a
wider change than "same width, no problem" suggests, and would want
forest-build measurement of downstream cost first.
D. Keep it, document it, test it. Add a Windows CI job with ITK_USE_64BITS_IDS=OFF + Python wrapping so the configuration stops
being unverified; un-mark_as_advanced it. Lowest risk; keeps all
three costs above.
Explicitly considered and rejected: force ON for all platforms.
It does not do what it appears to. Forcing the first clause of the
guard true leaves the second intact:
Platform
Forced-ON result
Change vs today
Linux / macOS (LP64)
unsigned long (2nd clause false)
none
Windows 64-bit (LLP64)
uint64_t
none (already default)
WASM / ILP32
uint64_t
32-bit ids become 64-bit
So it is a no-op on the platforms where most ITK is built, a no-op on
the Windows default, and lands its entire cost on WebAssembly: 64-bit
arithmetic emulated in a 32-bit VM, Index<3>/Offset<3> doubling
12 → 24 bytes, larger binaries — where binary size is a first-order
concern. And it still would not deliver type uniformity, which is the
only thing that retires this bug class.
⚠ The ABI trap in any "just make it uint64_t" approach
Getting one type everywhere requires dropping the ULLONG_MAX != ULONG_MAX clause too, making SizeValueType = uint64_t
unconditional. That is not width-neutral on LP64 — it is
type-identity-changing, and inconsistently between Linux and macOS:
$ c++ -std=c++17 probe.cxx && ./probe # macOS arm64, Apple clang
sizeof(long)=8 sizeof(long long)=8 sizeof(size_t)=8
ULLONG_MAX != ULONG_MAX -> 0
uint64_t is 'unsigned long' ? 0
uint64_t is 'unsigned long long' ? 1
On macOS uint64_t is unsigned long long; on Linux/glibc it is unsigned long. Both 64 bits, but distinct types for overload
resolution, name mangling and template instantiation.
Concretely: SizeValueType on macOS would silently move from unsigned long to unsigned long long while Wrapping/WrapBasicTypes.cmake:222 still computes ITKM_IT as UL,
because it keys on WIN32 AND ITK_USE_64BITS_IDS and not on the C++
type. That reproduces the exact #6772 defect class on macOS — where CI
would catch it — and on Linux, where it would not. Any such change
must fix the wrapping mangling in the same commit.
Reproduce / re-verify the claims above
# Option declaration and platform-dependent default
sed -n '668,678p' CMakeLists.txt
# The guard that makes it inert on LP64
sed -n '60,95p' Modules/Core/Common/include/itkIntTypes.h
# Every consumer in the tree (should be 5 files)
grep -rn "ITK_USE_64BITS_IDS" --exclude-dir=.git .# The wrapping divergence
sed -n '215,230p' Wrapping/WrapBasicTypes.cmake
# The Toboggan carve-out
sed -n '1,12p' Modules/Segmentation/Watersheds/wrapping/itkTobogganImageFilter.wrap
# WASM is a supported target
grep -n -A3 "WASI OR EMSCRIPTEN" CMakeLists.txt
Open questions that must be answered before deciding
Does anyone build ITK_USE_64BITS_IDS=OFF on 64-bit Windows, and
why?@blowekamp's 2019 answer was Win64 compatibility with code
assuming unsigned long. If that constituency is empty, option B is
cheap and A becomes tractable. A Discourse post is the fastest way
to find out. This is the single highest-value question here.
Does ITK-Wasm want 64-bit ids, and is the size/perf cost
acceptable on wasm32? Determines whether the option must survive
for ILP32 at all.
What is the downstream blast radius of option C? Measurable with
the forest build across SimpleITK, Slicer, ANTs, BRAINSTools,
elastix.
Suggested sequencing when this is picked up
Ask (1) and (2) on Discourse; wait for a real answer, not silence.
If (1) is empty → implement B, including deleting the Toboggan
carve-out, and add the Windows-wrapping CI job from D.
Only then evaluate C with forest-build evidence, and only with WrapBasicTypes.cmake fixed in the same commit.
Related: #6772 (the wrapping mismatch that surfaced this), #6769, #3502 (introduced itk.IT, July 2022, commit 6a9aca9906b6660b1d04d7d6971453395c2dfc1d), PR #1087, Discourse #2053.
ITK_USE_64BITS_IDSselects the width ofSizeValueType,IdentifierType,IndexValueTypeandOffsetValueType. It isinert on Linux and macOS, load-bearing on Windows and WebAssembly,
untested in one of its two states, and it caused a live wrapping
defect (#6772). This issue asks whether it should still exist.
This is a deliberate parking issue. No action is proposed for now —
the decision needs a proper ABI/downstream impact assessment that
nobody currently has time to do, and the deciding facts are not in the
repository. Everything needed to pick this up cold is recorded below,
so a future reader needs no other context.
Raised by @N-Dekker on #6772: "Is it still useful nowadays? Why would
some users still want to switch off
ITK_USE_64BITS_IDSon Windows,nowadays?"
The one-paragraph version
OFFis not a Windows state — it is the default everywhere except64-bit Windows. The option only changes any type where
longandlong longdiffer in width, which is Windows LLP64 and 32-bittargets (today: WebAssembly); on LP64 Linux/macOS it is a no-op in
both positions. Forcing it
ONglobally would therefore change nothingon Linux, macOS, or default Windows, and would land its entire cost on
WebAssembly — while still not producing a uniform type. Genuine
uniformity requires a wider change that carries a non-obvious ABI trap
on macOS (below).
Mechanics — exactly what the option does, with file:line
Declaration —
CMakeLists.txt:668-678. Declared for all platforms;only the default is platform-dependent:
Propagation —
Modules/Core/Common/src/itkConfigure.h.in:79(
#cmakedefine ITK_USE_64BITS_IDS).Consumption —
Modules/Core/Common/include/itkIntTypes.h:65:The second clause is the crux: the 64-bit branch is taken only
where
longandlong longdiffer in width.longSizeValueTypewasm32,wasm32-wasi), 32-bit targetsThat inertness on LP64 is why the #6772 mismatch survived from #3502
(July 2022) undetected: every platform where Python wrapping is
routinely built resolves
ITKM_ITtoULeither way.WebAssembly is a live, actively-developed ITK target, not a
hypothetical — ITK's own
CMakeLists.txt:316branches onif(WASI OR EMSCRIPTEN), andITK-Wasm is
current.
History — why the option exists
feb637c0b09fca7158553607dfd5b9bd48bb8c743267Release notes also record
COMP: Fix HDF5IO with ITK_USE_64BITS_IDS on Windows(4.3). The arc: the option existed; wrapping could not copewith it on Windows so it was prevented there in 4.4; it was then made
the Windows default in 4.10 once >4 GB image support outweighed the
wrapping friction.
Prior discussion: Discourse
#2053, "Could ITK drop ITK_USE_64BITS_IDS and just do SizeValueType = std::size_t?"
(2019, 8 posts). Positions:
SizeValueType = std::size_tanddropping the option, because the profusion of size/offset types makes
narrowing bugs hard to find. His PR BUG: Fix possible loss of data on type conversion #1087 fixed a batch; "this is
just a tip of the iceberg." Follow-up:
std::ptrdiff_tforIndexValueType/OffsetValueType.(1) Win64 compatibility with code historically assuming
unsigned long; (2) 32-bit architectures streaming large images.Noted the option's name is inaccurate and that he was unsure either
case was still relevant. Suggested adding
ITK_USE_SIZE_T_IDStoexperiment rather than making a breaking change during 5.0
maintenance.
size_tis 32-bit on 32-bit ARMand ITK wanted to keep processing large images there via streaming.
has 64-bit
size_t. @matt.mccormick partly conceded: "most ofthe newer and high performance systems are 64-bit ARM … so size_t
could be fine in practice."
Rough agreement in principle, then it stopped.
ITK_USE_SIZE_T_IDSwasnever added. Seven years on, the 32-bit-ARM premise that anchored the
main objection is weaker — but WebAssembly has since arrived as a new
ILP32 target, so the category of 32-bit concern is not empty.
What the option costs today
1. A wrapping-visible type divergence.
Wrapping/WrapBasicTypes.cmake:222is the sole place the mangledidentifier type is chosen:
Note it keys on the CMake option and
WIN32, never on the actual C++type. #6772 exists solely because
itk/support/types.pyre-derivedthis independently and disagreed on Windows with the option OFF.
2. A filter silently missing from the Windows Python package.
Modules/Segmentation/Watersheds/wrapping/itkTobogganImageFilter.wrap:Because the Windows default is ON,
itk.TobogganImageFilterisabsent from the standard Windows Python package — a
platform-dependent API gap with no diagnostic.
3. A configuration nothing tests. No CI job builds Python wrapping
on Windows with
ITK_USE_64BITS_IDS=OFF. #6772's defect was findableonly by reading CMake, never by running anything.
Options and trade-offs
A. Remove the option;
IdentifierTypefollows the platform.Removes the divergence, the Toboggan carve-out and the untested
configuration. But the Windows choice then has to be made for users:
hard-wiring 64-bit ids is an ABI break for anyone building OFF;
following
longsilently caps Windows at 32-bit ids — a functionalregression, and precisely what 4.10 fixed. Neither is free.
B. Remove only the ability to set
OFFon 64-bit Windows.Answers Niels' question directly and kills the divergence, the Toboggan
carve-out and the #6772 defect class in one step, while leaving the
option meaningful on ILP32/WASM. Narrowest blast radius. Cost: an ABI
break for any Windows consumer deliberately building OFF — existence
currently unknown. Cheapest real improvement, contingent on the
open question below.
C.
SizeValueType = std::size_t,Index/Offset = std::ptrdiff_t(the 2019 proposal). The only route to genuine uniformity and removes a
whole class of narrowing bugs. But see the ABI trap below — it is a
wider change than "same width, no problem" suggests, and would want
forest-build measurement of downstream cost first.
D. Keep it, document it, test it. Add a Windows CI job with
ITK_USE_64BITS_IDS=OFF+ Python wrapping so the configuration stopsbeing unverified; un-
mark_as_advancedit. Lowest risk; keeps allthree costs above.
Explicitly considered and rejected: force
ONfor all platforms.It does not do what it appears to. Forcing the first clause of the
guard true leaves the second intact:
ONresultunsigned long(2nd clause false)uint64_tuint64_tSo it is a no-op on the platforms where most ITK is built, a no-op on
the Windows default, and lands its entire cost on WebAssembly: 64-bit
arithmetic emulated in a 32-bit VM,
Index<3>/Offset<3>doubling12 → 24 bytes, larger binaries — where binary size is a first-order
concern. And it still would not deliver type uniformity, which is the
only thing that retires this bug class.
⚠ The ABI trap in any "just make it uint64_t" approach
Getting one type everywhere requires dropping the
ULLONG_MAX != ULONG_MAXclause too, makingSizeValueType = uint64_tunconditional. That is not width-neutral on LP64 — it is
type-identity-changing, and inconsistently between Linux and macOS:
On macOS
uint64_tisunsigned long long; on Linux/glibc it isunsigned long. Both 64 bits, but distinct types for overloadresolution, name mangling and template instantiation.
Concretely:
SizeValueTypeon macOS would silently move fromunsigned longtounsigned long longwhileWrapping/WrapBasicTypes.cmake:222still computesITKM_ITasUL,because it keys on
WIN32 AND ITK_USE_64BITS_IDSand not on the C++type. That reproduces the exact #6772 defect class on macOS — where CI
would catch it — and on Linux, where it would not. Any such change
must fix the wrapping mangling in the same commit.
Reproduce / re-verify the claims above
Type-identity probe used in the ABI-trap section:
Open questions that must be answered before deciding
ITK_USE_64BITS_IDS=OFFon 64-bit Windows, andwhy? @blowekamp's 2019 answer was Win64 compatibility with code
assuming
unsigned long. If that constituency is empty, option B ischeap and A becomes tractable. A Discourse post is the fastest way
to find out. This is the single highest-value question here.
acceptable on
wasm32? Determines whether the option must survivefor ILP32 at all.
the forest build across SimpleITK, Slicer, ANTs, BRAINSTools,
elastix.
Suggested sequencing when this is picked up
carve-out, and add the Windows-wrapping CI job from D.
WrapBasicTypes.cmakefixed in the same commit.Related: #6772 (the wrapping mismatch that surfaced this), #6769,
#3502 (introduced
itk.IT, July 2022, commit6a9aca9906b6660b1d04d7d6971453395c2dfc1d), PR #1087, Discourse#2053.