mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-26 11:59:29 +00:00
Make C++ documentation generation an xtask
Tear it out of the CMakeLists.txt and instead run it via cargo xtask cppdocs This allows the build_and_test step in the CI to only run cmake for the library/header related bits and the docs_and_demos step to only generate docs and not require a full host build of the library (as cargo xtask cmake would otherwise do).
This commit is contained in:
parent
704644c752
commit
65ff715fbc
6 changed files with 152 additions and 46 deletions
12
.github/workflows/rust.yaml
vendored
12
.github/workflows/rust.yaml
vendored
|
@ -85,10 +85,6 @@ jobs:
|
|||
with:
|
||||
command: test
|
||||
args: --verbose
|
||||
- name: Install doxygen
|
||||
if: matrix.os == 'ubuntu-20.04'
|
||||
run: sudo apt-get install doxygen
|
||||
- uses: dschep/install-pipenv-action@v1
|
||||
- name: Prepare cmake module
|
||||
run: cargo xtask cmake --prefix $HOME/sixtyfps_install --install
|
||||
- name: C++ Test
|
||||
|
@ -147,8 +143,8 @@ jobs:
|
|||
- name: Install doxygen
|
||||
run: sudo apt-get install doxygen
|
||||
- uses: dschep/install-pipenv-action@v1
|
||||
- name: Prepare cmake module (builds docs)
|
||||
run: cargo xtask cmake
|
||||
- name: Build Cpp docs
|
||||
run: cargo xtask cppdocs
|
||||
- name: Install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
- name: Setup Node.js
|
||||
|
@ -183,7 +179,7 @@ jobs:
|
|||
examples/printerdemo/wasm/dist/
|
||||
api/sixtyfps-wasm-interpreter/pkg/
|
||||
target/doc
|
||||
target/debug/docs/html
|
||||
target/cppdocs/html
|
||||
- name: Clean cache # Otherwise the cache is much too big
|
||||
run: |
|
||||
du -hs target
|
||||
|
@ -223,7 +219,7 @@ jobs:
|
|||
rm -rf docs
|
||||
mkdir -p docs
|
||||
mkdir -p docs/cpp
|
||||
cp -a ../target/debug/docs/html/* docs/cpp/
|
||||
cp -a ../target/cppdocs/html/* docs/cpp/
|
||||
mkdir -p docs/rust
|
||||
cp -a ../target/doc/* docs/rust/
|
||||
git add docs
|
||||
|
|
|
@ -81,21 +81,3 @@ install(FILES
|
|||
"${CMAKE_CURRENT_BINARY_DIR}/lib/cmake/SixtyFPS/SixtyFPSConfigVersion.cmake"
|
||||
DESTINATION lib/cmake/SixtyFPS
|
||||
)
|
||||
|
||||
find_package(Doxygen)
|
||||
find_program(PipEnv pipenv)
|
||||
if (DOXYGEN_FOUND)
|
||||
if (PipEnv)
|
||||
configure_file(../docs/conf.py.in docs/conf.py)
|
||||
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/../docs/index.rst ${CMAKE_CURRENT_BINARY_DIR}/docs/index.rst SYMBOLIC)
|
||||
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/../README.md ${CMAKE_CURRENT_BINARY_DIR}/docs/README.md SYMBOLIC)
|
||||
get_filename_component(markdown_docs_source ../../../docs ABSOLUTE)
|
||||
file(CREATE_LINK ${markdown_docs_source} ${CMAKE_CURRENT_BINARY_DIR}/docs/markdown SYMBOLIC)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E env PIPENV_PIPFILE=${CMAKE_CURRENT_SOURCE_DIR}/../docs/Pipfile ${PipEnv} install)
|
||||
add_custom_target(docs ALL COMMAND ${CMAKE_COMMAND} -E env PIPENV_PIPFILE=${CMAKE_CURRENT_SOURCE_DIR}/../docs/Pipfile ${PipEnv} run sphinx-build ./docs ./docs/html)
|
||||
else()
|
||||
message("Pipenv not found, not building documentation")
|
||||
endif()
|
||||
else()
|
||||
message("Doxygen not found, not building documentation")
|
||||
endif()
|
||||
|
|
|
@ -44,7 +44,7 @@ exhale_args = {
|
|||
"doxygenStripFromPath": "..",
|
||||
"createTreeView": True,
|
||||
"exhaleExecutesDoxygen": True,
|
||||
"exhaleDoxygenStdin": '''INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../include
|
||||
"exhaleDoxygenStdin": '''INPUT = ../../api/sixtyfps-cpp/include
|
||||
EXCLUDE_SYMBOLS = sixtyfps::cbindgen_private* sixtyfps::private_api*'''
|
||||
}
|
||||
|
107
xtask/src/cppdocs.rs
Normal file
107
xtask/src/cppdocs.rs
Normal file
|
@ -0,0 +1,107 @@
|
|||
/* LICENSE BEGIN
|
||||
This file is part of the SixtyFPS Project -- https://sixtyfps.io
|
||||
Copyright (c) 2020 Olivier Goffart <olivier.goffart@sixtyfps.io>
|
||||
Copyright (c) 2020 Simon Hausmann <simon.hausmann@sixtyfps.io>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-only
|
||||
This file is also available under commercial licensing terms.
|
||||
Please contact info@sixtyfps.io for more information.
|
||||
LICENSE END */
|
||||
use anyhow::{Context, Result};
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
|
||||
if dst.as_ref().exists() {
|
||||
std::fs::remove_file(dst.as_ref()).context("Error removing old symlink")?;
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
return std::os::windows::fs::symlink_file(&src, &dst).context("Error creating symlink");
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
return std::os::unix::fs::symlink(&src, &dst).context(format!(
|
||||
"Error creating symlink from {} to {}",
|
||||
src.as_ref().display(),
|
||||
dst.as_ref().display()
|
||||
));
|
||||
}
|
||||
|
||||
fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
|
||||
if dst.as_ref().exists() {
|
||||
std::fs::remove_file(dst.as_ref()).context("Error removing old symlink")?;
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
return std::os::windows::fs::symlink_dir(&src, &dst).context("Error creating symlink");
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
return std::os::unix::fs::symlink(&src, &dst).context(format!(
|
||||
"Error creating symlink from {} to {}",
|
||||
src.as_ref().display(),
|
||||
dst.as_ref().display()
|
||||
));
|
||||
}
|
||||
|
||||
fn symlink_files_in_dir<S: AsRef<Path>, T: AsRef<Path>, TS: AsRef<Path>>(
|
||||
src: S,
|
||||
target: T,
|
||||
target_to_source: TS,
|
||||
) -> Result<()> {
|
||||
for entry in std::fs::read_dir(src.as_ref()).context("Error reading docs source directory")? {
|
||||
let entry = entry.context("Error reading directory entry")?;
|
||||
let path = entry.path();
|
||||
if path.is_file() {
|
||||
let file_name = path.file_name().unwrap();
|
||||
let symlink_source = target_to_source.as_ref().to_path_buf().join(&file_name);
|
||||
let symlink_target = target.as_ref().to_path_buf().join(path.file_name().unwrap());
|
||||
symlink_file(symlink_source, symlink_target)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn generate() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let root = super::root_dir()?;
|
||||
|
||||
let docs_source_dir = root.join("api/sixtyfps-cpp");
|
||||
let docs_build_dir = root.join("target/cppdocs");
|
||||
|
||||
std::fs::create_dir_all(docs_build_dir.as_path()).context("Error creating docs build dir")?;
|
||||
|
||||
symlink_files_in_dir(
|
||||
docs_source_dir.join("docs"),
|
||||
&docs_build_dir,
|
||||
["..", "..", "api", "sixtyfps-cpp", "docs"].iter().collect::<PathBuf>(),
|
||||
)
|
||||
.context("Error symlinking files from docs source to docs build dir")?;
|
||||
|
||||
symlink_dir(["..", "..", "docs"].iter().collect::<PathBuf>(), docs_build_dir.join("markdown"))?;
|
||||
|
||||
symlink_file(
|
||||
["..", "..", "api", "sixtyfps-cpp", "README.md"].iter().collect::<PathBuf>(),
|
||||
docs_build_dir.join("README.md"),
|
||||
)?;
|
||||
|
||||
let pip_env =
|
||||
vec![(OsString::from("PIPENV_PIPFILE"), docs_source_dir.join("docs/Pipfile").to_owned())];
|
||||
|
||||
println!("Running pipenv install");
|
||||
|
||||
super::run_command("pipenv", &["install"], pip_env.clone())
|
||||
.context("Error running pipenv install")?;
|
||||
|
||||
println!("Running sphinx-build");
|
||||
|
||||
let output = super::run_command(
|
||||
"pipenv",
|
||||
&[
|
||||
"run",
|
||||
"sphinx-build",
|
||||
docs_build_dir.to_str().unwrap(),
|
||||
docs_build_dir.join("html").to_str().unwrap(),
|
||||
],
|
||||
pip_env.clone(),
|
||||
)
|
||||
.context("Error running pipenv install")?;
|
||||
|
||||
println!("{}", String::from_utf8_lossy(&output));
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -11,7 +11,7 @@ use anyhow::Context;
|
|||
use anyhow::Result;
|
||||
use lazy_static::lazy_static;
|
||||
use std::str::FromStr;
|
||||
use std::{path::Path, path::PathBuf, process::Command};
|
||||
use std::{path::Path, path::PathBuf};
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -208,7 +208,7 @@ lazy_static! {
|
|||
(".*\\.gitignore$", LicenseLocation::NoLicense),
|
||||
("\\.clang-format$", LicenseLocation::NoLicense),
|
||||
("^api/sixtyfps-cpp/docs/Pipfile$", LicenseLocation::NoLicense),
|
||||
("^api/sixtyfps-cpp/docs/conf.py.in$", LicenseLocation::NoLicense),
|
||||
("^api/sixtyfps-cpp/docs/conf.py$", LicenseLocation::NoLicense),
|
||||
("\\.cargo/config$", LicenseLocation::Tag(LicenseTagStyle::shell_comment_style())),
|
||||
(
|
||||
"\\.github/workflows/rust.yaml$",
|
||||
|
@ -264,25 +264,13 @@ const EXPECTED_HEADER: LicenseHeader<'static> = LicenseHeader(&[
|
|||
const EXPECTED_HOMEPAGE: &str = "https://sixtyfps.io";
|
||||
const EXPECTED_REPOSITORY: &str = "https://github.com/sixtyfpsui/sixtyfps";
|
||||
|
||||
fn run_command(program: &str, args: &[&str]) -> Result<Vec<u8>> {
|
||||
let cmdline = || format!("{} {}", program, args.join(" "));
|
||||
let output = Command::new(program)
|
||||
.args(args)
|
||||
.current_dir(super::root_dir()?)
|
||||
.output()
|
||||
.with_context(|| format!("Error launching {}", cmdline()))?;
|
||||
let code =
|
||||
output.status.code().with_context(|| format!("Command received signal: {}", cmdline()))?;
|
||||
if code != 0 {
|
||||
Err(anyhow::anyhow!("Command {} exited with non-zero status: {}", cmdline(), code))
|
||||
} else {
|
||||
Ok(output.stdout)
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_files() -> Result<Vec<PathBuf>> {
|
||||
let root = super::root_dir()?;
|
||||
let ls_files_output = run_command("git", &["ls-files", "-z"])?;
|
||||
let ls_files_output = super::run_command(
|
||||
"git",
|
||||
&["ls-files", "-z"],
|
||||
std::iter::empty::<(std::ffi::OsString, std::ffi::OsString)>(),
|
||||
)?;
|
||||
let mut files = Vec::new();
|
||||
for path in ls_files_output.split(|ch| *ch == 0) {
|
||||
if path.is_empty() {
|
||||
|
|
|
@ -7,11 +7,13 @@
|
|||
This file is also available under commercial licensing terms.
|
||||
Please contact info@sixtyfps.io for more information.
|
||||
LICENSE END */
|
||||
use anyhow::Context;
|
||||
use std::error::Error;
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
|
||||
mod cmake;
|
||||
mod cppdocs;
|
||||
mod license_headers_check;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
|
@ -20,6 +22,8 @@ pub enum TaskCommand {
|
|||
CMake(cmake::CMakeCommand),
|
||||
#[structopt(name = "check_license_headers")]
|
||||
CheckLicenseHeaders(license_headers_check::LicenseHeaderCheck),
|
||||
#[structopt(name = "cppdocs")]
|
||||
CppDocs,
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
|
@ -35,10 +39,39 @@ pub fn root_dir() -> anyhow::Result<PathBuf> {
|
|||
Ok(root)
|
||||
}
|
||||
|
||||
fn run_command<I, K, V>(program: &str, args: &[&str], env: I) -> anyhow::Result<Vec<u8>>
|
||||
where
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
K: AsRef<std::ffi::OsStr>,
|
||||
V: AsRef<std::ffi::OsStr>,
|
||||
{
|
||||
let cmdline = || format!("{} {}", program, args.join(" "));
|
||||
let output = std::process::Command::new(program)
|
||||
.args(args)
|
||||
.current_dir(root_dir()?)
|
||||
.envs(env)
|
||||
.output()
|
||||
.with_context(|| format!("Error launching {}", cmdline()))?;
|
||||
let code =
|
||||
output.status.code().with_context(|| format!("Command received signal: {}", cmdline()))?;
|
||||
if code != 0 {
|
||||
Err(anyhow::anyhow!(
|
||||
"Command {} exited with non-zero status: {}\nstdout: {}\nstderr: {}",
|
||||
cmdline(),
|
||||
code,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
))
|
||||
} else {
|
||||
Ok(output.stdout)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
match ApplicationArguments::from_args().command {
|
||||
TaskCommand::CMake(cmd) => cmd.build_cmake()?,
|
||||
TaskCommand::CheckLicenseHeaders(cmd) => cmd.check_license_headers()?,
|
||||
TaskCommand::CppDocs => cppdocs::generate()?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue