Compare commits

...

227 Commits

Author SHA1 Message Date
Duncan Ogilvie 0a887c08f8 Bump to 0.2.33
5 months ago
Duncan Ogilvie 9f2cfe4083
Merge pull request #146 from build-cpp/improved-conditions
5 months ago
Duncan Ogilvie 15ad1dc6a7 Support nested condition syntax for named conditions
5 months ago
Duncan Ogilvie dabffeaed9 Add back the option name as a named condition
5 months ago
Duncan Ogilvie 59fe5c38b8 Consider PROJECT_OPTION to be a valid condition
5 months ago
Duncan Ogilvie dcdc7ac410 Add a few more default named conditions
5 months ago
Duncan Ogilvie 88377a8bfb Bump to 0.2.32
5 months ago
Duncan Ogilvie 3a9685be82
Merge pull request #145 from build-cpp/system-bug
5 months ago
Duncan Ogilvie 5576789c18 Fix uninitialized 'system' field for fetch-content
5 months ago
Duncan Ogilvie a362978f99 Bump to 0.2.31
5 months ago
Duncan Ogilvie a2f33297e4
Merge pull request #144 from build-cpp/msvc-runtime-subproject
5 months ago
Duncan Ogilvie 674c976647 Do not set CMAKE_MSVC_RUNTIME_LIBRARY if it's already set
5 months ago
Duncan Ogilvie 714a666e88
Merge pull request #143 from build-cpp/project-improvements
6 months ago
Duncan Ogilvie d613e433d5 Skip linting on pull requests for the same repository
6 months ago
Duncan Ogilvie 7c828d8740 Add custom targets for running cmkr/tests
6 months ago
Duncan Ogilvie 559f750c89 Fix undefined behavior with std::tolower/toupper
6 months ago
Duncan Ogilvie 4b6b72874e Remove nlohmann_json
6 months ago
Duncan Ogilvie 6bffa7cc71 Bump to 0.2.30
6 months ago
Duncan Ogilvie f415b432ed Also run linting on pull requests
6 months ago
Duncan Ogilvie 6c46664336
Merge pull request #142 from anthonyprintup/globbing-extension-fix
6 months ago
Duncan Ogilvie f32aac63aa Review improvements
6 months ago
Anthony Printup 33d4cc4156
Fixed globbing when multiple extensions are present in the file name
6 months ago
Duncan Ogilvie 9288c8a87d Bump to 0.2.29
7 months ago
Duncan Ogilvie e36eee4420
Merge pull request #140 from build-cpp/improved-conditions
7 months ago
Duncan Ogilvie 53820c9f65 Support $<condition> in unnamed conditions
7 months ago
Duncan Ogilvie ff7e4b8f23 Allow arbitrary CMake expressions as conditions
7 months ago
Duncan Ogilvie 1072cb44e2 Bump to 0.2.28
7 months ago
Duncan Ogilvie 926fc15fa2
Merge pull request #139 from build-cpp/vcpkg-bump
7 months ago
Duncan Ogilvie e2c929adb0 Fix out-of-the-box vcpkg experience on macos
7 months ago
Duncan Ogilvie 0dec7ca4d5 Bump to the latest vcpkg
8 months ago
Duncan Ogilvie 45e346b4a3 Bump to 0.2.27
8 months ago
Duncan Ogilvie 7165986190
Merge pull request #138 from build-cpp/find-package-first
8 months ago
Duncan Ogilvie be0ef6d615 Generate find-package before fetch-content
8 months ago
Duncan Ogilvie d607b9028c Bump to 0.2.26
1 year ago
Duncan Ogilvie 099b14552c
Merge pull request #131 from build-cpp/fetch-subdir
1 year ago
Duncan Ogilvie 771c80a41a Add [fetch-content].subdir
1 year ago
Duncan Ogilvie 58c7de1d60
Merge pull request #129 from build-cpp/gitignore-improvement
1 year ago
Duncan Ogilvie a61e4bb999
Merge pull request #128 from build-cpp/language-documentation
1 year ago
Duncan Ogilvie 47aaeaf8ce Document the supported languages
1 year ago
Duncan Ogilvie 62609a0088 Improve the default .gitignore that's generated
1 year ago
Duncan Ogilvie e0d8a085db
Merge pull request #121 from anthonyprintup/relative-paths
1 year ago
Duncan Ogilvie 56da4144ae
Merge pull request #125 from anthonyprintup/fix-124
1 year ago
Duncan Ogilvie 9388b3f29d
Merge pull request #123 from anthonyprintup/quotes-fix
1 year ago
Anthony Printup 079644cfeb
fix(generator): Prevent calling `std::string::back` on an empty string
1 year ago
Anthony Printup a7ca9f04c0
fix(relative-paths): Replaced `has_parent_path` with a simpler path check
1 year ago
Anthony Printup 339c2aac94
fix(generator): Prevent command arguments from being quoted when generating tests
1 year ago
Anthony Printup c573c9a76d
test(relative-paths): Add the test-library file to libs
1 year ago
Anthony Printup b24a0a2fdc
test(relative-paths): Make `link-libraries` conditional to the Windows platform
1 year ago
Anthony Printup 854e8817c4
test(relative-paths): Remove inlined CMake from cmake.toml
1 year ago
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
1 year ago
Anthony Printup 19e61aa1aa
test(relative-paths): Attempt to fix the tests workflow
1 year ago
Anthony Printup bfa1e1fe0d
test(relative-paths): Added the latest `relative-paths` test to the tests workflow
1 year ago
Anthony Printup 56bd78f7ad
feat(project-parser): Added support for relative paths in `link-libraries`
1 year ago
Anthony Printup 4362b3547f
test(relative-paths): Added tests for #116
1 year ago
Duncan Ogilvie 08204d9847 Bump to 0.2.25
1 year ago
Duncan Ogilvie 2202aa8173
Merge pull request #120 from anthonyprintup/new-lines-fix
1 year ago
Anthony Printup d3829fb6cd Trim additional new lines at the end of the generated CMakeLists.txt
1 year ago
Duncan Ogilvie 3fb095210a
Merge pull request #118 from ZehMatt/vcpkg-errors
1 year ago
ζeh Matt 9f99365a25
Report better error messages for vcpkg projects and features
1 year ago
Duncan Ogilvie be387141b5 Add a 'Compiler flags' example to the documentation
1 year ago
Duncan Ogilvie 09ded38f70
Merge pull request #115 from build-cpp/clang-cl-condition
1 year ago
Duncan Ogilvie ad90b1ad3e Add 'clang-cl' and 'clang-any' conditions
1 year ago
Duncan Ogilvie 5bfa03d311 Bump to 0.2.24
1 year ago
Duncan Ogilvie bdd9d393d6
Merge pull request #113 from build-cpp/editorconfig
1 year ago
Duncan Ogilvie 1deaec2b41 Add .editorconfig and linting
1 year ago
Duncan Ogilvie cfee3bbc14
Merge pull request #111 from anthonyprintup/fetch-content-system
1 year ago
Anthony Printup bcaa60cabe
feat: Added SYSTEM flag support to fetch-content
1 year ago
Duncan Ogilvie 7b1d33395e Bump to 0.2.23
2 years ago
Duncan Ogilvie 240fafc102
Merge pull request #101 from build-cpp/minor-cleanup
2 years ago
Duncan Ogilvie 7a7ddf2699 Speed up the pipeline by using Ninja
2 years ago
Duncan Ogilvie 605a04e72d Fix formatting of files
2 years ago
Duncan Ogilvie fd7f078127 Add workflow for checking clang-format
2 years ago
Duncan Ogilvie ee0e0d71d9 Remove a bunch of dead code
2 years ago
Duncan Ogilvie 9d6897b572 Suppress warnings related to DOWNLOAD_EXTRACT_TIMESTAMP
2 years ago
Duncan Ogilvie f8c34e5545 Error when [vcpkg] is used from a non-root project
2 years ago
Duncan Ogilvie e6d783ea20 Fix a few clang-tidy warnings
2 years ago
Duncan Ogilvie ee7fe38a7b
Merge pull request #100 from build-cpp/include-subdir-bugfix
2 years ago
Duncan Ogilvie 66b2aad843 Fix a bug where includes in a subdir would not work
2 years ago
Duncan Ogilvie d2e376080a Bump to 0.2.22
2 years ago
Duncan Ogilvie 634908c651
Merge pull request #97 from build-cpp/cmkr-init-regression
2 years ago
Duncan Ogilvie 33911f3f1b Fix a regression where cmkr init wouldn't create any source files
2 years ago
Duncan Ogilvie e650073bef Bump to 0.2.21
2 years ago
Duncan Ogilvie 96e44f7771
Merge pull request #96 from build-cpp/check-sources
2 years ago
Duncan Ogilvie cb9ad5cdb3 Improve error messages and check if specified sources exist
2 years ago
Duncan Ogilvie c785b540d3 Document target templates
2 years ago
Duncan Ogilvie 275b73eefa Remove debug print
2 years ago
Duncan Ogilvie ea49a3acb7 Bump to 0.2.20
2 years ago
Duncan Ogilvie 257e14c869
Merge pull request #93 from build-cpp/gitattributes
2 years ago
Duncan Ogilvie 7508816fe7
Merge pull request #94 from build-cpp/user-experience
2 years ago
Duncan Ogilvie 45678bc5bc Automatically generate .gitattributes and .gitignore with cmkr init
2 years ago
Duncan Ogilvie b869e5646f Add a special "root" value for [options]
2 years ago
Duncan Ogilvie a499df84b1 Bump to 0.2.19
2 years ago
Duncan Ogilvie 49440f99e0
Merge pull request #92 from build-cpp/improved-options
2 years ago
Duncan Ogilvie 0c19c3da0c Improve the code related to [options]
2 years ago
Duncan Ogilvie 233cadadd0
Merge pull request #90 from mike1k/sanity
2 years ago
Duncan Ogilvie 58a5a935e5 Add a bunch of missing languages and extensions and refactor
2 years ago
Duncan Ogilvie e69427bf94
Merge pull request #91 from build-cpp/clang-condition
2 years ago
Duncan Ogilvie bc6359805d Change the `clang` condition to not detect clang-cl
2 years ago
Duncan Ogilvie 8dcc11e349 Add helper function Project::cmake_minimum_version for version-dependent features
2 years ago
Duncan Ogilvie 51dc49e6f1 Improve CI performance for non-tagged builds
2 years ago
mike 7d27c28b59 Fixed failing tests due to implicit project languages (internal list empty)
2 years ago
Duncan Ogilvie ae6bea3b58 Improve reference documentation
2 years ago
Duncan Ogilvie 5a0eda7abc Automatically generate release notes
2 years ago
Duncan Ogilvie f17923c18b Bump to 0.2.18
2 years ago
Duncan Ogilvie ad17890e23
Merge pull request #85 from build-cpp/settings-rename
2 years ago
Duncan Ogilvie c0b98b3ef4 Add documentation for the [variables] section
2 years ago
Duncan Ogilvie 2c6fc569af Preserve backwards compatibility
2 years ago
Duncan Ogilvie 12ee23a44c Improve error messages
2 years ago
Duncan Ogilvie 82342a6b6f Rename [settings] to [variables]
2 years ago
Duncan Ogilvie 1d95fab0ce Switch to giscus for documentation comments
2 years ago
Duncan Ogilvie 44a77329bf
Merge pull request #83 from build-cpp/document-basics
2 years ago
Duncan Ogilvie e68c5fccdc Add utteranc.es comments
2 years ago
Duncan Ogilvie e2722d2c09 Initial draft of new documentation
2 years ago
Duncan Ogilvie 2627864383
Merge pull request #78 from build-cpp/fix-tests
2 years ago
Duncan Ogilvie 05e21f734a Fix the tests
2 years ago
Duncan Ogilvie 1fd18503cd Successfully fail when running cmkr subcommands
2 years ago
Duncan Ogilvie 8b19441d34 Bump to 0.2.17
2 years ago
Duncan Ogilvie 2437eb90fe Minor improvements
2 years ago
Duncan Ogilvie 6e4006ec07 Fix typo in the docs
2 years ago
Duncan Ogilvie 697b638723 Fix warning on macos
2 years ago
Duncan Ogilvie 109c4bc99f Bump to 0.2.16
2 years ago
Duncan Ogilvie cad85f0bb1
Merge pull request #70 from build-cpp/fix-msvc-runtime
2 years ago
Duncan Ogilvie 53c88ceafa Actually generate the set(CMAKE_MSVC_RUNTIME_LIBRARY)
2 years ago
Duncan Ogilvie d2aa15b1c7 Bump to 0.2.15
2 years ago
Duncan Ogilvie e6ded077cf
Merge pull request #65 from gmh5225/feature-msvc-static
2 years ago
Duncan Ogilvie 3615ccab94 Document msvc-runtime feature
2 years ago
Duncan Ogilvie 73622aa5ba Remove the add_test hook to generate tests the same on all platforms
2 years ago
Duncan Ogilvie 69d844a152 Refactor msvc-static to msvc-runtime
2 years ago
gmh5225 af9a117f50
Fix merge
2 years ago
gmh5225 5fe8220728
Merge branch 'feature-msvc-static' of https://github.com/gmh5225/cmkr into feature-msvc-static
2 years ago
gmh5225 28f541cd3c
[feature] add CMP0091
2 years ago
gmh5225 2f3fd7b95e
Merge branch 'main' into feature-msvc-static
2 years ago
Duncan Ogilvie 07d99c582d
Merge pull request #68 from build-cpp/headers-crash
2 years ago
Duncan Ogilvie 5af2385cc3 Fix the way target.headers is merged into target.sources
2 years ago
gmh5225 981c48dbc5
[feature] msvc-static
2 years ago
Duncan Ogilvie 153bdbe591 Bump to 0.2.14
2 years ago
Duncan Ogilvie 97f1c5c1cc Fix a bug when there are regex characters in the path
2 years ago
Duncan Ogilvie 5b6d9c3826 Replace illegal characters in the project name with _ when doing cmkr init
2 years ago
Duncan Ogilvie a90988b81a Update the formatting to now allow functions on a single line
2 years ago
Duncan Ogilvie 3a1298f4e8
Merge pull request #60 from pmeerw/fix-warning
2 years ago
Peter Meerwald-Stadler 534f955827 error: fix warning, signedness of comparison
2 years ago
Duncan Ogilvie ef537ce084 Bump to 0.2.13
3 years ago
Duncan Ogilvie 9cdd0f7344 Escape lists when generating commands
3 years ago
Duncan Ogilvie e69cf4d2b9 Add install.optional flag
3 years ago
Duncan Ogilvie e98a906231 Document the install.component option
3 years ago
Duncan Ogilvie 9a82f8c796 Temporarily remove the crt-linkage and library-linkage options
3 years ago
Duncan Ogilvie 13255c68cf Use FetchContent_MakeAvailable for vcpkg in case they add CMakeLists.txt
3 years ago
Duncan Ogilvie 5768460827
Update credits
3 years ago
Duncan Ogilvie 50d4a905b6
Merge pull request #55 from ZehMatt/fix/#54
3 years ago
ζeh Matt f957cec2dc
Update CMakeLists.txt for tests
3 years ago
Duncan Ogilvie 232e49e087 Add support for vcpkg CRT and library linkage customization
3 years ago
ζeh Matt 7408d42160
Fix #54: Fix settings not being properly quoted
3 years ago
Duncan Ogilvie 1596a8143d Bump to 0.2.12
3 years ago
Duncan Ogilvie 9b0f18ee94 Fix a bug in fetch-content generation
3 years ago
Duncan Ogilvie 887086dc05
Credits
3 years ago
Duncan Ogilvie edc8e1e02e Bump to 0.2.11
3 years ago
Duncan Ogilvie 1f6e31e0ef Add optional CMKR_COMMIT_HASH for the paranoid
3 years ago
Duncan Ogilvie 4de1500bb3 Refactor cmake injection
3 years ago
Duncan Ogilvie 85370968f8 Improved fetch-content support
3 years ago
Duncan Ogilvie 06a4c04df6 Add support for 'shallow' in fetch-content
3 years ago
Duncan Ogilvie fef2a0215b Error when recursively globbing in the project root
3 years ago
Duncan Ogilvie fc74a5e802 Bump to 0.2.10
3 years ago
Duncan Ogilvie e48d402e21 Improve version bumping script
3 years ago
Duncan Ogilvie f6a245618e
Merge pull request #53 from build-cpp/better-validation
3 years ago
Duncan Ogilvie c713606fd4 Error when using an unknown key in the root of the TOML
3 years ago
Duncan Ogilvie fe9b6587a9 Error when trying to parse an empty cmake.toml file
3 years ago
Duncan Ogilvie a2f8d9e5c9 Bump to 0.2.9
3 years ago
Duncan Ogilvie c7925e7110
Merge pull request #52 from build-cpp/fix-options
3 years ago
Duncan Ogilvie c778a5fe2b Do not omit non-optional documentation in option()
3 years ago
Duncan Ogilvie 16b2cbbb57 Add sitemap.xml and robots.txt
3 years ago
Duncan Ogilvie 2f5c7823be Redirect /getting-started to https://cmkr.build
3 years ago
Duncan Ogilvie a29b6a8aaa SEO-friendly permalink
3 years ago
Duncan Ogilvie 5ac8b15c9a Bump to 0.2.8
3 years ago
Duncan Ogilvie e7d9faa6bb
Merge pull request #51 from cursey/improvement/install-component
3 years ago
cursey 6f8b07a801
Allow specifying install component name
3 years ago
Duncan Ogilvie e8c6ccb698 Minor improvements to bootstrapping code
3 years ago
Duncan Ogilvie 539ebc8f4b Host documentation on https://cmkr.build
3 years ago
Duncan Ogilvie 37ca385673 Show vcpkg version when configuring
3 years ago
Duncan Ogilvie 8ae029dab1 Bump to 0.2.7
3 years ago
Duncan Ogilvie fb16cc34b1 Fix a regression with invalid names being generated in vcpkg.json
3 years ago
Duncan Ogilvie 47703871e1 Bump to 0.2.6
3 years ago
Duncan Ogilvie a8d6b15dcb
Merge pull request #47 from cursey/templates
3 years ago
Duncan Ogilvie 87b3c7ec6c Document template targets
3 years ago
Duncan Ogilvie d905be1d13 Final touches
3 years ago
Duncan Ogilvie 8d13ccbeaa Delete driver test to add later
3 years ago
cursey bcbc9d2b20
Remove use of std::make_unique for C++11 compliance
3 years ago
cursey 05324f593b
Improve code reuse for target cmds
3 years ago
cursey 2b7ee72e86
Separate template parsing and generation
3 years ago
cursey 61d5e64d87
Fix parser expecting to always find templates
3 years ago
cursey eed1e38407
Add support for target templates
3 years ago
Duncan Ogilvie 61851d2bee Bump to 0.2.5
3 years ago
Duncan Ogilvie c0d665095e Add script to automatically bump the version
3 years ago
Duncan Ogilvie 6c1e388391 Add root, x64 and x32 conditions
3 years ago
Duncan Ogilvie 04905371b8 Bump to 0.2.4
3 years ago
Duncan Ogilvie 5a6ac44fcf
Merge pull request #46 from build-cpp/expanded-conditions
3 years ago
Duncan Ogilvie 9db82dfd05 Update toml reference
3 years ago
Duncan Ogilvie 459ebb14b5 Support conditions everywhere
3 years ago
Duncan Ogilvie 490869b9a2 Bump to 0.2.3
3 years ago
Duncan Ogilvie 8ae2754994
Merge pull request #45 from cursey/bootstrap-vcpkg-early
3 years ago
cursey 18419297f4
Bootstrap Vcpkg prior to FetchContent
3 years ago
Duncan Ogilvie bdaf5c94e6 Bump to 0.2.2
3 years ago
Duncan Ogilvie fa3b7a346c Emit options and settings before the project()
3 years ago
Duncan Ogilvie df1dbf7953 Bump to 0.2.1
3 years ago
Duncan Ogilvie 5951f6930e Update documentation for vcpkg features
3 years ago
Duncan Ogilvie a6d5f1c99b
Merge pull request #41 from cursey/vcpkg-package-features
3 years ago
Duncan Ogilvie dc852b9a2f Run clang-format
3 years ago
cursey 66621a9818
Fix spacing
3 years ago
cursey 2cd8ad0f18
Add missing const
3 years ago
cursey 084cbd6159
Cleanup vcpkg.json generation a little
3 years ago
cursey b4b0f533a9
Validate vcpkg features
3 years ago
cursey 0acc9b4e5a
Report the badly formed package name to the user
3 years ago
cursey 61dfb0eb60
Fix tabbing in vcpkg.json for packages that have features
3 years ago
cursey 3201fd052e
Add support for vcpkg package features
3 years ago
Duncan Ogilvie 83087ff06e Release v0.2.0 (finally)
3 years ago
Duncan Ogilvie 88e9241e9f Improve onboarding experience
3 years ago
Duncan Ogilvie eff967277d Update README with a migration guide
3 years ago
Duncan Ogilvie ea01497246 Bump CMKR_TAG
3 years ago
Duncan Ogilvie 04bf40a5a6 Generate resources/version.hpp with the project version
3 years ago
Duncan Ogilvie 4d14395994 Implement support a CMKR_CACHE environment variable
3 years ago
Duncan Ogilvie 3dd3368e4e Build in Debug with CMAKE_UNITY_BUILD
3 years ago
Duncan Ogilvie bb7874a6df Improve compilation times
3 years ago
Duncan Ogilvie 91dbf2986e Remove dependency on nlohmann json
3 years ago
Duncan Ogilvie 2bcf15c4ed Add support for object libraries
3 years ago
Duncan Ogilvie 6a825e15a0 Slightly improve cmkr init #24
3 years ago
Duncan Ogilvie cc2b984aa5 Update documentation for conditions
3 years ago
Duncan Ogilvie 56a88c41e2
Merge pull request #35 from build-cpp/toml-checker
3 years ago
Duncan Ogilvie 6809e8da41 Refactor and add checking for conditions
3 years ago

@ -10,7 +10,7 @@ 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
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
@ -72,7 +72,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

@ -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

@ -0,0 +1 @@
github: [mrexodia]

@ -1,21 +1,28 @@
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-20.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@v3
- name: Install Ninja
uses: seanmiddleditch/gha-setup-ninja@6263846cf3c17009dfc81604efabae16044fc074 # master
- name: Visual Studio Development Environment
uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1
- name: Tag cmkr.cmake - name: Tag cmkr.cmake
if: ${{ startsWith(github.ref, 'refs/tags/') }} if: ${{ startsWith(github.ref, 'refs/tags/') }}
@ -23,7 +30,7 @@ jobs:
- name: Build - name: Build
run: | run: |
cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} cmake -B build -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DCMAKE_UNITY_BUILD=ON
cmake --build build --config ${{ env.BUILD_TYPE }} --parallel cmake --build build --config ${{ env.BUILD_TYPE }} --parallel
cmake --install build --prefix ./install --config ${{ env.BUILD_TYPE }} cmake --install build --prefix ./install --config ${{ env.BUILD_TYPE }}
@ -35,31 +42,34 @@ jobs:
- name: Test - name: Test
run: | run: |
cd build/tests cd build/tests
ctest -C ${{ env.BUILD_TYPE }} ctest -C ${{ env.BUILD_TYPE }} --verbose
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
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@07c1e24a97f0951e13f88870b99c058fcf0b14cf # v5
if: ${{ startsWith(github.ref, 'refs/tags/') }}
with: with:
string: ${{ runner.os }} string: ${{ runner.os }}
- name: Compress artifacts - name: Compress artifacts
uses: papeloto/action-zip@v1 uses: vimtor/action-zip@26a249fb00d43ca98dad77a4b3838025fc226aa1 # v1.1
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@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15
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 }}

@ -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@v3
- name: clang-format
id: clang-format
uses: DoozyX/clang-format-lint-action@c3b2c943e924028b93a707a5b1b017976ab8d50c # v0.15
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@v3
- name: Run editorconfig-checker
uses: editorconfig-checker/action-editorconfig-checker@d4fca16fc71adef10fbe101903b654449fa9570c # master 2022-03-15

2
.gitignore vendored

@ -9,3 +9,5 @@ build*/
.idea/ .idea/
cmake-build*/ cmake-build*/
CMakeLists.txt.user CMakeLists.txt.user
.vscode/
.DS_Store

74
CMakeLists.txt generated

@ -7,17 +7,14 @@ 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.1.4 0.2.33
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/enum_helper.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"
) "src/build.cpp"
"src/cmake_generator.cpp"
list(APPEND cmkr_SOURCES "src/help.cpp"
cmake.toml "src/main.cpp"
"src/project_parser.cpp"
) )
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

@ -7,37 +7,58 @@
```toml ```toml
[project] [project]
name = "cmkr_for_beginners" name = "cmkr_for_beginners"
description = "A minimal cmkr project."
[target.hello_world] [target.hello_world]
type = "executable" type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
``` ```
`cmkr` can bootstrap itself from CMake and consumers of your project do not need to install anything to work with it. `cmkr` can bootstrap itself and you only need CMake and a C++ compiler to use it.
## Getting started ## Getting started
The easiest way to get started is to use the [cmkr_for_beginners](https://github.com/build-cpp/cmkr_for_beginners) template repository. Either open it in [Gitpod](https://gitpod.io/#https://github.com/build-cpp/cmkr_for_beginners), or clone the repository and run: To get started, run the following commands from your project directory:
```sh
curl https://raw.githubusercontent.com/build-cpp/cmkr/main/cmake/cmkr.cmake -o cmkr.cmake
cmake -P cmkr.cmake
```
After the bootstrapping process finishes, customize [`cmake.toml`](https://build-cpp.github.io/cmkr/cmake-toml) for your project and run CMake:
```sh
cmake -B 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` when necessary.
<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
Another way to get started is to use the [cmkr_for_beginners](https://github.com/build-cpp/cmkr_for_beginners) template repository. Either open it in [Gitpod](https://gitpod.io/#https://github.com/build-cpp/cmkr_for_beginners), or clone the repository and run:
```sh ```sh
cmake -B build cmake -B build
cmake --build build cmake --build build
``` ```
Alternatively you can check out the [cmkr topic](https://github.com/topics/cmkr), the [build-cpp organization](https://github.com/build-cpp) or the [tests](https://github.com/build-cpp/cmkr/tree/main/tests) for more examples and templates. You can also check out the [documentation](https://build-cpp.github.io/cmkr). Check out the [cmkr topic](https://github.com/topics/cmkr), the [build-cpp organization](https://github.com/build-cpp) or the [tests](https://github.com/build-cpp/cmkr/tree/main/tests) for more examples and templates.
## Command line ## Command line
Optionally you can install `cmkr` in your `PATH` and use it as a utility from the command line: Optionally you can put a [`cmkr` release](https://github.com/build-cpp/cmkr/releases) in your `PATH` and use it as a utility from the command line:
``` ```
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.
@ -45,8 +66,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 ❤️

@ -4,14 +4,14 @@ cmkr-include = false
[project] [project]
name = "cmkr" name = "cmkr"
version = "0.1.4" version = "0.2.33"
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"
@ -25,6 +25,7 @@ sources = [
"src/*.cpp", "src/*.cpp",
"include/*.hpp", "include/*.hpp",
"cmake/cmkr.cmake", "cmake/cmkr.cmake",
"cmake/version.hpp.in",
] ]
include-directories = [ include-directories = [
"include", "include",
@ -35,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"]

@ -0,0 +1,78 @@
cmake_minimum_required(VERSION 3.20)
if(NOT CMAKE_SCRIPT_MODE_FILE)
message(FATAL_ERROR "Usage: cmake -P bump_version.cmake [1.2.3]")
endif()
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
message(FATAL_ERROR "Cannot find cmake.toml")
endif()
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake")
message(FATAL_ERROR "Cannot find cmkr.cmake")
endif()
# Validate branch
find_package(Git REQUIRED)
execute_process(COMMAND "${GIT_EXECUTABLE}" branch --show-current OUTPUT_VARIABLE GIT_BRANCH)
string(STRIP "${GIT_BRANCH}" GIT_BRANCH)
if(NOT GIT_BRANCH STREQUAL "main")
message(FATAL_ERROR "You need to be on the main branch, you are on: ${GIT_BRANCH}")
endif()
file(READ "${CMAKE_SOURCE_DIR}/cmake.toml" CMAKE_TOML)
string(FIND "${CMAKE_TOML}" "[project]" PROJECT_INDEX)
string(SUBSTRING "${CMAKE_TOML}" ${PROJECT_INDEX} -1 CMAKE_TOML_PROJECT)
set(SEMVER_REGEX "([0-9]+)\\.([0-9]+)\\.([0-9]+)")
set(VERSION_REGEX "version = \"${SEMVER_REGEX}\"")
if(CMAKE_TOML_PROJECT MATCHES "${VERSION_REGEX}")
set(MAJOR "${CMAKE_MATCH_1}")
set(MINOR "${CMAKE_MATCH_2}")
set(PATCH "${CMAKE_MATCH_3}")
set(OLDVERSION "${MAJOR}.${MINOR}.${PATCH}")
else()
message(FATAL_ERROR "Failed to match semantic version in cmake.toml")
endif()
if(CMAKE_ARGV3)
if(NOT CMAKE_ARGV3 MATCHES "${SEMVER_REGEX}")
message(FATAL_ERROR "Invalid semantic version number '${CMAKE_ARGV3}'")
endif()
set(NEWVERSION "${CMAKE_ARGV3}")
else()
math(EXPR NEWPATCH "${PATCH} + 1")
set(NEWVERSION "${MAJOR}.${MINOR}.${NEWPATCH}")
endif()
message(STATUS "Version ${OLDVERSION} -> ${NEWVERSION}")
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}")
# Replace version in cmake.toml
string(REPLACE "version = \"${OLDVERSION}\"" "version = \"${NEWVERSION}\"" CMAKE_TOML "${CMAKE_TOML}")
file(CONFIGURE
OUTPUT "${CMAKE_SOURCE_DIR}/cmake.toml"
CONTENT "${CMAKE_TOML}"
@ONLY
NEWLINE_STYLE LF
)
# Run cmkr gen
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen RESULT_VARIABLE CMKR_EXEC_RESULT)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "cmkr gen failed (exit code ${CMKR_EXEC_RESULT})")
endif()
# Replace version in 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}")
file(CONFIGURE
OUTPUT "${CMAKE_SOURCE_DIR}/cmake/cmkr.cmake"
CONTENT "${CMKR_CMAKE}"
@ONLY
NEWLINE_STYLE LF
)
# 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}")

@ -1,16 +1,22 @@
include_guard() include_guard()
if(CMAKE_SCRIPT_MODE_FILE)
message(FATAL_ERROR "Running cmkr.cmake as a script is unsupported. To build your project try: cmake -B build")
endif()
# 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 "archive_52671dcf" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) set(CMKR_TAG "v0.2.33" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
set(CMKR_COMMIT_HASH "" CACHE STRING "cmkr git commit hash (optional)" FORCE)
# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake
if(CMAKE_SCRIPT_MODE_FILE)
set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build")
set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}")
endif()
# Set these from the command line to customize for development/debugging purposes # Set these from the command line to customize for development/debugging purposes
set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable") set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable")
set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation") set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation")
set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration")
mark_as_advanced(CMKR_REPO CMKR_TAG CMKR_COMMIT_HASH CMKR_EXECUTABLE CMKR_SKIP_GENERATION CMKR_BUILD_TYPE)
# Disable cmkr if generation is disabled # Disable cmkr if generation is disabled
if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION) if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION)
@ -22,7 +28,7 @@ if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION)
endif() endif()
# Disable cmkr if no cmake.toml file is found # Disable cmkr if no cmake.toml file is found
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml")
macro(cmkr) macro(cmkr)
endmacro() endmacro()
@ -52,18 +58,64 @@ else()
endif() endif()
# Use cached cmkr if found # Use cached cmkr if found
set(CMKR_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_${CMKR_TAG}") if(DEFINED ENV{CMKR_CACHE})
set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}")
string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}")
if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$")
set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/")
endif()
# Build in release mode for the cache
set(CMKR_BUILD_TYPE "Release")
else()
set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_")
endif()
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}")
if(NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE AND CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr") # 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
if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE)
cmkr_startswith("${CMKR_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/_cmkr" CMKR_STARTSWITH_BUILD)
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}'")
if(EXISTS "${CMKR_CACHED_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
else()
unset(CMKR_EXECUTABLE CACHE)
endif()
else()
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 CMKR_STARTSWITH_CACHE)
message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
unset(CMKR_EXECUTABLE CACHE)
endif()
endif()
if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}") if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}")
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE) elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE)
message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found") message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found")
elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}")
set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE)
message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'")
else() else()
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)
message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'") message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'")
@ -81,23 +133,34 @@ else()
${CMKR_REPO} ${CMKR_REPO}
"${CMKR_DIRECTORY}" "${CMKR_DIRECTORY}"
) )
if(CMKR_COMMIT_HASH)
execute_process(
COMMAND "${GIT_EXECUTABLE}" checkout -q "${CMKR_COMMIT_HASH}"
RESULT_VARIABLE CMKR_EXEC_RESULT
WORKING_DIRECTORY "${CMKR_DIRECTORY}"
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "Tag '${CMKR_TAG}' hash is not '${CMKR_COMMIT_HASH}'")
endif()
endif()
message(STATUS "[cmkr] Building cmkr (using system compiler)...") message(STATUS "[cmkr] Building cmkr (using system compiler)...")
cmkr_exec("${CMAKE_COMMAND}" cmkr_exec("${CMAKE_COMMAND}"
--no-warn-unused-cli --no-warn-unused-cli
"${CMKR_DIRECTORY}" "${CMKR_DIRECTORY}"
"-B${CMKR_DIRECTORY}/build" "-B${CMKR_DIRECTORY}/build"
"-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}"
"-DCMAKE_UNITY_BUILD=ON"
"-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}"
"-DCMKR_GENERATE_DOCUMENTATION=OFF" "-DCMKR_GENERATE_DOCUMENTATION=OFF"
) )
cmkr_exec("${CMAKE_COMMAND}" cmkr_exec("${CMAKE_COMMAND}"
--build "${CMKR_DIRECTORY}/build" --build "${CMKR_DIRECTORY}/build"
--config Release --config "${CMKR_BUILD_TYPE}"
--parallel --parallel
) )
cmkr_exec("${CMAKE_COMMAND}" cmkr_exec("${CMAKE_COMMAND}"
--install "${CMKR_DIRECTORY}/build" --install "${CMKR_DIRECTORY}/build"
--config Release --config "${CMKR_BUILD_TYPE}"
--prefix "${CMKR_DIRECTORY}" --prefix "${CMKR_DIRECTORY}"
--component cmkr --component cmkr
) )
@ -114,6 +177,29 @@ if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding")
endif() endif()
# Use cmkr.cmake as a script
if(CMAKE_SCRIPT_MODE_FILE)
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml")
execute_process(COMMAND "${CMKR_EXECUTABLE}" init
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new")
else()
message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build")
endif()
else()
execute_process(COMMAND "${CMKR_EXECUTABLE}" gen
RESULT_VARIABLE CMKR_EXEC_RESULT
)
if(NOT CMKR_EXEC_RESULT EQUAL 0)
message(FATAL_ERROR "[cmkr] Failed to generate project.")
else()
message(STATUS "[cmkr] Configure using: cmake -B build")
endif()
endif()
endif()
# This is the macro that contains black magic # This is the macro that contains black magic
macro(cmkr) macro(cmkr)
# When this macro is called from the generated file, fake some internal CMake variables # When this macro is called from the generated file, fake some internal CMake variables

@ -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()

@ -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")
@ -46,14 +46,14 @@ function(generate_documentation)
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" 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" 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

@ -5,15 +5,19 @@ function(generate_resources target)
PROPERTY SOURCES PROPERTY SOURCES
) )
foreach(SOURCE ${TARGET_SOURCES}) foreach(SOURCE ${TARGET_SOURCES})
if(SOURCE MATCHES ".cmake$")
get_filename_component(RESOURCE_NAME "${SOURCE}" NAME_WE) get_filename_component(RESOURCE_NAME "${SOURCE}" NAME_WE)
set(RESOURCE_HEADER "include/resources/${RESOURCE_NAME}.hpp") set(RESOURCE_HEADER "include/resources/${RESOURCE_NAME}.hpp")
if(SOURCE MATCHES ".cmake$")
# Add configure-time dependency on the source file # Add configure-time dependency on the source file
configure_file("${SOURCE}" "${RESOURCE_HEADER}" COPYONLY) configure_file("${SOURCE}" "${RESOURCE_HEADER}" COPYONLY)
# Generate the actual resource into the header # Generate the actual resource into the header
file(READ "${SOURCE}" RESOURCE_CONTENTS) file(READ "${SOURCE}" RESOURCE_CONTENTS)
configure_file("${PROJECT_SOURCE_DIR}/cmake/resource.hpp.in" "${RESOURCE_HEADER}" @ONLY) configure_file("${PROJECT_SOURCE_DIR}/cmake/resource.hpp.in" "${RESOURCE_HEADER}" @ONLY)
message(STATUS "[cmkr] Generated ${RESOURCE_HEADER}") message(STATUS "[cmkr] Generated ${RESOURCE_HEADER}")
elseif(SOURCE MATCHES ".in$")
configure_file("${SOURCE}" "${RESOURCE_HEADER}" @ONLY)
message(STATUS "[cmkr] Generated ${RESOURCE_HEADER}")
endif() endif()
endforeach() endforeach()
target_include_directories(${target} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/include") target_include_directories(${target} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/include")

@ -0,0 +1,3 @@
#pragma once
#define CMKR_VERSION "@PROJECT_VERSION@"

1
docs/.gitignore vendored

@ -1,2 +1,3 @@
_site/ _site/
.jekyll-metadata .jekyll-metadata
assets/

@ -0,0 +1 @@
cmkr.build

@ -3,6 +3,7 @@ gem "minima", "~> 2.5"
gem "github-pages", group: :jekyll_plugins gem "github-pages", group: :jekyll_plugins
gem "jekyll-remote-theme" gem "jekyll-remote-theme"
gem "jekyll-sitemap", "~> 1.4.0"
platforms :mingw, :x64_mingw, :mswin, :jruby do platforms :mingw, :x64_mingw, :mswin, :jruby do
gem "tzinfo", "~> 1.2" gem "tzinfo", "~> 1.2"

@ -271,6 +271,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
github-pages github-pages
jekyll-remote-theme jekyll-remote-theme
jekyll-sitemap (~> 1.4.0)
just-the-docs just-the-docs
minima (~> 2.5) minima (~> 2.5)
tzinfo (~> 1.2) tzinfo (~> 1.2)

@ -2,6 +2,7 @@ title: cmkr
plugins: plugins:
- jekyll-remote-theme - jekyll-remote-theme
- jekyll-sitemap
# Automatically deduce dark theme preference https://github.com/pmarsceill/just-the-docs/pull/464 # Automatically deduce dark theme preference https://github.com/pmarsceill/just-the-docs/pull/464
remote_theme: build-cpp/just-the-docs@light-switch remote_theme: build-cpp/just-the-docs@light-switch
@ -9,7 +10,7 @@ search_enabled: true
color_scheme: light-or-dark color_scheme: light-or-dark
heading_anchors: true heading_anchors: true
aux_links: aux_links:
"cmkr": "GitHub":
- "https://github.com/build-cpp/cmkr" - "https://github.com/build-cpp/cmkr"
aux_links_new_tab: true aux_links_new_tab: true
@ -19,3 +20,23 @@ gh_edit_repository: "https://github.com/build-cpp/cmkr"
gh_edit_branch: "main" gh_edit_branch: "main"
gh_edit_view_mode: "edit" gh_edit_view_mode: "edit"
gh_edit_source: docs gh_edit_source: docs
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>

@ -0,0 +1,76 @@
---
layout: page
title: Basics
nav_order: 1
---
# Basics
To effectively use cmkr it helps to understand the basic concepts of CMake.
## 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 library you can build. There are also [pseudo targets](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#pseudo-targets), but we ignore them for now.
<sub>Visual Studio: a **target** corresponds to a _project_.</sub>
## Target Properties
Targets have a collection of **properties** that describe how to build them.
Examples of properties:
- _Sources_: the `*.cpp` files used to build the target.
- _Compile options_: Command line flags for the compiler.
- _Link libraries_: The **dependencies** required to build this target.
<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 of the linker, CMake also propagates properties of the target you link to.
<sub>You can think of **linking** as _depending on_.</sub>
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"]
[target.DataProcessor]
type = "executable"
sources = ["DataProcessor/src/main.cpp"]
link-libraries = ["StringUtils"]
```

@ -1,15 +1,16 @@
--- ---
layout: page layout: page
title: cmake.toml title: Reference
permalink: /cmake-toml/ permalink: /cmake-toml/
nav_order: 3 nav_order: 3
--- ---
# cmake.toml # Reference
This page is supposed to be 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 more real-world 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,60 @@ 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 `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:
```toml
[target]
type = "executable"
sources = ["src/main.cpp"]
ptr64.sources = ["src/ptr64_only.cpp"]
``` ```
This will make the `arch64` and `arch32` conditions available with their respective CMake expressions. The following conditions are predefined (you can override them if you desire): 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):
```toml ```toml
[conditions] [conditions]
@ -57,15 +102,27 @@ 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"
x64 = "CMAKE_SIZEOF_VOID_P EQUAL 8"
x32 = "CMAKE_SIZEOF_VOID_P EQUAL 4"
android = "ANDROID"
apple = "APPLE"
bsd = "BSD"
cygwin = "CYGWIN"
ios = "IOS"
xcode = "XCODE"
wince = "WINCE"
``` ```
## Subdirectories ## Subdirectories
```toml ```toml
[subdir.mysubdir] [subdir.mysubdir]
condition = "linux" condition = "mycondition"
cmake-before = """ cmake-before = """
message(STATUS "CMake injected before the add_subdirectory() call" message(STATUS "CMake injected before the add_subdirectory() call"
""" """
@ -76,25 +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.03.25"
url = "https://github.com/microsoft/vcpkg/archive/refs/tags/2021.05.12.tar.gz" url = "https://github.com/microsoft/vcpkg/archive/refs/tags/2024.03.25.tar.gz"
packages = ["fmt", "zlib"] packages = ["fmt", "zlib"]
``` ```
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).
To specify package features you can use the following syntax: `imgui[docking-experimental,freetype,sdl2-binding,opengl3-binding]`.
## Packages ## Packages
```toml ```toml
[find-package]
mypackage = { version = "1.0", required = true, config = true, components = ["mycomponent"] }
# Alternative syntax
[find-package.mypackage] [find-package.mypackage]
condition = "mycondition"
version = "1.0" version = "1.0"
required = true required = true
config = true config = true
@ -106,26 +185,40 @@ 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
[fetch-content]
gitcontent = { git = "https://github.com/myuser/gitcontent", tag = "v0.1" }
svncontent = { svn = "https://svn-host.com/url", rev = "svn_rev" }
urlcontent = { url = "https://content-host.com/urlcontent.zip", hash = "123123123123" }
# Alternative syntax
[fetch-content.gitcontent] [fetch-content.gitcontent]
condition = "mycondition"
git = "https://github.com/myuser/gitcontent" git = "https://github.com/myuser/gitcontent"
tag = "v0.1" tag = "v0.1"
shallow = false
system = false
subdir = ""
[fetch-content.svncontent]
condition = "mycondition"
svn = "https://svn-host.com/url"
rev = "svn_rev"
[fetch-content.urlcontent]
condition = "mycondition"
url = "https://content-host.com/urlcontent.zip"
# These are equivalent, supported algorithms:
# md5, sha1, sha224, sha256, sha384, sha512, sha3_224, sha3_256, sha3_384, sha3_512
hash = "SHA1 502a4e25b8b209889c99c7fa0732102682c2e4ff"
sha1 = "502a4e25b8b209889c99c7fa0732102682c2e4ff"
``` ```
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.
## Targets ## Targets
```toml ```toml
[target.mytarget] [target.mytarget]
condition = "linux" condition = "mycondition"
alias = "mytarget::mytarget" alias = "mytarget::mytarget"
type = "static" # executable, library, shared, static, interface, custom type = "static" # executable, shared (DLL), static, interface, object, library, 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
@ -162,6 +255,29 @@ CXX_STANDARD_REQUIRED = true
FOLDER = "MyFolder" FOLDER = "MyFolder"
``` ```
## 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 = ""
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.
- `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.
@ -169,6 +285,7 @@ FOLDER = "MyFolder"
```toml ```toml
# You can declare as many as you want like this, but the name has to be unique # You can declare as many as you want like this, but the name has to be unique
[[test]] [[test]]
condition = "mycondition"
name = "mytest" name = "mytest"
command = "$<TARGET_FILE:mytest>" command = "$<TARGET_FILE:mytest>"
arguments = ["arg1", "arg2"] arguments = ["arg1", "arg2"]
@ -178,9 +295,12 @@ working-directory = "mytest-dir"
```toml ```toml
[[install]] [[install]]
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
``` ```

@ -1,22 +0,0 @@
---
layout: page
title: Command line
permalink: /command-line/
nav_order: 2
---
# Command line
Optionally you can install `cmkr` in your `PATH` and use it as a utility from the command line:
```
Usage: cmkr [arguments]
arguments:
init [executable|library|shared|static|interface] Starts a new project in the same directory.
gen Generates CMakeLists.txt file.
build <extra cmake args> Run cmake and build.
install Run cmake --install. Needs admin privileges.
clean Clean the build directory.
help Show help.
version Current cmkr version.
```

@ -0,0 +1,31 @@
---
# 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/linker flags for various platforms.
```toml
[project]
name = "compile-options"
description = "Compiler flags"
[target.hello]
type = "executable"
sources = ["src/main.cpp"]
msvc.compile-options = ["/W2"]
gcc.compile-options = ["-Wall"]
clang.compile-options = ["-Wall"]
```
The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags 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>

@ -19,6 +19,7 @@ description = "Header-only library"
[target.mylib] [target.mylib]
type = "interface" type = "interface"
include-directories = ["include"] include-directories = ["include"]
compile-features = ["cxx_std_11"]
[target.example] [target.example]
type = "executable" type = "executable"

@ -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>

@ -0,0 +1,40 @@
---
# Automatically generated from tests/templates/cmake.toml - DO NOT EDIT
layout: default
title: Target templates
permalink: /examples/templates
parent: Examples
nav_order: 7
---
# Target templates
To avoid repeating yourself in targets you can create your own target type (template). All properties of the template are inherited when used as a target type.
```toml
[project]
name = "templates"
description = "Target templates"
[template.app]
type = "executable"
sources = ["src/templates.cpp"]
compile-definitions = ["IS_APP"]
# Unlike interface targets you can also inherit properties
[template.app.properties]
CXX_STANDARD = "11"
CXX_STANDARD_REQUIRED = true
[target.app-a]
type = "app"
compile-definitions = ["APP_A"]
[target.app-b]
type = "app"
compile-definitions = ["APP_B"]
```
**Note**: In most cases you probably want to use an [interface](/examples/interface) target instead.
<sup><sub>This page was automatically generated from [tests/templates/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/templates/cmake.toml).</sub></sup>

@ -19,7 +19,7 @@ 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.html for available packages
[vcpkg] [vcpkg]
version = "2021.05.12" version = "2024.03.25"
packages = ["fmt"] packages = ["fmt"]
[find-package] [find-package]
@ -33,4 +33,6 @@ 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]`.
<sup><sub>This page was automatically generated from [tests/vcpkg/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/vcpkg/cmake.toml).</sub></sup> <sup><sub>This page was automatically generated from [tests/vcpkg/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/vcpkg/cmake.toml).</sub></sup>

@ -0,0 +1,10 @@
---
layout: null
permalink: /getting-started/
---
<html>
<head>
<meta http-equiv="refresh" content="0;url=https://cmkr.build">
</head>
</html>

@ -1,17 +0,0 @@
---
layout: page
title: Getting started
permalink: /getting-started/
nav_order: 1
---
# Getting started
The easiest way to get started is to use the [cmkr_for_beginners](https://github.com/build-cpp/cmkr_for_beginners) template repository. Either open it in [Gitpod](https://gitpod.io/#https://github.com/build-cpp/cmkr_for_beginners), or clone the repository and run:
```sh
cmake -B build
cmake --build build
```
Alternatively you can check out the [cmkr topic](https://github.com/topics/cmkr) or the [build-cpp organization](https://github.com/build-cpp) for more examples and templates.

@ -1,23 +1,81 @@
--- ---
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). It was originally created by [Mohammed Alyousef](https://github.com/MoAlyousef). [`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:
```toml ```toml
[project] [project]
name = "cmkr_for_beginners" name = "cmkr_for_beginners"
description = "A minimal cmkr project."
[target.hello_world] [target.hello_world]
type = "executable" type = "executable"
sources = ["src/main.cpp"] sources = ["src/main.cpp"]
``` ```
`cmkr` can bootstrap itself from CMake and consumers of your project do not need to install anything to work with it. `cmkr` can bootstrap itself, and you only need CMake and a C++ compiler to use it.
## Getting started
To get started, run the following commands from your project directory:
```sh
curl https://raw.githubusercontent.com/build-cpp/cmkr/main/cmake/cmkr.cmake -o cmkr.cmake
cmake -P cmkr.cmake
```
After the bootstrapping process finishes, customize [`cmake.toml`](./cmake-toml) for your project and run CMake:
```sh
cmake -B 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` when necessary.
<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
Another way to get started is to use the [cmkr_for_beginners](https://github.com/build-cpp/cmkr_for_beginners) template repository. Either open it in [Gitpod](https://gitpod.io/#https://github.com/build-cpp/cmkr_for_beginners), or clone the repository and run:
```sh
cmake -B build
cmake --build build
```
Check out the [cmkr topic](https://github.com/topics/cmkr), the [build-cpp organization](https://github.com/build-cpp) or the [tests](https://github.com/build-cpp/cmkr/tree/main/tests) for more examples and templates.
## Command line
Optionally you can put a [`cmkr` release](https://github.com/build-cpp/cmkr/releases) in your `PATH` and use it as a utility from the command line:
```
Usage: cmkr [arguments]
arguments:
init [executable|library|shared|static|interface] Create a project.
gen Generates CMakeLists.txt file.
build <extra cmake args> Run cmake and build.
install Run cmake --install.
clean Clean the build directory.
help Show help.
version Current cmkr version.
```
## Credits
- [gulrak/filesystem](https://github.com/gulrak/filesystem)
- [Tessil/ordered-map](https://github.com/Tessil/ordered-map)
- [ToruNiina/toml11](https://github.com/ToruNiina/toml11)
- [mpark/variant](https://github.com/mpark/variant)
- [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 ❤️

@ -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.

@ -1,2 +0,0 @@
bundle exec just-the-docs rake search:init
bundle exec jekyll serve --livereload

@ -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 **);

@ -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();

@ -5,13 +5,9 @@
namespace cmkr { namespace cmkr {
namespace gen { namespace gen {
int generate_project(const char *typ); void generate_project(const std::string &type);
int generate_cmake(const char *path, const parser::Project *parent_project = nullptr); void generate_cmake(const char *path, const parser::Project *parent_project = nullptr);
} // namespace gen } // namespace gen
} // namespace cmkr } // namespace cmkr
int cmkr_gen_generate_project(const char *typ);
int cmkr_gen_generate_cmake(const char *path);

@ -1,69 +0,0 @@
// https://codereview.stackexchange.com/a/14315
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
// This is the type that will hold all the strings.
// Each enumeration type will declare its own specialization.
// Any enum that does not have a specialization will generate a compiler error
// indicating that there is no definition of this variable (as there should be
// be no definition of a generic version).
template <typename T>
struct enumStrings {
static char const *data[];
};
// This is a utility type.
// Created automatically. Should not be used directly.
template <typename T>
struct enumRefHolder {
T &enumVal;
enumRefHolder(T &enumVal) : enumVal(enumVal) {}
};
template <typename T>
struct enumConstRefHolder {
T const &enumVal;
enumConstRefHolder(T const &enumVal) : enumVal(enumVal) {}
};
// The next two functions do the actual work of reading/writing an
// enum as a string.
template <typename T>
std::ostream &operator<<(std::ostream &str, enumConstRefHolder<T> const &data) {
return str << enumStrings<T>::data[data.enumVal];
}
template <typename T>
std::istream &operator>>(std::istream &str, enumRefHolder<T> const &data) {
std::string value;
str >> value;
// These two can be made easier to read in C++11
// using std::begin() and std::end()
//
static auto begin = std::begin(enumStrings<T>::data);
static auto end = std::end(enumStrings<T>::data);
auto find = std::find(begin, end, value);
if (find != end) {
data.enumVal = static_cast<T>(std::distance(begin, find));
} else {
throw std::invalid_argument("");
}
return str;
}
// This is the public interface:
// use the ability of function to deduce their template type without
// being explicitly told to create the correct type of enumRefHolder<T>
template <typename T>
enumConstRefHolder<T> enumToString(T const &e) {
return enumConstRefHolder<T>(e);
}
template <typename T>
enumRefHolder<T> enumFromString(T &e) {
return enumRefHolder<T>(e);
}

@ -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);

@ -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>

@ -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);

@ -1,45 +1,100 @@
#pragma once #pragma once
static const char *hello_world = &R"lit( static const char *cpp_executable = &R"lit(
#include <iostream> #include <iostream>
#include <cstdlib>
int %s() { int main() {
std::cout << "Hello World!\n"; std::cout << "Hello from cmkr!\n";
return 0; return EXIT_SUCCESS;
} }
)lit"[1]; // skip initial newline )lit"[1]; // skip initial newline
static const char *cmake_toml = &R"lit( static const char *cpp_library = &R"lit(
[cmake] #include <@name/@name.hpp>
version = "3.15"
# subdirs = []
# build-dir = ""
# cpp-flags = []
# c-flags = []
# link-flags = []
# generator = ""
# arguments = []
#include <iostream>
namespace @name {
void hello() {
std::cout << "Hello from cmkr!\n";
}
} // namespace @name
)lit"[1]; // skip initial newline
static const char *hpp_library = &R"lit(
#pragma once
namespace @name {
void hello();
} // namespace @name
)lit"[1]; // skip initial newline
static const char *hpp_interface = &R"lit(
#pragma once
#include <iostream>
namespace @name {
inline void hello() {
std::cout << "Hello from cmkr!\n";
}
} // namespace @name
)lit"[1]; // skip initial newline
static const char *toml_executable = &R"lit(
# Reference: https://build-cpp.github.io/cmkr/cmake-toml
[project] [project]
name = "%s" name = "@name"
version = "0.1.0"
[target.@name]
type = "executable"
sources = ["src/@name/main.cpp"]
compile-features = ["cxx_std_11"]
)lit"[1]; // skip initial newline
# [find-package] static const char *toml_library = &R"lit(
# Reference: https://build-cpp.github.io/cmkr/cmake-toml
[project]
name = "@name"
# [fetch-content] [target.@name]
type = "@type"
sources = [
"src/@name/@name.cpp",
"include/@name/@name.hpp"
]
include-directories = ["include"]
compile-features = ["cxx_std_11"]
)lit"[1]; // skip initial newline
# [options] static const char *toml_interface = &R"lit(
# Reference: https://build-cpp.github.io/cmkr/cmake-toml
[project]
name = "@name"
[target.%s] [target.@name]
type = "%s" type = "interface"
sources = ["src/*.cpp"]
include-directories = ["include"] include-directories = ["include"]
# alias = "" compile-features = ["cxx_std_11"]
# compile-features = [] )lit"[1]; // skip initial newline
# compile-definitions = []
# link-libraries = [] static const char *toml_migration = &R"lit(
# Reference: https://build-cpp.github.io/cmkr/cmake-toml
[[install]] [project]
%s = ["%s"] name = "@name"
destination = "${CMAKE_INSTALL_PREFIX}/%s"
# TODO: define a target for each of your executables/libraries like this:
#[target.myexecutable]
#type = "executable" # static, shared
#sources = ["src/@name/*.cpp", "include/@name/*.hpp"]
#include-directories = ["include"]
#compile-features = ["cxx_std_11"]
#link-libraries = ["target-or-library"]
)lit"[1]; // skip initial newline )lit"[1]; // skip initial newline

@ -1,31 +1,37 @@
#pragma once #pragma once
#include <map> #include <vector>
#include <mpark/variant.hpp>
#include <stdexcept>
#include <string> #include <string>
#include <mpark/variant.hpp>
#include <tsl/ordered_map.h> #include <tsl/ordered_map.h>
#include <vector> #include <tsl/ordered_set.h>
namespace cmkr { namespace cmkr {
namespace parser { namespace parser {
struct Setting { template <typename T>
using Condition = tsl::ordered_map<std::string, T>;
using ConditionVector = Condition<std::vector<std::string>>;
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 Package { struct Package {
std::string name; std::string name;
std::string condition;
std::string version; std::string version;
bool required = true; bool required = true;
bool config = false; bool config = false;
@ -35,7 +41,17 @@ struct Package {
struct Vcpkg { struct Vcpkg {
std::string version; std::string version;
std::string url; std::string url;
std::vector<std::string> packages;
struct Package {
std::string name;
std::vector<std::string> features;
};
std::vector<Package> packages;
bool enabled() const {
return !packages.empty();
}
}; };
enum TargetType { enum TargetType {
@ -45,18 +61,18 @@ enum TargetType {
target_static, target_static,
target_interface, target_interface,
target_custom, target_custom,
target_object,
target_template,
target_last,
}; };
template <typename T> extern const char *targetTypeNames[target_last];
using Condition = tsl::ordered_map<std::string, T>;
using ConditionVector = Condition<std::vector<std::string>>;
struct Target { struct Target {
std::string name; std::string name;
TargetType type = {}; TargetType type = target_last;
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
@ -94,8 +110,15 @@ struct Target {
ConditionVector include_after; ConditionVector include_after;
}; };
struct Template {
Target outline;
std::string add_function;
bool pass_sources_to_add_function = false;
};
struct Test { struct Test {
std::string name; std::string name;
std::string condition;
std::vector<std::string> configurations; std::vector<std::string> configurations;
std::string working_directory; std::string working_directory;
std::string command; std::string command;
@ -103,16 +126,20 @@ struct Test {
}; };
struct Install { struct Install {
std::string condition;
std::vector<std::string> targets; std::vector<std::string> targets;
std::vector<std::string> files; std::vector<std::string> files;
std::vector<std::string> dirs; std::vector<std::string> dirs;
std::vector<std::string> configs; std::vector<std::string> configs;
std::string destination; std::string destination;
std::string component;
bool optional = false;
}; };
struct Subdir { struct Subdir {
std::string name; std::string name;
std::string condition; std::string condition;
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;
@ -121,10 +148,28 @@ struct Subdir {
struct Content { struct Content {
std::string name; std::string name;
std::string condition;
tsl::ordered_map<std::string, std::string> arguments; tsl::ordered_map<std::string, std::string> arguments;
Condition<std::string> cmake_before;
Condition<std::string> cmake_after;
ConditionVector include_before;
ConditionVector include_after;
bool system = false;
std::string subdir;
}; };
enum MsvcRuntimeType {
msvc_dynamic,
msvc_static,
msvc_last,
};
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";
@ -142,15 +187,18 @@ struct Project {
std::string project_version; std::string project_version;
std::string project_description; std::string project_description;
std::vector<std::string> project_languages; std::vector<std::string> 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<Package> packages; std::vector<Package> packages;
Vcpkg vcpkg; Vcpkg vcpkg;
std::vector<Content> contents; std::vector<Content> contents;
std::vector<Template> templates;
std::vector<Target> targets; std::vector<Target> targets;
std::vector<Test> tests; std::vector<Test> tests;
std::vector<Install> installs; std::vector<Install> installs;
@ -158,6 +206,9 @@ 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);

@ -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>
@ -21,9 +19,7 @@ const char *handle_args(int argc, char **argv) {
throw std::runtime_error(cmkr::help::message()); throw std::runtime_error(cmkr::help::message());
std::string main_arg = args[1]; std::string main_arg = args[1];
if (main_arg == "gen") { if (main_arg == "gen") {
auto ret = cmkr::gen::generate_cmake(fs::current_path().string().c_str()); cmkr::gen::generate_cmake(fs::current_path().string().c_str());
if (ret)
return "CMake generation error!";
return "CMake generation successful!"; return "CMake generation successful!";
} else if (main_arg == "help") { } else if (main_arg == "help") {
return cmkr::help::message(); return cmkr::help::message();
@ -33,27 +29,23 @@ const char *handle_args(int argc, char **argv) {
std::string type = "executable"; std::string type = "executable";
if (args.size() > 2) if (args.size() > 2)
type = args[2]; type = args[2];
auto ret = cmkr::gen::generate_project(type.c_str()); cmkr::gen::generate_project(type.c_str());
if (ret) cmkr::gen::generate_cmake(fs::current_path().string().c_str());
return "Initialization failure!";
ret = cmkr::gen::generate_cmake(fs::current_path().string().c_str());
if (ret)
return "CMake generation error!";
return "Directory initialized!"; return "Directory initialized!";
} 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 run 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());
@ -61,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!";
}
}

@ -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 <sstream>
#include <cstddef>
#include <stdexcept>
#include <cstdlib> #include <cstdlib>
#include <system_error> #include <sstream>
namespace cmkr { namespace cmkr {
namespace build { namespace build {
@ -17,15 +13,14 @@ 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;
if (gen::generate_cmake(fs::current_path().string().c_str())) gen::generate_cmake(fs::current_path().string().c_str());
throw std::runtime_error("CMake generation failure!");
ss << "cmake -S. -DCMKR_BUILD_SKIP_GENERATION=ON -B" << project.build_dir << " "; ss << "cmake -DCMKR_BUILD_SKIP_GENERATION=ON -B" << project.build_dir << " ";
if (!project.generator.empty()) { if (!project.generator.empty()) {
ss << "-G \"" << project.generator << "\" "; ss << "-G \"" << project.generator << "\" ";
@ -49,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() {
@ -65,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);
}
}

File diff suppressed because it is too large Load Diff

@ -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];
}

@ -1,9 +1,12 @@
#include "help.hpp" #include "help.hpp"
#include <resources/version.hpp>
namespace cmkr { namespace cmkr {
namespace help { namespace help {
const char *version() noexcept { return "cmkr version 0.1.3"; } const char *version() noexcept {
return "cmkr version " CMKR_VERSION;
}
const char *message() noexcept { const char *message() noexcept {
return R"lit( return R"lit(
@ -20,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(); }

File diff suppressed because it is too large Load Diff

58
tests/CMakeLists.txt generated

@ -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,51 @@ 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
) )
add_test(
NAME
templates
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/templates"
COMMAND
"$<TARGET_FILE:cmkr>"
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()

@ -1,41 +1,67 @@
[[test]] [[test]]
name = "basic" name = "basic"
command = "$<TARGET_FILE:cmkr>"
working-directory = "basic" working-directory = "basic"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "interface" name = "interface"
command = "$<TARGET_FILE:cmkr>"
working-directory = "interface" working-directory = "interface"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "fetch-content" name = "fetch-content"
command = "$<TARGET_FILE:cmkr>"
working-directory = "fetch-content" working-directory = "fetch-content"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "conditions" name = "conditions"
command = "$<TARGET_FILE:cmkr>"
working-directory = "conditions" working-directory = "conditions"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "vcpkg" name = "vcpkg"
command = "$<TARGET_FILE:cmkr>"
working-directory = "vcpkg" working-directory = "vcpkg"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "cxx-standard" name = "cxx-standard"
command = "$<TARGET_FILE:cmkr>"
working-directory = "cxx-standard" working-directory = "cxx-standard"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "globbing" name = "globbing"
command = "$<TARGET_FILE:cmkr>"
working-directory = "globbing" working-directory = "globbing"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
[[test]]
name = "templates"
working-directory = "templates"
command = "$<TARGET_FILE:cmkr>"
arguments = ["build"]
[[test]]
condition = "msvc"
name = "msvc-runtime"
working-directory = "msvc-runtime"
command = "$<TARGET_FILE:cmkr>"
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"] arguments = ["build"]

@ -0,0 +1,15 @@
# Example project that sets compiler/linker flags for various platforms.
[project]
name = "compile-options"
description = "Compiler flags"
[target.hello]
type = "executable"
sources = ["src/main.cpp"]
msvc.compile-options = ["/W2"]
gcc.compile-options = ["-Wall"]
clang.compile-options = ["-Wall"]
# The `hello` target uses [conditions](/cmake-toml#conditions) to set different compiler flags 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.

@ -0,0 +1,5 @@
#include <cstdio>
int main() {
puts("Hello from cmkr!");
}

@ -2,6 +2,9 @@
name = "conditions" name = "conditions"
cmake-after = "set(CUSTOM ON)" cmake-after = "set(CUSTOM ON)"
[options]
CONDITIONS_BUILD_TESTS = "root"
[conditions] [conditions]
custom = "CUSTOM" custom = "CUSTOM"
@ -15,6 +18,8 @@ macos.cmake-after = "message(STATUS macos-after)"
linux.cmake-after = "message(STATUS linux-after)" linux.cmake-after = "message(STATUS linux-after)"
unix.cmake-after = "message(STATUS unix-after)" unix.cmake-after = "message(STATUS unix-after)"
custom.cmake-after = "message(STATUS custom-after)" custom.cmake-after = "message(STATUS custom-after)"
build-tests.cmake-after = "message(STATUS build-tests)"
"CONDITIONS_BUILD_TESTS AND $<linux>".cmake-after = "message(STATUS linux-tests)"
[target.example.properties] [target.example.properties]
AUTOMOC = false AUTOMOC = false

@ -1 +1,2 @@
int main() { } int main() {
}

@ -1,3 +1,4 @@
#include <Windows.h> #include <Windows.h>
void foo() { } void foo() {
}

@ -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));
} }

@ -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");
} }

@ -2,7 +2,6 @@
#include <string> #include <string>
namespace mylib namespace mylib {
{
std::string message(); std::string message();
} } // namespace mylib

@ -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!";
} }

@ -5,6 +5,7 @@ description = "Header-only library"
[target.mylib] [target.mylib]
type = "interface" type = "interface"
include-directories = ["include"] include-directories = ["include"]
compile-features = ["cxx_std_11"]
[target.example] [target.example]
type = "executable" type = "executable"

@ -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

@ -2,7 +2,6 @@
#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())
} }

@ -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"

@ -0,0 +1,5 @@
#include <cstdio>
int main() {
puts("Hello from cmkr(msvc-static)!");
}

@ -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!");
}

@ -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
}

@ -0,0 +1,25 @@
# To avoid repeating yourself in targets you can create your own target type (template). All properties of the template are inherited when used as a target type.
[project]
name = "templates"
description = "Target templates"
[template.app]
type = "executable"
sources = ["src/templates.cpp"]
compile-definitions = ["IS_APP"]
# Unlike interface targets you can also inherit properties
[template.app.properties]
CXX_STANDARD = "11"
CXX_STANDARD_REQUIRED = true
[target.app-a]
type = "app"
compile-definitions = ["APP_A"]
[target.app-b]
type = "app"
compile-definitions = ["APP_B"]
# **Note**: In most cases you probably want to use an [interface](/examples/interface) target instead.

@ -0,0 +1,13 @@
#include <cstdio>
#if !defined(IS_APP)
#error Something went wrong with the template
#endif // IS_APP
int main() {
#if defined(APP_A)
puts("Hello from app A!");
#elif defined(APP_B)
puts("Hello from app B!");
#endif
}

@ -7,7 +7,7 @@ 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.html for available packages
[vcpkg] [vcpkg]
version = "2021.05.12" version = "2024.03.25"
packages = ["fmt"] packages = ["fmt"]
[find-package] [find-package]
@ -19,3 +19,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]`.

@ -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");
} }

@ -0,0 +1,3 @@
# Disable clang-format in this folder
DisableFormat: true
SortIncludes: Never

4
third_party/CMakeLists.txt generated vendored

@ -16,7 +16,3 @@ target_include_directories(toml11 INTERFACE toml11-3.6.0)
# 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)

@ -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
Loading…
Cancel
Save