Add ability to add resources to jars
Previously Meson lacked the ability to add resources to jar files. Fixes #9945
This commit is contained in:
parent
a559dbe70d
commit
39f1d52e4a
|
@ -0,0 +1,34 @@
|
||||||
|
## JAR Resources
|
||||||
|
|
||||||
|
The ability to add resources to a JAR has been added. Use the `java_resources`
|
||||||
|
keyword argument. It takes a `sturctured_src` object.
|
||||||
|
|
||||||
|
```meson
|
||||||
|
jar(
|
||||||
|
meson.project_name(),
|
||||||
|
sources,
|
||||||
|
main_class: 'com.mesonbuild.Resources',
|
||||||
|
java_resources: structured_sources(
|
||||||
|
files('resources/resource1.txt'),
|
||||||
|
{
|
||||||
|
'subdir': files('resources/subdir/resource2.txt'),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
To access these resources in your Java application:
|
||||||
|
|
||||||
|
```java
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(
|
||||||
|
Resources.class.getResourceAsStream("/resource1.txt"),
|
||||||
|
StandardCharsets.UTF_8)) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(
|
||||||
|
Resources.class.getResourceAsStream("/subdir/resource2.txt"),
|
||||||
|
StandardCharsets.UTF_8)) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
|
@ -14,3 +14,7 @@ kwargs:
|
||||||
main_class:
|
main_class:
|
||||||
type: str
|
type: str
|
||||||
description: Main class for running the built jar
|
description: Main class for running the built jar
|
||||||
|
java_resources:
|
||||||
|
type: structured_src
|
||||||
|
since: 0.62.0
|
||||||
|
description: Resources to be added to the jar
|
||||||
|
|
|
@ -1231,10 +1231,11 @@ class NinjaBackend(backends.Backend):
|
||||||
elem = NinjaBuildElement(self.all_outputs, 'PHONY', 'phony', '')
|
elem = NinjaBuildElement(self.all_outputs, 'PHONY', 'phony', '')
|
||||||
self.add_build(elem)
|
self.add_build(elem)
|
||||||
|
|
||||||
def generate_jar_target(self, target):
|
def generate_jar_target(self, target: build.Jar):
|
||||||
fname = target.get_filename()
|
fname = target.get_filename()
|
||||||
outname_rel = os.path.join(self.get_target_dir(target), fname)
|
outname_rel = os.path.join(self.get_target_dir(target), fname)
|
||||||
src_list = target.get_sources()
|
src_list = target.get_sources()
|
||||||
|
resources = target.get_java_resources()
|
||||||
class_list = []
|
class_list = []
|
||||||
compiler = target.compilers['java']
|
compiler = target.compilers['java']
|
||||||
c = 'c'
|
c = 'c'
|
||||||
|
@ -1280,6 +1281,9 @@ class NinjaBackend(backends.Backend):
|
||||||
commands += ['-C', self.get_target_private_dir(target), '.']
|
commands += ['-C', self.get_target_private_dir(target), '.']
|
||||||
elem = NinjaBuildElement(self.all_outputs, outname_rel, jar_rule, [])
|
elem = NinjaBuildElement(self.all_outputs, outname_rel, jar_rule, [])
|
||||||
elem.add_dep(class_dep_list)
|
elem.add_dep(class_dep_list)
|
||||||
|
if resources:
|
||||||
|
# Copy all resources into the root of the jar.
|
||||||
|
elem.add_orderdep(self.__generate_sources_structure(Path(self.get_target_private_dir(target)), resources)[0])
|
||||||
elem.add_item('ARGS', commands)
|
elem.add_item('ARGS', commands)
|
||||||
self.add_build(elem)
|
self.add_build(elem)
|
||||||
# Create introspection information
|
# Create introspection information
|
||||||
|
@ -1663,11 +1667,10 @@ class NinjaBackend(backends.Backend):
|
||||||
elem.add_orderdep(instr)
|
elem.add_orderdep(instr)
|
||||||
self.add_build(elem)
|
self.add_build(elem)
|
||||||
|
|
||||||
def __generate_compile_structure(self, target: build.BuildTarget) -> T.Tuple[T.List[str], T.Optional[str]]:
|
def __generate_sources_structure(self, root: Path, structured_sources: build.StructuredSources) -> T.Tuple[T.List[str], T.Optional[str]]:
|
||||||
first_file: T.Optional[str] = None
|
first_file: T.Optional[str] = None
|
||||||
orderdeps: T.List[str] = []
|
orderdeps: T.List[str] = []
|
||||||
root = Path(self.get_target_private_dir(target)) / 'structured'
|
for path, files in structured_sources.sources.items():
|
||||||
for path, files in target.structured_sources.sources.items():
|
|
||||||
for file in files:
|
for file in files:
|
||||||
if isinstance(file, File):
|
if isinstance(file, File):
|
||||||
out = root / path / Path(file.fname).name
|
out = root / path / Path(file.fname).name
|
||||||
|
@ -1706,7 +1709,8 @@ class NinjaBackend(backends.Backend):
|
||||||
main_rust_file = None
|
main_rust_file = None
|
||||||
if target.structured_sources:
|
if target.structured_sources:
|
||||||
if target.structured_sources.needs_copy():
|
if target.structured_sources.needs_copy():
|
||||||
_ods, main_rust_file = self.__generate_compile_structure(target)
|
_ods, main_rust_file = self.__generate_sources_structure(Path(
|
||||||
|
self.get_target_private_dir(target)) / 'structured', target.structured_sources)
|
||||||
orderdeps.extend(_ods)
|
orderdeps.extend(_ods)
|
||||||
else:
|
else:
|
||||||
# The only way to get here is to have only files in the "root"
|
# The only way to get here is to have only files in the "root"
|
||||||
|
|
|
@ -36,7 +36,7 @@ from .mesonlib import (
|
||||||
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
|
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
|
||||||
get_filenames_templates_dict, substitute_values, has_path_sep,
|
get_filenames_templates_dict, substitute_values, has_path_sep,
|
||||||
OptionKey, PerMachineDefaultable,
|
OptionKey, PerMachineDefaultable,
|
||||||
MesonBugException,
|
MesonBugException
|
||||||
)
|
)
|
||||||
from .compilers import (
|
from .compilers import (
|
||||||
Compiler, is_object, clink_langs, sort_clink, lang_suffixes,
|
Compiler, is_object, clink_langs, sort_clink, lang_suffixes,
|
||||||
|
@ -122,7 +122,7 @@ known_exe_kwargs = known_build_target_kwargs | {'implib', 'export_dynamic', 'pie
|
||||||
known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'}
|
known_shlib_kwargs = known_build_target_kwargs | {'version', 'soversion', 'vs_module_defs', 'darwin_versions'}
|
||||||
known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'}
|
known_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'}
|
||||||
known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink'}
|
known_stlib_kwargs = known_build_target_kwargs | {'pic', 'prelink'}
|
||||||
known_jar_kwargs = known_exe_kwargs | {'main_class'}
|
known_jar_kwargs = known_exe_kwargs | {'main_class', 'java_resources'}
|
||||||
|
|
||||||
@lru_cache(maxsize=None)
|
@lru_cache(maxsize=None)
|
||||||
def get_target_macos_dylib_install_name(ld) -> str:
|
def get_target_macos_dylib_install_name(ld) -> str:
|
||||||
|
@ -2712,6 +2712,7 @@ class Jar(BuildTarget):
|
||||||
self.filename = self.name + '.jar'
|
self.filename = self.name + '.jar'
|
||||||
self.outputs = [self.filename]
|
self.outputs = [self.filename]
|
||||||
self.java_args = kwargs.get('java_args', [])
|
self.java_args = kwargs.get('java_args', [])
|
||||||
|
self.java_resources: T.Optional[StructuredSources] = kwargs.get('java_resources', None)
|
||||||
|
|
||||||
def get_main_class(self):
|
def get_main_class(self):
|
||||||
return self.main_class
|
return self.main_class
|
||||||
|
@ -2722,6 +2723,9 @@ class Jar(BuildTarget):
|
||||||
def get_java_args(self):
|
def get_java_args(self):
|
||||||
return self.java_args
|
return self.java_args
|
||||||
|
|
||||||
|
def get_java_resources(self) -> T.Optional[StructuredSources]:
|
||||||
|
return self.java_resources
|
||||||
|
|
||||||
def validate_install(self, environment):
|
def validate_install(self, environment):
|
||||||
# All jar targets are installable.
|
# All jar targets are installable.
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
project('resources', ['java'])
|
||||||
|
|
||||||
|
if meson.backend() != 'ninja'
|
||||||
|
error('MESON_SKIP_TEST: only valid on backends which support jar()')
|
||||||
|
endif
|
||||||
|
|
||||||
|
subdir('src')
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.mesonbuild;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class Resources {
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(
|
||||||
|
Resources.class.getResourceAsStream("/resource1.txt"),
|
||||||
|
StandardCharsets.UTF_8)) {
|
||||||
|
final BufferedReader buffered = new BufferedReader(reader);
|
||||||
|
|
||||||
|
assert buffered.readLine() == "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(
|
||||||
|
Resources.class.getResourceAsStream("/subdir/resource2.txt"),
|
||||||
|
StandardCharsets.UTF_8)) {
|
||||||
|
final BufferedReader buffered = new BufferedReader(reader);
|
||||||
|
|
||||||
|
assert buffered.readLine() == "2";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
sources = files('com/mesonbuild/Resources.java')
|
||||||
|
|
||||||
|
resources = jar(
|
||||||
|
meson.project_name(),
|
||||||
|
sources,
|
||||||
|
main_class: 'com.mesonbuild.Resources',
|
||||||
|
java_resources: structured_sources(
|
||||||
|
files('resources/resource1.txt'),
|
||||||
|
{
|
||||||
|
'subdir': files('resources/subdir/resource2.txt'),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
1
|
|
@ -0,0 +1 @@
|
||||||
|
2
|
Loading…
Reference in New Issue