{"id":16109876,"url":"https://github.com/clausklein/cmake-example-component-lib","last_synced_at":"2025-03-18T09:30:51.806Z","repository":{"id":51687007,"uuid":"342284686","full_name":"ClausKlein/cmake-example-component-lib","owner":"ClausKlein","description":"How to create a c++ component library like boost with CMake","archived":false,"fork":false,"pushed_at":"2022-11-29T20:25:39.000Z","size":119,"stargazers_count":21,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"develop","last_synced_at":"2025-03-16T18:42:08.630Z","etag":null,"topics":["clang-format","cmake","cmake-format","cpm","cpp"],"latest_commit_sha":null,"homepage":"https://clausklein.github.io/cmake-example-component-lib/","language":"CMake","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ClausKlein.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":"2021-02-25T15:12:36.000Z","updated_at":"2025-03-04T10:43:12.000Z","dependencies_parsed_at":"2022-08-23T01:31:56.493Z","dependency_job_id":null,"html_url":"https://github.com/ClausKlein/cmake-example-component-lib","commit_stats":null,"previous_names":[],"tags_count":4,"template":true,"template_full_name":"ClausKlein/ModernCppStarter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClausKlein%2Fcmake-example-component-lib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClausKlein%2Fcmake-example-component-lib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClausKlein%2Fcmake-example-component-lib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClausKlein%2Fcmake-example-component-lib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ClausKlein","download_url":"https://codeload.github.com/ClausKlein/cmake-example-component-lib/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244192487,"owners_count":20413531,"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":["clang-format","cmake","cmake-format","cpm","cpp"],"created_at":"2024-10-09T19:34:48.187Z","updated_at":"2025-03-18T09:30:51.513Z","avatar_url":"https://github.com/ClausKlein.png","language":"CMake","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://repository-images.githubusercontent.com/254842585/4dfa7580-7ffb-11ea-99d0-46b8fe2f4170\" height=\"175\" width=\"auto\" /\u003e\n\u003c/p\u003e\n\n# ModernCppComponentLibraryExample\n\nSetting up a new C++ project usually requires a significant amount of\npreparation and boilerplate code, even more so for modern C++ projects\nwith tests, executables and continuous integration.  This template is the\nresult of learnings from many previous projects and should help reduce\nthe work required to setup up a modern C++ project.\n\nThis repository is intended as a template to show the \"proper\" way to\nsetup a \"Modern CMake\" project with `components`. The required usage (for a\ndownstream library) should be nothing more than:\n\n```cmake\n  find_package(\n    MathFunctions 1\n    COMPONENTS Addition SquareRoot\n    REQUIRED\n  )\n\n  /#..\n\n  target_link_libraries(\n    MathFunctionsTests Boost::ut MathFunctions::Addition MathFunctions::SquareRoot\n  )\n```\n\n\n## Features\n\n- [Modern CMake practices](https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/)\n- [CMake for library authors: Best practice](https://crascit.com/2019/10/16/cppcon-2019-deep-cmake-for-library-authors/)\n- [Modernize C++ using clang-tidy](https://www.kdab.com/clang-tidy-part-1-modernize-source-code-using-c11c14/)\n- [CMake Importing Exporting Guilde](https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html?highlight=components#adding-components)\n- [Prevents clang-tidy to check sources added with FetchContents](https://discourse.cmake.org/t/how-to-prevent-clang-tidy-to-check-sources-added-with-fetchcontents/2871)\n- Suited for single header libraries and projects of any scale\n- Clean separation of library and executable code\n- Integrated test suite\n- Continuous integration via [GitHub Actions](https://help.github.com/en/actions/)\n- Code coverage via [gcovr](https://gcovr.com)\n- Code coverage via [codecov](https://codecov.io)\n- Code formatting enforced by [clang-format](https://clang.llvm.org/docs/ClangFormat.html) and [cmake-format](https://github.com/cheshirekow/cmake_format)\n- Reproducible dependency management via [CPM.cmake](https://github.com/TheLartians/CPM.cmake)\n- Installable target with automatic versioning information and header generation via [PackageProject.cmake](https://github.com/TheLartians/PackageProject.cmake)\n- Automatic [documentation](https://thelartians.github.io/ModernCppStarter) and deployment with [Doxygen](https://www.doxygen.nl) and [GitHub Pages](https://pages.github.com)\n- Support for [sanitizer tools, and more](#additional-tools)\n\n\n## Tips\n\n- Use [Gitflow Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow)\n- Use [Ninja](https://cmake.org/cmake/help/latest/generator/Ninja.html)\n  and [ccache](https://ccache.dev) to speed up your round trip time\n- Use [Boost::ut ](https://boost-ext.github.io/ut/) A pure C++20 μ(micro)/Unit Testing Framework if possible\n- Try [Qt Creator](https://www.qt.io/download-open-source) as [IDE](#IDE)\n  ... or simply use [gvim](https://packages.ubuntu.com/bionic/gvim) and type `:make test`\n\n\n## Usage\n\n### Adjust the template to your needs\n\n- Use this repo [as a template](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template) and replace all occurrences of \"MathFunctions\" in the relevant `CMakeLists.txt` with the name of your project\n- Replace the source files with your own\n- Happy coding!\n\nEventually, you can remove any unused files, such as the standalone\ndirectory or irrelevant github workflows for your project.  Feel free to\nreplace the [License](License) with one suited for your project.\n\nTo cleanly separate the library and subproject code, the outer\n[CMakeLists.txt](CMakeLists.txt) only defines the library itself while\nthe tests and other subprojects are self-contained in their own\ndirectories.  During development it is usually convenient to [build all\nsubprojects at once](#build-everything-at-once).\n\n\n### Use the makefile wrapper on unix bash or with GVIM\n\nThere is a [makefile](GNUmakefile) to wrap the\n[CMake](https://cmake.org/cmake/help/latest/manual/cmake.1.html)\ncommand-line interface for esay use at bash shell.\n\n\n### Build and run the standalone target\n\nUse the following command to build and run the executable target.\n\n```bash\nmake standalone\n\n# or\ncmake --build build/standalone\nbuild/standalone/MathFunctionsStandalone 2.0\n```\n\n### Build and run test suite\n\nUse the following commands from the project's root directory to run the\ntest suite.\n\n```bash\nmake test\n\n# or\ncmake -S test -B build/test\ncmake --build build/test\nCTEST_OUTPUT_ON_FAILURE=1 cmake --build build/test --target test\n\n# or simply call the executable:\nbuild/test/MathFunctionsTest\n```\n\nTo collect code coverage information, run CMake with the\n`-DENABLE_TEST_COVERAGE=1` option.\n\n\n### Generate a GCC Code Coverage Report\n\nTo generate or update with `gcovr` the html files\n[reports/gcov/index.html](https://clausklein.github.io/cmake-example-component-lib/):\n\n`make gcov`\n\n\n### Run clang-tidy\n\nThe [.clang-tidy](.clang-tidy)\n[checks](https://clang.llvm.org/extra/clang-tidy/) supports you to write\nclean code!\n\nTo check your project with _clang-tidy_ simply do\n\n`make tidy`\n\n\n### Run clang-format\n\nUse the following commands from the project's root directory to check and\nfix C++ and CMake source style.  This requires _clang-format_,\n_cmake-format_ and _pyyaml_ to be installed on the current system.\n\n```bash\nmake format\n\n# or\ncmake -S test -B build/test\n\n# view changes\ncmake --build build/test --target format\n\n# apply changes\ncmake --build build/test --target fix-format\n```\n\nSee [Format.cmake](https://github.com/TheLartians/Format.cmake) for details.\n\n\n### Build the documentation\n\nTo manually build documentation, call the following command.\n\n```bash\nmake doc\n\n# or\ncmake -S documentation -B build/doc\ncmake --build build/doc --target GenerateDocs\n# view the docs\nopen build/doc/doxygen/html/index.html\n```\n\nTo build the documentation locally, you will need Doxygen, jinja2 and\nPygments on installed your system.\n\n\n### Build everything at once\n\nThe project also includes an `all` directory that allows building all\ntargets at the same time.  This is useful during development, as it\nexposes all subprojects to your IDE and avoids redundant builds of the\nlibrary.\n\n\n## IDE\n\nUse [Qt Creator](https://www.qt.io/download-open-source) as IDE\n\nIt creates the best usable results when open the project via\n[all/CMakeLists.txt](all/CMakeLists.txt).  And it supports to direct\nimport a existing CMake build directory create with:\n\n\n```bash\nmake all\n\n# or\ncmake -S all -B build\ncmake --build build\n\n# run tests\nbuild/test/MathFunctionsTest\n# format code\ncmake --build build --target fix-format\n# run standalone\nbuild/standalone/MathFunctionsStandalone 42.0\n# build docs\ncmake --build build --target GenerateDocs\n```\n\n\n## Additional tools\n\nThe test and standalone subprojects include the\n[tools.cmake](cmake/tools.cmake) file which is used to import additional\ntools on-demand through CMake configuration arguments.  The following are\ncurrently supported.\n\n#### Sanitizers\n\nSanitizers can be enabled by configuring CMake with\n`-DUSE_SANITIZER=\u003cAddress | Memory | MemoryWithOrigins | Undefined | Thread | Leak | 'Address;Undefined'\u003e`.\n\n#### Static Analyzers\n\nStatic Analyzers can be enabled by setting\n`-DUSE_STATIC_ANALYZER=\u003cclang-tidy | iwyu | cppcheck\u003e`, or a combination\nof those in quotation marks, separated by semicolons.  By default,\nanalyzers will automatically find configuration files such as\n`.clang-format`.  Additional arguments can be passed to the analyzers by\nsetting the `CLANG_TIDY_ARGS`, `IWYU_ARGS` or `CPPCHECK_ARGS` variables.\n\n#### Ccache\n\nCcache can be enabled by configuring with `-DUSE_CCACHE=\u003cON | OFF\u003e`.\n\n\n## FAQ\n\n\u003e Can I use this for header-only libraries?\n\nYes, however you will need to change the library type to an `INTERFACE`\nlibrary as documented in the [CMakeLists.txt](CMakeLists.txt).  See\n[here](https://github.com/TheLartians/StaticTypeInfo) for an example\nheader-only library based on the template.\n\n\u003e I don't need a standalone target / documentation. How can I get rid of it?\n\nSimply remove the standalone / documentation directory and according\ngithub workflow file.\n\n\u003e Can I build the standalone and tests at the same time? / How can I tell my IDE about all subprojects?\n\nTo keep the template modular, all subprojects derived from the library\nhave been separated into their own CMake modules.  This approach makes it\ntrivial for third-party projects to re-use the projects library code.  To\nallow IDEs to see the full scope of the project, the template includes\nthe `all` directory that will create a single build for all subprojects.\nUse this as the main directory for best IDE support.\n\n\u003e I see you are using `GLOB` to add source files in `CMakeLists.txt`. Isn't that evil?\n\nGlob is considered bad because any changes to the source file structure\n[might not be automatically\ncaught](https://cmake.org/cmake/help/latest/command/file.html#filesystem)\nby CMake's builders and you will need to manually invoke CMake on\nchanges.  I personally prefer the `GLOB` solution for its simplicity, but\nfeel free to change it to explicitly listing sources.\n\n\u003e I want create additional targets that depend on my library. Should I modify the main `CMakeLists.txt` to include them?\n\nAvoid including derived projects from the libraries `CMakeLists.txt` (even\nthough it is a common sight in the C++ world), as this effectively\ninverts the dependency tree and makes the build system hard to reason\nabout.  Instead, create a new directory or project with a `CMakeLists.txt` that\nadds the library as a dependency (e.g. like the\n[standalone](standalone/CMakeLists.txt) directory).  Depending type it\nmight make sense move these components into a separate repositories and\nreference a specific commit or version of the library.  This has the\nadvantage that individual libraries and components can be improved and\nupdated independently.\n\n\u003e You recommend to add external dependencies using CPM.cmake. Will this force users of my library to use CPM as well?\n\n[CPM.cmake](https://github.com/TheLartians/CPM.cmake) should be invisible\nto library users as it's a self-contained CMake Script.  If problems do\narise, users can always opt-out by defining `CPM_USE_LOCAL_PACKAGES`,\nwhich will override all calls to `CPMAddPackage` with `find_package`.\nAlternatively, you could use `CPMFindPackage` instead of `CPMAddPackage`,\nwhich will try to use `find_package` before calling `CPMAddPackage` as a\nfallback.  Both approaches should be compatible with common C++ package\nmanagers without modifications, however come with the cost of\nreproducible builds.\n\n\u003e Can I configure and build my project offline?\n\nUsing CPM, all missing dependencies are downloaded at configure time.  To\navoid redundant downloads, it's recommended to set a CPM cache directory,\ne.g.: `export CPM_SOURCE_CACHE=$HOME/.cache/CPM`.  This will also allow\noffline configurations if all dependencies are present.  No internet\nconnection is required for building.\n\n\u003e Can I use CPack to create a package installer for my project?\n\nAs there are a lot of possible options and configurations, this is not\n(yet) in the scope of this template. See the [CPack\ndocumentation](https://cmake.org/cmake/help/latest/module/CPack.html) for\nmore information on setting up CPack installers.\n\n\u003e This is too much, I just want to create a singe C++ library.\n\nPerhaps the [ModernCppStarter](https://github.com/ClausKlein/ModernCppStarter)\n\n\u003e This is too much, I just want to play with C++ code and test some libraries.\n\nPerhaps the [MiniCppStarter](https://github.com/TheLartians/MiniCppStarter) is something for you!\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclausklein%2Fcmake-example-component-lib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclausklein%2Fcmake-example-component-lib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclausklein%2Fcmake-example-component-lib/lists"}