aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Partin <tristan@partin.io>2022-03-01 12:05:28 -0600
committerJussi Pakkanen <jpakkane@gmail.com>2022-03-22 13:21:26 +0200
commit39f1d52e4a82cc75a4a3a41c3cc17fe2dabdb30b (patch)
treeec8855a6f7ea0c937736f366258ae8ca2629ea9d
parenta559dbe70d113ebaa9bab406e371e54251d66e71 (diff)
downloadmeson-39f1d52e4a82cc75a4a3a41c3cc17fe2dabdb30b.zip
meson-39f1d52e4a82cc75a4a3a41c3cc17fe2dabdb30b.tar.gz
meson-39f1d52e4a82cc75a4a3a41c3cc17fe2dabdb30b.tar.bz2
Add ability to add resources to jars
Previously Meson lacked the ability to add resources to jar files. Fixes #9945
-rw-r--r--docs/markdown/snippets/jar-resources.md34
-rw-r--r--docs/yaml/functions/jar.yaml4
-rw-r--r--mesonbuild/backend/ninjabackend.py14
-rw-r--r--mesonbuild/build.py8
-rw-r--r--test cases/java/10 resources/meson.build7
-rw-r--r--test cases/java/10 resources/src/com/mesonbuild/Resources.java26
-rw-r--r--test cases/java/10 resources/src/meson.build13
-rw-r--r--test cases/java/10 resources/src/resources/resource1.txt1
-rw-r--r--test cases/java/10 resources/src/resources/subdir/resource2.txt1
9 files changed, 101 insertions, 7 deletions
diff --git a/docs/markdown/snippets/jar-resources.md b/docs/markdown/snippets/jar-resources.md
new file mode 100644
index 0000000..12b0c81
--- /dev/null
+++ b/docs/markdown/snippets/jar-resources.md
@@ -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)) {
+ // ...
+}
+```
diff --git a/docs/yaml/functions/jar.yaml b/docs/yaml/functions/jar.yaml
index 6e8e5dd..52f66e5 100644
--- a/docs/yaml/functions/jar.yaml
+++ b/docs/yaml/functions/jar.yaml
@@ -14,3 +14,7 @@ kwargs:
main_class:
type: str
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
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 614e864..c630cc3 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1231,10 +1231,11 @@ class NinjaBackend(backends.Backend):
elem = NinjaBuildElement(self.all_outputs, 'PHONY', 'phony', '')
self.add_build(elem)
- def generate_jar_target(self, target):
+ def generate_jar_target(self, target: build.Jar):
fname = target.get_filename()
outname_rel = os.path.join(self.get_target_dir(target), fname)
src_list = target.get_sources()
+ resources = target.get_java_resources()
class_list = []
compiler = target.compilers['java']
c = 'c'
@@ -1280,6 +1281,9 @@ class NinjaBackend(backends.Backend):
commands += ['-C', self.get_target_private_dir(target), '.']
elem = NinjaBuildElement(self.all_outputs, outname_rel, jar_rule, [])
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)
self.add_build(elem)
# Create introspection information
@@ -1663,11 +1667,10 @@ class NinjaBackend(backends.Backend):
elem.add_orderdep(instr)
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
orderdeps: T.List[str] = []
- root = Path(self.get_target_private_dir(target)) / 'structured'
- for path, files in target.structured_sources.sources.items():
+ for path, files in structured_sources.sources.items():
for file in files:
if isinstance(file, File):
out = root / path / Path(file.fname).name
@@ -1706,7 +1709,8 @@ class NinjaBackend(backends.Backend):
main_rust_file = None
if target.structured_sources:
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)
else:
# The only way to get here is to have only files in the "root"
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 4f569a6..2c841a6 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -36,7 +36,7 @@ from .mesonlib import (
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
get_filenames_templates_dict, substitute_values, has_path_sep,
OptionKey, PerMachineDefaultable,
- MesonBugException,
+ MesonBugException
)
from .compilers import (
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_shmod_kwargs = known_build_target_kwargs | {'vs_module_defs'}
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)
def get_target_macos_dylib_install_name(ld) -> str:
@@ -2712,6 +2712,7 @@ class Jar(BuildTarget):
self.filename = self.name + '.jar'
self.outputs = [self.filename]
self.java_args = kwargs.get('java_args', [])
+ self.java_resources: T.Optional[StructuredSources] = kwargs.get('java_resources', None)
def get_main_class(self):
return self.main_class
@@ -2722,6 +2723,9 @@ class Jar(BuildTarget):
def get_java_args(self):
return self.java_args
+ def get_java_resources(self) -> T.Optional[StructuredSources]:
+ return self.java_resources
+
def validate_install(self, environment):
# All jar targets are installable.
pass
diff --git a/test cases/java/10 resources/meson.build b/test cases/java/10 resources/meson.build
new file mode 100644
index 0000000..3b87219
--- /dev/null
+++ b/test cases/java/10 resources/meson.build
@@ -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')
diff --git a/test cases/java/10 resources/src/com/mesonbuild/Resources.java b/test cases/java/10 resources/src/com/mesonbuild/Resources.java
new file mode 100644
index 0000000..de1b7d6
--- /dev/null
+++ b/test cases/java/10 resources/src/com/mesonbuild/Resources.java
@@ -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";
+ }
+ }
+}
diff --git a/test cases/java/10 resources/src/meson.build b/test cases/java/10 resources/src/meson.build
new file mode 100644
index 0000000..51f7d75
--- /dev/null
+++ b/test cases/java/10 resources/src/meson.build
@@ -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'),
+ }
+ )
+)
diff --git a/test cases/java/10 resources/src/resources/resource1.txt b/test cases/java/10 resources/src/resources/resource1.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/test cases/java/10 resources/src/resources/resource1.txt
@@ -0,0 +1 @@
+1
diff --git a/test cases/java/10 resources/src/resources/subdir/resource2.txt b/test cases/java/10 resources/src/resources/subdir/resource2.txt
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/test cases/java/10 resources/src/resources/subdir/resource2.txt
@@ -0,0 +1 @@
+2