Referencing an executable from F# - f#

I've used F# to do some quick data-analysis using datastructures from another project. To do so, it needs access to this project; i.e. it needs an assembly reference - but the project is an executable.
I've tried this in F# interactive, and it almost works*; I can #I the appropriate path and #r the executable and a few support dll's - but I can't actually use em. And whatever I do, I can't get the reference into a compiled F# program: VS lets me add a reference just fine, and the appropriate compiler option -r:X:full\path\here.exe is correctly generated by the project, but none of the datastructures are present and the compiler complains of non-existent namespaces; it's as if the reference didn't exist. The application is 64-bit, which may be relevant. 64-bit dll's work fine.
(*) after setting fsi.exe to run in 64-bit mode it thinks it can load it, but actually using it returns FS0193: internal error.
How can I reference a managed 64-bit executable from an F# project?

To others with this same issue: as a workaround, I'm now compiling the executable as Any CPU (which will be executed in 64-bit mode, so behaves the same). This allows FSI and the compiler to reference it. Based on the questions referenced in the comments, this seems to be a known bug that will hopefully be fixed some day.

Related

Why can I compile 64 bit Delphi libraries through runtime package but not through source?

We are just starting on migrating some of our projects to 64-bit in Delphi, we also have a couple of 3rd party Delphi libraries that we are using.
Traditionally, when we use a 3rd party library we do so by using the design time package .bpl OR we just have the compiler compile the source code.
However, in 64-bit it seems we have to do it completely differently. If we are compiling a 64-bit library we need to use DCU.
For example, we have a library that we needed to use in 64-bit. The library supports 64-bit. To get it to work, I had to compile the runtime package as 64-bit then point the compiler to the outputted 64-bit DCU files. When I try to compile the library from source as 64-bit we get all kinds of errors.
So my question basically is: Why/How can we compile the source code through the runtime packages in 64-bit just fine, but when we try to compile as just source code in 64-bit we get errors?
To further illustrate just in case that wasn't clear:
A. Put all source files on search path. Compile program as 64-bit. ERRORS.
B. Open up supplied runtime .dproj from 3rd party library. Compile runtime library as 64-bit. Put outputted 64-bit DCU on search path. Compile program. Works fine.
Thanks
Edit: I'm going to be much more specific because it appears that i have failed in conveying what I'm trying to ask here.
We are using Clever Internet Suite 9.1 for Delphi.
We DO NOT use the design time package when compiling in 32-bit. We link directly to the source code through Delphi's search path. This works fine.
When I change my application to build as 64-bit We get this error:
[dcc64 Error] clSocket.pas(1971): E2089 Invalid typecast
A sample of the offending code (Slightly changed):
procedure cldostuff.WndProc(var Message: TMessage);
begin
if (Message.Msg = cl_const)
and (clSpecialType(Message).LookupHandle = FLookupHandle) then
begin
syncerror:= clSpecialType(Message).syncerror;
SetEvent(FCompleted);
end;
end;
The error is on the casting of the TMessage. I understand why TMessage would cause an error. I am not concerned about the error.
I am curious as to HOW compiling through a "package" works but not in DCU. Apparently I have misused the terminology of "Runtime package". I will post exactly what the clever developers told me on how to use in 64 bit.
The Clever Internet Suite fully supports 64-bit platform. The installer includes binaries for both 32-bit and 64-bit. Also, if you want to re-compile the library, you need to switch the platform option within the clinetsuite_x.dproj file, and recompile it (where _x depends on your Delphi version, e.g., in case of Delphi 10.3 Rio, the project file will be clinetsuite_103.dproj).
So I do Exactly that. I open up that .Dproj file and compile it. Once I do that it creates a Win64/Output folder that has ALL the dcus of the library. I can link to that and work in win64 bit just fine.
My questions is WHY does it work when I compile through the "Supplied .dproj file" but not when I compile through source code.
Hopefully I've done a better job of articulating what I am asking.
That compiler error is typically caused by a typecast between two value types of different size. If the code works in some compilation scenarios but not others then the obvious conclusion is that the record alignment options differ in those scenarios.
Most likely the package dproj file defines aligned records, i.e. {$ALIGN ON}. But your project does not. Perhaps it uses packed alignment, {$ALIGN 1}.
Make sure that all the units in the library are compiled with the same options as specified in the package dproj file. Typically that is done by the library providing an include file that specifies desired options and then the include file is included in all units. That insulates the code from compiler options specified in the host dproj file that are incompatible with those that the code requires.
You can add such a common include file since you have the source. In the longer term you should ask the developers of the library to make their code standalone and not require external specification of critical compiler options.

Same code, missing qtintf70.dll

Compiling some old code, my application will no longer run. Newly compiled exe-file won't start "because qtintf70.dll is missing from your computer".
Strange thing: an older exe file compiled from exact same code runs just fine. Both exe files tested on same system, but compiled on different Delphi installations (both Delphi 7 running on VirtualBox).
Googling, someone suggested "You have pulled in Clx somehow. Clx apps require the QT library. Look for units in your uses clauses that start with Q." but again: this is the exact same code. I've checked and can't find anything.
Suggestions?
In D7, the only source code units which reference qtintf70.dll are QForms.Pas and Qt.Pas.
So, what you need to do is to
Move all instances of these two files and their corresponding .DCU files to somewhere not on your project's search paths. Use a utility like SwiftSearch to make sure you find all of them.
Do a full build of the project.
The build should grind to a halt somewhere with a complaint that the compiler can't find one or other of these units. The source unit that is being compiled at the time is the one which contains a reference to one or other of them.

how to build custom system.pas in delphi to create system.dcu? [duplicate]

I have this craving to do some experiments with modifying the underbelly of the Delphi run time library (RTL), system.pas and the likes... It is possible or not?
I'm very fond of challenges like "yes, but you'll have to provide custom .obj files for some assembler wizardry because they were never distributed with the official Delphi source". Fine with me, I just want to know.
I want to do this experiment with Delphi 7, but inside information on any other version is fine. It is one of the perks of being with a company that worked with Delphi since the Stone Age.
(I always figured this to be one of those RTFM questions, with the answer being a resounding "NO!", but for some reason google won't confirm it.)
You can recompile the RTL like any other unit.
For System.pas you must use the command line compiler.
For instance, here is a working batch file content (there is some not well documented command line switches):
del *.dcu /s
"c:\program files\borland\delphi7\bin\dcc32.exe" -O+ -Q -M -Y -Z -$D+ System.pas
This will recompile System.pas and SysInit.pas (both lowest level RTL files).
But in order to use your recreated dcu files, you'll have to put the folder containing the updated dcu files into the first position of your IDE: for instance, in Delphi 7 it's Option / Environment Options / Library, then put your folder FIRST in both "Libary path" and "Browsing path" field.
And it's perhaps worth deleting the original .dcu files in your Delphi installation directory.
But be sure you won't change the "interface" part of the unit, or you'll have troubles with compiling with other not modified units of the RTL (or third-party components). You can change the "implementation" part, apply fixes or rewrite some part for speed or such, but don't change the "interface" part to avoid any linking error.
Always make a backup of the original .pas and .dcu files which you are changing. And it's a good idea to make some automated compilation test, so that you could be sure that your modifications of the RTL won't add any regression.
We made such a RTL recompilation for our Enhanced Run Time Library for better speed of low-level RTL functions (mostly System.pas and SysUtils.pas). Designed for Delphi 7 and 2007. For more recent Delphi version, you still can use the same principle.
You can only recompile the RTL from the command-line. There should be a makefile in the RTL source directory of your installation. It is designed to be used with the make.exe command-line utility which should be in the "bin" folder of your installation. I would recommend you copy the relevant sources to a separate location for experimentation. I must caution you that the System unit is tightly coupled with the compiler which expects many functions to have a specific name and have particular parameter lists, if any are even declared. Many RTL "helper" functions don't have any formally declared parameters, yet expect parameters to be passed in a certain fashion.
Another bit of caution is changing the interface declarations of certain classes, functions or types. Doing so may cause serious incompatibilities with existing DCU files and components. For this reason you must be very careful when intermixing DCU files from the included RTL or third-party components with your custom modified versions. I would suggest you start by only making implementation section changes only before venturing into the mine-field of interface breaking changes.

TEmbeddedWB & Console

When I tried to compile EmbeddedWB in Console it complains about some OleCtrls unit. Yet normal Webbrowser compiles without no problem.
How to compile it under Console?
[dcc64 Fatal Error] SHDocVw_EWB.pas(66): F1026 File not found: OleCtrls.dcu'
The issue is unit scope names. A console application by default has different unit namespace aliases from a forms application. Solve the problem by either:
Using fully qualified unit names. The full name for that unit is Vcl.OleCtrls.
Add missing unit scope names (in your case Vcl) to your console application's project configuration.
Since you are compiling third party code, it will be preferable for you not to modify that third party code. Hence option 2 is the way forward.
There may be other unit scope names that are needed. Make sure you add them all. And make sure that you are using the latest source for the component, obtained from the VCS repo and double check that it does indeed support XE4.
Note that my assumption is that by console you mean a console application. If you actually mean command line compilation then the answer is still essentially the same. You'll need to make sure that the unit scope names are specified when compiling. Normally that would be done in the project configuration and msbuild would pick them up and pass them on to dcc32 or dcc64.

F# powerpack and distribution

I need arbitrary precision rational numbers, which I'm given to understand are available in the F# powerpack. My question is about the mechanics of distribution; my program needs to be able to compile and run both on Windows/.Net and Linux/Mono at least, since I have potential users on both platforms. As I understand it, the best procedure is:
Download the powerpack .zip, not the installer.
Copy the DLL into my program directory.
Copy the accompanying license file into my program directory, to make sure everything is above board.
Declare references and go ahead and use the functions I need.
Ship the above files along with my source and binary, and since the DLL uses byte code, it will work fine on any platform.
Is this the correct procedure? Am I missing anything?
You're essentially correct, arbitrary precision rational numbers are available only in PowerPack (BigInteger is part of .NET 4.0, but rationals are still F# specific).
However, you'll also need to distribute your program with F# runtime redistributable (that is the FSharp.Core.dll assembly). It contains some basic F# types (such as types used to represent functions) that are not a part of standard .NET runtime.
More information about F# Redistributable Package is available at MSDN
You can download the FSharp.Core.dll redist from Microsoft Downloads.
When you add a reference to your project, the compiler includes the name and version of the referenced library in your application. When the application starts, the runtime tries to locate the library in various places. So, to deploy your application on both .NET and Mono, you'll need to (somehow) distribute your application together with FSharp.Core.dll and FSharp.PowerPack.dll.
The F# Redistributable and F# PowerPack installers place the library to GAC (Global Assembly Cache) which is shared by all .NET apps on the computer. On Mono, you can get the same result by using the gacutil tool (from command line). In that case, you need to copy them somewhere (anywhere) and run this tool. Your application will find them in the GAC.
Alternatively, if you place the assemblies to the same folder as your application (exe file) then both .NET and Mono should locate them correctly as well and it should work. I believe that this is discouraged for versioning reasons (e.g. the globally installed file can be easily updated), but I don't think the license prohibits this form of deployment.
It seems that for creating .NET/Mono redistributable, using the second technique would be easier (as it allows simple xcopy depoloyment).

Resources