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
9 changes: 6 additions & 3 deletions apps/helloworld/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
load("//bzl/valdi:valdi_application.bzl", "valdi_application")
load(
"//bzl/valdi:valdi_application.bzl",
"valdi_application",
"valdi_application_icons",
)
load("//bzl/valdi:valdi_exported_library.bzl", "valdi_exported_library")

valdi_application(
name = "hello_world",
android_activity_theme_name = "Theme.MyApp.Launch",
android_app_icon_name = "app_icon",
android_resource_files = glob(["app_assets/android/**"]),
ios_app_icons = glob(["app_assets/ios/Icons.xcassets/**"]),
icons = valdi_application_icons(src = "app_assets/icon.png"),
ios_bundle_id = "com.snap.valdi.helloworld",
ios_families = ["iphone"],
root_component_path = "App@hello_world/src/HelloWorldApp",
Expand Down
20 changes: 20 additions & 0 deletions bzl/valdi/valdi_android_application.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@ load("@rules_android//rules:rules.bzl", "android_binary")
load("@rules_kotlin//kotlin:android.bzl", "kt_android_library")
load("@valdi//valdi:valdi.bzl", "valdi_android_aar")
load("//bzl:expand_template.bzl", "expand_template")
load(
"//bzl/valdi:valdi_android_application_icons.bzl",
"generate_valdi_android_application_icons",
_valdi_android_application_icons = "valdi_android_application_icons",
)
load("//bzl/valdi/source_set:utils.bzl", "source_set_select")

def valdi_android_application_icons(src, round_src = None):
return _valdi_android_application_icons(src = src, round_src = round_src)

def _make_xml_compound_substitution(key_values):
output = []

Expand All @@ -20,6 +28,7 @@ def valdi_android_application(
app_manifest = None,
assets = None,
assets_dir = None,
app_icons = None,
resource_files = None,
icon_name = None,
round_icon_name = None,
Expand All @@ -30,6 +39,17 @@ def valdi_android_application(
src_activity_target = "{}_activitygen".format(name)
aar_target = "{}_aar".format(name)

generated_app_icons = generate_valdi_android_application_icons(
name,
app_icons,
resource_files,
icon_name,
round_icon_name,
)
resource_files = generated_app_icons.resource_files
icon_name = generated_app_icons.icon_name
round_icon_name = generated_app_icons.round_icon_name

expand_template(
name = src_activity_target,
src = "@valdi//bzl/valdi/app_templates:StartActivity.kt.tpl",
Expand Down
108 changes: 108 additions & 0 deletions bzl/valdi/valdi_android_application_icons.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
load(
"//bzl/valdi:valdi_application_icons_helper.bzl",
"convert_icon",
"is_application_icons",
"make_application_icons",
"toolbox_attr",
)

def valdi_android_application_icons(src, round_src = None):
return make_application_icons("android", src, round_src = round_src)

_ANDROID_ICON_DENSITIES = [
("mipmap-mdpi", 48),
("mipmap-hdpi", 72),
("mipmap-xhdpi", 96),
("mipmap-xxhdpi", 144),
("mipmap-xxxhdpi", 192),
]

def _android_application_icons_impl(ctx):
outputs = []

for density, pixel_size in _ANDROID_ICON_DENSITIES:
output = ctx.actions.declare_file("{}/{}/app_icon.png".format(ctx.attr.resource_root, density))
outputs.append(output)
convert_icon(ctx, ctx.file.src, output, pixel_size)

round_src = ctx.file.round_src if ctx.file.round_src else ctx.file.src
round_output = ctx.actions.declare_file("{}/{}/round_app_icon.png".format(ctx.attr.resource_root, density))
outputs.append(round_output)
convert_icon(ctx, round_src, round_output, pixel_size, round_icon = not ctx.file.round_src)

return [DefaultInfo(files = depset(outputs))]

_android_application_icons = rule(
implementation = _android_application_icons_impl,
attrs = {
"resource_root": attr.string(mandatory = True),
"src": attr.label(allow_single_file = True, mandatory = True),
"round_src": attr.label(allow_single_file = True),
"_toolbox": toolbox_attr(),
},
)

_ANDROID_RESOURCE_DIR_PREFIXES = [
"anim",
"animator",
"color",
"drawable",
"font",
"layout",
"menu",
"mipmap",
"raw",
"transition",
"values",
"xml",
]

def _is_android_resource_dir(path_segment):
for prefix in _ANDROID_RESOURCE_DIR_PREFIXES:
if path_segment == prefix or path_segment.startswith("{}-".format(prefix)):
return True

return False

def _infer_android_resource_root(resource_files, default_root):
for resource_file in resource_files or []:
if type(resource_file) != "string":
continue

path_segments = resource_file.split("/")
for index, path_segment in enumerate(path_segments):
if _is_android_resource_dir(path_segment):
return "/".join(path_segments[:index])

return default_root

def generate_valdi_android_application_icons(name, app_icons, resource_files, icon_name, round_icon_name):
if app_icons == None:
return struct(
resource_files = resource_files,
icon_name = icon_name,
round_icon_name = round_icon_name,
)

if not is_application_icons(app_icons, "android"):
fail("android app_icons must be created with valdi_android_application_icons()")

target_name = "{}_generated_app_icons".format(name)
resource_root = _infer_android_resource_root(resource_files, target_name)
kwargs = {
"name": target_name,
"resource_root": resource_root,
"src": app_icons.src,
}
if app_icons.round_src:
kwargs["round_src"] = app_icons.round_src
_android_application_icons(**kwargs)

resolved_resource_files = list(resource_files or [])
resolved_resource_files.append(":{}".format(target_name))

return struct(
resource_files = resolved_resource_files,
icon_name = icon_name or "app_icon",
round_icon_name = round_icon_name or "round_app_icon",
)
52 changes: 52 additions & 0 deletions bzl/valdi/valdi_application.bzl
Original file line number Diff line number Diff line change
@@ -1,13 +1,43 @@
load("//bzl/valdi:suffixed_deps.bzl", "get_suffixed_deps")
load("//bzl/valdi:valdi_android_application.bzl", "valdi_android_application")
load(
"//bzl/valdi:valdi_android_application_icons.bzl",
_valdi_android_application_icons = "valdi_android_application_icons",
)
load("//bzl/valdi:valdi_ios_application.bzl", "valdi_ios_application")
load(
"//bzl/valdi:valdi_ios_application_icons.bzl",
_valdi_ios_application_icons = "valdi_ios_application_icons",
)
load("//bzl/valdi:valdi_macos_application.bzl", "valdi_macos_application")
load(
"//bzl/valdi:valdi_macos_application_icons.bzl",
_valdi_macos_application_icons = "valdi_macos_application_icons",
)
load(
"//bzl/valdi:valdi_application_icons.bzl",
_valdi_application_icons = "valdi_application_icons",
)
load("//bzl/valdi:valdi_module.bzl", "valdi_hotreload")

def valdi_application_icons(src, round_src = None):
return _valdi_application_icons(src = src, round_src = round_src)

def valdi_ios_application_icons(src):
return _valdi_ios_application_icons(src = src)

def valdi_android_application_icons(src, round_src = None):
return _valdi_android_application_icons(src = src, round_src = round_src)

def valdi_macos_application_icons(src):
return _valdi_macos_application_icons(src = src)

def valdi_application(
name,
title,
root_component_path,
icons = None,
app_icons = None,
ios_bundle_id = None,
ios_info_plist = None,
ios_families = None,
Expand All @@ -18,17 +48,37 @@ def valdi_application(
android_assets = None,
android_assets_dir = None,
android_resource_files = None,
android_app_icons = None,
android_app_manifest = None,
android_app_icon_name = None,
android_round_app_icon_name = None,
android_activity_theme_name = None,
macos_app_icons = None,
desktop_window_width = 600,
desktop_window_height = 800,
desktop_window_resizable = True,
version = None,
deps = []):
resolved_ios_bundle_id = ios_bundle_id if ios_bundle_id else "com.snap.valdi.{}".format(name)
resolved_android_package = android_package if android_package else "com.snap.valdi.{}".format(name)
resolved_app_icons = icons if icons != None else app_icons

if icons != None and app_icons != None:
fail("Only one of icons or app_icons may be specified")

if resolved_app_icons != None:
if not hasattr(resolved_app_icons, "_valdi_application_icons") or resolved_app_icons._valdi_application_icons != "all":
fail("icons must be created with valdi_application_icons()")

if ios_app_icons == None:
ios_app_icons = _valdi_ios_application_icons(src = resolved_app_icons.src)
if android_app_icons == None:
android_app_icons = _valdi_android_application_icons(
src = resolved_app_icons.src,
round_src = resolved_app_icons.round_src,
)
if macos_app_icons == None:
macos_app_icons = _valdi_macos_application_icons(src = resolved_app_icons.src)

valdi_ios_application(
name = "{}_ios".format(name),
Expand All @@ -51,6 +101,7 @@ def valdi_application(
package = resolved_android_package,
assets = android_assets,
assets_dir = android_assets_dir,
app_icons = android_app_icons,
app_manifest = android_app_manifest,
resource_files = android_resource_files,
icon_name = android_app_icon_name,
Expand All @@ -68,6 +119,7 @@ def valdi_application(
window_width = desktop_window_width,
window_height = desktop_window_height,
window_resizable = desktop_window_resizable,
app_icons = macos_app_icons,
deps = get_suffixed_deps(deps, "_native"),
)

Expand Down
19 changes: 19 additions & 0 deletions bzl/valdi/valdi_application_icons.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
load(
"//bzl/valdi:valdi_android_application_icons.bzl",
"valdi_android_application_icons",
)
load(
"//bzl/valdi:valdi_application_icons_helper.bzl",
"make_application_icons",
)
load(
"//bzl/valdi:valdi_ios_application_icons.bzl",
"valdi_ios_application_icons",
)
load(
"//bzl/valdi:valdi_macos_application_icons.bzl",
"valdi_macos_application_icons",
)

def valdi_application_icons(src, round_src = None):
return make_application_icons("all", src, round_src = round_src)
47 changes: 47 additions & 0 deletions bzl/valdi/valdi_application_icons_helper.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
def make_application_icons(platform, src, round_src = None):
return struct(
_valdi_application_icons = platform,
src = src,
round_src = round_src,
)

def is_application_icons(value, platform):
return hasattr(value, "_valdi_application_icons") and value._valdi_application_icons == platform

def toolbox_attr():
return attr.label(
default = Label("//valdi/compiler/toolbox:valdi_compiler_toolbox"),
executable = True,
cfg = "exec",
)

def convert_icon(ctx, src, output, size, round_icon = False):
args = ctx.actions.args()
args.add("image_convert")
args.add("-i", src)
args.add("-o", output)
args.add("-w", str(size))
args.add("-h", str(size))
if round_icon:
args.add("--round")

ctx.actions.run(
executable = ctx.executable._toolbox,
inputs = [src],
outputs = [output],
arguments = [args],
mnemonic = "ValdiApplicationIcon",
progress_message = "Generating application icon {}".format(output.short_path),
)

def write_apple_contents_json(ctx, output, images):
ctx.actions.write(
output = output,
content = json.encode_indent({
"images": images,
"info": {
"author": "xcode",
"version": 1,
},
}) + "\n",
)
10 changes: 9 additions & 1 deletion bzl/valdi/valdi_ios_application.bzl
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
load("@build_bazel_rules_apple//apple:versioning.bzl", "apple_bundle_version")
load("//bzl:expand_template.bzl", "expand_template")
load(
"//bzl/valdi:valdi_ios_application_icons.bzl",
"generate_valdi_ios_application_icons",
_valdi_ios_application_icons = "valdi_ios_application_icons",
)

def valdi_ios_application_icons(src):
return _valdi_ios_application_icons(src = src)

def make_short_version(version):
components = version.split(".")
Expand Down Expand Up @@ -87,7 +95,7 @@ def valdi_ios_application(
deps = [":{}".format(src_target)],
minimum_os_version = minimum_os_version,
provisioning_profile = provisioning_profile,
app_icons = app_icons,
app_icons = generate_valdi_ios_application_icons(name, app_icons),
version = resolved_version,
tags = ["valdi_ios_application"],
visibility = ["//visibility:public"],
Expand Down
Loading
Loading