Fix resource strip prefix (#1476)
diff --git a/examples/nested_module_resources/BUILD.bazel b/examples/nested_module_resources/BUILD.bazel
index bc93da9..5491b92 100644
--- a/examples/nested_module_resources/BUILD.bazel
+++ b/examples/nested_module_resources/BUILD.bazel
@@ -1,8 +1,77 @@
-load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_binary")
+load("@rules_kotlin//kotlin:jvm.bzl", "kt_jvm_binary", "kt_jvm_library", "kt_jvm_test")
kt_jvm_binary(
name = "main",
- srcs = glob(["*.kt"]),
+ srcs = ["Main.kt"],
main_class = "MainKt",
deps = ["@nested//:printer"],
)
+
+# --- Resource libraries for integration testing ---
+
+# Case 1: Source resource WITH resource_strip_prefix
+kt_jvm_library(
+ name = "source_with_prefix",
+ resource_strip_prefix = "strip_prefix_resources",
+ resources = ["strip_prefix_resources/source_data.txt"],
+)
+
+# Case 2: Source resource WITHOUT resource_strip_prefix (no conventional prefix)
+kt_jvm_library(
+ name = "source_without_prefix",
+ resources = ["static_resources/source_no_prefix.txt"],
+)
+
+# Case 3: Generated resource WITH resource_strip_prefix
+genrule(
+ name = "gen_with_prefix",
+ outs = ["gen_prefix_out/generated_data.txt"],
+ cmd = "echo -n 'generated_with_prefix' > $@",
+)
+
+kt_jvm_library(
+ name = "generated_with_prefix",
+ resource_strip_prefix = "gen_prefix_out",
+ resources = [":gen_with_prefix"],
+)
+
+# Case 4: Generated resource WITHOUT resource_strip_prefix (core bug from #1469)
+genrule(
+ name = "gen_no_prefix",
+ outs = ["generated_no_prefix.txt"],
+ cmd = "echo -n 'generated_without_prefix' > $@",
+)
+
+kt_jvm_library(
+ name = "generated_without_prefix",
+ resources = [":gen_no_prefix"],
+)
+
+# Case 5: Generated resource under conventional prefix (src/main/resources/)
+genrule(
+ name = "gen_conventional",
+ outs = ["src/main/resources/conventional.txt"],
+ cmd = "echo -n 'generated_conventional' > $@",
+)
+
+kt_jvm_library(
+ name = "generated_conventional_prefix",
+ resources = [":gen_conventional"],
+)
+
+# --- Integration test: verifies resources are at correct classpath paths ---
+
+kt_jvm_test(
+ name = "resource_test",
+ srcs = ["ResourceTest.kt"],
+ main_class = "ResourceTest",
+ test_class = "ResourceTest",
+ deps = [
+ ":generated_conventional_prefix",
+ ":generated_with_prefix",
+ ":generated_without_prefix",
+ ":source_with_prefix",
+ ":source_without_prefix",
+ "@nested//:printer",
+ ],
+)
diff --git a/examples/nested_module_resources/ResourceTest.kt b/examples/nested_module_resources/ResourceTest.kt
new file mode 100644
index 0000000..77742bc
--- /dev/null
+++ b/examples/nested_module_resources/ResourceTest.kt
@@ -0,0 +1,42 @@
+object ResourceTest {
+ private fun loadResource(path: String): String? =
+ Thread.currentThread().contextClassLoader.getResource(path)?.readText()?.trim()
+
+ private fun assertResource(path: String, expected: String, description: String) {
+ val content = loadResource(path)
+ check(content != null) { "FAIL [$description]: resource '$path' not found on classpath" }
+ check(content == expected) {
+ "FAIL [$description]: expected '$expected' but got '$content'"
+ }
+ println("PASS [$description]: '$path' = '$expected'")
+ }
+
+ @JvmStatic
+ fun main(args: Array<String>) {
+ assertResource(
+ "source_data.txt", "source_with_prefix",
+ "source resource with resource_strip_prefix",
+ )
+ assertResource(
+ "static_resources/source_no_prefix.txt", "source_without_prefix",
+ "source resource without resource_strip_prefix",
+ )
+ assertResource(
+ "generated_data.txt", "generated_with_prefix",
+ "generated resource with resource_strip_prefix",
+ )
+ assertResource(
+ "generated_no_prefix.txt", "generated_without_prefix",
+ "generated resource without resource_strip_prefix (issue #1469)",
+ )
+ assertResource(
+ "conventional.txt", "generated_conventional",
+ "generated resource under src/main/resources/ conventional prefix",
+ )
+ assertResource(
+ "resource.txt", "world",
+ "cross-module resource with resource_strip_prefix",
+ )
+ println("\nAll resource loading tests passed.")
+ }
+}
diff --git a/examples/nested_module_resources/static_resources/source_no_prefix.txt b/examples/nested_module_resources/static_resources/source_no_prefix.txt
new file mode 100644
index 0000000..84ff046
--- /dev/null
+++ b/examples/nested_module_resources/static_resources/source_no_prefix.txt
@@ -0,0 +1 @@
+source_without_prefix
diff --git a/examples/nested_module_resources/strip_prefix_resources/source_data.txt b/examples/nested_module_resources/strip_prefix_resources/source_data.txt
new file mode 100644
index 0000000..e826a95
--- /dev/null
+++ b/examples/nested_module_resources/strip_prefix_resources/source_data.txt
@@ -0,0 +1 @@
+source_with_prefix
diff --git a/kotlin/internal/jvm/compile.bzl b/kotlin/internal/jvm/compile.bzl
index a5ff788..b3182c2 100644
--- a/kotlin/internal/jvm/compile.bzl
+++ b/kotlin/internal/jvm/compile.bzl
@@ -164,6 +164,16 @@
else:
return _adjust_resources_path_by_default_prefixes(path)
+def _resource_path_relative_to_root(resource):
+ if not resource.root.path:
+ return resource.path
+
+ root_prefix = resource.root.path + "/"
+ if resource.path.startswith(root_prefix):
+ return resource.path[len(root_prefix):]
+
+ return resource.path
+
def _format_compile_plugin_options(o):
"""Format compiler option into id:value for cmd line."""
return [
@@ -298,7 +308,8 @@
strip_prefix = ctx.files.resources[0].root.path + "/" + strip_prefix
for f in ctx.files.resources:
- target_path = _adjust_resources_path(f.path, strip_prefix)
+ resource_path = f.path if strip_prefix else _resource_path_relative_to_root(f)
+ target_path = _adjust_resources_path(resource_path, strip_prefix)
if target_path[0] == "/":
target_path = target_path[1:]
line = "{target_path}={f_path}\n".format(
diff --git a/src/test/starlark/internal/jvm/resource_strip_prefix_test.bzl b/src/test/starlark/internal/jvm/resource_strip_prefix_test.bzl
index 18f9e89..ecf077d 100644
--- a/src/test/starlark/internal/jvm/resource_strip_prefix_test.bzl
+++ b/src/test/starlark/internal/jvm/resource_strip_prefix_test.bzl
@@ -2,7 +2,7 @@
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("//kotlin:jvm.bzl", "kt_jvm_library")
-def _strip_resource_prefix_test_impl(ctx):
+def _resource_path_test_impl(ctx):
env = analysistest.begin(ctx)
actions = analysistest.target_actions(env)
@@ -17,8 +17,6 @@
arguments = file_write_actions[0].content
- pkg = ctx.attr.pkg
-
# The only line should be of the form:
# data.txt=<some prefix>/<pkg>/resourcez/data.txt
lines = arguments.splitlines()
@@ -26,7 +24,7 @@
line_parts = lines[0].split("=", 1)
asserts.equals(env, expected = 2, actual = len(line_parts))
source_path = line_parts[1]
- expected_suffix = pkg + "/" + ctx.attr.resource_strip_prefix + "/" + ctx.attr.resource_path
+ expected_suffix = ctx.attr.expected_source_suffix
asserts.true(
env,
source_path.endswith(expected_suffix),
@@ -35,22 +33,27 @@
destination_path = line_parts[0]
- # The destination path should have the resource_strip_prefix removed
- asserts.equals(env, expected = ctx.attr.resource_path, actual = destination_path, msg = "resource_strip_prefix was not applied correctly")
+ asserts.equals(
+ env,
+ expected = ctx.attr.expected_destination_path,
+ actual = destination_path,
+ msg = "resource path was not normalized correctly",
+ )
return analysistest.end(env)
-strip_resource_prefix_test = analysistest.make(
- _strip_resource_prefix_test_impl,
+resource_path_test = analysistest.make(
+ _resource_path_test_impl,
attrs = {
- "pkg": attr.string(),
- "resource_path": attr.string(),
- "resource_strip_prefix": attr.string(),
+ "expected_destination_path": attr.string(),
+ "expected_source_suffix": attr.string(),
},
)
# Macro to setup the test.
def _strip_resource_prefix_contents():
+ pkg = native.package_name()
+
write_file(
name = "file",
out = "resourcez/resource.txt",
@@ -63,6 +66,18 @@
tags = ["manual"],
)
+ write_file(
+ name = "generated_default_file",
+ out = "generated/resource.txt",
+ tags = ["manual"],
+ )
+
+ write_file(
+ name = "generated_standard_resource",
+ out = "src/main/resources/generated_resource.txt",
+ tags = ["manual"],
+ )
+
kt_jvm_library(
name = "dynamically_created_file",
srcs = ["source"],
@@ -86,6 +101,20 @@
tags = ["manual"],
)
+ kt_jvm_library(
+ name = "generated_default_package",
+ srcs = ["source"],
+ resources = ["generated_default_file"],
+ tags = ["manual"],
+ )
+
+ kt_jvm_library(
+ name = "generated_standard_package",
+ srcs = ["source"],
+ resources = ["generated_standard_resource"],
+ tags = ["manual"],
+ )
+
package_name = native.package_name().split("/")[-1]
native.filegroup(
name = package_name,
@@ -100,40 +129,52 @@
tags = ["manual"],
)
- strip_resource_prefix_test(
+ resource_path_test(
name = "dynamically_created_file_test",
target_under_test = ":dynamically_created_file",
tags = ["manual"],
- pkg = native.package_name(),
- resource_strip_prefix = "resourcez",
- resource_path = "resource.txt",
+ expected_destination_path = "resource.txt",
+ expected_source_suffix = pkg + "/resourcez/resource.txt",
)
- strip_resource_prefix_test(
+ resource_path_test(
name = "static_file_test",
target_under_test = ":static_file",
tags = ["manual"],
- pkg = native.package_name(),
- resource_strip_prefix = "test_resources",
- resource_path = "resource.txt",
+ expected_destination_path = "resource.txt",
+ expected_source_suffix = pkg + "/test_resources/resource.txt",
)
- strip_resource_prefix_test(
+ resource_path_test(
name = "standard_package_test",
target_under_test = ":standard_package",
tags = ["manual"],
- pkg = native.package_name(),
- resource_strip_prefix = "src/main/resources",
- resource_path = "resource.txt",
+ expected_destination_path = "resource.txt",
+ expected_source_suffix = pkg + "/src/main/resources/resource.txt",
)
- strip_resource_prefix_test(
+ resource_path_test(
+ name = "generated_default_package_test",
+ target_under_test = ":generated_default_package",
+ tags = ["manual"],
+ expected_destination_path = pkg + "/generated/resource.txt",
+ expected_source_suffix = pkg + "/generated/resource.txt",
+ )
+
+ resource_path_test(
+ name = "generated_standard_package_test",
+ target_under_test = ":generated_standard_package",
+ tags = ["manual"],
+ expected_destination_path = "generated_resource.txt",
+ expected_source_suffix = pkg + "/src/main/resources/generated_resource.txt",
+ )
+
+ resource_path_test(
name = "same_as_package_name_test",
target_under_test = ":same_as_package_name",
tags = ["manual"],
- pkg = native.package_name(),
- resource_strip_prefix = "test_resources",
- resource_path = "actual_file.txt",
+ expected_destination_path = "actual_file.txt",
+ expected_source_suffix = pkg + "/test_resources/actual_file.txt",
)
# Entry point from the BUILD file; macro for running each test case's macro and
@@ -146,6 +187,8 @@
name = name,
tests = [
":dynamically_created_file_test",
+ ":generated_default_package_test",
+ ":generated_standard_package_test",
":static_file_test",
":standard_package_test",
":same_as_package_name_test",