Add pkg_install.destdir_flag. (#990)
Add pkg_install.destdir_flag.
This allows `pkg_install(destdir)` to be set from a string_flag.
The use case is to push destdir to a flag you can set in .bazelrc instead of pushing an environment variable through the build.
diff --git a/pkg/install.bzl b/pkg/install.bzl
index fec35c8..ee3d195 100644
--- a/pkg/install.bzl
+++ b/pkg/install.bzl
@@ -17,6 +17,7 @@
run`-able installation script.
"""
+load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@rules_python//python:defs.bzl", "py_binary")
load("//pkg:providers.bzl", "PackageDirsInfo", "PackageFilegroupInfo", "PackageFilesInfo", "PackageSymlinkInfo")
load("//pkg/private:pkg_files.bzl", "create_mapping_context_from_ctx", "process_src", "write_manifest")
@@ -34,6 +35,11 @@
manifest_file = ctx.actions.declare_file(ctx.attr.name + "-install-manifest.json")
+ destdir = ctx.attr.destdir
+ if ctx.attr.destdir_flag:
+ if BuildSettingInfo in ctx.attr.destdir_flag:
+ destdir = ctx.attr.destdir_flag[BuildSettingInfo].value
+
# Write out the manifest in terms of "short" paths, which are those expected
# when you make `bazel run`nable binaries).
#
@@ -62,7 +68,7 @@
"{WORKSPACE_NAME}": ctx.workspace_name,
# Used to annotate --help with "bazel run //path/to/your:installer"
"{TARGET_LABEL}": label_str,
- "{DEFAULT_DESTDIR}": ctx.attr.destdir,
+ "{DEFAULT_DESTDIR}": destdir,
},
is_executable = True,
)
@@ -100,6 +106,7 @@
doc = "Source mapping/grouping targets",
),
"destdir": attr.string(),
+ "destdir_flag": attr.label(doc = "string flag to obtain destdir from"),
# This is private for now -- one could perhaps imagine making this
# public, but that would require more documentation of the underlying
# scripts and expected interfaces.
@@ -111,7 +118,7 @@
executable = True,
)
-def pkg_install(name, srcs, destdir = None, **kwargs):
+def pkg_install(name, srcs, destdir = None, destdir_flag = None, **kwargs):
"""Create an installer script from pkg_filegroups and friends.
This macro allows users to create `bazel run`nable installation scripts
@@ -170,14 +177,18 @@
If this is an absolute path, it is used as-is. If this is a relative
path, it is interpreted against `BUILD_WORKSPACE_DIRECTORY`.
+ destdir_flag: A string_flag target used to obtain the value of destdir.
**kwargs: common rule attributes
"""
+ if destdir and destdir_flag:
+ fail("You may only set on of destdir or destdir_flag")
_pkg_install_script(
name = name + "_install_script",
srcs = srcs,
destdir = destdir,
+ destdir_flag = destdir_flag,
**kwargs
)
diff --git a/tests/install/BUILD b/tests/install/BUILD
index 7d952d4..459b392 100644
--- a/tests/install/BUILD
+++ b/tests/install/BUILD
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
load("@rules_python//python:defs.bzl", "py_test")
load("//pkg:install.bzl", "pkg_install")
load("//pkg:mappings.bzl", "pkg_attributes", "pkg_files", "pkg_mkdirs", "pkg_mklink")
@@ -25,6 +26,7 @@
args = ["-v"],
data = [
":test_installer",
+ ":test_installer_flag",
],
imports = ["../.."],
main = "test.py",
@@ -115,3 +117,16 @@
link_name = "/lib/fake.so.1",
target = "fake.so.1.2.3",
)
+
+string_flag(
+ name = "install_dir",
+ build_setting_default = "FromFlag",
+)
+
+pkg_install(
+ name = "test_installer_flag",
+ srcs = [
+ ":artifact-in-owned-dir",
+ ],
+ destdir_flag = ":install_dir",
+)
diff --git a/tests/install/test.py b/tests/install/test.py
index 270e835..927d48c 100644
--- a/tests/install/test.py
+++ b/tests/install/test.py
@@ -211,6 +211,25 @@
self.assertEqual(num_missing, 0)
+class DestdirFlagTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ r = runfiles.Create()
+ cls.script_path = r.Rlocation(
+ f"rules_pkg/tests/install/test_installer_flag_install_script.py"
+ )
+
+ def test_installer_build_from_flag(self):
+ # This is about as good as we can do without a lot of scaffolding.
+ # To test the flag, we would have to invoke bazel from bazel, which is messy.
+ with open(self.script_path) as installer:
+ script = installer.read()
+ # Default value from BUILD file.
+ self.assertIn("FromFlag", script)
+
+
class WipeTest(PkgInstallTestBase):
def test_wipe(self):
self.installdir.mkdir(exist_ok=True)