mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-29 13:24:48 +00:00
C++: Make it possible to split up the C++ code generated for a .slint file
Add a COMPILATION_UNITS argument to slint_target_sources that defines into how many .cpp files to split up a .slint file. The new default is now one.
This commit is contained in:
parent
12f5343cd8
commit
c25a03d6f7
6 changed files with 160 additions and 31 deletions
|
@ -12,7 +12,7 @@ set_property(CACHE DEFAULT_SLINT_EMBED_RESOURCES PROPERTY STRINGS
|
||||||
|
|
||||||
function(SLINT_TARGET_SOURCES target)
|
function(SLINT_TARGET_SOURCES target)
|
||||||
# Parse the NAMESPACE argument
|
# Parse the NAMESPACE argument
|
||||||
cmake_parse_arguments(SLINT_TARGET_SOURCES "" "NAMESPACE" "LIBRARY_PATHS" ${ARGN})
|
cmake_parse_arguments(SLINT_TARGET_SOURCES "" "NAMESPACE;COMPILATION_UNITS" "LIBRARY_PATHS" ${ARGN})
|
||||||
|
|
||||||
get_target_property(enabled_features Slint::Slint SLINT_ENABLED_FEATURES)
|
get_target_property(enabled_features Slint::Slint SLINT_ENABLED_FEATURES)
|
||||||
if (("EXPERIMENTAL" IN_LIST enabled_features) AND ("SYSTEM_TESTING" IN_LIST enabled_features))
|
if (("EXPERIMENTAL" IN_LIST enabled_features) AND ("SYSTEM_TESTING" IN_LIST enabled_features))
|
||||||
|
@ -30,6 +30,15 @@ function(SLINT_TARGET_SOURCES target)
|
||||||
set(_SLINT_CPP_NAMESPACE_ARG "--cpp-namespace=${SLINT_TARGET_SOURCES_NAMESPACE}")
|
set(_SLINT_CPP_NAMESPACE_ARG "--cpp-namespace=${SLINT_TARGET_SOURCES_NAMESPACE}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (DEFINED SLINT_TARGET_SOURCES_COMPILATION_UNITS)
|
||||||
|
if (NOT SLINT_TARGET_SOURCES_COMPILATION_UNITS MATCHES "^[0-9]+$")
|
||||||
|
message(FATAL_ERROR "Expected number, got '${SLINT_TARGET_SOURCES_COMPILATION_UNITS}' for COMPILATION_UNITS argument")
|
||||||
|
endif()
|
||||||
|
set(compilation_units ${SLINT_TARGET_SOURCES_COMPILATION_UNITS})
|
||||||
|
else()
|
||||||
|
set(compilation_units 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
while (SLINT_TARGET_SOURCES_LIBRARY_PATHS)
|
while (SLINT_TARGET_SOURCES_LIBRARY_PATHS)
|
||||||
list(POP_FRONT SLINT_TARGET_SOURCES_LIBRARY_PATHS name_and_path)
|
list(POP_FRONT SLINT_TARGET_SOURCES_LIBRARY_PATHS name_and_path)
|
||||||
list(APPEND _SLINT_CPP_LIBRARY_PATHS_ARG "-L")
|
list(APPEND _SLINT_CPP_LIBRARY_PATHS_ARG "-L")
|
||||||
|
@ -48,8 +57,15 @@ function(SLINT_TARGET_SOURCES target)
|
||||||
set(scale_factor_target_prop "$<TARGET_PROPERTY:${target},SLINT_SCALE_FACTOR>")
|
set(scale_factor_target_prop "$<TARGET_PROPERTY:${target},SLINT_SCALE_FACTOR>")
|
||||||
set(scale_factor_arg "$<IF:$<STREQUAL:${scale_factor_target_prop},>,,--scale-factor=${scale_factor_target_prop}>")
|
set(scale_factor_arg "$<IF:$<STREQUAL:${scale_factor_target_prop},>,,--scale-factor=${scale_factor_target_prop}>")
|
||||||
|
|
||||||
|
if (compilation_units GREATER 0)
|
||||||
|
foreach(cpp_num RANGE 1 ${compilation_units})
|
||||||
|
list(APPEND cpp_files "${CMAKE_CURRENT_BINARY_DIR}/slint_generated_${_SLINT_BASE_NAME}_${cpp_num}.cpp")
|
||||||
|
endforeach()
|
||||||
|
list(TRANSFORM cpp_files PREPEND "--cpp-file=" OUTPUT_VARIABLE cpp_files_arg)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.h
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.h ${cpp_files}
|
||||||
COMMAND ${SLINT_COMPILER_ENV} $<TARGET_FILE:Slint::slint-compiler> ${_SLINT_ABSOLUTE}
|
COMMAND ${SLINT_COMPILER_ENV} $<TARGET_FILE:Slint::slint-compiler> ${_SLINT_ABSOLUTE}
|
||||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.h
|
-o ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.h
|
||||||
--depfile ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.d
|
--depfile ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.d
|
||||||
|
@ -59,13 +75,14 @@ function(SLINT_TARGET_SOURCES target)
|
||||||
${_SLINT_CPP_NAMESPACE_ARG}
|
${_SLINT_CPP_NAMESPACE_ARG}
|
||||||
${_SLINT_CPP_LIBRARY_PATHS_ARG}
|
${_SLINT_CPP_LIBRARY_PATHS_ARG}
|
||||||
${scale_factor_arg}
|
${scale_factor_arg}
|
||||||
|
${cpp_files_arg}
|
||||||
DEPENDS Slint::slint-compiler ${_SLINT_ABSOLUTE}
|
DEPENDS Slint::slint-compiler ${_SLINT_ABSOLUTE}
|
||||||
COMMENT "Generating ${_SLINT_BASE_NAME}.h"
|
COMMENT "Generating ${_SLINT_BASE_NAME}.h"
|
||||||
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.d
|
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.d
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(${target} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.h)
|
target_sources(${target} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/${_SLINT_BASE_NAME}.h ${cpp_files})
|
||||||
endforeach()
|
endforeach()
|
||||||
target_include_directories(${target} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
target_include_directories(${target} PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
## `slint_target_sources`
|
## `slint_target_sources`
|
||||||
|
|
||||||
```
|
```
|
||||||
slint_target_sources(<target> <files>.... [NAMESPACE namespace] [LIBRARY_PATHS name1=lib1 name2=lib2 ...])
|
slint_target_sources(<target> <files>.... [NAMESPACE namespace] [LIBRARY_PATHS name1=lib1 name2=lib2 ...] [COMPILATION_UNITS num])
|
||||||
```
|
```
|
||||||
|
|
||||||
Use this function to tell cmake about the .slint files of your application, similar to the builtin cmake [target_sources](https://cmake.org/cmake/help/latest/command/target_sources.html) function.
|
Use this function to tell cmake about the .slint files of your application, similar to the builtin cmake [target_sources](https://cmake.org/cmake/help/latest/command/target_sources.html) function.
|
||||||
|
@ -31,6 +31,11 @@ slint_target_sources(my_application the_window.slint
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, a `.slint` file is compiled to a `.h` file for inclusion in your application's business logic code, and a `.cpp` file with code generated by
|
||||||
|
the slint-compier. If you want to speed up compilation of the generated `.cpp` file, then you can pass the `COMPILATION_UNITS` argument with a value greater
|
||||||
|
than 1 to create multiple `.cpp` files. These can be compiled in parallel, which might speed up overall build times. However, splitting the generated code
|
||||||
|
across multiple `.cpp` files decreases the compiler's visibility and thus ability to perform optimizations. You can also pass `COMPILATION_UNITS 0` to generate
|
||||||
|
only one single `.h` file.
|
||||||
|
|
||||||
## Resource Embedding
|
## Resource Embedding
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ pub fn generate(
|
||||||
match format {
|
match format {
|
||||||
#[cfg(feature = "cpp")]
|
#[cfg(feature = "cpp")]
|
||||||
OutputFormat::Cpp(config) => {
|
OutputFormat::Cpp(config) => {
|
||||||
let output = cpp::generate(doc, config, compiler_config);
|
let output = cpp::generate(doc, config, compiler_config)?;
|
||||||
write!(destination, "{}", output)?;
|
write!(destination, "{}", output)?;
|
||||||
}
|
}
|
||||||
#[cfg(feature = "rust")]
|
#[cfg(feature = "rust")]
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
// cSpell:ignore cmath constexpr cstdlib decltype intptr itertools nullptr prepended struc subcomponent uintptr vals
|
// cSpell:ignore cmath constexpr cstdlib decltype intptr itertools nullptr prepended struc subcomponent uintptr vals
|
||||||
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
use std::io::BufWriter;
|
||||||
|
|
||||||
use lyon_path::geom::euclid::approxeq::ApproxEq;
|
use lyon_path::geom::euclid::approxeq::ApproxEq;
|
||||||
|
|
||||||
|
@ -14,6 +15,8 @@ use lyon_path::geom::euclid::approxeq::ApproxEq;
|
||||||
#[derive(Clone, Debug, Default, PartialEq)]
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub namespace: Option<String>,
|
pub namespace: Option<String>,
|
||||||
|
pub cpp_files: Vec<std::path::PathBuf>,
|
||||||
|
pub header_include: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ident(ident: &str) -> String {
|
fn ident(ident: &str) -> String {
|
||||||
|
@ -82,6 +85,7 @@ mod cpp_ast {
|
||||||
///A full C++ file
|
///A full C++ file
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
|
pub is_cpp_file: bool,
|
||||||
pub includes: Vec<String>,
|
pub includes: Vec<String>,
|
||||||
pub after_includes: String,
|
pub after_includes: String,
|
||||||
pub namespace: Option<String>,
|
pub namespace: Option<String>,
|
||||||
|
@ -89,10 +93,65 @@ mod cpp_ast {
|
||||||
pub definitions: Vec<Declaration>,
|
pub definitions: Vec<Declaration>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl File {
|
||||||
|
pub fn split_off_cpp_files(&mut self, header_file_name: String, count: usize) -> Vec<File> {
|
||||||
|
let mut cpp_files = Vec::with_capacity(count);
|
||||||
|
if count == 0 {
|
||||||
|
return cpp_files;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut definitions = Vec::new();
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
while i < self.definitions.len() {
|
||||||
|
if matches!(&self.definitions[i], Declaration::Function(fun) if fun.template_parameters.is_some())
|
||||||
|
{
|
||||||
|
i += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
definitions.push(self.definitions.remove(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any definition in the header file is inline.
|
||||||
|
self.definitions.iter_mut().for_each(|def| match def {
|
||||||
|
Declaration::Function(f) => f.is_inline = true,
|
||||||
|
Declaration::Var(v) => v.is_inline = true,
|
||||||
|
_ => {}
|
||||||
|
});
|
||||||
|
|
||||||
|
let cpp_includes = vec![format!("\"{header_file_name}\"")];
|
||||||
|
|
||||||
|
let chunk_size = definitions.len() / count;
|
||||||
|
cpp_files.extend((0..count - 1).map(|_| File {
|
||||||
|
is_cpp_file: true,
|
||||||
|
includes: cpp_includes.clone(),
|
||||||
|
after_includes: String::new(),
|
||||||
|
namespace: self.namespace.clone(),
|
||||||
|
declarations: Default::default(),
|
||||||
|
definitions: definitions.drain(0..chunk_size).collect(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
cpp_files.push(File {
|
||||||
|
is_cpp_file: true,
|
||||||
|
includes: cpp_includes,
|
||||||
|
after_includes: String::new(),
|
||||||
|
namespace: self.namespace.clone(),
|
||||||
|
declarations: Default::default(),
|
||||||
|
definitions,
|
||||||
|
});
|
||||||
|
|
||||||
|
cpp_files.resize_with(count, Default::default);
|
||||||
|
|
||||||
|
cpp_files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for File {
|
impl Display for File {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||||
writeln!(f, "// This file is auto-generated")?;
|
writeln!(f, "// This file is auto-generated")?;
|
||||||
writeln!(f, "#pragma once")?;
|
if !self.is_cpp_file {
|
||||||
|
writeln!(f, "#pragma once")?;
|
||||||
|
}
|
||||||
for i in &self.includes {
|
for i in &self.includes {
|
||||||
writeln!(f, "#include {}", i)?;
|
writeln!(f, "#include {}", i)?;
|
||||||
}
|
}
|
||||||
|
@ -186,6 +245,7 @@ mod cpp_ast {
|
||||||
statements: f.statements.take(),
|
statements: f.statements.take(),
|
||||||
template_parameters: f.template_parameters.clone(),
|
template_parameters: f.template_parameters.clone(),
|
||||||
constructor_member_initializers: f.constructor_member_initializers.clone(),
|
constructor_member_initializers: f.constructor_member_initializers.clone(),
|
||||||
|
..Default::default()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -223,6 +283,7 @@ mod cpp_ast {
|
||||||
pub is_constructor_or_destructor: bool,
|
pub is_constructor_or_destructor: bool,
|
||||||
pub is_static: bool,
|
pub is_static: bool,
|
||||||
pub is_friend: bool,
|
pub is_friend: bool,
|
||||||
|
pub is_inline: bool,
|
||||||
/// The list of statement instead the function. When None, this is just a function
|
/// The list of statement instead the function. When None, this is just a function
|
||||||
/// declaration without the definition
|
/// declaration without the definition
|
||||||
pub statements: Option<Vec<String>>,
|
pub statements: Option<Vec<String>>,
|
||||||
|
@ -244,8 +305,9 @@ mod cpp_ast {
|
||||||
if self.is_friend {
|
if self.is_friend {
|
||||||
write!(f, "friend ")?;
|
write!(f, "friend ")?;
|
||||||
}
|
}
|
||||||
// all functions are `inline` because we are in a header
|
if self.is_inline {
|
||||||
write!(f, "inline ")?;
|
write!(f, "inline ")?;
|
||||||
|
}
|
||||||
if !self.is_constructor_or_destructor {
|
if !self.is_constructor_or_destructor {
|
||||||
write!(f, "auto ")?;
|
write!(f, "auto ")?;
|
||||||
}
|
}
|
||||||
|
@ -270,6 +332,7 @@ mod cpp_ast {
|
||||||
/// A variable or a member declaration.
|
/// A variable or a member declaration.
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Var {
|
pub struct Var {
|
||||||
|
pub is_inline: bool,
|
||||||
pub ty: String,
|
pub ty: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub array_size: Option<usize>,
|
pub array_size: Option<usize>,
|
||||||
|
@ -541,7 +604,7 @@ pub fn generate(
|
||||||
doc: &Document,
|
doc: &Document,
|
||||||
config: Config,
|
config: Config,
|
||||||
compiler_config: &CompilerConfiguration,
|
compiler_config: &CompilerConfiguration,
|
||||||
) -> impl std::fmt::Display {
|
) -> std::io::Result<impl std::fmt::Display> {
|
||||||
let mut file = File { namespace: config.namespace.clone(), ..Default::default() };
|
let mut file = File { namespace: config.namespace.clone(), ..Default::default() };
|
||||||
|
|
||||||
file.includes.push("<array>".into());
|
file.includes.push("<array>".into());
|
||||||
|
@ -570,10 +633,11 @@ pub fn generate(
|
||||||
init.push('}');
|
init.push('}');
|
||||||
|
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "const inline uint8_t".into(),
|
ty: "const uint8_t".into(),
|
||||||
name: format!("slint_embedded_resource_{}", er.id),
|
name: format!("slint_embedded_resource_{}", er.id),
|
||||||
array_size: Some(data.len()),
|
array_size: Some(data.len()),
|
||||||
init: Some(init),
|
init: Some(init),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
#[cfg(feature = "software-renderer")]
|
#[cfg(feature = "software-renderer")]
|
||||||
|
@ -601,14 +665,15 @@ pub fn generate(
|
||||||
let data = data.iter().map(ToString::to_string).join(", ");
|
let data = data.iter().map(ToString::to_string).join(", ");
|
||||||
let data_name = format!("slint_embedded_resource_{}_data", er.id);
|
let data_name = format!("slint_embedded_resource_{}_data", er.id);
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "inline const uint8_t".into(),
|
ty: "const uint8_t".into(),
|
||||||
name: data_name.clone(),
|
name: data_name.clone(),
|
||||||
array_size: Some(count),
|
array_size: Some(count),
|
||||||
init: Some(format!("{{ {data} }}")),
|
init: Some(format!("{{ {data} }}")),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
let texture_name = format!("slint_embedded_resource_{}_texture", er.id);
|
let texture_name = format!("slint_embedded_resource_{}_texture", er.id);
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "inline const slint::cbindgen_private::types::StaticTexture".into(),
|
ty: "const slint::cbindgen_private::types::StaticTexture".into(),
|
||||||
name: texture_name.clone(),
|
name: texture_name.clone(),
|
||||||
array_size: None,
|
array_size: None,
|
||||||
init: Some(format!(
|
init: Some(format!(
|
||||||
|
@ -619,6 +684,7 @@ pub fn generate(
|
||||||
.index = 0,
|
.index = 0,
|
||||||
}}"
|
}}"
|
||||||
)),
|
)),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
let init = format!("slint::cbindgen_private::types::StaticTextures {{
|
let init = format!("slint::cbindgen_private::types::StaticTextures {{
|
||||||
.size = {{ {width}, {height} }},
|
.size = {{ {width}, {height} }},
|
||||||
|
@ -627,10 +693,11 @@ pub fn generate(
|
||||||
.textures = slint::cbindgen_private::Slice<slint::cbindgen_private::types::StaticTexture>{{ &{texture_name}, 1 }}
|
.textures = slint::cbindgen_private::Slice<slint::cbindgen_private::types::StaticTexture>{{ &{texture_name}, 1 }}
|
||||||
}}");
|
}}");
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "inline const slint::cbindgen_private::types::StaticTextures".into(),
|
ty: "const slint::cbindgen_private::types::StaticTextures".into(),
|
||||||
name: format!("slint_embedded_resource_{}", er.id),
|
name: format!("slint_embedded_resource_{}", er.id),
|
||||||
array_size: None,
|
array_size: None,
|
||||||
init: Some(init),
|
init: Some(init),
|
||||||
|
..Default::default()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "software-renderer")]
|
#[cfg(feature = "software-renderer")]
|
||||||
|
@ -649,19 +716,20 @@ pub fn generate(
|
||||||
let family_name_var = format!("slint_embedded_resource_{}_family_name", er.id);
|
let family_name_var = format!("slint_embedded_resource_{}_family_name", er.id);
|
||||||
let family_name_size = family_name.len();
|
let family_name_size = family_name.len();
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "inline const uint8_t".into(),
|
ty: "const uint8_t".into(),
|
||||||
name: family_name_var.clone(),
|
name: family_name_var.clone(),
|
||||||
array_size: Some(family_name_size),
|
array_size: Some(family_name_size),
|
||||||
init: Some(format!(
|
init: Some(format!(
|
||||||
"{{ {} }}",
|
"{{ {} }}",
|
||||||
family_name.as_bytes().iter().map(ToString::to_string).join(", ")
|
family_name.as_bytes().iter().map(ToString::to_string).join(", ")
|
||||||
)),
|
)),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let charmap_var = format!("slint_embedded_resource_{}_charmap", er.id);
|
let charmap_var = format!("slint_embedded_resource_{}_charmap", er.id);
|
||||||
let charmap_size = character_map.len();
|
let charmap_size = character_map.len();
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "inline const slint::cbindgen_private::CharacterMapEntry".into(),
|
ty: "const slint::cbindgen_private::CharacterMapEntry".into(),
|
||||||
name: charmap_var.clone(),
|
name: charmap_var.clone(),
|
||||||
array_size: Some(charmap_size),
|
array_size: Some(charmap_size),
|
||||||
init: Some(format!(
|
init: Some(format!(
|
||||||
|
@ -674,12 +742,13 @@ pub fn generate(
|
||||||
))
|
))
|
||||||
.join(", ")
|
.join(", ")
|
||||||
)),
|
)),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
for (glyphset_index, glyphset) in glyphs.iter().enumerate() {
|
for (glyphset_index, glyphset) in glyphs.iter().enumerate() {
|
||||||
for (glyph_index, glyph) in glyphset.glyph_data.iter().enumerate() {
|
for (glyph_index, glyph) in glyphset.glyph_data.iter().enumerate() {
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "inline const uint8_t".into(),
|
ty: "const uint8_t".into(),
|
||||||
name: format!(
|
name: format!(
|
||||||
"slint_embedded_resource_{}_gs_{}_gd_{}",
|
"slint_embedded_resource_{}_gs_{}_gd_{}",
|
||||||
er.id, glyphset_index, glyph_index
|
er.id, glyphset_index, glyph_index
|
||||||
|
@ -689,11 +758,12 @@ pub fn generate(
|
||||||
"{{ {} }}",
|
"{{ {} }}",
|
||||||
glyph.data.iter().map(ToString::to_string).join(", ")
|
glyph.data.iter().map(ToString::to_string).join(", ")
|
||||||
)),
|
)),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
file.declarations.push(Declaration::Var(Var{
|
file.declarations.push(Declaration::Var(Var{
|
||||||
ty: "inline const slint::cbindgen_private::BitmapGlyph".into(),
|
ty: "const slint::cbindgen_private::BitmapGlyph".into(),
|
||||||
name: format!("slint_embedded_resource_{}_glyphset_{}", er.id, glyphset_index),
|
name: format!("slint_embedded_resource_{}_glyphset_{}", er.id, glyphset_index),
|
||||||
array_size: Some(glyphset.glyph_data.len()),
|
array_size: Some(glyphset.glyph_data.len()),
|
||||||
init: Some(format!("{{ {} }}", glyphset.glyph_data.iter().enumerate().map(|(glyph_index, glyph)| {
|
init: Some(format!("{{ {} }}", glyphset.glyph_data.iter().enumerate().map(|(glyph_index, glyph)| {
|
||||||
|
@ -703,13 +773,14 @@ pub fn generate(
|
||||||
glyph.data.len()
|
glyph.data.len()
|
||||||
)
|
)
|
||||||
}).join(", \n"))),
|
}).join(", \n"))),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let glyphsets_var = format!("slint_embedded_resource_{}_glyphsets", er.id);
|
let glyphsets_var = format!("slint_embedded_resource_{}_glyphsets", er.id);
|
||||||
let glyphsets_size = glyphs.len();
|
let glyphsets_size = glyphs.len();
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "inline const slint::cbindgen_private::BitmapGlyphs".into(),
|
ty: "const slint::cbindgen_private::BitmapGlyphs".into(),
|
||||||
name: glyphsets_var.clone(),
|
name: glyphsets_var.clone(),
|
||||||
array_size: Some(glyphsets_size),
|
array_size: Some(glyphsets_size),
|
||||||
init: Some(format!(
|
init: Some(format!(
|
||||||
|
@ -726,6 +797,7 @@ pub fn generate(
|
||||||
))
|
))
|
||||||
.join(", \n")
|
.join(", \n")
|
||||||
)),
|
)),
|
||||||
|
..Default::default()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let init = format!(
|
let init = format!(
|
||||||
|
@ -742,10 +814,11 @@ pub fn generate(
|
||||||
);
|
);
|
||||||
|
|
||||||
file.declarations.push(Declaration::Var(Var {
|
file.declarations.push(Declaration::Var(Var {
|
||||||
ty: "inline const slint::cbindgen_private::BitmapFont".into(),
|
ty: "const slint::cbindgen_private::BitmapFont".into(),
|
||||||
name: format!("slint_embedded_resource_{}", er.id),
|
name: format!("slint_embedded_resource_{}", er.id),
|
||||||
array_size: None,
|
array_size: None,
|
||||||
init: Some(init),
|
init: Some(init),
|
||||||
|
..Default::default()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -896,7 +969,14 @@ pub fn generate(
|
||||||
file.includes.push("<cmath>".into());
|
file.includes.push("<cmath>".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
file
|
let cpp_files = file.split_off_cpp_files(config.header_include, config.cpp_files.len());
|
||||||
|
|
||||||
|
for (cpp_file_name, cpp_file) in config.cpp_files.iter().zip(cpp_files) {
|
||||||
|
use std::io::Write;
|
||||||
|
write!(&mut BufWriter::new(std::fs::File::create(&cpp_file_name)?), "{}", cpp_file)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_struct(
|
fn generate_struct(
|
||||||
|
@ -1043,7 +1123,7 @@ fn generate_public_component(
|
||||||
Access::Public,
|
Access::Public,
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
name: "show".into(),
|
name: "show".into(),
|
||||||
signature: "()".into(),
|
signature: "() -> void".into(),
|
||||||
statements: Some(vec!["window().show();".into()]),
|
statements: Some(vec!["window().show();".into()]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|
@ -1053,7 +1133,7 @@ fn generate_public_component(
|
||||||
Access::Public,
|
Access::Public,
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
name: "hide".into(),
|
name: "hide".into(),
|
||||||
signature: "()".into(),
|
signature: "() -> void".into(),
|
||||||
statements: Some(vec!["window().hide();".into()]),
|
statements: Some(vec!["window().hide();".into()]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|
@ -1073,7 +1153,7 @@ fn generate_public_component(
|
||||||
Access::Public,
|
Access::Public,
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
name: "run".into(),
|
name: "run".into(),
|
||||||
signature: "()".into(),
|
signature: "() -> void".into(),
|
||||||
statements: Some(vec![
|
statements: Some(vec![
|
||||||
"show();".into(),
|
"show();".into(),
|
||||||
"slint::run_event_loop();".into(),
|
"slint::run_event_loop();".into(),
|
||||||
|
@ -1493,7 +1573,7 @@ fn generate_item_tree(
|
||||||
));
|
));
|
||||||
|
|
||||||
file.definitions.push(Declaration::Var(Var {
|
file.definitions.push(Declaration::Var(Var {
|
||||||
ty: "inline const slint::private_api::ItemTreeVTable".to_owned(),
|
ty: "const slint::private_api::ItemTreeVTable".to_owned(),
|
||||||
name: format!("{}::static_vtable", item_tree_class_name),
|
name: format!("{}::static_vtable", item_tree_class_name),
|
||||||
init: Some(format!(
|
init: Some(format!(
|
||||||
"{{ visit_children, get_item_ref, get_subtree_range, get_subtree, \
|
"{{ visit_children, get_item_ref, get_subtree_range, get_subtree, \
|
||||||
|
@ -2021,7 +2101,8 @@ fn generate_sub_component(
|
||||||
}
|
}
|
||||||
else_ = "} else ";
|
else_ = "} else ";
|
||||||
}
|
}
|
||||||
let ret = if signature.contains("->") { "{}" } else { "" };
|
let ret =
|
||||||
|
if signature.contains("->") && !signature.contains("-> void") { "{}" } else { "" };
|
||||||
code.push(format!("{else_}return {ret};"));
|
code.push(format!("{else_}return {ret};"));
|
||||||
target_struct.members.push((
|
target_struct.members.push((
|
||||||
field_access,
|
field_access,
|
||||||
|
@ -2108,7 +2189,7 @@ fn generate_sub_component(
|
||||||
|
|
||||||
dispatch_item_function(
|
dispatch_item_function(
|
||||||
"accessibility_action",
|
"accessibility_action",
|
||||||
"(uint32_t index, const slint::cbindgen_private::AccessibilityAction &action) const",
|
"(uint32_t index, const slint::cbindgen_private::AccessibilityAction &action) const -> void",
|
||||||
", action",
|
", action",
|
||||||
accessibility_action_cases,
|
accessibility_action_cases,
|
||||||
);
|
);
|
||||||
|
@ -2527,7 +2608,7 @@ fn generate_public_api_for_properties(
|
||||||
Access::Public,
|
Access::Public,
|
||||||
Declaration::Function(Function {
|
Declaration::Function(Function {
|
||||||
name: format!("set_{}", &prop_ident),
|
name: format!("set_{}", &prop_ident),
|
||||||
signature: format!("(const {} &value) const", &cpp_property_type),
|
signature: format!("(const {} &value) const -> void", &cpp_property_type),
|
||||||
statements: Some(prop_setter),
|
statements: Some(prop_setter),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -20,8 +20,10 @@ pub fn test(testcase: &test_driver_lib::TestCase) -> Result<(), Box<dyn Error>>
|
||||||
|
|
||||||
let mut diag = BuildDiagnostics::default();
|
let mut diag = BuildDiagnostics::default();
|
||||||
let syntax_node = parser::parse(source.clone(), Some(&testcase.absolute_path), None, &mut diag);
|
let syntax_node = parser::parse(source.clone(), Some(&testcase.absolute_path), None, &mut diag);
|
||||||
let output_format =
|
let output_format = generator::OutputFormat::Cpp(generator::cpp::Config {
|
||||||
generator::OutputFormat::Cpp(generator::cpp::Config { namespace: cpp_namespace });
|
namespace: cpp_namespace,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
let mut compiler_config = CompilerConfiguration::new(output_format.clone());
|
let mut compiler_config = CompilerConfiguration::new(output_format.clone());
|
||||||
compiler_config.include_paths = include_paths;
|
compiler_config.include_paths = include_paths;
|
||||||
|
|
|
@ -70,6 +70,10 @@ struct Cli {
|
||||||
/// C++ namespace
|
/// C++ namespace
|
||||||
#[arg(long = "cpp-namespace", name = "C++ namespace")]
|
#[arg(long = "cpp-namespace", name = "C++ namespace")]
|
||||||
cpp_namespace: Option<String>,
|
cpp_namespace: Option<String>,
|
||||||
|
|
||||||
|
/// C++ files to generate (0 for header-only output)
|
||||||
|
#[arg(long = "cpp-file", name = "C++ file to generate", number_of_values = 1, action)]
|
||||||
|
cpp_files: Vec<std::path::PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
|
@ -89,8 +93,28 @@ fn main() -> std::io::Result<()> {
|
||||||
if !matches!(format, generator::OutputFormat::Cpp(..)) {
|
if !matches!(format, generator::OutputFormat::Cpp(..)) {
|
||||||
eprintln!("C++ namespace option was set. Output format will be C++.");
|
eprintln!("C++ namespace option was set. Output format will be C++.");
|
||||||
}
|
}
|
||||||
format =
|
format = generator::OutputFormat::Cpp(generator::cpp::Config {
|
||||||
generator::OutputFormat::Cpp(generator::cpp::Config { namespace: args.cpp_namespace });
|
namespace: args.cpp_namespace,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if !args.cpp_files.is_empty() {
|
||||||
|
match &mut format {
|
||||||
|
generator::OutputFormat::Cpp(ref mut config) => {
|
||||||
|
config.cpp_files = args.cpp_files;
|
||||||
|
|
||||||
|
if args.output == std::path::Path::new("-") {
|
||||||
|
eprintln!("--cpp-file can only be used together with -o");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.header_include = args.output.to_string_lossy().to_string();
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
eprintln!("C++ files option was set but the output format is not C++ - ignorning");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut compiler_config = CompilerConfiguration::new(format.clone());
|
let mut compiler_config = CompilerConfiguration::new(format.clone());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue