Compare commits

...

77 Commits

Author SHA1 Message Date
Duncan Ogilvie 264e4ace18 Fix bug checking the root path of subdirectories 2021-06-26 17:15:56 +02:00
Duncan Ogilvie b6ab584a1a Bump CMKR_TAG 2021-06-26 16:28:12 +02:00
Duncan Ogilvie 3cd84a9708 Add basic support for [subdir.mydir] 2021-06-26 16:22:26 +02:00
Duncan Ogilvie 9932e501ce Rename files to make the project easier to navigate 2021-06-25 12:38:48 +02:00
Duncan Ogilvie 1b37dd76a5 Rename things to try to make the code more readable 2021-06-25 12:25:58 +02:00
Duncan Ogilvie 82f2a11311 Bump CMKR_TAG 2021-06-23 22:36:29 +02:00
Duncan Ogilvie eaf03eb785 Add support for target condition 2021-06-15 02:15:06 +02:00
Duncan Ogilvie 8ea5b77ba5 Merge pull request #28 from build-cpp/conditional-properties
Implement conditional properties
2021-06-14 23:38:47 +02:00
Duncan Ogilvie a12b3ae021 Bump CMKR_TAG 2021-06-14 23:36:39 +02:00
Duncan Ogilvie 2450cfb2c9 Implement conditional properties
Closes #8
2021-06-14 23:29:51 +02:00
Duncan Ogilvie 8d024556e3 Fix CI 2021-06-14 04:34:44 +02:00
Duncan Ogilvie af3807ca2b Add support for private- target options 2021-06-14 04:01:02 +02:00
Duncan Ogilvie 17f085c66d Minor improvements to cmkr.cmake 2021-06-01 17:14:08 +02:00
Duncan Ogilvie 5ad6134e07 Merge pull request #27 from build-cpp/manifest
Add support for headers and vcpkg manifest mode
2021-05-31 15:30:34 +02:00
Duncan Ogilvie 7b20d8c54c Restore [vcpkg].version functionality and add a test + documentation 2021-05-31 14:02:13 +02:00
MoAlyousef ffdedbdace fixes 2021-05-29 17:40:44 +03:00
MoAlyousef bb7a0bc0ed signal failure to write a vcpkg.json file 2021-05-28 05:48:23 +03:00
MoAlyousef dd0003f8fe add nlohmann_json to cmake toml 2021-05-28 05:39:00 +03:00
MoAlyousef a32caca8f0 fix fetching vcpkg 2021-05-28 05:08:45 +03:00
MoAlyousef f565ad2af0 fix formatting, add check for project version in manifest mode 2021-05-28 05:03:00 +03:00
MoAlyousef dc4b59f05d prelim vcpkg manifest support 2021-05-28 04:54:04 +03:00
Duncan Ogilvie 4988f141e4 Bump version in cmkr.cmake bootstrapper 2021-05-18 13:14:43 +02:00
Duncan Ogilvie 64b58425e6 Add missing code generation for link-options 2021-05-18 13:13:48 +02:00
Duncan Ogilvie d4f0cdf152 Allow test working directories with a relative path 2021-05-16 23:07:22 +02:00
Duncan Ogilvie 306bb3d4fc Automatically generate documentation from tests 2021-05-16 22:55:55 +02:00
Duncan Ogilvie acd3688d16 Fix [fetch-content] 2021-05-16 22:51:42 +02:00
Duncan Ogilvie 23c5713c6b Fix pipeline typos 2021-05-13 21:48:21 +02:00
Duncan Ogilvie cebe73c8e5 Improved dark theme 2021-05-13 21:43:34 +02:00
Duncan Ogilvie 779d4ae96a Update README.md 2021-05-13 15:32:07 +02:00
Duncan Ogilvie 7eed60bc7d Use dark theme when the system uses dark theme in the documentation 2021-05-13 06:16:36 +02:00
Duncan Ogilvie aa468dcf9c Only upload artifacts for certain operating systems in the matrix 2021-05-13 05:53:46 +02:00
Duncan Ogilvie 1bd9d2228e Logic for prereleases in github actions 2021-05-13 05:47:37 +02:00
Duncan Ogilvie 5364b5ea72 Add credits for documentation favicon 2021-05-13 05:30:56 +02:00
Duncan Ogilvie 7a5d3b0491 Github actions artifacts and release binaries 2021-05-13 05:29:21 +02:00
Duncan Ogilvie 02f1a70628 Use relative paths in the install command to support --prefix 2021-05-13 04:37:28 +02:00
Duncan Ogilvie 7bd97e56e3 Update README.md 2021-05-13 04:19:08 +02:00
Duncan Ogilvie 6e0e3d8215 Update index.md 2021-05-13 04:18:55 +02:00
Duncan Ogilvie 00230ee11a Update index.md 2021-05-13 04:18:42 +02:00
Duncan Ogilvie e734886d9f Merge pull request #22 from darknessxk/feature/docs
Feature/docs
2021-05-13 04:14:59 +02:00
Duncan Ogilvie cf748514fb Use rewritten readme as a base for the documentation 2021-05-13 03:58:23 +02:00
Luiz "darknessxk" Felipe fbe968f817 Fixed search issue 2021-05-13 03:29:42 +02:00
Luiz "darknessxk" Felipe d1097c8303 Rolled back dark theme,e removed import from folder, more examples will be added with time 2021-05-13 03:29:41 +02:00
Luiz "darknessxk" Felipe 8697d87e50 Fixed wrong permalinks 2021-05-13 03:29:41 +02:00
Luiz "darknessxk" Felipe 7dfa905625 Changed the examples pattern to a better one with indexation, better ordered menus 2021-05-13 03:29:41 +02:00
Luiz "darknessxk" Felipe 9a008f0e40 Enabled search 2021-05-13 03:29:41 +02:00
Luiz "darknessxk" Felipe deb08bcf79 Changed page's title to h1 2021-05-13 03:29:41 +02:00
Luiz "darknessxk" Felipe 3ba07bfd17 Added Quickstart example 2021-05-13 03:29:41 +02:00
Luiz "darknessxk" Felipe 3f1dfe5be3 Added shell to markdown code blocks 2021-05-13 03:29:41 +02:00
Luiz "darknessxk" Felipe a002ddc606 Added Usage title to the page 2021-05-13 03:29:40 +02:00
Luiz "darknessxk" Felipe c686f1bec5 Added building page 2021-05-13 03:29:40 +02:00
Luiz "darknessxk" Felipe 812ef8e7a6 Added navigation order, split building block to its own page 2021-05-13 03:29:40 +02:00
Luiz "darknessxk" Felipe 862fce189c Removed about page 2021-05-13 03:29:40 +02:00
Luiz "darknessxk" Felipe cd98345125 Enabled dark theme 2021-05-13 03:29:40 +02:00
Luiz "darknessxk" Felipe 945e4b74c4 Added readme content to index page 2021-05-13 03:29:39 +02:00
Luiz "darknessxk" Felipe 2ad6acbce9 Used to run jekyll locally 2021-05-13 03:29:39 +02:00
Luiz "darknessxk" Felipe c893ddd8c5 Default assets 2021-05-13 03:29:39 +02:00
Luiz "darknessxk" Felipe 55fa8b937a Added default index (to be changed) 2021-05-13 03:29:39 +02:00
Luiz "darknessxk" Felipe 2648d8c6c8 Added About, Examples, Usage folders with a few content 2021-05-13 03:29:39 +02:00
Luiz "darknessxk" Felipe 3413105fec Default 404 page 2021-05-13 03:29:39 +02:00
Luiz "darknessxk" Felipe 85bef09710 docs ignored folder 2021-05-13 03:29:38 +02:00
Luiz "darknessxk" Felipe 964961eb64 Jekyll configuration and prep 2021-05-13 03:29:38 +02:00
Duncan Ogilvie b350ed2c55 Rewrite README 2021-05-13 03:22:38 +02:00
Duncan Ogilvie 7cf16eaf70 Merge pull request #20 from build-cpp/conditional-subdirs
Add support for conditional subdirs
2021-05-04 12:42:04 +02:00
Duncan Ogilvie 9622334bf1 Switch to using target_sources instead of passing sources directly to add_xxx 2021-05-03 19:39:22 +02:00
Duncan Ogilvie 6ad29ef624 Allow conditional subdirs 2021-05-03 19:37:39 +02:00
Duncan Ogilvie 718c2c7527 Get rid of redundant name field in cmkr init 2021-05-03 17:45:51 +02:00
Duncan Ogilvie 8ea0c7396c Merge pull request #19 from build-cpp/project-refactor
Project refactor
2021-05-03 17:42:08 +02:00
Duncan Ogilvie 34c12379c2 Add a check to see whether cmkr was run before pushing 2021-05-03 17:35:31 +02:00
Duncan Ogilvie 6395267e4b Merge cmkrlib into the cmkr target 2021-05-03 17:23:33 +02:00
Duncan Ogilvie 6d9b40bd15 Get rid of hack to hide a warning during bootstrapping on Windows 2021-05-03 17:08:23 +02:00
Duncan Ogilvie c4673d59e2 Simplify default conditions
It was JustMagic's idea to add 'lunix'
2021-05-03 17:05:19 +02:00
Duncan Ogilvie 220dec6bbb Merge pull request #18 from darknessxk/task/change-init-code
Task/change init code
2021-05-03 16:27:16 +02:00
darknessxk 4efa74f91f Changed project string from [[target]] to [target.%s] 2021-05-03 11:21:59 -03:00
darknessxk fbd07c47bc Added argument to target name 2021-05-03 11:21:26 -03:00
Duncan Ogilvie 17d4dc0555 Move all links to the new organization 2021-05-03 15:42:37 +02:00
Duncan Ogilvie a6dfb2272d Add docs placeholder for pages 2021-05-03 14:09:42 +02:00
Duncan Ogilvie 7fdafa4189 Delete CHANGELOG.md and move to GitHub releases 2021-05-03 11:45:28 +02:00
59 changed files with 26878 additions and 373 deletions
+1
View File
@@ -0,0 +1 @@
CMakeLists.txt linguist-generated
+37
View File
@@ -4,6 +4,8 @@ on: [push, pull_request]
jobs:
build:
# Skip building pull requests from the same repository
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != '${{ github.repository }}'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
@@ -14,11 +16,46 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build
run: |
cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}
cmake --build build --config ${{ env.BUILD_TYPE }} --parallel
cmake --install build --prefix ./install --config ${{ env.BUILD_TYPE }}
- name: Check if cmkr was run
run: |
./install/bin/cmkr gen
git diff --exit-code
- name: Test
run: |
cd build/tests
ctest -C ${{ env.BUILD_TYPE }}
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: ${{ github.event.repository.name }}-${{ matrix.os }}
path: install/bin/*
- name: Get lowercase OS name
id: osname
uses: ASzc/change-string-case-action@v1
with:
string: ${{ runner.os }}
- name: Compress artifacts
uses: papeloto/action-zip@v1
with:
files: install/bin/
dest: ${{ github.event.repository.name }}-${{ steps.osname.outputs.lowercase }}.zip
- name: Release
uses: softprops/action-gh-release@v1
if: ${{ startsWith(github.ref, 'refs/tags/') && (matrix.os == 'windows-2019' || matrix.os == 'macos-10.15' || matrix.os == 'ubuntu-16.04') }}
with:
prerelease: ${{ !startsWith(github.ref, 'refs/tags/v') || contains(github.ref, '-pre') }}
files: ${{ github.event.repository.name }}-${{ steps.osname.outputs.lowercase }}.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-27
View File
@@ -1,27 +0,0 @@
# CHANGELOG
## 0.1.4 - 2021-04-11
- Use `GIT_SHALLOW ON` by default when getting git dependencies.
- Add cmake.description field.
- Change bin.defines to bin.definitions.
## 0.1.3 - 2020-11-27
- Support building with C++11.
- @mrexodia implemented CMake integration and bootstrapping.
- Add dependency on ghc_filesystem and mpark_variant which are fetched automatically using FetchContent.
## 0.1.2 - 2020-11-20
- Add support for target properties.
- Add installs.
- Require cmake >= 3.15.
- Support settings and caching settings.
- Support config when running cmkr build.
- Add prompt prior to CMakeLists.txt generation if already existent in the current dir.
## 0.1.1 - 2020-11-19
- Add support for globbing.
- Add support for find_package components.
- Add options.
- Support aliases.
- Support interface libs (header-only libs).
- Support testing.
+55 -48
View File
@@ -1,5 +1,5 @@
# This file is automatically generated from cmake.toml - DO NOT EDIT
# See https://github.com/MoAlyousef/cmkr for more information
# See https://github.com/build-cpp/cmkr for more information
cmake_minimum_required(VERSION 2.8...3.8)
@@ -23,10 +23,6 @@ if(CMKR_ROOT_PROJECT)
configure_file(cmake.toml cmake.toml COPYONLY)
endif()
# Hack to hide a warning during cmkr bootstrapping on Windows
if(CMAKE_BUILD_TYPE)
endif()
project(cmkr
LANGUAGES
CXX
@@ -36,6 +32,8 @@ project(cmkr
"CMakeLists generator from TOML"
)
include("cmake/generate_documentation.cmake")
# third_party
set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER})
if(CMAKE_FOLDER)
@@ -57,62 +55,56 @@ add_subdirectory(tests)
set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER})
# Target cmkrlib
unset(cmkrlib_SOURCES)
list(APPEND cmkrlib_SOURCES
"src/cmkrlib/args.cpp"
"src/cmkrlib/build.cpp"
"src/cmkrlib/cmake.cpp"
"src/cmkrlib/error.cpp"
"src/cmkrlib/gen.cpp"
"src/cmkrlib/help.cpp"
"src/cmkrlib/cmake.hpp"
"src/cmkrlib/enum_helper.hpp"
"src/cmkrlib/fs.hpp"
"include/args.h"
"include/build.h"
"include/error.h"
"include/gen.h"
"include/help.h"
"include/literals.h"
)
# Target cmkr_generate_documentation
set(CMKR_TARGET cmkr_generate_documentation)
set(cmkr_generate_documentation_SOURCES "")
list(APPEND cmkrlib_SOURCES
cmake.toml
)
set(CMKR_SOURCES ${cmkr_generate_documentation_SOURCES})
add_library(cmkr_generate_documentation INTERFACE)
add_library(cmkrlib STATIC ${cmkrlib_SOURCES})
if(cmkr_generate_documentation_SOURCES)
target_sources(cmkr_generate_documentation INTERFACE ${cmkr_generate_documentation_SOURCES})
endif()
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${cmkrlib_SOURCES})
generate_documentation()
target_compile_features(cmkrlib PUBLIC
cxx_std_11
)
target_include_directories(cmkrlib PUBLIC
include
)
target_link_libraries(cmkrlib PUBLIC
toml11
ghc_filesystem
mpark_variant
ordered_map
)
unset(CMKR_TARGET)
unset(CMKR_SOURCES)
# Target cmkr
unset(cmkr_SOURCES)
set(CMKR_TARGET cmkr)
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/build.hpp"
"include/cmake_generator.hpp"
"include/enum_helper.hpp"
"include/error.hpp"
"include/fs.hpp"
"include/help.hpp"
"include/literals.hpp"
"include/project_parser.hpp"
)
list(APPEND cmkr_SOURCES
cmake.toml
)
add_executable(cmkr ${cmkr_SOURCES})
set(CMKR_SOURCES ${cmkr_SOURCES})
add_executable(cmkr)
if(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)
@@ -121,15 +113,30 @@ endif()
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${cmkr_SOURCES})
target_link_libraries(cmkr PRIVATE
cmkrlib
target_compile_features(cmkr PRIVATE
cxx_std_11
)
target_include_directories(cmkr PRIVATE
include
)
target_link_libraries(cmkr PRIVATE
toml11
ghc_filesystem
mpark_variant
ordered_map
nlohmann_json
)
unset(CMKR_TARGET)
unset(CMKR_SOURCES)
install(
TARGETS
cmkr
DESTINATION
"${CMAKE_INSTALL_PREFIX}/bin"
bin
COMPONENT
cmkr
)
+26 -55
View File
@@ -1,40 +1,35 @@
# cmkr
cmkr, pronounced "cmaker", is A CMakeLists.txt generator from TOML.
`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).
See the [cmkr topic](https://github.com/topics/cmkr) for examples. Feel free to add the `cmkr` topic to your projects if you used cmkr!
## Building
cmkr requires a C++11 compiler, cmake >= 3.15.
```
git clone https://github.com/moalyousef/cmkr
cd cmkr
cmake -Bbin
cmake --build bin --parallel
```
## Usage
cmkr parses cmake.toml files (using toml11 by Toru Niina) at the project directory. A basic hello world format with the minimum required fields:
`cmkr` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example:
```toml
[cmake]
minimum = "3.15"
[project]
name = "app"
version = "0.1.0"
name = "cmkr_for_beginners"
description = "A minimal cmkr project."
[target.app]
[target.hello_world]
type = "executable"
sources = ["src/main.cpp"]
```
**NOTE**: The documentation is currently a work-in-progress due to breaking changes since `0.1.4`. For examples you can check the [cmkr topic](https://github.com/topics/cmkr).
`cmkr` can bootstrap itself from CMake and consumers of your project do not need to install anything to work with it.
The cmkr executable can be run from the command-line:
## 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), 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).
## Command line
Optionally you can install `cmkr` in your `PATH` and use it as a utility from the command line:
```
Usage: cmkr [arguments]
@@ -48,34 +43,10 @@ arguments:
version Current cmkr version.
```
The build command invokes cmake and the default build-system on your platform (unless a generator is specified), it also accepts extra cmake build arguments:
## Credits
```
cmkr build --config Release
```
## Binary types
### executable
Executable binary. Equivalent to [add_executable(name)](https://cmake.org/cmake/help/latest/command/add_executable.html).
### library
Library, can be static or shared depending on the BUILD_SHARED_LIBS variable. Equivalent to [add_library()](https://cmake.org/cmake/help/latest/command/add_library.html).
### static
Static library/archive. Equivalent to [add_library(name STATIC)](https://cmake.org/cmake/help/latest/command/add_library.html).
### shared
Shared/dynamic library. Equivalent to [add_library(name SHARED)](https://cmake.org/cmake/help/latest/command/add_library.html).
### interface
Header-only library. Equivalent to [add_library(name INTERFACE)](https://cmake.org/cmake/help/latest/command/add_library.html).
## Roadmap
- Support more cmake fields.
- https://github.com/gulrak/filesystem
- https://github.com/Tessil/ordered-map
- https://github.com/ToruNiina/toml11
- https://github.com/mpark/variant
- https://www.svgrepo.com/svg/192268/hammer
+11 -14
View File
@@ -2,29 +2,26 @@
version = "2.8...3.8"
[project]
cmake-before = """
# Hack to hide a warning during cmkr bootstrapping on Windows
if(CMAKE_BUILD_TYPE)
endif()
"""
name = "cmkr"
version = "0.1.4"
description = "CMakeLists generator from TOML"
languages = ["CXX"]
subdirs = ["third_party", "tests"]
include-after = ["cmake/generate_documentation.cmake"]
[target.cmkrlib]
type = "static"
sources = ["src/cmkrlib/*.cpp", "src/cmkrlib/*.hpp", "include/*.h"]
include-directories = ["include"]
compile-features = ["cxx_std_11"]
link-libraries = ["toml11", "ghc_filesystem", "mpark_variant", "ordered_map"]
[target.cmkr_generate_documentation]
type = "interface"
cmake-after = """
generate_documentation()
"""
[target.cmkr]
type = "executable"
sources = ["src/main.cpp"]
link-libraries = ["cmkrlib"]
sources = ["src/*.cpp", "include/*.hpp"]
include-directories = ["include"]
compile-features = ["cxx_std_11"]
link-libraries = ["toml11", "ghc_filesystem", "mpark_variant", "ordered_map", "nlohmann_json"]
[[install]]
targets = ["cmkr"]
destination = "${CMAKE_INSTALL_PREFIX}/bin"
destination = "bin"
+11 -4
View File
@@ -1,15 +1,15 @@
include_guard()
# Change these defaults to point to your infrastructure if desired
set(CMKR_REPO "https://github.com/MoAlyousef/cmkr" CACHE STRING "cmkr git repository" FORCE)
set(CMKR_TAG "archive_7b7b2603" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
set(CMKR_TAG "archive_3cd84a97" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
# Set these from the command line to customize for development/debugging purposes
set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable")
set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation")
# Disable cmkr if generation is disabled
if(CMKR_SKIP_GENERATION)
if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION)
message(STATUS "[cmkr] Skipping automatic cmkr generation")
macro(cmkr)
endmacro()
@@ -78,10 +78,12 @@ else()
)
message(STATUS "[cmkr] Building cmkr...")
cmkr_exec("${CMAKE_COMMAND}"
--no-warn-unused-cli
"${CMKR_DIRECTORY}"
"-B${CMKR_DIRECTORY}/build"
"-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}"
"-DCMKR_GENERATE_DOCUMENTATION=OFF"
)
cmkr_exec("${CMAKE_COMMAND}"
--build "${CMKR_DIRECTORY}/build"
@@ -130,10 +132,15 @@ macro(cmkr)
file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST)
# Delete the temporary file if it was left for some reason
set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt")
if(EXISTS "${CMKR_TEMP_FILE}")
file(REMOVE "${CMKR_TEMP_FILE}")
endif()
if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST)
# Copy the now-generated CMakeLists.txt to CMakerLists.txt
# This is done because you cannot include() a file you are currently in
set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt")
configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY)
# Add the macro required for the hack at the start of the cmkr macro
+20
View File
@@ -0,0 +1,20 @@
---
# Automatically generated from tests/@EXAMPLE_PERMALINK@/cmake.toml - DO NOT EDIT
layout: default
title: @EXAMPLE_TITLE@
permalink: /examples/@EXAMPLE_PERMALINK@
parent: Examples
nav_order: @EXAMPLE_INDEX@
---
# @EXAMPLE_TITLE@
@EXAMPLE_HEADER@
```toml
@EXAMPLE_TOML@
```
@EXAMPLE_FOOTER@
<sup><sub>This page was automatically generated from [tests/@EXAMPLE_PERMALINK@/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/@EXAMPLE_PERMALINK@/cmake.toml).</sub></sup>
+76
View File
@@ -0,0 +1,76 @@
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)
if(CMKR_GENERATE_DOCUMENTATION)
message(STATUS "[cmkr] Generating documentation...")
# Delete previously generated examples
set(example_folder "${PROJECT_SOURCE_DIR}/docs/examples")
file(GLOB example_files "${example_folder}/*.md")
list(REMOVE_ITEM example_files "${example_folder}/index.md")
if(example_files)
file(REMOVE ${example_files})
endif()
message(DEBUG "[cmkr] Test directories: ${CMKR_TESTS}")
set(test_index 0)
foreach(test_dir ${CMKR_TESTS})
set(test_name "${test_dir}")
set(test_dir "${PROJECT_SOURCE_DIR}/tests/${test_dir}")
set(test_toml "${test_dir}/cmake.toml")
if(IS_DIRECTORY "${test_dir}" AND EXISTS "${test_toml}")
message(DEBUG "[cmkr] Generating documentation for: ${test_toml} (index: ${test_index})")
# Set template variables
set(EXAMPLE_PERMALINK "${test_name}")
set(EXAMPLE_INDEX ${test_index})
math(EXPR test_index "${test_index}+1")
# Read cmake.toml file
file(READ "${test_toml}" test_contents NO_HEX_CONVERSION)
string(LENGTH "${test_contents}" toml_length)
# Extract header text
string(REGEX MATCH "^(\n*(#[^\n]+\n)+\n*)" EXAMPLE_HEADER "${test_contents}")
string(LENGTH "${EXAMPLE_HEADER}" header_length)
string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER)
string(REGEX REPLACE "\n# ?" "\n" EXAMPLE_HEADER "\n${EXAMPLE_HEADER}")
string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER)
# Extract footer text
string(REGEX MATCH "(((#[^\n]+)(\n+|$))+)$" EXAMPLE_FOOTER "${test_contents}")
string(LENGTH "${EXAMPLE_FOOTER}" footer_length)
string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER)
string(REGEX REPLACE "\n# ?" "\n" EXAMPLE_FOOTER "\n${EXAMPLE_FOOTER}")
string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER)
# Extract toml body
math(EXPR toml_length "${toml_length}-${header_length}-${footer_length}")
string(SUBSTRING "${test_contents}" ${header_length} ${toml_length} EXAMPLE_TOML)
string(STRIP "${EXAMPLE_TOML}" EXAMPLE_TOML)
# Extract title from description
if("${EXAMPLE_TOML}" MATCHES "description *= *\"([^\"]+)\"")
set(EXAMPLE_TITLE "${CMAKE_MATCH_1}")
# Generate documentation markdown page
configure_file("${PROJECT_SOURCE_DIR}/cmake/example.md.in" "${example_folder}/${EXAMPLE_PERMALINK}.md" @ONLY NEWLINE_STYLE LF)
else()
message(DEBUG "[cmkr] Skipping documentation generation for ${test_name} because description is missing")
endif()
endif()
endforeach()
endif()
endfunction()
+2
View File
@@ -0,0 +1,2 @@
_site/
.jekyll-metadata
+25
View File
@@ -0,0 +1,25 @@
---
permalink: /404.html
layout: default
---
<style type="text/css" media="screen">
.container {
margin: 10px auto;
max-width: 600px;
text-align: center;
}
h1 {
margin: 30px 0;
font-size: 4em;
line-height: 1;
letter-spacing: -1px;
}
</style>
<div class="container">
<h1>404</h1>
<p><strong>Page not found :(</strong></p>
<p>The requested page could not be found.</p>
</div>
+13
View File
@@ -0,0 +1,13 @@
source "https://rubygems.org"
gem "minima", "~> 2.5"
gem "github-pages", group: :jekyll_plugins
gem "jekyll-remote-theme"
platforms :mingw, :x64_mingw, :mswin, :jruby do
gem "tzinfo", "~> 1.2"
gem "tzinfo-data"
end
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
gem "just-the-docs"
+280
View File
@@ -0,0 +1,280 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.3.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.17.13)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.8)
dnsruby (1.61.5)
simpleidn (~> 0.1)
em-websocket (0.5.2)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
ethon (0.14.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.7.0)
faraday (1.4.1)
faraday-excon (~> 1.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-excon (1.1.0)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.1.0)
ffi (1.15.0)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (214)
github-pages-health-check (= 1.17.0)
jekyll (= 3.9.0)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.1.6)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.15.1)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.13.0)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.7.1)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.1.1)
jekyll-theme-cayman (= 0.1.1)
jekyll-theme-dinky (= 0.1.1)
jekyll-theme-hacker (= 0.1.2)
jekyll-theme-leap-day (= 0.1.1)
jekyll-theme-merlot (= 0.1.1)
jekyll-theme-midnight (= 0.1.1)
jekyll-theme-minimal (= 0.1.1)
jekyll-theme-modernist (= 0.1.1)
jekyll-theme-primer (= 0.5.4)
jekyll-theme-slate (= 0.1.1)
jekyll-theme-tactile (= 0.1.1)
jekyll-theme-time-machine (= 0.1.1)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
kramdown (= 2.3.1)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.10.4, < 2.0)
rouge (= 3.26.0)
terminal-table (~> 1.4)
github-pages-health-check (1.17.0)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
public_suffix (>= 2.0.2, < 5.0)
typhoeus (~> 1.3)
html-pipeline (2.14.0)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.6.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.0)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.7.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.3.1)
commonmarker (~> 0.14)
jekyll (>= 3.7, < 5.0)
jekyll-commonmark-ghpages (0.1.6)
commonmarker (~> 0.17.6)
jekyll-commonmark (~> 1.2)
rouge (>= 2.0, < 4.0)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.15.1)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.13.0)
jekyll (>= 3.4, < 5.0)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.7.1)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.1.2)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.5.4)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.1.1)
jekyll (~> 3.5)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.12.0)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
just-the-docs (0.3.3)
jekyll (>= 3.8.5)
jekyll-seo-tag (~> 2.0)
rake (>= 12.3.1, < 13.1.0)
kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
listen (3.5.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
mini_portile2 (2.5.1)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.14.4)
multipart-post (2.1.1)
nokogiri (1.11.3)
mini_portile2 (~> 2.5.0)
racc (~> 1.4)
octokit (4.21.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.6)
racc (1.5.2)
rake (13.0.3)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (3.26.0)
ruby-enum (0.9.0)
i18n
ruby2_keywords (0.0.4)
rubyzip (2.3.0)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
simpleidn (0.2.1)
unf (~> 0.1.4)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (1.2.9)
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
zeitwerk (2.4.2)
PLATFORMS
ruby
DEPENDENCIES
github-pages
jekyll-remote-theme
just-the-docs
minima (~> 2.5)
tzinfo (~> 1.2)
tzinfo-data
wdm (~> 0.1.1)
BUNDLED WITH
2.1.2
+21
View File
@@ -0,0 +1,21 @@
title: cmkr
plugins:
- jekyll-remote-theme
# Automatically deduce dark theme preference https://github.com/pmarsceill/just-the-docs/pull/464
remote_theme: build-cpp/just-the-docs@light-switch
search_enabled: true
color_scheme: light-or-dark
heading_anchors: true
aux_links:
"cmkr":
- "https://github.com/build-cpp/cmkr"
aux_links_new_tab: true
gh_edit_link: true
gh_edit_link_text: "Edit this page on GitHub."
gh_edit_repository: "https://github.com/build-cpp/cmkr"
gh_edit_branch: "main"
gh_edit_view_mode: "edit"
gh_edit_source: docs
+22
View File
@@ -0,0 +1,22 @@
---
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.
```
+26
View File
@@ -0,0 +1,26 @@
---
# Automatically generated from tests/basic/cmake.toml - DO NOT EDIT
layout: default
title: Minimal example
permalink: /examples/basic
parent: Examples
nav_order: 0
---
# Minimal example
A minimal `cmake.toml` project:
```toml
[project]
name = "basic"
description = "Minimal example"
[target.basic]
type = "executable"
sources = ["src/basic.cpp"]
```
Declares an executable target called `basic` with `src/basic.cpp` as a source file. Equivalent to CMake's [add_executable](https://cmake.org/cmake/help/latest/command/add_executable.html)`(basic src/basic.cpp)`.
<sup><sub>This page was automatically generated from [tests/basic/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/basic/cmake.toml).</sub></sup>
+30
View File
@@ -0,0 +1,30 @@
---
# Automatically generated from tests/fetch-content/cmake.toml - DO NOT EDIT
layout: default
title: Fetching from git
permalink: /examples/fetch-content
parent: Examples
nav_order: 2
---
# Fetching from git
Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) from [GitHub](https://github.com) and links an `example` target to it:
```toml
[project]
name = "fetch-content"
description = "Fetching from git"
[fetch-content]
fmt = { git = "https://github.com/fmtlib/fmt", tag = "7.1.3" }
[target.example]
type = "executable"
sources = ["src/main.cpp"]
link-libraries = ["fmt::fmt"]
```
This is equivalent to calling CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html).
<sup><sub>This page was automatically generated from [tests/fetch-content/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/fetch-content/cmake.toml).</sub></sup>
+11
View File
@@ -0,0 +1,11 @@
---
layout: default
title: Examples
permalink: /examples/
nav_order: 100
has_children: true
---
# Examples
The examples in this section are automatically generated from the [tests](https://github.com/build-cpp/cmkr/blob/main/tests/cmake.toml).
+31
View File
@@ -0,0 +1,31 @@
---
# Automatically generated from tests/interface/cmake.toml - DO NOT EDIT
layout: default
title: Header-only library
permalink: /examples/interface
parent: Examples
nav_order: 1
---
# Header-only library
```toml
[project]
name = "interface"
description = "Header-only library"
[target.mylib]
type = "interface"
include-directories = ["include"]
[target.example]
type = "executable"
sources = ["src/main.cpp"]
link-libraries = ["mylib"]
```
<sup><sub>This page was automatically generated from [tests/interface/cmake.toml](https://github.com/build-cpp/cmkr/tree/main/tests/interface/cmake.toml).</sub></sup>
+36
View File
@@ -0,0 +1,36 @@
---
# Automatically generated from tests/vcpkg/cmake.toml - DO NOT EDIT
layout: default
title: Dependencies from vcpkg
permalink: /examples/vcpkg
parent: Examples
nav_order: 4
---
# Dependencies from vcpkg
Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://vcpkg.io/) and links an `example` target to it:
```toml
[project]
name = "vcpkg"
description = "Dependencies from vcpkg"
# See https://github.com/microsoft/vcpkg/releases for vcpkg versions
# See https://vcpkg.io/en/packages.html for available packages
[vcpkg]
version = "2021.05.12"
packages = ["fmt"]
[find-package]
fmt = {}
[target.example]
type = "executable"
sources = ["src/main.cpp"]
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`.
<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>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

+17
View File
@@ -0,0 +1,17 @@
---
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.
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+46
View File
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 508 508" style="enable-background:new 0 0 508 508;" xml:space="preserve">
<circle style="fill:#90DFAA;" cx="254" cy="254" r="254"/>
<rect x="185.183" y="201.014" transform="matrix(-0.6939 -0.7201 0.7201 -0.6939 234.8233 525.8541)" style="fill:#2B3B4E;" width="88.002" height="24"/>
<g>
<path style="fill:#324A5E;" d="M121.6,194.4c-8.8-16.4-2.8-40,14-56.4c50.8-50.4,108.8-52.4,136.8-49.6c4,0.4,3.6,6.4-0.8,8
c-11.6,4-21.2,8.8-29.6,14c-25.2,15.2-34,47.6-17.6,64.8l2.8,2.8c1.2,1.2,0.8,3.2-0.8,4.8l-26,25.2c-1.2,1.2-3.2,1.6-4.4,0.8
c-8.8-7.2-22-8.4-35.2-4C138.8,212.4,127.2,205.2,121.6,194.4z"/>
<path style="fill:#324A5E;" d="M144,228l-18,17.2c-4.8,4.8-12.4,4.4-17.2-0.4l-29.2-30c-4.8-4.8-4.4-12.4,0.4-17.2l18-17.2
c4.8-4.8,12.4-4.4,17.2,0.4l29.2,30C149.2,216,148.8,223.6,144,228z"/>
</g>
<path style="fill:#FFFFFF;" d="M249.6,240.8l7.2-6.8c5.2-4.8,13.6-4,20,1.6L402,353.2c6.8,6.4,7.6,16,2.4,21.2l-19.6,18.8
c-5.6,5.2-15.2,4-21.2-3.2L250.4,260.8C244.8,254.4,244.4,245.6,249.6,240.8z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+23
View File
@@ -0,0 +1,23 @@
---
layout: home
title: Index
nav_order: 0
---
# Index
`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` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example:
```toml
[project]
name = "cmkr_for_beginners"
description = "A minimal cmkr project."
[target.hello_world]
type = "executable"
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.
View File
+2
View File
@@ -0,0 +1,2 @@
bundle exec just-the-docs rake search:init
bundle exec jekyll serve --livereload
+2
View File
@@ -0,0 +1,2 @@
bundle install
bundle exec jekyll serve --force_polling --livereload --incremental
-8
View File
@@ -1,6 +1,5 @@
#pragma once
#ifdef __cplusplus
namespace cmkr {
namespace args {
@@ -9,11 +8,4 @@ const char *handle_args(int argc, char **argv);
} // namespace args
} // namespace cmkr
extern "C" {
#endif
const char *cmkr_args_handle_args(int, char **);
#ifdef __cplusplus
}
#endif
+2 -10
View File
@@ -1,7 +1,5 @@
#pragma once
#ifdef __cplusplus
namespace cmkr {
namespace build {
@@ -13,15 +11,9 @@ int install();
} // namespace build
} // namespace cmkr
extern "C" {
#endif
int cmkr_build_run(int argc, char **argv);
int cmkr_build_clean(void);
int cmkr_build_clean();
int cmkr_build_install(void);
#ifdef __cplusplus
}
#endif
int cmkr_build_install();
@@ -1,6 +1,5 @@
#pragma once
#ifdef __cplusplus
namespace cmkr {
namespace gen {
@@ -11,13 +10,6 @@ int generate_cmake(const char *path, bool root = true);
} // namespace gen
} // namespace cmkr
extern "C" {
#endif
int cmkr_gen_generate_project(const char *typ);
int cmkr_gen_generate_cmake(const char *path);
#ifdef __cplusplus
}
#endif
-8
View File
@@ -1,6 +1,5 @@
#pragma once
#ifdef __cplusplus
namespace cmkr {
namespace error {
@@ -25,11 +24,4 @@ struct Status {
} // namespace error
} // namespace cmkr
extern "C" {
#endif
const char *cmkr_error_status_string(int);
#ifdef __cplusplus
}
#endif
-8
View File
@@ -1,6 +1,5 @@
#pragma once
#ifdef __cplusplus
namespace cmkr {
namespace help {
@@ -11,13 +10,6 @@ const char *message() noexcept;
} // namespace help
} // namespace cmkr
extern "C" {
#endif
const char *cmkr_help_version(void);
const char *cmkr_help_message(void);
#ifdef __cplusplus
}
#endif
+1 -2
View File
@@ -30,8 +30,7 @@ version = "0.1.0"
# [options]
[[target]]
name = "%s"
[target.%s]
type = "%s"
sources = ["src/*.cpp"]
include-directories = ["include"]
@@ -8,7 +8,7 @@
#include <vector>
namespace cmkr {
namespace cmake {
namespace parser {
struct Setting {
std::string name;
@@ -34,6 +34,7 @@ struct Package {
struct Vcpkg {
std::string version;
std::string url;
std::vector<std::string> packages;
};
@@ -55,19 +56,37 @@ struct Target {
std::string name;
TargetType type = {};
// https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html#project-commands
ConditionVector compile_definitions;
ConditionVector compile_features;
ConditionVector compile_options;
ConditionVector include_directories;
ConditionVector link_directories;
ConditionVector link_libraries;
ConditionVector link_options;
ConditionVector precompile_headers;
ConditionVector headers;
ConditionVector sources;
// https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html#project-commands
ConditionVector compile_definitions;
ConditionVector private_compile_definitions;
ConditionVector compile_features;
ConditionVector private_compile_features;
ConditionVector compile_options;
ConditionVector private_compile_options;
ConditionVector include_directories;
ConditionVector private_include_directories;
ConditionVector link_directories;
ConditionVector private_link_directories;
ConditionVector link_libraries;
ConditionVector private_link_libraries;
ConditionVector link_options;
ConditionVector private_link_options;
ConditionVector precompile_headers;
ConditionVector private_precompile_headers;
std::string condition;
std::string alias;
tsl::ordered_map<std::string, std::string> properties;
Condition<tsl::ordered_map<std::string, std::string>> properties;
Condition<std::string> cmake_before;
Condition<std::string> cmake_after;
@@ -91,14 +110,23 @@ struct Install {
std::string destination;
};
struct CMake {
struct Subdir {
std::string name;
std::string condition;
Condition<std::string> cmake_before;
Condition<std::string> cmake_after;
ConditionVector include_before;
ConditionVector include_after;
};
struct Project {
// This is the CMake version required to use all cmkr versions.
std::string cmake_version = "3.15";
std::string cmkr_include = "cmkr.cmake";
std::string build_dir = "build";
std::string generator;
std::string config;
std::vector<std::string> subdirs;
Condition<std::vector<std::string>> project_subdirs;
std::vector<std::string> cppflags;
std::vector<std::string> cflags;
std::vector<std::string> linkflags;
@@ -121,9 +149,12 @@ struct CMake {
std::vector<Test> tests;
std::vector<Install> installs;
tsl::ordered_map<std::string, std::string> conditions;
std::vector<Subdir> subdirs;
CMake(const std::string &path, bool build);
Project(const std::string &path, bool build);
};
} // namespace cmake
bool is_root_path(const std::string &path);
} // namespace parser
} // namespace cmkr
+4 -4
View File
@@ -1,7 +1,7 @@
#include "args.h"
#include "build.h"
#include "gen.h"
#include "help.h"
#include "arguments.hpp"
#include "build.hpp"
#include "cmake_generator.hpp"
#include "help.hpp"
#include "fs.hpp"
#include <exception>
+22 -22
View File
@@ -1,7 +1,7 @@
#include "build.h"
#include "cmake.hpp"
#include "error.h"
#include "gen.h"
#include "build.hpp"
#include "project_parser.hpp"
#include "error.hpp"
#include "cmake_generator.hpp"
#include "fs.hpp"
#include <sstream>
@@ -14,10 +14,10 @@ namespace cmkr {
namespace build {
int run(int argc, char **argv) {
cmake::CMake cmake(".", true);
parser::Project project(".", true);
if (argc > 2) {
for (size_t i = 2; i < argc; ++i) {
cmake.build_args.push_back(argv[i]);
for (int i = 2; i < argc; ++i) {
project.build_args.push_back(argv[i]);
}
}
std::stringstream ss;
@@ -25,22 +25,22 @@ int run(int argc, char **argv) {
if (gen::generate_cmake(fs::current_path().string().c_str()))
throw std::runtime_error("CMake generation failure!");
ss << "cmake -S. -B" << cmake.build_dir << " ";
ss << "cmake -S. -B" << project.build_dir << " ";
if (!cmake.generator.empty()) {
ss << "-G \"" << cmake.generator << "\" ";
if (!project.generator.empty()) {
ss << "-G \"" << project.generator << "\" ";
}
if (!cmake.config.empty()) {
ss << "-DCMAKE_BUILD_TYPE=" << cmake.config << " ";
if (!project.config.empty()) {
ss << "-DCMAKE_BUILD_TYPE=" << project.config << " ";
}
if (!cmake.gen_args.empty()) {
for (const auto &arg : cmake.gen_args) {
if (!project.gen_args.empty()) {
for (const auto &arg : project.gen_args) {
ss << "-D" << arg << " ";
}
}
ss << "&& cmake --build " << cmake.build_dir << " --parallel";
ss << "&& cmake --build " << project.build_dir << " --parallel";
if (argc > 2) {
for (const auto &arg : cmake.build_args) {
for (const auto &arg : project.build_args) {
ss << " " << arg;
}
}
@@ -50,17 +50,17 @@ int run(int argc, char **argv) {
int clean() {
bool ret = false;
cmake::CMake cmake(".", true);
if (fs::exists(cmake.build_dir)) {
ret = fs::remove_all(cmake.build_dir);
fs::create_directory(cmake.build_dir);
parser::Project project(".", true);
if (fs::exists(project.build_dir)) {
ret = fs::remove_all(project.build_dir);
fs::create_directory(project.build_dir);
}
return !ret;
}
int install() {
cmake::CMake cmake(".", false);
auto cmd = "cmake --install " + cmake.build_dir;
parser::Project project(".", false);
auto cmd = "cmake --install " + project.build_dir;
return ::system(cmd.c_str());
}
} // namespace build
+265 -101
View File
@@ -1,14 +1,17 @@
#include "gen.h"
#include "cmake.hpp"
#include "error.h"
#include "literals.h"
#include "cmake_generator.hpp"
#include "error.hpp"
#include "literals.hpp"
#include "project_parser.hpp"
#include "fs.hpp"
#include <cassert>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <new>
#include <nlohmann/json.hpp>
#include <regex>
#include <sstream>
#include <stdexcept>
#include <string>
@@ -155,12 +158,14 @@ struct Command {
bool first_arg = true;
bool had_newline = false;
bool generated = false;
std::string post_comment;
Command(std::stringstream &ss, int depth, const std::string &command) : ss(ss), depth(depth), command(command) {}
Command(std::stringstream &ss, int depth, std::string command, std::string post_comment)
: ss(ss), depth(depth), command(std::move(command)), post_comment(std::move(post_comment)) {}
~Command() {
if (!generated) {
assert(false && "Incorrect usage of cmd()");
assert(false && "Incorrect usage of cmd(), you probably forgot ()");
}
}
@@ -300,7 +305,11 @@ struct Command {
(void)std::initializer_list<bool>{print_arg(values)...};
if (had_newline)
ss << '\n' << indent(depth);
ss << ")\n";
ss << ")";
if (!post_comment.empty()) {
ss << " # " << post_comment;
}
ss << "\n";
return CommandEndl(ss);
}
};
@@ -316,25 +325,25 @@ static std::string tolf(const std::string &str) {
};
struct Generator {
Generator(cmake::CMake &cmake) : cmake(cmake) {}
Generator(parser::Project &project) : project(project) {}
Generator(const Generator &) = delete;
cmake::CMake &cmake;
parser::Project &project;
std::stringstream ss;
int indent = 0;
Command cmd(const std::string &command) {
Command cmd(const std::string &command, const std::string &post_comment = "") {
if (command.empty())
throw std::invalid_argument("command cannot be empty");
if (command == "if") {
indent++;
return Command(ss, indent - 1, command);
return Command(ss, indent - 1, command, post_comment);
} else if (command == "else" || command == "elseif") {
return Command(ss, indent - 1, command);
return Command(ss, indent - 1, command, post_comment);
} else if (command == "endif") {
indent--;
}
return Command(ss, indent, command);
return Command(ss, indent, command, post_comment);
}
CommandEndl comment(const std::string &comment) {
@@ -378,19 +387,21 @@ struct Generator {
}
template <typename T, typename Lambda>
void handle_condition(const cmake::Condition<T> &value, const Lambda &fn) {
void handle_condition(const parser::Condition<T> &value, const Lambda &fn) {
if (!value.empty()) {
for (const auto &itr : value) {
const auto &condition = itr.first;
if (!condition.empty()) {
if (cmake.conditions.count(condition) == 0) {
if (project.conditions.count(condition) == 0) {
// TODO: somehow print line number information here?
throw std::runtime_error("Unknown condition '" + condition + "'");
}
cmd("if")(RawArg(cmake.conditions[condition]));
cmd("if", condition)(RawArg(project.conditions[condition]));
}
fn(condition, itr.second);
if (!itr.second.empty()) {
fn(condition, itr.second);
}
if (!condition.empty()) {
cmd("endif")();
@@ -401,28 +412,54 @@ struct Generator {
}
};
static std::string vcpkg_escape_identifier(const std::string &name) {
// Do a reasonable effort to escape the project name for use with vcpkg
std::string escaped;
for (char ch : name) {
if ((ch & 0x80) != 0) {
throw std::runtime_error("Non-ASCII characters are not allowed in [project].name when using [vcpkg]");
}
if (ch == '_' || ch == ' ') {
ch = '-';
}
escaped += std::tolower(ch);
}
const std::regex reserved("prn|aux|nul|con|lpt[1-9]|com[1-9]|core|default");
const std::regex ok("[a-z0-9]+(-[a-z0-9]+)*");
std::cmatch m;
if (!std::regex_match(escaped.c_str(), m, reserved) && std::regex_match(escaped.c_str(), m, ok)) {
return escaped;
} else {
throw std::runtime_error("The escaped project name '" + escaped + "' is not usable with [vcpkg]");
}
}
int generate_cmake(const char *path, bool root) {
if (!fs::exists(fs::path(path) / "cmake.toml")) {
throw std::runtime_error("No cmake.toml found!");
}
cmake::CMake cmake(path, false);
Generator gen(cmake);
parser::Project project(path, false);
Generator gen(project);
// Helper lambdas for more convenient CMake generation
auto &ss = gen.ss;
auto cmd = [&gen](const std::string &comment) { return gen.cmd(comment); };
auto cmd = [&gen](const std::string &command) { return gen.cmd(command); };
auto comment = [&gen](const std::string &comment) { return gen.comment(comment); };
auto endl = [&gen]() { gen.endl(); };
auto inject_includes = [&gen](const std::vector<std::string> &includes) { gen.inject_includes(includes); };
auto inject_cmake = [&gen](const std::string &cmake) { gen.inject_cmake(cmake); };
std::string cmkr_url = "https://github.com/build-cpp/cmkr";
comment("This file is automatically generated from cmake.toml - DO NOT EDIT");
comment("See https://github.com/MoAlyousef/cmkr for more information");
comment("See " + cmkr_url + " for more information");
endl();
if (root) {
cmd("cmake_minimum_required")("VERSION", cmake.cmake_version).endl();
cmd("cmake_minimum_required")("VERSION", project.cmake_version).endl();
comment("Regenerate CMakeLists.txt automatically in the root project");
cmd("set")("CMKR_ROOT_PROJECT", "OFF");
@@ -431,7 +468,7 @@ int generate_cmake(const char *path, bool root) {
cmd("set")("CMKR_ROOT_PROJECT", "ON").endl();
comment("Bootstrap cmkr");
cmd("include")(cmake.cmkr_include, "OPTIONAL", "RESULT_VARIABLE", "CMKR_INCLUDE_RESULT");
cmd("include")(project.cmkr_include, "OPTIONAL", "RESULT_VARIABLE", "CMKR_INCLUDE_RESULT");
cmd("if")("CMKR_INCLUDE_RESULT");
cmd("cmkr")();
cmd("endif")().endl();
@@ -450,48 +487,48 @@ int generate_cmake(const char *path, bool root) {
// clang-format on
// TODO: remove support and replace with global compile-features
if (!cmake.cppflags.empty()) {
if (!project.cppflags.empty()) {
ss << "set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} \"";
for (const auto &flag : cmake.cppflags) {
for (const auto &flag : project.cppflags) {
ss << flag << " ";
}
ss << "\")\n\n";
}
// TODO: remove support and replace with global compile-features
if (!cmake.cflags.empty()) {
if (!project.cflags.empty()) {
ss << "set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} \"";
for (const auto &flag : cmake.cflags) {
for (const auto &flag : project.cflags) {
ss << flag << " ";
}
ss << "\")\n\n";
}
// TODO: remove support and replace with global linker-flags
if (!cmake.linkflags.empty()) {
if (!project.linkflags.empty()) {
ss << "set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} \"";
for (const auto &flag : cmake.linkflags) {
for (const auto &flag : project.linkflags) {
ss << flag << " ";
}
ss << "\")\n\n";
}
gen.handle_condition(cmake.include_before, [&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(cmake.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.handle_condition(project.include_before, [&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(project.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
if (!cmake.project_name.empty()) {
auto languages = std::make_pair("LANGUAGES", cmake.project_languages);
auto version = std::make_pair("VERSION", cmake.project_version);
auto description = std::make_pair("DESCRIPTION", cmake.project_description);
cmd("project")(cmake.project_name, languages, version, description).endl();
if (!project.project_name.empty()) {
auto languages = std::make_pair("LANGUAGES", project.project_languages);
auto version = std::make_pair("VERSION", project.project_version);
auto description = std::make_pair("DESCRIPTION", project.project_description);
cmd("project")(project.project_name, languages, version, description).endl();
}
gen.handle_condition(cmake.include_after, [&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(cmake.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
gen.handle_condition(project.include_after, [&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(project.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
if (!cmake.contents.empty()) {
if (!project.contents.empty()) {
cmd("include")("FetchContent").endl();
for (const auto &dep : cmake.contents) {
for (const auto &dep : project.contents) {
cmd("message")("STATUS", "Fetching " + dep.first + "...");
ss << "FetchContent_Declare(\n\t" << dep.first << "\n";
for (const auto &arg : dep.second) {
@@ -518,20 +555,51 @@ int generate_cmake(const char *path, bool root) {
}
}
if (!cmake.vcpkg.version.empty()) {
assert("pmm is required in fetch-content for vcpkg to work" && cmake.contents.count("pmm") != 0);
comment("Bootstrap vcpkg");
cmd("include")("${pmm_SOURCE_DIR}/pmm.cmake");
tsl::ordered_map<std::string, std::vector<std::string>> vcpkg_args;
vcpkg_args["REVISION"] = {cmake.vcpkg.version};
vcpkg_args["REQUIRES"] = cmake.vcpkg.packages;
auto vcpkg = std::make_pair("VCPKG", vcpkg_args);
cmd("pmm")(vcpkg).endl();
if (!project.vcpkg.packages.empty()) {
// Allow the user to specify a url or derive it from the version
auto url = project.vcpkg.url;
if (url.empty()) {
if (project.vcpkg.version.empty()) {
throw std::runtime_error("You need either [vcpkg].version or [vcpkg].url");
}
url = "https://github.com/microsoft/vcpkg/archive/refs/tags/" + project.vcpkg.version + ".tar.gz";
}
// CMake to bootstrap vcpkg and download the packages
// clang-format off
cmd("if")("CMKR_ROOT_PROJECT", "AND", "NOT", "CMKR_DISABLE_VCPKG");
cmd("include")("FetchContent");
cmd("message")("STATUS", "Fetching vcpkg...");
cmd("FetchContent_Declare")("vcpkg", "URL", url);
cmd("FetchContent_MakeAvailable")("vcpkg");
cmd("include")("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake");
cmd("endif")();
endl();
// clang-format on
// Generate vcpkg.json
using namespace nlohmann;
json j;
j["$cmkr"] = "This file is automatically generated from cmake.toml - DO NOT EDIT";
j["$cmkr-url"] = cmkr_url;
j["$schema"] = "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json";
j["name"] = vcpkg_escape_identifier(project.project_name);
j["version-string"] = project.project_version;
j["dependencies"] = project.vcpkg.packages;
if (!project.project_description.empty()) {
j["description"] = project.project_description;
}
std::ofstream ofs("vcpkg.json");
if (!ofs) {
throw std::runtime_error("Failed to create a vcpkg.json manifest file!");
}
ofs << std::setw(2) << j << std::endl;
}
if (!cmake.packages.empty()) {
if (!project.packages.empty()) {
comment("Packages");
for (const auto &dep : cmake.packages) {
for (const auto &dep : project.packages) {
auto version = dep.version;
if (version == "*")
version.clear();
@@ -542,17 +610,17 @@ int generate_cmake(const char *path, bool root) {
}
}
if (!cmake.options.empty()) {
if (!project.options.empty()) {
comment("Options");
for (const auto &opt : cmake.options) {
for (const auto &opt : project.options) {
cmd("option")(opt.name, opt.comment, opt.val ? "ON" : "OFF");
}
endl();
}
if (!cmake.settings.empty()) {
if (!project.settings.empty()) {
comment("Settings");
for (const auto &set : cmake.settings) {
for (const auto &set : project.settings) {
std::string set_val;
if (set.val.index() == 1) {
set_val = mpark::get<1>(set.val);
@@ -571,27 +639,67 @@ int generate_cmake(const char *path, bool root) {
endl();
}
auto add_subdir = [&](const std::string &dir) {
// clang-format off
comment(dir);
cmd("set")("CMKR_CMAKE_FOLDER", "${CMAKE_FOLDER}");
cmd("if")("CMAKE_FOLDER");
cmd("set")("CMAKE_FOLDER", "${CMAKE_FOLDER}/" + dir);
cmd("else")();
cmd("set")("CMAKE_FOLDER", dir);
cmd("endif")();
// clang-format on
cmd("add_subdirectory")(dir);
cmd("set")("CMAKE_FOLDER", "${CMKR_CMAKE_FOLDER}").endl();
};
// generate_cmake is called on the subdirectories recursively later
if (!cmake.subdirs.empty()) {
for (const auto &dir : cmake.subdirs) {
// clang-format off
comment(dir);
cmd("set")("CMKR_CMAKE_FOLDER", "${CMAKE_FOLDER}");
cmd("if")("CMAKE_FOLDER");
cmd("set")("CMAKE_FOLDER", "${CMAKE_FOLDER}/" + dir);
cmd("else")();
cmd("set")("CMAKE_FOLDER", dir);
cmd("endif")();
// clang-format on
cmd("add_subdirectory")(dir);
cmd("set")("CMAKE_FOLDER", "${CMKR_CMAKE_FOLDER}").endl();
}
if (!project.project_subdirs.empty()) {
gen.handle_condition(project.project_subdirs, [&](const std::string &, const std::vector<std::string> &subdirs) {
for (const auto &dir : subdirs) {
add_subdir(dir);
}
});
endl();
}
for (const auto &subdir : project.subdirs) {
if (!subdir.condition.empty()) {
const auto &condition = subdir.condition;
if (project.conditions.count(condition) == 0) {
throw std::runtime_error("Unknown condition '" + condition + "' for [subdir." + subdir.name + "]");
}
gen.cmd("if", condition)(RawArg(project.conditions[condition]));
}
if (!cmake.targets.empty()) {
for (const auto &target : cmake.targets) {
gen.handle_condition(subdir.include_before,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(subdir.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
add_subdir(subdir.name);
gen.handle_condition(subdir.include_after, [&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(subdir.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
if (!subdir.condition.empty()) {
cmd("endif")();
}
}
if (!project.targets.empty()) {
for (const auto &target : project.targets) {
comment("Target " + target.name);
if (!target.condition.empty()) {
const auto &condition = target.condition;
if (project.conditions.count(condition) == 0) {
throw std::runtime_error("Unknown condition '" + condition + "' for [target." + target.name + "]");
}
gen.cmd("if", condition)(RawArg(project.conditions[condition]));
}
cmd("set")("CMKR_TARGET", target.name);
gen.handle_condition(target.include_before,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(target.cmake_before, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
@@ -599,7 +707,7 @@ int generate_cmake(const char *path, bool root) {
auto sources_var = target.name + "_SOURCES";
bool added_toml = false;
cmd("unset")(sources_var).endl();
cmd("set")(sources_var, RawArg("\"\"")).endl();
gen.handle_condition(target.sources, [&](const std::string &condition, const std::vector<std::string> &condition_sources) {
auto sources = expand_cmake_paths(condition_sources, path);
if (sources.empty()) {
@@ -613,40 +721,41 @@ int generate_cmake(const char *path, bool root) {
cmd("list")("APPEND", sources_var, sources);
});
if (!added_toml && target.type != cmake::target_interface) {
if (!added_toml && target.type != parser::target_interface) {
cmd("list")("APPEND", sources_var, std::vector<std::string>{"cmake.toml"}).endl();
}
cmd("set")("CMKR_SOURCES", "${" + sources_var + "}");
std::string add_command;
std::string target_type;
std::string target_scope;
switch (target.type) {
case cmake::target_executable:
case parser::target_executable:
add_command = "add_executable";
target_type = "";
target_scope = "PRIVATE";
break;
case cmake::target_library:
case parser::target_library:
add_command = "add_library";
target_type = "";
target_scope = "PUBLIC";
break;
case cmake::target_shared:
case parser::target_shared:
add_command = "add_library";
target_type = "SHARED";
target_scope = "PUBLIC";
break;
case cmake::target_static:
case parser::target_static:
add_command = "add_library";
target_type = "STATIC";
target_scope = "PUBLIC";
break;
case cmake::target_interface:
case parser::target_interface:
add_command = "add_library";
target_type = "INTERFACE";
target_scope = "INTERFACE";
break;
case cmake::target_custom:
case parser::target_custom:
// TODO: add proper support, this is hacky
add_command = "add_custom_target";
target_type = "SOURCES";
@@ -656,10 +765,16 @@ int generate_cmake(const char *path, bool root) {
assert("Unimplemented enum value" && false);
}
cmd(add_command)(target.name, target_type, "${" + target.name + "_SOURCES}").endl();
cmd(add_command)(target.name, target_type).endl();
// clang-format off
cmd("if")(sources_var);
cmd("target_sources")(target.name, target.type == parser::target_interface ? "INTERFACE" : "PRIVATE", "${" + sources_var + "}");
cmd("endif")().endl();
// clang-format on
// The first executable target will become the Visual Studio startup project
if (target.type == cmake::target_executable) {
if (target.type == parser::target_executable) {
cmd("get_directory_property")("CMKR_VS_STARTUP_PROJECT", "DIRECTORY", "${PROJECT_SOURCE_DIR}", "DEFINITION", "VS_STARTUP_PROJECT");
// clang-format off
cmd("if")("NOT", "CMKR_VS_STARTUP_PROJECT");
@@ -669,50 +784,81 @@ int generate_cmake(const char *path, bool root) {
}
if (!target.sources.empty()) {
cmd("source_group")("TREE", "${CMAKE_CURRENT_SOURCE_DIR}", "FILES", "${" + target.name + "_SOURCES}").endl();
cmd("source_group")("TREE", "${CMAKE_CURRENT_SOURCE_DIR}", "FILES", "${" + sources_var + "}").endl();
}
if (!target.alias.empty()) {
cmd("add_library")(target.alias, "ALIAS", target.name);
}
auto target_cmd = [&](const char *command, const cmake::ConditionVector &cargs) {
gen.handle_condition(
cargs, [&](const std::string &, const std::vector<std::string> &args) { cmd(command)(target.name, target_scope, args); });
auto target_cmd = [&](const char *command, const parser::ConditionVector &cargs, const std::string &scope) {
gen.handle_condition(cargs,
[&](const std::string &, const std::vector<std::string> &args) { cmd(command)(target.name, scope, args); });
};
target_cmd("target_compile_definitions", target.compile_definitions);
target_cmd("target_compile_features", target.compile_features);
target_cmd("target_compile_options", target.compile_options);
target_cmd("target_include_directories", target.include_directories);
target_cmd("target_link_directories", target.link_directories);
target_cmd("target_link_libraries", target.link_libraries);
target_cmd("target_precompile_headers", target.precompile_headers);
target_cmd("target_compile_definitions", target.compile_definitions, target_scope);
target_cmd("target_compile_definitions", target.private_compile_definitions, "PRIVATE");
target_cmd("target_compile_features", target.compile_features, target_scope);
target_cmd("target_compile_features", target.private_compile_features, "PRIVATE");
target_cmd("target_compile_options", target.compile_options, target_scope);
target_cmd("target_compile_options", target.private_compile_options, "PRIVATE");
target_cmd("target_include_directories", target.include_directories, target_scope);
target_cmd("target_include_directories", target.private_include_directories, "PRIVATE");
target_cmd("target_link_directories", target.link_directories, target_scope);
target_cmd("target_link_directories", target.private_link_directories, "PRIVATE");
target_cmd("target_link_libraries", target.link_libraries, target_scope);
target_cmd("target_link_libraries", target.private_link_libraries, "PRIVATE");
target_cmd("target_link_options", target.link_options, target_scope);
target_cmd("target_link_options", target.private_link_options, "PRIVATE");
target_cmd("target_precompile_headers", target.precompile_headers, target_scope);
target_cmd("target_precompile_headers", target.private_precompile_headers, "PRIVATE");
if (!target.properties.empty()) {
cmd("set_target_properties")(target.name, "PROPERTIES", target.properties).endl();
gen.handle_condition(target.properties, [&](const std::string &, const tsl::ordered_map<std::string, std::string> &properties) {
cmd("set_target_properties")(target.name, "PROPERTIES", properties);
});
}
gen.handle_condition(target.include_after,
[&](const std::string &, const std::vector<std::string> &includes) { inject_includes(includes); });
gen.handle_condition(target.cmake_after, [&](const std::string &, const std::string &cmake) { inject_cmake(cmake); });
cmd("unset")("CMKR_TARGET");
cmd("unset")("CMKR_SOURCES");
if (!target.condition.empty()) {
cmd("endif")();
}
endl();
}
}
if (!cmake.tests.empty()) {
if (!project.tests.empty()) {
cmd("enable_testing")().endl();
for (const auto &test : cmake.tests) {
for (const auto &test : project.tests) {
auto name = std::make_pair("NAME", test.name);
auto configurations = std::make_pair("CONFIGURATIONS", test.configurations);
auto working_directory = std::make_pair("WORKING_DIRECTORY", test.working_directory);
auto dir = test.working_directory;
if (fs::is_directory(fs::path(path) / dir)) {
dir = "${CMAKE_CURRENT_LIST_DIR}/" + dir;
}
auto working_directory = std::make_pair("WORKING_DIRECTORY", dir);
auto command = std::make_pair("COMMAND", test.command);
auto arguments = std::make_pair("", test.arguments);
cmd("add_test")(name, configurations, working_directory, command, arguments).endl();
}
}
if (!cmake.installs.empty()) {
for (const auto &inst : cmake.installs) {
if (!project.installs.empty()) {
for (const auto &inst : project.installs) {
auto targets = std::make_pair("TARGETS", inst.targets);
auto dirs = std::make_pair("DIRS", inst.dirs);
std::vector<std::string> files_data;
@@ -755,10 +901,28 @@ int generate_cmake(const char *path, bool root) {
}
}
for (const auto &sub : cmake.subdirs) {
auto subpath = fs::path(path) / fs::path(sub);
if (fs::exists(subpath / "cmake.toml"))
auto generate_subdir = [path](const fs::path &sub) {
// Skip generating for subdirectories that have a cmake.toml with a [project] in it
fs::path subpath;
for (const auto &p : sub) {
subpath /= p;
if (parser::is_root_path((path / subpath).string())) {
return;
}
}
subpath = path / sub;
if (fs::exists(subpath / "cmake.toml")) {
generate_cmake(subpath.string().c_str(), false);
}
};
for (const auto &itr : project.project_subdirs) {
for (const auto &sub : itr.second) {
generate_subdir(sub);
}
}
for (const auto &subdir : project.subdirs) {
generate_subdir(subdir.name);
}
return 0;
+1 -1
View File
@@ -1,4 +1,4 @@
#include "error.h"
#include "error.hpp"
#include <assert.h>
+1 -1
View File
@@ -1,4 +1,4 @@
#include "help.h"
#include "help.hpp"
namespace cmkr {
namespace help {
+1 -1
View File
@@ -1,4 +1,4 @@
#include "args.h"
#include "arguments.hpp"
#include <cstdio>
#include <cstdlib>
@@ -1,4 +1,4 @@
#include "cmake.hpp"
#include "project_parser.hpp"
#include "enum_helper.hpp"
#include "fs.hpp"
@@ -7,10 +7,10 @@
#include <tsl/ordered_map.h>
template <>
const char *enumStrings<cmkr::cmake::TargetType>::data[] = {"executable", "library", "shared", "static", "interface", "custom"};
const char *enumStrings<cmkr::parser::TargetType>::data[] = {"executable", "library", "shared", "static", "interface", "custom"};
namespace cmkr {
namespace cmake {
namespace parser {
using TomlBasicValue = toml::basic_value<toml::preserve_comments, tsl::ordered_map, std::vector>;
@@ -55,16 +55,18 @@ static void get_optional(const TomlBasicValue &v, const toml::key &ky, Condition
template <typename T>
static void get_optional(const TomlBasicValue &v, const toml::key &ky, T &destination) {
// TODO: this currently doesn't allow you to get an optional map<string, X>
if (v.contains(ky)) {
destination = toml::find<T>(v, ky);
}
}
CMake::CMake(const std::string &path, bool build) {
if (!fs::exists(fs::path(path) / "cmake.toml")) {
Project::Project(const std::string &path, bool build) {
const auto toml_path = fs::path(path) / "cmake.toml";
if (!fs::exists(toml_path)) {
throw std::runtime_error("No cmake.toml was found!");
}
const auto toml = toml::parse<toml::preserve_comments, tsl::ordered_map, std::vector>((fs::path(path) / "cmake.toml").string());
const auto toml = toml::parse<toml::preserve_comments, tsl::ordered_map, std::vector>(toml_path.string());
if (build) {
if (toml.contains("cmake")) {
const auto &cmake = toml::find(toml, "cmake");
@@ -98,7 +100,21 @@ CMake::CMake(const std::string &path, bool build) {
get_optional(project, "cmake-after", cmake_after);
get_optional(project, "include-before", include_before);
get_optional(project, "include-after", include_after);
get_optional(project, "subdirs", subdirs);
get_optional(project, "subdirs", project_subdirs);
}
if (toml.contains("subdir")) {
const auto &subs = toml::find(toml, "subdir").as_table();
for (const auto &sub : subs) {
Subdir subdir;
subdir.name = sub.first;
get_optional(sub.second, "condition", subdir.condition);
get_optional(sub.second, "cmake-before", subdir.cmake_before);
get_optional(sub.second, "cmake-after", subdir.cmake_after);
get_optional(sub.second, "include-before", subdir.include_before);
get_optional(sub.second, "include-after", subdir.include_after);
subdirs.push_back(subdir);
}
}
if (toml.contains("settings")) {
@@ -163,7 +179,9 @@ CMake::CMake(const std::string &path, bool build) {
}
// TODO: refactor to std::vector<Content> instead of this hacky thing?
get_optional(toml, "fetch-content", contents);
if (toml.contains("fetch-content")) {
contents = toml::find<decltype(contents)>(toml, "fetch-content");
}
if (toml.contains("bin")) {
throw std::runtime_error("[[bin]] has been renamed to [[target]]");
@@ -178,34 +196,75 @@ CMake::CMake(const std::string &path, bool build) {
target.name = itr.first;
target.type = to_enum<TargetType>(toml::find(t, "type").as_string(), "target type");
get_optional(t, "headers", target.headers);
get_optional(t, "sources", target.sources);
get_optional(t, "compile-definitions", target.compile_definitions);
get_optional(t, "private-compile-definitions", target.private_compile_definitions);
get_optional(t, "compile-features", target.compile_features);
get_optional(t, "private-compile-features", target.private_compile_features);
get_optional(t, "compile-options", target.compile_options);
get_optional(t, "private-compile-options", target.private_compile_options);
get_optional(t, "include-directories", target.include_directories);
get_optional(t, "private-include-directories", target.private_include_directories);
get_optional(t, "link-directories", target.link_directories);
get_optional(t, "private-link-directories", target.private_link_directories);
get_optional(t, "link-libraries", target.link_libraries);
get_optional(t, "private-link-libraries", target.private_link_libraries);
get_optional(t, "link-options", target.link_options);
get_optional(t, "private-link-options", target.private_link_options);
get_optional(t, "precompile-headers", target.precompile_headers);
get_optional(t, "private-precompile-headers", target.private_precompile_headers);
if (!target.headers.empty()) {
auto &sources = target.sources.nth(0).value();
const auto &headers = target.headers.nth(0)->second;
sources.insert(sources.end(), headers.begin(), headers.end());
}
if (t.contains("condition")) {
target.condition = toml::find(t, "condition").as_string();
}
if (t.contains("alias")) {
target.alias = toml::find(t, "alias").as_string();
}
if (t.contains("properties")) {
const auto &props = toml::find(t, "properties").as_table();
for (const auto &propKv : props) {
if (propKv.second.is_array()) {
auto store_property = [&target](const toml::key &k, const TomlBasicValue &v, const std::string &condition) {
if (v.is_array()) {
std::string property_list;
for (const auto &list_val : propKv.second.as_array()) {
for (const auto &list_val : v.as_array()) {
if (!property_list.empty()) {
property_list += ';';
}
property_list += list_val.as_string();
}
target.properties[propKv.first] = property_list;
target.properties[condition][k] = property_list;
} else if (v.is_boolean()) {
target.properties[condition][k] = v.as_boolean() ? "ON" : "OFF";
} else {
target.properties[propKv.first] = propKv.second.as_string();
target.properties[condition][k] = v.as_string();
}
};
const auto &props = toml::find(t, "properties").as_table();
for (const auto &propKv : props) {
const auto &k = propKv.first;
const auto &v = propKv.second;
if (v.is_table()) {
for (const auto &condKv : v.as_table()) {
store_property(condKv.first, condKv.second, k);
}
} else {
store_property(k, v, "");
}
}
}
@@ -247,22 +306,17 @@ CMake::CMake(const std::string &path, bool build) {
if (toml.contains("vcpkg")) {
const auto &v = toml::find(toml, "vcpkg");
vcpkg.version = toml::find(v, "version").as_string();
get_optional(v, "url", vcpkg.url);
get_optional(v, "version", vcpkg.version);
vcpkg.packages = toml::find<decltype(vcpkg.packages)>(v, "packages");
// This allows the user to use a custom pmm version if desired
if (contents.count("pmm") == 0) {
contents["pmm"]["url"] = "https://github.com/vector-of-bool/pmm/archive/refs/tags/1.5.1.tar.gz";
// Hack to not execute pmm's example CMakeLists.txt
contents["pmm"]["SOURCE_SUBDIR"] = "pmm";
}
}
// Reasonable default conditions (you can override these if you desire)
conditions["win32"] = conditions["windows"] = conditions["win"] = "WIN32";
conditions["macos"] = conditions["macosx"] = conditions["osx"] = conditions["mac"] = R"cond("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")cond";
conditions["unix"] = "UNIX";
conditions["linux"] = R"cond("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")cond";
conditions["windows"] = R"cmake(WIN32)cmake";
conditions["macos"] = R"cmake("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")cmake";
conditions["unix"] = R"cmake(UNIX)cmake";
conditions["bsd"] = R"cmake("${CMAKE_SYSTEM_NAME}" MATCHES "BSD")cmake";
conditions["linux"] = conditions["lunix"] = R"cmake("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")cmake";
if (toml.contains("conditions")) {
auto conds = toml::find<decltype(conditions)>(toml, "conditions");
@@ -272,5 +326,15 @@ CMake::CMake(const std::string &path, bool build) {
}
}
}
} // namespace cmake
bool is_root_path(const std::string &path) {
const auto toml_path = fs::path(path) / "cmake.toml";
if (!fs::exists(toml_path)) {
return false;
}
const auto toml = toml::parse<toml::preserve_comments, tsl::ordered_map, std::vector>(toml_path.string());
return toml.contains("project");
}
} // namespace parser
} // namespace cmkr
+31 -1
View File
@@ -1,5 +1,5 @@
# This file is automatically generated from cmake.toml - DO NOT EDIT
# See https://github.com/MoAlyousef/cmkr for more information
# See https://github.com/build-cpp/cmkr for more information
# Create a configure-time dependency on cmake.toml to improve IDE support
if(CMKR_ROOT_PROJECT)
@@ -18,6 +18,26 @@ add_test(
build
)
add_test(
NAME
interface
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/interface"
COMMAND
$<TARGET_FILE:cmkr>
build
)
add_test(
NAME
fetch-content
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/fetch-content"
COMMAND
$<TARGET_FILE:cmkr>
build
)
add_test(
NAME
conditions
@@ -28,3 +48,13 @@ add_test(
build
)
add_test(
NAME
vcpkg
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/vcpkg"
COMMAND
$<TARGET_FILE:cmkr>
build
)
+4 -2
View File
@@ -1,9 +1,11 @@
[cmake]
version = "3.5"
# A minimal `cmake.toml` project:
[project]
name = "basic"
description = "Minimal example"
[target.basic]
type = "executable"
sources = ["src/basic.cpp"]
# Declares an executable target called `basic` with `src/basic.cpp` as a source file. Equivalent to CMake's [add_executable](https://cmake.org/cmake/help/latest/command/add_executable.html)`(basic src/basic.cpp)`.
+20 -2
View File
@@ -1,11 +1,29 @@
[[test]]
name = "basic"
command = "$<TARGET_FILE:cmkr>"
working-directory = "${CMAKE_CURRENT_LIST_DIR}/basic"
working-directory = "basic"
arguments = ["build"]
[[test]]
name = "interface"
command = "$<TARGET_FILE:cmkr>"
working-directory = "interface"
arguments = ["build"]
[[test]]
name = "fetch-content"
command = "$<TARGET_FILE:cmkr>"
working-directory = "fetch-content"
arguments = ["build"]
[[test]]
name = "conditions"
command = "$<TARGET_FILE:cmkr>"
working-directory = "${CMAKE_CURRENT_LIST_DIR}/conditions"
working-directory = "conditions"
arguments = ["build"]
[[test]]
name = "vcpkg"
command = "$<TARGET_FILE:cmkr>"
working-directory = "vcpkg"
arguments = ["build"]
+10 -4
View File
@@ -8,10 +8,16 @@ custom = "CUSTOM"
[target.example]
type = "executable"
sources = ["src/main.cpp"]
win32.sources = ["src/win32.cpp"]
windows.sources = ["src/windows_specific.cpp"]
cmake-after = "message(STATUS cmake-after)"
win32.cmake-after = "message(STATUS win32-after)"
unix.cmake-after = "message(STATUS unix-after)"
windows.cmake-after = "message(STATUS win32-after)"
macos.cmake-after = "message(STATUS macos-after)"
linux.cmake-after = "message(STATUS linux-after)"
unix.cmake-after = "message(STATUS unix-after)"
custom.cmake-after = "message(STATUS custom-after)"
linux.cmake-after = "message(STATUS linux-after)"
[target.example.properties]
AUTOMOC = false
custom.OUTPUT_NAME = "example2"
custom.AUTORCC = true
AUTOGEN = "ON"
+15
View File
@@ -0,0 +1,15 @@
# Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) from [GitHub](https://github.com) and links an `example` target to it:
[project]
name = "fetch-content"
description = "Fetching from git"
[fetch-content]
fmt = { git = "https://github.com/fmtlib/fmt", tag = "7.1.3" }
[target.example]
type = "executable"
sources = ["src/main.cpp"]
link-libraries = ["fmt::fmt"]
# This is equivalent to calling CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html).
+6
View File
@@ -0,0 +1,6 @@
#include <fmt/core.h>
int main()
{
fmt::print("Hello, world!\n");
}
+12
View File
@@ -0,0 +1,12 @@
[project]
name = "interface"
description = "Header-only library"
[target.mylib]
type = "interface"
include-directories = ["include"]
[target.example]
type = "executable"
sources = ["src/main.cpp"]
link-libraries = ["mylib"]
+4
View File
@@ -0,0 +1,4 @@
namespace mylib
{
static const char* version() { return "v1.0"; }
} // namespace mylib
+8
View File
@@ -0,0 +1,8 @@
#include <cstdio>
#include "mylib/mylib.hpp"
int main()
{
printf("mylib version: %s\n", mylib::version())
}
+21
View File
@@ -0,0 +1,21 @@
# Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) using [vcpkg](https://vcpkg.io/) and links an `example` target to it:
[project]
name = "vcpkg"
description = "Dependencies from vcpkg"
# See https://github.com/microsoft/vcpkg/releases for vcpkg versions
# See https://vcpkg.io/en/packages.html for available packages
[vcpkg]
version = "2021.05.12"
packages = ["fmt"]
[find-package]
fmt = {}
[target.example]
type = "executable"
sources = ["src/main.cpp"]
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`.
+6
View File
@@ -0,0 +1,6 @@
#include <fmt/core.h>
int main()
{
fmt::print("Hello, world!\n");
}
+11
View File
@@ -0,0 +1,11 @@
{
"$cmkr": "This file is automatically generated from cmake.toml - DO NOT EDIT",
"$cmkr-url": "https://github.com/build-cpp/cmkr",
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
"dependencies": [
"fmt"
],
"description": "Example of using vcpkg",
"name": "vcpkg",
"version-string": ""
}
Generated Vendored
+4
View File
@@ -16,3 +16,7 @@ target_include_directories(toml11 INTERFACE toml11-3.6.0)
# https://github.com/mpark/variant (BSL-1.0)
add_library(mpark_variant INTERFACE)
target_include_directories(mpark_variant INTERFACE variant-1.4.0/include)
# https://github.com/nlohmann/json (MIT)
add_library(nlohmann_json INTERFACE)
target_include_directories(nlohmann_json INTERFACE nlohmann-3.9.1/include)
+21
View File
@@ -0,0 +1,21 @@
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