{"id":13419937,"url":"https://github.com/iauns/cpm","last_synced_at":"2026-03-14T13:12:36.701Z","repository":{"id":10615306,"uuid":"12834577","full_name":"iauns/cpm","owner":"iauns","description":"C++ Package Manager","archived":false,"fork":false,"pushed_at":"2021-08-28T15:17:32.000Z","size":380,"stargazers_count":740,"open_issues_count":14,"forks_count":80,"subscribers_count":46,"default_branch":"master","last_synced_at":"2024-07-31T22:52:47.108Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://cpm.rocks","language":"CMake","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iauns.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-09-14T19:16:42.000Z","updated_at":"2024-07-26T03:21:25.000Z","dependencies_parsed_at":"2022-09-09T04:01:33.320Z","dependency_job_id":null,"html_url":"https://github.com/iauns/cpm","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iauns%2Fcpm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iauns%2Fcpm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iauns%2Fcpm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iauns%2Fcpm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iauns","download_url":"https://codeload.github.com/iauns/cpm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221548145,"owners_count":16840980,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T22:01:23.175Z","updated_at":"2026-03-14T13:12:31.633Z","avatar_url":"https://github.com/iauns.png","language":"CMake","readme":"CPM\n===\n\n[![Build Status](https://travis-ci.org/iauns/cpm.png)](https://travis-ci.org/iauns/cpm)\n\n**Note** CPM is not being actively maintained. I plan on keeping the website\nactive but don't plan on making further modifications to the codebase. If\nanyone is interested in moving the project forward please contact me (iauns)\nby sending an e-mail or opening an issue.\n\nA C++ Package Manager based on CMake and Git.\n\nCPM is designed to promote small, well-tested, composable C++ modules. CPM\nallows you to link against multiple different versions of the same static\nlibrary without symbol conflicts. You can include other C++ modules that may\ndepend on older or newer versions of the same modules you are using.\nAdditionally, CPM will automatically download and build C++ modules for you. To\nexplore CPM's ecosystem head over to the CPM website: http://cpm.rocks .\n\nYou can manage C or C++ libraries that do not utilize CPM. A number of\n'external' modules are already listed on the website. These modules abstract\naway the details of downloading, building, and linking against various\nprojects. Just be aware that you cannot statically link against multiple\ndifferent versions of these 'external' modules because they are not built as\nCPM modules and do not manage symbols like real CPM modules do.\n\nFor an example of a module with various interdependencies, check out\n[cpm-es-render](http://cpm.rocks/mod/gh/iauns/cpm-es-render). Here's an\nexample dependency graph that the cpm website automatically generated for this\nmodule:\n\n[![cpm-es-render dependency graph](images/depgraph-small.gif)](http://cpm.rocks/mod/gh/iauns/cpm-es-render)\n\n**Table of Contents**\n\n- [Brief Example](#brief-example)\n- [Using CPM](#using-cpm)\n  - [Quick Setup](#quick-setup)\n  - [Things to Note](#things-to-note)\n- [Building CPM Modules](#building-cpm-modules)\n  - [CMakeLists.txt Entry](#cmakeliststxt-entry)\n  - [Library target name](#library-target-name)\n  - [Wrapping Namespace](#wrapping-namespace)\n  - [Directory Structure](#directory-structure)\n  - [Exporting Build Info](#exporting-build-info)\n  - [Registering Your Module](#registering-your-module)\n  - [Building Externals](#building-externals)\n- [CPM Function Reference](#cpm-function-reference)\n  - [General Purpose](#general-purpose)\n  - [Modules Only](#modules-only)\n- [Miscellaneous Issues and Questions](#miscellaneous-issues-and-questions)\n\nBrief Example\n=============\n\nBelow is a sample of a CMakeLists.txt file that uses 3 modules. These modules\nare: platform specific OpenGL headers, an axis aligned bounding box\nimplementation, and G-truc's GLSL vector math library. See the next section\nfor a full explanation of how to use CPM. The following CMakeLists.txt is\nself-contained and will build as-is:\n\n```cmake\n  cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR)\n  project(foo)\n\n  #------------------------------------------------------------------------------\n  # Required CPM Setup - no need to modify - See: https://github.com/iauns/cpm\n  #------------------------------------------------------------------------------\n  set(CPM_DIR \"${CMAKE_CURRENT_BINARY_DIR}/cpm_packages\" CACHE TYPE STRING)\n  find_package(Git)\n  if(NOT GIT_FOUND)\n    message(FATAL_ERROR \"CPM requires Git.\")\n  endif()\n  if (NOT EXISTS ${CPM_DIR}/CPM.cmake)\n    message(STATUS \"Cloning repo (https://github.com/iauns/cpm)\")\n    execute_process(\n      COMMAND \"${GIT_EXECUTABLE}\" clone https://github.com/iauns/cpm ${CPM_DIR}\n      RESULT_VARIABLE error_code\n      OUTPUT_QUIET ERROR_QUIET)\n    if(error_code)\n      message(FATAL_ERROR \"CPM failed to get the hash for HEAD\")\n    endif()\n  endif()\n  include(${CPM_DIR}/CPM.cmake)\n\n  #------------------------------------------------------------------------------\n  # CPM Modules\n  #------------------------------------------------------------------------------\n\n  # ++ MODULE: OpenGL platform\n  CPM_AddModule(\"gl_platform\"\n    GIT_REPOSITORY \"https://github.com/iauns/cpm-gl-platform\"\n    GIT_TAG \"1.3.5\")\n\n  # ++ MODULE: aabb\n  CPM_AddModule(\"aabb\"\n    GIT_REPOSITORY \"https://github.com/iauns/cpm-glm-aabb\"\n    GIT_TAG \"1.0.3\")\n\n  # ++ EXTERNAL-MODULE: GLM\n  CPM_AddModule(\"glm\"\n    GIT_REPOSITORY \"https://github.com/iauns/cpm-glm\"\n    GIT_TAG \"1.0.2\"\n    USE_EXISTING_VER TRUE)\n\n  CPM_Finish()\n\n  #-----------------------------------------------------------------------\n  # Setup source\n  #-----------------------------------------------------------------------\n\n  # NOTE: Feel free to ignore this section. It simply creates a main.cpp source\n  # file from scratch instead of relying on the source being present. This is\n  # done only to keep this CMakeLists.txt self-contained.\n\n  file(WRITE src/main.cpp \"#include \u003ciostream\u003e\\n\")\n  file(APPEND src/main.cpp \"#include \u003cglm-aabb/AABB.hpp\u003e\\n\")\n  file(APPEND src/main.cpp \"#include \u003cglm/glm.hpp\u003e\\n\\n\")\n  file(APPEND src/main.cpp \"namespace glm_aabb = CPM_AABB_NS;\\n\\n\")\n  file(APPEND src/main.cpp \"int main(int argc, char** av)\\n\")\n  file(APPEND src/main.cpp \"{\\n\")\n  file(APPEND src/main.cpp \"  glm_aabb::AABB aabb(glm::vec3(-1.0), glm::vec3(1.0));\\n\")\n  file(APPEND src/main.cpp \"  aabb.extend(glm::vec3(-2.0, 3.0, -0.5));\\n\")\n  file(APPEND src/main.cpp \"  glm_aabb::AABB aabb2(glm::vec3(1.0), 1.0);\\n\")\n  file(APPEND src/main.cpp \"  std::cout \u003c\u003c \\\"AABB Interesction: \\\" \u003c\u003c aabb.intersect(aabb2) \u003c\u003c std::endl;\\n\")\n  file(APPEND src/main.cpp \"  return 0;\\n\")\n  file(APPEND src/main.cpp \"}\\n\")\n\n  set(Sources src/main.cpp)\n\n  #-----------------------------------------------------------------------\n  # Setup executable\n  #-----------------------------------------------------------------------\n  set(EXE_NAME cpm-test)\n  add_executable(${EXE_NAME} ${Sources})\n  target_link_libraries(${EXE_NAME} ${CPM_LIBRARIES})\n```\n\nUsing CPM\n=========\n\nQuick Setup\n-----------\n\nTo use CPM in your C++ project, include the following at the top of your\nCMakeLists.txt:\n\n```cmake\n  #------------------------------------------------------------------------------\n  # Required CPM Setup - no need to modify - See: https://github.com/iauns/cpm\n  #------------------------------------------------------------------------------\n  set(CPM_DIR \"${CMAKE_CURRENT_BINARY_DIR}/cpm-packages\" CACHE TYPE STRING)\n  find_package(Git)\n  if(NOT GIT_FOUND)\n    message(FATAL_ERROR \"CPM requires Git.\")\n  endif()\n  if (NOT EXISTS ${CPM_DIR}/CPM.cmake)\n    message(STATUS \"Cloning repo (https://github.com/iauns/cpm)\")\n    execute_process(\n      COMMAND \"${GIT_EXECUTABLE}\" clone https://github.com/iauns/cpm ${CPM_DIR}\n      RESULT_VARIABLE error_code\n      OUTPUT_QUIET ERROR_QUIET)\n    if(error_code)\n      message(FATAL_ERROR \"CPM failed to get the hash for HEAD\")\n    endif()\n  endif()\n  include(${CPM_DIR}/CPM.cmake)\n  \n  #------------------------------------------------------------------------------\n  # CPM Modules\n  #------------------------------------------------------------------------------\n\n  # TODO: Include any modules here...\n  \n  CPM_Finish()\n\n```\n\nThen add the ``${CPM_LIBRARIES}`` variable to your ``target_link_libraries``\nsimilar to the following:\n\n```cmake\ntarget_link_libraries(my_project ${CPM_LIBRARIES}) \n```\n\nAnd you're done. You will be able to start using CPM modules right away by\nadding the following snippet to the CPM Modules section of your\nCMakeLists.txt:\n\n```cmake\n  CPM_AddModule(\"aabb\"\n    GIT_REPOSITORY \"https://github.com/iauns/cpm-glm-aabb\"\n    GIT_TAG \"1.0.2\")\n```\n\nThis snippet will automatically download, build, and link version 1.0.2 of a\nsimple axis aligned bounding box implementation named `aabb`. A new namespace\nis generated for `aabb` and a preprocessor definition for this namespace is\nautomatically added to your project. The preprocessor namespace definition\nalways follows the form ``CPM_\u003cNAME\u003e_NS`` where ``\u003cNAME\u003e`` is the capitalized\nfirst argument of your call to ``CPM_AddModule``.\n\nFor example, in the 'aabb' snippet above, the first argument to\n`CPM_AddModule` was \"aabb\" so the preprocessor definition ``CPM_AABB_NS``\nwould be added to our project. This declares the namepsace under which CPM has\nbound the 'aabb' module. For instance, aabb's only class is named `AABB`. So\nthe fully qualified name for the `AABB` class would be: `CPM_AABB_NS::AABB`.\nYou may want to rename the namespace to something more appropriate:\n``namespace glm_aabb = CPM_AABB_NS;``. But that's entirely up to you.\nDepending on your needs, using the CPM namespace as-is may be all you need.\n\nBe sure to place all calls to `CPM_AddModule` before your call to\n`CPM_Finish`. The ``# TODO: Include any modules here...``\nsection mentioned in the first snippet indicates where you should place calls\nto ``CPM_AddModule``.\n\nWhy even bother with these preprocessor namespace definitions? The reason is\nso that we can leverage multiple different versions of a single CPM module in\nthe same static linkage unit. Why would we want to let users utilize multiple\nversions of our module in the first place? In many cases, users won't know\nthat they are actually using multiple different versions of your module. For\nexample, a more recent version of your module may be included directly by the\nuser, but an older version of your module may be pulled in as a dependency of\nanother module the user is relying on. If you're interested, you can see CPM's\n[dependency graph](#dependency-hierarchy) for your project.\n\nThings To Note\n--------------\n\n### Includes\n\nEvery module's root directory will be added to your include path. It is common\nthat every module's github page describes what file or files you should\ninclude in your project. The paths to these files will be relative to the\nmodule's root directory. So you can copy the include directive directly from\nthe module's github page into your code. For example, to access AABB's\nfunctionality we would include its interface header file like so:\n\n```\n#include \u003cglm-aabb/AABB.hpp\u003e\n```\n\n### Compiler Flags\n\nIf you have compiler flags you wish to apply to all modules, then add them\ndirectly before the CPM section in your CMakeListst.txt. Since each call to\n`CPM_AddModule` uses `add_subdirectory` internally, every module will inherit\nyour compiler flags (for good or bad).\n\n### CPM Externals\n\nIf the library you are interested in isn't a CPM module, try browsing through\nthe CPM externals listed on http://cpmcpp.com. Just use `CPM_AddModule` as you\nwould with any other module. Note that you will likely want to use the\n`USE_EXISTING_VER` parameter to `CPM_AddModule` in conjunction with external\nmodules.\n\nIf you don't find a formula for your favorite library, kindly consider\ncontributing one to our CPM modules repository.\n\n### Tag Advice\n\nWhile it may be tempting to use the `origin/master` tag to track the most\nrecent changes to a module, it is not recommended. Using version tags for a\nmodule (such as `1.0.2`) and upgrading modules when necessary will save you\ntime in the long run. If you track `origin/master` and upstream decides to\nrelease a major version which includes significant API changes then your\nbuilds will likely break immediately. But if versioned tags are used, you\nwill maintain your build integrity even through upstream version upgrades.\n\n### Advantages\n\n* Automatically manages code retrieval and building of CPM modules and externals.\n* Allows the use of multiple different versions of the same statically linked\n  module in the same executable.\n* Built entirely in CMake. Nothing else is required.\n* All CPM module code will be included in any generated project solution.\n* Will automatically detect preprocessor naming conflicts.\n* Optionally cache downloaded modules and repositories to a central directory.\n\n### Limitations\n\n* Only supports git (with very limited support for SVN).\n\n\nBuilding CPM Modules\n====================\n\nIf you only want to use pre-existing CPM modules and aren't interested in\nbuilding modules yourself, feel free to skip this section. But, if you are\ninterested in building CPM modules then please read on as some guidelines and\nrequirements are listed below.\n\nCMakeLists.txt Entry\n--------------------\n\nThere must be a CMakeLists.txt at the root of your module project and this\nCMakeLists.txt file must contain all relevant CPM directives and code (see\nbelow). Do not use issue calls to CPM (``CPM_*``) in a subdirectory\n(``add_subdirectory``).\n\nAdd the following to the top of the CMakeLists.txt for your module:\n\n```cmake\n  #-----------------------------------------------------------------------\n  # CPM configuration\n  #-----------------------------------------------------------------------\n  set(CPM_MODULE_NAME \u003cname\u003e)\n  set(CPM_LIB_TARGET_NAME ${CPM_MODULE_NAME})\n  \n  if ((DEFINED CPM_DIR) AND (DEFINED CPM_UNIQUE_ID) AND (DEFINED CPM_TARGET_NAME))\n    set(CPM_LIB_TARGET_NAME ${CPM_TARGET_NAME})\n    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CPM_DIR})\n    include(CPM)\n  else()\n    set(CPM_DIR \"${CMAKE_CURRENT_BINARY_DIR}/cpm-packages\" CACHE TYPE STRING)\n    find_package(Git)\n    if(NOT GIT_FOUND)\n      message(FATAL_ERROR \"CPM requires Git.\")\n    endif()\n    if (NOT EXISTS ${CPM_DIR}/CPM.cmake)\n      message(STATUS \"Cloning repo (https://github.com/iauns/cpm)\")\n      execute_process(\n        COMMAND \"${GIT_EXECUTABLE}\" clone https://github.com/iauns/cpm ${CPM_DIR}\n        RESULT_VARIABLE error_code\n        OUTPUT_QUIET ERROR_QUIET)\n      if(error_code)\n        message(FATAL_ERROR \"CPM failed to get the hash for HEAD\")\n      endif()\n    endif()\n    include(${CPM_DIR}/CPM.cmake)\n  endif()\n  \n  # Include CPM modules or externals here (with CPM_AddModule).\n  \n  CPM_InitModule(${CPM_MODULE_NAME})\n```\n\nBe sure to update the ``\u003cname\u003e`` at the beginning of the snippet. ``\u003cname\u003e`` \nis placed in the namespace preprocessor definition for your module. For example,\nif ``\u003cname\u003e`` is 'spire' then the preprocessor definition that will be added\nto your project will be ``CPM_SPIRE_NS``. Use this definition as a wrapper\naround your code and namespaces. Don't worry about users using the same name in\ntheir call to `CPM_AddModule` as the name you choose in your call to\n`CPM_InitModule`. CPM will automatically handle this for you. Also use\n``CPM_LIB_TARGET_NAME`` as the name of your library in `add_library` and include\n``CPM_LIBRARIES`` in `target_link_libraries` for your static library. Example:\n\n```cmake\n  # Our CPM module library\n  add_library(${CPM_LIB_TARGET_NAME} ${Source})\n  target_link_libraries(${CPM_LIB_TARGET_NAME} ${CPM_LIBRARIES})\n```\n\nHere is an example class that demonstrates the namespace wrapping:\n\n```cpp\n  namespace CPM_SPIRE_NS {\n\n  ... code here ...\n\n  } // namespace CPM_SPIRE_NS\n```\n\nLibrary target name\n-------------------\n\nIf you used the code snippet above make sure that your generated library target\nname is `${CPM_LIB_TARGET_NAME}`. This will ensure your library target name \nmatches with what CPM is expecting. But, if you can't name your target\n`${CPM_LIB_TARGET_NAME}` for any reason, use `CPM_ExportAdditionalLibraryTarget`\ninstead in order name your target whatever you would like. See the function\nreference below.\n\nWrapping Namespace\n------------------\n\nCPM allows multiple different versions of the same module to be statically\nlinked into the same target . As such, when you are building a module for CPM\n(not when you are using CPM modules!), you should either surround your\ntop-level namespaces in `CPM_[module name]_NS` tags or use `CPM_[module\nname]_NS` as your top level namespace, like so:\n\n```cpp\n  namespace CPM_[module name]_NS {\n\n    ...  \n\n  } // namespace CPM_[module name]_NS\n```\n\nThe first argument given to `CPM_InitModule` becomes ``[module name]`` in your\napplication.\n\nNote that this is *not* required but it is *heavily* recommended when you are\nbuilding CPM modules. You must include this if you want your users to be able\nto use multiple versions of your module within the same static linkage unit.\n\nDirectory Structure\n-------------------\n\nIn order to avoid header name conflicts CPM modules adhere to the directory\nfollowing structure:\n\n```\n  Root of [module name]\n    |-\u003e CMakeLists.txt\n    |-\u003e test\n    |-\u003e [module name]\n      |-\u003e [public headers go here]  \n      |-\u003e src\n        |-\u003e [private headers and source code]\n```\n\nUsing this structure users would include your public headers using:\n\n```\n  #include \u003c[module name]/interface.h\u003e\n```\nExporting Build Info\n--------------------\n\n### Include Paths\n\nBy default, the root of your project is added to the include path. If you need\nto expose more directories to the consumer of your module use the\n``CPM_ExportAdditionalIncludeDir`` function to add directories to the\nconsumer's include path. The first and only argument to\n``CPM_ExportAdditionalIncludeDir`` is the directory you want to add to the\npath. Be sure to clearly document any changes you make to the include path in\nyour module's README.\n\n### Definitions\n\nJust as with the include paths above you can set preprocessor definitions for\nthe consumer. Use the function ``CPM_ExportAdditionalDefinition``, like below:\n\n```\n  CPM_ExportAdditionalDefinition(\"-DMONGO_HAVE_STDINT\")\n```\n\n### Targets\n\nIf you have additional targets, or don't want to use the target name that\nCPM generates for you, you can use the `CPM_ExportAdditionalLibraryTarget`\nfunction that comes with CPM.\n\n```\n  CPM_ExportAdditionaLibraryTarget(\"MyTargetName\")\n```\n\nThis target will be added to the `target_link_libraries` call issued by the\nconsumer of your module.\n\nRegistering Your Module\n-----------------------\n\nOnce you have finished writing your module, add your repository to the\necosystem using the [CPM website](http://cpm.rocks/mod/add). A dependency\ngraph will be automatically generated for your module, and you will be able to\nsee others using your module.\n\nNote that this step is *not* mandatory. You can use your module without\nregistering it by pointing CPM to the URL of your git repository. Module\nregistration is recommended because it makes it easier for others to find.\n\nBuilding Externals\n------------------\n\nIf you are wrapping non-CPM code then you are likely building a CPM external.\nBuilding an external is just like building a module except for a call to:\n\n```\n  CPM_ForceOnlyOneModuleVersion()\n```\n\nsomewhere in your module's CMakeLists.txt file. This function ensures exactly\none (and only one) version of your module is ever statically linked.\n\nIn addition to this, you should reference the original repository in your\ncpm-modules JSON file by adding the 'externalURL' key/value pair. The key being\n'externalURL' and the value being be a URL locating the repository for which you\nhave created this external. Also set the 'external' key to 'true' in your JSON\nfile so that the CPM website knows you have built an external. For an example\nsee: [CPM External for Google Test](https://github.com/iauns/cpm-modules/blob/master/iauns/google_test.json).\n\nCPM Function Reference\n======================\n\nAll CMake functions that CPM exposes are listed below.\n\nGeneral Purpose\n---------------\n\n### CPM_AddModule\n\nAdds a CPM module to your project. All arguments except `\u003cname\u003e` are optional.\nAdditionally, one of either the `GIT_REPOSITORY` or `SOURCE_DIR` arguments\nmust be present in your call to `CPM_AddModule`. Should be called before\neither `CPM_Finish` or `CPM_InitModule`\n\n```cmake\n  CPM_AddModule(\u003cname\u003e           # Required - Module target name. Used to generate your \n                                 # preprocessor definition.\n    [GIT_REPOSITORY repo]        # Git repository that corresponds to a CPM module.\n                                 # If this argument is not specfied, then SOURCE_DIR must be set.\n    [GIT_TAG tag]                # Git tag to checkout. Tags, shas, and branches all work.\n    [USE_EXISTING_VER truth]     # If set to true, and an existing version of this module is \n                                 # found then the existing version of this module is used\n                                 # instead of the version indicated by GIT_TAG.\n    [SOURCE_DIR dir]             # Uses 'dir' as the source directory instead of cloning\n                                 # from a repo. If this is not specified, then \n                                 # GIT_REPOSITORY must be specified.\n    [SOURCE_GHOST_GIT_REPO repo] # Ghost repository when using SOURCE_DIR.\n                                 # Used to correctly correlate SOURCE_DIR modules with their \n                                 # correct upstream repository.\n    [SOURCE_GHOST_GIT_TAG tag]   # Ghost git tag when using SOURCE_DIR.\n    [EXPORT_MODULE truth]        # If true, then this module's (\u003cname\u003e) definitions and includes\n                                 # will be exported to any consumer of your module.\n    [FORWARD_DECLARATION truth]  # If true, then only the module's preprocessor definition \n                                 # (that the \u003cname\u003e argument above is used to generate) \n                                 # is exported to the consumer of the module. This is useful \n                                 # for situations where you only need to forward declare a \n                                 # module's classes in your interface classes and not actually \n                                 # include the target module's interface headers. This is \n                                 # preferred over EXPORT_MODULE.\n    )\n```\n\n### CPM_EnsureRepoIsCurrent\n\nA utility function that allows you to download and ensure that some repository\nis up to date and present on the filesystem before proceeding forward with\nCMakeLists.txt processing. Useful for building CPM externals. You can use this\nfunction outside of any call to CPM_Finish or CPM_InitModule\n\n```cmake\n  CPM_EnsureRepoIsCurrent(\n    [TARGET_DIR dir]             # Required - Directory in which to place repository.\n    [GIT_REPOSITORY repo]        # Git repository to clone and keep up to date.\n    [GIT_TAG tag]                # Git tag to checkout.\n    [SVN_REPOSITORY repo]        # SVN repository to checkout.\n    [SVN_REVISION rev]           # SVN revision.\n    [SVN_TRUST_CERT 1]           # Trust the Subversion server site certificate\n    [USE_CACHING 1]              # Enables caching of repositories if the user \n                                 # has specified CPM_MODULE_CACHING_DIR.\n                                 # Not enabled by default.\n    )\n```\n\n### CPM_Finish\n\nThis function is for the top-level application only. Call when you are\nfinished issuing calls to `CPM_AddModule`.\n\n```cmake\nCPM_Finish()\n```\n\nModules Only\n------------\n\nThe functions listed in this section are used exclusively for constructing\nmodules. If you use one of these functions in non-module code, a CMake warning\nwill be generated and the function call will be ignored.\n\n### CPM_InitModule\n\nThis function is the module's counterpart to `CPM_Finish`. Call this to\nindicate to CPM that you have finished issuing calls to `CPM_AddModule`.\nThe only argument indicates the name of the module. This name will only be\nused for generating the preprocessor definition you should use for your\nmodule.\n\n```cmake\nCPM_InitModule(\"my_module\")\n```\n\n### CPM_ExportAdditionalDefinition\n\nWhen building modules, this exports an additional definition in the module\nconsumer's scope. Use sparingly. Primarily used to expose mandatory external\nproject definitions.\n\n```cmake\nCPM_ExportAdditionalDefinition(\"-DMY_DEFINITION=42\")\n```\n\n### CPM_ExportAdditionalIncludeDir\n\nExposes an additional include directory to the consumer of a module.\nUse sparingly. Primarily used to expose external project directories\nto module consumers.\n\n```cmake\nCPM_ExportAdditionalIncludeDir(\"./foo/bar\")\n```\n\nNote, for this function, do not quote lists of include directories. Pass the\nlist in as-is.\n\n### CPM_ExportAdditionalLibraryTarget\n\nThis function is mostly used to avoid having to name targets per the\n`${CPM_TARGET_NAME}` convention in CPM. For an example of its use see\nhttp://github.com/iauns/cpm-google-test. Google test itself generates its own\ntarget name when included as a subdirectory so we must use that name.\n\n```cmake\nCPM_ExportAdditionalLibraryTarget(\"my_target\")\n```\n\nMiscellaneous Issues and Questions\n==================================\n\nBelow are some common issues users encounter and solutions to them.\n\nWhen are modules downloaded and updated?\n----------------------------------------\n\nDuring the CMake configure step. No repository cloning or fetching occurs\nduring the build step.\n\nExposing foreign module interfaces\n----------------------------------\n\nSome modules require the ability to expose classes from other modules through\npublic headers. This is allowed by tagging the module that you plan on\nexporting with ``EXPORT_MODULE TRUE`` just like:\n\n```\n  CPM_AddModule(\"GLM\"\n    GIT_REPOSITORY \"https://github.com/iauns/cpm-glm\"\n    GIT_TAG \"origin/master\"\n    USE_EXISTING_VER TRUE\n    EXPORT_MODULE TRUE    # Use EXPORT_MODULE sparingly. We expose GLM's interface\n    )                     # through our own interface hence why we export it.\n```\n\nIn this case, GLM's definitions and include paths will be exported to the\ndirect consumer of your module. It will not export this module to any parents\nof your consumer.\n\nUsing an existing module version\n--------------------------------\n\nCPM allows you the flexibility of selecting the most recently used version of a\nparticular module instead of the version you requested. This is useful when you\nare working with externals or modules that require you to only use one version.\nSimply add ``USE_EXISTING_VER TRUE`` in your call to ``CPM_AddModule``. An\nexample of this is given above in the section on exposing foreign module\ninterfaces.\n\nFor example, if a module you added (lets call this module `B`) requested\nversion `v0.9.5` of module `A`, and you subsequently requested `v0.9.1` of\nmodule `A`, then your version would be upgraded to `v0.9.5` to comply with the\npre-existing version of the module if you specified `USE_EXISTING_VER TRUE`\nwhen adding module `A`. It is considered best practice to set\n`USE_EXSTING_VER` to `TRUE` when adding *externals* (not regular modules) to\nyour project. Especially when building modules for others to use. But also be\naware that your version can be *downgraded* in the same manner. You can\ngenerally avoid being downgraded by re-arranging the order of your calls to\n`CPM_AddModule`.\n\nWhen adding regular non-external modules, you may consider using this\noption to reduce the size of your executable if multiple different versions of\nthe same module are being used. Just be weary of compiler errors due to\nversion conflicts. In most cases, this option should be avoided when using\nregular, non-external, CPM modules.\n\nForce only one module version\n-----------------------------\n\nAs pointed out in the externals section you may force all consumers, indirect\nor direct, of your module to use only one version. Most module creators won't\nneed to worry about this corner case, but it is required that all externals\nuse this. Include a call to ``CPM_ForceOnlyOneModuleVersion`` anywhere in\nyour module's CMakeLists.txt file to enforce this. Usually this call is made\ndirectly before calling ``CPM_InitModule``.\n\nIf you do this, you should indicate that your module is an 'external' in your\nmodule's JSON file. Even if you don't use any external code. It is important\nto separate these modules from 'regular' modules, and the nomenclature we have\nchosen for these types of modules are 'externals'.\n\nDownloading repos without external projects\n-------------------------------------------\n\nCPM provides a utility function that allows you to download repositories at\nconfiguration time. This function is: `CPM_EnsureRepoIsCurrent`. This function\nwill also ensure the tag you specify is up to date and the repo is present\nbefore continuing execution of CMakeLists.txt. You can download both git\nrepositories and SVN repositories using this function. For a reference\nregarding the function's parameters, see the comments at the top of CPM.cmake.\n\nFor examples of using this function, see the\n[google test](https://github.com/iauns/cpm-google-test) CPM external.\n\n\nHow do I cache modules?\n-----------------------\n\nCPM supports cached repositories and modules by setting either the\n`CPM_MODULE_CACHE_DIR` CMake variable or the `CPM_CACHE_DIR` environment\nvariable to an appropriate cache directory (such as `~/.cpm_cache`). When\nset, a search will be performed in the cache directory for all modules that\ndon't already exist in your project's build directory. If the module is not\nfound in the cache directory, CPM will download the module into the cache\ndirectory. This is useful if you find yourself with no or limited internet\naccess from time to time as your cache directory will be searched before\nattempting to download the repository from the internet.\n\nHere's a quick example of using this variable from the command line:\n\n```\n  cmake -DCPM_MODULE_CACHE_DIR=~/.cpm_cache ...\n```\n\nThe cache directory is searched only when a module is not found in your\nproject's build directory. If the module is then found in the cache directory,\nthe cache directory will be updated using the appropriate SCM and its\ndirectory contents will be copied into your project's build directory. Any\nsubsequent invokation of CMake will find the module in your project's build\ndirectory and will not search in the cache directory. Unless you have cleaned\nthe project or removed the build directory's modules.\n\nHow do I cache CPM itself?\n--------------------------\n\nUse the following code snippet instead of the one given above. This snippet\nchecks to see if CPM exists in the cache directory before attempting to\ndownload it.\n\n```cmake\n#------------------------------------------------------------------------------\n# Required CPM Setup - See: http://github.com/iauns/cpm\n#------------------------------------------------------------------------------\nset(CPM_DIR \"${CMAKE_CURRENT_BINARY_DIR}/cpm-packages\" CACHE TYPE STRING)\nfind_package(Git)\nif(NOT GIT_FOUND)\n  message(FATAL_ERROR \"CPM requires Git.\")\nendif()\nif ((NOT DEFINED CPM_MODULE_CACHE_DIR) AND (NOT \"$ENV{CPM_CACHE_DIR}\" STREQUAL \"\"))\n  set(CPM_MODULE_CACHE_DIR \"$ENV{CPM_CACHE_DIR}\")\nendif()\nif ((NOT EXISTS ${CPM_DIR}/CPM.cmake) AND (DEFINED CPM_MODULE_CACHE_DIR))\n  if (EXISTS \"${CPM_MODULE_CACHE_DIR}/github_iauns_cpm\")\n    message(STATUS \"Found cached version of CPM.\")\n    file(COPY \"${CPM_MODULE_CACHE_DIR}/github_iauns_cpm/\" DESTINATION ${CPM_DIR})\n  endif()\nendif()\nif (NOT EXISTS ${CPM_DIR}/CPM.cmake)\n  message(STATUS \"Cloning repo (https://github.com/iauns/cpm)\")\n  execute_process(\n    COMMAND \"${GIT_EXECUTABLE}\" clone https://github.com/iauns/cpm ${CPM_DIR}\n    RESULT_VARIABLE error_code\n    OUTPUT_QUIET ERROR_QUIET)\n  if(error_code)\n    message(FATAL_ERROR \"CPM failed to get the hash for HEAD\")\n  endif()\nendif()\ninclude(${CPM_DIR}/CPM.cmake)\n\n# Modules go here...\n\nCPM_Finish()\n```\n\n\u003ca name=\"dependency-hierarchy\"\u003e\u003c/a\u003e\nHow do I see the module dependency hierarchy?\n---------------------------------------------\n\nWhen building your project define: ``CPM_SHOW_HIERARCHY=TRUE``.\n\nOn the command line this would look something like\n\n```\n  cmake -DCPM_SHOW_HIERARCHY=TRUE ...\n```\n\nIt is best to run this command after you have successfully built your project\nso the output is not muddied by status messages.\n\nI get errors regarding reused binary directories\n------------------------------------------------\n\nIf you get errors similar to:\n\n```\n  The binary directory\n\n    /Users/jhughes/me/cpp/cpm/modules/ ... /bin\n\n  is already used to build a source directory.  It cannot be used to build\n  source directory.\n```\n\nThis means that there exists a circular module reference which is not allowed\nin CPM. The module graph must not contain cycles. For example, if Module A\nadds Module B, and Module B adds Module A, you will get this error.\n\nHow do I Manage CPM Namespaces?\n-------------------------------\n\nThere are a number of options here. You could rename the `CPM_\u003cNAME\u003e_NS` at\nthe top of your implementation files:\n\n```cpp\nnamespace Spire = CPM_SPIRE_NS;\n```\n\nOr you can build a header that renames all of the module namespaces for you.\nSomething akin to the following:\n\n```cpp\n  #ifndef __MY_NAMESPACES_H\n  #define __MY_NAMESPACES_H\n\n  // 'Forward declaration' of CPM module namespaces.\n  namespace CPM_SPIRE_NS {}\n  namespace CPM_SPIRE_SCIRUN_NS {}\n  ... (more forward declarations) ...\n  \n  // Renaming the namespaces in our top level namespace.\n  namespace my_namespace {\n    namespace Spire     = CPM_SPIRE_NS;\n    namespace SpireSR   = CPM_SPIRE_SCIRUN_NS;\n  }\n\n  #endif\n```\n\nBe careful with the latter header based approach since there are some\npitfalls. For example, the increased possibility of header guard confilcts\nand namespace conflicts. In general, renaming the namespace at the source\nlevel is the recommended way to go.\n\n","funding_links":[],"categories":["TODO scan for Android support in followings","Build Systems","排序","构建系统","Package Management / Build Systems"],"sub_categories":["构建系统"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiauns%2Fcpm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiauns%2Fcpm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiauns%2Fcpm/lists"}