Skip to content

MNT: Use policy_max in cmake_minimum_required#990

Merged
gonuke merged 4 commits into
svalinn:developfrom
matthewfeickert:mnt/use-policy_max
Feb 16, 2026
Merged

MNT: Use policy_max in cmake_minimum_required#990
gonuke merged 4 commits into
svalinn:developfrom
matthewfeickert:mnt/use-policy_max

Conversation

@matthewfeickert

@matthewfeickert matthewfeickert commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

Description

  • Set policy_max which defines the maximum CMake policy. cmake_minimum_required sets two minimums: the real (lower) minimum and the (upper) minimum based on has been tested with. The defaults (CMake policies) will be set to the highest value possible between the two values.
  • Move cmake_minimum_required position in files given warning:

cmake_minimum_required() should be called prior to this top-level project()
call. Please see the cmake-commands(7) manual for usage documentation of
both commands.

  • Older versions of CMake v3.x policies are being deprecated and dropped and v2 policies are now longer supported.
  • FATAL_ERROR option is accepted but ignored by CMake 2.6 and higher, and so is removed as it can have no effect.
  • CMake policy is not changed on CMake patch releases, so specifying a CMake version beyond the minor level to the patch level is not informative or meaningful.

Fixes to Mac Build/Test workflow

  • Homebrew's Eigen in 2026 is Eigen v5.x, which is incompatible with MOAB v5.5.1 FindEigen3.cmake. Homebrew has bad version control, and so instead of trying to force Homebrew to install a compatible version, build Eigen v3.4.0 (a header-only library) from source to ensure that Eigen3Config.cmake is generated for DAGMC's CMake invocation to use find_package(Eigen3 REQUIRED NO_MODULE).
  • Additionally, in CMake v4 TestEndianess.c.in was renamed to TestEndianness.c.in to fix a typo. MOAB v5.5.1 used a custom config/TestBigEndian.cmake that hardcodes the use of TestEndianess.c.in.
$ git grep "TestEndianess.c.in"
config/TestBigEndian.cmake:39:  CONFIGURE_FILE("${CMAKE_ROOT}/Modules/TestEndianess.c.in"

As config/ is first in CMAKE_MODULE_PATH, MOAB's broken version is used instead of CMake's working built-in module. To avoid this, set HAVE_WORDS_BIGENDIAN=TRUE to skip the test, instead of deleting the broken module. This works as HAVE_WORDS_BIGENDIAN=TRUE skips the test test_big_endian, defaulting to little-endian, which for effectively all runner platforms is correct.

$ git grep -m 1 '(HAVE_' -- config/TestBigEndian.cmake
config/TestBigEndian.cmake:8:  IF(HAVE_${VARIABLE} MATCHES ^HAVE_${VARIABLE}$)
  • Surprisingly, adopting modern CMake invocations also fixes a bug in the build related to MOAB_DIR, which I did not expect.

Motivation and Context

Changes

Maintenance and build longevity.

Behavior

What is the current behavior? What is the new behavior?

The CMake policy is frozen at old or fully deprecated versions which are no longer accessible by modern CMake. The CMake policy_max range allows for setting the lower minimum and then updating the lower and the upper minimums as needed given changes, allowing for the most wide range of viable builds.

Changelog file

All pull requests are required to update the CHANGELOG file with the PR. Your update can take different forms including:

  • creating a new entry describing your change, including a reference to this pull request number
  • adding a reference to your pull request number to an exist entry if that entry can include your changes

✔️

@matthewfeickert

Copy link
Copy Markdown
Contributor Author

👋 @shimwell @ahnaf-tahmid-chowdhury @gonuke @pshriwise as you all reviewed PR #969, which was the last time

cmake_minimum_required(VERSION 3.18)

was touched, can I get one of you to approve a CI run on this before I request review (in the event that I might want to clear or clarify a few things first)?

@matthewfeickert

matthewfeickert commented Feb 13, 2026

Copy link
Copy Markdown
Contributor Author

Thanks to whoever enabled the CI. 👍

The macOS build tests are failing but given

- name: Build MOAB
shell: bash -l {0}
run: |
cd ${HOME}
mkdir -pv moab/bld
cd moab
git clone https://bitbucket.org/fathomteam/moab -b 5.5.1 --depth 1 --shallow-submodules
cd bld
cmake ../moab -DENABLE_HDF5=ON \
-DENABLE_PYMOAB=OFF \
-DHDF5_ROOT=$HDF5_PATH \
-DBUILD_SHARED_LIBS=ON \
-DENABLE_BLASLAPACK=OFF \
-DENABLE_FORTRAN=OFF \
-DCMAKE_INSTALL_PREFIX=${HOME}/moab
make
make install
rm -rf ${HOME}/moab/moab ${HOME}/moab/bld

and

-- The C compiler identification is AppleClang 17.0.0.17000013
-- The CXX compiler identification is AppleClang 17.0.0.17000013
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for inttypes.h
-- Looking for inttypes.h - found
-- Looking for stdint.h
-- Looking for stdint.h - found
-- Looking for stddef.h
-- Looking for stddef.h - found
-- Looking for stdlib.h
-- Looking for stdlib.h - found
-- Looking for sys/types.h
-- Looking for sys/types.h - found
-- Looking for memory.h
-- Looking for memory.h - found
-- Check if the system is big endian
-- Searching 16 bit integer
-- Check size of unsigned short
CMake Error: File /opt/homebrew/share/cmake/Modules/TestEndianess.c.in does not exist.
-- Check size of unsigned short - done
CMake Error at config/TestBigEndian.cmake:39 (CONFIGURE_FILE):
-- Using unsigned short
  CONFIGURE_FILE Problem configuring file
Call Stack (most recent call first):
  CMakeLists.txt:168 (TEST_BIG_ENDIAN)


CMake Error at config/TestBigEndian.cmake:43 (FILE):
  FILE failed to open for reading (No such file or directory):

    /Users/runner/work/DAGMC/moab/bld/CMakeFiles/CMakeTmp/TestEndianess.c
-- Configuring incomplete, errors occurred!
Call Stack (most recent call first):
  CMakeLists.txt:168 (TEST_BIG_ENDIAN)


CMake Error at /Users/runner/work/DAGMC/moab/bld/CMakeFiles/CMakeTmp/CMakeLists.txt:21 (target_sources):
  Cannot find source file:

    /Users/runner/work/DAGMC/moab/bld/CMakeFiles/CMakeTmp/TestEndianess.c


CMake Error at /Users/runner/work/DAGMC/moab/bld/CMakeFiles/CMakeTmp/CMakeLists.txt:20 (add_executable):
  No SOURCES given to target: cmTC_2e25d


CMake Error at config/TestBigEndian.cmake:46 (TRY_COMPILE):
  Failed to generate test project build system.
Call Stack (most recent call first):
  CMakeLists.txt:168 (TEST_BIG_ENDIAN)


make: *** No targets specified and no makefile found.  Stop.
make: *** No rule to make target `install'.  Stop.

this seems to be unrelated to this PR specifically and more issues with what's currently installed by the Homebrew cmake on the runner(?).

* Set policy_max which defines the maximum CMake policy. cmake_minimum_required
  sets two minimums: the real (lower) minimum and the (upper) minimum based on
  has been tested with. The defaults (CMake policies) will be set to the highest
  value possible between the two values.
   - c.f. https://cmake.org/cmake/help/latest/command/cmake_minimum_required.html
* Move cmake_minimum_required position in files given warning:
     cmake_minimum_required() should be called prior to this top-level project()
     call.  Please see the cmake-commands(7) manual for usage documentation of
     both commands.
* Older versions of CMake v3.x policies are being deprecated and as of CMake v4,
  compatibility with CMake < 3.5 has been removed, so all CMake v2 policies are
  no longer useable.
* FATAL_ERROR option is accepted but ignored by CMake 2.6 and higher, and so is
  removed as it can have no effect.
* CMake policy is not changed on CMake patch releases, so specifying a CMake version
  beyond the minor level to the patch level is not informative or meaningful.
* Homebrew's Eigen in 2026 is Eigen v5.x, which is incompatible with MOAB
  v5.5.1 FindEigen3.cmake. Homebrew has bad version control, and so
  instead of trying to force Homebrew to install a compatible version,
  build Eigen v3.4.0 (a header-only library) from source to ensure that
  Eigen3Config.cmake is generated for DAGMC's CMake invocation to use
  find_package(Eigen3 REQUIRED NO_MODULE).
* Additionally, in CMavke v4 TestEndianess.c.in was renamed to
  TestEndianness.c.in to fix a typo. MOAB v5.5.1 used a custom
  config/TestBigEndian.cmake that hardcodes the use of TestEndianess.c.in.

    $ git grep "TestEndianess.c.in"
    config/TestBigEndian.cmake:39:    CONFIGURE_FILE("${CMAKE_ROOT}/Modules/TestEndianess.c.in"

  As config/ is first in CMAKE_MODULE_PATH, MOAB's broken version is used
  instead of CMake's working built-in module. To avoid this, set
  HAVE_WORDS_BIGENDIAN=TRUE to skip the test, instead of deleting the broken
  module. This works as HAVE_WORDS_BIGENDIAN=TRUE skips the test
  test_big_endian, defaulting to little-endian, which for effectively all runner
  platforms is correct.

   $ git grep -m 1 '(HAVE_' -- config/TestBigEndian.cmake
   config/TestBigEndian.cmake:8:  IF(HAVE_${VARIABLE} MATCHES ^HAVE_${VARIABLE}$)
* Use modern CMake syntax of the general pattern

cmake -G <generator> -DCMAKE_INSTALL_PREFIX=<prefix> -S src -B build
cmake build -LH
cmake --build build --clean-first --parallel <number parallel>
cmake --install build

which allows for more portability, and allows for CMake to be more efficient
in its execution and use alternative generators like ninja.
@matthewfeickert matthewfeickert marked this pull request as ready for review February 14, 2026 09:01
@matthewfeickert

Copy link
Copy Markdown
Contributor Author

👋 @shimwell @ahnaf-tahmid-chowdhury @gonuke @pshriwise this is ready for review now (and needs a CI approval again). Let me know if you have any questions. 👍

@gonuke gonuke 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.

Thanks @matthewfeickert - I wasn't aware of this CMake policy. I am curious whether what the value of adding the max version is? I suppose if a newer version makes our CMake configuration break, this would detect/avoid that? On the other hand, it creates a maintenance burden to keep updating this periodically.

I made a note about the change in gtest - wonder what your thoughts are there?

# as ${gtest_SOURCE_DIR} and to the root binary directory as
# ${gtest_BINARY_DIR}.
# Language "C" is required for find_package(Threads).
cmake_minimum_required(VERSION 2.6...4.2)

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 think this is otherwise-unedited copy of the google-test-suite code. Is it problematic to leave this one as-is and make an issue to change our dependence on this, either by updating the version we have copied in or make it an external dependency?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Is it problematic to leave this one as-is and make an issue to change our dependence on this, either by updating the version we have copied in or make it an external dependency?

It actually won't build at all, given that CMake v4.0 dropped all policies older than 3.5 (longer summary in #990 (comment)). It there a particularly strong reason to vendor gtest compared to having it as an external? If not, having it as a dependency would probably be more long-term sustainable with CMake.

brew install eigen hdf5
brew install hdf5

# Homebrew's Eigen in 2026 is Eigen v5.x, which is incompatible with

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.

Huh... maybe we should be moving this forward in MOAB under a different issue...

@matthewfeickert matthewfeickert Feb 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@gonuke I'm happy to migrate any MOAB related things to https://bitbucket.org/fathomteam/moab/src/master/. I had assumed that as MOAB v5.6.0 existed on conda-forge but DAGMC was testing against MOAB v5.5.1 that there was some restriction on DAGMC's compatibility with the v5.6.x series of MOAB. If not (that's great) then MOAB related things can for sure be moved upstream and separated out from this PR.

git clone -b 5.5.1 --depth 1 --shallow-submodules https://bitbucket.org/fathomteam/moab moab_src

# In CMavke v4 TestEndianess.c.in was renamed to TestEndianness.c.in
# to fix a typo. MOAB v5.5.1 used a custom config/TestBigEndian.cmake

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.

Seems like another place for a MOAB issue/update?

@matthewfeickert

matthewfeickert commented Feb 16, 2026

Copy link
Copy Markdown
Contributor Author

I wasn't aware of this CMake policy. I am curious whether what the value of adding the max version is? I suppose if a newer version makes our CMake configuration break, this would detect/avoid that?

@gonuke The short version of this is somewhat the opposite of your statement. cmake_minimum_required(VERSION) means "use CMake policy of ==VERSION" and not "use CMake policy >=VERSION". Newer versions of CMake (the software release) don't break old CMake builds (unless you have custom CMake files that hardcode things), but they do remove outdated policies. Using policy_max is actually about keeping your CMake builds building for as long as possible, so that when new CMake releases drop outdated policies you have not pinned your project to a policy that is no longer in support.

Here's a much longer summary taken from my colleague Henry Schreiner on a GitLab project MR (I'm quoting exactly here, so the CMake versions in question will be different):

... many times packages were fine with, or even wanted the better defaults with newer versions, but they also wanted to support older CMake versions. This is where the upper bound comes in: You now set two “minimums”: the real (lower) minimum and the (upper) minimum based on what you’ve tested with. The defaults (policies) will be set to the highest value possible between the two values. So if you have cmake_minimum_required(VERSION 3.15...3.26) , then if you run with CMake 3.14, it’s an error, if you run with CMake 3.21, it uses 3.21's policies, and if you run with CMake 3.29, it uses 3.26's policies.

Eventually, they want to drop old policies. CMake 4.0 doesn’t support policies older than 3.5, and warns on policies older than 3.10. So cmake_minimum_required(VERSION 2.8...3.15) is perfectly fine; it sets the policies to 3.15 on CMake 4.0. But cmake_minimum_required(VERSION 3.4) is not, as that sets the policies to 3.4 on newer CMake’s, and those policies have been removed in 4.0. You should set the upper minimum to the highest value you can to ensure your code builds for as long as possible.

On the other hand, it creates a maintenance burden to keep updating this periodically.

In practice this is low effort in that builds are ideally tested with latest (or at least modern) releases of tooling, and so when a new major or modern version of CMake comes out you bump the policy_max up to that version and test, and that will eventually make its way out into a release. The releases should build indefinitely into the future as long as you're able to get a distribution of CMake that has supported policies between <min> and <policy_max>. When some future version of CMake drops these (like how CMake v4.0 dropped policies older than 3.5) you are then bound to use an older version of CMake to build those older releases. As CMake drops policies rather slowly this means that having a range can give you a much extended build support window of many years compared to having only <min>.

@gonuke gonuke 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.

Thanks for the interest, investment and education @matthewfeickert

Lets go forward with this as is and generate some new issues for things that arose here

@gonuke gonuke merged commit b124672 into svalinn:develop Feb 16, 2026
20 checks passed
@matthewfeickert matthewfeickert deleted the mnt/use-policy_max branch February 16, 2026 23:03
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