| CMake Source Code Guide | |
| *********************** | |
| The following is a guide to the CMake source code for developers. | |
| See documentation on `CMake Development`_ for more information. | |
| .. _`CMake Development`: README.rst | |
| C++ Code Style | |
| ============== | |
| We use `clang-format`_ version **18** to define our style for C++ code in | |
| the CMake source tree. See the `.clang-format`_ configuration file for our | |
| style settings. Use the `Utilities/Scripts/clang-format.bash`_ script to | |
| format source code. It automatically runs ``clang-format`` on the set of | |
| source files for which we enforce style. The script also has options to | |
| format only a subset of files, such as those that are locally modified. | |
| .. _`clang-format`: https://clang.llvm.org/docs/ClangFormat.html | |
| .. _`.clang-format`: ../../.clang-format | |
| .. _`Utilities/Scripts/clang-format.bash`: ../../Utilities/Scripts/clang-format.bash | |
| In addition, we have a few coding conventions that we prefer for new code to | |
| follow (which are not enforced by other tooling): | |
| * Name local variables using ``camelCase``. | |
| * Name class members and free functions using ``PascalCase``. | |
| * Reference class members using ``this->Member``. | |
| * Use east ``const`` style, e.g., ``int const`` instead of ``const int``. | |
| * Declare variables using a locally-specified type: | |
| .. code-block:: c++ | |
| T x = f(); | |
| Use ``auto`` only if the real type explicitly appears in the initializer: | |
| .. code-block:: c++ | |
| auto y = cm::make_unique<T>(); | |
| auto z = []() -> T {...}(); | |
| Exceptions: | |
| * Iterators: ``auto i = myMap.find(myKey);`` | |
| * Lambdas: ``auto f = []() {...};`` | |
| * Use ``CM_UNREACHABLE`` for logically unreachable code paths instead of | |
| ad-hoc ``assert(false ...)`` statements or comment-only placeholders. | |
| C++ Subset Permitted | |
| ==================== | |
| CMake requires compiling as C++11 in order to support building on older | |
| toolchains. However, to facilitate development, some standard library | |
| features from more recent C++ standards are supported through a compatibility | |
| layer. These features are defined under the namespace ``cm`` and headers | |
| are accessible under the ``cm/`` directory. The headers under ``cm/`` can | |
| be used in place of the standard ones when extended features are needed. | |
| For example ``<cm/memory>`` can be used in place of ``<memory>``. | |
| The class ``cm::filesystem::path``, from the ``<cm/filesystem>`` header, is | |
| fully compatible with the class ``std::filesystem::path`` regarding the API but | |
| is a specific implementation (derived from the ``std::filesystem::path`` class) | |
| to ensure a behavior independent of the current locale. | |
| Available features are: | |
| * From ``C++14``: | |
| * ``<cm/array>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/deque>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/forward_list>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/iomanip>``: | |
| ``cm::quoted`` | |
| * ``<cm/iterator>``: | |
| ``cm::make_reverse_iterator``, ``cm::cbegin``, ``cm::cend``, | |
| ``cm::rbegin``, ``cm::rend``, ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/list>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/map>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/memory>``: | |
| ``cm::make_unique`` | |
| * ``<cm/set>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/string>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/string_view>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/shared_mutex>``: | |
| ``cm::shared_lock`` | |
| * ``<cm/type_traits>``: | |
| ``cm::conditional_t``, ``cm::decay_t``, ``cm::enable_if_t``, | |
| ``cm::remove_cv_t``, ``cm::remove_reference_t`` | |
| * ``<cm/unordered_map>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/unordered_set>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * ``<cm/vector>``: | |
| ``cm::cbegin``, ``cm::cend``, ``cm::rbegin``, ``cm::rend``, | |
| ``cm::crbegin``, ``cm::crend`` | |
| * From ``C++17``: | |
| * ``<cm/algorithm>``: | |
| ``cm::clamp`` | |
| * ``<cm/array>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/deque>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``cm/filesystem>``: | |
| ``cm::filesystem::path`` | |
| * ``<cm/forward_list>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/iterator>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/list>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/map>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/optional>``: | |
| ``cm::nullopt_t``, ``cm::nullopt``, ``cm::optional``, | |
| ``cm::make_optional``, ``cm::bad_optional_access`` | |
| * ``<cm/set>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/shared_mutex>``: | |
| ``cm::shared_mutex`` | |
| * ``<cm/string>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/string_view>``: | |
| ``cm::string_view``, ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/type_traits>``: | |
| ``cm::bool_constant``, ``cm::invoke_result_t``, ``cm::invoke_result``, | |
| ``cm::is_same_v``, ``cm::void_t`` | |
| * ``<cm/unordered_map>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/unordered_set>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * ``<cm/utility>``: | |
| ``cm::in_place_t``, ``cm::in_place`` | |
| * ``<cm/vector>``: | |
| ``cm::size``, ``cm::empty``, ``cm::data`` | |
| * From ``C++20``: | |
| * ``<cm/array>``: | |
| ``cm::ssize`` | |
| * ``<cm/deque>``: | |
| ``cm::erase``, ``cm::erase_if``, ``cm::ssize`` | |
| * ``<cm/forward_list>``: | |
| ``cm::ssize`` | |
| * ``<cm/iterator>``: | |
| ``cm::ssize`` | |
| * ``<cm/list>``: | |
| ``cm::erase``, ``cm::erase_if``, ``cm::ssize`` | |
| * ``<cm/map>`` : | |
| ``cm::erase_if``, ``cm::ssize`` | |
| * ``<cm/ranges>``: | |
| ``cm::ranges::views::keys``, ``cm::ranges::views::values`` | |
| * ``<cm/set>`` : | |
| ``cm::erase_if``, ``cm::ssize`` | |
| * ``<cm/string_view>``: | |
| ``cm::ssize`` | |
| * ``<cm/string>``: | |
| ``cm::erase``, ``cm::erase_if``, ``cm::ssize`` | |
| * ``<cm/unordered_map>``: | |
| ``cm::erase_if``, ``cm::ssize`` | |
| * ``<cm/unordered_set>``: | |
| ``cm::erase_if``, ``cm::ssize`` | |
| * ``<cm/vector>``: | |
| ``cm::erase``, ``cm::erase_if``, ``cm::ssize`` | |
| * From ``C++23``: | |
| * ``<cm/type_traits>``: | |
| ``cm::is_scoped_enum`` | |
| * ``<cm/utility>``: | |
| ``cm::unreachable`` | |
| Additionally, some useful non-standard extensions to the C++ standard library | |
| are available in headers under the directory ``cmext/`` in namespace ``cm``. | |
| These are: | |
| * ``<cmext/algorithm>``: | |
| * ``cm::append``: | |
| Append elements to a sequential container. | |
| * ``cm::contains``: | |
| Checks if element or key is contained in container. | |
| * ``cm::keys`` | |
| Extract keys from associative container or sequence container with tuple as | |
| element | |
| * ``cm::values`` | |
| Extract values from associative container or sequence container with tuple as | |
| element | |
| * ``<cmext/enum_set>`` | |
| * ``cm::enum_set``: | |
| Container to manage set of elements from an ``enum class`` definition. | |
| * ``<cmext/iterator>``: | |
| * ``cm::is_iterator``: | |
| Checks if a type is an iterator type. | |
| * ``cm::is_input_iterator``: | |
| Checks if a type is an input iterator type. | |
| * ``cm::is_range``: | |
| Checks if a type is a range type: functions ``std::begin()`` and | |
| ``std::end()`` apply. | |
| * ``cm::is_input_range``: | |
| Checks if a type is an input range type: functions ``std::begin()`` and | |
| ``std::end()`` apply and return an input iterator. | |
| * ``<cmext/memory>``: | |
| * ``cm::static_reference_cast``: | |
| Apply a ``static_cast`` to a smart pointer. | |
| * ``cm::dynamic_reference_cast``: | |
| Apply a ``dynamic_cast`` to a smart pointer. | |
| * ``<cmext/type_traits>``: | |
| * ``cm::is_pair``: | |
| Checks if a type is a std::pair<> type. | |
| * ``cm::is_tuple``: | |
| Checks if a type is a std::tuple<> type. | |
| * ``cm::is_container``: | |
| Checks if a type is a container type. | |
| * ``cm::is_associative_container``: | |
| Checks if a type is an associative container type. | |
| * ``cm::is_unordered_associative_container``: | |
| Checks if a type is an unordered associative container type. | |
| * ``cm::is_sequence_container``: | |
| Checks if a type is a sequence container type. | |
| * ``cm::is_unique_ptr``: | |
| Checks if a type is a ``std::unique_ptr`` type. | |
| * ``cm::remove_member_pointer`` | |
| Produces the underlying type of a member-pointer type, ie, given ``T C::*``, | |
| returns ``T``. | |
| * ``cm::member_pointer_class`` | |
| Produces the class associated with a member-pointer type, ie, given | |
| ``T C::*``, returns ``C``. | |
| CMake assumes the compiler supports ``#pragma once``. Use this for all | |
| hand-written header files. | |
| Dynamic Memory Management | |
| ========================= | |
| To ensure efficient memory management, i.e. no memory leaks, it is required | |
| to use smart pointers. Any dynamic memory allocation must be handled by a | |
| smart pointer such as ``std::unique_ptr`` or ``std::shared_ptr``. | |
| It is allowed to pass raw pointers between objects to enable objects sharing. | |
| A raw pointer **must** not be deleted. Only the object(s) owning the smart | |
| pointer are allowed to delete dynamically allocated memory. | |
| CMake Module/Script Style | |
| ========================= | |
| ``execute_process`` should capture ``RESULT_VARIABLE`` to avoid | |
| unexpected termination of CMake in case the user or project has set | |
| ``CMAKE_EXECUTE_PROCESS_COMMAND_ERROR_IS_FATAL`` to a value other than | |
| ``NONE``. Output should be captured for both stdout and stderr by using | |
| ``OUTPUT_VARIABLE``/``OUTPUT_QUIET`` and ``ERROR_VARIABLE``/``ERROR_QUIET``. | |
| Third Parties | |
| ============= | |
| To build CMake, some third parties are needed. Under ``Utilities`` | |
| directory, are versions of these third parties which can be used as an | |
| alternate to the ones provided by the system. | |
| To enable the selection of the third parties between the system and CMake ones, | |
| in CMake sources, third parties headers must be prefixed by ``cm3p/`` | |
| (for example: ``<cm3p/json/reader.h>``). These wrappers are located under | |
| ``Utilities/cm3p`` directory. | |
| Source Tree Layout | |
| ================== | |
| The CMake source tree is organized as follows. | |
| * ``Auxiliary/``: | |
| Shell and editor integration files. | |
| * ``Help/``: | |
| Documentation. See the `CMake Documentation Guide`_. | |
| * ``Help/dev/``: | |
| Developer documentation. | |
| * ``Help/release/dev/``: | |
| Release note snippets for development since last release. | |
| * ``Licenses/``: | |
| License files for third-party libraries in binary distributions. | |
| * ``Modules/``: | |
| CMake language modules installed with CMake. | |
| * ``Packaging/``: | |
| Files used for packaging CMake itself for distribution. | |
| * ``Source/``: | |
| Source code of CMake itself. | |
| * ``Templates/``: | |
| Files distributed with CMake as implementation details for generators, | |
| packagers, etc. | |
| * ``Tests/``: | |
| The test suite. See `Tests/README.rst`_. | |
| To run the tests, see the `CMake Testing Guide`_. | |
| * ``Utilities/``: | |
| Scripts, third-party source code. | |
| * ``Utilities/std/cm``: | |
| Support files for various C++ standards. | |
| * ``Utilities/std/cmext``: | |
| Extensions to the C++ STL. | |
| * ``Utilities/cm3p``: | |
| Public headers for third parties needed to build CMake. | |
| * ``Utilities/Sphinx/``: | |
| Sphinx configuration to build CMake user documentation. | |
| * ``Utilities/Release/``: | |
| Scripts used to package CMake itself for distribution on ``cmake.org``. | |
| See `Utilities/Release/README.rst`_. | |
| .. _`CMake Documentation Guide`: documentation.rst | |
| .. _`CMake Testing Guide`: testing.rst | |
| .. _`Tests/README.rst`: ../../Tests/README.rst | |
| .. _`Utilities/Release/README.rst`: ../../Utilities/Release/README.rst |