How to make a path from a string in starlark? - bazel

I'm writing some validation code for a bazel build rule and I need to do some path validation. I need to check that a certain file exists in the same directory as the BUILD file. I notice that there's a context attribute build_file_path which points to the BUILD file. I'd like to extract the parent directory from this.
It looks like I can't create a new path object - I don't see a constructor/initializer. It also seems like Starlark doesn't support os.path like python because imports aren't supported.
What's the canonical way to get the parent directory of a string object representing a path in Starlark?

I can't answer your final question, but hopefully the following will help with the initial problem:
You could use the Label of the target for which this instance of the rule is being built and find its package. This will give you a string representing the parent directory of the BUILD file.
i.e. ctx.label.package

load("#bazel_skylib//lib:paths.bzl", "paths")
paths.dirname(path_str)
See https://github.com/bazelbuild/bazel-skylib/blob/main/docs/paths_doc.md

Related

How to use --save_temps in Bazel rule instead of command line?

Is there a way to control the Bazel build to generate wanted temp files for a list of source files instead of just using the command line option "--save_temps"?
One way is using a cc_binary, and add "-E" option in the "copts", but the obj file name will always have a ".o". This kind of ".o" files will be overwriten by the other build targets. I don't know how to control the compiler output file name in Bazel.
Any better ideas?
cc_library has an output group with the static library, which you can then extract. Something like this:
filegroup(
name = "extract_archive",
srcs = [":some_cc_library"],
output_group = "archive",
)
Many tools will accept the static archive instead of an object file. If the tool you're using does, then that's easy. If not, things get a bit more complicated.
Extracting the object file from the static archive is a bit trickier. You could use a genrule with the $(AR) Make variable, but that won't work with some C++ toolchains that require additional flags to configure architectures etc.
The better (but more complicated) answer is to follow the guidance in integrating with C++ rules. You can get the ar from the toolchain and the flags to use it in a custom rule, and then create an action to extract it. You could also access the OutputGroupInfo from the cc_library in the rule directly instead of using filegroup if you've already got a custom rule.
Thanks all for your suggestions.
Now I think I can solve this problem in two steps(Seems Bazel does not allow to combine two rules into one):
Step1, add a -E option like a normal cc_libary, we can call it a pp_library. It is easy.
Step2, in a new rules, its input is the target of pp_library, then in this rule find out the obj files(can be found via : action.outputs.to_list()) and copy them to the a new place via ctx.actions.run_shell() run_shell.
I take Bazel: copy multiple files to binary directory as a reference.

How can a Bazel `repository_rule` adjust a `label_flag` (or a `config_setting` more generally)?

I can create a label_flag in Bazel to allow command line flags to in turn be matched with a config_setting in a Bazel BUILD file.
However, I'd like to not hard-code the default value of the label_flag, and instead compute a good default based on the system when evaluating a repository_rule (or some other part of the WORKSPACE file).
The best (but awful) way I've come up with to do this is to have the default value loaded from a .bzl file that is generated using the template function on the repository_ctx.
I feel like generating a new file by doing textual substitutions probably isn't the right way to do this, but I can't find anything else. Ideas? help?
Generating a bzl file using the repository rule that inspects the host system is the only way to achieve what you need right now. So you're holding it "right" :)

how to find and deploy the correct files with Bazel's pkg_tar() in Windows?

please take a look at the bin-win target in my repository here:
https://github.com/thinlizzy/bazelexample/blob/master/demo/BUILD#L28
it seems to be properly packing the executable inside a file named bin-win.tar.gz, but I still have some questions:
1- in my machine, the file is being generated at this directory:
C:\Users\John\AppData\Local\Temp_bazel_John\aS4O8v3V\execroot__main__\bazel-out\x64_windows-fastbuild\bin\demo
which makes finding the tar.gz file a cumbersome task.
The question is how can I make my bin-win target to move the file from there to a "better location"? (perhaps defined by an environment variable or a cmd line parameter/flag)
2- how can I include more files with my executable? My actual use case is I want to supply data files and some DLLs together with the executable. Should I use a filegroup() rule and refer its name in the "srcs" attribute as well?
2a- for the DLLs, is there a way to make a filegroup() rule to interpret environment variables? (e.g: the directories of the DLLs)
Thanks!
Look for the bazel-bin and bazel-genfiles directories in your workspace. These are actually junctions (directory symlinks) that Bazel updates after every build. If you bazel build //:demo, you can access its output as bazel-bin\demo.
(a) You can also set TMP and TEMP in your environment to point to e.g. c:\tmp. Bazel will pick those up instead of C:\Users\John\AppData\Local\Temp, so the full path for the output directory (that bazel-bin points to) will be c:\tmp\aS4O8v3V\execroot\__main__\bazel-out\x64_windows-fastbuild\bin.
(b) Or you can pass the --output_user_root startup flag, e.g. bazel--output_user_root=c:\tmp build //:demo. That will have the same effect as (a).
There's currently no way to get rid of the _bazel_John\aS4O8v3V\execroot part of the path.
Yes, I think you need to put those files in pkg_tar.srcs. Whether you use a filegroup() rule is irrelevant; filegroup just lets you group files together, so you can refer to the group by name, which is useful when you need to refer to the same files in multiple rules.
2.a. I don't think so.

How to create and load a configuration file in dxl

I have a script which saves some files at a given location. It works fine but when I send this code to someone else, he has to change the paths in the code. It's not comfortable for someone who does not know what is in that code and for me to explain every time where and how the code should be changed.
I want to get this path in a variable which will be taken from the configuration file. So it will be easier for everyone to change just this config file and nothing in my code. But I have never done this before and could not find any information on how I can do this in the internet.
PS: I do not have any code and I ask about an ultimate solution but it is really difficult to find something good in the internet about dxl, especially since I'm new with that. Maybe someone of you already does that or has an idea how it could be done?
DXL has a perm to read the complete context of a file into a variable: string readFile (string) (or Buffer readFile (string))
you can split the output by \n and then use regular expressions to find all lines that match the pattern
^\s*([^;#].*)\s*=\s*(.*)\s*$
(i.e. key = value - where comment lines start with ; or #)
But in DOORS I prefer using DOORS modules as configuration modules. Object Heading can be the key, Object Text can be the value.
Hardcode the full name of the configuration module into your DXL file and the user can modify the behaviour of the application.
The advantage over a file is that you need not make assumptions on where the config file is to be stored on the file system.
It really depends on your situation. You are going to need to be a little more specific about what you mean by "they need to change the paths in the code". What are these paths to? Are they DOORS module paths, are they paths to local/network files, or are the something else entirely?
Like user3329561 said, you COULD use a DOORS module as a configuration file. I wouldn't recommend it though, simply because that is not what DOORS modules were designed for. DOORS is fully capable of reading system files in one line at a time as well as all at once, but I can't recommend that option either until I know what types of paths you want to load and why.
I suspect that there is a better solution for your problem that will present itself once more information is provided.
I had the same problem, I needed to specify the path of my configuration file used in my dxl script.
I solved this issue passing the directory path as a parameter to DOORS.exe as follow:
"...\DOORS\9.3\bin\doors.exe" -dxl "string myVar = \"Hello Word\"
then in my dxl script, the variable myVar is a global variable.

How do I find a particular sub directory using Ant and then use it to create a symlink?

I need to create a symlink to a sub-directory using Ant. The issue is that I don't know where the target sub-directory is.
To create a symlink with ant I do this:
<symlink link="${parent.dir}/FOO/linkname" resource="${parent.dir}/BAR/target"/>
But I don't know what BAR is called in advance so I need to do a search for "target" under parent.dir and then pass the one result into the resource.
Is this possible using fileset? Or another way?
It might be possible to use a fileset but that might give you several symlinks or none.
A much better approach is to define the path to BAR in a property. If there is a dynamic part in this path, change the code so that Ant evaluates the dynamic part and everyone else uses Ant's value.
The typical example here is that the path contains a version or timestamp. Define those in your build file so you can use them everywhere. If a Java process needs the values, pass them to the process as a system property (-D...).

Resources