Automatically generate documentation from tests

toml-checker
Duncan Ogilvie 4 years ago
parent acd3688d16
commit 306bb3d4fc

17
CMakeLists.txt generated

@ -32,6 +32,8 @@ project(cmkr
"CMakeLists generator from TOML" "CMakeLists generator from TOML"
) )
include("cmake/generate_documentation.cmake")
# third_party # third_party
set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER}) set(CMKR_CMAKE_FOLDER ${CMAKE_FOLDER})
if(CMAKE_FOLDER) if(CMAKE_FOLDER)
@ -54,6 +56,21 @@ set(CMAKE_FOLDER ${CMKR_CMAKE_FOLDER})
# Target cmkr_generate_documentation
set(CMKR_TARGET cmkr_generate_documentation)
set(cmkr_generate_documentation_SOURCES "")
set(CMKR_SOURCES ${cmkr_generate_documentation_SOURCES})
add_library(cmkr_generate_documentation INTERFACE)
if(cmkr_generate_documentation_SOURCES)
target_sources(cmkr_generate_documentation INTERFACE ${cmkr_generate_documentation_SOURCES})
endif()
generate_documentation()
unset(CMKR_TARGET)
unset(CMKR_SOURCES)
# Target cmkr # Target cmkr
set(CMKR_TARGET cmkr) set(CMKR_TARGET cmkr)
set(cmkr_SOURCES "") set(cmkr_SOURCES "")

@ -7,6 +7,13 @@ version = "0.1.4"
description = "CMakeLists generator from TOML" description = "CMakeLists generator from TOML"
languages = ["CXX"] languages = ["CXX"]
subdirs = ["third_party", "tests"] subdirs = ["third_party", "tests"]
include-after = ["cmake/generate_documentation.cmake"]
[target.cmkr_generate_documentation]
type = "interface"
cmake-after = """
generate_documentation()
"""
[target.cmkr] [target.cmkr]
type = "executable" type = "executable"

@ -83,6 +83,7 @@ else()
"-B${CMKR_DIRECTORY}/build" "-B${CMKR_DIRECTORY}/build"
"-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}"
"-DCMKR_GENERATE_DOCUMENTATION=OFF"
) )
cmkr_exec("${CMAKE_COMMAND}" cmkr_exec("${CMAKE_COMMAND}"
--build "${CMKR_DIRECTORY}/build" --build "${CMKR_DIRECTORY}/build"

@ -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,73 @@
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})
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")
file(REMOVE ${example_files})
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()

3
docs/.gitignore vendored

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

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

@ -1,17 +0,0 @@
---
layout: default
title: Changing C/C++ version
permalink: /examples/cpp-version-change
parent: Examples
nav_order: 3
---
# Changing C/C++ version
Simple example changing C++ to version 20 and C standard to the version 11
```toml
[target.example]
type = "executable"
compile-features = [ "cxx_std_20", "c_std_11" ]
```

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

@ -1,22 +0,0 @@
---
layout: default
title: Import content from Github
permalink: /examples/import-from-git
parent: Examples
nav_order: 2
---
# Import content from Github
Importing an existing project called Zydis to my project
tag is optional but you can target any branch with it
```toml
[fetch-content]
zydis = { git = "https://github.com/zyantific/zydis.git", tag = "v3.1.0" }
[target.example]
type = "executable"
link-libraries = ["zydis"]
```

@ -1,10 +0,0 @@
---
layout: default
title: Examples
permalink: /examples/
nav_order: 4
has_children: true
---
# Examples

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

@ -1,23 +0,0 @@
---
layout: default
title: Quickstart
permalink: /examples/quickstart
parent: Examples
nav_order: 1
---
# Quickstart
Smallest possible start point you can have using cmkr
```toml
[cmake]
version = "3.15"
[project]
name = "hello-world"
[target.hello-world]
type = "executable"
sources = [ "src/*.cpp" ]
```

@ -6,7 +6,7 @@ nav_order: 0
# Index # Index
[cmkr](https://github.com/build-cpp/cmkr), pronounced "cmaker", is a modern build system based on [CMake](https://cmake.org/) and [TOML](https://toml.io). It was originally created by [Mohammed Alyousef](https://github.com/MoAlyousef). `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: `cmkr` parses `cmake.toml` files and generates a modern, idiomatic `CMakeLists.txt` for you. A minimal example:

@ -0,0 +1,2 @@
bundle install
bundle exec jekyll serve --force_polling --livereload --incremental

20
tests/CMakeLists.txt generated

@ -12,7 +12,7 @@ add_test(
NAME NAME
basic basic
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/basic" basic
COMMAND COMMAND
$<TARGET_FILE:cmkr> $<TARGET_FILE:cmkr>
build build
@ -20,9 +20,9 @@ add_test(
add_test( add_test(
NAME NAME
conditions interface
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/conditions" interface
COMMAND COMMAND
$<TARGET_FILE:cmkr> $<TARGET_FILE:cmkr>
build build
@ -30,9 +30,19 @@ add_test(
add_test( add_test(
NAME NAME
interface fetch-content
WORKING_DIRECTORY WORKING_DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/interface" fetch-content
COMMAND
$<TARGET_FILE:cmkr>
build
)
add_test(
NAME
conditions
WORKING_DIRECTORY
conditions
COMMAND COMMAND
$<TARGET_FILE:cmkr> $<TARGET_FILE:cmkr>
build build

@ -1,9 +1,11 @@
[cmake] # A minimal `cmake.toml` project:
version = "3.5"
[project] [project]
name = "basic" name = "basic"
description = "Minimal example"
[target.basic] [target.basic]
type = "executable" type = "executable"
sources = ["src/basic.cpp"] sources = ["src/basic.cpp"]
# Declares an executable target called `basic` with `src/basic.cpp` as a source file. Equivalent to CMake's [add_executable](https://cmake.org/cmake/help/latest/command/add_executable.html)`(basic src/basic.cpp)`.

@ -1,17 +1,23 @@
[[test]] [[test]]
name = "basic" name = "basic"
command = "$<TARGET_FILE:cmkr>" command = "$<TARGET_FILE:cmkr>"
working-directory = "${CMAKE_CURRENT_LIST_DIR}/basic" working-directory = "basic"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "conditions" name = "interface"
command = "$<TARGET_FILE:cmkr>" command = "$<TARGET_FILE:cmkr>"
working-directory = "${CMAKE_CURRENT_LIST_DIR}/conditions" working-directory = "interface"
arguments = ["build"] arguments = ["build"]
[[test]] [[test]]
name = "interface" name = "fetch-content"
command = "$<TARGET_FILE:cmkr>"
working-directory = "fetch-content"
arguments = ["build"]
[[test]]
name = "conditions"
command = "$<TARGET_FILE:cmkr>" command = "$<TARGET_FILE:cmkr>"
working-directory = "${CMAKE_CURRENT_LIST_DIR}/interface" working-directory = "conditions"
arguments = ["build"] arguments = ["build"]

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

@ -1,5 +1,6 @@
[project] [project]
name = "interface" name = "interface"
description = "Header-only library"
[target.mylib] [target.mylib]
type = "interface" type = "interface"

Loading…
Cancel
Save