Is there a way to do this in F#:
let fakeToolsPath = "D:\tools\FAKE\tools\FakeLib.dll"
#r fakeToolsPath
the fake tools are on a different path depending on the build agent that builds the code, so I need to be able to set it dynamically, from an environment variable or some config file.
Three ideas, in order of increasing hackiness - you'll be the judge which one makes most sense in your scenario:
In .fsx script, you can use __SOURCE_DIRECTORY__ to get the directory where the script is located. If your dll is always located in the same directory relative to the script, you can use that as a "hook" to get to it.
There's a command-line --reference argument to fsi.exe that should do what you want. If you're using fake.exe instead, you can use --fsiargs to pass it in (take a look at the link for details).
If everything else fails, create a symlink as a separate build step in your CI job configuration and just hardcode the path in the script.
Related
I'm writing a Bazel rule which processes an input depsets with lots of jar files in it. My goal is to get the full (absolute) path of the jars for launching an application.
I use java_binary for the initial application. However, the application itself later then dynamically loads additional jars into the JVM. I need to give that application the absolute path to those jars.
As the depset is pretty expensive to process I want to move that into the execution phase. This requires the use of Args in combination with a map_each function like this:
args.add_joined("--jars", dependencies, join_with = ",", map_each = _expand_jars)
I'm now stuck with how to turn the jar path into an absolute path. In an older version (which was running in the analysis phase) I passed in the path using a rule attribute. This is required because (for some reason) the bootstrap application couldn't access the jars in the external/ directory. In the mapping function I have it hard coded to "bazel-myworkspace/../../", which I'd like to get rid of. It does follow the symlink into the exec root and from there I'm able to get to the output base.
def _expand_jars(file):
if file.path.startswith("external/"):
return "bazel-myworkspace/../../" + file.path
else:
return file.path
Any ideas?
I'd like to specify an environment variable for use in the source path (library path) at a project level.
We often have a couple of versions checked out of our SVN repository at the same time in different directories, and I'd like to specify the repository root for a project in relative terms at a project level. I could then use that path in a project's source path and I wouldn't have to include indecipherable dot dot slashes (..\) in paths.
For example, say I have checked out trunk to c:\projects\trunk. Then underneath there I have a project in <repositoryroot>\Foo\Bar\ under trunk which uses the Delphi Spring framework under <repositoryroot>\components\external\Spring4d. I end up with a whole bunch of directories in the search path with ..\..\External\Spring4D\Source at the beginning. For example ..\..\External\Spring4D\Source\Base\Collections. I would like to be able to be able to use ${Spring4D} instead, producing ${Spring4D}\Base\Collections\, which is much less wordy and it means that if you move a project or component you can change one value and it updates all paths.
I know that you can do this on a Delphi level by specifying paths in Delphi's environment variables, but I would like to achieve the same thing on a project level or repository level.
Does anyone have any ideas on how to achieve this? Are there any settings or even add-ins that would allow this sort of functionality?
You can manually edit your project file (.dproj) and add a variable there:
<PropertyGroup>
<MyVariableName>MyVariableContent</MyVariableName>
</PropertyGroup>
Later on, you can refer to the content of that variable:
<DCC_UnitSearchPath>C:\Components;$(MyVariableName)</DCC_UnitSearchPath>
You can also define a new environment variable (SystemPropertiesAdvanced.exe -> Environment variables -> Add) and then refer to that variable using the same syntax, e.g.:
<DCC_UnitSearchPath>C:\Components;$(PATH)</DCC_UnitSearchPath>
(Note that it is a very bad idea to use PATH here, it's only an example of a variable which will exist in your environment.)
You could also employ some cmd script magic to to create environment variables that point to those subdirectories and at the end call the IDE, so these environment variables are available in the IDE in the same way as global environment variables would be (see pepak's answer for that).
Pointers:
%0 is the name of the current cmd file
use tilde for file name parts
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.
I am trying to get a value of the full current directory path from within .bzl rule. I have tried following:
ctx.host_configuration.default_shell_env.PATH returns "/Users/[user_name]/.rbenv/shims:/usr/local/bin:/usr/bin:/bin:...
ctx.bin_dir.path returns bazel-out/local-fastbuild/bin
pwd = ctx.expand_make_variables("cmd", "$$PWD", {}) returns string $PWD - I don't think this rule is helpful for me, but may be just using it wrong.
What I need is the directory under which the cmd that runs Bazel .bzl rule is running. For example: /Users/[user_name]/git/workspace/path/to/bazel/rule.bzl or at least first part of the path prior to the WORKSPACE directory.
I can't use pwd because I need this value before I call ctx.actions.run_shell()
Are there no attributes in Bazel configurations that hold this value?
The goal is to have hermetic builds, so you shouldn't depend on the absolute path.
Feel free to use pwd inside the command of ctx.actions.run_shell() (for reproducible builds, be careful, avoid putting the absolute path in the generated files).
Edit.
Technically, there are some workarounds. For example, you can pass the path via the --define flag:
bazel build :all --define=path=$(pwd)
Then the value will be available using ctx.var["path"].
Based on your comment below, you want the path to declare an output. Let me repeat: You shouldn't use an absolute path to declare the output file. Declare an output in your package. Then ask the tool you call to use that output.
For example, when you call gcc, you can use -o to specify the output. When a tool writes to stdout, use the shell to redirect it. If the tool is really not flexible, you may want to wrap it with your own script (e.g. call the tool and copy the output file).
Using an absolute path here is not the right solution. For example, it should be possible to execute the action on a remote machine (where your absolute path won't make sense.
Zip may be a reasonable solution. It's useful when you cannot know in advance the number or the names of the output files.
Context
I am writing a repository rule that invokes another Bazel project. My current approach is to build the additional project as a deploy jar. I would like a user to be able to instantiate the rule like:
jar_path = some/relative/path
my_rule(name = "something", p_arg="m_arg", binary=jar_path)
and then given the jar_path and the arguments, I would like the repository rule to execute the following command in the shell:
java -jar $(SOME_JAR) $(ARGUMENTS_PROVIDED_BY_RULE)
Problem
First, it's unclear how best to accomplish the deploy jar approach. So far, I have attempt two different approaches, with varying levels of success. For examples, I have skimmed through the scala_rules, the maven_rules, and the skylark cookbook.
Second, and more importantly, I am not sure whether the deploy jar is the best route to accomplishing my goals. Again, my interest is to invoke a target from an external Bazel project, that is currently hosted on github. (So feasibly, I could try to fetch the project using the http_archive rule).
Below, I describe the attempts I have made.
Approach 1
My first approach involved trying to execute the command using the command field in ctx.action. I tried various enumerations of
java -jar {computed_absolute_path_of_deploy_jar} {args_passed_from_instantiation}.
My biggest issue here was with determining the absolute path of the deploy jar. The file's root path, would contain some additional information. For example, it would like something like this.
/abs/olute/path[ something ]/rela/tive/path
As a side note, I'm not sure if this is a bug/nit, but the File.root.path, evaluated to None, despite File.none not being None.
My first approach involved was to was to try to use skylark [ctx.binary]
Approach 2
Next thing I tried was to mimic the input binary example from the docs. This was also unsuccessful. The issue was that the actual binary could not be found. Here is how I configured it.
First, I relaxed the repository rule into a regular skylark rule.
def _test_binary(ctx):
ctx.action(
....
arguments = [ctx.attr.p_arg],
executable = ctx.executable.binary)
test_binary = rule(
...
attrs = {
"binary":attr.label(mandatory=True, cfg="host", allow_files=True, executable=True),
...
}
Then, in my external project, I loaded the skylark rule into the WORKSPACE file. Finally, I called the macro from one of my BUILD files as follows:
load("#something_rule//:something_rule.bzl", "test_binary")
test_binary(name = "hello", p_arg = "hello", binary = "script.sh")
The script is a one line java -jar something_deploy.jar -- -arg:$1, and is in the same directory as the BUILD file.
Bazel complains that src/script.sh does not exist. I presume because it is looking for the file in /private/var/tmp/-bazel_username/somehash/relative_path. In response, I tried to pass the absolute path, which is not allowed.
Cheers.
It looks like you're mixing up repository rules with build extensions ("normal" rules). A good rule of thumb is:
Repository rules are for getting sources onto your system or symlinking them to a place Bazel can see them.
Build extension are for everything else: compiling, copying files, running binaries, etc.
I don't actually think you need to use either, for this. You say that the other project is on GitHub, so you can add the following to your WORKSPACE file:
http_archive(
name = "other_project",
...
)
Then, in your BUILD file:
genrule(
name = "run-a-jar",
srcs = ["#other_project//some/relative:path"],
cmd = "java -jar $(location #other_project//some/relative:path) -- arg1 arg2 > $#",
outs = ["jar-output"],
)
You shouldn't need to use the _deploy.jar target, since you're not moving the jar out of its project (_deploy.jar is useful when you need to relocate it).
Other things from your question:
I'm not sure if this is a bug/nit, but the File.root.path, evaluated to None,
Are you sure it didn't evaluate to ""? The path is relative to the execution root, so for sources, it will always be "" (for outputs, it'll be bazel-out/local-fastbuild/bin or similar).
Bazel complains that src/script.sh does not exist.
Passing -s to Bazel can really help debugging Skylark rules. You can see exactly where it is looking.