How do I compile my Delphi project on the command line? - delphi

Has anyone ever managed to compile their Delphi 6 & 7 (NOT any Delphi > 7 ) projects using the command line?
All the instructions I see are not very clear on what exactly needs to go where!
Am looking for step-by-step kind of instructions.
Answers should be limited to Delphi 6 & 7: I understand Delphi 2006 and > uses MSBuild which is far much easier.
Links are also high appreciated.
Gath

This is not difficult to do. I have a standard Delphi 5 install on my machine here, and when I open a command prompt, navigate to the $(DELPHI)\Demos\Threads directory and enter dcc32.exe thrddemo.dpr the application is built on the command line.
For your own project you may need to add some switches to include file directories, output directories, defines or similar things. Running dcc32.exe without parameters gives a list of switches and parameters. It is all described in the documentation, as well.
For repeatability you should create a batch file or a regular Makefile.
Note that both the project cfg file and the common dcc32.cfg in the Delphi directory contain important settings. For some information about how they affect the build see for example this link on Delphi Wikia.

For build automation, I use Apache Ant, which is a software tool for automating software build processes. I use it for all my projects, from Delphi 6 to Delphi 2009, and Free Pascal.
Things it can do "out of the box" include MD5 checksum generation, ZIP file creation, text search/replace (useful for copyright header generation), execution of SQL statements, XSLT processing.
For example, to compile all projects with Delphi 6, this is (a part of) the script:
<target name="compile_d6">
<!-- Compile with Delphi 6 -->
<apply executable="${d6}\Bin\dcc32" failonerror="true" output="build-d6.log" >
<!-- rebuild quiet -->
<arg value="-B"/>
<arg value="-Q"/>
<!-- file paths -->
<arg value="-I${source};${indy10}/Lib/System"/>
<arg value="-O${source};${indy10}/D6;${jcl}/d6"/>
<arg value="-U${source};${indy10}/D6;${jcl}/d6"/>
<!-- all *.dpr files in current directory -->
<fileset dir=".">
<patternset><include name="*.dpr"/></patternset>
</fileset>
</apply>
</target>
Free open source CI (Continous Integration) servers like Hudson/Jenkins support Apache Ant build scripts out of the box, which means that you can have them build the project automatically whenever you checked in a change in the source repository.

You can build everything using this command line:
"C:\Program Files\Borland\Delphi7\Bin\DCC32.exe" -Q -B your-project.dpr
Put this line in a .bat file so you don't need to type it always. Take a look at the command line options running this:
"C:\Program Files\Borland\Delphi7\Bin\DCC32.exe" -h
BTW: -Q is quiet compile and -B will rebuild everything. If you want a quickier compilation don't use -B.
It will use all the options in your-project.cfg file. I've found this dof2cfg executable very useful. With it I can edit the .dof text file and propagate the change to the command line and IDE. No need to edit it for each project.
Important warning for long paths: Delphi 7 command line compiler has a very weird bug. If your path is very long, it will fail with an inscrutable error: a access violation without any meaningful information. If it fails without any reasonable motive, try to reduce the maximum path size and the filename size. Put the project in the root folder usually solve it.

FinalBuilder makes it very easy. Give it a try.

I would suggest combination of NAnt and dcc32, but there's also Juancarlo Añez's "WAnt - A Pascal-Friendly Build Tool". I've been using modified version of the 1.x instead of the 2.x alpha. Since it's open source, I could extend the code to output log in XML with the same format as NAnt, so I can integrate it with CruiseControl.NET.

For later versions of Delphi, this should be changed to:
"C:\Program Files (x86)\Embarcadero\RAD Studio\8.0\bin\DCC32.exe" -h

Related

Running ANT with Different JDKs via EXEC (APT/WSGEN workaround)

I hope this finds an ANT build master who has some experience running ANT with different JDK versions concurrently!
I have inherited a fairly old set of libraries & ANT build files that currently work under Java 6/7. In attempting to modernize this system to utilize Java 8 or any future JDK upgrades, I've been working on a means of refactoring these build files to work with Java 8.
The current build system has the following characteristic:
Ant 1.7.0 & Java 1.7.0_55
Usage of the deprecated APT tool via ANT APT tasks
Usage of wsgen (jaxws related libraries) via ANT WSGEN tasks (e.g. classname="com.sun.tools.ws.ant.WsGen")
Effectively the build files mix code generation and compilation to create our desired output.
The APT tool was deprecated in Java 1.7, one needs to move to using JAVAC in 1.8 and beyond!
In attempting to replace the usages of APT with JAVAC I found that not only is the tool removed but so are the numerous packages/class/interfaces associated with the APT tool. I've seen this topic discussed here in multiple Q&A's, however most of the proposed solutions were non-starters.
The one suggestion I did find which had promise was to separate the code generation (usages of APT) from the compilation (JAVAC) to reside in different ANT build files. After separating the build file into a "main" build file and a "codegen" build file, this seems to work just fine.
Example:
<property name="apt.output.file" value="codegen.apt.${java.version}.log" /> <!-- A different log file will exist when I run the "main" ant build file using Java 7 vs 8 for comparison purposes. -->
<exec executable="${exec.ant.cmd}" osfamily="unix" failonerror="true" output="${apt.output.file}" >
<arg line="${ant.apt.cmd.line.options}" />
<env key="JAVA_HOME" value="${exec.java.home}"/> <!-- Java 1.7 -->
<env key="ANT_HOME" value="${ant.home.path}"/> <!-- Ant 1.7.0 -->
<env key="PATH" value="${exec.java.home}/bin" /> <!-- Reset PATH to be certain -->
<!-- The various properties are defined in the build file, and would be fairly unsurprising. -->
</exec>
Now that the "codegen" pieces were self-contained, this allows me to:
Run the "main" ANT build file with Java 8.
For the "codegen" pieces, use an EXEC as per above to specify the ANT/JAVA version to do the *.java code generation.
The good news, for those of you in similar situations, is that this seems to work fine for APT. I changed my JAVA_HOME & PATH to point at Java 8, and it seems to work fine (assuming APT is limited to just *.java source generation, no compilation).
Now here's the rub and what I hope someone might have some expertise on. I found that the APT tool was also used to create an ANT build file (wsgen-build.xml). Said file defines the WSGEN task and then uses it a number of times:
<project name="some-wsgen-fragment" default="wsgenall">
<target name="wsgenall">
<taskdef name="wsgen" classname="com.sun.tools.ws.ant.WsGen" >
<classpath>
<pathelement path="${jaxws.home}/lib/jaxws-tools.jar" />
</classpath>
</taskdef>
<echo message="wsgen for SomeWebServiceImpl" />
<wsgen destdir="${classes.server.gen.dir}" sourcedestdir="${something.gen.dir}" sei="com.something.or.other.SomeWebServiceImpl">
<classpath>
<pathelement path="${classes.server.gen.dir}" />
<path refid="classpath.all" />
</classpath>
</wsgen>
... Repeated usages of wsgen exactly as above, with different classes
Similar to the APT tasks, the "main" build file invokes an EXEC to run an "old" ANT with appropriate parameters to invoke this generated build file under the same environment it works under.
Under Java 1.7 & ANT 1.7.0, this works fine.
When I change Java to 1.8, I change the JDK for JAVA_HOME and the "java.target" to 1.8, I get the following mysterious error:
[echo] wsgen for SomeWebServiceImpl
Finding class com.something.or.other.SomeWebServiceImpl
[antcall] Exiting codegen-buildfile.xml.
BUILD FAILED
codegen-buildfile.xml:58: The following error occurred while executing this line:
wsgen-build.xml:9: Requires JDK 5.0 or later. Please download it from http://java.sun.com/j2se/1.5/
at org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:541)
at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:418)
at org.apache.tools.ant.taskdefs.CallTarget.execute(CallTarget.java:105)
The issue to me "feels" like the following:
Why does an ANT running Java 8 interfere with an ANT running Java 7 and how might this be remedied?
Some Q&A that has lead me to this question:
Have you tried using ANT -v -d for figuring this out?
Yes, I'm generating a log file based on the ${java.version} used for the "main" build file. I generate a file for Java 8 and one for Java 7, and diff the two. There are no environment/property/settings difference between the two (Java 7 vs Java 8) until I hit the error referenced above. There are minor variations in the order classes get loaded, but that is it.
When you change between Java 7 and Java 8, are you making sure that change isn't affecting your EXEC tasks?
The diff of the log files as referenced above verifies this, but when I invoke EXEC the properties in the first example above are effectively hard-coded with the ENV tags being used to ensure the environment variables are also the same regardless of the Java version used in the "main" build file.
Surely there is some environment variable difference causing this issue?
I'm logging a number of variables attempting to diagnose the issue. So far the "codegen" ANT build file has everything the same, regardless if the "main" ANT is run in either Java 7 or 8: ANT_HOME, JAVA_HOME, PATH, ant.version, java.version, java.vm.version, java.class.path, java.ext.dirs. The verbose ANT log bears this out as well, no property/environment/classpath issues between them.
I can't tell from your EXEC example, but are you using full paths? Perhaps the PATH variable is an issue?
While not shown, I'm specifying the full paths to ANT and JAVA since I need to specify the ANT/JDK exactly to ensure I'm running the specific versions desired.
How are you invoking the generated build file with the wsgen tasks (wsgen-build.xml) that is having the problem?
The "main" build file invokes an EXEC on the "codegen" build file, as per the example above. The only difference is a different build target, one target is used for APT, another is used for the WSGEN piece. In said WSGEN target within the "codegen" build file, the wsgen-build.xml is currently imported and the target invoked via ANTCALL. I've also tried using just the ANT task, both have the same result.
Can you run your EXEC commands from the command shell?
Yes, if I run the step on the command line, it either works or not depending on if Java 7 or 8 is set as JAVA_HOME and which appears first on the PATH. For example, if I update JAVA_HOME to be Java 8, I get the following error: java.lang.NoClassDefFoundError: com/sun/mirror/apt/AnnotationProcessorFactory. This is correct since that class no longer exists in Java 8 (but does exist in 7).
Have you tried using a script or batch file instead of using EXEC on the ANT executable?
Yes, same error resulted. I tried this with a simple .bat file that set the requisite environment variables and invoked the command from the shell.
What OS are you on, have you tried a different machine/OS to see if this is environment specific?
I have a Win7 & a RHEL 7 environment, this problem happens in both and I'm using the osfamily attribute to conditional-ize the EXEC command per platform.
Ant 1.7.0 is pretty old, have you tried an updated Ant?
Same issue occurs using Ant 1.9.4 as well. The 1.9.4 Ant only runs for the "main" build file, the "codegen" build file will use 1.7.0 since I'm explicitly setting that via the EXEC tasks. I did try 1.9.4 even for the "codegen" ant build file, but it made no difference in the error.
If you managed to read thru this in its entirety, my hat off to you sir or madam! Thank you for any insight/advice you may have!

Buildiling .net multiple Solutions in Jenkins using MSBuild plugin

I am trying to build .net multiple Solutions files in Jenkins using MSBuild plugin. I have installed and configured MSBuild. In the Build step - 'Build a Visual Studio project or Solution using MSBuild', under 'MSBuild Build FIle' how do we reference the build file(ex, test.txt) which have 5 solution file paths in it. When i give the path directly C:\test.txt, the build is failing with error
C:\test.txt(1,1): error MSB4025: The project file could not be loaded. Data at the root level is invalid. Line 1, position 1.
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:02.22
Build step 'Build a Visual Studio project or solution using MSBuild' marked build as failure
Finished: FAILURE
Below are the solution file paths mentioned in my test.txt file
C:\workspace\DotNet\Constants.sln
C:\workspace\DotNet\Security.sln
C:\workspace\DotNet\Library.sln
C:\workspace\DotNet\Mapping.sln
C:\workspace\DotNet\MapForce.sln
Could I build by mentioning five solution file paths in .txt file and referring the .txt file path by just using one 'Build a Visual Studio project or solution using MSBuild section'?
I have tried with command prompt manually it builds fine. Also, tried with 'Execute Windows batch command' option by batch commands it works fine and builds successfully, facing problem with 'Build a Visual Studio project or solution using MSBuild' when spefiying .txt file which has many solution file paths in it.
Appreciate your help on this.
MSBuild builds MSBuild files, written in xml, not text files (hence the error MSB4025). Luckily creating a file which can be used to build x other files is fairly simple, here is an example:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<ItemGroup>
<Sln Include="C:\workspace\DotNet\Constants.sln"/>
<Sln Include="C:\workspace\DotNet\Security.sln"/>
<Sln Include="C:\workspace\DotNet\Library.sln"/>
<Sln Include="C:\workspace\DotNet\Mapping.sln"/>
<Sln Include="C:\workspace\DotNet\MapForce.sln"/>
</ItemGroup>
<Target Name="Build">
<MsBuild Projects="#(Sln)" Targets="Build" Properties="Configuration=Release;Platform=Win32" BuildInParallel="True" />
</Target>
</Project>
This is just written in a straightforward way, shorter but possibly more complicated code might apply. E.g. to just build all solutions in the C:\workspace\DotNet directory you'd just write <Sln Include="C:\workspace\DotNet\*.sln"/> instead of manually spelling out each of them. Or if all of them reside in that directory you could include them by filename only, e.g. <Sln Include="Constants.sln"/> and then add the directory when expanding the list like Projects="#(Sln->'c:\workspace\dotnet\%(Identity)')".
As you can see this builds the Win32|Release version, change that by altering the properties. Also not the BuildInParallel switch: only use this if the solutions don't depend on each other.

MSBuild and multiple Delphi versions

I have a project for which I need to build two executables: one under Delphi XE2 and one under XE3. I have a build script which builds each version (i.e. one script for XE2 and one for XE3).
If I run the build script for the last version of the IDE I ran, all works well (i.e. run Delphi XE2, build app, run XE2 build script).
However if I run the build script having just run a different version of the IDE I get an AV as soon as my app starts (I.e. run Delphi XE2, built app, run XE3 build script).
It looks as though something about the build script is being cached/modified by the IDE and I need to restore the appropriate data for the version I want to build with. I've tried this with the .dproj, but no luck.
Or could it be loading form resources - both editions show errors due to non-existent properties at start up if the IDE. If so, is there an easy way around this without having maintain multiple versions of all the .fmx files?
Here's a sample build script:
set path=%path%;c:\Windows\Microsoft.NET\Framework\v3.5
set path=%path%;c:\Program Files (x86)\Embarcadero\RAD Studio\10.0
set path=%path%;c:\Documents and Settings\All Users\Documents\RAD Studio\10.0
set BDS=c:\Program Files (x86)\Embarcadero\RAD Studio\10.0
set FrameworkDir=c:\Windows\Microsoft.NET\Framework\
set FrameworkVersion=v3.5
set failed=false
cd \myprogs\monkeystyler
msbuild monkeystyler.dproj /t:build /p:config=full||set failed=true
cd build
if not %failed%==true goto Done
echo ****FAILED TO BULD MONKEYSTYLER
****
Pause
exit
:done
Let's take a look at this line in your XE3 script:
set path=%path%;c:\Program Files (x86)\Embarcadero\RAD Studio\10.0
My guess is that you follow that up in the XE2 script with:
set path=%path%;c:\Program Files (x86)\Embarcadero\RAD Studio\9.0
At which point your path variable looks like this:
set path=%path%;c:\Program Files (x86)\Embarcadero\RAD Studio\10.0;c:\Program Files (x86)\Embarcadero\RAD Studio\9.0
And so the second script fails because the paths from the first script appear earlier.
The elegant way to fix this is to use setlocal and endlocal in your scripts to isolate them from each other.
setlocal
set path=%path%;c:\Windows\Microsoft.NET\Framework\v3.5
set path=%path%;c:\Program Files (x86)\Embarcadero\RAD Studio\10.0
.....
endlocal
The hacky way to fix it is to set the path like this:
set path=c:\Program Files (x86)\Embarcadero\RAD Studio\10.0;%path%
Please use the elegant approach!
What's more you should use pushd and popd to isolate directory changes to each script.
If this doesn't solve everything, do give more information. For a start, error messages are very useful.
The last IDE that you run will update the EnvOption.proj in your <user>\AppData\Roaming\Embarcadero\BDS\<version>folder.
This contains all your search paths, among other things.
This file is indirectly included in your project. So if you run say XE2's IDE then compile your XE3 app, you will get the wrong paths.
You will probably want to disable that and explicitly specify your search paths in each project's dproj file.
e.g. msbuild myproj.proj /p:ImportEnvOptions=false
This is my best guess. Sorry if it's 5 years too late. I have just struggled with similar issues!
All the best
Steve
I went back to my suspicion that it was the form file resources.
My theory was that the with the form files saved by the 'wrong' version of the IDE, when a project built with a different version tried to load them I was getting access violations due to the app trying to load data for properties which where not available in that edition.
To test this I got compiled the project successfully in one version of the IDE (XE3 in this case), did my automated build and tested that the app ran (it did).
I then loaded a .fmx file for the project and added a non-existent property to the form.
Build and the app fails same as before.
Remove the added property and build now succeeds.
All (!) I need to do now is write some code to parse the form files and remove any non-existent properties for the version I'm building.

compile jdk via ant

I want to compile jdk files in order to include debug infromation.
I'd like to use ant, because it's included in my NetBeans environement, so i've done the following:
unzipped /src.zip in a tmp directory
created a very simple build.xml file (one default target, one taks) in my tmp directory:
<?xml version="1.0" encoding="UTF-8"?>
<project name="CompileJDK" default="default" basedir=".">
<target name="default">
<javac srcdir="."
destdir="jdkwd"
debug="on"
/>
</target>
</project>
created a jdkwd directory
launched ant without parameters (just >log.txt)
This leads to 100 compilation errors such as:
[javac] C:\jdkdebug\java\awt\Window.java:196: cannot find symbol
[javac] symbol : class IdentityArrayList
[javac] location: class java.awt.Window
[javac] private static final IdentityArrayList<Window> allWindows = new IdentityArrayList<Window>();
I have just one JDK installed on my machine, so i don't know why it does not resolve all this references.
UPDATE:
The majority of these unresolved references belongs to the package:
sun.awt.util
The question now is corrected to: where are the missing jdk files?
Building the JDK itself is a complex process and is not achievable by a simple javac call wrapped inside an ant project.
You should look at the OpenJDK Build README to get instructions on how to build for your platform.
http://www.oracle.com/technetwork/java/faq-141681.html
A14. Where can I get the Java programming language source code?
Java Software has two separate bundles of source code that you can obtain at no charge:
The Java 2 SDK, Standard Edition itself contains a file called src.zip that contains the source code for the public classes in the java package. Because this does not contain sun.* classes, you cannot do a complete build of the Java technology from these source files. These source files are for your information, to supplement the documentation, so you can see how Java technology works.
The full source code release is available from us by going to the Community Source Code Licensing web site..
The community source code link is incorrect: it's now http://download.java.net/openjdk/jdk7/
Try adding a classpath to your javac call.
<classpath path="/PATH/to/missing_class/" />
Also, try running ant with the -d and -v options. It's a lot of output but will show you where its searching for classes.
According to this post (from 2007), you should include rt.jar and tools.jar on your classpath to compile the JRE sources.
However, I tried that, and it doesn't work for me (100 errors).
There are more elaborate and older (2004) instructions in christhielen's post in the Java bug requesting debug symbols.
If you use Gentoo compiling OpenJDK would be as simple as running emerge dev-java/icedtea.
There is a debug use flag that would switch off all optimizations, I haven't tried it myself but chances are that this is what you want. If it's not - then it should not be a big deal to change build scripts, but would require you to learn a little bit of portage.

Do I have to use a solution file with a Team Build definition?

Our application uses a combination of ASP.NET and Flex platforms.
I am able to successfully use the build service to build and deploy the .NET web site. That works fine. However, we also have our ActionScript files in TFS and I've created a batch file to successfully compile the ActionScript from the command-line.
I want to create two separate build definitions for the ASP.NET and Flex compilation. Flex obviously doesn't have an SLN file--can I create a build definition file from scratch to support the Flex compile batch file without a solution file? The tasks are fairly simple to create (see below), but I've never built a customized Team Build script without using the Create wizard--and the Create wizard expects you to supply a solution file, which I don't have.
My build script would be very straight-forward:
Get the latest version of the ActionScript files
Run the ActionScript compile batch file
Copy the ActionScript files to the deploy folder
Absolutely. TFSBuild.proj is an MSBuild file that calls your solution build in TFS. You can modify that to build whatever you want using MSBuild, which is the language which .vbproj and .csproj files are written in. There's a wealth of tasks that MSBuild allows you to use...
No you don't need a solution file in getting a build done using TFSBuild. A very simple project file could look like this (courtesy Aaron Hallberg):
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<Target Name="EndToEndIteration">
<Exec Command="SomeScript.cmd" />
</Target>
</Project>
Please investigate this page from Aarons blog. The default targets in a tfsbuild.proj file is actually defined in a "common" targets file and imported into the projfile by this instruction:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\TeamBuild\Microsoft.TeamFoundation.Build.targets" />
If the import is removed you only need the EndToEndIteration target to get tfsbuild running....
All the best
/Niels

Resources