mirror of
https://github.com/build-cpp/cmkr
synced 2026-06-08 13:22:55 +00:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 264e4ace18 | |||
| b6ab584a1a | |||
| 3cd84a9708 | |||
| 9932e501ce | |||
| 1b37dd76a5 | |||
| 82f2a11311 | |||
| eaf03eb785 | |||
| 8ea5b77ba5 | |||
| a12b3ae021 | |||
| 2450cfb2c9 | |||
| 8d024556e3 | |||
| af3807ca2b | |||
| 17f085c66d | |||
| 5ad6134e07 | |||
| 7b20d8c54c | |||
| ffdedbdace | |||
| bb7a0bc0ed | |||
| dd0003f8fe | |||
| a32caca8f0 | |||
| f565ad2af0 | |||
| dc4b59f05d | |||
| 4988f141e4 | |||
| 64b58425e6 | |||
| d4f0cdf152 | |||
| 306bb3d4fc | |||
| acd3688d16 | |||
| 23c5713c6b | |||
| cebe73c8e5 | |||
| 779d4ae96a | |||
| 7eed60bc7d | |||
| aa468dcf9c | |||
| 1bd9d2228e | |||
| 5364b5ea72 | |||
| 7a5d3b0491 | |||
| 02f1a70628 | |||
| 7bd97e56e3 | |||
| 6e0e3d8215 | |||
| 00230ee11a | |||
| e734886d9f | |||
| cf748514fb | |||
| fbe968f817 | |||
| d1097c8303 | |||
| 8697d87e50 | |||
| 7dfa905625 | |||
| 9a008f0e40 | |||
| deb08bcf79 | |||
| 3ba07bfd17 | |||
| 3f1dfe5be3 | |||
| a002ddc606 | |||
| c686f1bec5 | |||
| 812ef8e7a6 | |||
| 862fce189c | |||
| cd98345125 | |||
| 945e4b74c4 | |||
| 2ad6acbce9 | |||
| c893ddd8c5 | |||
| 55fa8b937a | |||
| 2648d8c6c8 | |||
| 3413105fec | |||
| 85bef09710 | |||
| 964961eb64 | |||
| b350ed2c55 | |||
| 7cf16eaf70 | |||
| 9622334bf1 | |||
| 6ad29ef624 | |||
| 718c2c7527 | |||
| 8ea0c7396c | |||
| 34c12379c2 | |||
| 6395267e4b | |||
| 6d9b40bd15 | |||
| c4673d59e2 | |||
| 220dec6bbb | |||
| 4efa74f91f | |||
| fbd07c47bc | |||
| 17d4dc0555 | |||
| a6dfb2272d | |||
| 7fdafa4189 | |||
| 7cdf36f317 | |||
| bf14f069a7 | |||
| 3b4bc919a1 | |||
| c0bdbeb9d8 | |||
| 42725d0339 | |||
| 8f393d967d | |||
| 1cf9240579 | |||
| 7b7b260379 | |||
| 747bc8be00 | |||
| 00121c261f | |||
| 326647011b | |||
| 598c9b9ba8 | |||
| d62dff29b1 | |||
| 783f343e40 | |||
| 5312b44860 |
@@ -0,0 +1 @@
|
||||
CMakeLists.txt linguist-generated
|
||||
@@ -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
@@ -5,6 +5,7 @@ compile_commands.json
|
||||
temp.*
|
||||
.vs
|
||||
.cache
|
||||
build*/
|
||||
.idea/
|
||||
cmake-build*/
|
||||
build*/
|
||||
.idea/
|
||||
cmake-build*/
|
||||
CMakeLists.txt.user
|
||||
|
||||
@@ -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.
|
||||
Generated
+72
-45
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
Generated
+32
-15
@@ -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
@@ -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
@@ -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_3cd84a97" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE)
|
||||
|
||||
# Set these from the command line to customize for development/debugging purposes
|
||||
set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable")
|
||||
set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation")
|
||||
|
||||
# Disable cmkr if generation is disabled
|
||||
if(CMKR_SKIP_GENERATION)
|
||||
if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION)
|
||||
message(STATUS "[cmkr] Skipping automatic cmkr generation")
|
||||
macro(cmkr)
|
||||
endmacro()
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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()
|
||||
@@ -0,0 +1,2 @@
|
||||
_site/
|
||||
.jekyll-metadata
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
```
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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).
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 109 KiB |
@@ -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 |
@@ -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 |
@@ -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.
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
bundle exec just-the-docs rake search:init
|
||||
bundle exec jekyll serve --livereload
|
||||
@@ -0,0 +1,2 @@
|
||||
bundle install
|
||||
bundle exec jekyll serve --force_polling --livereload --incremental
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace cmkr {
|
||||
namespace help {
|
||||
|
||||
@@ -11,13 +10,6 @@ const char *message() noexcept;
|
||||
} // namespace help
|
||||
} // namespace cmkr
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char *cmkr_help_version(void);
|
||||
|
||||
const char *cmkr_help_message(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,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
|
||||
@@ -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!";
|
||||
@@ -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
|
||||
@@ -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((path / subpath).string())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
subpath = path / sub;
|
||||
if (fs::exists(subpath / "cmake.toml")) {
|
||||
generate_cmake(subpath.string().c_str(), false);
|
||||
}
|
||||
};
|
||||
for (const auto &itr : project.project_subdirs) {
|
||||
for (const auto &sub : itr.second) {
|
||||
generate_subdir(sub);
|
||||
}
|
||||
}
|
||||
for (const auto &subdir : project.subdirs) {
|
||||
generate_subdir(subdir.name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,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", build_dir);
|
||||
generator = toml::find_or(cmake, "generator", generator);
|
||||
config = toml::find_or(cmake, "config", 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,4 +1,4 @@
|
||||
#include "error.h"
|
||||
#include "error.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "help.h"
|
||||
#include "help.hpp"
|
||||
|
||||
namespace cmkr {
|
||||
namespace help {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "args.h"
|
||||
#include "arguments.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
# These will be generated by cmkr, so no point in tracking them
|
||||
**/CMakeLists.txt
|
||||
Generated
+60
@@ -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
|
||||
)
|
||||
|
||||
@@ -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)`.
|
||||
@@ -0,0 +1,5 @@
|
||||
#include <cstdio>
|
||||
|
||||
int main() {
|
||||
puts("Hello from cmkr!");
|
||||
}
|
||||
@@ -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"]
|
||||
@@ -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"
|
||||
@@ -0,0 +1 @@
|
||||
int main() { }
|
||||
@@ -0,0 +1,3 @@
|
||||
#include <Windows.h>
|
||||
|
||||
void foo() { }
|
||||
@@ -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).
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
fmt::print("Hello, world!\n");
|
||||
}
|
||||
@@ -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"]
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace mylib
|
||||
{
|
||||
static const char* version() { return "v1.0"; }
|
||||
} // namespace mylib
|
||||
@@ -0,0 +1,8 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include "mylib/mylib.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("mylib version: %s\n", mylib::version())
|
||||
}
|
||||
@@ -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`.
|
||||
@@ -0,0 +1,6 @@
|
||||
#include <fmt/core.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
fmt::print("Hello, world!\n");
|
||||
}
|
||||
@@ -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": ""
|
||||
}
|
||||
+4
@@ -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)
|
||||
Vendored
+21
@@ -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.
|
||||
+25447
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user