Skip to content

Commit 306bb3d

Browse files
committed
Automatically generate documentation from tests
1 parent acd3688 commit 306bb3d

22 files changed

+273
-86
lines changed

CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmake.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ version = "0.1.4"
77
description = "CMakeLists generator from TOML"
88
languages = ["CXX"]
99
subdirs = ["third_party", "tests"]
10+
include-after = ["cmake/generate_documentation.cmake"]
11+
12+
[target.cmkr_generate_documentation]
13+
type = "interface"
14+
cmake-after = """
15+
generate_documentation()
16+
"""
1017

1118
[target.cmkr]
1219
type = "executable"

cmake/cmkr.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ else()
8383
"-B${CMKR_DIRECTORY}/build"
8484
"-DCMAKE_BUILD_TYPE=Release"
8585
"-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}"
86+
"-DCMKR_GENERATE_DOCUMENTATION=OFF"
8687
)
8788
cmkr_exec("${CMAKE_COMMAND}"
8889
--build "${CMKR_DIRECTORY}/build"

cmake/example.md.in

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
# Automatically generated from tests/@EXAMPLE_PERMALINK@/cmake.toml - DO NOT EDIT
3+
layout: default
4+
title: @EXAMPLE_TITLE@
5+
permalink: /examples/@EXAMPLE_PERMALINK@
6+
parent: Examples
7+
nav_order: @EXAMPLE_INDEX@
8+
---
9+
10+
# @EXAMPLE_TITLE@
11+
12+
@EXAMPLE_HEADER@
13+
14+
```toml
15+
@EXAMPLE_TOML@
16+
```
17+
18+
@EXAMPLE_FOOTER@
19+
20+
<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>

cmake/generate_documentation.cmake

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
option(CMKR_GENERATE_DOCUMENTATION "Generate cmkr documentation" ${CMKR_ROOT_PROJECT})
2+
set(CMKR_TESTS "" CACHE INTERNAL "List of test directories in the order declared in tests/cmake.toml")
3+
4+
if(CMKR_GENERATE_DOCUMENTATION)
5+
# Hook the add_test function to capture the tests in the order declared in tests/cmake.toml
6+
function(add_test)
7+
cmake_parse_arguments(TEST "" "WORKING_DIRECTORY" "" ${ARGN})
8+
list(APPEND CMKR_TESTS "${TEST_WORKING_DIRECTORY}")
9+
set(CMKR_TESTS "${CMKR_TESTS}" CACHE INTERNAL "")
10+
_add_test(${test} ${ARGN})
11+
endfunction()
12+
endif()
13+
14+
function(generate_documentation)
15+
if(CMKR_GENERATE_DOCUMENTATION)
16+
message(STATUS "[cmkr] Generating documentation...")
17+
18+
# Delete previously generated examples
19+
set(example_folder "${PROJECT_SOURCE_DIR}/docs/examples")
20+
file(GLOB example_files "${example_folder}/*.md")
21+
list(REMOVE_ITEM example_files "${example_folder}/index.md")
22+
file(REMOVE ${example_files})
23+
24+
message(DEBUG "[cmkr] Test directories: ${CMKR_TESTS}")
25+
set(test_index 0)
26+
foreach(test_dir ${CMKR_TESTS})
27+
set(test_name "${test_dir}")
28+
set(test_dir "${PROJECT_SOURCE_DIR}/tests/${test_dir}")
29+
set(test_toml "${test_dir}/cmake.toml")
30+
if(IS_DIRECTORY "${test_dir}" AND EXISTS "${test_toml}")
31+
message(DEBUG "[cmkr] Generating documentation for: ${test_toml} (index: ${test_index})")
32+
33+
# Set template variables
34+
set(EXAMPLE_PERMALINK "${test_name}")
35+
set(EXAMPLE_INDEX ${test_index})
36+
math(EXPR test_index "${test_index}+1")
37+
38+
# Read cmake.toml file
39+
file(READ "${test_toml}" test_contents NO_HEX_CONVERSION)
40+
string(LENGTH "${test_contents}" toml_length)
41+
42+
# Extract header text
43+
string(REGEX MATCH "^(\n*(#[^\n]+\n)+\n*)" EXAMPLE_HEADER "${test_contents}")
44+
string(LENGTH "${EXAMPLE_HEADER}" header_length)
45+
string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER)
46+
string(REGEX REPLACE "\n# ?" "\n" EXAMPLE_HEADER "\n${EXAMPLE_HEADER}")
47+
string(STRIP "${EXAMPLE_HEADER}" EXAMPLE_HEADER)
48+
49+
# Extract footer text
50+
string(REGEX MATCH "(((#[^\n]+)(\n+|$))+)$" EXAMPLE_FOOTER "${test_contents}")
51+
string(LENGTH "${EXAMPLE_FOOTER}" footer_length)
52+
string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER)
53+
string(REGEX REPLACE "\n# ?" "\n" EXAMPLE_FOOTER "\n${EXAMPLE_FOOTER}")
54+
string(STRIP "${EXAMPLE_FOOTER}" EXAMPLE_FOOTER)
55+
56+
# Extract toml body
57+
math(EXPR toml_length "${toml_length}-${header_length}-${footer_length}")
58+
string(SUBSTRING "${test_contents}" ${header_length} ${toml_length} EXAMPLE_TOML)
59+
string(STRIP "${EXAMPLE_TOML}" EXAMPLE_TOML)
60+
61+
# Extract title from description
62+
if("${EXAMPLE_TOML}" MATCHES "description *= *\"([^\"]+)\"")
63+
set(EXAMPLE_TITLE "${CMAKE_MATCH_1}")
64+
65+
# Generate documentation markdown page
66+
configure_file("${PROJECT_SOURCE_DIR}/cmake/example.md.in" "${example_folder}/${EXAMPLE_PERMALINK}.md" @ONLY NEWLINE_STYLE LF)
67+
else()
68+
message(DEBUG "[cmkr] Skipping documentation generation for ${test_name} because description is missing")
69+
endif()
70+
endif()
71+
endforeach()
72+
endif()
73+
endfunction()

docs/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
_site
1+
_site/
2+
.jekyll-metadata

docs/examples/basic.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
# Automatically generated from tests/basic/cmake.toml - DO NOT EDIT
3+
layout: default
4+
title: Minimal example
5+
permalink: /examples/basic
6+
parent: Examples
7+
nav_order: 0
8+
---
9+
10+
# Minimal example
11+
12+
A minimal `cmake.toml` project:
13+
14+
```toml
15+
[project]
16+
name = "basic"
17+
description = "Minimal example"
18+
19+
[target.basic]
20+
type = "executable"
21+
sources = ["src/basic.cpp"]
22+
```
23+
24+
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)`.
25+
26+
<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>

docs/examples/cpp-version-change.markdown

Lines changed: 0 additions & 17 deletions
This file was deleted.

docs/examples/fetch-content.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
# Automatically generated from tests/fetch-content/cmake.toml - DO NOT EDIT
3+
layout: default
4+
title: Fetching from git
5+
permalink: /examples/fetch-content
6+
parent: Examples
7+
nav_order: 2
8+
---
9+
10+
# Fetching from git
11+
12+
Downloads [fmt v7.1.3](https://fmt.dev/7.1.3/) from [GitHub](https://github.com) and links an `example` target to it:
13+
14+
```toml
15+
[project]
16+
name = "fetch-content"
17+
description = "Fetching from git"
18+
19+
[fetch-content]
20+
fmt = { git = "https://github.com/fmtlib/fmt", tag = "7.1.3" }
21+
22+
[target.example]
23+
type = "executable"
24+
sources = ["src/main.cpp"]
25+
link-libraries = ["fmt::fmt"]
26+
```
27+
28+
This is equivalent to calling CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html).
29+
30+
<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>

docs/examples/import-from-git.markdown

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)