bazelbuild / rules_apple

Bazel rules to build apps for Apple platforms.
Apache License 2.0
507 stars 263 forks source link

Allow for custom substitutions in plists #1659

Open nvanfleet opened 2 years ago

nvanfleet commented 2 years ago

Currently there are some hard coded substitutions when merging plists here. This allows for values to be changed via intake into the plist tool.

However it's not possible to change arbitrary values in a plist tool which is sometimes done. This would be really useful for those specific cases and would match Xcode's support of doing so.

For example in a plist file

    <key>ExampleValueWhichTheApplicationChecks</key>
    <string>$(INJECTED_COMPILE_TIME_INFORMATION)</string>

This is supported in a straightforward manner using Xcode build.

VARIABLE="test_value"

xcodebuild \
    archive \
    INJECTED_COMPILE_TIME_INFORMATION =${VARIABLE} \
    ...

Xcode will then merge the value into the plist.

None of the formats for bazel seem to work

bazel build \
   --copt="-D${INJECTED_COMPILE_TIME_INFORMATION}=hello" \
   --copt="-D$(INJECTED_COMPILE_TIME_INFORMATION)=hello" \
   INJECTED_COMPILE_TIME_INFORMATION ="hello" \
   ...

You get the error ERROR: In target "Foo.bundle (while bundling under "//platform/ios:resources")"; unknown variable reference "$(INJECTED_COMPILE_TIME_INFORMATION)" while merging plists (key: "ExampleValueWhichTheApplicationChecks", value: "$(INJECTED_COMPILE_TIME_INFORMATION)").

Related: https://github.com/bazelbuild/rules_apple/issues/643

keith commented 2 years ago

Right now the assumption is that if you need extra processing you do that ahead of time with some expand_template type rule, and then pass the output of that into the final ios_application or whatever you're building. I think for some types of info that might not work, if it's dynamic, but in that case I think then you'd need to use --stamp instead. We could theoretically add a custom starlark flag to support these options and processing, but semantically stamping might be right for what you're trying to do

uiChuanqi commented 1 year ago

Hi, "and then pass the output of that into the final ios_application" , what does this mean? My problem now are , Emmm, i cann't add variables to Info.plist except give an constant value to the new key.

The detail description is here: can not add new variables into Info.plist

and this is my BUILD:

ios_application(
    name = "SampleApp",
    bundle_id = "com.ui.SampleApp",
    families = ["iphone", "ipad"],
    minimum_os_version = "15.0",
    infoplists = [":NewInfo"],
    deps = [":SampleAppLibrary"],
    resources = glob(["Assets.xcassets/**"]) + glob(["*.xcconfig"]),
    visibility = ["//visibility:public"],
)

hello(
    name = "NewInfo",
    replacements = {
    "Host_URL" : "BUILD_test",
    },
    infoSrc = "Info.plist"
)

and this is my source Info.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleVersion</key>
    <string>1</string>
        <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>Host_URL</key>
    <string>${Host_URL}</string>
</dict>
</plist>

there comes out one error like this:

243323821-3344c78b-fdc7-44d3-85b8-189c5d7ca4e2

and my expand_template is as below:

def _hello_implement(ctx):
    ctx.actions.expand_template(
        template = ctx.file.infoSrc,
        output = ctx.outputs.out,
        substitutions = ctx.attr.replaceDic,
    )

hello = rule(
    attrs = dict(
        infoSrc = attr.label(mandatory = True, allow_single_file = [".plist"]),
        replaceDic = attr.string_dict(allow_empty = False),
    ),
    outputs = {"out": "%{name}.plist"},
    implementation = _hello_implement,
)

could you please give me some suggesstions ?

Right now the assumption is that if you need extra processing you do that ahead of time with some expand_template type rule, and then pass the output of that into the final ios_application or whatever you're building. I think for some types of info that might not work, if it's dynamic, but in that case I think then you'd need to use --stamp instead. We could theoretically add a custom starlark flag to support these options and processing, but semantically stamping might be right for what you're trying to do

keith commented 1 year ago

expand_template is literal so you need to do:

    replacements = {
    "${Host_URL}" : "BUILD_test",
    },
uiChuanqi commented 1 year ago

expand_template is literal so you need to do:

    replacements = {
    "${Host_URL}" : "BUILD_test",
    },

Finally works! Excellent ! Thank you very much ! But i find this:

    #BUILD
    replaceDic = {
    "${Host_URL}" : "https://www.apple.com/",
    },
  #xcconfig
BACKSLASH = /
Host_URL = "https:${BACKSLASH}/www.google.nl/"

Open the generated xcodeproj, add the xcconfig to target and then build it, the "Host_URL" will come out in the User-defined, and its value is "https://www.google.nl/",

2023-06-07 15 25

when use it in project:

#OtherClassTest.swift
var url = Bundle.main.infoDictionary?["Host_URL"] as! String

the url's value is "https://www.apple.com/", is this right ?