Comments (10)
If you intend for the out
artifact to be a directory, then you definitely need to declare it with dir = True
, and buck is right to make you do that.
I suspect the reason that things go wrong if you do that is because you're trying to use a projected artifact as an output. It's not really clear what the behavior of that is supposed to be to me, I wouldn't be surprised if no one ever really thought about that case. If you switch to something like "--destination", cmd_args(base_folder.as_output(), ctx.attrs.toolchain_name, delimiter = "/")
, it'll work better.
I would have to dig into this a bit more to confirm though. I also realize that won't work on windows as written too, which is a bit meh. May think about this more
from buck2.
Isn’t http_archive using a projected artifact as an output?
buck2/prelude/http_archive/http_archive.bzl
Line 215 in 39d2754
from buck2.
I've tried changing the python script to implicitly create the directory (so the --destination arg is passing in just the base folder) and that has the same problem. It seems to be related to the output = package_folder.project(sub_target)
call when an intermediate folder on-disk is a symlink. I'd have to go back and verify, but I'm pretty sure the same rule works if the python script creates actual folders without symlinks.
from buck2.
@zjturner output of an action, not output of analysis.
@AtomicOperation can you confirm, is the python script trying to make the output
dir a symlink or the toolchain_name
in the output
dir?
from buck2.
I'm trying to make an output dir (base_folder in the snippet above) and a symlink to a folder underneath that (toolchain_folder in the snippet).
from buck2.
I suspect the reason that things go wrong if you do that is because you're trying to use a projected artifact as an output. It's not really clear what the behavior of that is supposed to be to me, I wouldn't be surprised if no one ever really thought about that case
@JakobDegen can you explain this a little more? Isn't the entire point of projecting an artifact to create an output relative to some other output?
from buck2.
can you explain this a little more? Isn't the entire point of projecting an artifact to create an output relative to some other output?
Right, but the typical expectation is that you first declare the artifact, use .as_output()
to make it the output of some action, and only then project it - in other words, projection is meant for an already bound artifact.
So concretely, I would expect that the version of the code that works looks something like this:
def _install_toolchain_impl(ctx = "context"):
base_folder = ctx.actions.declare_output("out", dir = True)
command = cmd_args(["install_toolchain.py",
"--toolchain", ctx.attrs.toolchain_name,
"--version", ctx.attrs.version,
"--destination", base_folder.as_output(),
]
)
sub_targets = {}
for sub_target in ctx.attrs.sub_targets:
output = base_folder.project(ctx.attrs.toolchain_name).project(sub_target)
command.hidden(output.as_output())
sub_targets[sub_target] = [DefaultInfo(default_outputs = [output])]
Note that I'm passing the entire base_folder.as_output()
to the action, and then only calling .project()
afterwards. Obviously this would need adjustments to the python script
from buck2.
Thanks, but unfortunately doing it the way you suggest with the .project() call happening after .as_output() results in the same Find would traverse a leaf at path...
error.
from buck2.
I looked into this some and I can reproduce this. Here's a minimal reproducer:
# root//bucklink:BUCK
load(":rule.bzl", "link_dir")
link_dir(
name = "makelink",
link_name = "hello",
link_target = "D:\\src\\buck2",
script = "makelink.py",
sub_targets = [
"buck2",
"prelude"
]
)
# root//bucklink:makelink.py
import os
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--link_name", type=str)
parser.add_argument("--link_target", type=str)
parser.add_argument("--destination", type=str)
args = parser.parse_args()
os.makedirs(args.destination, exist_ok=True)
symlink_path = os.path.join(args.destination, args.link_name)
link_location = args.destination
link_target = args.link_target
print(f"Creating symlink from {symlink_path} to {link_target}")
os.symlink(link_target, symlink_path, target_is_directory=True)
# root//bucklink:rule.bzl
load("@prelude//python:toolchain.bzl", "PythonToolchainInfo")
def _link_dir_impl(ctx:AnalysisContext) -> list[Provider]:
base_folder = ctx.actions.declare_output("out", dir = True)
python = ctx.attrs.python[PythonToolchainInfo]
args = python.interpreter.args.copy()
args.add(ctx.attrs.script)
args.add("--link_name", ctx.attrs.link_name)
args.add("--link_target", ctx.attrs.link_target)
args.add("--destination", base_folder.as_output())
ctx.actions.run(
args,
category = "genrule",
)
sub_targets = {}
for sub_target in ctx.attrs.sub_targets:
output = base_folder.project(ctx.attrs.link_name).project(sub_target)
sub_targets[sub_target] = [DefaultInfo(default_outputs = [output])]
return [DefaultInfo(default_outputs=[base_folder], sub_targets=sub_targets)]
link_dir = rule(
impl = _link_dir_impl,
attrs = {
"python": attrs.default_only(attrs.toolchain_dep(providers = [PythonToolchainInfo], default = "toolchains//:python")),
"script": attrs.source(),
"link_name": attrs.string(),
"link_target": attrs.string(),
"sub_targets": attrs.list(attrs.string()),
}
)
Just replace the link_target
in bucklink/BUCK
with a real path to your buck2 source folder.
If you run buck2 build //bucklink:makelink
it works. The link is created on disk. No errors are generated. But if you instead run buck2 build //bucklink:makelink[prelude]
you get an error like this:
$ buck2 build //bucklink:makelink[prelude]
File changed: root//bucklink/rule.bzl
Build ID: e9cb1937-0626-466a-a1e3-db73effdfb13
Jobs completed: 6. Time elapsed: 0.1s.
Cache hits: 0%. Commands: 1 (cached: 0, remote: 0, local: 1)
BUILD FAILED
The path `hello/prelude` cannot be projected in the artifact ``(root//bucklink:makelink (foo//platforms:native#ae24adfe62876596))/out`, action: (target: `root//bucklink:makelink (foo//platforms:native#ae24adfe62876596)`, id: `0`)`
Caused by:
Find would traverse a leaf at path: `buck-out/v2/gen/root/ae24adfe62876596/bucklink/__makelink__/out/prelude`
from buck2.
Back from travel.
I asked about this, and it would indeed be possible to support projecting through symlinks, at least external symlinks. However, it's a bit of a refactor because you end up with artifacts that aren't really at the place they claim to be.
from buck2.
Related Issues (20)
- Conflicting inputs on erlang build of Opentelemetry HOT 1
- error: Variable `typing` not found HOT 2
- Excluding rules from certain platforms HOT 6
- Unable to `buck2 clean` a repo which uses `git_fetch()` on Windows
- `configured_alias` and configuration modifiers HOT 2
- review Go analysis.Pass.Module proposal
- Early-building some parts of graph HOT 7
- How to use "buck2 clean" or other commands to delete only the generated files (cache) without killing the daemon? HOT 2
- Question: how to pass dependencies that change state forward across a non-output-changing rule HOT 4
- buck2 : Is java supported as a part of buck2 HOT 2
- Share work across configurations by setting working directory for actions then canonicalizing that working directory in RE HOT 5
- How to use multiple execution platforms HOT 1
- Distributed project.ignore
- How to use c/aquery to find the dependents of an anon_target HOT 3
- Trouble linking Apple Frameworks HOT 1
- documentation mentions `frecli` which doesn't seem to be available publicly HOT 1
- Adding support for new languages HOT 5
- Java rules don't appear to be usable in OSS edition of buck2 HOT 2
- Builtin prelude support for running python in a venv?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from buck2.