Convert FileIncludes to filefilter predicate - f#-fake

I'm trying to use CopyDir to copy my build artifacts to an output directory.
I'm not sure how I am supposed to define the filter predicate that CopyDir takes as an argument. I've looked in the documentation and tried searching for many different keywords on Google.
Target "Copy-Build-Output" (fun _ ->
let baseDir = (sourceDir + #"Trunk\Webroot")
let outputfiles =
!! (sourceDir ## "**/*.*")
-- (sourceDir ## "**/*.cs")
-- (sourceDir ## "**/*.csproj")
-- (sourceDir ## "**/*.vspscc")
-- (sourceDir ## "**/*.cssscc")
-- (sourceDir ## "web.config")
-- (sourceDir ## "bin/*.xml")
-- (sourceDir ## "obj/**")
CopyDir outputDir baseDir ????
)
How do I take the file include set and convert it into a matching statement?

Why you need to create separate target for copying output while you can set up output directory in build target itself as follow (example for MSBUILD) .
you can set path like OutDir and sourcecode path according to location of build script (example for build script at the root of application)
Target "Build" (fun _ ->
!! "**/*.csproj"
-- "**/*.Tests.csproj"
|> MSBuildRelease OutDir "Rebuild"
|> Log "Building Projects: "
please refer http://fsharp.github.io/FAKE/apidocs/fake-msbuildhelper.html for more info.

If you want to copy every file (eg. *.*) a filter predicate of (fun x -> true) is enough.
Target "Copy-Build-Output" (fun _ ->
let baseDir = (sourceDir + #"Trunk\Webroot")
let outputfiles =
!! (sourceDir ## "**/*.*")
-- (sourceDir ## "**/*.cs")
-- (sourceDir ## "**/*.csproj")
-- (sourceDir ## "**/*.vspscc")
-- (sourceDir ## "**/*.cssscc")
-- (sourceDir ## "web.config")
-- (sourceDir ## "bin/*.xml")
-- (sourceDir ## "obj/**")
CopyDir outputDir baseDir (fun x -> true)
)
The filter predicate is a function string -> bool. That is any function taking a string as input and returning a bool.
So for copying only .png images you could use (fun x -> x.EndsWith(".png")).
There is probably other methods for specifying files. But this work for me.

Related

Merge multiple output chunks to one file in nextflow

I have a nextflow process that outputs multiple files, like below:
[chr1,/path/to/chr1_chunk1.TC.linear]
[chr1,/path/to/chr1_chunk1.HDL.linear]
[chr1,/path/to/chr1_chunk2.TC.linear]
[chr1,/path/to/chr1_chunk2.HDL.linear]
.....
The above example I got after using transpose() operator.
Now, I want to concatenate All chunks and all chromosome together ordered by chunk and chromosome number so that I get 1 file for TC and another file for HDL. I have multiple traits in many chunks so this link wouldn't be helpful. output files (chromosomal chunks) merging in nextflow
Any help?
You can use a combination of the branch and collectFile operators. Look at the following directory structure below (where the .linear files have their names as contents):
➜ sandbox tree .
.
├── ex1.HDL.linear
├── ex1.TC.linear
├── ex2.HDL.linear
├── ex2.TC.linear
├── ex3.HDL.linear
├── ex3.TC.linear
└── example.nf
I wrote the following minimal reproducible example:
workflow {
files = Channel.fromPath('**.linear', checkIfExists: true)
files
.branch {
TC: it.name.contains('TC')
HDL: it.name.contains('HDL')
}
.set { result }
result
.TC
.collectFile(name: 'TC.txt', storeDir: '/Users/mribeirodantas/sandbox')
result
.HDL
.collectFile(name: 'HDL.txt', storeDir: '/Users/mribeirodantas/sandbox')
}
After running this pipeline with nextflow run example.nf, I will get in the /Users/mribeirodantas/sandbox folder two new files: TC.txt and HDL.txt. The content of TC.txt, for example, is:
ex2.TC.linear
ex3.TC.linear
ex1.TC.linear
If your chunk files are sufficiently small, you can use the collectFile operator to concatenate them into files with names defined using a dynamic grouping criteria:
The grouping criteria is specified by a closure that must return a
pair in which the first element defines the file name for the group
and the second element the actual value to be appended to that file.
To sort by chromosome number and then by chunk number, you can use the toSortedList and flatMap operators to feed the sorted collection into the collectFile operator:
input_ch
.map { key, chunk_file ->
def matcher = chunk_file.name =~ /^chr(\d+)_chunk(\d+)\.(\w+)\.linear$/
def (_, chrom, chunk, trait) = matcher[0]
tuple( (chrom as int), (chunk as int), trait, chunk_file )
}
.toSortedList( { a, b -> (a[0] <=> b[0]) ?: (a[1] <=> b[1]) } )
.flatMap()
.collectFile( sort: false ) { chrom, chunk, trait, chunk_file ->
[ "${trait}.linear", chunk_file.text ]
}

How do you specify Fake Target inputs and output?

In the build systems that I'm familiar with (make and msbuild) there's a way to specify the inputs and outputs for a target. If the time stamps on the input files are earlier than those on the outputs the task is skipped. I can't find something similar in FAKE.
For example if I wanted to translate this Makefile to Fake
a.exe: a.fs
fsharpc a.fs -o a.exe
it might look like:
Target "a.exe" (fun _ -> ["a.fs"] |> FscHelper.compile [...])
However, when I run the build command it will always execute the compiler and produce a new a.exe regardless the modification time on a.fs. Is there a simple way to get the same behavior as the makefile?
You could use =?>and provide a function that returns true or false if the task should run.
let fileModified f1 f2 =
FileInfo(f1).LastWriteTime > FileInfo(f2).LastWriteTime
and then in target dependencies
=?> ("a.exe", fileModified "a.fs" "a.exe")
A more complete code example to flesh out Lazydevs answer:
#r "packages/FAKE/tools/FakeLib.dll"
open Fake
open System.IO
Target "build" (fun _ ->
trace "built"
)
let needsUpdate f1 f2 =
let lastWrite files =
files
|> Seq.map (fun f -> FileInfo(f).LastWriteTime)
|> Seq.max
let t1 = lastWrite f1
let t2 = lastWrite f2
t1 > t2
let BuildTarget name infiles outfiles fn =
Target name (fn infiles)
name =?> ("build", needsUpdate infiles outfiles)
BuildTarget "compile" ["Test2.fs"; "Test1.fs"] ["Test2.dll"] (fun files _ ->
files
|> FscHelper.compile [
FscHelper.Target FscHelper.TargetType.Library
]
|> function 0 -> () | c -> failwithf "compile error"
)
RunTargetOrDefault "build"

Difference between .absolute and .abspath

Is there one? They both yield the same string
given 'file.txt'.IO -> $io {
say $io."$_" for <path abspath absolute>
}
# file.txt
# /Users/Me/file.txt
# /Users/Me/file.txt
The method Path::IO::absolute got a multi candidate that accepts a prefix to be glued in-between the current work dir and the filename or path fragment provided as a Path::IO instance.
dd 'file.txt'.IO.absolute('foo');
OUTPUT«"/home/camelia/foo/file.txt"␤»

Fake: What is the difference between fileset selectors: !!, ++ and !+

There are different fileset selectors in FAKE. What is the difference between these: !!, ++, !+?
I found these examples:
Example 1:
// Filesets
let appReferences =
!! "src/app/**/*.csproj"
++ "src/app/**/*.fsproj"
Example 2:
// files
let appReferences =
!+ "./src/**/*.fsproj"
|> Scan
Example 3:
let filesToZip =
!+ (buildDir + "/**/*.*")
-- "*.zip"
|> Scan
!+ "./src/**/*.fsproj"
|> Scan
is obsolete and replaced by !!
-- "*.zip"
excludes files from the fileset above.

Easiest way to set msbuild logging verbosity in fake?

I have a target that looks like this:
Target "builddotnetcode" (fun _ ->
!! "../Mercury.sln"
|> MSBuildRelease null "Clean,Build"
|> Log "MercuryBuild - Output: "
)
I want to simply set the verbosity in there somewhere. As far as I can tell from the docs you need to specify the Verbosity member of the MSBuildParams object. But build is the only MSBuildHelper function that provides a way to pass a MSBuildParams. Using build I then need to specify Configuration=Release property, the project list, and remove the pipeline to the Log. It seems like there ought to be a simpler way that does not cause me to redefine the entire task. Am I missing something?
So what i did is the following. The reason i did is it this was as I want to create a log file per solution file that I am building
let loggerConfig : list<MSBuildFileLoggerConfig> = [
{
Number = 1
Filename = Some (baseDir + name + "_build.log")
Verbosity = Some MSBuildVerbosity.Minimal
Parameters = Some [MSBuildLogParameter.Append]
}
]
let setParams defaults =
{ defaults with
Verbosity = Some MSBuildVerbosity.Minimal
Targets = ["Build"]
MaxCpuCount = Some (Some 4)
FileLoggers = Some loggerConfig
ToolsVersion = Some "12.0"
Properties =
[
"Optimize", "True"
"DebugSymbols", "True"
"Configuration", buildMode
]
}
Lastly the only msbuild task that I could see that will let you override the msbuilddefaults was standard build.
build setParams solution
|> DoNothing