Tup dependencies from the root directory? - tup

I've tried to create a rule similar to the minimal example:
: ../library/something local |> !compile |> ./something_else
This works, but I would like to write something like:
: $(PROJ_ROOT)/library/something local |> !compile |> ./something_else
Where the PROJ_ROOT variable is the same, even if I add folder depth.
Does tup support this?

You need to pass the root directory to every subdirectory using
include_rules
In your top-level Tupfile you specify TOP = $(TUP_CWD)
In any child you write include_rules. You can now access $(TOP)
to get the relative path, which consists of ../../, etc.

Related

Reading the content of directory declared with `actions.declare_directory`

Imagine I have a java_binary target triggered by a custom rule that generates source code and places the generated sources under a directory, let's call it "root".
So after the code generation we will have something like this:
// bazel-bin/...../src/com/example/root
root:
-> Foo.java
-> Bar.java
-> utils
-> Baz.java
Now, I have another target, a java_library, that depends on the previously generated sources, so it depends on the custom rule.
My custom rule definition currently looks something like this:
def _code_generator(ctx):
outputDir = ctx.actions.declare_directory("root")
files = [
ctx.actions.declare_file("root/Foo.java"),
ctx.actions.declare_file("root/Bar.java"),
ctx.actions.declare_file("root/utils/Baz.java"),
// and many,
// many other files
]
outputs = []
outputs.append(outputDir)
outputs.extend(files)
ctx.actions.run(
executable = // executable pointing to the java_binary
outputs = outputs
// ....
)
This works. But as you can see, every anticipated file that is to be generated, is hard-coded in the rule definition. This makes it very fragile, should the code generation produce a different set of files in the future (which it will).
(Without specifying each of the files, as shown above, Bazel will fail the build saying that the files have no generating action)
So I was wondering, is there a way to read the content of the root directory and automatically, somehow, declare each of the files as an output?
What I tried:
The documentation of declare_directory says:
The contents of the directory are not directly accessible from Starlark, but can be expanded in an action command with Args.add_all().
And add_all says:
[...] Each directory File item is replaced by all Files recursively contained in that directory.
This sounds like there could be a way to get access to the individual files in the directory, but I am not sure how.
I tried:
outputDir = ctx.actions.declare_directory("root")
//...
args = ctx.actions.args()
args.add_all(outputDir)
with the intention to access the individual files later from args, but the build fails with: "Error in add_all: expected value of type sequence or depset for values, got File".
Any other ideas on how to implement the rule, so that I don't have to hard-code each and every file that will be generated?

CopyRecursive not working in FAKE script

I have the following target defined in my FAKE build script. It is being executed. I have verified this usuing trace statements. There is a large file structure in the folder at "MyWebApp". I get no output at the destination folder. What could I be doing wrong?
Target "Push" (fun _ ->
let dir= FileSystemHelper.currentDirectory
let src = dir+ #"\deploy\" + version + #"\MyWebApp"
let dest = #"c:\windows\temp\deploy\" + version
CopyRecursive src dest |> ignore
()
Thanks
Jim
If you look at the definition of CopyRecursive
let CopyRecursive dir outputDir = copyRecursive (directoryInfo dir) (directoryInfo outputDir)
you may notice it represents the partially evaluated (and, by the way, marked at the moment as obsolete) function copyRecursive having signature bool->string list.
Your script sends this partially evaluated function value to ignore and, apparently, nothing happens as the result.
In order to allow copyRecursive to do its work just provide the missing third input argument of type bool that defines if the function should override files with the same names in the target directory. Assuming this is the behavior that you want just change the correspondent line in your script by
CopyRecursive src dest true |> ignore
This will allow copyRecursive to perform its side-effect copying magic returning the list of names of copied files, that you may discard with ignore.

How to get the parent dir name for a given dir in erlang?

In erlang, i have a dir /proj/htdocs/root/jpT/elqstux/16-04-12/ct_run.ct_sim#esekilvxen263.2016-04-12_09.27.06/auto.suite.sbg_ft_esrvcc_midcall_SUITE.groups.esrvcc_midcall_media_stop_002.logs/run.2016-04-12_09.27.12/log_private/,
I want get the parent dir name of this dir.
in this case, the expect result is /proj/htdocs/root/jpT/elqstux/16-04-12/ct_run.ct_sim#esekilvxen263.2016-04-12_09.27.06/auto.suite.sbg_ft_esrvcc_midcall_SUITE.groups.esrvcc_midcall_media_stop_002.logs/run.2016-04-12_09.27.12/.
But i try dirname(Filename) -> file:filename_all(), but i am not successed.
So, i want to know is there have this method for this purpose?
As your input path ends with /, you need to call filename:dirname/1 twice (or you can remove it yourself and call filename:dirname/1 once):
1> Path = "/proj/htdocs/root/jpT/elqstux/16-04-12/ct_run.ct_sim#esekilvxen263.2016-04-12_09.27.06/auto.suite.sbg_ft_esrvcc_midcall_SUITE.groups.esrvcc_midcall_media_stop_002.logs/run.2016-04-12_09.27.12/log_private/".
"/proj/htdocs/root/jpT/elqstux/16-04-12/ct_run.ct_sim#esekilvxen263.2016-04-12_09.27.06/auto.suite.sbg_ft_esrvcc_midcall_SUITE.groups.esrvcc_midcall_media_stop_002.logs/run.2016-04-12_09.27.12/log_private/"
2> Expected = "/proj/htdocs/root/jpT/elqstux/16-04-12/ct_run.ct_sim#esekilvxen263.2016-04-12_09.27.06/auto.suite.sbg_ft_esrvcc_midcall_SUITE.groups.esrvcc_midcall_media_stop_002.logs/run.2016-04-12_09.27.12/".
"/proj/htdocs/root/jpT/elqstux/16-04-12/ct_run.ct_sim#esekilvxen263.2016-04-12_09.27.06/auto.suite.sbg_ft_esrvcc_midcall_SUITE.groups.esrvcc_midcall_media_stop_002.logs/run.2016-04-12_09.27.12/"
3> filename:dirname(filename:dirname(Path)).
"/proj/htdocs/root/jpT/elqstux/16-04-12/ct_run.ct_sim#esekilvxen263.2016-04-12_09.27.06/auto.suite.sbg_ft_esrvcc_midcall_SUITE.groups.esrvcc_midcall_media_stop_002.logs/run.2016-04-12_09.27.12"
Your expected path also includes a trailing /, so you can manually append that as filename:dirname doesn't include it:
4> filename:dirname(filename:dirname(Path)) ++ "/" == Expected.
true

Why does PathBuf lose the current directory when I push a file onto it?

Part of the current directory stored seems to be lost when I push a string onto a path. For example, if I do...
let mut path = "/test.txt";
let mut localpath = env::current_dir().unwrap();
println!("{}", localpath.display());
localpath.push(path);
println!("{}", localpath.display());
I get outputs on the console similar to
C:\User\JohnDoe\Desktop\testfolder
C:\test.txt
Does anyone know why push(path) might be deleting \User\JohnDoe\Desktop\testfolder?
From the docs:
If path is absolute, it replaces the current path.
On Windows:
if path has a root but no prefix (e.g. \windows), it replaces
everything except for the prefix (if any) of self.
if path has a
prefix but no root, it replaces self.
Your example falls under the first bullet point, where it replaces everything but C: with \test.txt.
The solution is to use a non-absolute path, ie, test.txt.

Fsx execution path

I have a c# .net library I am looking to use within FSI/FSX. As part of the initialization of the .net lib, by default it expects and references a custom config file (MyAppConfig.xml) which loads various things before it can be used. When using it in c# it gets copied to the bin folder and the app by default expects it to be there and references it there unless there is a specific entry in the app.config to tell it otherwise. (I should add that it does it all by convention rather than injecting a path + filename, as per NLog, say)
I have an f# source file in a console app which will execute this initialization find, but I can't quite work out how to achieve this with FSI/FSX.
So my program.fs looks simply like
open System
open myApp
module Program =
[<EntryPoint>]
let Main(args) =
myApp.Initialization.Load() // references MyAppConfig.xml
Console.WriteLine("do my stuff!")
Console.ReadLine() |> ignore
0
If I try and do the same in FSI or using FSX, I have
#r #"E:\...path to MyApp...\MyApp.dll"
#I #"E:\...path to MyAppConfig.xml ..."
Environment.CurrentDirectory <- #"E:\...path to MyAppConfig.xml ..."
myApp.Initialization.Load() |> ignore // fails ... can't find MyAppConfig.xml
//do my stuff
I suspect that I've not got the paths quite right.
I'd be grateful of a steer
EDIT:
So I've managed to attach a debugger to the c# lib and see where it is looking for the config file - turns out it is "c:\Program Files\Microsoft F#\v4.0\" ( System.AppDomain.CurrentDomain.BaseDirectory) which again shows I've not quite understood how to tell FSI/FSX to use a particular path. If I copy the config file (MyAppConfig.xml) to that location it works fine.
Many thx
S
I'm not sure of the implications, but one possiblity might be temporarily changing the app base:
let origAppBase = AppDomain.CurrentDomain.BaseDirectory
AppDomain.CurrentDomain.SetData("APPBASE", "path_to_MyAppConfig.xml")
myApp.Initialization.Load() |> ignore
AppDomain.CurrentDomain.SetData("APPBASE", origAppBase) //restore original app base

Resources