4 people like it.

FSI dependencies <-> VS dependencies

This script generates a file named __project.fsx, for each proejct which can be #load "__project.fsx" in script intending to use the same dependency graph as the code in VS a file named __solmerged.fsx, at the solution root which can be #load "__solmerged.fsx" in script intending to use the same dependency graph as the code in VS In both cases, this enforce that : **a script compiling in VS should run from FSI **

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
//This script generates 
//a file named __project.fsx, for each proejct which can be #load "__project.fsx" in script intending to use the same dependency graph as the code in VS
//a file named __solmerged.fsx, at the solution root which can be #load "__solmerged.fsx" in script intending to use the same dependency graph as the code in VS
//In both cases, this enforce that a script compiling in VS should work from within FSI 


#if INTERACTIVE
#r "System.Xml"
#r "System.Xml.Linq"
#endif

open System
open System.IO
open System.Xml.Linq

let rec findsolutiondir (p:DirectoryInfo) =  if (p.GetFiles("*.sln") |> Array.length > 0)  then p
                                             else findsolutiondir p.Parent

let root = findsolutiondir (DirectoryInfo(__SOURCE_DIRECTORY__))

type Dependency = 
   | GacLocation of String
   | ProjectFile of DirectoryInfo
   | DllFile of DirectoryInfo

let refsforaproject (dirproject:DirectoryInfo) =   [
         for fsProjFile in dirproject.GetFiles("*.fsproj") do
                 let getElemName name = XName.Get(name, "http://schemas.microsoft.com/developer/msbuild/2003")
                 let getElemValue name (parent:XElement) =
                     let elem = parent.Element(getElemName name)
                     if elem = null || String.IsNullOrEmpty elem.Value then None else Some(elem.Value)

                 let getAttrValue name (elem:XElement) =
                     let attr = elem.Attribute(XName.Get name)
                     if attr = null || String.IsNullOrEmpty attr.Value then None else Some(attr.Value)

                 let (|??) (option1: 'a Option) option2 =
                     if option1.IsSome then option1 else option2

                 let fsProjFile = dirproject.GetFiles("*.fsproj") |> Seq.head
                 let fsProjXml = XDocument.Load fsProjFile.FullName

                 let refspath = 
                     fsProjXml.Document.Descendants(getElemName "Reference")
                     |> Seq.choose (fun elem -> getElemValue "HintPath" elem)
                     |> Seq.map (fun ref ->  //if dirproject.Name.Contains("divsharp") then printfn "fulname : %A" ( DirectoryInfo(dirproject.FullName +  "\\" + ref).FullName)
                                             DllFile(DirectoryInfo(dirproject.FullName +  "\\" + ref)) )
                                             //("#r ", true, DirectoryInfo(dirproject.FullName +  "\\" + ref).FullName) )

                 let refsgac = 
                     fsProjXml.Document.Descendants(getElemName "Reference")
                     |> Seq.choose (fun elem -> if (getElemValue "HintPath" elem).IsNone then getAttrValue "Include" elem else None)
                     |> Seq.map (fun ref -> GacLocation(ref))

                 let fsFiles = 
                     fsProjXml.Document.Descendants(getElemName "Compile")
                     |> Seq.choose (fun elem -> //printfn "%A" elem
                                                getAttrValue "Include" elem)
                     |> Seq.map (fun fsFile -> ProjectFile( DirectoryInfo(dirproject.FullName +  "\\" + fsFile)))
                                               //#load ", true, DirectoryInfo(dirproject.FullName +  "\\" + fsFile).FullName))

                 let projDll = 
                     fsProjXml.Document.Descendants(getElemName "ProjectReference")
                     |> Seq.choose (fun elem -> getAttrValue "Include" elem)
                     |> Seq.map (fun projFile -> let refedPrjDir = DirectoryInfo(dirproject.FullName + "\\" + projFile).Parent
                                                 //("#r " ,  true, refedPrjDir.FullName +   "\\bin\\Debug\\" + refedPrjDir.Name + ".dll"))  //refedPrjDir.Name -> assembly name
                                                 DllFile(DirectoryInfo(refedPrjDir.FullName +   "\\bin\\Debug\\" + refedPrjDir.Name + ".dll")))

                 yield! refspath
                 yield! refsgac
                 yield! projDll
                 yield! fsFiles 
   ]

let toabsolute root rel = DirectoryInfo(root + rel).FullName
let f n = String.concat "." (Array.create (n+1) ".\\")

let writerelative root path = 
      let rec intwriterelative (root:DirectoryInfo) (path:DirectoryInfo) n = 
         if path.FullName.Contains(root.FullName + "\\" ) then f n + path.FullName.Remove(0,root.FullName.Length + 1)    //most common acestor = root
         else intwriterelative root.Parent path (n+1)
      intwriterelative root path 0

let getprojectdir (root:DirectoryInfo) = 
   let rec getdirs (root:DirectoryInfo) = seq {
      yield! root.GetDirectories() |> Array.filter(fun f -> f.GetFiles("*.fsproj") |> Array.length > 0 ) 
      yield! root.GetDirectories() |> Array.map(fun d -> getdirs d) |> Seq.concat}
   getdirs root   

let orderKey = function | GacLocation(n) -> "A" + n
                        | ProjectFile(n) -> "C" + n.FullName
                        | DllFile(n)     -> "B" + n.FullName

let tostrings rootwrite (dependencies) =
    dependencies |> Seq.distinct
                 |> Seq.map (fun dep  -> match dep with
                                         | GacLocation(n) -> "#r \"" + n + "\""
                                         | ProjectFile(n) -> "#load @\"" + writerelative rootwrite n + "\""
                                         | DllFile(n)     -> "#r @\"" + writerelative rootwrite n + "\"")

do 
   let projects = getprojectdir root |> Seq.map(fun p -> p, refsforaproject p)
   
   projects |> Seq.iter (fun (p,ds) ->  File.WriteAllLines(p.FullName+ "\\" + "__project.fsx", tostrings p (ds |> Seq.sortBy orderKey)))
   let s = projects |> Seq.map ( fun (p, dep) -> seq{ yield sprintf "//project %A" p.Name
                                                      yield!  dep |> Seq.sortBy orderKey |> tostrings root } )
                    |> Seq.concat

   File.WriteAllLines(root.FullName+ "\\" + "__solmerged.fsx",  s)
namespace System
namespace System.IO
namespace System.Xml
namespace System.Xml.Linq
val findsolutiondir : p:DirectoryInfo -> DirectoryInfo

Full name: Script.findsolutiondir
val p : DirectoryInfo
Multiple items
type DirectoryInfo =
  inherit FileSystemInfo
  new : path:string -> DirectoryInfo
  member Create : unit -> unit + 1 overload
  member CreateSubdirectory : path:string -> DirectoryInfo + 1 overload
  member Delete : unit -> unit + 1 overload
  member EnumerateDirectories : unit -> IEnumerable<DirectoryInfo> + 2 overloads
  member EnumerateFileSystemInfos : unit -> IEnumerable<FileSystemInfo> + 2 overloads
  member EnumerateFiles : unit -> IEnumerable<FileInfo> + 2 overloads
  member Exists : bool
  member GetAccessControl : unit -> DirectorySecurity + 1 overload
  member GetDirectories : unit -> DirectoryInfo[] + 2 overloads
  ...

Full name: System.IO.DirectoryInfo

--------------------
DirectoryInfo(path: string) : unit
DirectoryInfo.GetFiles() : FileInfo []
DirectoryInfo.GetFiles(searchPattern: string) : FileInfo []
DirectoryInfo.GetFiles(searchPattern: string, searchOption: SearchOption) : FileInfo []
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val length : array:'T [] -> int

Full name: Microsoft.FSharp.Collections.Array.length
property DirectoryInfo.Parent: DirectoryInfo
val root : DirectoryInfo

Full name: Script.root
type Dependency =
  | GacLocation of String
  | ProjectFile of DirectoryInfo
  | DllFile of DirectoryInfo

Full name: Script.Dependency
union case Dependency.GacLocation: String -> Dependency
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
union case Dependency.ProjectFile: DirectoryInfo -> Dependency
union case Dependency.DllFile: DirectoryInfo -> Dependency
val refsforaproject : dirproject:DirectoryInfo -> Dependency list

Full name: Script.refsforaproject
val dirproject : DirectoryInfo
val fsProjFile : FileInfo
val getElemName : (string -> XName)
val name : string
type XName =
  member Equals : obj:obj -> bool
  member GetHashCode : unit -> int
  member LocalName : string
  member Namespace : XNamespace
  member NamespaceName : string
  member ToString : unit -> string
  static member Get : expandedName:string -> XName + 1 overload

Full name: System.Xml.Linq.XName
XName.Get(expandedName: string) : XName
XName.Get(localName: string, namespaceName: string) : XName
val getElemValue : (string -> XElement -> string option)
val parent : XElement
Multiple items
type XElement =
  inherit XContainer
  new : name:XName -> XElement + 4 overloads
  member AncestorsAndSelf : unit -> IEnumerable<XElement> + 1 overload
  member Attribute : name:XName -> XAttribute
  member Attributes : unit -> IEnumerable<XAttribute> + 1 overload
  member DescendantNodesAndSelf : unit -> IEnumerable<XNode>
  member DescendantsAndSelf : unit -> IEnumerable<XElement> + 1 overload
  member FirstAttribute : XAttribute
  member GetDefaultNamespace : unit -> XNamespace
  member GetNamespaceOfPrefix : prefix:string -> XNamespace
  member GetPrefixOfNamespace : ns:XNamespace -> string
  ...

Full name: System.Xml.Linq.XElement

--------------------
XElement(name: XName) : unit
XElement(other: XElement) : unit
XElement(other: XStreamingElement) : unit
XElement(name: XName, content: obj) : unit
XElement(name: XName, [<ParamArray>] content: obj []) : unit
val elem : XElement
XContainer.Element(name: XName) : XElement
String.IsNullOrEmpty(value: string) : bool
property XElement.Value: string
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val getAttrValue : (string -> XElement -> string option)
val attr : XAttribute
XElement.Attribute(name: XName) : XAttribute
property XAttribute.Value: string
val option1 : Option<'a>
module Option

from Microsoft.FSharp.Core
val option2 : Option<'a>
property Option.IsSome: bool
module Seq

from Microsoft.FSharp.Collections
val head : source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.head
val fsProjXml : XDocument
Multiple items
type XDocument =
  inherit XContainer
  new : unit -> XDocument + 3 overloads
  member Declaration : XDeclaration with get, set
  member DocumentType : XDocumentType
  member NodeType : XmlNodeType
  member Root : XElement
  member Save : fileName:string -> unit + 6 overloads
  member WriteTo : writer:XmlWriter -> unit
  static member Load : uri:string -> XDocument + 7 overloads
  static member Parse : text:string -> XDocument + 1 overload

Full name: System.Xml.Linq.XDocument

--------------------
XDocument() : unit
XDocument([<ParamArray>] content: obj []) : unit
XDocument(other: XDocument) : unit
XDocument(declaration: XDeclaration, [<ParamArray>] content: obj []) : unit
XDocument.Load(reader: Xml.XmlReader) : XDocument
XDocument.Load(textReader: TextReader) : XDocument
XDocument.Load(stream: Stream) : XDocument
XDocument.Load(uri: string) : XDocument
XDocument.Load(reader: Xml.XmlReader, options: LoadOptions) : XDocument
XDocument.Load(textReader: TextReader, options: LoadOptions) : XDocument
XDocument.Load(stream: Stream, options: LoadOptions) : XDocument
XDocument.Load(uri: string, options: LoadOptions) : XDocument
property FileSystemInfo.FullName: string
val refspath : seq<Dependency>
property XObject.Document: XDocument
XContainer.Descendants() : Collections.Generic.IEnumerable<XElement>
XContainer.Descendants(name: XName) : Collections.Generic.IEnumerable<XElement>
val choose : chooser:('T -> 'U option) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.choose
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
Multiple items
val ref : string

--------------------
type 'T ref = Ref<'T>

Full name: Microsoft.FSharp.Core.ref<_>
val refsgac : seq<Dependency>
val fsFiles : seq<Dependency>
val fsFile : string
val projDll : seq<Dependency>
val projFile : string
val refedPrjDir : DirectoryInfo
property DirectoryInfo.Name: string
val toabsolute : root:string -> rel:string -> string

Full name: Script.toabsolute
val root : string
val rel : string
val f : n:int -> string

Full name: Script.f
val n : int
val concat : sep:string -> strings:seq<string> -> string

Full name: Microsoft.FSharp.Core.String.concat
val create : count:int -> value:'T -> 'T []

Full name: Microsoft.FSharp.Collections.Array.create
val writerelative : root:DirectoryInfo -> path:DirectoryInfo -> string

Full name: Script.writerelative
val root : DirectoryInfo
val path : DirectoryInfo
val intwriterelative : (DirectoryInfo -> DirectoryInfo -> int -> string)
String.Contains(value: string) : bool
String.Remove(startIndex: int) : string
String.Remove(startIndex: int, count: int) : string
property String.Length: int
val getprojectdir : root:DirectoryInfo -> seq<DirectoryInfo>

Full name: Script.getprojectdir
val getdirs : (DirectoryInfo -> seq<DirectoryInfo>)
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
DirectoryInfo.GetDirectories() : DirectoryInfo []
DirectoryInfo.GetDirectories(searchPattern: string) : DirectoryInfo []
DirectoryInfo.GetDirectories(searchPattern: string, searchOption: SearchOption) : DirectoryInfo []
val filter : predicate:('T -> bool) -> array:'T [] -> 'T []

Full name: Microsoft.FSharp.Collections.Array.filter
val f : DirectoryInfo
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val d : DirectoryInfo
val concat : sources:seq<#seq<'T>> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.concat
val orderKey : _arg1:Dependency -> string

Full name: Script.orderKey
val n : String
val n : DirectoryInfo
val tostrings : rootwrite:DirectoryInfo -> dependencies:seq<Dependency> -> seq<string>

Full name: Script.tostrings
val rootwrite : DirectoryInfo
val dependencies : seq<Dependency>
val distinct : source:seq<'T> -> seq<'T> (requires equality)

Full name: Microsoft.FSharp.Collections.Seq.distinct
val dep : Dependency
val projects : seq<DirectoryInfo * Dependency list>
val iter : action:('T -> unit) -> source:seq<'T> -> unit

Full name: Microsoft.FSharp.Collections.Seq.iter
val ds : Dependency list
type File =
  static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
  static member AppendAllText : path:string * contents:string -> unit + 1 overload
  static member AppendText : path:string -> StreamWriter
  static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
  static member Create : path:string -> FileStream + 3 overloads
  static member CreateText : path:string -> StreamWriter
  static member Decrypt : path:string -> unit
  static member Delete : path:string -> unit
  static member Encrypt : path:string -> unit
  static member Exists : path:string -> bool
  ...

Full name: System.IO.File
File.WriteAllLines(path: string, contents: Collections.Generic.IEnumerable<string>) : unit
File.WriteAllLines(path: string, contents: string []) : unit
File.WriteAllLines(path: string, contents: Collections.Generic.IEnumerable<string>, encoding: Text.Encoding) : unit
File.WriteAllLines(path: string, contents: string [], encoding: Text.Encoding) : unit
val sortBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Seq.sortBy
val s : seq<string>
val dep : Dependency list
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
Raw view Test code New version

More information

Link:http://fssnip.net/ds
Posted:12 years ago
Author:nicolas2
Tags: fsi , references , dependencies , dll