Compare commits

..

241 Commits

Author SHA1 Message Date
Duncan Ogilvie 39b4522bc5 Validate APPEND custom commands more strictly 2026-04-14 20:09:11 +02:00
Duncan Ogilvie da4ec26df0 Fix latest custom target review issues 2026-04-14 15:32:07 +02:00
Duncan Ogilvie 31f77ab328 Address latest custom command review feedback 2026-04-14 15:11:31 +02:00
Duncan Ogilvie 6d41c92e37 Fix custom command review issues 2026-04-14 15:07:23 +02:00
Duncan Ogilvie 411eb03db4 Protobuf example 2026-04-14 15:07:16 +02:00
Duncan Ogilvie 9f80ce4429 Generator executable example 2026-04-14 15:06:54 +02:00
Duncan Ogilvie 8650f53174 Simple post build test 2026-04-14 15:06:53 +02:00
Duncan Ogilvie 6cb1009c0e Add support for custom commands 2026-04-14 15:06:53 +02:00
Duncan Ogilvie 26acf23989 Merge pull request #199 from build-cpp/gitignore-update
Add CMakeUserPresets.json to generated .gitignore
2026-04-14 12:12:36 +02:00
Duncan Ogilvie 15886fc340 Add CMakeUserPresets.json to generated .gitignore 2026-04-14 12:09:54 +02:00
Duncan Ogilvie d5e34b0bcc Merge pull request #197 from ZehMatt/fix-option-prefix2
Fix a regression that no longer warns if condition is manually defined
2026-02-14 19:11:36 +01:00
ζeh Matt 916ae11cae Fix a regression that no longer warns if condition is manually defined 2026-02-14 18:14:39 +02:00
Duncan Ogilvie eaa361611a Merge pull request #196 from ZehMatt/fix-option-prefix
Fix warnings when options are not prefixed with the project name
2026-02-14 16:38:37 +01:00
ζeh Matt 2300612ba9 Fix warnings when options are not prefixed with the project name 2026-02-14 17:23:02 +02:00
Duncan Ogilvie 25f015bc83 Bump to 0.2.46 2026-02-01 16:39:51 +01:00
Duncan Ogilvie fc674b4c6b Merge pull request #195 from build-cpp/conditional-languages
Add support for conditional [project].languages
2026-02-01 16:39:16 +01:00
Duncan Ogilvie 433dbb0500 Add test for conditional Objective-C support
Closes #183
2026-02-01 16:37:23 +01:00
Duncan Ogilvie 4772a2b683 Add support for conditional [project].languages
Closes #184
2026-02-01 16:14:17 +01:00
Duncan Ogilvie fb4931df1f Merge pull request #193 from build-cpp/toml11-upgrade
Support TOML 1.1.0
2026-02-01 15:36:15 +01:00
Duncan Ogilvie e96cd30217 Merge pull request #194 from build-cpp/add-dependencies
Add support for [target].dependencies
2026-02-01 15:36:04 +01:00
Duncan Ogilvie 2db8d1ee1d Add support for [target].dependencies
Closes #177
2026-02-01 15:33:09 +01:00
Duncan Ogilvie 645737afd4 Merge pull request #191 from de-ep/fix-tilde-expansion
fix #186
2025-12-21 14:33:09 +01:00
deep 98c2e962c0 fix tilde expansion: add windows support 2025-12-21 14:44:32 +05:30
Duncan Ogilvie 438feccf0f Add support for toml 1.1.0 2025-12-20 15:11:36 +01:00
Duncan Ogilvie 80cc29b8e1 Upgrade toml11 to 3.8.1 2025-12-20 14:29:26 +01:00
Duncan Ogilvie 1a62034a8a Fix formatting 2025-12-20 13:49:34 +01:00
Duncan Ogilvie c12472cd8f Merge pull request #180 from d06i/fix
fix #172
2025-12-17 18:35:20 +01:00
deep 228553d43a fix #186 2025-12-10 19:23:24 +05:30
Duncan Ogilvie 8f4b376e42 Bump to 0.2.45 2025-08-26 17:16:10 +02:00
Duncan Ogilvie fcbf937c49 Merge pull request #189 from iamtimmy/main
template add-function arguments
2025-08-26 17:00:55 +02:00
iamtimmy e609c8a48f template add-function arguments
add arguments support to add-function functionality in templates
2025-08-26 16:46:32 +02:00
Duncan Ogilvie 735898dbac Update basics.md 2025-08-11 03:37:01 +02:00
Duncan Ogilvie f7126b0158 Update basics.md 2025-08-11 03:35:53 +02:00
Duncan Ogilvie b6702714eb Fix info 2025-08-11 03:31:57 +02:00
Duncan Ogilvie efa4f716c2 Add CMake phases to basics 2025-08-11 03:30:28 +02:00
Duncan Ogilvie 76b7b8e778 Clarify basics documentation page 2025-08-11 03:05:37 +02:00
Duncan Ogilvie 501b26ced5 Update fetch-content documentation 2025-06-25 01:50:29 +02:00
Duncan Ogilvie 5bc36275ad Merge pull request #185 from build-cpp/gh-actions-bump
Bump github actions
2025-05-30 01:16:56 +02:00
Duncan Ogilvie 35c837a181 Bump github actions 2025-05-30 00:24:22 +02:00
Duncan Ogilvie 710dfa4963 Merge pull request #182 from evanwporter/patch-1
bumped up upload version
2025-05-30 00:15:38 +02:00
Duncan Ogilvie c49ee6bafe Update README.md 2025-05-29 23:21:04 +02:00
Evan 368273bab2 bumped up upload version 2025-04-19 15:49:15 -07:00
d06i ffe08ae60c fix #172 2025-04-18 00:19:51 +03:00
Duncan Ogilvie b1249af365 Bump to 0.2.44 2025-01-19 15:12:34 +01:00
Duncan Ogilvie ea2ff31b5a Merge pull request #173 from build-cpp/fix-empty-properties
Make sure empty target properties are emitted correctly
2025-01-19 15:10:06 +01:00
Duncan Ogilvie a32eb66df4 Make sure empty target properties are emitted correctly 2025-01-19 14:53:50 +01:00
Duncan Ogilvie 9b85833240 Add link to example vcpkg repository 2024-12-06 18:19:35 +01:00
Duncan Ogilvie ccb3d0b9ef Bump to 0.2.43 2024-12-04 13:00:03 +01:00
Duncan Ogilvie 49cdab39bd Merge pull request #169 from build-cpp/namespace-targets
Support `::mylib` which that target that exists at configure-time
2024-12-04 12:55:57 +01:00
Duncan Ogilvie e318139314 Add documentation for ::mylib 2024-12-04 12:15:51 +01:00
Duncan Ogilvie 0f2a9a55fb Support link-libraries = ["::mylib"] which checks the if target exists
https://gitlab.kitware.com/cmake/cmake/-/issues/26497
2024-12-04 12:15:49 +01:00
Duncan Ogilvie 38cec2d5d1 Do not allow lambdas on a single line 2024-12-04 11:55:13 +01:00
Duncan Ogilvie 3caf593438 Bump to 0.2.42 2024-12-03 15:35:05 +01:00
Duncan Ogilvie c94dbd6416 Merge pull request #168 from build-cpp/target-directory-bug
Fix linking against a target that's also a directory
2024-12-03 13:41:16 +01:00
Duncan Ogilvie a1eaf601c6 Fix linking against a target that's also a directory
Closes #166
2024-12-03 13:39:32 +01:00
Duncan Ogilvie 10320c8e55 Bump to 0.2.41 2024-12-02 15:56:02 +01:00
Duncan Ogilvie 45e12c8d98 Merge pull request #165 from build-cpp/cmake-support
Fix vcpkg support for CMake 3.30
2024-12-02 15:55:43 +01:00
Duncan Ogilvie e12ebc060d Use FetchContent_MakeAvailable for vcpkg 2024-12-02 15:54:19 +01:00
Duncan Ogilvie c6e3fc159f Suppress deprecation warning for CMake <3.10 2024-12-02 15:50:22 +01:00
Duncan Ogilvie dc6f306d9c Bump to 0.2.40 2024-11-28 23:02:34 +01:00
Duncan Ogilvie e08bd5a311 Merge pull request #164 from build-cpp/vcpkg-overlay-bugfix
Use absolute paths for vcpkg overlays
2024-11-28 23:02:17 +01:00
Duncan Ogilvie 068977e2f5 Use absolute paths for vcpkg overlays 2024-11-28 23:01:14 +01:00
Duncan Ogilvie 73147747a4 Bump to 0.2.39 2024-11-28 21:26:27 +01:00
Duncan Ogilvie a64fa9cc34 Merge pull request #163 from build-cpp/vcpkg-fetch-folder
Move vcpkg download location directly in `${CMAKE_BINARY_DIR}/vcpkg`
2024-11-28 21:25:53 +01:00
Duncan Ogilvie eb6ccb39ee Move vcpkg download location directly in ${CMAKE_BINARY_DIR} 2024-11-28 21:24:03 +01:00
Duncan Ogilvie 91dd8ce51f Bump to 0.2.38 2024-11-28 14:40:22 +01:00
Duncan Ogilvie efbfca27bd Merge pull request #160 from build-cpp/vcpkg-triplets
Add support for `[vcpkg].overlay-triplets`
2024-11-28 14:38:46 +01:00
Duncan Ogilvie 78bcf2acf7 Add support for [vcpkg].overlay-triplets 2024-11-28 14:28:10 +01:00
Duncan Ogilvie 83559cc5d4 Improve target reference documentation 2024-11-28 14:28:08 +01:00
Duncan Ogilvie 5d85cc83e3 Ignore generated vcpkg.json 2024-11-28 13:44:11 +01:00
Duncan Ogilvie dea41d80b5 Bump to 0.2.37 2024-11-27 14:17:48 +01:00
Duncan Ogilvie b52cf5b241 Merge pull request #158 from build-cpp/vcpkg-default-features
Allow disabling default features with vcpkg
2024-11-27 14:16:25 +01:00
Duncan Ogilvie e9480a625f Allow disabling default features with vcpkg 2024-11-27 14:13:37 +01:00
Duncan Ogilvie 13a7a8788a Bump to 0.2.36 2024-11-26 13:36:24 +01:00
Duncan Ogilvie 45ca74099c Merge pull request #156 from build-cpp/vcpkg-overlay-ports
Add [vcpkg].overlay-ports feature
2024-11-26 13:35:32 +01:00
Duncan Ogilvie ae3d73896e Add [vcpkg].overlay-ports feature 2024-11-26 12:33:29 +01:00
Duncan Ogilvie 57042565d1 Merge pull request #154 from build-cpp/configure-depends
Use CMAKE_CONFIGURE_DEPENDS when supported
2024-11-03 11:44:02 +01:00
deep d02ee3ed24 Added check to make sure hash is valid hex (#153) 2024-11-03 10:49:33 +01:00
Duncan Ogilvie 4a15d2ba55 Use CMAKE_CONFIGURE_DEPENDS when supported 2024-11-03 10:33:32 +01:00
Duncan Ogilvie 87c0295f93 Fix CI 2024-10-14 13:02:20 +02:00
Duncan Ogilvie a608e6b778 Bump to 0.2.35 2024-10-13 16:16:36 +02:00
Duncan Ogilvie 523f5f4a8a Merge pull request #150 from build-cpp/msvc-runtime-root
Only emit `MSVC_RUNTIME_LIBRARY` in the root project
2024-09-06 14:39:47 +02:00
Duncan Ogilvie 510cf71af5 Only emit MSVC_RUNTIME_LIBRARY in the root project 2024-09-06 14:33:04 +02:00
Duncan Ogilvie 87d90138b4 Merge pull request #149 from build-cpp/relative-libs
Improve relative path functionality for link-libraries
2024-09-06 14:25:33 +02:00
Duncan Ogilvie 50615e0c27 Bump clang-format-lint-action
https://github.com/DoozyX/clang-format-lint-action/issues/73
2024-09-06 14:22:12 +02:00
Duncan Ogilvie 42ed3048b3 Improve relative path functionality for link-libraries 2024-09-06 13:50:43 +02:00
Duncan Ogilvie b0a1d79a42 Bump to 0.2.34 2024-08-05 15:28:58 +02:00
Duncan Ogilvie 5882bc082d Support integer properties
Closes #148
2024-08-05 15:28:38 +02:00
Duncan Ogilvie a90b3c6095 Add RC as a default language 2024-08-05 15:28:16 +02:00
Duncan Ogilvie 0a887c08f8 Bump to 0.2.33 2024-07-06 14:50:39 +02:00
Duncan Ogilvie 9f2cfe4083 Merge pull request #146 from build-cpp/improved-conditions
Improve error-prone condition handling
2024-07-06 14:49:32 +02:00
Duncan Ogilvie 15ad1dc6a7 Support nested condition syntax for named conditions 2024-07-06 14:43:32 +02:00
Duncan Ogilvie dabffeaed9 Add back the option name as a named condition 2024-07-06 14:43:32 +02:00
Duncan Ogilvie 59fe5c38b8 Consider PROJECT_OPTION to be a valid condition 2024-07-06 14:43:32 +02:00
Duncan Ogilvie dcdc7ac410 Add a few more default named conditions 2024-07-06 14:43:32 +02:00
Duncan Ogilvie 88377a8bfb Bump to 0.2.32 2024-07-06 14:03:55 +02:00
Duncan Ogilvie 3a9685be82 Merge pull request #145 from build-cpp/system-bug
Fix uninitialized 'system' field for fetch-content
2024-07-06 14:03:08 +02:00
Duncan Ogilvie 5576789c18 Fix uninitialized 'system' field for fetch-content 2024-07-06 14:02:33 +02:00
Duncan Ogilvie a362978f99 Bump to 0.2.31 2024-06-21 00:33:33 +02:00
Duncan Ogilvie a2f33297e4 Merge pull request #144 from build-cpp/msvc-runtime-subproject
Do not set CMAKE_MSVC_RUNTIME_LIBRARY if it's already set
2024-06-21 00:32:50 +02:00
Duncan Ogilvie 674c976647 Do not set CMAKE_MSVC_RUNTIME_LIBRARY if it's already set 2024-06-21 00:32:30 +02:00
Duncan Ogilvie 714a666e88 Merge pull request #143 from build-cpp/project-improvements
Project improvements
2024-06-01 01:25:26 +02:00
Duncan Ogilvie d613e433d5 Skip linting on pull requests for the same repository 2024-06-01 00:55:31 +02:00
Duncan Ogilvie 7c828d8740 Add custom targets for running cmkr/tests 2024-06-01 00:55:31 +02:00
Duncan Ogilvie 559f750c89 Fix undefined behavior with std::tolower/toupper 2024-06-01 00:55:29 +02:00
Duncan Ogilvie 4b6b72874e Remove nlohmann_json 2024-05-31 22:45:27 +02:00
Duncan Ogilvie 6bffa7cc71 Bump to 0.2.30 2024-05-31 22:36:39 +02:00
Duncan Ogilvie f415b432ed Also run linting on pull requests 2024-05-31 22:34:27 +02:00
Duncan Ogilvie 6c46664336 Merge pull request #142 from anthonyprintup/globbing-extension-fix
Fixed globbing when multiple extensions are present in the file name
2024-05-31 22:31:18 +02:00
Duncan Ogilvie f32aac63aa Review improvements 2024-05-31 22:24:01 +02:00
Anthony Printup 33d4cc4156 Fixed globbing when multiple extensions are present in the file name 2024-05-30 00:36:14 +02:00
Duncan Ogilvie 9288c8a87d Bump to 0.2.29 2024-04-15 03:08:33 +02:00
Duncan Ogilvie e36eee4420 Merge pull request #140 from build-cpp/improved-conditions
Allow arbitrary CMake expressions as conditions
2024-04-15 03:08:02 +02:00
Duncan Ogilvie 53820c9f65 Support $<condition> in unnamed conditions 2024-04-15 03:01:51 +02:00
Duncan Ogilvie ff7e4b8f23 Allow arbitrary CMake expressions as conditions 2024-04-15 02:12:02 +02:00
Duncan Ogilvie 1072cb44e2 Bump to 0.2.28 2024-04-14 00:08:11 +02:00
Duncan Ogilvie 926fc15fa2 Merge pull request #139 from build-cpp/vcpkg-bump
Bump to the latest vcpkg
2024-04-14 00:06:00 +02:00
Duncan Ogilvie e2c929adb0 Fix out-of-the-box vcpkg experience on macos 2024-04-13 23:57:30 +02:00
Duncan Ogilvie 0dec7ca4d5 Bump to the latest vcpkg 2024-04-13 23:21:25 +02:00
Duncan Ogilvie 45e346b4a3 Bump to 0.2.27 2024-03-28 11:38:01 +01:00
Duncan Ogilvie 7165986190 Merge pull request #138 from build-cpp/find-package-first
Generate find-package before fetch-content
2024-03-28 11:37:31 +01:00
Duncan Ogilvie be0ef6d615 Generate find-package before fetch-content 2024-03-28 11:36:15 +01:00
Duncan Ogilvie d607b9028c Bump to 0.2.26 2023-11-09 13:32:05 +01:00
Duncan Ogilvie 099b14552c Merge pull request #131 from build-cpp/fetch-subdir
Add [fetch-content].subdir
2023-11-09 13:31:48 +01:00
Duncan Ogilvie 771c80a41a Add [fetch-content].subdir
Closes #98
2023-11-09 13:28:29 +01:00
Duncan Ogilvie 58c7de1d60 Merge pull request #129 from build-cpp/gitignore-improvement
Improve the default .gitignore that's generated
2023-10-18 13:22:44 +02:00
Duncan Ogilvie a61e4bb999 Merge pull request #128 from build-cpp/language-documentation
Document the supported languages
2023-10-18 13:22:32 +02:00
Duncan Ogilvie 47aaeaf8ce Document the supported languages 2023-10-18 12:27:04 +02:00
Duncan Ogilvie 62609a0088 Improve the default .gitignore that's generated 2023-10-18 12:26:38 +02:00
Duncan Ogilvie e0d8a085db Merge pull request #121 from anthonyprintup/relative-paths
Added support for relative paths in `link-libraries`
2023-09-22 16:13:03 +02:00
Duncan Ogilvie 56da4144ae Merge pull request #125 from anthonyprintup/fix-124
fix(generator): Prevent calling `std::string::back` on an empty string
2023-09-22 16:12:20 +02:00
Duncan Ogilvie 9388b3f29d Merge pull request #123 from anthonyprintup/quotes-fix
Prevent wrapping test command arguments in quotes
2023-09-22 16:12:07 +02:00
Anthony Printup 079644cfeb fix(generator): Prevent calling std::string::back on an empty string
Fixes #124
2023-09-20 02:34:02 +02:00
Anthony Printup a7ca9f04c0 fix(relative-paths): Replaced has_parent_path with a simpler path check 2023-09-20 00:35:41 +02:00
Anthony Printup 339c2aac94 fix(generator): Prevent command arguments from being quoted when generating tests
Fixes #122
2023-09-18 18:36:58 +02:00
Anthony Printup c573c9a76d test(relative-paths): Add the test-library file to libs 2023-09-18 17:49:21 +02:00
Anthony Printup b24a0a2fdc test(relative-paths): Make link-libraries conditional to the Windows platform 2023-09-18 17:49:20 +02:00
Anthony Printup 854e8817c4 test(relative-paths): Remove inlined CMake from cmake.toml 2023-09-18 17:49:11 +02:00
Anthony Printup 1c2947b2fc fix(relative-paths): Prevent processing paths which may contain CMake macros, added a check to see if the library that's being linked exists on disk 2023-09-18 17:35:46 +02:00
Anthony Printup 19e61aa1aa test(relative-paths): Attempt to fix the tests workflow 2023-09-18 16:41:37 +02:00
Anthony Printup bfa1e1fe0d test(relative-paths): Added the latest relative-paths test to the tests workflow 2023-09-18 15:49:17 +02:00
Anthony Printup 56bd78f7ad feat(project-parser): Added support for relative paths in link-libraries
Fixes #116
2023-09-18 15:44:44 +02:00
Anthony Printup 4362b3547f test(relative-paths): Added tests for #116 2023-09-18 15:43:46 +02:00
Duncan Ogilvie 08204d9847 Bump to 0.2.25 2023-09-16 18:51:26 +02:00
Duncan Ogilvie 2202aa8173 Merge pull request #120 from anthonyprintup/new-lines-fix
Trim additional newline characters at the end of CMakeLists.txt
2023-09-16 18:49:45 +02:00
Anthony Printup d3829fb6cd Trim additional new lines at the end of the generated CMakeLists.txt 2023-09-16 18:49:30 +02:00
Duncan Ogilvie 3fb095210a Merge pull request #118 from ZehMatt/vcpkg-errors
Report better error messages for vcpkg projects and features
2023-08-25 22:21:52 +02:00
ζeh Matt 9f99365a25 Report better error messages for vcpkg projects and features 2023-08-25 15:58:24 +03:00
Duncan Ogilvie be387141b5 Add a 'Compiler flags' example to the documentation 2023-07-09 19:26:07 +02:00
Duncan Ogilvie 09ded38f70 Merge pull request #115 from build-cpp/clang-cl-condition
Add `clang-cl` and `clang-any` conditions
2023-07-09 18:01:06 +02:00
Duncan Ogilvie ad90b1ad3e Add 'clang-cl' and 'clang-any' conditions 2023-07-09 16:20:05 +02:00
Duncan Ogilvie 5bfa03d311 Bump to 0.2.24 2023-06-12 19:12:47 +02:00
Duncan Ogilvie bdd9d393d6 Merge pull request #113 from build-cpp/editorconfig
Add `.editorconfig` and linting
2023-06-12 18:28:12 +02:00
Duncan Ogilvie 1deaec2b41 Add .editorconfig and linting
Closes #112
2023-06-12 18:26:13 +02:00
Duncan Ogilvie cfee3bbc14 Merge pull request #111 from anthonyprintup/fetch-content-system
Fix #110
2023-06-12 17:48:54 +02:00
Anthony Printup bcaa60cabe feat: Added SYSTEM flag support to fetch-content 2023-06-12 15:41:20 +02:00
Duncan Ogilvie 7b1d33395e Bump to 0.2.23 2023-03-25 11:25:18 +00:00
Duncan Ogilvie 240fafc102 Merge pull request #101 from build-cpp/minor-cleanup
Cleanup
2023-03-25 11:24:44 +00:00
Duncan Ogilvie 7a7ddf2699 Speed up the pipeline by using Ninja 2023-03-25 11:19:48 +00:00
Duncan Ogilvie 605a04e72d Fix formatting of files 2023-03-24 11:07:02 +00:00
Duncan Ogilvie fd7f078127 Add workflow for checking clang-format 2023-03-24 11:04:58 +00:00
Duncan Ogilvie ee0e0d71d9 Remove a bunch of dead code 2023-03-24 11:03:45 +00:00
Duncan Ogilvie 9d6897b572 Suppress warnings related to DOWNLOAD_EXTRACT_TIMESTAMP 2023-03-24 11:03:40 +00:00
Duncan Ogilvie f8c34e5545 Error when [vcpkg] is used from a non-root project 2023-03-24 10:43:17 +00:00
Duncan Ogilvie e6d783ea20 Fix a few clang-tidy warnings 2023-03-24 10:41:59 +00:00
Duncan Ogilvie ee7fe38a7b Merge pull request #100 from build-cpp/include-subdir-bugfix
Fix a bug where includes in a subdir would not work
2023-03-24 10:13:30 +00:00
Duncan Ogilvie 66b2aad843 Fix a bug where includes in a subdir would not work 2023-03-24 10:04:32 +00:00
Duncan Ogilvie d2e376080a Bump to 0.2.22 2023-03-09 21:36:11 +01:00
Duncan Ogilvie 634908c651 Merge pull request #97 from build-cpp/cmkr-init-regression
Fix a regression where cmkr init wouldn't create any source files
2023-03-09 21:35:25 +01:00
Duncan Ogilvie 33911f3f1b Fix a regression where cmkr init wouldn't create any source files 2023-03-09 21:35:11 +01:00
Duncan Ogilvie e650073bef Bump to 0.2.21 2023-03-08 09:48:40 +01:00
Duncan Ogilvie 96e44f7771 Merge pull request #96 from build-cpp/check-sources
Improve error messages and check if specified sources exist
2023-03-08 09:47:43 +01:00
Duncan Ogilvie cb9ad5cdb3 Improve error messages and check if specified sources exist 2023-03-08 09:41:40 +01:00
Duncan Ogilvie c785b540d3 Document target templates 2023-03-08 09:01:39 +01:00
Duncan Ogilvie 275b73eefa Remove debug print 2023-03-02 08:43:45 +01:00
Duncan Ogilvie ea49a3acb7 Bump to 0.2.20 2023-02-28 21:31:18 +01:00
Duncan Ogilvie 257e14c869 Merge pull request #93 from build-cpp/gitattributes
Automatically generate .gitattributes and .gitignore with cmkr init
2023-02-28 21:30:34 +01:00
Duncan Ogilvie 7508816fe7 Merge pull request #94 from build-cpp/user-experience
Add a special "root" value for `[options]`
2023-02-28 21:27:11 +01:00
Duncan Ogilvie 45678bc5bc Automatically generate .gitattributes and .gitignore with cmkr init 2023-02-28 21:26:07 +01:00
Duncan Ogilvie b869e5646f Add a special "root" value for [options] 2023-02-28 19:34:31 +01:00
Duncan Ogilvie a499df84b1 Bump to 0.2.19 2023-02-28 17:11:55 +01:00
Duncan Ogilvie 49440f99e0 Merge pull request #92 from build-cpp/improved-options
Improve and document the `[options]` feature
2023-02-20 02:13:50 +01:00
Duncan Ogilvie 0c19c3da0c Improve the code related to [options] 2023-02-20 02:09:36 +01:00
Duncan Ogilvie 233cadadd0 Merge pull request #90 from mike1k/sanity
Error on unknown language & unacceptable source file.
2023-02-20 01:31:47 +01:00
Duncan Ogilvie 58a5a935e5 Add a bunch of missing languages and extensions and refactor 2023-02-20 01:18:48 +01:00
Duncan Ogilvie e69427bf94 Merge pull request #91 from build-cpp/clang-condition
Fix the `clang` condition and CI improvements
2023-02-19 22:30:15 +01:00
Duncan Ogilvie bc6359805d Change the clang condition to not detect clang-cl
References:
- https://github.com/cursey/safetyhook/issues/18
- https://discourse.cmake.org/t/clang-on-windows-detected-with-msvc-interface/3470
2023-02-19 22:23:34 +01:00
Duncan Ogilvie 8dcc11e349 Add helper function Project::cmake_minimum_version for version-dependent features 2023-02-19 22:19:12 +01:00
Duncan Ogilvie 51dc49e6f1 Improve CI performance for non-tagged builds 2023-02-19 20:06:58 +01:00
mike 7d27c28b59 Fixed failing tests due to implicit project languages (internal list empty) 2023-02-09 10:53:48 -06:00
Duncan Ogilvie ae6bea3b58 Improve reference documentation 2023-01-28 11:57:22 +01:00
Duncan Ogilvie 5a0eda7abc Automatically generate release notes 2023-01-15 13:34:36 +01:00
Duncan Ogilvie f17923c18b Bump to 0.2.18 2023-01-14 21:28:17 +01:00
Duncan Ogilvie ad17890e23 Merge pull request #85 from build-cpp/settings-rename
Rename `[settings]` to `[variables]`
2023-01-14 21:14:12 +01:00
Duncan Ogilvie c0b98b3ef4 Add documentation for the [variables] section 2023-01-14 18:12:57 +01:00
Duncan Ogilvie 2c6fc569af Preserve backwards compatibility 2023-01-14 16:17:06 +01:00
Duncan Ogilvie 12ee23a44c Improve error messages 2023-01-14 15:52:19 +01:00
Duncan Ogilvie 82342a6b6f Rename [settings] to [variables] 2023-01-14 15:51:57 +01:00
Duncan Ogilvie 1d95fab0ce Switch to giscus for documentation comments 2023-01-02 14:56:38 +01:00
Duncan Ogilvie 44a77329bf Merge pull request #83 from build-cpp/document-basics
Document basics
2023-01-02 12:43:24 +01:00
Duncan Ogilvie e68c5fccdc Add utteranc.es comments 2023-01-02 12:43:20 +01:00
Duncan Ogilvie e2722d2c09 Initial draft of new documentation 2023-01-02 12:02:24 +01:00
Duncan Ogilvie 2627864383 Merge pull request #78 from build-cpp/fix-tests
Successfully fail when running cmkr subcommands
2022-11-29 10:11:45 +01:00
Duncan Ogilvie 05e21f734a Fix the tests 2022-11-29 10:06:34 +01:00
Duncan Ogilvie 1fd18503cd Successfully fail when running cmkr subcommands 2022-11-24 00:32:31 +01:00
Duncan Ogilvie 8b19441d34 Bump to 0.2.17 2022-11-24 00:31:42 +01:00
Duncan Ogilvie 2437eb90fe Minor improvements
- Drastically improve quality of generated CMake
- Fix a regression with recursive globbing in the root
- Automatically include CSharpUtilities when using CSharp
2022-11-24 00:23:30 +01:00
Duncan Ogilvie 6e4006ec07 Fix typo in the docs 2022-10-25 00:59:58 +02:00
Duncan Ogilvie 697b638723 Fix warning on macos 2022-10-11 14:19:29 +02:00
Duncan Ogilvie 109c4bc99f Bump to 0.2.16 2022-10-08 10:48:16 +02:00
Duncan Ogilvie cad85f0bb1 Merge pull request #70 from build-cpp/fix-msvc-runtime
Actually generate the set(CMAKE_MSVC_RUNTIME_LIBRARY)
2022-10-08 10:47:56 +02:00
Duncan Ogilvie 53c88ceafa Actually generate the set(CMAKE_MSVC_RUNTIME_LIBRARY)
Closes #69 (nice)
2022-10-08 10:37:27 +02:00
Duncan Ogilvie d2aa15b1c7 Bump to 0.2.15 2022-10-07 22:21:07 +02:00
Duncan Ogilvie e6ded077cf Merge pull request #65 from gmh5225/feature-msvc-static
[feature] msvc-static
2022-10-07 22:20:36 +02:00
Duncan Ogilvie 3615ccab94 Document msvc-runtime feature 2022-10-07 22:15:32 +02:00
Duncan Ogilvie 73622aa5ba Remove the add_test hook to generate tests the same on all platforms 2022-10-07 22:09:54 +02:00
Duncan Ogilvie 69d844a152 Refactor msvc-static to msvc-runtime 2022-10-07 17:46:36 +02:00
gmh5225 af9a117f50 Fix merge 2022-10-07 06:50:26 +08:00
gmh5225 5fe8220728 Merge branch 'feature-msvc-static' of https://github.com/gmh5225/cmkr into feature-msvc-static 2022-10-07 06:41:43 +08:00
gmh5225 28f541cd3c [feature] add CMP0091 2022-10-07 06:41:11 +08:00
gmh5225 2f3fd7b95e Merge branch 'main' into feature-msvc-static 2022-10-07 05:35:11 +08:00
Duncan Ogilvie 07d99c582d Merge pull request #68 from build-cpp/headers-crash
Fix the way target.headers is merged into target.sources
2022-10-06 18:30:13 +02:00
Duncan Ogilvie 5af2385cc3 Fix the way target.headers is merged into target.sources
- It would crash if you did not specify target.sources
- Headers with condition would be merged incorrectly
2022-10-06 18:22:51 +02:00
gmh5225 981c48dbc5 [feature] msvc-static 2022-10-02 10:43:32 +08:00
Duncan Ogilvie 153bdbe591 Bump to 0.2.14 2022-07-19 14:17:47 +02:00
Duncan Ogilvie 97f1c5c1cc Fix a bug when there are regex characters in the path
Closes #61
2022-07-19 14:05:47 +02:00
Duncan Ogilvie 5b6d9c3826 Replace illegal characters in the project name with _ when doing cmkr init 2022-07-19 13:42:56 +02:00
Duncan Ogilvie a90988b81a Update the formatting to now allow functions on a single line
This makes it less annoying when the IDE is auto-formatting while you type
2022-07-19 13:41:43 +02:00
Duncan Ogilvie 3a1298f4e8 Merge pull request #60 from pmeerw/fix-warning
error: fix warning, signedness of comparison
2022-06-28 19:47:39 +02:00
Peter Meerwald-Stadler 534f955827 error: fix warning, signedness of comparison
cmkr/src/error.cpp:23:24: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
   23 |     assert(i >= 0 && i < (sizeof(err_string) / sizeof(*(err_string))));
2022-06-28 18:21:15 +02:00
Duncan Ogilvie ef537ce084 Bump to 0.2.13 2022-06-01 19:27:03 +02:00
Duncan Ogilvie 9cdd0f7344 Escape lists when generating commands 2022-06-01 19:26:41 +02:00
Duncan Ogilvie e69cf4d2b9 Add install.optional flag 2022-06-01 19:06:53 +02:00
Duncan Ogilvie e98a906231 Document the install.component option 2022-06-01 16:59:54 +02:00
Duncan Ogilvie 9a82f8c796 Temporarily remove the crt-linkage and library-linkage options
These require a lot more work to integrate properly with vcpkg, reimplement triplet detection and set a custom triplet
2022-06-01 16:57:09 +02:00
Duncan Ogilvie 13255c68cf Use FetchContent_MakeAvailable for vcpkg in case they add CMakeLists.txt 2022-06-01 16:53:38 +02:00
Duncan Ogilvie 5768460827 Update credits 2022-04-08 18:16:38 +02:00
Duncan Ogilvie 50d4a905b6 Merge pull request #55 from ZehMatt/fix/#54
Fix #54: Fix settings not being properly quoted
2022-04-01 12:49:02 +02:00
ζeh Matt f957cec2dc Update CMakeLists.txt for tests 2022-04-01 03:37:04 +03:00
Duncan Ogilvie 232e49e087 Add support for vcpkg CRT and library linkage customization 2022-04-01 02:27:41 +02:00
ζeh Matt 7408d42160 Fix #54: Fix settings not being properly quoted 2022-04-01 03:15:32 +03:00
124 changed files with 5779 additions and 26963 deletions
+4 -3
View File
@@ -10,16 +10,17 @@ AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: true AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false
AllowShortLambdasOnASingleLine: None
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true AlwaysBreakTemplateDeclarations: true
BinPackArguments: true BinPackArguments: true
BinPackParameters: true BinPackParameters: true
BraceWrapping: BraceWrapping:
AfterClass: false AfterClass: false
AfterControlStatement: false AfterControlStatement: false
AfterEnum: false AfterEnum: false
@@ -72,7 +73,7 @@ PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60 PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right PointerAlignment: Right
ReflowComments: true ReflowComments: true
SortIncludes: true SortIncludes: false
SortUsingDeclarations: true SortUsingDeclarations: true
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true SpaceAfterTemplateKeyword: true
+24
View File
@@ -0,0 +1,24 @@
root = true
[*]
end_of_line = lf
trim_trailing_whitespace = true
charset = utf-8
[*.{c,h,cpp,hpp,toml}]
indent_style = space
insert_final_newline = true
[{CMakeLists.txt, *.cmake}]
indent_style = tab
tab_width = 8
insert_final_newline = true
# Exclude the third_party folder
[/third_party/**]
charset = unset
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset
indent_style = unset
indent_size = unset
+16 -9
View File
@@ -1,21 +1,25 @@
name: CMake name: build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: cmake:
# Skip building pull requests from the same repository # Skip building pull requests from the same repository
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }} if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [windows-2019, macos-10.15, ubuntu-20.04] os: [windows-2022, macos-latest, ubuntu-22.04]
env: env:
BUILD_TYPE: Release BUILD_TYPE: 'Release'
CMAKE_GENERATOR: 'Ninja'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Visual Studio Development Environment
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.1
- name: Tag cmkr.cmake - name: Tag cmkr.cmake
if: ${{ startsWith(github.ref, 'refs/tags/') }} if: ${{ startsWith(github.ref, 'refs/tags/') }}
@@ -38,28 +42,31 @@ jobs:
ctest -C ${{ env.BUILD_TYPE }} --verbose ctest -C ${{ env.BUILD_TYPE }} --verbose
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: ${{ github.event.repository.name }}-${{ matrix.os }} name: ${{ github.event.repository.name }}-${{ matrix.os }}
path: install/bin/* path: install/bin/*
- name: Get lowercase OS name - name: Get lowercase OS name
id: osname id: osname
uses: ASzc/change-string-case-action@v1 uses: ASzc/change-string-case-action@ccb130a4e483d3e86287289183704dc9bf53e77e # master 2024-04-05
if: ${{ startsWith(github.ref, 'refs/tags/') }}
with: with:
string: ${{ runner.os }} string: ${{ runner.os }}
- name: Compress artifacts - name: Compress artifacts
uses: vimtor/action-zip@v1 uses: vimtor/action-zip@1379ea20d4c5705669ba81fd626dd01b1c738f26 # v1.2
if: ${{ startsWith(github.ref, 'refs/tags/') }}
with: with:
files: install/bin/ files: install/bin/
dest: ${{ github.event.repository.name }}-${{ steps.osname.outputs.lowercase }}.zip dest: ${{ github.event.repository.name }}-${{ steps.osname.outputs.lowercase }}.zip
- name: Release - name: Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2
if: ${{ startsWith(github.ref, 'refs/tags/') }} if: ${{ startsWith(github.ref, 'refs/tags/') }}
with: with:
prerelease: ${{ !startsWith(github.ref, 'refs/tags/v') || contains(github.ref, '-pre') }} prerelease: ${{ !startsWith(github.ref, 'refs/tags/v') || contains(github.ref, '-pre') }}
files: ${{ github.event.repository.name }}-${{ steps.osname.outputs.lowercase }}.zip files: ${{ github.event.repository.name }}-${{ steps.osname.outputs.lowercase }}.zip
generate_release_notes: true
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+41
View File
@@ -0,0 +1,41 @@
name: lint
on: [push, pull_request]
jobs:
clang-format:
# Skip building pull requests from the same repository
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: clang-format
id: clang-format
uses: DoozyX/clang-format-lint-action@c71d0bf4e21876ebec3e5647491186f8797fde31 # v0.18.2
with:
exclude: './third_party'
extensions: 'c,h,cpp,hpp'
clangFormatVersion: 15
style: file
- name: clang-format instructions
if: ${{ failure() && steps.clang-format.outcome == 'failure' }}
run: |
# Instructions for fixing the formatting errors
echo -e "\n\033[0;31mTo fix the formatting, run:\nclang-format -style=file -i \$(git ls-files \"*.c\" \"*.h\" \"*.cpp\" \"*.hpp\")\033[0m\n"
exit 1
editorconfig:
# Skip building pull requests from the same repository
if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run editorconfig-checker
uses: editorconfig-checker/action-editorconfig-checker@27dd658c2b1282c7f1f4dc242cdf0f6d8af728ab # master 2025-05-30
+2
View File
@@ -9,3 +9,5 @@ build*/
.idea/ .idea/
cmake-build*/ cmake-build*/
CMakeLists.txt.user CMakeLists.txt.user
.vscode/
.DS_Store
+25 -55
View File
@@ -1,23 +1,20 @@
# This file is automatically generated from cmake.toml - DO NOT EDIT # This file is automatically generated from cmake.toml - DO NOT EDIT
# See https://github.com/build-cpp/cmkr for more information # See https://github.com/build-cpp/cmkr for more information
cmake_minimum_required(VERSION 2.8...3.8) cmake_minimum_required(VERSION 2.8...3.31)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build") message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build")
endif() endif()
# Regenerate CMakeLists.txt automatically in the root project
set(CMKR_ROOT_PROJECT OFF) set(CMKR_ROOT_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CMKR_ROOT_PROJECT ON) set(CMKR_ROOT_PROJECT ON)
# Enable folder support # Enable folder support
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
endif()
# Create a configure-time dependency on cmake.toml to improve IDE support # Create a configure-time dependency on cmake.toml to improve IDE support
if(CMKR_ROOT_PROJECT)
configure_file(cmake.toml cmake.toml COPYONLY) configure_file(cmake.toml cmake.toml COPYONLY)
endif() endif()
@@ -25,7 +22,7 @@ project(cmkr
LANGUAGES LANGUAGES
CXX CXX
VERSION VERSION
0.2.12 0.2.46
DESCRIPTION DESCRIPTION
"CMakeLists generator from TOML" "CMakeLists generator from TOML"
) )
@@ -33,7 +30,7 @@ project(cmkr
include("cmake/generate_documentation.cmake") include("cmake/generate_documentation.cmake")
include("cmake/generate_resources.cmake") include("cmake/generate_resources.cmake")
# third_party # Subdirectory: third_party
set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER}) set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER})
if(CMAKE_FOLDER) if(CMAKE_FOLDER)
set(CMAKE_FOLDER "${CMAKE_FOLDER}/third_party") set(CMAKE_FOLDER "${CMAKE_FOLDER}/third_party")
@@ -43,7 +40,7 @@ endif()
add_subdirectory(third_party) add_subdirectory(third_party)
set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER}) set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER})
# tests # Subdirectory: tests
set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER}) set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER})
if(CMAKE_FOLDER) if(CMAKE_FOLDER)
set(CMAKE_FOLDER "${CMAKE_FOLDER}/tests") set(CMAKE_FOLDER "${CMAKE_FOLDER}/tests")
@@ -53,64 +50,35 @@ endif()
add_subdirectory(tests) add_subdirectory(tests)
set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER}) set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER})
# Target: cmkr_generate_documentation
# Target cmkr_generate_documentation
set(CMKR_TARGET cmkr_generate_documentation)
set(cmkr_generate_documentation_SOURCES "")
set(CMKR_SOURCES ${cmkr_generate_documentation_SOURCES})
add_library(cmkr_generate_documentation INTERFACE) add_library(cmkr_generate_documentation INTERFACE)
if(cmkr_generate_documentation_SOURCES) set(CMKR_TARGET cmkr_generate_documentation)
target_sources(cmkr_generate_documentation INTERFACE ${cmkr_generate_documentation_SOURCES})
endif()
generate_documentation() generate_documentation()
unset(CMKR_TARGET) # Target: cmkr
unset(CMKR_SOURCES) set(cmkr_SOURCES
cmake.toml
# Target cmkr "cmake/cmkr.cmake"
set(CMKR_TARGET cmkr) "cmake/version.hpp.in"
set(cmkr_SOURCES "")
list(APPEND cmkr_SOURCES
"src/arguments.cpp"
"src/build.cpp"
"src/cmake_generator.cpp"
"src/error.cpp"
"src/help.cpp"
"src/main.cpp"
"src/project_parser.cpp"
"include/arguments.hpp" "include/arguments.hpp"
"include/build.hpp" "include/build.hpp"
"include/cmake_generator.hpp" "include/cmake_generator.hpp"
"include/error.hpp"
"include/fs.hpp" "include/fs.hpp"
"include/help.hpp" "include/help.hpp"
"include/literals.hpp" "include/literals.hpp"
"include/project_parser.hpp" "include/project_parser.hpp"
"cmake/cmkr.cmake" "src/arguments.cpp"
"cmake/version.hpp.in" "src/build.cpp"
"src/cmake_generator.cpp"
"src/help.cpp"
"src/main.cpp"
"src/project_parser.cpp"
) )
list(APPEND cmkr_SOURCES
cmake.toml
)
set(CMKR_SOURCES ${cmkr_SOURCES})
add_executable(cmkr) add_executable(cmkr)
if(cmkr_SOURCES) target_sources(cmkr PRIVATE ${cmkr_SOURCES})
target_sources(cmkr PRIVATE ${cmkr_SOURCES})
endif()
get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT)
if(NOT CMKR_VS_STARTUP_PROJECT)
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT cmkr)
endif()
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${cmkr_SOURCES}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${cmkr_SOURCES})
target_compile_features(cmkr PRIVATE target_compile_features(cmkr PRIVATE
@@ -126,13 +94,15 @@ target_link_libraries(cmkr PRIVATE
ghc_filesystem ghc_filesystem
mpark_variant mpark_variant
ordered_map ordered_map
nlohmann_json
) )
generate_resources(${CMKR_TARGET}) get_directory_property(CMKR_VS_STARTUP_PROJECT DIRECTORY ${PROJECT_SOURCE_DIR} DEFINITION VS_STARTUP_PROJECT)
if(NOT CMKR_VS_STARTUP_PROJECT)
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT cmkr)
endif()
unset(CMKR_TARGET) set(CMKR_TARGET cmkr)
unset(CMKR_SOURCES) include("cmake/custom_targets.cmake")
install( install(
TARGETS TARGETS
+18 -13
View File
@@ -1,5 +1,7 @@
# cmkr # cmkr
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/build-cpp/cmkr)
`cmkr`, pronounced "cmaker", is a modern build system based on [CMake](https://cmake.org/) and [TOML](https://toml.io). `cmkr`, pronounced "cmaker", is a modern build system based on [CMake](https://cmake.org/) and [TOML](https://toml.io).
`cmkr` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example: `cmkr` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example:
@@ -13,27 +15,29 @@ type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
``` ```
`cmkr` can bootstrap itself from CMake and you only need CMake to use it. `cmkr` can bootstrap itself and you only need CMake and a C++ compiler to use it.
## Getting started ## Getting started
To get started run the following commands from your project directory: To get started, run the following commands from your project directory:
```sh ```sh
curl https://raw.githubusercontent.com/build-cpp/cmkr/main/cmake/cmkr.cmake -o cmkr.cmake curl https://raw.githubusercontent.com/build-cpp/cmkr/main/cmake/cmkr.cmake -o cmkr.cmake
cmake -P cmkr.cmake cmake -P cmkr.cmake
``` ```
After the bootstrapping process finishes, modify [`cmake.toml`](https://build-cpp.github.io/cmkr/cmake-toml) and open the project in your favorite IDE or build with CMake: After the bootstrapping process finishes, customize [`cmake.toml`](https://build-cpp.github.io/cmkr/cmake-toml) for your project and run CMake:
```sh ```sh
cmake -B build cmake -B build
cmake --build build cmake --build build
``` ```
Once bootstrapped, `cmkr` does not introduce extra steps to your workflow. After modifying `cmake.toml` you simply build/configure your CMake project and `cmkr` will automatically regenerate `CMakeLists.txt`. Once bootstrapped, `cmkr` does not introduce extra steps to your workflow. After modifying `cmake.toml` you simply build/configure your CMake project and `cmkr` will automatically regenerate `CMakeLists.txt` when necessary.
In CI settings the `cmkr` bootstrapping process is skipped so there is no extra configure-time overhead in your pipelines. <sub>**Note**: The `cmake.toml` project file, generated `CMakeLists.txt` and `cmkr.cmake` bootstrapping script are all intended to be added to source control.</sub>
In CI environments the `cmkr` bootstrapping process is skipped, so there is no additional overhead in your pipelines.
## Template repositories ## Template repositories
@@ -53,10 +57,10 @@ Optionally you can put a [`cmkr` release](https://github.com/build-cpp/cmkr/rele
``` ```
Usage: cmkr [arguments] Usage: cmkr [arguments]
arguments: arguments:
init [executable|library|shared|static|interface] Starts a new project in the same directory. init [executable|library|shared|static|interface] Create a project.
gen Generates CMakeLists.txt file. gen Generates CMakeLists.txt file.
build <extra cmake args> Run cmake and build. build <extra cmake args> Run cmake and build.
install Run cmake --install. Needs admin privileges. install Run cmake --install.
clean Clean the build directory. clean Clean the build directory.
help Show help. help Show help.
version Current cmkr version. version Current cmkr version.
@@ -64,9 +68,10 @@ arguments:
## Credits ## Credits
- https://github.com/gulrak/filesystem - [gulrak/filesystem](https://github.com/gulrak/filesystem)
- https://github.com/Tessil/ordered-map - [Tessil/ordered-map](https://github.com/Tessil/ordered-map)
- https://github.com/ToruNiina/toml11 - [ToruNiina/toml11](https://github.com/ToruNiina/toml11)
- https://github.com/mpark/variant - [mpark/variant](https://github.com/mpark/variant)
- https://www.svgrepo.com/svg/192268/hammer - [SVG Repo Hammer](https://www.svgrepo.com/svg/192268/hammer)
- https://github.com/can1357 for buying `cmkr.build` ❤️ - [can1357](https://github.com/can1357) for buying `cmkr.build` ❤️
- [JustasMasiulis](https://github.com/JustasMasiulis) for fixing the dark theme ❤️
+4 -7
View File
@@ -1,17 +1,17 @@
[cmake] [cmake]
version = "2.8...3.8" version = "2.8...3.31"
cmkr-include = false cmkr-include = false
[project] [project]
name = "cmkr" name = "cmkr"
version = "0.2.12" version = "0.2.46"
description = "CMakeLists generator from TOML" description = "CMakeLists generator from TOML"
languages = ["CXX"] languages = ["CXX"]
subdirs = ["third_party", "tests"]
include-after = [ include-after = [
"cmake/generate_documentation.cmake", "cmake/generate_documentation.cmake",
"cmake/generate_resources.cmake" "cmake/generate_resources.cmake"
] ]
subdirs = ["third_party", "tests"]
[target.cmkr_generate_documentation] [target.cmkr_generate_documentation]
type = "interface" type = "interface"
@@ -36,11 +36,8 @@ link-libraries = [
"ghc_filesystem", "ghc_filesystem",
"mpark_variant", "mpark_variant",
"ordered_map", "ordered_map",
"nlohmann_json",
] ]
cmake-after = """ include-after = ["cmake/custom_targets.cmake"]
generate_resources(${CMKR_TARGET})
"""
[[install]] [[install]]
targets = ["cmkr"] targets = ["cmkr"]
+77 -77
View File
@@ -1,78 +1,78 @@
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
if(NOT CMAKE_SCRIPT_MODE_FILE) if(NOT CMAKE_SCRIPT_MODE_FILE)
message(FATAL_ERROR "Usage: cmake -P bump_version.cmake [1.2.3]") message(FATAL_ERROR "Usage: cmake -P bump_version.cmake [1.2.3]")
endif() endif()
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml") if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
message(FATAL_ERROR "Cannot find cmake.toml") message(FATAL_ERROR "Cannot find cmake.toml")
endif() endif()
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake") if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake")
message(FATAL_ERROR "Cannot find cmkr.cmake") message(FATAL_ERROR "Cannot find cmkr.cmake")
endif() endif()
# Validate branch # Validate branch
find_package(Git REQUIRED) find_package(Git REQUIRED)
execute_process(COMMAND "${GIT_EXECUTABLE}" branch --show-current OUTPUT_VARIABLE GIT_BRANCH) execute_process(COMMAND "${GIT_EXECUTABLE}" branch --show-current OUTPUT_VARIABLE GIT_BRANCH)
string(STRIP "${GIT_BRANCH}" GIT_BRANCH) string(STRIP "${GIT_BRANCH}" GIT_BRANCH)
if(NOT GIT_BRANCH STREQUAL "main") if(NOT GIT_BRANCH STREQUAL "main")
message(FATAL_ERROR "You need to be on the main branch, you are on: ${GIT_BRANCH}") message(FATAL_ERROR "You need to be on the main branch, you are on: ${GIT_BRANCH}")
endif() endif()
file(READ "${CMAKE_SOURCE_DIR}/cmake.toml" CMAKE_TOML) file(READ "${CMAKE_SOURCE_DIR}/cmake.toml" CMAKE_TOML)
string(FIND "${CMAKE_TOML}" "[project]" PROJECT_INDEX) string(FIND "${CMAKE_TOML}" "[project]" PROJECT_INDEX)
string(SUBSTRING "${CMAKE_TOML}" ${PROJECT_INDEX} -1 CMAKE_TOML_PROJECT) string(SUBSTRING "${CMAKE_TOML}" ${PROJECT_INDEX} -1 CMAKE_TOML_PROJECT)
set(SEMVER_REGEX "([0-9]+)\\.([0-9]+)\\.([0-9]+)") set(SEMVER_REGEX "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
set(VERSION_REGEX "version = \"${SEMVER_REGEX}\"") set(VERSION_REGEX "version = \"${SEMVER_REGEX}\"")
if(CMAKE_TOML_PROJECT MATCHES "${VERSION_REGEX}") if(CMAKE_TOML_PROJECT MATCHES "${VERSION_REGEX}")
set(MAJOR "${CMAKE_MATCH_1}") set(MAJOR "${CMAKE_MATCH_1}")
set(MINOR "${CMAKE_MATCH_2}") set(MINOR "${CMAKE_MATCH_2}")
set(PATCH "${CMAKE_MATCH_3}") set(PATCH "${CMAKE_MATCH_3}")
set(OLDVERSION "${MAJOR}.${MINOR}.${PATCH}") set(OLDVERSION "${MAJOR}.${MINOR}.${PATCH}")
else() else()
message(FATAL_ERROR "Failed to match semantic version in cmake.toml") message(FATAL_ERROR "Failed to match semantic version in cmake.toml")
endif() endif()
if(CMAKE_ARGV3) if(CMAKE_ARGV3)
if(NOT CMAKE_ARGV3 MATCHES "${SEMVER_REGEX}") if(NOT CMAKE_ARGV3 MATCHES "${SEMVER_REGEX}")
message(FATAL_ERROR "Invalid semantic version number '${CMAKE_ARGV3}'") message(FATAL_ERROR "Invalid semantic version number '${CMAKE_ARGV3}'")
endif() endif()
set(NEWVERSION "${CMAKE_ARGV3}") set(NEWVERSION "${CMAKE_ARGV3}")
else() else()
math(EXPR NEWPATCH "${PATCH} + 1") math(EXPR NEWPATCH "${PATCH} + 1")
set(NEWVERSION "${MAJOR}.${MINOR}.${NEWPATCH}") set(NEWVERSION "${MAJOR}.${MINOR}.${NEWPATCH}")
endif() endif()
message(STATUS "Version ${OLDVERSION} -> ${NEWVERSION}") message(STATUS "Version ${OLDVERSION} -> ${NEWVERSION}")
find_program(CMKR_EXECUTABLE "cmkr" PATHS "${CMAKE_SOURCE_DIR}/build" PATH_SUFFIXES Debug Release RelWithDebInfo MinSizeRel NO_CACHE REQUIRED) find_program(CMKR_EXECUTABLE "cmkr" PATHS "${CMAKE_SOURCE_DIR}/build" PATH_SUFFIXES Debug Release RelWithDebInfo MinSizeRel NO_CACHE REQUIRED)
message(STATUS "Found cmkr: ${CMKR_EXECUTABLE}") message(STATUS "Found cmkr: ${CMKR_EXECUTABLE}")
# Replace version in cmake.toml # Replace version in cmake.toml
string(REPLACE "version = \"${OLDVERSION}\"" "version = \"${NEWVERSION}\"" CMAKE_TOML "${CMAKE_TOML}") string(REPLACE "version = \"${OLDVERSION}\"" "version = \"${NEWVERSION}\"" CMAKE_TOML "${CMAKE_TOML}")
file(CONFIGURE file(CONFIGURE
OUTPUT "${CMAKE_SOURCE_DIR}/cmake.toml" OUTPUT "${CMAKE_SOURCE_DIR}/cmake.toml"
CONTENT "${CMAKE_TOML}" CONTENT "${CMAKE_TOML}"
@ONLY @ONLY
NEWLINE_STYLE LF NEWLINE_STYLE LF
) )
# Run cmkr gen # Run cmkr gen
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen RESULT_VARIABLE CMKR_EXEC_RESULT) execute_process(COMMAND "${CMKR_EXECUTABLE}" gen RESULT_VARIABLE CMKR_EXEC_RESULT)
if(NOT CMKR_EXEC_RESULT EQUAL 0) if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "cmkr gen failed (exit code ${CMKR_EXEC_RESULT})") message(FATAL_ERROR "cmkr gen failed (exit code ${CMKR_EXEC_RESULT})")
endif() endif()
# Replace version in cmkr.cmake # Replace version in cmkr.cmake
file(READ "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake" CMKR_CMAKE) file(READ "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake" CMKR_CMAKE)
string(REGEX REPLACE "CMKR_TAG \"[^\"]+\"" "CMKR_TAG \"v${NEWVERSION}\"" CMKR_CMAKE "${CMKR_CMAKE}") string(REGEX REPLACE "CMKR_TAG \"[^\"]+\"" "CMKR_TAG \"v${NEWVERSION}\"" CMKR_CMAKE "${CMKR_CMAKE}")
file(CONFIGURE file(CONFIGURE
OUTPUT "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake" OUTPUT "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake"
CONTENT "${CMKR_CMAKE}" CONTENT "${CMKR_CMAKE}"
@ONLY @ONLY
NEWLINE_STYLE LF NEWLINE_STYLE LF
) )
# Print git commands # Print git commands
message(STATUS "Git commands to create new version:\ngit commit -a -m \"Bump to ${NEWVERSION}\"\ngit tag v${NEWVERSION}\ngit push origin main v${NEWVERSION}") message(STATUS "Git commands to create new version:\ngit commit -a -m \"Bump to ${NEWVERSION}\"\ngit tag v${NEWVERSION}\ngit push origin main v${NEWVERSION}")
+29 -5
View File
@@ -2,7 +2,7 @@ include_guard()
# Change these defaults to point to your infrastructure if desired # Change these defaults to point to your infrastructure if desired
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
set(CMKR_TAG "v0.2.12" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) set(CMKR_TAG "v0.2.46" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE) set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake # To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
@@ -58,9 +58,16 @@ else()
endif() endif()
# Use cached cmkr if found # Use cached cmkr if found
if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") if(DEFINED ENV{CMKR_CACHE})
set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}") set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}")
string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}") string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
if(CMKR_DIRECTORY_PREFIX MATCHES "^~")
if(WIN32)
string(REGEX REPLACE "^~" "$ENV{USERPROFILE}" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
elseif(UNIX)
string(REGEX REPLACE "^~" "$ENV{HOME}" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
endif()
endif()
if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$") if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$")
set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/") set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/")
endif() endif()
@@ -72,10 +79,27 @@ endif()
set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}") set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}")
set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}") set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}")
# Helper function to check if a string starts with a prefix
# Cannot use MATCHES, see: https://github.com/build-cpp/cmkr/issues/61
function(cmkr_startswith str prefix result)
string(LENGTH "${prefix}" prefix_length)
string(LENGTH "${str}" str_length)
if(prefix_length LESS_EQUAL str_length)
string(SUBSTRING "${str}" 0 ${prefix_length} str_prefix)
if(prefix STREQUAL str_prefix)
set("${result}" ON PARENT_SCOPE)
return()
endif()
endif()
set("${result}" OFF PARENT_SCOPE)
endfunction()
# Handle upgrading logic # Handle upgrading logic
if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE) if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE)
if(CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr") cmkr_startswith("${CMKR_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/_cmkr" CMKR_STARTSWITH_BUILD)
if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") cmkr_startswith("${CMKR_EXECUTABLE}" "${CMKR_DIRECTORY_PREFIX}" CMKR_STARTSWITH_CACHE)
if(CMKR_STARTSWITH_BUILD)
if(DEFINED ENV{CMKR_CACHE})
message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'") message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'")
if(EXISTS "${CMKR_CACHED_EXECUTABLE}") if(EXISTS "${CMKR_CACHED_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
@@ -86,7 +110,7 @@ if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE)
message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
unset(CMKR_EXECUTABLE CACHE) unset(CMKR_EXECUTABLE CACHE)
endif() endif()
elseif(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}" AND CMKR_EXECUTABLE MATCHES "^${CMKR_DIRECTORY_PREFIX}") elseif(DEFINED ENV{CMKR_CACHE} AND CMKR_STARTSWITH_CACHE)
message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
unset(CMKR_EXECUTABLE CACHE) unset(CMKR_EXECUTABLE CACHE)
endif() endif()
+18
View File
@@ -0,0 +1,18 @@
generate_resources(cmkr)
add_custom_target(regenerate-cmake
COMMAND "$<TARGET_FILE:cmkr>" gen
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
)
if(CMAKE_CONFIGURATION_TYPES)
add_custom_target(run-tests
COMMAND "${CMAKE_CTEST_COMMAND}" -C $<CONFIG>
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/tests"
)
else()
add_custom_target(run-tests
COMMAND "${CMAKE_CTEST_COMMAND}"
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/tests"
)
endif()
+17 -17
View File
@@ -1,21 +1,21 @@
option(CMKR_GENERATE_DOCUMENTATION "Generate cmkr documentation" ${CMKR_ROOT_PROJECT}) option(CMKR_GENERATE_DOCUMENTATION "Generate cmkr documentation" ${CMKR_ROOT_PROJECT})
set(CMKR_TESTS "" CACHE INTERNAL "List of test directories in the order declared in tests/cmake.toml")
if(CMKR_GENERATE_DOCUMENTATION)
# Hook the add_test function to capture the tests in the order declared in tests/cmake.toml
function(add_test)
cmake_parse_arguments(TEST "" "WORKING_DIRECTORY" "" ${ARGN})
get_filename_component(TEST_WORKING_DIRECTORY "${TEST_WORKING_DIRECTORY}" NAME)
list(APPEND CMKR_TESTS "${TEST_WORKING_DIRECTORY}")
set(CMKR_TESTS "${CMKR_TESTS}" CACHE INTERNAL "")
_add_test(${test} ${ARGN})
endfunction()
endif()
function(generate_documentation) function(generate_documentation)
if(CMKR_GENERATE_DOCUMENTATION) if(CMKR_GENERATE_DOCUMENTATION)
message(STATUS "[cmkr] Generating documentation...") message(STATUS "[cmkr] Generating documentation...")
# Extract the order of the tests
set(CMKR_TESTS "")
file(READ "${PROJECT_SOURCE_DIR}/tests/cmake.toml" tests_toml NO_HEX_CONVERSION)
string(REGEX MATCHALL "working-directory = \"([^\"]+)\"" tests_match "${tests_toml}")
foreach(match ${tests_match})
if(match MATCHES "working-directory = \"([^\"]+)\"")
list(APPEND CMKR_TESTS "${CMAKE_MATCH_1}")
else()
message(FATAL_ERROR "This should not happen (wrong regex?)")
endif()
endforeach()
# Delete previously generated examples # Delete previously generated examples
set(example_folder "${PROJECT_SOURCE_DIR}/docs/examples") set(example_folder "${PROJECT_SOURCE_DIR}/docs/examples")
file(GLOB example_files "${example_folder}/*.md") file(GLOB example_files "${example_folder}/*.md")
@@ -41,21 +41,21 @@ function(generate_documentation)
# Read cmake.toml file # Read cmake.toml file
file(READ "${test_toml}" test_contents NO_HEX_CONVERSION) file(READ "${test_toml}" test_contents NO_HEX_CONVERSION)
string(LENGTH "${test_contents}" toml_length) string(LENGTH "${test_contents}" toml_length)
# Extract header text # Extract header text
string(REGEX MATCH "^(\n*(#[^\n]+\n)+\n*)" EXAMPLE_HEADER "${test_contents}") string(REGEX MATCH "^(\n*(#[^\n]+\n)+\n*)" EXAMPLE_HEADER "${test_contents}")
string(LENGTH "${EXAMPLE_HEADER}" header_length) string(LENGTH "${EXAMPLE_HEADER}" header_length)
string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER) string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER)
string(REGEX REPLACE "\n# ?" "\n\n" EXAMPLE_HEADER "\n${EXAMPLE_HEADER}") string(REGEX REPLACE "\n# ?" "\n\n" EXAMPLE_HEADER "\n${EXAMPLE_HEADER}")
string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER) string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER)
# Extract footer text # Extract footer text
string(REGEX MATCH "(((#[^\n]+)(\n+|$))+)$" EXAMPLE_FOOTER "${test_contents}") string(REGEX MATCH "(((#[^\n]+)(\n+|$))+)$" EXAMPLE_FOOTER "${test_contents}")
string(LENGTH "${EXAMPLE_FOOTER}" footer_length) string(LENGTH "${EXAMPLE_FOOTER}" footer_length)
string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER) string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER)
string(REGEX REPLACE "\n# ?" "\n\n" EXAMPLE_FOOTER "\n${EXAMPLE_FOOTER}") string(REGEX REPLACE "\n# ?" "\n\n" EXAMPLE_FOOTER "\n${EXAMPLE_FOOTER}")
string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER) string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER)
# Extract toml body # Extract toml body
math(EXPR toml_length "${toml_length}-${header_length}-${footer_length}") math(EXPR toml_length "${toml_length}-${header_length}-${footer_length}")
string(SUBSTRING "${test_contents}" ${header_length} ${toml_length} EXAMPLE_TOML) string(SUBSTRING "${test_contents}" ${header_length} ${toml_length} EXAMPLE_TOML)
@@ -64,7 +64,7 @@ function(generate_documentation)
# Extract title from description # Extract title from description
if("${EXAMPLE_TOML}" MATCHES "description *= *\"([^\"]+)\"") if("${EXAMPLE_TOML}" MATCHES "description *= *\"([^\"]+)\"")
set(EXAMPLE_TITLE "${CMAKE_MATCH_1}") set(EXAMPLE_TITLE "${CMAKE_MATCH_1}")
# Generate documentation markdown page # Generate documentation markdown page
configure_file("${PROJECT_SOURCE_DIR}/cmake/example.md.in" "${example_folder}/${EXAMPLE_PERMALINK}.md" @ONLY NEWLINE_STYLE LF) configure_file("${PROJECT_SOURCE_DIR}/cmake/example.md.in" "${example_folder}/${EXAMPLE_PERMALINK}.md" @ONLY NEWLINE_STYLE LF)
else() else()
+6 -6
View File
@@ -1,7 +1,7 @@
namespace cmkr { namespace cmkr {
namespace resources { namespace resources {
static const char* @RESOURCE_NAME@ = R"RESOURCE(@RESOURCE_CONTENTS@)RESOURCE"; static const char* @RESOURCE_NAME@ = R"RESOURCE(@RESOURCE_CONTENTS@)RESOURCE";
} }
} }
+1 -1
View File
@@ -1 +1 @@
cmkr.build cmkr.build
+19 -1
View File
@@ -21,4 +21,22 @@ gh_edit_branch: "main"
gh_edit_view_mode: "edit" gh_edit_view_mode: "edit"
gh_edit_source: docs gh_edit_source: docs
production_url : https://cmkr.build ga_tracking: G-DY172KY7Z9
production_url : https://cmkr.build
footer_content: |
<script src="https://giscus.app/client.js"
data-repo="build-cpp/cmkr"
data-repo-id="MDEwOlJlcG9zaXRvcnkyOTQwMDc3MzY="
data-category="Documentation"
data-category-id="DIC_kwDOEYYzuM4CTXeA"
data-mapping="pathname"
data-strict="1"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="top"
data-theme="preferred_color_scheme"
data-lang="en"
crossorigin="anonymous"
async>
</script>
+143
View File
@@ -0,0 +1,143 @@
---
layout: page
title: Basics
nav_order: 1
---
# Basics
To effectively use cmkr it helps to understand the basic concepts of CMake. This page serves as an introduction to CMake for beginners. Links to the CMake documentation are included for reference.
## Projects
A CMake **project** is a collection of targets. In the context of libraries the project usually corresponds to the **package** that other projects can depend on.
<sub>Visual Studio: a CMake **project** corresponds to a _solution_.</sub>
## Targets
The basic unit of CMake is called a **target**. A target (also referred to as [binary target](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#binary-targets) in the CMake documentation) corresponds to an executable or static/dynamic library you can build.
<sub>Visual Studio: a **target** corresponds to a _project_.</sub>
Most important target types:
|Type|Purpose|
|-|-|
|Executable|Program you run on your computer (`.exe`)|
|Static library|Library code _compiled into_ the final executable (`.lib`, `.a`)|
|Dynamic library|Library code loaded at runtime (`.dll`, `.so`, `.dylib`)|
|Interface|Used for organizational purposes (common flags/includes/libraries)|
There are also other [pseudo targets](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#pseudo-targets), but they are not important for now.
## Target Properties
Targets have a collection of **properties** that describe how the compiler builds them.
The most commonly-used properties:
- [_Sources_](https://cmake.org/cmake/help/latest/command/target_sources.html): the `*.cpp` files used to build the target.
- [_Include directories_](https://cmake.org/cmake/help/latest/command/target_include_directories.html): Paths to directories the compiler will search when doing `#include`.
- [_Compile definitions_](https://cmake.org/cmake/help/latest/command/target_compile_definitions.html): Preprocessor macro definitions used for compilation (`-DMYOPTION`).
- [_Compile options_](https://cmake.org/cmake/help/latest/command/target_compile_options.html): Command line flags for the compiler (platform/compiler specific).
- [_Compile features_](https://cmake.org/cmake/help/latest/command/target_compile_features.html): C/C++ standard version to build with.
- [_Link libraries_](https://cmake.org/cmake/help/latest/command/target_link_libraries.html): The **dependencies** required to build this target.
- [_Link options_](https://cmake.org/cmake/help/latest/command/target_link_options.html): Command line flags for the linker (platform/linker specific).
<sub>See the [CMake documentation](https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#properties-on-targets) for an exhaustive list of target properties.</sub>
**Important**: The term **link** has a slightly different meaning in CMake than you might expect. In addition to adding a library to the command line, CMake also (transitively) propagates properties of the target you link to based on their _visibility_.
You should think of **linking** in CMake as _depending on_.
{:.info}
The propagation of properties depends on their **visibility**:
- **Private**: properties that are only used when building the target itself.
- **Interface**: properties that are used when depending on this target.
- **Public**: combination of private and interface.
In practice you default to **private**, unless consumers of your library _require_ the property to build their target. In that case you use **public**.
## Example
The most intuitive example is with _include directories_. Imagine there are two targets:
1. `StringUtils`: A library with string utilities.
- _Sources_: `StringUtils/src/stringutils.cpp`
- _Include directories_: `StringUtils/include`
2. `DataProcessor`: An executable that uses functionality from `StringUtils` to process some data.
- _Sources_: `DataProcessor/src/main.cpp`
- _Link libraries_: `StringUtils`
The _include directories_ property of `StringUtils` has to be **public**. If it was **private**, the `DataProcessor` target would fail to `#include <stringutils.hpp>` since the _include directories_ property is not propagated.
The `cmake.toml` for this example would look something like this:
```toml
[project]
name = "DataProcessor"
[target.StringUtils]
type = "static"
sources = ["StringUtils/src/stringutils.cpp"]
headers = ["StringUtils/include/stringutils.hpp"]
include-directories = ["StringUtils/include"] # public (default for libraries)
[target.DataProcessor]
type = "executable"
sources = ["DataProcessor/src/main.cpp"]
link-libraries = ["StringUtils"] # private (default for executables)
```
The generated `CMakeLists.txt` (simplified) looks like this:
```cmake
project(DataProcessor)
# Target: StringUtils
add_library(StringUtils STATIC
"StringUtils/include/stringutils.hpp"
"StringUtils/src/stringutils.cpp"
)
target_include_directories(StringUtils PUBLIC
"StringUtils/include"
)
# Target: DataProcessor
add_executable(DataProcessor
"DataProcessor/src/main.cpp"
)
target_link_libraries(DataProcessor PRIVATE
StringUtils
)
```
## CMake Phases
CMake works in three phases:
1. **Configure**: Execute `CMakeLists.txt` (find dependencies, create targets, OS/compiler-specific conditions, etc).
2. **Generate**: Generate build files (propagates target properties and handles [_generator expressions_](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html)).
3. **Build**: Execute the compiler to produce executables/libraries.
CMake keeps generated files separate from your source in a **build directory**. You specify a [**generator**](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html) (Visual Studio/Ninja) and [**build type**](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations) (Debug/Release) during configuration.
```bash
# Configure project and generate build files in build directory
cmake -B build -DCMAKE_BUILD_TYPE=Release
# Build the project
cmake --build build --config Release
```
We specify both `CMAKE_BUILD_TYPE` and `--config` to be compatible with generators that support multiple configurations at once ((like Visual Studio/Xcode/Ninja Multi-Config).
{:.info}
**Build Types**:
- `Debug`: No optimization, debug symbols
- `Release`: Full optimization, no debug symbols
- `RelWithDebInfo`: Medium optimizations, debug symbols
- `MinSizeRel`: Optimize for size, no debug symbols
**Generators**: CMake auto-detects (Makefiles on Linux/macOS, Visual Studio on Windows), but you can specify explicitly with `-G` during the _configure_ step.
+244 -28
View File
@@ -2,14 +2,15 @@
layout: page layout: page
title: Reference title: Reference
permalink: /cmake-toml/ permalink: /cmake-toml/
nav_order: 1 nav_order: 3
--- ---
# Reference # Reference
This page is a reference for the options in the `cmake.toml` file. If you think anything is missing or unclear, please [edit this page](https://github.com/build-cpp/cmkr/edit/main/docs/cmake-toml.md) or open an [issue](https://github.com/build-cpp/cmkr/issues). This page is a reference for the options in the `cmake.toml` file. If you think anything is missing or unclear, please [edit this page](https://github.com/build-cpp/cmkr/edit/main/docs/cmake-toml.md) or open an [issue](https://github.com/build-cpp/cmkr/issues).
See the [examples](/examples) section for concrete examples. This is a reference page. Check out the [examples](/examples) and the [cmkr topic](https://github.com/topics/cmkr) as well.
{:.info}
## CMake configuration ## CMake configuration
@@ -27,6 +28,7 @@ name = "myproject"
version = "1.0.0" version = "1.0.0"
description = "Description of the project" description = "Description of the project"
languages = ["C", "CXX"] languages = ["C", "CXX"]
msvc-runtime = "" # dynamic (implicit default), static
cmake-before = """ cmake-before = """
message(STATUS "CMake injected before the project() call") message(STATUS "CMake injected before the project() call")
""" """
@@ -37,17 +39,45 @@ include-before = ["cmake/before-project.cmake"]
include-after = ["cmake/after-project.cmake"] include-after = ["cmake/after-project.cmake"]
``` ```
### Languages
Supported languages are (see [`enable_language`](https://cmake.org/cmake/help/latest/command/enable_language.html) for more information):
- `C`
- `CXX` → C++
- `CSharp` → C#
- `CUDA`
- `OBJC` → Objective-C
- `OBJCXX` → Objective-C++
- `Fortran`
- `HIP`
- `ISPC`
- `Swift`
- `ASM`
- `ASM_MASM` → [Microsoft Macro Assembler (MASM)](https://learn.microsoft.com/en-US/cpp/assembler/masm/masm-for-x64-ml64-exe)
- `ASM_NASM` → [Netwide Assembler (NASM)](https://www.nasm.us)
- `ASM_MARMASM` [Microsoft ARM Assembler](https://learn.microsoft.com/en-us/cpp/assembler/arm/arm-assembler-command-line-reference)
- `ASM-ATT`
- `Java` (undocumented)
- `RC` (undocumented)
After a language is enabled, adding sources files with the corresponding extension to your target will automatically use the appropriate compiler/assembler for it.
_Note_: It is generally discouraged to disable the `C` language, unless you are absolutely sure it is not used. Sometimes projects added with `fetch-content` implicitly require it and the error messages can be extremely confusing.
## Conditions ## Conditions
You can specify your own conditions and use them in any `condition` field: You can specify your own named conditions and use them in any `condition` field:
```toml ```toml
[conditions] [conditions]
arch64 = "CMAKE_SIZEOF_VOID_P EQUALS 8" ptr64 = "CMAKE_SIZEOF_VOID_P EQUAL 8"
arch32 = "CMAKE_SIZEOF_VOID_P EQUALS 4" ptr32 = "CMAKE_SIZEOF_VOID_P EQUAL 4"
``` ```
This will make the `arch64` and `arch32` conditions available with their respective CMake expressions. This will make the `ptr64` and `ptr32` conditions available with their respective CMake expressions.
**Note**: condition names can only contain lower-case alphanumeric characters (`[0-9a-z]`) and dashes (`-`).
You can also prefix most keys with `condition.` to represent a conditional: You can also prefix most keys with `condition.` to represent a conditional:
@@ -55,9 +85,13 @@ You can also prefix most keys with `condition.` to represent a conditional:
[target] [target]
type = "executable" type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
windows.sources = ["src/windows_specific.cpp"] ptr64.sources = ["src/ptr64_only.cpp"]
``` ```
Instead of a named condition you can also specify a [CMake expression](https://cmake.org/cmake/help/latest/command/if.html#condition-syntax) in quotes. Instances of `$<name>` are replaced with the corresponding condition. For example: `"CONDITIONS_BUILD_TESTS AND $<linux>"` becomes `CONDITIONS_BUILD_TESTS AND (CMAKE_SYSTEM_NAME MATCHES "Linux")` in the final `CMakeLists.txt` file.
### Predefined conditions
The following conditions are predefined (you can override them if you desire): The following conditions are predefined (you can override them if you desire):
```toml ```toml
@@ -68,11 +102,20 @@ unix = "UNIX"
bsd = "CMAKE_SYSTEM_NAME MATCHES \"BSD\"" bsd = "CMAKE_SYSTEM_NAME MATCHES \"BSD\""
linux = "CMAKE_SYSTEM_NAME MATCHES \"Linux\"" linux = "CMAKE_SYSTEM_NAME MATCHES \"Linux\""
gcc = "CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" OR CMAKE_C_COMPILER_ID STREQUAL \"GNU\"" gcc = "CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" OR CMAKE_C_COMPILER_ID STREQUAL \"GNU\""
clang = "CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" OR CMAKE_C_COMPILER_ID MATCHES \"Clang\""
msvc = "MSVC" msvc = "MSVC"
clang = "(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\") OR (CMAKE_C_COMPILER_ID MATCHES \"Clang\" AND NOT CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\")"
clang-cl = "(CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\") OR (CMAKE_C_COMPILER_ID MATCHES \"Clang\" AND CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES \"^MSVC$\")"
clang-any = "CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" OR CMAKE_C_COMPILER_ID MATCHES \"Clang\""
root = "CMKR_ROOT_PROJECT" root = "CMKR_ROOT_PROJECT"
x64 = "CMAKE_SIZEOF_VOID_P EQUAL 8" x64 = "CMAKE_SIZEOF_VOID_P EQUAL 8"
x32 = "CMAKE_SIZEOF_VOID_P EQUAL 4" x32 = "CMAKE_SIZEOF_VOID_P EQUAL 4"
android = "ANDROID"
apple = "APPLE"
bsd = "BSD"
cygwin = "CYGWIN"
ios = "IOS"
xcode = "XCODE"
wince = "WINCE"
``` ```
## Subdirectories ## Subdirectories
@@ -90,18 +133,47 @@ include-before = ["cmake/before-subdir.cmake"]
include-after = ["cmake/after-subdir.cmake"] include-after = ["cmake/after-subdir.cmake"]
``` ```
## Options
```toml
[options]
MYPROJECT_BUILD_TESTS = false
MYPROJECT_SPECIAL_OPTION = { value = true, help = "Docstring for this option." }
MYPROJECT_BUILD_EXAMPLES = "root"
```
Options correspond to [CMake cache variables](https://cmake.org/cmake/help/book/mastering-cmake/chapter/CMake%20Cache.html) that can be used to customize your project at configure-time. You can configure with `cmake -DMYPROJECT_BUILD_TESTS=ON` to enable the option. Every option automatically gets a corresponding [condition](#conditions). Additionally, a normalized condition is created based on the `[project].name` (i.e. `MYPROJECT_BUILD_TESTS` becomes `build-tests`).
The special value `root` can be used to set the option to `true` if the project is compiled as the root project (it will be `false` if someone is including your project via `[fetch-content]` or `[subdir]`).
## Variables
```toml
[variables]
MYBOOL = true
MYSTRING = "hello"
```
Variables emit a [`set`](https://cmake.org/cmake/help/latest/command/set.html) and can be used to configure subprojects and packages.
## Vcpkg ## Vcpkg
```toml ```toml
[vcpkg] [vcpkg]
version = "2021.05.12" version = "2024.11.16"
url = "https://github.com/microsoft/vcpkg/archive/refs/tags/2021.05.12.tar.gz" url = "https://github.com/microsoft/vcpkg/archive/refs/tags/2024.11.16.tar.gz"
packages = ["fmt", "zlib"] packages = ["fmt", "zlib"]
overlay-ports = ["my-ports"]
overlay-triplets = ["my-triplets"]
``` ```
The vcpkg `version` will automatically generate the `url` from the [official repository](https://github.com/microsoft/vcpkg/releases). For a custom registry you can specify your own `url` (and omit the `version`). You can browse available packages on [vcpkg.io](https://vcpkg.io/en/packages.html). The vcpkg `version` will automatically generate the `url` from the [official repository](https://github.com/microsoft/vcpkg/releases). For a custom registry you can specify your own `url` (and omit the `version`). You can browse available packages on [vcpkg.io](https://vcpkg.io/en/packages.html) or [vcpkg.link](https://vcpkg.link).
To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`. To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`. To disable the [default features](https://learn.microsoft.com/en-us/vcpkg/concepts/default-features) you can do: `cpp-httplib[core,openssl]`
The `overlay-ports` feature allows you to embed vcpkg ports inside your project, without having to fork the main vcpkg registry or creating a custom registry. You can find more information in the relevant [documentation](https://learn.microsoft.com/en-us/vcpkg/concepts/overlay-ports). The `overlay-triplets` feature allows you to customize triplets and change the default behavior (for example always preferring static libraries on Windows). To specify both in one go you can do `[vcpkg].overlay = "vcpkg-overlay"`.
For a concrete example of all the features, take a look at the [vcpkg_template](https://github.com/build-cpp/vcpkg_template) repository.
## Packages ## Packages
@@ -119,50 +191,90 @@ components = ["mycomponent"]
**Note**: The `[fetch-content]` feature is unpolished and will likely change in a future release. **Note**: The `[fetch-content]` feature is unpolished and will likely change in a future release.
```toml ```toml
# Include CMake project from git
[fetch-content.gitcontent] [fetch-content.gitcontent]
condition = "mycondition" condition = "mycondition"
git = "https://github.com/myuser/gitcontent" git = "https://github.com/myuser/gitcontent"
tag = "v0.1" tag = "v0.1"
shallow = false # shallow clone (--depth 1)
system = false
subdir = "" # folder containing CMakeLists.txt
# Set cache variables before FetchContent_MakeAvailable
options = { BUILD_TESTS = false, BUILD_EXAMPLES = false }
# Include a CMake project from a URL
[fetch-content.urlcontent]
condition = "mycondition"
url = "https://content-host.com/urlcontent.zip"
# Other supported algorithms:
# md5, sha1, sha224, sha256, sha384, sha512, sha3_224, sha3_256, sha3_384, sha3_512
hash = "SHA1 502a4e25b8b209889c99c7fa0732102682c2e4ff"
sha1 = "502a4e25b8b209889c99c7fa0732102682c2e4ff"
[fetch-content.svncontent] [fetch-content.svncontent]
condition = "mycondition" condition = "mycondition"
svn = "https://svn-host.com/url" svn = "https://svn-host.com/url"
rev = "svn_rev" rev = "svn_rev"
[fetch-content.urlcontent] # For many options, you can also use a separate table:
condition = "mycondition" # [fetch-content.bigproject.options]
url = "https://content-host.com/urlcontent.zip" # BUILD_TESTS = false
hash = "123123123123" # BUILD_EXAMPLES = false
# SOME_STRING_OPTION = "value"
# SOME_LIST_OPTION = ["item1", "item2"] # becomes "item1;item2"
``` ```
Table keys that match CMake variable names (`[A-Z_]+`) will be passed to the [`FetchContent_Declare`](https://cmake.org/cmake/help/latest/module/FetchContent.html#command:fetchcontent_declare) command.
The `options` field allows setting CACHE variables before `FetchContent_MakeAvailable` is called. This is useful for configuring options on the fetched dependency (e.g., disabling tests). Boolean values become `ON`/`OFF`, arrays become semicolon-separated strings.
## Targets ## Targets
```toml ```toml
[target.mytarget] [target.mytarget]
condition = "mycondition" condition = "mycondition"
alias = "mytarget::mytarget" alias = "mytarget::mytarget"
type = "static" # executable, shared (DLL), static, interface, object, library, custom type = "static" # executable, library, shared (DLL), static, interface, object, custom
headers = ["src/mytarget.h"] headers = ["src/mytarget.h"]
sources = ["src/mytarget.cpp"] sources = ["src/mytarget.cpp"]
msvc-runtime = "" # dynamic (implicit default), static
# The keys below match the target_xxx CMake commands # The keys below match the target_xxx CMake commands
# Keys prefixed with private- will get PRIVATE visibility # Keys prefixed with private- will get PRIVATE visibility
compile-definitions = [""] compile-definitions = [""] # preprocessor define (-DFOO)
private-compile-definitions = [""] private-compile-definitions = [""]
compile-features = [""] compile-features = [""] # C++ standard version (cxx_std_20)
private-compile-features = [""] private-compile-features = [""]
compile-options = [""] compile-options = [""] # compiler flags
private-compile-options = [""] private-compile-options = [""]
include-directories = [""] include-directories = [""] # include paths/directories
private-include-directories = [""] private-include-directories = [""]
link-directories = [""] link-directories = [""] # library directories
private-link-directories = [""] private-link-directories = [""]
link-libraries = [""] link-libraries = [""] # dependencies
private-link-libraries = [""] private-link-libraries = [""]
link-options = [""] link-options = [""] # linker flags
private-link-options = [""] private-link-options = [""]
precompile-headers = [""] precompile-headers = [""] # precompiled headers
private-precompile-headers = [""] private-precompile-headers = [""]
dependencies = [""] # add_dependencies(target ...)
# Keys below are for type = "custom" (add_custom_target)
all = false
command = ["${CMAKE_COMMAND}", "-E", "echo", "Hello"] # one command line
commands = [ # multiple command lines
["${CMAKE_COMMAND}", "-E", "echo", "First"],
["${CMAKE_COMMAND}", "-E", "echo", "Second"],
]
depends = ["generated.txt"] # add_custom_target(... DEPENDS ...)
byproducts = ["generated.txt"]
working-directory = "${CMAKE_CURRENT_BINARY_DIR}"
comment = "Run custom target"
job-pool = "pool"
job-server-aware = true
verbatim = true
uses-terminal = false # incompatible with job-pool when true
command-expand-lists = true
cmake-before = """ cmake-before = """
message(STATUS "CMake injected before the target") message(STATUS "CMake injected before the target")
@@ -180,6 +292,108 @@ CXX_STANDARD_REQUIRED = true
FOLDER = "MyFolder" FOLDER = "MyFolder"
``` ```
### Custom commands
Use `[[target.<name>.custom-command]]` to map directly to [`add_custom_command`](https://cmake.org/cmake/help/latest/command/add_custom_command.html). A custom command can use either the `OUTPUT` form or the `TARGET` form:
```toml
# OUTPUT form (add_custom_command(OUTPUT ...))
[[target.mytarget.custom-command]]
condition = "mycondition"
outputs = ["generated.cpp"] # relative paths are interpreted from ${CMAKE_CURRENT_BINARY_DIR}
command = [
"${CMAKE_COMMAND}",
"-DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/generated.cpp",
"-P",
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate.cmake",
]
depends = ["cmake/generate.cmake"]
byproducts = ["generated.hpp"]
main-dependency = "cmake/generate.cmake"
implicit-depends = [["CXX", "src/input.idl"]]
working-directory = "${CMAKE_CURRENT_BINARY_DIR}"
comment = "Generate source"
depfile = "${CMAKE_CURRENT_BINARY_DIR}/generated.d"
job-pool = "pool" # incompatible with uses-terminal when uses-terminal = true
job-server-aware = true
verbatim = true
append = false
uses-terminal = false
codegen = false
command-expand-lists = false
depends-explicit-only = false
# TARGET form (add_custom_command(TARGET ...))
[[target.mytarget.custom-command]]
build-event = "post-build" # pre-build, pre-link, post-build
command = ["${CMAKE_COMMAND}", "-E", "touch", "${CMAKE_CURRENT_BINARY_DIR}/post-build.stamp"]
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/post-build.stamp"]
working-directory = "${CMAKE_CURRENT_BINARY_DIR}"
comment = "Post-build step"
verbatim = true
command-expand-lists = false
uses-terminal = false
```
For each custom command entry, exactly one of `outputs` or `build-event` is required. Relative `outputs`/`byproducts` paths follow CMake and are interpreted from the current binary directory. `build-event` is only valid for non-`interface` targets, and `pre-link` is not supported for `type = "custom"`. In both `add_custom_command(OUTPUT ...)` and `add_custom_target(...)`, `job-pool` cannot be combined with `uses-terminal = true`. When `append = true` is used with the `OUTPUT` form, at least one `command`/`commands` entry or `depends` must also be provided.
A table mapping the cmkr features to the relevant CMake construct and the relevant documentation pages:
| cmkr | CMake construct | Description |
| ---- | ----- | ----------- |
| `alias` | [Alias Libraries](https://cmake.org/cmake/help/latest/command/add_library.html#alias-libraries) | Create an [alias target](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#alias-targets), used for namespacing or clarity. |
| `sources` | [`target_sources`](https://cmake.org/cmake/help/latest/command/target_sources.html) | Source files (`PRIVATE` except `interface` targets). |
| `headers` | [`target_sources`](https://cmake.org/cmake/help/latest/command/target_sources.html) | For readability (and future packaging). |
| `msvc-runtime` | [`MSVC_RUNTIME_LIBRARY`](https://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html) | The [CMP0091](https://cmake.org/cmake/help/latest/policy/CMP0091.html) policy is set automatically. |
| `compile-definitions` | [`target_compile_definitions`](https://cmake.org/cmake/help/latest/command/target_compile_definitions.html) | Adds a macro definition (define, `-DMYMACRO=XXX`). |
| `compile-features` | [`target_compile_features`](https://cmake.org/cmake/help/latest/command/target_compile_features.html) | Specifies the C++ standard version (`cxx_std_20`). |
| `compile-options` | [`target_compile_options`](https://cmake.org/cmake/help/latest/command/target_compile_options.html) | Adds compiler flags. |
| `include-directories` | [`target_include_directories`](https://cmake.org/cmake/help/latest/command/target_include_directories.html) | Adds include directories. |
| `link-directories` | [`target_link_directories`](https://cmake.org/cmake/help/latest/command/target_link_directories.html) | Adds library directories. |
| `link-libraries` | [`target_link_libraries`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) | Adds library dependencies. Use `::mylib` to make sure a target exists. |
| `link-options` | [`target_link_options`](https://cmake.org/cmake/help/latest/command/target_link_options.html) | Adds linker flags. |
| `precompile-headers` | [`target_precompile_headers`](https://cmake.org/cmake/help/latest/command/target_precompile_headers.html) | Specifies precompiled headers. |
| `dependencies` | [`add_dependencies`](https://cmake.org/cmake/help/latest/command/add_dependencies.html) | Adds target-level dependencies. |
| `type = "custom"` + custom target keys | [`add_custom_target`](https://cmake.org/cmake/help/latest/command/add_custom_target.html) | Creates a custom target with command/dependency options. |
| `[[target.<name>.custom-command]]` | [`add_custom_command`](https://cmake.org/cmake/help/latest/command/add_custom_command.html) | Supports both `OUTPUT` and `TARGET` forms. |
| `properties` | [`set_target_properties`](https://cmake.org/cmake/help/latest/command/set_target_properties.html) | See [properties on targets](https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#properties-on-targets) for more information. |
The default [visibility](/basics) is as follows:
| Type | Visibility |
| ------------ | ----------- |
| `executable` | `PRIVATE` |
| `library` | `PUBLIC` |
| `shared` | `PUBLIC` |
| `static` | `PUBLIC` |
| `object` | `PUBLIC` |
| `interface` | `INTERFACE` |
## Templates
To avoid repeating yourself you can create your own target type and use it in your targets:
```toml
[template.example]
condition = "MYPROJECT_BUILD_EXAMPLES"
type = "executable"
link-libraries = ["myproject::mylib"]
add-function = ""
add-arguments = ["myoption"]
pass-sources = false
# Properties from the template are merged with the ones here
[target.myexample]
type = "example"
sources = ["src/myexample.cpp"]
```
The properties declared on a `template` are the same as the ones you use for targets. The only exceptions are:
- `add-function`: Specifies a custom add function. Projects like [pybind11](https://pybind11.readthedocs.io/en/stable/cmake/index.html#new-findpython-mode) have their own `add_xxx` function, which you can specify here.
- `add-arguments`: Arguments to pass to the `add-function` before the list of sources. See [cmake_parse_arguments](https://cmake.org/cmake/help/latest/command/cmake_parse_arguments.html) for more details.
- `pass-sources`: Pass sources directly to the add function instead of using `target_sources`.
## Tests and installation (unfinished) ## Tests and installation (unfinished)
**Note**: The `[[test]]` and `[[install]]` are unfinished features and will likely change in a future release. **Note**: The `[[test]]` and `[[install]]` are unfinished features and will likely change in a future release.
@@ -200,7 +414,9 @@ working-directory = "mytest-dir"
condition = "mycondition" condition = "mycondition"
targets = ["mytarget", "mytest"] targets = ["mytarget", "mytest"]
destination = ["bin"] destination = ["bin"]
component = "mycomponent"
files = ["content/my.png"] files = ["content/my.png"]
dirs = [""] dirs = ["include"]
configs = [""] configs = ["Release", "Debug"]
``` optional = false
```
+34
View File
@@ -0,0 +1,34 @@
---
# Automatically generated from tests/compile-options/cmake.toml - DO NOT EDIT
layout: default
title: Compiler flags
permalink: /examples/compile-options
parent: Examples
nav_order: 9
---
# Compiler flags
Example project that sets compiler flags and preprocessor defines for various platforms.
```toml
[project]
name = "compile-options"
description = "Compiler flags"
[target.hello]
type = "executable"
sources = ["src/main.cpp"]
msvc.compile-options = ["/W2"]
msvc.compile-definitions = ["PLATFORM=\"msvc\""]
gcc.compile-options = ["-Wall"]
gcc.compile-definitions = ["PLATFORM=\"gcc\""]
clang.compile-options = ["-Wall"]
clang.compile-definitions = ["PLATFORM=\"clang\""]
```
The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags and definitions depending on the platform. See the [targets](/cmake-toml/#targets) documentation for other things you can set.
_Note_: In general you only want to specify flags _required_ to compile your code without errors.
<sup><sub>This page was automatically generated from [tests/compile-options/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/compile-options/cmake.toml).</sub></sup>
+141
View File
@@ -0,0 +1,141 @@
---
# Automatically generated from tests/custom-command/cmake.toml - DO NOT EDIT
layout: default
title: Tests add_custom_command and add_custom_target support
permalink: /examples/custom-command
parent: Examples
nav_order: 12
---
# Tests add_custom_command and add_custom_target support
This test demonstrates add_custom_command and add_custom_target support in cmkr.
```toml
#
# There are two forms of add_custom_command in CMake:
# 1. Output form: generates files that can be consumed by other targets
# 2. Target form: runs commands at build time for a specific target (pre-build, pre-link, post-build)
[project]
name = "custom-command"
description = "Tests add_custom_command and add_custom_target support"
# -----------------------------------------------------------------------------
# Simple executable demonstrating post-build events
# -----------------------------------------------------------------------------
[target.hello]
type = "executable"
sources = ["src/hello.cpp"]
# This post-build command runs after the 'hello' executable is built.
# build-event can be: "pre-build", "pre-link", or "post-build"
[[target.hello.custom-command]]
build-event = "post-build"
command = ["${CMAKE_COMMAND}", "-E", "echo", "Built executable: $<TARGET_FILE_NAME:hello>"]
comment = "Print the built executable name"
# -----------------------------------------------------------------------------
# Executable with code generation (output form custom command)
# -----------------------------------------------------------------------------
[target.custom-command]
type = "executable"
sources = ["src/main.cpp"]
include-directories = ["${CMAKE_CURRENT_BINARY_DIR}/generated"]
# Output form: This custom command generates source files before building.
# Relative outputs follow CMake and are interpreted from the binary directory.
# The outputs are automatically added as sources to the target.
[[target.custom-command.custom-command]]
outputs = ["generated/generated.cpp"]
byproducts = ["generated/generated.hpp"]
depends = ["cmake/generate_source.cmake"]
command = [
"${CMAKE_COMMAND}",
"-DOUTPUT_CPP=${CMAKE_CURRENT_BINARY_DIR}/generated/generated.cpp",
"-DOUTPUT_HPP=${CMAKE_CURRENT_BINARY_DIR}/generated/generated.hpp",
"-P",
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate_source.cmake",
]
comment = "Generate source files"
verbatim = true
# Target form: This post-build command runs after 'custom-command' is built.
[[target.custom-command.custom-command]]
build-event = "post-build"
command = [
"${CMAKE_COMMAND}",
"-E",
"touch",
"${CMAKE_CURRENT_BINARY_DIR}/custom-command-post-build.stamp",
]
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/custom-command-post-build.stamp"]
comment = "Create a post-build stamp file"
verbatim = true
# -----------------------------------------------------------------------------
# Custom target (add_custom_target)
# -----------------------------------------------------------------------------
# A custom target runs commands independently of any executable/library.
# Setting 'all = true' makes it run as part of the default build.
[target.custom-codegen]
type = "custom"
all = true
command = [
"${CMAKE_COMMAND}",
"-E",
"touch",
"${CMAKE_CURRENT_BINARY_DIR}/custom-target.stamp",
]
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/custom-target.stamp"]
comment = "Run custom target"
verbatim = true
# -----------------------------------------------------------------------------
# Template-based custom target
# -----------------------------------------------------------------------------
# Custom target options should also work when the target type comes from a template.
[template.generated-custom-target]
type = "custom"
all = true
verbatim = true
[target.custom-codegen-template]
type = "generated-custom-target"
command = [
"${CMAKE_COMMAND}",
"-DINPUT=${CMAKE_CURRENT_BINARY_DIR}/template-custom-target.stamp",
"-P",
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/verify_file_exists.cmake",
]
comment = "Verify the generated stamp exists"
# The output-form custom command should automatically become a dependency of the
# custom target, so the verification command sees the stamp file.
[[target.custom-codegen-template.custom-command]]
outputs = ["template-custom-target.stamp"]
command = [
"${CMAKE_COMMAND}",
"-E",
"touch",
"${CMAKE_CURRENT_BINARY_DIR}/template-custom-target.stamp",
]
comment = "Create a stamp file for the template-based custom target"
verbatim = true
# A target-level all = false should override the template's all = true.
# If this target is incorrectly included in the default build, the build fails.
[target.custom-codegen-template-disabled]
type = "generated-custom-target"
all = false
command = ["${CMAKE_COMMAND}", "-E", "false"]
comment = "This target must not run as part of the default build"
```
<sup><sub>This page was automatically generated from [tests/custom-command/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/custom-command/cmake.toml).</sub></sup>
+3 -2
View File
@@ -16,8 +16,9 @@ Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) from [GitHub](https://github.com)
name = "fetch-content" name = "fetch-content"
description = "Fetching from git" description = "Fetching from git"
[fetch-content] [fetch-content.fmt]
fmt = { git = "https://github.com/fmtlib/fmt", tag = "7.1.3" } git = "https://github.com/fmtlib/fmt"
tag = "7.1.3"
[target.example] [target.example]
type = "executable" type = "executable"
+74
View File
@@ -0,0 +1,74 @@
---
# Automatically generated from tests/generator-executable/cmake.toml - DO NOT EDIT
layout: default
title: Tests using an executable to generate sources for another target
permalink: /examples/generator-executable
parent: Examples
nav_order: 13
---
# Tests using an executable to generate sources for another target
This test demonstrates a common pattern: using an executable to generate sources
for another target. The generator runs at build time and produces code that is
consumed by the main executable.
```toml
#
# CMake handles the dependency automatically: the generator executable is built
# first, then it runs to produce the generated sources, and finally the main
# executable is built using those sources.
[project]
name = "generator-executable"
description = "Tests using an executable to generate sources for another target"
# -----------------------------------------------------------------------------
# Generator executable: produces code at build time
# -----------------------------------------------------------------------------
[target.generate_numbers]
type = "executable"
sources = ["src/generate_numbers.cpp"]
# Post-build: confirm the generator was built
[[target.generate_numbers.custom-command]]
build-event = "post-build"
command = ["${CMAKE_COMMAND}", "-E", "echo", "Generator built successfully: $<TARGET_FILE_NAME:generate_numbers>"]
comment = "Confirm generator executable was built"
# -----------------------------------------------------------------------------
# Main executable: uses generated sources
# -----------------------------------------------------------------------------
[target.main]
type = "executable"
sources = ["src/main.cpp"]
include-directories = ["${CMAKE_CURRENT_BINARY_DIR}/generated"]
# Create the generated directory before the generator runs.
cmake-before = """
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/generated")
"""
# Output form custom command: runs the generate_numbers executable to generate sources.
# The outputs are automatically added as sources to this target.
# The DEPENDS on "generate_numbers" ensures the generator is built before this runs.
[[target.main.custom-command]]
outputs = ["${CMAKE_CURRENT_BINARY_DIR}/generated/numbers.cpp"]
depends = ["generate_numbers"]
command = ["$<TARGET_FILE:generate_numbers>", "${CMAKE_CURRENT_BINARY_DIR}/generated/numbers.cpp"]
comment = "Run generate_numbers to generate numbers.cpp"
# Post-build: run the executable to verify it works
[[target.main.custom-command]]
build-event = "post-build"
command = ["$<TARGET_FILE:main>"]
comment = "Run the main executable to verify generated code works"
```
<sup><sub>This page was automatically generated from [tests/generator-executable/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/generator-executable/cmake.toml).</sub></sup>
+34
View File
@@ -0,0 +1,34 @@
---
# Automatically generated from tests/msvc-runtime/cmake.toml - DO NOT EDIT
layout: default
title: Static MSVC runtime
permalink: /examples/msvc-runtime
parent: Examples
nav_order: 8
---
# Static MSVC runtime
```toml
[project]
name = "msvc-runtime"
description = "Static MSVC runtime"
msvc-runtime = "static"
# This target will compile with a static runtime
[target.static-runtime]
type = "executable"
sources = ["src/main.cpp"]
# This target overrides the [project].msvc-runtime
[target.dynamic-runtime]
type = "executable"
sources = ["src/main.cpp"]
msvc-runtime = "dynamic"
```
<sup><sub>This page was automatically generated from [tests/msvc-runtime/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/msvc-runtime/cmake.toml).</sub></sup>
+30
View File
@@ -0,0 +1,30 @@
---
# Automatically generated from tests/objective-c/cmake.toml - DO NOT EDIT
layout: default
title: Objective-C
permalink: /examples/objective-c
parent: Examples
nav_order: 11
---
# Objective-C
Add Objective-C sources on Apple platforms:
```toml
[project]
name = "objective-c"
description = "Objective-C"
languages = ["C"]
apple.languages = ["OBJC"]
[target.hello]
type = "executable"
sources = ["src/main.c"]
apple.sources = ["src/apple.m"]
apple.link-libraries = ["$<LINK_LIBRARY:FRAMEWORK,Foundation>"]
```
<sup><sub>This page was automatically generated from [tests/objective-c/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/objective-c/cmake.toml).</sub></sup>
+99
View File
@@ -0,0 +1,99 @@
---
# Automatically generated from tests/protobuf/cmake.toml - DO NOT EDIT
layout: default
title: Demonstrates protobuf integration with cmkr custom commands
permalink: /examples/protobuf
parent: Examples
nav_order: 14
---
# Demonstrates protobuf integration with cmkr custom commands
This test demonstrates using protobuf with cmkr for code generation.
```toml
#
# The example:
# 1. Fetches protobuf from GitHub using FetchContent
# 2. Uses a custom command to generate C++ sources from a .proto file
# 3. Links an executable against the generated sources and protobuf library
# 4. Serializes and deserializes a simple message
#
# Note: protobuf v21.x is used because newer versions (v22+) require abseil-cpp
# as a dependency, which significantly complicates the build.
[cmake]
version = "3.18...3.31"
[project]
name = "protobuf-example"
description = "Demonstrates protobuf integration with cmkr custom commands"
# -----------------------------------------------------------------------------
# Fetch protobuf from GitHub
# Using v21.12 (last version before abseil-cpp became required)
# -----------------------------------------------------------------------------
[fetch-content.protobuf]
git = "https://github.com/protocolbuffers/protobuf"
tag = "v21.12"
options = {
protobuf_BUILD_TESTS = false,
protobuf_BUILD_EXAMPLES = false,
protobuf_BUILD_LIBPROTOC = false,
protobuf_BUILD_SHARED_LIBS = false,
protobuf_MSVC_STATIC_RUNTIME = false,
SKIP_INSTALL_ALL = true,
protobuf_WITH_ZLIB = false,
}
# -----------------------------------------------------------------------------
# Main executable using protobuf
# -----------------------------------------------------------------------------
[target.protobuf_example]
type = "executable"
sources = [
"src/main.cpp",
]
include-directories = [
"${CMAKE_CURRENT_BINARY_DIR}/generated",
]
link-libraries = ["protobuf::libprotobuf"]
compile-features = ["cxx_std_17"]
# Create the generated directory before running protoc
cmake-before = """
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/generated")
"""
# Custom command to generate C++ sources from .proto file
# This uses protoc from the fetched protobuf repository
[[target.protobuf_example.custom-command]]
outputs = [
"${CMAKE_CURRENT_BINARY_DIR}/generated/addressbook.pb.h",
"${CMAKE_CURRENT_BINARY_DIR}/generated/addressbook.pb.cc",
]
depends = [
"${CMAKE_CURRENT_SOURCE_DIR}/proto/addressbook.proto",
"protobuf::protoc", # Ensure protoc is built first
]
command = [
"$<TARGET_FILE:protobuf::protoc>",
"--cpp_out=${CMAKE_CURRENT_BINARY_DIR}/generated",
"-I${CMAKE_CURRENT_SOURCE_DIR}/proto",
"${CMAKE_CURRENT_SOURCE_DIR}/proto/addressbook.proto",
]
comment = "Generate C++ sources from addressbook.proto"
verbatim = true
# Post-build: run the executable to verify it works
[[target.protobuf_example.custom-command]]
build-event = "post-build"
command = ["$<TARGET_FILE:protobuf_example>"]
comment = "Run protobuf_example to verify serialization/deserialization works"
```
<sup><sub>This page was automatically generated from [tests/protobuf/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/protobuf/cmake.toml).</sub></sup>
+4 -4
View File
@@ -20,11 +20,11 @@ description = "Target templates"
type = "executable" type = "executable"
sources = ["src/templates.cpp"] sources = ["src/templates.cpp"]
compile-definitions = ["IS_APP"] compile-definitions = ["IS_APP"]
# Unlike interface targets you can also inherit properties # Unlike interface targets you can also inherit properties
[template.app.properties] properties = {
CXX_STANDARD = "11" CXX_STANDARD = "11",
CXX_STANDARD_REQUIRED = true CXX_STANDARD_REQUIRED = true,
}
[target.app-a] [target.app-a]
type = "app" type = "app"
+4 -5
View File
@@ -9,7 +9,7 @@ nav_order: 4
# Dependencies from vcpkg # Dependencies from vcpkg
Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://vcpkg.io/) and links an `example` target to it: Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://github.com/microsoft/vcpkg) and links an `example` target to it:
```toml ```toml
[project] [project]
@@ -17,13 +17,12 @@ name = "vcpkg"
description = "Dependencies from vcpkg" description = "Dependencies from vcpkg"
# See https://github.com/microsoft/vcpkg/releases for vcpkg versions # See https://github.com/microsoft/vcpkg/releases for vcpkg versions
# See https://vcpkg.io/en/packages.html for available packages # See https://vcpkg.io/en/packages or https://vcpkg.link for available packages
[vcpkg] [vcpkg]
version = "2021.05.12" version = "2024.11.16"
packages = ["fmt"] packages = ["fmt"]
[find-package] [find-package.fmt]
fmt = {}
[target.example] [target.example]
type = "executable" type = "executable"
+9 -9
View File
@@ -1,10 +1,10 @@
--- ---
layout: null layout: null
permalink: /getting-started/ permalink: /getting-started/
--- ---
<html> <html>
<head> <head>
<meta http-equiv="refresh" content="0;url=https://cmkr.build"> <meta http-equiv="refresh" content="0;url=https://cmkr.build">
</head> </head>
</html> </html>
+19 -15
View File
@@ -1,12 +1,12 @@
--- ---
layout: home layout: home
title: Index title: Documentation
nav_order: 0 nav_order: 0
--- ---
# Index # Documentation
`cmkr`, pronounced "cmaker", is a modern build system based on [CMake](https://cmake.org/) and [TOML](https://toml.io). [`cmkr`](https://github.com/build-cpp/cmkr), pronounced "cmaker", is a modern build system based on [CMake](https://cmake.org/) and [TOML](https://toml.io).
`cmkr` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example: `cmkr` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example:
@@ -19,27 +19,29 @@ type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
``` ```
`cmkr` can bootstrap itself from CMake and you only need CMake to use it. `cmkr` can bootstrap itself, and you only need CMake and a C++ compiler to use it.
## Getting started ## Getting started
To get started run the following commands from your project directory: To get started, run the following commands from your project directory:
```sh ```sh
curl https://raw.githubusercontent.com/build-cpp/cmkr/main/cmake/cmkr.cmake -o cmkr.cmake curl https://raw.githubusercontent.com/build-cpp/cmkr/main/cmake/cmkr.cmake -o cmkr.cmake
cmake -P cmkr.cmake cmake -P cmkr.cmake
``` ```
After the bootstrapping process finishes, modify [`cmake.toml`](https://build-cpp.github.io/cmkr/cmake-toml) and open the project in your favorite IDE or build with CMake: After the bootstrapping process finishes, customize [`cmake.toml`](./cmake-toml) for your project and run CMake:
```sh ```sh
cmake -B build cmake -B build
cmake --build build cmake --build build
``` ```
Once bootstrapped, `cmkr` does not introduce extra steps to your workflow. After modifying `cmake.toml` you simply build/configure your CMake project and `cmkr` will automatically regenerate `CMakeLists.txt`. Once bootstrapped, `cmkr` does not introduce extra steps to your workflow. After modifying `cmake.toml` you simply build/configure your CMake project and `cmkr` will automatically regenerate `CMakeLists.txt` when necessary.
In CI settings the `cmkr` bootstrapping process is skipped so there is no extra configure-time overhead in your pipelines. <sub>**Note**: The `cmake.toml` project file, generated `CMakeLists.txt` and `cmkr.cmake` bootstrapping script are all intended to be added to source control.</sub>
In CI environments the `cmkr` bootstrapping process is skipped, so there is no additional overhead in your pipelines.
## Template repositories ## Template repositories
@@ -59,10 +61,10 @@ Optionally you can put a [`cmkr` release](https://github.com/build-cpp/cmkr/rele
``` ```
Usage: cmkr [arguments] Usage: cmkr [arguments]
arguments: arguments:
init [executable|library|shared|static|interface] Starts a new project in the same directory. init [executable|library|shared|static|interface] Create a project.
gen Generates CMakeLists.txt file. gen Generates CMakeLists.txt file.
build <extra cmake args> Run cmake and build. build <extra cmake args> Run cmake and build.
install Run cmake --install. Needs admin privileges. install Run cmake --install.
clean Clean the build directory. clean Clean the build directory.
help Show help. help Show help.
version Current cmkr version. version Current cmkr version.
@@ -70,8 +72,10 @@ arguments:
## Credits ## Credits
- https://github.com/gulrak/filesystem - [gulrak/filesystem](https://github.com/gulrak/filesystem)
- https://github.com/Tessil/ordered-map - [Tessil/ordered-map](https://github.com/Tessil/ordered-map)
- https://github.com/ToruNiina/toml11 - [ToruNiina/toml11](https://github.com/ToruNiina/toml11)
- https://github.com/mpark/variant - [mpark/variant](https://github.com/mpark/variant)
- https://www.svgrepo.com/svg/192268/hammer - [SVG Repo Hammer](https://www.svgrepo.com/svg/192268/hammer)
- [can1357](https://github.com/can1357) for buying `cmkr.build` ❤️
- [JustasMasiulis](https://github.com/JustasMasiulis) for fixing the dark theme ❤️
+83
View File
@@ -0,0 +1,83 @@
---
layout: page
title: Philosophy
nav_order: 2
published: false
---
# Philosophy
## Problem statement
Similar to writing good C++, writing good CMake is difficult. The main difference is that nobody actually wants to learn CMake. The build system is something that should "just work".
There have been many attempts at creating new build systems (with varying levels of success). Naturally this causes [competing standards](https://xkcd.com/927/), which is undesirable. CMake is pretty much the de facto standard, and it has seen extensive use in complex software projects.
One of the main issues of CMake is the turing-complete scripting language you use to describe your projects. As your project gets more complex this can be very helpful, but it also unnecessarily complicates simple projects. There have been discussions about a declarative language on the [CMake issue tracker](https://gitlab.kitware.com/cmake/cmake/-/issues/19891) to solve this problem, but it looks like a "LISP-like" language is seriously being considered...
## The solution
The way cmkr (pronounced "cmaker") solves this problem is by using [TOML](https://toml.io/). Below is a minimal `cmake.toml` project:
```toml
[project]
name = "cmkr_for_beginners"
[target.hello_world]
type = "executable"
sources = ["src/main.cpp"]
```
The key difference between `cmkr` and other build systems is that it _generates_ CMake. This means that your projects are fully compatible with the CMake ecosystem, and you can try it out without having to rewrite your whole build system.
TODO: link/include more examples? Talk about conditions, packaging (missing)
### Another layer?!
A common issue people have with cmkr is that it introduces an additional layer of indirection to your build system. CMake is already a meta-buildsystem, which means you could call cmkr a "meta-meta-buildsystem".
Presumably the reason for this friction is that additional layers of abstraction introduce additional complexity. Because of this cmkr has been designed to be completely seamless:
- The user doesn't have to install any additional software to use cmkr. All you need is a semi-recent version of CMake and a C++ compiler.
- Modifying `cmake.toml` automatically triggers a regeneration of `CMakeLists.txt`. There is no change to your build process.
- The `CMakeLists.txt` is generated to be human-readable. This means you can easily "eject" from cmkr and go back to CMake.
An additional argument for cmkr is that anecdotally people say it "just works". Because of its simplicity it's also easy to teach, even to people without programming experience.
There is also precedent in the JavaScript community. Bundlers and translators are the norm there and their developer experience is miles ahead of C++.
<sub>Not to say the JavaScript ecosystem is without its flaws, but generators does not appear to be one of them</sub>
### Unsupported features
Because cmkr is still in early in development there are many missing/unfinished features. It was decided that users can bridge the gap by including CMake at arbitrary locations.
This has the advantage that it forces complexity in the build system to be self-contained and modular, a problem all too common in projects as they age.
## Enterprise
Words like "bootstrapping" and "generating code" might worry engineers working in an enterprise environment, and rightly so. From the beginning it has been a priority to make cmkr suitable for use in big corporations with strict protocols for security and reproducibility.
### No additional dependencies
As mentioned above, the only thing you need is a working C++ compiler and a semi-recent version of CMake. It is assumed that you are already building (and executing) C++ projects on your servers, so cmkr does not introduce additional requirements.
All the logic for downloading and compiling the `cmkr` executable is self-contained in a ~250 line `cmkr.cmake` script. You can easily audit it and see if it's up to your standards.
### Reproducibility
Per default the `cmkr.cmake` bootstrapping script contains the exact version of cmkr used to generate your project. As long as the cmkr repository is available you will build the exact same version of cmkr, which will generate the exact same `CMakeLists.txt` file.
This also means that cmkr can decide to break backwards compatibility without affecting legacy projects. An effort will always be made to maintain backwards compatibility though.
### Integrity
As an additional safeguard you can modify `cmkr.cmake` to pin the version tag to a commit hash. This hash is checked to ensure the integrity of the upstream repository.
### Availability
You can easily point `cmkr.cmake` to a mirror of the cmkr repository to ensure availability should something catastrophic happen.
### Not executed in CI
The final (and key) feature is that the bootstrapping process is never executed in CI environments. This means `cmkr` is only ever executed on your developer's machines and not on your infrastructure.
View File
-2
View File
@@ -1,2 +0,0 @@
bundle exec just-the-docs rake search:init
bundle exec jekyll serve --livereload
+1 -1
View File
@@ -1,2 +1,2 @@
bundle install bundle install
bundle exec jekyll serve --force_polling --livereload --incremental bundle exec jekyll serve --force_polling --livereload --incremental
-2
View File
@@ -7,5 +7,3 @@ const char *handle_args(int argc, char **argv);
} // namespace args } // namespace args
} // namespace cmkr } // namespace cmkr
const char *cmkr_args_handle_args(int, char **);
-6
View File
@@ -11,9 +11,3 @@ int install();
} // namespace build } // namespace build
} // namespace cmkr } // namespace cmkr
int cmkr_build_run(int argc, char **argv);
int cmkr_build_clean();
int cmkr_build_install();
-27
View File
@@ -1,27 +0,0 @@
#pragma once
namespace cmkr {
namespace error {
struct Status {
enum class Code {
Success = 0,
RuntimeError,
InitError,
GenerationError,
BuildError,
CleanError,
InstallError,
};
Status(Code ec) noexcept;
operator int() const noexcept;
Code code() const noexcept;
private:
Code ec_ = Code::Success;
};
} // namespace error
} // namespace cmkr
const char *cmkr_error_status_string(int);
+2 -4
View File
@@ -1,8 +1,6 @@
#pragma once #pragma once
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || \ #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || (defined(__cplusplus) && __cplusplus >= 201703L)) && defined(__has_include)
(defined(__cplusplus) && __cplusplus >= 201703L)) && \
defined(__has_include)
#if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) #if __has_include(<filesystem>) && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)
#define GHC_USE_STD_FS #define GHC_USE_STD_FS
#include <filesystem> #include <filesystem>
@@ -12,4 +10,4 @@ namespace fs = std::filesystem;
#ifndef GHC_USE_STD_FS #ifndef GHC_USE_STD_FS
#include <ghc/filesystem.hpp> #include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem; namespace fs = ghc::filesystem;
#endif #endif
-4
View File
@@ -9,7 +9,3 @@ const char *message() noexcept;
} // namespace help } // namespace help
} // namespace cmkr } // namespace cmkr
const char *cmkr_help_version(void);
const char *cmkr_help_message(void);
+149 -21
View File
@@ -1,9 +1,11 @@
#pragma once #pragma once
#include <mpark/variant.hpp>
#include <string>
#include <tsl/ordered_map.h>
#include <vector> #include <vector>
#include <string>
#include <mpark/variant.hpp>
#include <tsl/ordered_map.h>
#include <tsl/ordered_set.h>
namespace cmkr { namespace cmkr {
namespace parser { namespace parser {
@@ -13,21 +15,21 @@ using Condition = tsl::ordered_map<std::string, T>;
using ConditionVector = Condition<std::vector<std::string>>; using ConditionVector = Condition<std::vector<std::string>>;
struct Setting { struct Variable {
std::string name; std::string name;
std::string comment; std::string help;
mpark::variant<bool, std::string> val; mpark::variant<bool, std::string> value;
bool cache = false; bool cache = false;
bool force = false; bool force = false;
}; };
struct Option { struct Option {
std::string name; std::string name;
std::string comment; std::string help;
bool val = false; mpark::variant<bool, std::string> value;
}; };
struct FindPackage { struct Package {
std::string name; std::string name;
std::string condition; std::string condition;
std::string version; std::string version;
@@ -43,9 +45,18 @@ struct Vcpkg {
struct Package { struct Package {
std::string name; std::string name;
std::vector<std::string> features; std::vector<std::string> features;
bool default_features = true;
}; };
std::vector<Package> packages; std::vector<Package> packages;
// https://github.com/Microsoft/vcpkg-docs/blob/main/vcpkg/users/buildsystems/cmake-integration.md
std::vector<std::string> overlay_ports;
std::vector<std::string> overlay_triplets;
bool enabled() const {
return !packages.empty();
}
}; };
enum TargetType { enum TargetType {
@@ -63,11 +74,108 @@ enum TargetType {
extern const char *targetTypeNames[target_last]; extern const char *targetTypeNames[target_last];
struct Target { struct Target {
struct CustomTarget {
bool has_all = false;
bool all = false;
bool has_command = false;
bool has_commands = false;
std::vector<std::vector<std::string>> commands;
std::vector<std::string> depends;
std::vector<std::string> byproducts;
bool has_working_directory = false;
std::string working_directory;
bool has_comment = false;
std::string comment;
bool has_job_pool = false;
std::string job_pool;
bool has_job_server_aware = false;
bool job_server_aware = false;
bool has_verbatim = false;
bool verbatim = false;
bool has_uses_terminal = false;
bool uses_terminal = false;
bool has_command_expand_lists = false;
bool command_expand_lists = false;
bool empty() const {
return !has_all && !has_command && !has_commands && commands.empty() && depends.empty() && byproducts.empty() && !has_working_directory &&
!has_comment && !has_job_pool && !has_job_server_aware && !has_verbatim && !has_uses_terminal && !has_command_expand_lists;
}
};
struct CustomCommand {
struct ImplicitDependency {
std::string language;
std::string file;
};
std::string condition;
std::vector<std::vector<std::string>> commands;
std::vector<std::string> outputs;
std::string build_event;
bool has_append = false;
bool append = false;
bool has_main_dependency = false;
std::string main_dependency;
std::vector<std::string> depends;
std::vector<std::string> byproducts;
std::vector<ImplicitDependency> implicit_depends;
bool has_working_directory = false;
std::string working_directory;
bool has_comment = false;
std::string comment;
bool has_depfile = false;
std::string depfile;
bool has_job_pool = false;
std::string job_pool;
bool has_job_server_aware = false;
bool job_server_aware = false;
bool has_verbatim = false;
bool verbatim = false;
bool has_uses_terminal = false;
bool uses_terminal = false;
bool has_codegen = false;
bool codegen = false;
bool has_command_expand_lists = false;
bool command_expand_lists = false;
bool has_depends_explicit_only = false;
bool depends_explicit_only = false;
bool is_output_form() const {
return !outputs.empty();
}
bool is_target_form() const {
return !build_event.empty();
}
};
std::string name; std::string name;
TargetType type = target_last; TargetType type = target_last;
std::string type_name; std::string type_name;
ConditionVector headers;
ConditionVector sources; ConditionVector sources;
// https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html#project-commands // https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html#project-commands
@@ -95,6 +203,11 @@ struct Target {
ConditionVector precompile_headers; ConditionVector precompile_headers;
ConditionVector private_precompile_headers; ConditionVector private_precompile_headers;
ConditionVector dependencies;
CustomTarget custom_target;
std::vector<CustomCommand> custom_commands;
std::string condition; std::string condition;
std::string alias; std::string alias;
Condition<tsl::ordered_map<std::string, std::string>> properties; Condition<tsl::ordered_map<std::string, std::string>> properties;
@@ -108,6 +221,7 @@ struct Target {
struct Template { struct Template {
Target outline; Target outline;
std::string add_function; std::string add_function;
std::vector<std::string> add_arguments;
bool pass_sources_to_add_function = false; bool pass_sources_to_add_function = false;
}; };
@@ -128,6 +242,7 @@ struct Install {
std::vector<std::string> configs; std::vector<std::string> configs;
std::string destination; std::string destination;
std::string component; std::string component;
bool optional = false;
}; };
struct Subdir { struct Subdir {
@@ -140,26 +255,35 @@ struct Subdir {
ConditionVector include_after; ConditionVector include_after;
}; };
struct ContentOption {
mpark::variant<bool, std::string> value;
};
struct Content { struct Content {
std::string name; std::string name;
std::string condition; std::string condition;
tsl::ordered_map<std::string, std::string> arguments; tsl::ordered_map<std::string, std::string> arguments;
tsl::ordered_map<std::string, ContentOption> options;
Condition<std::string> cmake_before; Condition<std::string> cmake_before;
Condition<std::string> cmake_after; Condition<std::string> cmake_after;
ConditionVector include_before; ConditionVector include_before;
ConditionVector include_after; ConditionVector include_after;
bool system = false;
std::string subdir;
}; };
struct Package { enum MsvcRuntimeType {
std::string name; msvc_dynamic,
std::vector<std::string> targets; msvc_static,
std::vector<std::string> headers; msvc_last,
std::vector<std::string> dependencies;
std::string namespace_name;
}; };
extern const char *msvcRuntimeTypeNames[msvc_last];
struct Project { struct Project {
const Project *parent;
// This is the CMake version required to use all cmkr versions. // This is the CMake version required to use all cmkr versions.
std::string cmake_version = "3.15"; std::string cmake_version = "3.15";
std::string cmkr_include = "cmkr.cmake"; std::string cmkr_include = "cmkr.cmake";
@@ -176,16 +300,17 @@ struct Project {
std::string project_name; std::string project_name;
std::string project_version; std::string project_version;
std::string project_description; std::string project_description;
std::vector<std::string> project_languages; ConditionVector project_languages;
bool project_allow_unknown_languages = false;
MsvcRuntimeType project_msvc_runtime = msvc_last;
Condition<std::string> cmake_before; Condition<std::string> cmake_before;
Condition<std::string> cmake_after; Condition<std::string> cmake_after;
ConditionVector include_before; ConditionVector include_before;
ConditionVector include_after; ConditionVector include_after;
std::vector<Setting> settings; std::vector<Variable> variables;
std::vector<Option> options; std::vector<Option> options;
std::vector<FindPackage> packages; std::vector<Package> packages;
Vcpkg vcpkg; Vcpkg vcpkg;
Package package;
std::vector<Content> contents; std::vector<Content> contents;
std::vector<Template> templates; std::vector<Template> templates;
std::vector<Target> targets; std::vector<Target> targets;
@@ -195,9 +320,12 @@ struct Project {
std::vector<Subdir> subdirs; std::vector<Subdir> subdirs;
Project(const Project *parent, const std::string &path, bool build); Project(const Project *parent, const std::string &path, bool build);
const Project *root() const;
bool cmake_minimum_version(int major, int minor) const;
static bool is_condition_name(const std::string &name);
}; };
bool is_root_path(const std::string &path); bool is_root_path(const std::string &path);
} // namespace parser } // namespace parser
} // namespace cmkr } // namespace cmkr
+4 -16
View File
@@ -2,10 +2,8 @@
#include "build.hpp" #include "build.hpp"
#include "cmake_generator.hpp" #include "cmake_generator.hpp"
#include "help.hpp" #include "help.hpp"
#include "fs.hpp" #include "fs.hpp"
#include <exception>
#include <iostream>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -37,17 +35,17 @@ const char *handle_args(int argc, char **argv) {
} else if (main_arg == "build") { } else if (main_arg == "build") {
auto ret = build::run(argc, argv); auto ret = build::run(argc, argv);
if (ret) if (ret)
return "CMake build error!"; throw std::runtime_error("CMake build failed!");
return "CMake build completed!"; return "CMake build completed!";
} else if (main_arg == "install") { } else if (main_arg == "install") {
auto ret = build::install(); auto ret = build::install();
if (ret) if (ret)
return "CMake install error!"; throw std::runtime_error("CMake install failed!");
return "CMake install completed!"; return "CMake install completed!";
} else if (main_arg == "clean") { } else if (main_arg == "clean") {
auto ret = build::clean(); auto ret = build::clean();
if (ret) if (ret)
return "CMake clean error!"; throw std::runtime_error("CMake clean failed!");
return "Cleaned build directory!"; return "Cleaned build directory!";
} else { } else {
throw std::runtime_error(cmkr::help::message()); throw std::runtime_error(cmkr::help::message());
@@ -55,13 +53,3 @@ const char *handle_args(int argc, char **argv) {
} }
} // namespace args } // namespace args
} // namespace cmkr } // namespace cmkr
const char *cmkr_args_handle_args(int argc, char **argv) {
try {
return cmkr::args::handle_args(argc, argv);
} catch (const std::exception &e) {
return e.what();
} catch (...) {
return "Unknown error!";
}
}
+4 -38
View File
@@ -1,14 +1,10 @@
#include "build.hpp" #include "build.hpp"
#include "cmake_generator.hpp" #include "cmake_generator.hpp"
#include "error.hpp"
#include "project_parser.hpp" #include "project_parser.hpp"
#include "fs.hpp" #include "fs.hpp"
#include <cstddef>
#include <cstdlib> #include <cstdlib>
#include <sstream> #include <sstream>
#include <stdexcept>
#include <system_error>
namespace cmkr { namespace cmkr {
namespace build { namespace build {
@@ -17,7 +13,7 @@ int run(int argc, char **argv) {
parser::Project project(nullptr, ".", true); parser::Project project(nullptr, ".", true);
if (argc > 2) { if (argc > 2) {
for (int i = 2; i < argc; ++i) { for (int i = 2; i < argc; ++i) {
project.build_args.push_back(argv[i]); project.build_args.emplace_back(argv[i]);
} }
} }
std::stringstream ss; std::stringstream ss;
@@ -48,13 +44,13 @@ int run(int argc, char **argv) {
} }
int clean() { int clean() {
bool ret = false; bool success = false;
parser::Project project(nullptr, ".", true); parser::Project project(nullptr, ".", true);
if (fs::exists(project.build_dir)) { if (fs::exists(project.build_dir)) {
ret = fs::remove_all(project.build_dir); success = fs::remove_all(project.build_dir);
fs::create_directory(project.build_dir); fs::create_directory(project.build_dir);
} }
return !ret; return success ? EXIT_SUCCESS : EXIT_FAILURE;
} }
int install() { int install() {
@@ -64,33 +60,3 @@ int install() {
} }
} // namespace build } // namespace build
} // namespace cmkr } // namespace cmkr
int cmkr_build_run(int argc, char **argv) {
try {
return cmkr::build::run(argc, argv);
} catch (const std::system_error &e) {
return e.code().value();
} catch (...) {
return cmkr::error::Status(cmkr::error::Status::Code::BuildError);
}
}
int cmkr_build_clean(void) {
try {
return cmkr::build::clean();
} catch (const std::system_error &e) {
return e.code().value();
} catch (...) {
return cmkr::error::Status(cmkr::error::Status::Code::CleanError);
}
}
int cmkr_build_install(void) {
try {
return cmkr::build::install();
} catch (const std::system_error &e) {
return e.code().value();
} catch (...) {
return cmkr::error::Status(cmkr::error::Status::Code::InstallError);
}
}
+1117 -348
View File
File diff suppressed because it is too large Load Diff
-25
View File
@@ -1,25 +0,0 @@
#include "error.hpp"
#include <cassert>
namespace cmkr {
namespace error {
Status::Status(Code ec) noexcept : ec_(ec) {}
Status::operator int() const noexcept { return static_cast<int>(ec_); }
Status::Code Status::code() const noexcept { return ec_; }
} // namespace error
} // namespace cmkr
// strings for cmkr::error::Status::Code
static const char *err_string[] = {
"Success", "Runtime error", "Initialization error", "CMake generation error", "Build error", "Clean error", "Install error",
};
const char *cmkr_error_status(int i) {
assert(i >= 0 && i < (sizeof(err_string) / sizeof(*(err_string))));
return err_string[i];
}
+3 -5
View File
@@ -4,7 +4,9 @@
namespace cmkr { namespace cmkr {
namespace help { namespace help {
const char *version() noexcept { return "cmkr version " CMKR_VERSION; } const char *version() noexcept {
return "cmkr version " CMKR_VERSION;
}
const char *message() noexcept { const char *message() noexcept {
return R"lit( return R"lit(
@@ -21,7 +23,3 @@ arguments:
} }
} // namespace help } // namespace help
} // namespace cmkr } // namespace cmkr
const char *cmkr_help_version(void) { return cmkr::help::version(); }
const char *cmkr_help_message(void) { return cmkr::help::message(); }
+700 -73
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -1,3 +1,4 @@
# These will be generated by cmkr, so no point in tracking them # These will be generated by cmkr, so no point in tracking them
**/CMakeLists.txt **/CMakeLists.txt
**/cmkr.cmake **/cmkr.cmake
**/vcpkg.json
+81 -8
View File
@@ -14,7 +14,7 @@ add_test(
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/basic" "${CMAKE_CURRENT_LIST_DIR}/basic"
COMMAND COMMAND
$<TARGET_FILE:cmkr> "$<TARGET_FILE:cmkr>"
build build
) )
@@ -24,7 +24,7 @@ add_test(
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/interface" "${CMAKE_CURRENT_LIST_DIR}/interface"
COMMAND COMMAND
$<TARGET_FILE:cmkr> "$<TARGET_FILE:cmkr>"
build build
) )
@@ -34,7 +34,7 @@ add_test(
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/fetch-content" "${CMAKE_CURRENT_LIST_DIR}/fetch-content"
COMMAND COMMAND
$<TARGET_FILE:cmkr> "$<TARGET_FILE:cmkr>"
build build
) )
@@ -44,7 +44,7 @@ add_test(
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/conditions" "${CMAKE_CURRENT_LIST_DIR}/conditions"
COMMAND COMMAND
$<TARGET_FILE:cmkr> "$<TARGET_FILE:cmkr>"
build build
) )
@@ -54,7 +54,7 @@ add_test(
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/vcpkg" "${CMAKE_CURRENT_LIST_DIR}/vcpkg"
COMMAND COMMAND
$<TARGET_FILE:cmkr> "$<TARGET_FILE:cmkr>"
build build
) )
@@ -64,7 +64,7 @@ add_test(
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/cxx-standard" "${CMAKE_CURRENT_LIST_DIR}/cxx-standard"
COMMAND COMMAND
$<TARGET_FILE:cmkr> "$<TARGET_FILE:cmkr>"
build build
) )
@@ -74,7 +74,7 @@ add_test(
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/globbing" "${CMAKE_CURRENT_LIST_DIR}/globbing"
COMMAND COMMAND
$<TARGET_FILE:cmkr> "$<TARGET_FILE:cmkr>"
build build
) )
@@ -84,7 +84,80 @@ add_test(
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/templates" "${CMAKE_CURRENT_LIST_DIR}/templates"
COMMAND COMMAND
$<TARGET_FILE:cmkr> "$<TARGET_FILE:cmkr>"
build build
) )
if(MSVC) # msvc
add_test(
NAME
msvc-runtime
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/msvc-runtime"
COMMAND
"$<TARGET_FILE:cmkr>"
build
)
endif()
add_test(
NAME
compile-options
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/compile-options"
COMMAND
"$<TARGET_FILE:cmkr>"
build
)
if(WIN32) # windows
add_test(
NAME
relative-paths
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/relative-paths"
COMMAND
"$<TARGET_FILE:cmkr>"
build
)
endif()
add_test(
NAME
objective-c
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/objective-c"
COMMAND
"$<TARGET_FILE:cmkr>"
build
)
add_test(
NAME
custom-command
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/custom-command"
COMMAND
"$<TARGET_FILE:cmkr>"
build
)
add_test(
NAME
generator-executable
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/generator-executable"
COMMAND
"$<TARGET_FILE:cmkr>"
build
)
add_test(
NAME
protobuf
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/protobuf"
COMMAND
"$<TARGET_FILE:cmkr>"
build
)
+1 -1
View File
@@ -8,4 +8,4 @@ description = "Minimal example"
type = "executable" type = "executable"
sources = ["src/basic.cpp"] sources = ["src/basic.cpp"]
# Declares an executable target called `basic` with `src/basic.cpp` as a source file. Equivalent to CMake's [add_executable](https://cmake.org/cmake/help/latest/command/add_executable.html)`(basic src/basic.cpp)`. # Declares an executable target called `basic` with `src/basic.cpp` as a source file. Equivalent to CMake's [add_executable](https://cmake.org/cmake/help/latest/command/add_executable.html)`(basic src/basic.cpp)`.
+41 -3
View File
@@ -47,7 +47,45 @@ command = "$<TARGET_FILE:cmkr>"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "package" condition = "msvc"
working-directory = "package" name = "msvc-runtime"
working-directory = "msvc-runtime"
command = "$<TARGET_FILE:cmkr>" command = "$<TARGET_FILE:cmkr>"
arguments = ["build"] arguments = ["build"]
[[test]]
name = "compile-options"
working-directory = "compile-options"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
[[test]]
condition = "windows"
name = "relative-paths"
working-directory = "relative-paths"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
[[test]]
name = "objective-c"
working-directory = "objective-c"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
[[test]]
name = "custom-command"
working-directory = "custom-command"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
[[test]]
name = "generator-executable"
working-directory = "generator-executable"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
[[test]]
name = "protobuf"
working-directory = "protobuf"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
+18
View File
@@ -0,0 +1,18 @@
# Example project that sets compiler flags and preprocessor defines for various platforms.
[project]
name = "compile-options"
description = "Compiler flags"
[target.hello]
type = "executable"
sources = ["src/main.cpp"]
msvc.compile-options = ["/W2"]
msvc.compile-definitions = ["PLATFORM=\"msvc\""]
gcc.compile-options = ["-Wall"]
gcc.compile-definitions = ["PLATFORM=\"gcc\""]
clang.compile-options = ["-Wall"]
clang.compile-definitions = ["PLATFORM=\"clang\""]
# The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags and definitions depending on the platform. See the [targets](/cmake-toml/#targets) documentation for other things you can set.
# _Note_: In general you only want to specify flags _required_ to compile your code without errors.
+5
View File
@@ -0,0 +1,5 @@
#include <cstdio>
int main() {
puts("Hello from cmkr!");
}
+28 -23
View File
@@ -1,23 +1,28 @@
[project] [project]
name = "conditions" name = "conditions"
cmake-after = "set(CUSTOM ON)" cmake-after = "set(CUSTOM ON)"
[conditions] [options]
custom = "CUSTOM" CONDITIONS_BUILD_TESTS = "root"
[target.example] [conditions]
type = "executable" custom = "CUSTOM"
sources = ["src/main.cpp"]
windows.sources = ["src/windows_specific.cpp"] [target.example]
cmake-after = "message(STATUS cmake-after)" type = "executable"
windows.cmake-after = "message(STATUS win32-after)" sources = ["src/main.cpp"]
macos.cmake-after = "message(STATUS macos-after)" windows.sources = ["src/windows_specific.cpp"]
linux.cmake-after = "message(STATUS linux-after)" cmake-after = "message(STATUS cmake-after)"
unix.cmake-after = "message(STATUS unix-after)" windows.cmake-after = "message(STATUS win32-after)"
custom.cmake-after = "message(STATUS custom-after)" macos.cmake-after = "message(STATUS macos-after)"
linux.cmake-after = "message(STATUS linux-after)"
[target.example.properties] unix.cmake-after = "message(STATUS unix-after)"
AUTOMOC = false custom.cmake-after = "message(STATUS custom-after)"
custom.OUTPUT_NAME = "example2" build-tests.cmake-after = "message(STATUS build-tests)"
custom.AUTORCC = true "CONDITIONS_BUILD_TESTS AND $<linux>".cmake-after = "message(STATUS linux-tests)"
AUTOGEN = "ON"
[target.example.properties]
AUTOMOC = false
custom.OUTPUT_NAME = "example2"
custom.AUTORCC = true
AUTOGEN = "ON"
+2 -1
View File
@@ -1 +1,2 @@
int main() { } int main() {
}
@@ -1,3 +1,4 @@
#include <Windows.h> #include <Windows.h>
void foo() { } void foo() {
}
+123
View File
@@ -0,0 +1,123 @@
# This test demonstrates add_custom_command and add_custom_target support in cmkr.
#
# There are two forms of add_custom_command in CMake:
# 1. Output form: generates files that can be consumed by other targets
# 2. Target form: runs commands at build time for a specific target (pre-build, pre-link, post-build)
[project]
name = "custom-command"
description = "Tests add_custom_command and add_custom_target support"
# -----------------------------------------------------------------------------
# Simple executable demonstrating post-build events
# -----------------------------------------------------------------------------
[target.hello]
type = "executable"
sources = ["src/hello.cpp"]
# This post-build command runs after the 'hello' executable is built.
# build-event can be: "pre-build", "pre-link", or "post-build"
[[target.hello.custom-command]]
build-event = "post-build"
command = ["${CMAKE_COMMAND}", "-E", "echo", "Built executable: $<TARGET_FILE_NAME:hello>"]
comment = "Print the built executable name"
# -----------------------------------------------------------------------------
# Executable with code generation (output form custom command)
# -----------------------------------------------------------------------------
[target.custom-command]
type = "executable"
sources = ["src/main.cpp"]
include-directories = ["${CMAKE_CURRENT_BINARY_DIR}/generated"]
# Output form: This custom command generates source files before building.
# Relative outputs follow CMake and are interpreted from the binary directory.
# The outputs are automatically added as sources to the target.
[[target.custom-command.custom-command]]
outputs = ["generated/generated.cpp"]
byproducts = ["generated/generated.hpp"]
depends = ["cmake/generate_source.cmake"]
command = [
"${CMAKE_COMMAND}",
"-DOUTPUT_CPP=${CMAKE_CURRENT_BINARY_DIR}/generated/generated.cpp",
"-DOUTPUT_HPP=${CMAKE_CURRENT_BINARY_DIR}/generated/generated.hpp",
"-P",
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/generate_source.cmake",
]
comment = "Generate source files"
verbatim = true
# Target form: This post-build command runs after 'custom-command' is built.
[[target.custom-command.custom-command]]
build-event = "post-build"
command = [
"${CMAKE_COMMAND}",
"-E",
"touch",
"${CMAKE_CURRENT_BINARY_DIR}/custom-command-post-build.stamp",
]
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/custom-command-post-build.stamp"]
comment = "Create a post-build stamp file"
verbatim = true
# -----------------------------------------------------------------------------
# Custom target (add_custom_target)
# -----------------------------------------------------------------------------
# A custom target runs commands independently of any executable/library.
# Setting 'all = true' makes it run as part of the default build.
[target.custom-codegen]
type = "custom"
all = true
command = [
"${CMAKE_COMMAND}",
"-E",
"touch",
"${CMAKE_CURRENT_BINARY_DIR}/custom-target.stamp",
]
byproducts = ["${CMAKE_CURRENT_BINARY_DIR}/custom-target.stamp"]
comment = "Run custom target"
verbatim = true
# -----------------------------------------------------------------------------
# Template-based custom target
# -----------------------------------------------------------------------------
# Custom target options should also work when the target type comes from a template.
[template.generated-custom-target]
type = "custom"
all = true
verbatim = true
[target.custom-codegen-template]
type = "generated-custom-target"
command = [
"${CMAKE_COMMAND}",
"-DINPUT=${CMAKE_CURRENT_BINARY_DIR}/template-custom-target.stamp",
"-P",
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/verify_file_exists.cmake",
]
comment = "Verify the generated stamp exists"
# The output-form custom command should automatically become a dependency of the
# custom target, so the verification command sees the stamp file.
[[target.custom-codegen-template.custom-command]]
outputs = ["template-custom-target.stamp"]
command = [
"${CMAKE_COMMAND}",
"-E",
"touch",
"${CMAKE_CURRENT_BINARY_DIR}/template-custom-target.stamp",
]
comment = "Create a stamp file for the template-based custom target"
verbatim = true
# A target-level all = false should override the template's all = true.
# If this target is incorrectly included in the default build, the build fails.
[target.custom-codegen-template-disabled]
type = "generated-custom-target"
all = false
command = ["${CMAKE_COMMAND}", "-E", "false"]
comment = "This target must not run as part of the default build"
@@ -0,0 +1,13 @@
if(NOT DEFINED OUTPUT_CPP)
message(FATAL_ERROR "OUTPUT_CPP is required")
endif()
if(NOT DEFINED OUTPUT_HPP)
message(FATAL_ERROR "OUTPUT_HPP is required")
endif()
get_filename_component(_output_dir "${OUTPUT_CPP}" DIRECTORY)
file(MAKE_DIRECTORY "${_output_dir}")
file(WRITE "${OUTPUT_HPP}" "#pragma once\n#define GENERATED_VALUE 42\n")
file(WRITE "${OUTPUT_CPP}" "#include \"generated.hpp\"\nint generated_value() { return GENERATED_VALUE; }\n")
@@ -0,0 +1,9 @@
if(NOT DEFINED INPUT)
message(FATAL_ERROR "INPUT is required")
endif()
if(NOT EXISTS "${INPUT}")
message(FATAL_ERROR "Expected file not found: ${INPUT}")
endif()
message(STATUS "Verified file exists: ${INPUT}")
+6
View File
@@ -0,0 +1,6 @@
#include <iostream>
int main() {
std::cout << "Hello, world!" << std::endl;
return 0;
}
+7
View File
@@ -0,0 +1,7 @@
#include "generated.hpp"
int generated_value();
int main() {
return generated_value() == GENERATED_VALUE ? 0 : 1;
}
+12 -12
View File
@@ -1,12 +1,12 @@
# Require a C++11 compiler for the target `example`. # Require a C++11 compiler for the target `example`.
[project] [project]
name = "cxx-standard" name = "cxx-standard"
description = "Changing C++ standard" description = "Changing C++ standard"
[target.example] [target.example]
type = "executable" type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
compile-features = ["cxx_std_11"] compile-features = ["cxx_std_11"]
# This is equivalent to CMake's [target_compile_features](https://cmake.org/cmake/help/latest/command/target_compile_features.html)`(example PRIVATE cxx_std_11)`. For more information on available C/C++ standards and features see [cmake-compile-features(7)](https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html). # This is equivalent to CMake's [target_compile_features](https://cmake.org/cmake/help/latest/command/target_compile_features.html)`(example PRIVATE cxx_std_11)`. For more information on available C/C++ standards and features see [cmake-compile-features(7)](https://cmake.org/cmake/help/latest/manual/cmake-compile-features.7.html).
+7 -8
View File
@@ -1,8 +1,7 @@
#include <cstdio> #include <cstdio>
#include <tuple> #include <tuple>
int main() int main() {
{ auto tpl = std::make_tuple(1, 2);
auto tpl = std::make_tuple(1, 2); printf("Hello from C++11 %d\n", std::get<0>(tpl));
printf("Hello from C++11 %d\n", std::get<0>(tpl)); }
}
+4 -3
View File
@@ -4,12 +4,13 @@
name = "fetch-content" name = "fetch-content"
description = "Fetching from git" description = "Fetching from git"
[fetch-content] [fetch-content.fmt]
fmt = { git = "https://github.com/fmtlib/fmt", tag = "7.1.3" } git = "https://github.com/fmtlib/fmt"
tag = "7.1.3"
[target.example] [target.example]
type = "executable" type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
link-libraries = ["fmt::fmt"] link-libraries = ["fmt::fmt"]
# This is equivalent to calling CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html). # This is equivalent to calling CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html).
+2 -3
View File
@@ -1,6 +1,5 @@
#include <fmt/core.h> #include <fmt/core.h>
int main() int main() {
{
fmt::print("Hello, world!\n"); fmt::print("Hello, world!\n");
} }
+54
View File
@@ -0,0 +1,54 @@
# This test demonstrates a common pattern: using an executable to generate sources
# for another target. The generator runs at build time and produces code that is
# consumed by the main executable.
#
# CMake handles the dependency automatically: the generator executable is built
# first, then it runs to produce the generated sources, and finally the main
# executable is built using those sources.
[project]
name = "generator-executable"
description = "Tests using an executable to generate sources for another target"
# -----------------------------------------------------------------------------
# Generator executable: produces code at build time
# -----------------------------------------------------------------------------
[target.generate_numbers]
type = "executable"
sources = ["src/generate_numbers.cpp"]
# Post-build: confirm the generator was built
[[target.generate_numbers.custom-command]]
build-event = "post-build"
command = ["${CMAKE_COMMAND}", "-E", "echo", "Generator built successfully: $<TARGET_FILE_NAME:generate_numbers>"]
comment = "Confirm generator executable was built"
# -----------------------------------------------------------------------------
# Main executable: uses generated sources
# -----------------------------------------------------------------------------
[target.main]
type = "executable"
sources = ["src/main.cpp"]
include-directories = ["${CMAKE_CURRENT_BINARY_DIR}/generated"]
# Create the generated directory before the generator runs.
cmake-before = """
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/generated")
"""
# Output form custom command: runs the generate_numbers executable to generate sources.
# The outputs are automatically added as sources to this target.
# The DEPENDS on "generate_numbers" ensures the generator is built before this runs.
[[target.main.custom-command]]
outputs = ["${CMAKE_CURRENT_BINARY_DIR}/generated/numbers.cpp"]
depends = ["generate_numbers"]
command = ["$<TARGET_FILE:generate_numbers>", "${CMAKE_CURRENT_BINARY_DIR}/generated/numbers.cpp"]
comment = "Run generate_numbers to generate numbers.cpp"
# Post-build: run the executable to verify it works
[[target.main.custom-command]]
build-event = "post-build"
command = ["$<TARGET_FILE:main>"]
comment = "Run the main executable to verify generated code works"
@@ -0,0 +1,44 @@
// Simple code generator that produces a C++ source file with a function
// that returns a vector of numbers.
#include <fstream>
#include <iostream>
#include <string>
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <output_file>" << std::endl;
return 1;
}
std::string output_path = argv[1];
// The example ensures the output directory exists before invoking the generator.
std::ofstream out(output_path);
if (!out) {
std::cerr << "Failed to open: " << output_path << std::endl;
return 1;
}
out << "// Auto-generated by codegen - DO NOT EDIT\n";
out << "#include <vector>\n";
out << "#include <cstddef>\n";
out << "\n";
out << "std::vector<int> get_numbers() {\n";
out << " return {";
for (int i = 1; i <= 10; ++i) {
if (i > 1)
out << ", ";
out << i * i; // 1, 4, 9, 16, 25, 36, 49, 64, 81, 100
}
out << "};\n";
out << "}\n";
out << "\n";
out << "std::size_t get_numbers_count() {\n";
out << " return 10;\n";
out << "}\n";
std::cout << "Generated: " << output_path << std::endl;
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
// Main executable that uses the generated code
#include <iostream>
#include <vector>
// Functions generated by codegen executable
std::vector<int> get_numbers();
std::size_t get_numbers_count();
int main() {
std::cout << "Numbers from generated code:" << std::endl;
auto numbers = get_numbers();
for (std::size_t i = 0; i < numbers.size(); ++i) {
std::cout << " numbers[" << i << "] = " << numbers[i] << std::endl;
}
// Verify the count
if (numbers.size() == get_numbers_count()) {
std::cout << "Success: Generated " << numbers.size() << " numbers!" << std::endl;
return 0;
} else {
std::cerr << "Error: Count mismatch!" << std::endl;
return 1;
}
}
+18 -18
View File
@@ -1,18 +1,18 @@
[project] [project]
name = "globbing" name = "globbing"
description = "Globbing sources" description = "Globbing sources"
# Recursively glob in the mylib/ folder # Recursively glob in the mylib/ folder
[target.mylib] [target.mylib]
type = "static" type = "static"
alias = "mylib::mylib" alias = "mylib::mylib"
sources = ["mylib/**.hpp", "mylib/**.cpp"] sources = ["mylib/**.hpp", "mylib/**.cpp"]
include-directories = ["mylib/include"] include-directories = ["mylib/include"]
# Single-folder glob in example/src/ # Single-folder glob in example/src/
[target.example] [target.example]
type = "executable" type = "executable"
sources = ["example/src/*.cpp"] sources = ["example/src/*.cpp"]
link-libraries = ["mylib::mylib"] link-libraries = ["mylib::mylib"]
# As you can see in the example above you can use `**.ext` to glob recursively and `*.ext` to glob non-recursively. This **does not** generate `file(GLOB ...)` commands, but instead globs when cmkr is run. Files are sorted to give deterministic results regardless of the platform used. # As you can see in the example above you can use `**.ext` to glob recursively and `*.ext` to glob non-recursively. This **does not** generate `file(GLOB ...)` commands, but instead globs when cmkr is run. Files are sorted to give deterministic results regardless of the platform used.
+7 -7
View File
@@ -1,7 +1,7 @@
#include <iostream> #include <iostream>
#include <mylib/mylib.hpp> #include <mylib/mylib.hpp>
int main() { int main() {
std::cout << mylib::message() << std::endl; std::cout << mylib::message() << std::endl;
return 0; return 0;
} }
+7 -8
View File
@@ -1,8 +1,7 @@
#pragma once #pragma once
#include <string> #include <string>
namespace mylib namespace mylib {
{ std::string message();
std::string message(); } // namespace mylib
}
+5 -6
View File
@@ -1,6 +1,5 @@
#include <mylib/mylib.hpp> #include <mylib/mylib.hpp>
std::string mylib::message() std::string mylib::message() {
{ return "cmkr is awesome!";
return "cmkr is awesome!"; }
}
+13 -13
View File
@@ -1,13 +1,13 @@
[project] [project]
name = "interface" name = "interface"
description = "Header-only library" description = "Header-only library"
[target.mylib] [target.mylib]
type = "interface" type = "interface"
include-directories = ["include"] include-directories = ["include"]
compile-features = ["cxx_std_11"] compile-features = ["cxx_std_11"]
[target.example] [target.example]
type = "executable" type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
link-libraries = ["mylib"] link-libraries = ["mylib"]
+5 -4
View File
@@ -1,4 +1,5 @@
namespace mylib namespace mylib {
{ static const char *version() {
static const char* version() { return "v1.0"; } return "v1.0";
} // namespace mylib }
} // namespace mylib
+7 -8
View File
@@ -1,8 +1,7 @@
#include <cstdio> #include <cstdio>
#include "mylib/mylib.hpp" #include "mylib/mylib.hpp"
int main() int main() {
{ printf("mylib version: %s\n", mylib::version());
printf("mylib version: %s\n", mylib::version()) }
}
+15
View File
@@ -0,0 +1,15 @@
[project]
name = "msvc-runtime"
description = "Static MSVC runtime"
msvc-runtime = "static"
# This target will compile with a static runtime
[target.static-runtime]
type = "executable"
sources = ["src/main.cpp"]
# This target overrides the [project].msvc-runtime
[target.dynamic-runtime]
type = "executable"
sources = ["src/main.cpp"]
msvc-runtime = "dynamic"
+5
View File
@@ -0,0 +1,5 @@
#include <cstdio>
int main() {
puts("Hello from cmkr(msvc-static)!");
}
+13
View File
@@ -0,0 +1,13 @@
# Add Objective-C sources on Apple platforms:
[project]
name = "objective-c"
description = "Objective-C"
languages = ["C"]
apple.languages = ["OBJC"]
[target.hello]
type = "executable"
sources = ["src/main.c"]
apple.sources = ["src/apple.m"]
apple.link-libraries = ["$<LINK_LIBRARY:FRAMEWORK,Foundation>"]
+7
View File
@@ -0,0 +1,7 @@
#import <Foundation/Foundation.h>
void platform_specific() {
NSFileHandle *stdout = [NSFileHandle fileHandleWithStandardOutput];
NSString *message = @"Hello from Objective-C!\n";
[stdout writeData:[message dataUsingEncoding:NSUTF8StringEncoding] error:nil];
}
+14
View File
@@ -0,0 +1,14 @@
#include <stdio.h>
#ifdef __APPLE__
void platform_specific();
#else
void platform_specific() {
puts("This is not an Apple platform.");
}
#endif
int main() {
platform_specific();
return 0;
}
-20
View File
@@ -1,20 +0,0 @@
[project]
name = "Utility"
version = "1.2"
[target.Utility]
type = "static"
alias = "Utility::Utility" # autogenerate this alias as ${PROJECT_NAME}::TargetName
sources = [
"src/Utility/*.cpp",
"include/Utility/*.hpp",
]
include-directories = ["include"]
compile-features = ["cxx_std_11"]
[package]
name = "Utility" # defaults to ${PROJECT_NAME}
targets = ["Utility"] # required
headers = ["include/**.hpp", "include/**.h"] # required
dependencies = [] # defaults to all the required packages
namespace = "Utility::" # defaults to ${PROJECT_NAME}::
-9
View File
@@ -1,9 +0,0 @@
#pragma once
#include <string>
namespace String
{
bool startsWith(const std::string& str, const std::string& prefix);
std::string reverse(const std::string& str);
}
-19
View File
@@ -1,19 +0,0 @@
#include <cctype>
#include <algorithm>
#include <Utility/String.hpp>
namespace String
{
bool startsWith(const std::string& str, const std::string& prefix)
{
return str.find(prefix) == 0;
}
std::string reverse(const std::string& str)
{
auto result = str;
std::reverse(result.begin(), result.end());
return result;
}
}
+2
View File
@@ -0,0 +1,2 @@
build/
*.bin
+81
View File
@@ -0,0 +1,81 @@
# This test demonstrates using protobuf with cmkr for code generation.
#
# The example:
# 1. Fetches protobuf from GitHub using FetchContent
# 2. Uses a custom command to generate C++ sources from a .proto file
# 3. Links an executable against the generated sources and protobuf library
# 4. Serializes and deserializes a simple message
#
# Note: protobuf v21.x is used because newer versions (v22+) require abseil-cpp
# as a dependency, which significantly complicates the build.
[cmake]
version = "3.18...3.31"
[project]
name = "protobuf-example"
description = "Demonstrates protobuf integration with cmkr custom commands"
# -----------------------------------------------------------------------------
# Fetch protobuf from GitHub
# Using v21.12 (last version before abseil-cpp became required)
# -----------------------------------------------------------------------------
[fetch-content.protobuf]
git = "https://github.com/protocolbuffers/protobuf"
tag = "v21.12"
options = {
protobuf_BUILD_TESTS = false,
protobuf_BUILD_EXAMPLES = false,
protobuf_BUILD_LIBPROTOC = false,
protobuf_BUILD_SHARED_LIBS = false,
protobuf_MSVC_STATIC_RUNTIME = false,
SKIP_INSTALL_ALL = true,
protobuf_WITH_ZLIB = false,
}
# -----------------------------------------------------------------------------
# Main executable using protobuf
# -----------------------------------------------------------------------------
[target.protobuf_example]
type = "executable"
sources = [
"src/main.cpp",
]
include-directories = [
"${CMAKE_CURRENT_BINARY_DIR}/generated",
]
link-libraries = ["protobuf::libprotobuf"]
compile-features = ["cxx_std_17"]
# Create the generated directory before running protoc
cmake-before = """
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/generated")
"""
# Custom command to generate C++ sources from .proto file
# This uses protoc from the fetched protobuf repository
[[target.protobuf_example.custom-command]]
outputs = [
"${CMAKE_CURRENT_BINARY_DIR}/generated/addressbook.pb.h",
"${CMAKE_CURRENT_BINARY_DIR}/generated/addressbook.pb.cc",
]
depends = [
"${CMAKE_CURRENT_SOURCE_DIR}/proto/addressbook.proto",
"protobuf::protoc", # Ensure protoc is built first
]
command = [
"$<TARGET_FILE:protobuf::protoc>",
"--cpp_out=${CMAKE_CURRENT_BINARY_DIR}/generated",
"-I${CMAKE_CURRENT_SOURCE_DIR}/proto",
"${CMAKE_CURRENT_SOURCE_DIR}/proto/addressbook.proto",
]
comment = "Generate C++ sources from addressbook.proto"
verbatim = true
# Post-build: run the executable to verify it works
[[target.protobuf_example.custom-command]]
build-event = "post-build"
command = ["$<TARGET_FILE:protobuf_example>"]
comment = "Run protobuf_example to verify serialization/deserialization works"
+31
View File
@@ -0,0 +1,31 @@
// A simple address book example demonstrating protobuf serialization.
// Based on the official protobuf tutorial example.
syntax = "proto3";
package tutorial;
// A person with basic contact information
message Person {
string name = 1;
int32 id = 2;
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
}
// An address book containing multiple people
message AddressBook {
repeated Person people = 1;
}
+146
View File
@@ -0,0 +1,146 @@
// Protobuf serialization/deserialization example
// This demonstrates using protobuf with cmkr for code generation
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
// Creates a sample address book with some people
void create_address_book(tutorial::AddressBook &book) {
// Add first person
tutorial::Person *person1 = book.add_people();
person1->set_name("Alice Smith");
person1->set_id(1);
person1->set_email("alice@example.com");
// Add phone numbers for Alice
tutorial::Person::PhoneNumber *phone1 = person1->add_phones();
phone1->set_number("555-1234");
phone1->set_type(tutorial::Person::HOME);
tutorial::Person::PhoneNumber *phone2 = person1->add_phones();
phone2->set_number("555-5678");
phone2->set_type(tutorial::Person::WORK);
// Add second person
tutorial::Person *person2 = book.add_people();
person2->set_name("Bob Johnson");
person2->set_id(2);
person2->set_email("bob@example.com");
tutorial::Person::PhoneNumber *phone3 = person2->add_phones();
phone3->set_number("555-9999");
phone3->set_type(tutorial::Person::MOBILE);
}
// Prints the contents of an address book
void print_address_book(const tutorial::AddressBook &book) {
std::cout << "Address Book (" << book.people_size() << " people):\n";
std::cout << "==========================================\n\n";
for (int i = 0; i < book.people_size(); ++i) {
const tutorial::Person &person = book.people(i);
std::cout << "Person ID: " << person.id() << "\n";
std::cout << " Name: " << person.name() << "\n";
std::cout << " Email: " << person.email() << "\n";
for (int j = 0; j < person.phones_size(); ++j) {
const tutorial::Person::PhoneNumber &phone = person.phones(j);
std::cout << " Phone #" << (j + 1) << ": " << phone.number() << " (";
switch (phone.type()) {
case tutorial::Person::MOBILE:
std::cout << "mobile";
break;
case tutorial::Person::HOME:
std::cout << "home";
break;
case tutorial::Person::WORK:
std::cout << "work";
break;
default:
std::cout << "unknown";
}
std::cout << ")\n";
}
std::cout << "\n";
}
}
int main() {
// Verify that the version of the library that we linked against is
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
std::cout << "Protobuf cmkr Example\n";
std::cout << "=====================\n\n";
// Create an address book
tutorial::AddressBook original_book;
create_address_book(original_book);
std::cout << "Original Address Book:\n";
print_address_book(original_book);
// Serialize to string
std::string serialized;
if (!original_book.SerializeToString(&serialized)) {
std::cerr << "Error: Failed to serialize address book\n";
return 1;
}
std::cout << "Serialized size: " << serialized.size() << " bytes\n\n";
// Deserialize into a new object
tutorial::AddressBook deserialized_book;
if (!deserialized_book.ParseFromString(serialized)) {
std::cerr << "Error: Failed to deserialize address book\n";
return 1;
}
std::cout << "Deserialized Address Book:\n";
print_address_book(deserialized_book);
// Write to file
const char *filename = "addressbook.bin";
{
std::ofstream output(filename, std::ios::binary);
if (!original_book.SerializeToOstream(&output)) {
std::cerr << "Error: Failed to write to file\n";
return 1;
}
}
std::cout << "Written to file: " << filename << "\n";
// Read back from file
tutorial::AddressBook file_book;
{
std::ifstream input(filename, std::ios::binary);
if (!file_book.ParseFromIstream(&input)) {
std::cerr << "Error: Failed to read from file\n";
return 1;
}
}
std::cout << "Read back from file successfully!\n\n";
// Verify all three versions are identical
bool all_match = true;
if (original_book.SerializeAsString() != deserialized_book.SerializeAsString()) {
std::cerr << "Error: Original and deserialized don't match!\n";
all_match = false;
}
if (original_book.SerializeAsString() != file_book.SerializeAsString()) {
std::cerr << "Error: Original and file don't match!\n";
all_match = false;
}
if (all_match) {
std::cout << "SUCCESS: All serialization methods produced identical results!\n";
}
// Clean up any global objects allocated by protobuf
google::protobuf::ShutdownProtobufLibrary();
return all_match ? 0 : 1;
}
+11
View File
@@ -0,0 +1,11 @@
[project]
name = "relative-paths"
[target.test-library]
type = "static"
sources = ["src/library-code.cpp"]
[target.example]
type = "executable"
sources = ["src/main.cpp"]
windows.link-libraries = ["libs/test-library-x64-Release.lib"]
@@ -0,0 +1,6 @@
// Created by Anthony Printup on 9/18/2023.
#include <cstdio>
extern "C" void library_function() {
std::puts("Hello from library_function!");
}
+12
View File
@@ -0,0 +1,12 @@
// Created by Anthony Printup on 9/18/2023.
#include <cstdio>
#ifdef WIN32
extern "C" void library_function();
#endif
int main() {
puts("Hello from cmkr(relative-paths)!");
#ifdef WIN32
library_function();
#endif
}
+5 -5
View File
@@ -8,11 +8,11 @@ description = "Target templates"
type = "executable" type = "executable"
sources = ["src/templates.cpp"] sources = ["src/templates.cpp"]
compile-definitions = ["IS_APP"] compile-definitions = ["IS_APP"]
# Unlike interface targets you can also inherit properties # Unlike interface targets you can also inherit properties
[template.app.properties] properties = {
CXX_STANDARD = "11" CXX_STANDARD = "11",
CXX_STANDARD_REQUIRED = true CXX_STANDARD_REQUIRED = true,
}
[target.app-a] [target.app-a]
type = "app" type = "app"
@@ -22,4 +22,4 @@ compile-definitions = ["APP_A"]
type = "app" type = "app"
compile-definitions = ["APP_B"] compile-definitions = ["APP_B"]
# **Note**: In most cases you probably want to use an [interface](/examples/interface) target instead. # **Note**: In most cases you probably want to use an [interface](/examples/interface) target instead.
+5 -6
View File
@@ -1,17 +1,16 @@
# Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://vcpkg.io/) and links an `example` target to it: # Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://github.com/microsoft/vcpkg) and links an `example` target to it:
[project] [project]
name = "vcpkg" name = "vcpkg"
description = "Dependencies from vcpkg" description = "Dependencies from vcpkg"
# See https://github.com/microsoft/vcpkg/releases for vcpkg versions # See https://github.com/microsoft/vcpkg/releases for vcpkg versions
# See https://vcpkg.io/en/packages.html for available packages # See https://vcpkg.io/en/packages or https://vcpkg.link for available packages
[vcpkg] [vcpkg]
version = "2021.05.12" version = "2024.11.16"
packages = ["fmt"] packages = ["fmt"]
[find-package] [find-package.fmt]
fmt = {}
[target.example] [target.example]
type = "executable" type = "executable"
@@ -19,4 +18,4 @@ sources = ["src/main.cpp"]
link-libraries = ["fmt::fmt"] link-libraries = ["fmt::fmt"]
# The bootstrapping of vcpkg is fully automated and no user interaction is necessary. You can disable vcpkg by setting `CMKR_DISABLE_VCPKG=ON`. # The bootstrapping of vcpkg is fully automated and no user interaction is necessary. You can disable vcpkg by setting `CMKR_DISABLE_VCPKG=ON`.
# To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`. # To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`.
+2 -3
View File
@@ -1,6 +1,5 @@
#include <fmt/core.h> #include <fmt/core.h>
int main() int main() {
{
fmt::print("Hello, world!\n"); fmt::print("Hello, world!\n");
} }
-11
View File
@@ -1,11 +0,0 @@
{
"$cmkr": "This file is automatically generated from cmake.toml - DO NOT EDIT",
"$cmkr-url": "https://github.com/build-cpp/cmkr",
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
"dependencies": [
"fmt"
],
"description": "Dependencies from vcpkg",
"name": "vcpkg",
"version-string": ""
}
+3
View File
@@ -0,0 +1,3 @@
# Disable clang-format in this folder
DisableFormat: true
SortIncludes: Never
Generated Vendored
+4 -7
View File
@@ -9,14 +9,11 @@ add_library(ordered_map INTERFACE)
target_include_directories(ordered_map INTERFACE ordered-map-1.0.0/include) target_include_directories(ordered_map INTERFACE ordered-map-1.0.0/include)
target_compile_definitions(ordered_map INTERFACE NOMINMAX) target_compile_definitions(ordered_map INTERFACE NOMINMAX)
# https://github.com/ToruNiina/toml11 (MIT) # https://github.com/ToruNiina/toml11 (MIT)
add_library(toml11 INTERFACE) add_library(toml11 INTERFACE)
target_include_directories(toml11 INTERFACE toml11-3.6.0) target_include_directories(toml11 INTERFACE toml11-3.8.1)
target_compile_definitions(toml11 INTERFACE TOML11_USE_UNRELEASED_TOML_FEATURES)
# https://github.com/mpark/variant (BSL-1.0) # https://github.com/mpark/variant (BSL-1.0)
add_library(mpark_variant INTERFACE) add_library(mpark_variant INTERFACE)
target_include_directories(mpark_variant INTERFACE variant-1.4.0/include) target_include_directories(mpark_variant INTERFACE variant-1.4.0/include)
# https://github.com/nlohmann/json (MIT)
add_library(nlohmann_json INTERFACE)
target_include_directories(nlohmann_json INTERFACE nlohmann-3.9.1/include)
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2013-2021 Niels Lohmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More