I am using Delphi XE2 and I have a program that can be compiled as Win32 EXE or ISAPI DLL. That works fine.
However my problem is how to conditionally compile.
{$include MyConditionals.Inc}
{$ifdef ISAPISERVER}
library
{$else}
program
{$endif}
MyProgram;
That works, but the FILE extension is getting wrong. It generates an EXE extension always. I need that when selected the library condition to have the DLL extension generated.
How can easily change the condition and have the right extension?
AFAIK you can't use a conditional compilation to change the extension of the binary. The extension of the file is set in the build process depending of the value (Application, Library, Console) for the AppType entry in the .dproj file. My recommendation is create a build batch file for the dll and another for the application.
Apparently, IDE itself is preventing you from doing that. I successfully produced both executable binary and dynamic-link library from the following source:
{$IFDEF CGI}program{$ELSE}library{$ENDIF} test;
begin
end.
using dcc32 -DCGI test.pas and dcc32 -DNSAPI test.pas commands.
Delphi IDE thinks what it "owns" the project source, so it is advised against placing conditional directives there even in newer MSBuild-based IDEs.
Related
I'm creating a Delphi package using OpenGL and the GLEW extension. I downloaded GLEW from the official website. That was a painful way to make it usable with Embarcadero, but I finally succeeded. At this point, I'm able to compile and use GLEW in any C++ Builder or Delphi application project.
However, I experiment difficulties to use GLEW in my Delphi package. As GLEW is a DLL, I declare the external functions that I need as in the following example:
procedure glBindVertexArray(glArray: GLuint); external 'glew32.dll' name '__glewBindVertexArray';
This works well when I compile an application project, so I'm sure that the declaration is correct. I can compile and link my package without problems. However, when I try to use it in a demo project, I receive the following link error:
[ilink32 Error] Error: Unresolved external '__glewBindVertexArray' referenced from C:\USERS\PUBLIC\DOCUMENTS\EMBARCADERO\STUDIO\15.0\DCP\QRMODELS.LIB|TQRMD2_OpenGL
So my GLEW functions are not found by the linker. The problem is that I don't know how to link an external DLL into a Delphi package. When I try to add the DLL in the "Requires" section, my package can no more be compiled and I receive the following error:
[dcc32 Fatal Error] QRModels.dpk(35): E2202 Required package 'glew32' not found
I also tried to add glew32.lib in my package, and tried to link GLEW in my target project, but without success.
So, what is the correct way to link an external standard DLL, that isn't a .dcp, in Embarcadero Delphi packages? I remember you that I can use this DLL without problems in any Delphi application project, and I own the corresponding .lib too, that is already converted to be used with Embarcadero compiler.
Regards
NOTE: As suggested in the comment posted by David Heffernan, I tried to create a small package that includes an external function to the user32.dll. This worked well. I also tried to include one of my GLEW external function. Now the issue is different: the package links and builds well, and the target project too. But when the exe runs, I get an error message saying that glew32.dll is missing on my computer. So my issue is basically a bad installation of the GLEW library. However, all my other projects using GLEW works well, including those I create with other compilers, as e.g. Code::Blocks.
I also compared my package options, and the only thing that is different is that the package I create is divided in 2 projects, one for the design time and one for the runtime. I already created such other packages without problems, but I never tried to include external DLL in them.
Here is my test unit:
unit Unit1;
interface
uses OpenGL;
function MessageBeep(uType: Cardinal): LongBool; stdcall; external 'user32';
procedure glBindVertexArray(glArray: GLuint); stdcall; external 'glew32.dll' name '__glewBindVertexArray';
type
TTest = class(TObject)
public
procedure TestBeep; virtual;
procedure TestGlew; virtual;
end;
implementation
procedure TTest.TestBeep;
begin
MessageBeep($40);
end;
procedure TTest.TestGlew;
begin
glBindVertexArray(0);
end;
end.
Regards
is it possible for the linker to find 'glew32.dll' (is it in the search path or in the working path of the Debugger)?
maybe this can help you
http://rvelthuis.de/articles/articles-cobjs.html
http://docwiki.embarcadero.com/RADStudio/Sydney/en/Link_object_file_(Delphi)
https://hub.packtpub.com/implementing-c-libraries-in-delphi-for-hpc-tutorial/
The last article is part of Delphi High Performance from Packt (a very good book on Delphi)
By the way, if you want to include a .lib file in Delphi, it is not enough to just add the .lib file to the project. You have to include the .lib file with {$ L 'LibName.lib'}
here's an Embarcadero Link http://docwiki.embarcadero.com/RADStudio/Sydney/en/Link_object_file_(Delphi)
You just have to make sure that your .lib file is in the correct format e.g. OMF, COFF, ELF coz Visual Studio uses COFF, Delphi OMF and C++ Builder ELF
Delphi 64-Bit Windows Compiler http://docwiki.embarcadero.com/RADStudio/Sydney/en/DCC64
Delphi 32-Bit Windows Compiler http://docwiki.embarcadero.com/RADStudio/Sydney/en/DCC32
C++ Builder 64-Bit Windows Compiler http://docwiki.embarcadero.com/RADStudio/Sydney/en/BCC64
if your .lib file is not in the correct format, you can use the following open source project to convert it
https://github.com/gitGNU/objconv
I have to compile my project with a changed VCL unit. I use Delphi XE8. I copied Vcl.StdCtrls.pas from D:\Program Files (x86)\Embarcadero\Studio\16.0\source\vcl to my project folder where my .dpr file is localed, then I changed my copy of Vcl.StdCtrls.pas. I also added this unit to project tree. The problem is that with Delphi XE8 such method of recompiling VCL units no longer works. I put an obvious syntax error in my modified Vcl.StdCtrls.pas unit. Compiler does not report the error which means it does no even check the file. I always do a full build Shift+F9. I found a similar question How to recompile a specific unit from the VCL? but like I said, it no longer works, not for Delphi XE8.
Also, the modified unit is on my uses list in .dpr file:
uses
Vcl.StdCtrls in 'D:\Dev\MYPROJECT\Vcl.StdCtrls.pas',
...
// it does not help
This seems to be a bug. I guess you're using runtime packages. In XE7 such project will not compile - which is the correct behavior. In XE8 it compiles, apparently using the VCL runtime package and ignoring your modified unit.
Edit:
Note that even in previous Delphi versions, modifying a VCL unit while using runtime packages would still require you to repackage the modified packages and their dependencies (in this case, vcl and rtl).
In other words, you cannot simply use a modified unit while linking against a runtime package which contains another copy of that unit. Unit names must be unique within the full scope of the project, including the main executable and all linked runtime packages.
So the solution for you is to either:
not use runtime packages, or
repackage all required units into your own runtime packages, and link against them instead of Embarcadero-supplied rtl, vcl etc.
I found a workaround for a bug (QC#25702) in the Delphi VCL unit Grids.pas, so I copied that file to my project's source folder, added it to the project and changed a few lines of code. That was with Delphi 2007, and everything worked as expected.
Now, with Delphi XE2, the project no longer compiles. It complains about incompatible types "TCustomGrid" and "TdzVirtualStringGrid" (which is a descendant of TCustomGrid). It turns out that one unit refers to TCustomGrid as declared in my copy of Grids.pas, the other to TCustomGrid as declared in Vcl.Grids.pas. This happens even though both units have "Grids" in their uses clause (rather than Vcl.Grids). Any idea how I could solve this?
Your problem is that you are including the Delphi 2007 Grids unit in your XE2 project. That won't work at all. What you need to do to modify an RTL/VCL unit in this way is as follows:
Start with the source code for the unit supplied with the Delphi version that you are using. In this case start with Vcl.Grids.pas supplied with XE2.
Make a copy of that unit inside your project directory, and add that unit to your project.
Make any modifications to the implementation section of the copied unit.
I'm trying to know if the project is a library or not, after read the help I wrote this code that does not work:
{$IF DEFINED(LIBPREFIX)}
{$DEFINE PROJECT_IS_EXECUTABLE}
{$UNDEF PROJECT_IS_LIBRARY}
{$ELSE}
{$DEFINE PROJECT_IS_EXECUTABLE}
{$UNDEF PROJECT_IS_LIBRARY}
{$IFEND}
I tried DEFINED, DECLARED and
{$IF (LIBPREFIX = '')}
Every try always returns the same for DLLs and for programs.
How can I do this using only built-in compiler directives?
EDIT
My intention is to remove the extra information from "PE File".
I do it directly in .dpr project file, so no matter how the other units were compiled, but I can not do the same in DLL projects.
Therefore I was looking a way to block it in DLL projects.
This is how I solved this issue, I add this directives to my .dpr programs:
{$DEFINE STRIPE_PE_INFO}
{$DEFINE STRIPE_RTTI}
{$I DDC_STRIP.inc}
And DDC_STRIP.inc has all the logic.
There's no way to know this when your file is being compiled. A source file can be compiled to a .dcu and then linked into any type of project. A good example are the RTL and VCL units.
Probably the best you can do is to define a conditional in your project options that indicates whether or not the project is a library. But you need to make sure that the .dcu is always re-compiled when you build any project that uses this unit.
You can't determine this at compile time, but at runtime, you can check the SysInit.ModuleIsLib (Delphi 2007) to determine if the code is running in a library (or package).
Best thing I can think of is to set a define in an include file. You could use a pre-build action (bat file) to modify the include file.
I am upgrading from Delphi 6 to Delphi XE. In Delphi 6 I was using HTML help files (.chm) and used the StoHtmlHelp to make it so that I could call context sensitive help like we used to call .hlp files. I'm upgrading to Delphi XE so I need to use that native HTML help support.
I know I'm supposed to add HTMLHelpViewer to the uses clause of the project, but when I do I get a compiler warning that it couldn't find the file.
Could not compile used unit 'HTMLHelpViewer.pas'
Does anyone know why Delphi isn't finding this file by default? It should be built in.
Not being able to compile a file and not finding a file arent't the same thing. If Delphi is trying to compile HTMLHelpViewer.pas you must either:
have the vcl source folder(s) on your library path (not recommended), or
another HTMLHelpViewer.pas file is somewhere on your library path, that path comes before the standard Delphi lib folder, and that HTMLHelpViewer.pas file contains something that Delphi XE is not happy about.
The first is not likely and it would be very strange indeed if Delphi could not compile one of its units (apart from system.pas).
The second seems more likely... And if that unit used to compile, the complaints from Delphi XE could well be due to differences between Delphi 6 and Delphi XE.
You don't actually need to add it the uses clause of the .dpr file – you just need to use it from some unit in your project.
Having said that, you may actually prefer to add it to your .dpr file, and if so then do it like this:
uses
Forms,
HtmlHelpViewer,
MyUnit in 'MyUnit.pas',
I'm guessing that you have something like this:
uses
Forms,
HtmlHelpViewer in 'C:\Program Files\Borland\Delphi6\Source\VCL\HtmlHelpViewer.pas',
MyUnit in 'MyUnit.pas',
This will fail because you are asking XE to compile D6 source.
For RTL/VCL units its best to omit the path to the file and let the compiler find it (it knows where to look).