new: port the meson, cmake and autotools template bodies to manifests

This commit is contained in:
2026-09-18 15:08:27 +02:00
parent e6f2012835
commit fa399f64b2
14 changed files with 203 additions and 145 deletions
+2
View File
@@ -0,0 +1,2 @@
bin_PROGRAMS = {command}
{command}_SOURCES = hello.c
@@ -0,0 +1,5 @@
AC_INIT([{name}], [{upstream_version}])
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
+8
View File
@@ -0,0 +1,8 @@
#include <stdio.h>
/* Placeholder for {name}, generated by `pkh new`. */
int main(void)
{
printf("Hello from {command}!\n");
return 0;
}
+15 -4
View File
@@ -1,8 +1,13 @@
## The `autotools` template: a C project with a configure.ac built through
## debhelper's auto-detection (dh runs autoreconf itself when it finds
## configure.ac, debhelper >= 10 — no override needed). The logic half —
## the AC_INIT probe, the skeleton bodies and the gettext detection
## (appended to Build-Depends) — lives in src/new/templates/autotools.rs.
## configure.ac, debhelper >= 10 — no override needed). The skeleton bodies
## below are static data (the first source build runs `autoreconf`,
## integrated in the dh sequence, so no generated configure script is
## committed); the logic half — the AC_INIT probe and the GNU-gettext
## detection (appended to Build-Depends) — lives in
## src/new/templates/autotools.rs. hello.c.tpl duplicates the shared C
## skeleton of the other C/C++ template directories (see
## meson/manifest.yml for why).
##
## Schema: see src/new/templates/mod.rs.
@@ -16,4 +21,10 @@ build_depends:
- libtool
architecture: any
rules_dh_line: "dh $@"
files: []
files:
- path: configure.ac
template: configure.ac.tpl
- path: Makefile.am
template: Makefile.am.tpl
- path: hello.c
template: hello.c.tpl
+5
View File
@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project({name} VERSION {upstream_version})
add_executable({command} hello.c)
install(TARGETS {command} RUNTIME DESTINATION bin)
+8
View File
@@ -0,0 +1,8 @@
#include <stdio.h>
/* Placeholder for {name}, generated by `pkh new`. */
int main(void)
{
printf("Hello from {command}!\n");
return 0;
}
+10 -4
View File
@@ -1,7 +1,9 @@
## The `cmake` template: a C/C++ project built with CMake through the
## debhelper cmake buildsystem. The logic half — the project() probe, the
## skeleton bodies and the wizard's pkg-config opt-in (appended to
## Build-Depends) — lives in src/new/templates/cmake.rs.
## debhelper cmake buildsystem. The skeleton bodies below are static data;
## the logic half — the project() probe and the wizard's pkg-config
## opt-in (appended to Build-Depends) — lives in src/new/templates/cmake.rs.
## hello.c.tpl duplicates the shared C skeleton of the other C/C++
## template directories (see meson/manifest.yml for why).
##
## Schema: see src/new/templates/mod.rs.
@@ -13,4 +15,8 @@ build_depends:
- cmake
architecture: any
rules_dh_line: "dh $@ --buildsystem=cmake"
files: []
files:
- path: CMakeLists.txt
template: CMakeLists.txt.tpl
- path: hello.c
template: hello.c.tpl
+8
View File
@@ -0,0 +1,8 @@
#include <stdio.h>
/* Placeholder for {name}, generated by `pkh new`. */
int main(void)
{
printf("Hello from {command}!\n");
return 0;
}
+16 -4
View File
@@ -1,7 +1,15 @@
## The `meson` template: a C/C++ project built with Meson through the
## debhelper meson buildsystem. The logic half — the project() probe, the
## skeleton bodies and the wizard's pkg-config opt-in (appended to
## Build-Depends) — lives in src/new/templates/meson.rs.
## debhelper meson buildsystem. The skeleton bodies below are static data;
## the logic half — the project() probe and the wizard's pkg-config
## opt-in (appended to Build-Depends) — lives in src/new/templates/meson.rs.
##
## hello.c.tpl is deliberately duplicated (byte-identical) across the
## makefile, cmake and autotools template directories: every template
## directory is self-contained — the registry embeds each directory's
## bodies under its own entry — so a shared body would need
## cross-directory references the manifest schema has no machinery for.
## The duplication replaces the Rust hello_c() helper meson.rs used to
## lend cmake.rs and autotools.rs.
##
## Schema: see src/new/templates/mod.rs.
@@ -13,4 +21,8 @@ build_depends:
- meson
architecture: any
rules_dh_line: "dh $@ --buildsystem=meson"
files: []
files:
- path: meson.build
template: meson.build.tpl
- path: hello.c
template: hello.c.tpl
+3
View File
@@ -0,0 +1,3 @@
project('{name}', version: '{upstream_version}', license: '{license}', default_options: ['c_std=c11'])
executable('{command}', 'hello.c', install: true)
+34 -42
View File
@@ -2,17 +2,16 @@
//! debhelper's auto-detection (dh runs `autoreconf` itself when it finds
//! `configure.ac`, debhelper ≥ 10 — no override needed).
//!
//! The metadata is manifest data; the logic half here is the `AC_INIT`
//! probe, the GNU-gettext detection (appending `gettext` to the manifest's
//! Build-Depends) and — until the bodies move into the manifest's `files:`
//! list — the `configure.ac`/`Makefile.am`/`hello.c` skeleton.
//! The metadata and the `configure.ac`/`Makefile.am`/`hello.c` skeleton
//! bodies are manifest data (`data/templates/autotools/manifest.yml`); the
//! logic half here is the `AC_INIT` probe and the GNU-gettext detection
//! (appending `gettext` to the manifest's Build-Depends).
use std::path::Path;
use regex::Regex;
use super::meson::hello_c;
use super::{OutputFile, ProbeResult, TemplateHooks, source_dir_of};
use super::{ProbeResult, TemplateHooks, source_dir_of};
use crate::new::options::NewOptions;
/// The logic half of the autotools template.
@@ -22,35 +21,6 @@ pub struct Hooks;
pub static HOOKS: Hooks = Hooks;
impl TemplateHooks for Hooks {
/// A minimal `configure.ac`, the matching `Makefile.am` and `hello.c`.
/// The first source build runs `autoreconf` (integrated in the dh
/// sequence), so no generated configure script is committed.
fn skeleton_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
vec![
OutputFile::new(
"configure.ac",
format!(
"AC_INIT([{name}], [{version}])\n\
AM_INIT_AUTOMAKE([foreign])\n\
AC_PROG_CC\n\
AC_CONFIG_FILES([Makefile])\n\
AC_OUTPUT\n",
name = opts.name,
version = opts.upstream_version,
),
),
OutputFile::new(
"Makefile.am",
format!(
"bin_PROGRAMS = {command}\n\
{command}_SOURCES = hello.c\n",
command = opts.command,
),
),
hello_c(opts),
]
}
/// A packaged `configure.ac` that sets up GNU gettext (the
/// `AM_GNU_GETTEXT` macro, see [`uses_gettext`]) appends `gettext` to
/// the manifest's Build-Depends.
@@ -149,23 +119,45 @@ mod tests {
assert!(template.rules_extra(&o).is_empty());
assert!(template.debian(&o).is_empty());
// Skeleton (manifest data): configure.ac + Makefile.am + hello.c,
// byte-exact.
let skeleton = template.skeleton(&o);
assert_eq!(skeleton.len(), 3);
let configure = skeleton
.iter()
.find(|f| f.path == "configure.ac")
.expect("configure.ac skeleton");
assert!(
configure
.contents
.starts_with("AC_INIT([mytool], [0.1.0])\n")
assert_eq!(
configure.contents,
"AC_INIT([mytool], [0.1.0])\n\
AM_INIT_AUTOMAKE([foreign])\n\
AC_PROG_CC\n\
AC_CONFIG_FILES([Makefile])\n\
AC_OUTPUT\n"
);
let makefile_am = skeleton
.iter()
.find(|f| f.path == "Makefile.am")
.expect("Makefile.am skeleton");
assert!(makefile_am.contents.contains("bin_PROGRAMS = mytool"));
assert!(makefile_am.contents.contains("mytool_SOURCES = hello.c"));
assert!(skeleton.iter().any(|f| f.path == "hello.c"));
assert_eq!(
makefile_am.contents,
"bin_PROGRAMS = mytool\nmytool_SOURCES = hello.c\n"
);
let hello = skeleton
.iter()
.find(|f| f.path == "hello.c")
.expect("hello.c skeleton");
assert_eq!(
hello.contents,
"#include <stdio.h>\n\
\n\
/* Placeholder for mytool, generated by `pkh new`. */\n\
int main(void)\n\
{\n\
\tprintf(\"Hello from mytool!\\n\");\n\
\treturn 0;\n\
}\n"
);
}
#[test]
+27 -35
View File
@@ -1,16 +1,15 @@
//! The `cmake` template: a C/C++ project built with CMake through the
//! debhelper cmake buildsystem.
//!
//! The metadata is manifest data; the logic half here is the `project()`
//! probe, the wizard's pkg-config opt-in (appended to the manifest's
//! Build-Depends) and — until the bodies move into the manifest's `files:`
//! list — the `CMakeLists.txt`/`hello.c` skeleton.
//! The metadata and the `CMakeLists.txt`/`hello.c` skeleton bodies are
//! manifest data (`data/templates/cmake/manifest.yml`); the logic half
//! here is the `project()` probe and the wizard's pkg-config opt-in
//! (appended to the manifest's Build-Depends).
use std::path::Path;
use regex::Regex;
use super::meson::hello_c;
use super::{ProbeResult, TemplateHooks};
use crate::new::options::NewOptions;
@@ -21,27 +20,6 @@ pub struct Hooks;
pub static HOOKS: Hooks = Hooks;
impl TemplateHooks for Hooks {
/// A minimal `CMakeLists.txt` (project declaration + one installed
/// executable) and the classic `hello.c`.
fn skeleton_files(&self, opts: &NewOptions) -> Vec<super::OutputFile> {
vec![
super::OutputFile::new(
"CMakeLists.txt",
format!(
"cmake_minimum_required(VERSION 3.16)\n\
project({name} VERSION {version})\n\
\n\
add_executable({command} hello.c)\n\
install(TARGETS {command} RUNTIME DESTINATION bin)\n",
name = opts.name,
version = opts.upstream_version,
command = opts.command,
),
),
hello_c(opts),
]
}
/// The wizard's pkg-config opt-in ([`NewOptions::pkg_config`], offered
/// when the project's build file hints at `pkg_check_modules` usage)
/// adds `pkg-config` to the manifest's Build-Depends.
@@ -116,22 +94,36 @@ mod tests {
assert!(template.rules_extra(&o).is_empty());
assert!(template.debian(&o).is_empty());
// Skeleton (manifest data): CMakeLists.txt + hello.c, byte-exact.
let skeleton = template.skeleton(&o);
assert_eq!(skeleton.len(), 2);
let cmakelists = skeleton
.iter()
.find(|f| f.path == "CMakeLists.txt")
.expect("CMakeLists.txt skeleton");
assert!(
cmakelists
.contents
.contains("project(mytool VERSION 0.1.0)")
assert_eq!(
cmakelists.contents,
"cmake_minimum_required(VERSION 3.16)\n\
project(mytool VERSION 0.1.0)\n\
\n\
add_executable(mytool hello.c)\n\
install(TARGETS mytool RUNTIME DESTINATION bin)\n"
);
assert!(
cmakelists
.contents
.contains("add_executable(mytool hello.c)")
let hello = skeleton
.iter()
.find(|f| f.path == "hello.c")
.expect("hello.c skeleton");
assert_eq!(
hello.contents,
"#include <stdio.h>\n\
\n\
/* Placeholder for mytool, generated by `pkh new`. */\n\
int main(void)\n\
{\n\
\tprintf(\"Hello from mytool!\\n\");\n\
\treturn 0;\n\
}\n"
);
assert!(skeleton.iter().any(|f| f.path == "hello.c"));
}
#[test]
+28 -53
View File
@@ -1,17 +1,16 @@
//! The `meson` template: a C/C++ project built with Meson through the
//! debhelper meson buildsystem.
//!
//! The metadata is manifest data; the logic half here is the `project()`
//! probe, the wizard's pkg-config opt-in (appended to the manifest's
//! Build-Depends) and — until the bodies move into the manifest's `files:`
//! list — the `meson.build`/`hello.c` skeleton. [`hello_c`] is the shared
//! placeholder of the C/C++ skeletons.
//! The metadata and the `meson.build`/`hello.c` skeleton bodies are
//! manifest data (`data/templates/meson/manifest.yml`); the logic half
//! here is the `project()` probe and the wizard's pkg-config opt-in
//! (appended to the manifest's Build-Depends).
use std::path::Path;
use regex::Regex;
use super::{OutputFile, ProbeResult, TemplateHooks};
use super::{ProbeResult, TemplateHooks};
use crate::new::options::NewOptions;
/// The logic half of the meson template.
@@ -21,27 +20,6 @@ pub struct Hooks;
pub static HOOKS: Hooks = Hooks;
impl TemplateHooks for Hooks {
/// A minimal `meson.build` (project declaration + one installed
/// executable) and the classic `hello.c`.
fn skeleton_files(&self, opts: &NewOptions) -> Vec<OutputFile> {
vec![
OutputFile::new(
"meson.build",
format!(
"project('{name}', version: '{version}', license: '{license}', \
default_options: ['c_std=c11'])\n\
\n\
executable('{command}', 'hello.c', install: true)\n",
name = opts.name,
version = opts.upstream_version,
license = opts.license.spdx(),
command = opts.command,
),
),
hello_c(opts),
]
}
/// The wizard's pkg-config opt-in ([`NewOptions::pkg_config`], offered
/// when the project's build file hints at `dependency(` usage) adds
/// `pkg-config` to the manifest's Build-Depends.
@@ -69,25 +47,6 @@ impl TemplateHooks for Hooks {
}
}
/// The shared `hello.c` placeholder of the C/C++ skeletons.
pub(super) fn hello_c(opts: &NewOptions) -> OutputFile {
OutputFile::new(
"hello.c",
format!(
"#include <stdio.h>\n\
\n\
/* Placeholder for {name}, generated by `pkh new`. */\n\
int main(void)\n\
{{\n\
\tprintf(\"Hello from {command}!\\n\");\n\
\treturn 0;\n\
}}\n",
name = opts.name,
command = opts.command,
),
)
}
#[cfg(test)]
mod tests {
use super::*;
@@ -131,19 +90,35 @@ mod tests {
assert!(template.rules_extra(&o).is_empty());
assert!(template.debian(&o).is_empty());
// Skeleton (manifest data): meson.build + hello.c, byte-exact.
let skeleton = template.skeleton(&o);
assert_eq!(skeleton.len(), 2);
let meson_build = skeleton
.iter()
.find(|f| f.path == "meson.build")
.expect("meson.build skeleton");
assert!(meson_build.contents.contains("project('mytool'"));
assert!(meson_build.contents.contains("version: '0.1.0'"));
assert!(
meson_build
.contents
.contains("executable('mytool', 'hello.c', install: true)")
assert_eq!(
meson_build.contents,
"project('mytool', version: '0.1.0', license: 'MIT', \
default_options: ['c_std=c11'])\n\
\n\
executable('mytool', 'hello.c', install: true)\n"
);
let hello = skeleton
.iter()
.find(|f| f.path == "hello.c")
.expect("hello.c skeleton");
assert_eq!(
hello.contents,
"#include <stdio.h>\n\
\n\
/* Placeholder for mytool, generated by `pkh new`. */\n\
int main(void)\n\
{\n\
\tprintf(\"Hello from mytool!\\n\");\n\
\treturn 0;\n\
}\n"
);
assert!(skeleton.iter().any(|f| f.path == "hello.c"));
}
#[test]
+34 -3
View File
@@ -362,19 +362,50 @@ static TEMPLATE_SOURCES: &[TemplateSources] = &[
TemplateSources {
id: TemplateId::MESON,
manifest: include_str!("../../../data/templates/meson/manifest.yml"),
tpls: &[],
tpls: &[
(
"meson.build.tpl",
include_str!("../../../data/templates/meson/meson.build.tpl"),
),
(
"hello.c.tpl",
include_str!("../../../data/templates/meson/hello.c.tpl"),
),
],
hooks: Some(&meson::HOOKS),
},
TemplateSources {
id: TemplateId::CMAKE,
manifest: include_str!("../../../data/templates/cmake/manifest.yml"),
tpls: &[],
tpls: &[
(
"CMakeLists.txt.tpl",
include_str!("../../../data/templates/cmake/CMakeLists.txt.tpl"),
),
(
"hello.c.tpl",
include_str!("../../../data/templates/cmake/hello.c.tpl"),
),
],
hooks: Some(&cmake::HOOKS),
},
TemplateSources {
id: TemplateId::AUTOTOOLS,
manifest: include_str!("../../../data/templates/autotools/manifest.yml"),
tpls: &[],
tpls: &[
(
"configure.ac.tpl",
include_str!("../../../data/templates/autotools/configure.ac.tpl"),
),
(
"Makefile.am.tpl",
include_str!("../../../data/templates/autotools/Makefile.am.tpl"),
),
(
"hello.c.tpl",
include_str!("../../../data/templates/autotools/hello.c.tpl"),
),
],
hooks: Some(&autotools::HOOKS),
},
TemplateSources {