-
Notifications
You must be signed in to change notification settings - Fork 485
Description
I have a CMake project which depends on Simbody using the FetchContent module, which adds Simbody as a subproject.
I had some difficulties with that approach that led me to look at the Simbody CMake build system.
While I was familiarizing myself with the Simbody CMake, I noticed a number of things that can be natively done by (recent) CMake's, some outdated/deprecated CMake commands, and a number of configuration options whose purpose/usecase I don't understand and/or don't appear to be used anymore. So in the spirit of not surprising y'all with a giant CMake rewrite PR, here is a list of comments and questions about the CMake build recipe:
-
Playing nice as a subproject:
-
Bump Allow building simbody as cmake subproject #721
- The
CMAKE_SOURCE_DIR=>CMAKE_CURRENT_SOURCE_DIRreplacement only affects how simbody is built when it is a subproject (i.e. no functional change for regular builds). When Simbody is a subproject,CMAKE_SOURCE_DIRis the directory of the top-level project, and paths in simbody that assumeCMAKE_SOURCE_DIRis the simbody source directory will be incorrect.
- The
-
CACHE'ed variables are global
- The CMakeCache is global to a CMake project, so subprojects setting CACHE variables can overwrite settings in the top-level project. Overwriting can happen by either force setting, or setting CACHE variables before parent projects if they don't FORCE set. For example, the
INSTALL_DOCS,BUILD_EXAMPLES, andBUILD_TESTING1 variables (all fairly common in software built with CMake) conflict with variables of the same name in opensim-core
- Solution:
- Best practice is that most CACHE'ed variables in a project should be prefixed with the project name, e.g.
SIMBODY_INSTALL_DOCSetc. - Check if the project is top level (requires CMake >=3.21) when setting un-prefixed cache variables
- Reconsider default values for variables when Simbody is a dependency/subproject (aka not the top-level project), e.g. if Simbody is a dependency, Simbody's tests probably shouldn't be built
- Best practice is that most CACHE'ed variables in a project should be prefixed with the project name, e.g.
- The CMakeCache is global to a CMake project, so subprojects setting CACHE variables can overwrite settings in the top-level project. Overwriting can happen by either force setting, or setting CACHE variables before parent projects if they don't FORCE set. For example, the
-
-
Purpose and maintenance cost of simultaneous shared and static builds, simultaneous versioned and unversioned builds
- There are multiple untested (by CI) configuration options, and the target definitions for the static/shared, versioned/unversioned targets are mostly the same, with only minor differences. What are the intended use cases for these options and who are the users?
- Versioning:
- What is the functional/intended difference between the version suffix and builtin library versions (e.g.
SOVERSION, etc)? - Why/when/who would need to generate (from the same build config) versioned and unversioned libraries?
- What is the functional/intended difference between the version suffix and builtin library versions (e.g.
- How often are these simultaneous builds needed, and are separate builds (i.e. create separate build directories for each option) inconvenient enough to be worth the added complexity/configuration duplication?
- There is no build de-duplication afaik, so no advantage to multiple targets with the same sources within the same build directory/configuration (but c.f. ccache)
- Versioning:
- Solutions: remove or rewrite to reduce duplication:
- Remove simultaneous static/shared builds and add examples of the functional equivalent separate builds to
CONTRIBUTING.md,CMakePresets.josnand/orSampleCMakeLists.txt - Keep simultaneous builds but rewrite to simplify (I have ideas [as of yet, untested])
- Versioning suffixes can be added more idiomatically using
<$CONFIG>_POSTFIXand potentially other options - Add better docstrings to configurations, with examples of why they might be used
- Remove simultaneous static/shared builds and add examples of the functional equivalent separate builds to
- There are multiple untested (by CI) configuration options, and the target definitions for the static/shared, versioned/unversioned targets are mostly the same, with only minor differences. What are the intended use cases for these options and who are the users?
-
Accessibility to newcomers
- There are 7 CACHE variables2 shown in the GUI that "can't be changed here/from the GUI". None of these are relevant to a new/potential contributor (imo), and should be hidden (marked "INTERNAL" in
CMakeLists.txt) to reduce visual noise and mental load for new contributors.- If the intent is to inform users what values these variables are being set to,
messages can be printed when cmake is configured
- If the intent is to inform users what values these variables are being set to,
- Another 7 CACHE variables3 are only changed (from defaults) in special, advanced situations, and should be marked as such in CMake (i.e.
mark_as_advanced), again to reduce visual noise and mental load
- There are 7 CACHE variables2 shown in the GUI that "can't be changed here/from the GUI". None of these are relevant to a new/potential contributor (imo), and should be hidden (marked "INTERNAL" in
-
CMake style/idioms. I'm not sure if some of these things are intentional stylistic choices vs. leftover from earlier versions of CMake
- Text inside
elseandendifparentheses is ignored/unused by CMake.- Adds visual noise with no beneficial impacts on clarity, imo
- Manual
SIMBODY_(MAJOR|MINOR|PATCH)_VERSIONdeclaration versus defining inprojectdeclaration and usingCMAKE_PROJECT_VERSION_(MAJOR|MINOR|PATCH)everywhere else (same for subprojects)- Defining version in the
projectdeclaration automatically definesCMAKE_PROJECT_VERSION_(MAJOR|MINOR|PATCH)variables
- Defining version in the
- Provide common alternative build configs with CMakePresets.json (requires CMake >= 3.19)
- Define variants for supported, but less common builds (e.g. static, versioned, namespaced, etc)
- Define a standard/multi-platform CI build config
- Text inside
If it helps, I can break these questions/concerns out into separate issues. Looking forward to discussing with y'all and hopefully submitting some PR's!
Footnotes
-
BUILD_TESTINGis somewhat special because it is checked/set by the Dart/CTest module. ↩ -
BUILD_PLATFORM,LAPACK_BEING_USED,SIMBODY_SONAME_VERSION,SIMBODY_VERSION,SimTKCOMMON_LIBRARY_NAME,SimTKMATH_LIBRARY_NAME,SimTKSIMBODY_LIBRARY_NAME↩ -
BUILD_STATIC_LIBRARIES,BUILD_UNVERSIONED_LIBRARIES,BUILD_USING_NAMESPACE,BUILD_USING_OTHER_LAPACK,BUILD_VERSIONED_LIBRARIES,SIMBODY_COVERAGE,WINDOWS_USE_EXTERNAL_LIBS↩