Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

incompatible_disallow_unsound_directory_outputs #18646

Closed
tjgq opened this issue Jun 12, 2023 · 8 comments
Closed

incompatible_disallow_unsound_directory_outputs #18646

tjgq opened this issue Jun 12, 2023 · 8 comments
Labels
breaking-change-7.0 Incompatible flags to be flipped in Bazel 7.0 incompatible-change Incompatible/breaking change migration-ready Incompatible flag is ready for migration with Bazel rolling releases or Bazel@last_green

Comments

@tjgq
Copy link
Contributor

tjgq commented Jun 12, 2023

This flag, which I'm planning to flip for Bazel 7, forbids an action from creating a directory where a file is expected (which is unsound, as Bazel will not accurately track the directory contents). Such an action will produce the following error message:

ERROR: /Users/tjgq/example/BUILD:1:8: output 'out' of //:target is a directory; dependency checking of directories is unsound

The only native rule for which this is likely to be a problem is genrule through its outs attribute. For Starlark rules, the ctx.actions.declare_file, attr.output and attr.output_list APIs, as well as the deprecated outputs parameter to the rule constructor, all declare output files. An output directory must instead be declared through the ctx.actions.declare_directory API, which offending rules will have to migrate to.

@tjgq tjgq added breaking-change-7.0 Incompatible flags to be flipped in Bazel 7.0 migration-ready Incompatible flag is ready for migration with Bazel rolling releases or Bazel@last_green incompatible-change Incompatible/breaking change labels Jun 12, 2023
copybara-service bot pushed a commit that referenced this issue Sep 27, 2023
The downstream pipeline didn't detect any breakage.

A few tests need to explicitly set the flag to false, or be rewritten to not rely on directory-producing genrules.

Progress on #18646.

PiperOrigin-RevId: 568852835
Change-Id: Ib7508be7f9c6c9448435145a11149c70fbbfa854
@tjgq tjgq closed this as completed Oct 16, 2023
gnoliyil pushed a commit to gnoliyil/fuchsia that referenced this issue Jan 27, 2024
... instead of `dir`. In general Bazel discourages using directories as
inputs and outputs, which will result in unsound dependency checks. In
Bazel 7 such usage will result in build errors by default [0].

In `assembly_bundle`, the `dir` field is necessary to locate the
assembly bundle directory. The same can be achieved by pointing to an
actual file in the root of the directory (assembly_config.json should
always exist in AIBs), and get the path to its parent directory.

Also removed `platform_aib.bzl`, this rule currently can only output a
directory, and it's non-trivial to make it list all files from the
directory in outputs. One common alternative is to create an archive
from this directory and use that as the output. This rule is not needed
until we are ready to start migrating AIB definitions from GN to Bazel,
and we can revisit when we are ready to do that.

[0] bazelbuild/bazel#18646

Bug: 319069000

Change-Id: I783dc5a2d2a3ee69ec0b97e670ad4f105ae07b4d
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/973216
Commit-Queue: Jay Zhuang <jayzhuang@google.com>
Reviewed-by: David Turner <digit@google.com>
@allsey87
Copy link

@tjgq what is the workaround for the use case outlined in #23015?

@tjgq
Copy link
Contributor Author

tjgq commented Aug 28, 2024

@allsey87 Use the path to a file as the $(location ...) argument, then manipulate it in your cc_binary to obtain the parent directory.

@allsey87
Copy link

That would work for a cc_binary that you can modify or patch, but it doesn't solve the problem in general. Consider the following situation using the Meson build system via rules_foreign_cc. Here I need to set the environment variable PYTHONPATH to the directory containing Cython:

cython.BUILD

exports_files(["."])

numpy.BUILD

meson(
    name = "numpy",
    build_data = [
        "@cython//:.",
    ],
    env = {
        "PYTHONPATH": "$(execpath @cython//:.)",
    },
)

I have admitted most fields for brevity, but the above code currently works but results in the "dependency checking of directories is unsound" warning. Is there an alternative solution to this problem?

@fmeum
Copy link
Collaborator

fmeum commented Aug 28, 2024

What happens if you add two labels to build_data, one for all files and one for a single file, and then reference the single file via location with /.. appended as needed?

@tjgq
Copy link
Contributor Author

tjgq commented Aug 28, 2024

What @fmeum said is a valid workaround; another is to set the --host_jvm_args=-DBAZEL_TRACK_SOURCE_DIRECTORIES=1 startup option, which would make source directories incrementally correct and disable the warning.

But more importantly: I've just realized that your example is a source directory, not an output directory, so it's unaffected by this flag flip, which only affects the latter.

@allsey87
Copy link

@fmeum do you mean something like:

cython.BUILD

# this file always exists
exports_files(["BUILD.bazel"])

numpy.BUILD

meson(
    name = "numpy",
    build_data = [
        "@cython//:BUILD.bazel",
    ],
    env = {
        "PYTHONPATH": "$(execpath @cython//:BUILD.bazel)/.."
    },
)

This would assign PYTHONPATH to something like:

PYTHONPATH=/home/developer/.cache/bazel/_bazel_developer/25e07d78077dfe1eca932359d50e41ef/sandbox/processwrapper-sandbox/10/execroot/_main/external/cython/BUILD.bazel/..

Which is not a valid path under Linux and results in the Python module not being found. I also tried placing the ../ inside build data as follows:

build_data = [
      "@cython//:BUILD.bazel/..",
],

However, this gives errors such as: invalid label '@cython//:BUILD.bazel/..' in element 0 of attribute 'build_data' in 'meson' rule: invalid target name 'BUILD.bazel/..': target names may not contain up-level references '..'

Perhaps I have misunderstood your workaround/suggestion?

@allsey87
Copy link

allsey87 commented Aug 28, 2024

@tjgq setting --host_jvm_args=-DBAZEL_TRACK_SOURCE_DIRECTORIES=1 works but gives somewhere between 100 and 1000 warnings that state Directory artifact crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/X/Y/Z. Note the double space after "artifact".

Sample of these warnings:

WARNING: Directory artifact  crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/src/tools/android/java/com/google/devtools/build/android/r8
WARNING: Directory artifact  crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/src/tools/android/java/com/google/devtools/build/android/proto
WARNING: Directory artifact  crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/src/tools/android/java/com/google/devtools/build/android/idlclass
WARNING: Directory artifact  crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/src/tools/android/java/com/google/devtools/build/android/dexer
WARNING: Directory artifact  crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/src/tools/android/java/com/google/devtools/build/android/ziputils
WARNING: Directory artifact  crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/src/tools/android/java/com/google/devtools/build/android/desugar
WARNING: Directory artifact  crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/src/tools/android/java/com/google/devtools/build/android/incrementaldeployment
WARNING: Directory artifact  crosses package boundary into package rooted at bazel-builder-bazel/external/bazel_tools/src/tools/android/java/com/google/devtools/build/android/desugar/scan

I think the blank artifact name is the same item being referenced in the input '' warning below, when --host_jvm_args=-DBAZEL_TRACK_SOURCE_DIRECTORIES=0

WARNING: /home/developer/.cache/bazel/_bazel_developer/25e07d78077dfe1eca932359d50e41ef/external/numpy/BUILD.bazel:33:6: input '' of @@numpy//:numpy is a directory; dependency checking of directories is unsound

@fmeum
Copy link
Collaborator

fmeum commented Aug 28, 2024

You are right, this only works if the tool consuming the variable cleans the path before interpreting it (although that's arguably not correct).

An alternative would be to extract CYTHON = Label("@cython//:BUILD.bazel") into a Starlark constant in a .bzl file and then use CYTHON.workspace_name or CYTHON.workspace_name + "/" + CYTHON.package in BUILD files to construct the path. This only works for source files though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking-change-7.0 Incompatible flags to be flipped in Bazel 7.0 incompatible-change Incompatible/breaking change migration-ready Incompatible flag is ready for migration with Bazel rolling releases or Bazel@last_green
Projects
None yet
Development

No branches or pull requests

3 participants