@@ -191,49 +191,100 @@ module internal FSharpEnvironment =
191191// - default location of fsi.exe in FSharp.VS.FSI.dll
192192// - default location of fsc.exe in FSharp.Compiler.CodeDom.dll
193193// - default F# binaries directory in (project system) Project.fs
194- let BinFolderOfDefaultFSharpCompiler =
195- // Check for an app.config setting to redirect the default compiler location
196- // Like fsharp-compiler-location
197- try
198- let result = tryAppConfig" fsharp-compiler-location"
199- match resultwith
200- | Some_ -> result
201- | None->
194+
195+ /// Try to find the F# compiler location by looking at the "fsharpi" script installed by F# packages
196+ let internal tryFsharpiScript ( url : string ) =
197+ try
198+ let str = File.ReadAllText( url)
199+ let reg = new System.Text.RegularExpressions.Regex( " mono.* (\/ .*)\/ fsi\. exe" )
200+ let res = reg.Match( str)
201+ if res.Successthen Some( res.Groups.[ 1 ]. Value) else None
202+ with e->
203+ None
202204
203- // Note: If the keys below change, be sure to update code in:
204- // Property pages (ApplicationPropPage.vb)
205205
206- #if FX_ ATLEAST_ 45
207- let key20 = @" Software\Microsoft\FSharp\3.0\Runtime\v2.0"
208- let key40 = @" Software\Microsoft\FSharp\3.0\Runtime\v4.0"
209- #else
210- let key20 = @" Software\Microsoft\FSharp\2.0\Runtime\v2.0"
211- let key40 = @" Software\Microsoft\FSharp\2.0\Runtime\v4.0"
212- #endif
213- let key1 , key2 =
214- match FSharpCoreLibRunningVersionwith
215- | None-> key20, key40
216- | Some v-> if v.Length> 1 && v.[ 0 ] <= '3' then key20, key40else key40, key20
206+ let BackupInstallationProbePoints =
207+ [ // prefer the latest installation of Mono on Mac
208+ " /Library/Frameworks/Mono.framework/Versions/Current"
209+ // prefer freshly built F# compilers on Linux
210+ " /usr/local"
211+ // otherwise look in the standard place
212+ " /usr" ]
213+
214+ // The default location of FSharp.Core.dll and fsc.exe based on the version of fsc.exe that is running
215+ // Used for
216+ // - location of design-time copies of FSharp.Core.dll and FSharp.Compiler.Interactive.Settings.dll for the default assumed environment for scripts
217+ // - default ToolPath in tasks in FSharp.Build.dll (for Fsc tasks)
218+ // - default F# binaries directory in service.fs (REVIEW: check this)
219+ // - default location of fsi.exe in FSharp.VS.FSI.dll
220+ // - default location of fsc.exe in FSharp.Compiler.CodeDom.dll
221+ let BinFolderOfDefaultFSharpCompiler () =
222+ // Check for an app.config setting to redirect the default compiler location
223+ // Like fsharp-compiler-location
224+ try
225+ // FSharp.Compiler support setting an appkey for compiler location. I've never seen this used.
226+ //printfn "Resolution" "BinFolderOfDefaultFSharpCore: Probing app.config"
227+ let result = tryAppConfig" fsharp-compiler-location"
228+ match resultwith
229+ | Some_ -> result
230+ | None->
231+
232+ // On windows the location of the compiler is via a registry key
233+ let key20 = @" Software\Microsoft\FSharp\2.0\Runtime\v4.0"
234+ let key40 = @" Software\Microsoft\FSharp\3.0\Runtime\v4.0"
235+ let key1 , key2 =
236+ match FSharpCoreLibRunningVersionwith
237+ | None-> key40, key20
238+ | Some v-> if v.Length> 1 && v.[ 0 ] <= '3' then key20, key40else key40, key20
239+
240+ //printfn "Resolution" "BinFolderOfDefaultFSharpCore: Probing registry key %s" key1
241+ let result = tryRegKey key1
242+ match resultwith
243+ | Some_ -> result
244+ | None->
245+ //printfn "Resolution" "BinFolderOfDefaultFSharpCore: Probing registry key %s" key2
246+ let result = tryRegKey key2
247+ match resultwith
248+ | Some_ -> result
249+ | None->
250+
251+ // On Unix we let you set FSHARP_COMILER_BIN. I've rarely seen this used and its not documented in the install isntructions.
252+ //printfn "Resolution" "BinFolderOfDefaultFSharpCore: Probing environment variable FSHARP_COMPILER_BIN"
253+ let result =
254+ let var = System.Environment.GetEnvironmentVariable( " FSHARP_COMPILER_BIN" )
255+ if String.IsNullOrEmpty( var) then None
256+ else Some( var)
257+ match resultwith
258+ | Some_ -> result
259+ | None->
260+
261+ // On Unix we probe 'bin' under various hardwired paths for the scripts 'fsharpc' and 'fsharpi'.
262+ // We then loko in the script to see the Mono location it is pointing to.
263+ // This is pretty fragile, e.g. the script lookup is done via a regular expression.
264+ // Really we should just search the path or otherwise resolve the 'mono' command?
265+ let result =
266+ BackupInstallationProbePoints|> List.tryPick( fun x ->
267+ //printfn "Resolution" "BinFolderOfDefaultFSharpCore: Probing %s" x
268+ let safeExists f = ( try File.Exists( f) with _ -> false )
269+ let file f = Path.Combine( Path.Combine( x, " bin" ), f)
270+ let exists f = safeExists( file f)
271+ match ( if exists" fsc" && exists" fsi" then tryFsharpiScript( file" fsi" ) else None) with
272+ | Some res-> Some res
273+ | None->
274+ match ( if exists" fsharpc" && exists" fsharpi" then tryFsharpiScript( file" fsharpi" ) else None) with
275+ | Some res-> Some res
276+ | None-> None)
217277
218- let result = tryRegKey key1
219- match resultwith
220- | Some_ -> result
221- | None->
222- let result = tryRegKey key2
223- match resultwith
224- | Some_ -> result
225- | None->
226-
227- // This was failing on rolling build for staging because the prototype compiler doesn't have the key. Disable there.
228- #if FX_ ATLEAST_ 40_ COMPILER_ LOCATION
229- System.Diagnostics.Debug.Assert( result<> None, sprintf" Could not find location of compiler at '%s ' or '%s '" key1 key2)
230- #endif
231-
232- // For the prototype compiler, we can just use the current domain
233- tryCurrentDomain()
234- with e->
235- System.Diagnostics.Debug.Assert( false , " Error while determining default location of F# compiler" )
236- None
278+ match resultwith
279+ | Some_ -> result
280+ | None->
281+ // For the prototype compiler, we can just use the current domain
282+ tryCurrentDomain()
283+ with e->
284+ System.Diagnostics.Debug.Assert( false , " Error while determining default location of F# compiler" )
285+ //printfn "Resolution" "BinFolderOfDefaultFSharpCore: error %s" (e.ToString())
286+ None
287+
237288
238289#endif // SILVERLIGHT
239290#if FX_ ATLEAST_ 45