Compare commits

..

91 Commits

Author SHA1 Message Date
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
Duncan Ogilvie 7cdf36f317 Initial support for conditional arguments 2021-05-02 23:53:12 +02:00
Duncan Ogilvie bf14f069a7 Minor fixes (removed TODOs and rename checks) 2021-05-02 21:51:04 +02:00
Duncan Ogilvie 3b4bc919a1 Merge branch 'bootstrapper-upgrade' 2021-05-02 02:22:46 +02:00
Duncan Ogilvie c0bdbeb9d8 Merge branch 'array-properties' 2021-05-02 02:22:39 +02:00
Duncan Ogilvie 42725d0339 Update the README to be in sync with master 2021-05-02 02:12:24 +02:00
Duncan Ogilvie 8f393d967d Make cmkr bootstrapper more robust 2021-05-01 00:44:29 +02:00
Duncan Ogilvie 1cf9240579 Support an array of properties
[target.example.properties]
SOME_LIST = [
    "item1",
    "item2",
]
2021-04-26 01:01:28 +02:00
Mohammed Alyousef 7b7b260379 Merge pull request #6 from MoAlyousef/develop
Ongoing development
2021-04-20 02:33:29 +03:00
Duncan Ogilvie 747bc8be00 Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	CMakeLists.txt
#	README.md
#	cmake.toml
#	include/literals.h
#	src/cmake.cpp
#	src/cmake.hpp
#	src/gen.cpp
2021-04-19 16:22:08 +02:00
MoAlyousef 00121c261f 0.1.4 2021-04-11 04:52:44 +03:00
Duncan Ogilvie 326647011b Initial attempt at adding tests 2021-04-06 15:02:01 +02:00
Duncan Ogilvie 598c9b9ba8 Sort globbed files alphabetically for consistent cross-OS generation 2021-04-06 14:42:07 +02:00
Duncan Ogilvie d62dff29b1 Implement stronger type checking for optional values 2021-04-06 14:08:31 +02:00
Duncan Ogilvie 783f343e40 Run GitHub Actions on a bigger matrix 2021-04-06 12:52:31 +02:00
Duncan Ogilvie 5312b44860 Fix warnings on AppleClang 12 2021-04-06 12:19:47 +02:00
Duncan Ogilvie 6162e86329 Respect default members while building 2021-04-05 18:54:24 +02:00
67 changed files with 27461 additions and 762 deletions
+1
View File
@@ -0,0 +1 @@
CMakeLists.txt linguist-generated
+50 -8
View File
@@ -2,18 +2,60 @@ name: CMake
on: [push, pull_request]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
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
matrix:
os: [windows-latest, macos-10.15, ubuntu-18.04]
os: [windows-2016, windows-2019, macos-10.15, ubuntu-16.04, ubuntu-18.04, ubuntu-20.04]
env:
BUILD_TYPE: Release
steps:
- uses: actions/checkout@v2
- name: Checkout
uses: actions/checkout@v2
- name: Build
run: cmake -S. -Bbin -DCMAKE_BUILD_TYPE=$BUILD_TYPE && cmake --build bin --parallel --config $BUILD_TYPE
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 }}
+4 -3
View File
@@ -5,6 +5,7 @@ compile_commands.json
temp.*
.vs
.cache
build*/
.idea/
cmake-build*/
build*/
.idea/
cmake-build*/
CMakeLists.txt.user
-22
View File
@@ -1,22 +0,0 @@
# CHANGELOG
## 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.
+72 -45
View File
@@ -1,4 +1,5 @@
# This file was generated automatically by cmkr.
# This file is automatically generated from cmake.toml - DO NOT EDIT
# See https://github.com/build-cpp/cmkr for more information
cmake_minimum_required(VERSION 2.8...3.8)
@@ -22,20 +23,17 @@ 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
VERSION
0.1.3
0.1.4
DESCRIPTION
"CMakeLists generator from TOML"
)
include("cmake/generate_documentation.cmake")
# third_party
set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER})
if(CMAKE_FOLDER)
@@ -46,53 +44,67 @@ endif()
add_subdirectory(third_party)
set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER})
# tests
set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER})
if(CMAKE_FOLDER)
set(CMAKE_FOLDER "${CMAKE_FOLDER}/tests")
else()
set(CMAKE_FOLDER tests)
endif()
add_subdirectory(tests)
set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER})
# Target cmkrlib
set(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"
cmake.toml
)
add_library(cmkrlib STATIC ${cmkrlib_SOURCES})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${cmkrlib_SOURCES})
# Target cmkr_generate_documentation
set(CMKR_TARGET cmkr_generate_documentation)
set(cmkr_generate_documentation_SOURCES "")
target_compile_features(cmkrlib PUBLIC
cxx_std_11
)
set(CMKR_SOURCES ${cmkr_generate_documentation_SOURCES})
add_library(cmkr_generate_documentation INTERFACE)
target_include_directories(cmkrlib PUBLIC
include
)
if(cmkr_generate_documentation_SOURCES)
target_sources(cmkr_generate_documentation INTERFACE ${cmkr_generate_documentation_SOURCES})
endif()
target_link_libraries(cmkrlib PUBLIC
toml11
ghc_filesystem
mpark_variant
ordered_map
)
generate_documentation()
unset(CMKR_TARGET)
unset(CMKR_SOURCES)
# Target cmkr
set(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)
@@ -101,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
)
+20 -126
View File
@@ -1,125 +1,36 @@
# 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).
`cmkr` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example:
## 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:
```toml
[cmake]
minimum = "3.15"
[project]
name = "app"
version = "0.1.0"
name = "cmkr_for_beginners"
description = "A minimal cmkr project."
[[target]]
name = "app"
[target.hello_world]
type = "executable"
sources = ["src/main.cpp"]
```
This project's cmake.toml:
```toml
[cmake]
minimum = "3.15"
`cmkr` can bootstrap itself from CMake and consumers of your project do not need to install anything to work with it.
[project]
name = "cmkr"
version = "0.1.3"
## Getting started
[fetch-content]
toml11 = { git = "https://github.com/ToruNiina/toml11" }
filesystem = { git = "https://github.com/gulrak/filesystem" }
mpark_variant = { url = "https://github.com/mpark/variant/archive/v1.4.0.tar.gz" }
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:
[[target]]
name = "cmkrlib"
type = "static"
sources = ["src/cmake.cpp", "src/gen.cpp", "src/help.cpp", "src/build.cpp", "src/error.cpp"]
include-directories = ["include"]
compile-features = ["cxx_std_11"]
link-libraries = ["toml11::toml11", "ghc_filesystem"]
[[target]]
name = "cmkr"
type = "executable"
sources = ["src/main.cpp", "src/args.cpp"]
link-libraries = ["cmkrlib"]
[[install]]
targets = ["cmkr"]
destination = "${CMAKE_INSTALL_PREFIX}/bin"
```sh
cmake -B build
cmake --build build
```
Currently supported fields:
```toml
[cmake] # required for top-level project
minimum = "3.15" # required
subdirs = [] # optional
build-dir = "build" # optional
cpp-flags = [] # optional
c-flags = [] # optional
link-flags = [] # optional
generator = "Ninja" # optional, only valid when run using: cmkr build
config = "Release" # optional, only valid when run using: cmkr build
arguments = ["CMAKE_TOOLCHAIN_FILE=/path/to/toolchain"] # optional, valid when run using: cmkr 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).
[settings] # optional
CMAKE_BUILD_TYPE = "Release"
TOML_BUILD_TESTS = false # optional
TOML_BUILD_DOCS = { value = false, comment = "builds dependency docs", cache = true, force = true } # optional
OLD_VERSION = "0.1.1" # optional
## Command line
[project] # required per project
name = "app" # required
version = "0.1.0" # required
Optionally you can install `cmkr` in your `PATH` and use it as a utility from the command line:
[find-package] # optional, runs find_package, use "*" to ignore version
Boost = { version = "1.74.0", required = false, components = ["system"] } # optional
spdlog = "*"
[fetch-content] # optional, runs fetchContent
toml11 = { git = "https://github.com/ToruNiina/toml11", tag = "v3.5.0" } # optional
[options] # optional
APP_BUILD_STUFF = false # optional
APP_OTHER_STUFF = { comment = "does other stuff", value = false } # optional
[[target]] # required, can define several binaries
name = "app" # required
type = "executable" # required (executable || library || shared || static || interface)
sources = ["src/*.cpp"] # required, supports globbing
include-directories = ["include"] # optional
alias = "" # optional
compile-features = [] # optional
compile-definitions = [] # optional
link-libraries = [] # optional
properties = { PROPERTY1 = "property1", ... } # optional
[[test]] # optional, can define several
name = "test1" # required
command = "app" # required
arguments = ["arg1", "arg2"] # optional
[[install]] # optional, can define several
targets = ["app"] # optional
files = ["include/*.h"] # optional
dirs = [] # optional
configs = [] # optional (Release|Debug...etc)
destination = "${CMAKE_INSTALL_PREFIX}/bin" # required
```
The cmkr executable can be run from the command-line:
```
Usage: cmkr [arguments]
arguments:
@@ -131,28 +42,11 @@ arguments:
help Show help.
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:
```
cmkr build --config Release
```
## Binary types
## Credits
### 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.
- Support conditional cmake args somehow!
- 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
+13 -16
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.3"
version = "0.1.4"
description = "CMakeLists generator from TOML"
languages = ["CXX"]
subdirs = ["third_party"]
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"
+32 -15
View File
@@ -1,27 +1,44 @@
# This file was generated automatically by cmkr.
# Regenerate CMakeLists.txt file when necessary
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
if(CMKR_INCLUDE_RESULT)
cmkr()
endif()
cmake_minimum_required(VERSION 3.15)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Regenerate CMakeLists.txt automatically in the root project
set(CMKR_ROOT_PROJECT OFF)
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CMKR_ROOT_PROJECT ON)
set(example_PROJECT_VERSION 0.1.0)
project(example VERSION ${example_PROJECT_VERSION})
# Bootstrap cmkr
include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT)
if(CMKR_INCLUDE_RESULT)
cmkr()
endif()
set(EXAMPLE_SOURCES
src/example.cpp
# Enable folder support
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
endif()
# Create a configure-time dependency on cmake.toml to improve IDE support
if(CMKR_ROOT_PROJECT)
configure_file(cmake.toml cmake.toml COPYONLY)
endif()
project(example
VERSION
0.1.0
)
# Target example
set(example_SOURCES
"src/example.cpp"
cmake.toml
)
add_executable(example ${EXAMPLE_SOURCES})
source_group(TREE ${PROJECT_SOURCE_DIR} FILES ${EXAMPLE_SOURCES})
add_executable(example ${example_SOURCES})
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 example)
endif()
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${example_SOURCES})
+2 -3
View File
@@ -1,13 +1,12 @@
# This is a minimal example project used for testing the cmkr bootstrapping process
[cmake]
minimum = "3.15"
version = "3.15"
[project]
name = "example"
version = "0.1.0"
[[target]]
name = "example"
[target.example]
type = "executable"
sources = ["src/example.cpp"]
+21 -6
View File
@@ -1,13 +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")
set(CMKR_TAG "archive_84f6b39f" CACHE STRING "cmkr git tag (this needs to be available forever)")
set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE)
set(CMKR_TAG "archive_eaf03eb7" 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()
@@ -45,7 +47,14 @@ else()
endif()
# Use cached cmkr if found
set(CMKR_CACHED_EXECUTABLE "${CMAKE_CURRENT_BINARY_DIR}/_cmkr/bin/${CMKR_EXECUTABLE_NAME}")
set(CMKR_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_${CMKR_TAG}")
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")
message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'")
unset(CMKR_EXECUTABLE CACHE)
endif()
if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}")
message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'")
elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE)
@@ -55,7 +64,6 @@ else()
message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'")
message(STATUS "[cmkr] Fetching cmkr...")
set(CMKR_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/_cmkr")
if(EXISTS "${CMKR_DIRECTORY}")
cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}")
endif()
@@ -70,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"
@@ -122,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
+5 -6
View File
@@ -1,15 +1,15 @@
#pragma once
static const char *hello_world = R"lit(
static const char *hello_world = &R"lit(
#include <iostream>
int %s() {
std::cout << "Hello World!\n";
return 0;
}
)lit" + 1; // skip initial newline
)lit"[1]; // skip initial newline
static const char *cmake_toml = R"lit(
static const char *cmake_toml = &R"lit(
[cmake]
version = "3.15"
# subdirs = []
@@ -30,8 +30,7 @@ version = "0.1.0"
# [options]
[[target]]
name = "%s"
[target.%s]
type = "%s"
sources = ["src/*.cpp"]
include-directories = ["include"]
@@ -43,4 +42,4 @@ include-directories = ["include"]
[[install]]
%s = ["%s"]
destination = "${CMAKE_INSTALL_PREFIX}/%s"
)lit" + 1; // skip initial newline
)lit"[1]; // skip initial newline
@@ -8,7 +8,7 @@
#include <vector>
namespace cmkr {
namespace cmake {
namespace parser {
struct Setting {
std::string name;
@@ -21,7 +21,7 @@ struct Setting {
struct Option {
std::string name;
std::string comment;
bool val;
bool val = false;
};
struct Package {
@@ -34,6 +34,7 @@ struct Package {
struct Vcpkg {
std::string version;
std::string url;
std::vector<std::string> packages;
};
@@ -46,34 +47,59 @@ enum TargetType {
target_custom,
};
template <typename T>
using Condition = tsl::ordered_map<std::string, T>;
using ConditionVector = Condition<std::vector<std::string>>;
struct Target {
std::string name;
TargetType type;
TargetType type = {};
ConditionVector headers;
ConditionVector sources;
// https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html#project-commands
std::vector<std::string> compile_definitions;
std::vector<std::string> compile_features;
std::vector<std::string> compile_options;
std::vector<std::string> include_directories;
std::vector<std::string> link_directories;
std::vector<std::string> link_libraries;
std::vector<std::string> link_options;
std::vector<std::string> precompile_headers;
std::vector<std::string> sources;
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;
std::string cmake_before;
std::string cmake_after;
std::vector<std::string> include_before;
std::vector<std::string> include_after;
Condition<std::string> cmake_before;
Condition<std::string> cmake_after;
ConditionVector include_before;
ConditionVector include_after;
};
struct Test {
std::string name;
std::string cmd;
std::vector<std::string> args;
std::vector<std::string> configurations;
std::string working_directory;
std::string command;
std::vector<std::string> arguments;
};
struct Install {
@@ -84,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;
@@ -101,10 +136,10 @@ struct CMake {
std::string project_version;
std::string project_description;
std::vector<std::string> project_languages;
std::string cmake_before;
std::string cmake_after;
std::vector<std::string> include_before;
std::vector<std::string> include_after;
Condition<std::string> cmake_before;
Condition<std::string> cmake_after;
ConditionVector include_before;
ConditionVector include_after;
std::vector<Setting> settings;
std::vector<Option> options;
std::vector<Package> packages;
@@ -113,8 +148,13 @@ struct CMake {
std::vector<Target> targets;
std::vector<Test> tests;
std::vector<Install> installs;
CMake(const std::string &path, bool build);
tsl::ordered_map<std::string, std::string> conditions;
std::vector<Subdir> subdirs;
Project(const std::string &path, bool build);
};
} // namespace cmake
bool is_root_path(const std::string &path);
} // namespace parser
} // namespace cmkr
+5 -6
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>
@@ -21,8 +21,7 @@ const char *handle_args(int argc, char **argv) {
throw std::runtime_error(cmkr::help::message());
std::string main_arg = args[1];
if (main_arg == "gen") {
auto current_path = fs::current_path();
auto ret = cmkr::gen::generate_cmake(current_path.string().c_str());
auto ret = cmkr::gen::generate_cmake(fs::current_path().string().c_str());
if (ret)
return "CMake generation error!";
return "CMake generation successful!";
+24 -25
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,34 +14,33 @@ 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;
if (!fs::exists("CMakeLists.txt"))
if (gen::generate_cmake("."))
throw std::runtime_error("CMake generation failure!");
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;
}
}
@@ -51,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
+428 -171
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>
@@ -41,7 +44,6 @@ static std::vector<std::string> expand_cmake_path(const fs::path &name, const fs
std::vector<std::string> temp;
auto extract_suffix = [](const fs::path &base, const fs::path &full) {
// TODO: delet this
auto fullpath = full.string();
auto base_len = base.string().length();
auto delet = fullpath.substr(base_len + 1, fullpath.length() - base_len);
@@ -70,6 +72,8 @@ static std::vector<std::string> expand_cmake_path(const fs::path &name, const fs
for (auto &path : temp) {
std::replace(path.begin(), path.end(), '\\', '/');
}
// Sort paths alphabetically for consistent cross-OS generation
std::sort(temp.begin(), temp.end());
return temp;
}
@@ -139,6 +143,13 @@ struct CommandEndl {
void endl() { ss << '\n'; }
};
struct RawArg {
RawArg() = default;
RawArg(std::string arg) : arg(std::move(arg)) {}
std::string arg;
};
// Credit: JustMagic
struct Command {
std::stringstream &ss;
@@ -147,18 +158,21 @@ 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 ()");
}
}
std::string quote(const std::string &str) {
// Don't quote arguments that don't need quoting
if (str.find(' ') == std::string::npos && str.find('\"') == std::string::npos && str.find('/') == std::string::npos) {
if (str.find(' ') == std::string::npos && str.find('\"') == std::string::npos && str.find('/') == std::string::npos &&
str.find(';') == std::string::npos) {
return str;
}
std::string result;
@@ -244,8 +258,26 @@ struct Command {
return true;
}
bool print_arg(const RawArg &arg) {
if (arg.arg.empty()) {
return true;
}
if (had_newline) {
first_arg = false;
ss << '\n' << indent(depth + 1);
} else if (first_arg) {
first_arg = false;
} else {
ss << ' ';
}
ss << arg.arg;
return true;
}
template <class T>
bool print_arg(const T &value, bool indentation = true) {
bool print_arg(const T &value) {
std::stringstream tmp;
tmp << value;
auto str = tmp.str();
@@ -253,15 +285,13 @@ struct Command {
return true;
}
if (indentation) {
if (had_newline) {
first_arg = false;
ss << '\n' << indent(depth + 1);
} else if (first_arg) {
first_arg = false;
} else {
ss << ' ';
}
if (had_newline) {
first_arg = false;
ss << '\n' << indent(depth + 1);
} else if (first_arg) {
first_arg = false;
} else {
ss << ' ';
}
ss << quote(str);
@@ -272,74 +302,164 @@ struct Command {
CommandEndl operator()(Ts &&...values) {
generated = true;
ss << indent(depth) << command << '(';
std::initializer_list<bool>{print_arg(values)...};
(void)std::initializer_list<bool>{print_arg(values)...};
if (had_newline)
ss << '\n';
ss << ")\n";
ss << '\n' << indent(depth);
ss << ")";
if (!post_comment.empty()) {
ss << " # " << post_comment;
}
ss << "\n";
return CommandEndl(ss);
}
};
static std::string tolf(const std::string &str) {
std::string result;
for (char ch : str) {
if (ch != '\r') {
result += ch;
}
}
return result;
};
struct Generator {
Generator(parser::Project &project) : project(project) {}
Generator(const Generator &) = delete;
parser::Project &project;
std::stringstream ss;
int indent = 0;
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, post_comment);
} else if (command == "else" || command == "elseif") {
return Command(ss, indent - 1, command, post_comment);
} else if (command == "endif") {
indent--;
}
return Command(ss, indent, command, post_comment);
}
CommandEndl comment(const std::string &comment) {
ss << Command::indent(indent) << "# " << comment << '\n';
return CommandEndl(ss);
}
void endl() { ss << '\n'; }
void inject_includes(const std::vector<std::string> &includes) {
if (!includes.empty()) {
for (const auto &file : includes) {
if (!fs::is_regular_file(file)) {
throw std::runtime_error("Include '" + file + "' does not exist");
}
cmd("include")(file);
}
}
}
void inject_cmake(const std::string &cmake) {
if (!cmake.empty()) {
if (cmake.back() == '\"') {
throw std::runtime_error("Detected additional \" at the end of cmake block");
}
auto cmake_lf = tolf(cmake);
while (cmake_lf.back() == '\n')
cmake_lf.pop_back();
bool did_indent = false;
for (char ch : cmake_lf) {
if (!did_indent) {
ss << Command::indent(indent);
did_indent = true;
} else if (ch == '\n') {
did_indent = false;
}
ss << ch;
}
ss << '\n';
}
}
template <typename T, typename Lambda>
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 (project.conditions.count(condition) == 0) {
// TODO: somehow print line number information here?
throw std::runtime_error("Unknown condition '" + condition + "'");
}
cmd("if", condition)(RawArg(project.conditions[condition]));
}
if (!itr.second.empty()) {
fn(condition, itr.second);
}
if (!condition.empty()) {
cmd("endif")();
}
endl();
}
}
}
};
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!");
}
parser::Project project(path, false);
Generator gen(project);
// Helper lambdas for more convenient CMake generation
std::stringstream ss;
int indent = 0;
auto cmd = [&ss, &indent](const std::string &command) {
if (command.empty())
throw std::invalid_argument("command cannot be empty");
if (command == "if") {
indent++;
return Command(ss, indent - 1, command);
} else if (command == "else" || command == "elseif") {
return Command(ss, indent - 1, command);
} else if (command == "endif") {
indent--;
}
return Command(ss, indent, command);
};
auto comment = [&ss, &indent](const std::string &comment) {
ss << Command::indent(indent) << "# " << comment << '\n';
return CommandEndl(ss);
};
auto endl = [&ss]() { ss << '\n'; };
auto tolf = [](const std::string &str) {
std::string result;
for (char ch : str) {
if (ch != '\r') {
result += ch;
}
}
return result;
};
auto inject_includes = [&cmd, &endl](const std::vector<std::string> &includes) {
if (!includes.empty()) {
for (const auto &file : includes) {
// TODO: warn/error if file doesn't exist?
cmd("include")(file);
}
endl();
}
};
auto inject_cmake = [&ss, &tolf](const std::string &cmake) {
if (!cmake.empty()) {
if (cmake.back() == '\"') {
throw std::runtime_error("Detected additional \" at the end of cmake block");
}
ss << tolf(cmake) << "\n\n";
}
};
auto &ss = gen.ss;
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); };
// TODO: add link with proper documentation
comment("This file was generated automatically by cmkr.").endl();
cmake::CMake cmake(path, false);
std::string cmkr_url = "https://github.com/build-cpp/cmkr";
comment("This file is automatically generated from cmake.toml - DO NOT EDIT");
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");
@@ -348,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();
@@ -367,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";
}
inject_includes(cmake.include_before);
inject_cmake(cmake.cmake_before);
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();
}
inject_includes(cmake.include_after);
inject_cmake(cmake.cmake_after);
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) {
@@ -435,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();
@@ -459,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);
@@ -488,74 +639,123 @@ 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();
}
if (!cmake.targets.empty()) {
for (const auto &target : cmake.targets) {
comment("Target " + target.name);
inject_includes(target.include_before);
inject_cmake(target.cmake_before);
if (!target.sources.empty()) {
auto sources = expand_cmake_paths(target.sources, path);
if (sources.empty()) {
throw std::runtime_error(target.name + " sources wildcard found 0 files");
}
if (target.type != cmake::target_interface) {
// Do not add cmake.toml twice
if (std::find(sources.begin(), sources.end(), "cmake.toml") == sources.end()) {
sources.push_back("cmake.toml");
}
}
cmd("set")(target.name + "_SOURCES", sources).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]));
}
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); });
auto sources_var = target.name + "_SOURCES";
bool added_toml = false;
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()) {
auto source_key = condition.empty() ? "sources" : (condition + ".sources");
throw std::runtime_error(target.name + " " + source_key + " wildcard found 0 files");
}
// Do not add cmake.toml twice
if (!added_toml && std::find(sources.begin(), sources.end(), "cmake.toml") != sources.end()) {
added_toml = true;
}
cmd("list")("APPEND", sources_var, sources);
});
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";
@@ -565,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");
@@ -578,48 +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 std::vector<std::string> &args) {
if (!args.empty()) {
cmd(command)(target.name, target_scope, args).endl();
}
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);
});
}
inject_includes(target.include_after);
inject_cmake(target.cmake_after);
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()) {
cmd("include")("CTest");
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 command = std::make_pair("COMMAND", test.cmd);
cmd("add_test")(name, command, test.args).endl();
auto configurations = std::make_pair("CONFIGURATIONS", test.configurations);
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;
@@ -662,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(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;
-238
View File
@@ -1,238 +0,0 @@
#include "cmake.hpp"
#include "enum_helper.hpp"
#include "fs.hpp"
#include <stdexcept>
#include <toml.hpp>
#include <tsl/ordered_map.h>
template <>
const char *enumStrings<cmkr::cmake::TargetType>::data[] = {"executable", "library", "shared", "static", "interface", "custom"};
namespace cmkr {
namespace cmake {
using TomlBasicValue = toml::basic_value<toml::preserve_comments, tsl::ordered_map, std::vector>;
template <typename EnumType>
static EnumType to_enum(const std::string &str, const std::string &help_name) {
EnumType value;
try {
std::stringstream ss(str);
ss >> enumFromString(value);
} catch (std::invalid_argument &) {
std::string supported;
for (const auto &s : enumStrings<EnumType>::data) {
if (!supported.empty()) {
supported += ", ";
}
supported += s;
}
throw std::runtime_error("Unknown " + help_name + "'" + str + "'! Supported types are: " + supported);
}
return value;
}
static std::vector<std::string> optional_array(const TomlBasicValue &v, const toml::key &ky) {
return toml::find_or(v, ky, std::vector<std::string>());
};
CMake::CMake(const std::string &path, bool build) {
if (!fs::exists(fs::path(path) / "cmake.toml")) {
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());
if (build) {
if (toml.contains("cmake")) {
const auto &cmake = toml::find(toml, "cmake");
if (cmake.contains("bin-dir")) {
throw std::runtime_error("bin-dir has been renamed to build-dir");
}
build_dir = toml::find_or(cmake, "build-dir", "");
generator = toml::find_or(cmake, "generator", "");
config = toml::find_or(cmake, "config", "");
gen_args = optional_array(cmake, "arguments");
}
} else {
if (toml.contains("cmake")) {
const auto &cmake = toml::find(toml, "cmake");
cmake_version = toml::find(cmake, "version").as_string();
cmkr_include = toml::find_or(cmake, "cmkr-include", cmkr_include);
cppflags = optional_array(cmake, "cpp-flags");
cflags = optional_array(cmake, "c-flags");
linkflags = optional_array(cmake, "link-flags");
}
if (toml.contains("project")) {
const auto &project = toml::find(toml, "project");
project_name = toml::find(project, "name").as_string();
project_version = toml::find_or(project, "version", "");
project_description = toml::find_or(project, "description", "");
project_languages = optional_array(project, "languages");
cmake_before = toml::find_or(project, "cmake-before", "");
cmake_after = toml::find_or(project, "cmake-after", "");
include_before = optional_array(project, "include-before");
include_after = optional_array(project, "include-after");
subdirs = optional_array(project, "subdirs");
}
if (toml.contains("settings")) {
using set_map = std::map<std::string, TomlBasicValue>;
const auto &sets = toml::find<set_map>(toml, "settings");
for (const auto set : sets) {
Setting s;
s.name = set.first;
if (set.second.is_boolean()) {
s.val = set.second.as_boolean();
} else if (set.second.is_string()) {
s.val = set.second.as_string();
} else {
s.comment = toml::find_or(set.second, "comment", "");
if (set.second.contains("value")) {
auto v = toml::find(set.second, "value");
if (v.is_boolean()) {
s.val = v.as_boolean();
} else {
s.val = v.as_string();
}
}
s.cache = toml::find_or(set.second, "cache", false);
s.force = toml::find_or(set.second, "force", false);
}
settings.push_back(s);
}
}
if (toml.contains("options")) {
using opts_map = tsl::ordered_map<std::string, TomlBasicValue>;
const auto &opts = toml::find<opts_map>(toml, "options");
for (const auto opt : opts) {
Option o;
o.name = opt.first;
if (opt.second.is_boolean()) {
o.val = opt.second.as_boolean();
} else {
o.comment = toml::find_or(opt.second, "comment", "");
o.val = toml::find_or(opt.second, "value", false);
}
options.push_back(o);
}
}
if (toml.contains("find-package")) {
using pkg_map = tsl::ordered_map<std::string, TomlBasicValue>;
const auto &pkgs = toml::find<pkg_map>(toml, "find-package");
for (const auto &pkg : pkgs) {
Package p;
p.name = pkg.first;
if (pkg.second.is_string()) {
p.version = pkg.second.as_string();
} else {
p.version = toml::find_or(pkg.second, "version", p.version);
p.required = toml::find_or(pkg.second, "required", p.required);
p.config = toml::find_or(pkg.second, "config", p.config);
p.components = toml::find_or(pkg.second, "components", p.components);
}
packages.push_back(p);
}
}
// TODO: refactor to std::vector<Content> instead of this hacky thing?
contents = toml::find_or<decltype(contents)>(toml, "fetch-content", {});
if (toml.contains("bin")) {
throw std::runtime_error("[[bin]] has been renamed to [[target]]");
}
if (toml.contains("target")) {
const auto &ts = toml::find(toml, "target").as_table();
for (const auto &itr : ts) {
const auto &t = itr.second;
Target target;
target.name = itr.first;
target.type = to_enum<TargetType>(toml::find(t, "type").as_string(), "target type");
target.sources = optional_array(t, "sources");
#define renamed(from, to) \
if (t.contains(from)) { \
throw std::runtime_error(from "has been renamed to " to); \
}
renamed("include-dirs", "include-directories");
renamed("link-libs", "link-libraries");
renamed("defines", "compile-definitions");
renamed("features", "compile-features");
#undef renamed
target.compile_definitions = optional_array(t, "compile-definitions");
target.compile_features = optional_array(t, "compile-features");
target.compile_options = optional_array(t, "compile-options");
target.include_directories = optional_array(t, "include-directories");
target.link_directories = optional_array(t, "link-directories");
target.link_libraries = optional_array(t, "link-libraries");
target.link_options = optional_array(t, "link-options");
target.precompile_headers = optional_array(t, "precompile-headers");
if (t.contains("alias")) {
target.alias = toml::find(t, "alias").as_string();
}
if (t.contains("properties")) {
using prop_map = tsl::ordered_map<std::string, std::string>;
target.properties = toml::find<prop_map>(t, "properties");
}
target.cmake_before = toml::find_or(t, "cmake-before", target.cmake_before);
target.cmake_after = toml::find_or(t, "cmake-after", target.cmake_after);
target.include_before = optional_array(t, "include-before");
target.include_after = optional_array(t, "include-after");
targets.push_back(target);
}
}
if (toml.contains("test")) {
const auto &ts = toml::find(toml, "test").as_array();
for (const auto &t : ts) {
Test test;
test.name = toml::find(t, "name").as_string();
test.cmd = toml::find(t, "type").as_string();
test.args = optional_array(t, "arguments");
tests.push_back(test);
}
}
if (toml.contains("install")) {
const auto &ts = toml::find(toml, "install").as_array();
for (const auto &t : ts) {
Install inst;
inst.targets = optional_array(t, "targets");
inst.files = optional_array(t, "files");
inst.dirs = optional_array(t, "dirs");
inst.configs = optional_array(t, "configs");
inst.destination = toml::find(t, "destination").as_string();
installs.push_back(inst);
}
}
if (toml.contains("vcpkg")) {
const auto &v = toml::find(toml, "vcpkg");
vcpkg.version = toml::find(v, "version").as_string();
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";
}
}
}
}
} // namespace cmake
} // namespace cmkr
+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>
+340
View File
@@ -0,0 +1,340 @@
#include "project_parser.hpp"
#include "enum_helper.hpp"
#include "fs.hpp"
#include <stdexcept>
#include <toml.hpp>
#include <tsl/ordered_map.h>
template <>
const char *enumStrings<cmkr::parser::TargetType>::data[] = {"executable", "library", "shared", "static", "interface", "custom"};
namespace cmkr {
namespace parser {
using TomlBasicValue = toml::basic_value<toml::preserve_comments, tsl::ordered_map, std::vector>;
template <typename EnumType>
static EnumType to_enum(const std::string &str, const std::string &help_name) {
EnumType value;
try {
std::stringstream ss(str);
ss >> enumFromString(value);
} catch (std::invalid_argument &) {
std::string supported;
for (const auto &s : enumStrings<EnumType>::data) {
if (!supported.empty()) {
supported += ", ";
}
supported += s;
}
throw std::runtime_error("Unknown " + help_name + "'" + str + "'! Supported types are: " + supported);
}
return value;
}
template <typename T>
static void get_optional(const TomlBasicValue &v, const toml::key &ky, T &destination);
template <typename T>
static void get_optional(const TomlBasicValue &v, const toml::key &ky, Condition<T> &destination) {
// TODO: this algorithm in O(n) over the amount of keys, kinda bad
const auto &table = v.as_table();
for (const auto &itr : table) {
const auto &key = itr.first;
const auto &value = itr.second;
if (value.is_table()) {
if (value.contains(ky)) {
destination[key] = toml::find<T>(value, ky);
}
} else if (key == ky) {
destination[""] = toml::find<T>(v, ky);
}
}
}
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);
}
}
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>(toml_path.string());
if (build) {
if (toml.contains("cmake")) {
const auto &cmake = toml::find(toml, "cmake");
if (cmake.contains("bin-dir")) {
throw std::runtime_error("bin-dir has been renamed to build-dir");
}
get_optional(cmake, "build-dir", build_dir);
get_optional(cmake, "generator", generator);
get_optional(cmake, "config", config);
get_optional(cmake, "arguments", gen_args);
}
} else {
if (toml.contains("cmake")) {
const auto &cmake = toml::find(toml, "cmake");
cmake_version = toml::find(cmake, "version").as_string();
get_optional(cmake, "cmkr-include", cmkr_include);
get_optional(cmake, "cpp-flags", cppflags);
get_optional(cmake, "c-flags", cflags);
get_optional(cmake, "link-flags", linkflags);
}
if (toml.contains("project")) {
const auto &project = toml::find(toml, "project");
project_name = toml::find(project, "name").as_string();
get_optional(project, "version", project_version);
get_optional(project, "description", project_description);
get_optional(project, "languages", project_languages);
get_optional(project, "cmake-before", cmake_before);
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", 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")) {
using set_map = std::map<std::string, TomlBasicValue>;
const auto &sets = toml::find<set_map>(toml, "settings");
for (const auto &set : sets) {
Setting s;
s.name = set.first;
if (set.second.is_boolean()) {
s.val = set.second.as_boolean();
} else if (set.second.is_string()) {
s.val = set.second.as_string();
} else {
get_optional(set.second, "comment", s.comment);
if (set.second.contains("value")) {
auto v = toml::find(set.second, "value");
if (v.is_boolean()) {
s.val = v.as_boolean();
} else {
s.val = v.as_string();
}
}
get_optional(set.second, "cache", s.cache);
get_optional(set.second, "force", s.force);
}
settings.push_back(s);
}
}
if (toml.contains("options")) {
using opts_map = tsl::ordered_map<std::string, TomlBasicValue>;
const auto &opts = toml::find<opts_map>(toml, "options");
for (const auto &opt : opts) {
Option o;
o.name = opt.first;
if (opt.second.is_boolean()) {
o.val = opt.second.as_boolean();
} else {
get_optional(opt.second, "comment", o.comment);
get_optional(opt.second, "value", o.val);
}
options.push_back(o);
}
}
if (toml.contains("find-package")) {
using pkg_map = tsl::ordered_map<std::string, TomlBasicValue>;
const auto &pkgs = toml::find<pkg_map>(toml, "find-package");
for (const auto &pkg : pkgs) {
Package p;
p.name = pkg.first;
if (pkg.second.is_string()) {
p.version = pkg.second.as_string();
} else {
get_optional(pkg.second, "version", p.version);
get_optional(pkg.second, "required", p.required);
get_optional(pkg.second, "config", p.config);
get_optional(pkg.second, "components", p.components);
}
packages.push_back(p);
}
}
// TODO: refactor to std::vector<Content> instead of this hacky thing?
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]]");
}
if (toml.contains("target")) {
const auto &ts = toml::find(toml, "target").as_table();
for (const auto &itr : ts) {
const auto &t = itr.second;
Target target;
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")) {
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 : v.as_array()) {
if (!property_list.empty()) {
property_list += ';';
}
property_list += list_val.as_string();
}
target.properties[condition][k] = property_list;
} else if (v.is_boolean()) {
target.properties[condition][k] = v.as_boolean() ? "ON" : "OFF";
} else {
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, "");
}
}
}
get_optional(t, "cmake-before", target.cmake_before);
get_optional(t, "cmake-after", target.cmake_after);
get_optional(t, "include-before", target.include_before);
get_optional(t, "include-after", target.include_after);
targets.push_back(target);
}
}
if (toml.contains("test")) {
const auto &ts = toml::find(toml, "test").as_array();
for (const auto &t : ts) {
Test test;
test.name = toml::find(t, "name").as_string();
get_optional(t, "configurations", test.configurations);
get_optional(t, "working-directory", test.working_directory);
test.command = toml::find(t, "command").as_string();
get_optional(t, "arguments", test.arguments);
tests.push_back(test);
}
}
if (toml.contains("install")) {
const auto &ts = toml::find(toml, "install").as_array();
for (const auto &t : ts) {
Install inst;
get_optional(t, "targets", inst.targets);
get_optional(t, "files", inst.files);
get_optional(t, "dirs", inst.dirs);
get_optional(t, "configs", inst.configs);
inst.destination = toml::find(t, "destination").as_string();
installs.push_back(inst);
}
}
if (toml.contains("vcpkg")) {
const auto &v = toml::find(toml, "vcpkg");
get_optional(v, "url", vcpkg.url);
get_optional(v, "version", vcpkg.version);
vcpkg.packages = toml::find<decltype(vcpkg.packages)>(v, "packages");
}
// Reasonable default conditions (you can override these if you desire)
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");
for (const auto &cond : conds) {
conditions[cond.first] = cond.second;
}
}
}
}
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
+2
View File
@@ -0,0 +1,2 @@
# These will be generated by cmkr, so no point in tracking them
**/CMakeLists.txt
+60
View File
@@ -0,0 +1,60 @@
# This file is automatically generated from cmake.toml - DO NOT EDIT
# 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)
configure_file(cmake.toml cmake.toml COPYONLY)
endif()
enable_testing()
add_test(
NAME
basic
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/basic"
COMMAND
$<TARGET_FILE:cmkr>
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
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/conditions"
COMMAND
$<TARGET_FILE:cmkr>
build
)
add_test(
NAME
vcpkg
WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/vcpkg"
COMMAND
$<TARGET_FILE:cmkr>
build
)
+11
View File
@@ -0,0 +1,11 @@
# 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)`.
+5
View File
@@ -0,0 +1,5 @@
#include <cstdio>
int main() {
puts("Hello from cmkr!");
}
+29
View File
@@ -0,0 +1,29 @@
[[test]]
name = "basic"
command = "$<TARGET_FILE:cmkr>"
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 = "conditions"
arguments = ["build"]
[[test]]
name = "vcpkg"
command = "$<TARGET_FILE:cmkr>"
working-directory = "vcpkg"
arguments = ["build"]
+23
View File
@@ -0,0 +1,23 @@
[project]
name = "conditions"
cmake-after = "set(CUSTOM ON)"
[conditions]
custom = "CUSTOM"
[target.example]
type = "executable"
sources = ["src/main.cpp"]
windows.sources = ["src/windows_specific.cpp"]
cmake-after = "message(STATUS cmake-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)"
[target.example.properties]
AUTOMOC = false
custom.OUTPUT_NAME = "example2"
custom.AUTORCC = true
AUTOGEN = "ON"
+1
View File
@@ -0,0 +1 @@
int main() { }
+3
View File
@@ -0,0 +1,3 @@
#include <Windows.h>
void foo() { }
+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