Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/markdown/snippets/embed_directories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## BuildTarget now has an `embed_directories` keyword argument

This provides an include_directories like path for `--embed`.
8 changes: 8 additions & 0 deletions docs/yaml/functions/_build_target_base.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ kwargs:

These may only be static sources.

embed_directories:
type: array[inc | str]
since: 1.13.0
description: |
one or more objects created with the [[include_directories]] function, or
strings, which will be implicitly convert to [[@inc]] objects, that is
used for the #embed.

gui_app:
type: bool
deprecated: 0.56.0
Expand Down
6 changes: 6 additions & 0 deletions mesonbuild/backend/ninjabackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -3176,6 +3176,12 @@ def _generate_single_compile_target_args(self, target: build.BuildTarget, compil
commands += bargs
for d in i.extra_build_dirs:
commands += compiler.get_include_args(d, i.is_system)

# Add any embed search dir arguments
for i in target.embed_dirs:
for incdir in i.rel_string_list(self.build_to_src, self.build_dir):
commands.extend(compiler.get_embed_args(incdir))

# Add per-target compile args, f.ex, `c_args : ['-DFOO']`. We set these
# near the end since these are supposed to override everything else.
commands += self.escape_extra_args(target.get_extra_args(compiler.get_language()))
Expand Down
3 changes: 3 additions & 0 deletions mesonbuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class BuildTargetKeywordArguments(TypedDict, total=False):
d_unittest: bool
dependencies: T.List[dependencies.Dependency]
depend_files: T.List[File]
embed_directories: list[IncludeDirs]
extra_files: T.List[File]
gnu_symbol_visibility: Literal['default', 'internal', 'hidden', 'protected', 'inlineshidden', '']
implicit_include_directories: bool
Expand Down Expand Up @@ -819,6 +820,7 @@ def __init__(
self.structured_sources = structured_sources
self.external_deps: T.List[dependencies.Dependency] = []
self.include_dirs: T.List['IncludeDirs'] = []
self.embed_dirs = kwargs['embed_directories'].copy()
self.link_language: T.Optional[Language] = kwargs.get('link_language')
self.link_targets: T.List[LinkableTargetTypes] = []
self.link_whole_targets: T.List[StaticTargetTypes] = []
Expand Down Expand Up @@ -1543,6 +1545,7 @@ def add_deps(self, deps: T.List[dependencies.Dependency]) -> None:
self.process_sourcelist(dep.sources)
self.extra_files.extend(f for f in dep.extra_files if f not in self.extra_files)
self.add_include_dirs(dep.include_directories, dep.get_include_type())
self.embed_dirs.extend(dep.embed_directories)
self.objects.extend(dep.objects)
self.link_targets.extend(dep.libraries)
self.link_whole_targets.extend(dep.whole_libraries)
Expand Down
4 changes: 4 additions & 0 deletions mesonbuild/compilers/c.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,10 @@ def get_option_link_args(self, target: 'BuildTarget', subproject: T.Optional[str
def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
return ['-fpch-preprocess', '-include', os.path.basename(header)]

def get_embed_args(self, path: str) -> list[str]:
# Requires C23 or C++26 standard and GCC 15
return [f'--embed-dir={path}']


class PGICCompiler(PGICompiler, CCompiler):
def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
Expand Down
4 changes: 4 additions & 0 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1704,3 +1704,7 @@ def get_crt_static(self) -> bool:
def get_target_libdir(self) -> str:
"""Where is the libdir for the current machine located"""
raise EnvironmentException(f'{self.get_id()} does not support Rust target libdir')

def get_embed_args(self, path: str) -> list[str]:
"""Format arguments for C and C++ #embed statements."""
raise EnvironmentException(f'{self.get_id()} does not support embed search paths')
4 changes: 4 additions & 0 deletions mesonbuild/compilers/cpp.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,10 @@ def get_pch_use_args(self, pch_dir: str, header: str) -> T.List[str]:
def get_cpp_modules_args(self) -> T.List[str]:
return ['-fmodules', '-fmodules-ts']

def get_embed_args(self, path: str) -> list[str]:
# Requires C23 or C++26 standard and GCC 15
return [f'--embed-dir={path}']


class PGICPPCompiler(PGICompiler, CPPCompiler):
def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_machine: MachineChoice,
Expand Down
5 changes: 5 additions & 0 deletions mesonbuild/compilers/mixins/clang.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,11 @@ def get_lto_link_args(self, *, target: T.Optional[BuildTarget] = None, threads:
args.append(f'-flto-jobs={threads}')
return args

def get_embed_args(self, path: str) -> list[str]:
# Requires C23 or C++26 standard and Clang 19
# Is not currently supported by AppleClang
return [f'--embed-dir={path}']


class ClangCStds(CompilerMixinBase):

Expand Down
5 changes: 4 additions & 1 deletion mesonbuild/dependencies/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ class InternalDependency(Dependency):
type_name = DependencyTypeName('internal')

def __init__(self, version: str, incdirs: T.Optional[T.List['IncludeDirs']] = None,
embed_dirs: list[IncludeDirs] | None = None,
compile_args: T.Optional[T.List[str]] = None,
link_args: T.Optional[T.List[str]] = None,
libraries: T.Optional[T.List[LinkableTargetTypes]] = None,
Expand All @@ -322,6 +323,7 @@ def __init__(self, version: str, incdirs: T.Optional[T.List['IncludeDirs']] = No
self.version = version
self.is_found = True
self.include_directories = incdirs or []
self.embed_directories = embed_dirs or []
self.compile_args = compile_args or []
self.link_args = link_args or []
self.libraries = libraries or []
Expand Down Expand Up @@ -370,11 +372,12 @@ def get_partial_dependency(self, *, compile_args: bool = False,
final_sources = self.sources.copy() if sources else []
final_extra_files = self.extra_files.copy() if extra_files else []
final_includes = self.include_directories.copy() if includes else []
final_embed = self.embed_directories.copy() if includes else []
final_deps = [d.get_partial_dependency(
compile_args=compile_args, link_args=link_args, links=links,
includes=includes, sources=sources) for d in self.ext_deps]
return type(self)(
self.version, final_includes, final_compile_args,
self.version, final_includes, final_embed, final_compile_args,
final_link_args, final_libraries, final_whole_libraries,
final_sources, final_extra_files, final_deps, self.variables, [], [], [], self.name)

Expand Down
6 changes: 5 additions & 1 deletion mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
ENV_KW,
ENV_METHOD_KW,
ENV_SEPARATOR_KW,
EMBED_DIRECTORIES,
INCLUDE_DIRECTORIES,
INSTALL_KW,
INSTALL_DIR_KW,
Expand Down Expand Up @@ -725,6 +726,7 @@ def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwa
KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]),
INCLUDE_DIRECTORIES.evolve(name='d_import_dirs', since='0.62.0'),
D_MODULE_VERSIONS_KW.evolve(since='0.62.0'),
EMBED_DIRECTORIES,
LINK_ARGS_KW,
DEPENDENCIES_KW,
INCLUDE_DIRECTORIES.evolve(since_values={ContainerTypeInfo(list, str): '0.50.0'}),
Expand All @@ -740,6 +742,7 @@ def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var]
kwargs: kwtypes.FuncDeclareDependency) -> dependencies.Dependency:
deps = kwargs['dependencies']
incs = self.extract_incdirs(kwargs['include_directories'])
embed_directories = self.extract_incdirs(kwargs['embed_directories'])
libs = kwargs['link_with']
libs_whole = kwargs['link_whole']
objects = kwargs['objects']
Expand All @@ -766,7 +769,7 @@ def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var]
and os.path.isdir(v):
variables[k] = P_OBJ.DependencyVariableString(v)

dep = dependencies.InternalDependency(version, incs, compile_args,
dep = dependencies.InternalDependency(version, incs, embed_directories, compile_args,
link_args, libs, libs_whole, sources, extra_files,
deps, variables, d_module_versions, d_import_dirs,
objects)
Expand Down Expand Up @@ -3693,6 +3696,7 @@ def __convert_build_target_base_kwargs(self, kwargs: kwtypes.BuildTarget, final:

# Convert into IncludeDirs objects
final['include_directories'] = self.extract_incdirs(kwargs['include_directories'])
final['embed_directories'] = self.extract_incdirs(kwargs['embed_directories'])
final['d_import_dirs'] = self.extract_incdirs(kwargs['d_import_dirs'], True)

# Convert language arguments
Expand Down
2 changes: 2 additions & 0 deletions mesonbuild/interpreter/kwargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ class BuildTarget(BaseBuildTarget):
d_import_dirs: T.List[T.Union[str, build.IncludeDirs]]
d_module_versions: T.List[T.Union[str, int]]
d_unittest: bool
embed_directories: list[str | build.IncludeDirs]
install_dir: T.List[T.Union[str, bool]]
install_vala_header: T.Union[str, bool, None]
install_vala_vapi: T.Union[str, bool, None]
Expand Down Expand Up @@ -540,6 +541,7 @@ class FuncDeclareDependency(TypedDict):
d_import_dirs: T.List[T.Union[build.IncludeDirs, str]]
d_module_versions: T.List[T.Union[str, int]]
dependencies: T.List[Dependency]
embed_directories: list[str | build.IncludeDirs]
extra_files: T.List[FileOrString]
include_directories: T.List[T.Union[build.IncludeDirs, str]]
link_args: T.List[str]
Expand Down
12 changes: 9 additions & 3 deletions mesonbuild/interpreter/type_checking.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,11 @@ def _local_program_convertor(raw: T.List[T.Union[str, File, BuildTarget, Generat
default=[],
)

EMBED_DIRECTORIES = INCLUDE_DIRECTORIES.evolve(
name='embed_directories',
since='1.13.0',
)

def _default_options_convertor(raw: T.Union[str, T.List[str], T.Dict[str, ElementaryOptionValues]]) -> T.Dict[OptionKey, ElementaryOptionValues]:
d = _override_options_convertor(raw)
return {OptionKey.from_string(k): v for k, v in d.items()}
Expand Down Expand Up @@ -577,7 +582,7 @@ def suite_convertor(suite: T.List[str]) -> T.List[str]:
default=[],
)

_LANGUAGE_KWS: T.List[KwargInfo[T.List[str]]] = [
_LANGUAGE_KWS: T.List[KwargInfo[T.List[str | File]]] = [
_BASE_LANG_KW.evolve(name=f'{lang}_args')
for lang in compilers.all_languages - {'rust', 'vala', 'java'}
]
Expand All @@ -587,7 +592,7 @@ def suite_convertor(suite: T.List[str]) -> T.List[str]:
_LANGUAGE_KWS.append(_BASE_LANG_KW.evolve(name='rust_args', since='0.41.0'))

# We need this deprecated values more than the non-deprecated values. So we'll evolve them out elsewhere.
_JAVA_LANG_KW: KwargInfo[T.List[str]] = _BASE_LANG_KW.evolve(
_JAVA_LANG_KW: KwargInfo[T.List[str | File]] = _BASE_LANG_KW.evolve(
name='java_args',
deprecated='1.3.0',
deprecated_message='This does not, and never has, done anything. It should be removed'
Expand Down Expand Up @@ -781,6 +786,7 @@ def _pch_convertor(args: T.List[str]) -> T.Optional[T.Tuple[str, T.Optional[str]
*_LANGUAGE_KWS,
BT_SOURCES_KW,
INCLUDE_DIRECTORIES.evolve(name='d_import_dirs'),
EMBED_DIRECTORIES,
LINK_ARGS_KW,
LINK_WHOLE_KW.evolve(
as_default=[('', ('1.11.0', "Replace an empty string with an empty array: `link_whole : ''` -> `link_whole : []`"))],
Expand Down Expand Up @@ -1010,7 +1016,7 @@ def _shortname_validator(shortname: T.Optional[str]) -> T.Optional[str]:
for a in _LANGUAGE_KWS],
]

_SHARED_STATIC_ARGS: T.List[KwargInfo[T.List[str]]] = [
_SHARED_STATIC_ARGS: T.List[KwargInfo[T.List[str | File]]] = [
*[l.evolve(name=l.name.replace('_', '_static_'), since='1.3.0')
for l in _LANGUAGE_KWS],
*[l.evolve(name=l.name.replace('_', '_shared_'), since='1.3.0')
Expand Down
2 changes: 1 addition & 1 deletion mesonbuild/interpreterbase/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ def evolve(self, *,
convertor: T.Union[T.Callable[[_T], object], None, _NULL_T] = _NULL,
extra_types: T.Union[T.Mapping[T.Type, T.Callable[[object], str]], None, _NULL_T] = _NULL,
as_default: T.Union[T.List[T.Tuple[object, T.Union[str, T.Tuple[str, str]]]], None, _NULL_T] = _NULL
) -> 'KwargInfo':
) -> 'KwargInfo[_T]':
"""Create a shallow copy of this KwargInfo, with modifications.

This allows us to create a new copy of a KwargInfo with modifications.
Expand Down
2 changes: 1 addition & 1 deletion mesonbuild/modules/external_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def dependency_method(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'D
compile_args = [f'-I{abs_includedir}']
link_args = [f'-L{abs_libdir}', f'-l{libname}']
sources = self.target
dep = InternalDependency(version, [], compile_args, link_args, [],
dep = InternalDependency(version, [], [], compile_args, link_args, [],
[], [sources], [], [], {}, [], [], [])
return dep

Expand Down
2 changes: 1 addition & 1 deletion mesonbuild/modules/gnome.py
Original file line number Diff line number Diff line change
Expand Up @@ -2324,7 +2324,7 @@ def generate_vapi(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'Gener
incs = [build.IncludeDirs(state.subdir, ['.'] + vapi_includes, False,
state.current_build_project)]
sources = [vapi_target] + vapi_depends
rv = InternalDependency(None, incs, [], [], link_with, [], sources, [], [], {}, [], [], [])
rv = InternalDependency(None, incs, [], [], [], link_with, [], sources, [], [], {}, [], [], [])
created_values.append(rv)
return ModuleReturnValue(rv, created_values)

Expand Down
1 change: 1 addition & 0 deletions test cases/common/300 embed dirs/embed/data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, World!
35 changes: 35 additions & 0 deletions test cases/common/300 embed dirs/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright © 2026 Intel Corporation
*/

#include <stdio.h>

const char msg[] =
{
#embed "data.txt"
};

const char expected[] = {
'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\n',
};


int main(void) {
const int num_found = sizeof(msg) / sizeof(msg[0]);
const int num_expected = sizeof(expected) / sizeof(expected[0]);

if (num_found != num_expected) {
fprintf(stderr, "The number of found arguments (%d) does not match the expected(%d)\n", num_found, num_expected);
return 1;
}

for (unsigned i = 0; i < num_found; ++i) {
if (msg[i] != expected[i]) {
fprintf(stderr, "The items at index %d does not match: found: %c, expected: %c\n", i, msg[i], expected[i]);
return 1;
}
}

return 0;
}
35 changes: 35 additions & 0 deletions test cases/common/300 embed dirs/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright © 2026 Intel Corporation
*/

#include <iostream>

constexpr char msg[] =
{
#embed "data.txt"
};

constexpr char expected[] = {
'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\n',
};


int main(void) {
constexpr int num_found = sizeof(msg) / sizeof(msg[0]);
constexpr int num_expected = sizeof(expected) / sizeof(expected[0]);

if (num_found != num_expected) {
std::cerr << "The number of found arguments (" << num_found << ") does not match the expected (" << num_expected << ")\n";
return 1;
}

for (unsigned i = 0; i < num_found; ++i) {
if (msg[i] != expected[i]) {
std::cerr << "The items at index " << i << "does not match: found: " << msg[i] << "expected: " << expected[i] << "\n";
return 1;
}
}

return 0;
}
40 changes: 40 additions & 0 deletions test cases/common/300 embed dirs/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright © 2026 Intel Corporation

project(
'embed dirs',
meson_version : '>= 1.13.0',
default_options : {'c_std' : 'c23', 'cpp_std' : 'c++26'},
)

dep = declare_dependency(
embed_directories : ['embed'],
)

if add_languages('c', required : false, native : false)
exe = executable(
'c_prog',
'main.c',
embed_directories : ['embed'],
)

test('C embed', exe)

exe = executable(
'c_with_dep',
'main.c',
dependencies : dep,
)

test('From dependency object', exe)
endif

if add_languages('cpp', required : false, native : false)
exe = executable(
'cpp_prog',
'main.cpp',
embed_directories : include_directories('embed'),
)

test('C++ embed', exe)
endif
Loading