Can I add conditional defines in the msbuild command line? - delphi

I have the following sample code:
program boohoo;
{$APPTYPE CONSOLE}
{$IFDEF boo}
{$MESSAGE warn 'boo'}
{$ENDIF}
{$IFDEF hoo}
{$MESSAGE warn 'hoo'}
{$ENDIF}
begin
end.
In the project options the conditional boo is defined. I would like to be able to add the conditional hoo as part of my msbuild command line.
I have tried it like this:
msbuild boohoo.dproj /p:Config=Release;DCC_Define="$(DCC_Define);hoo"
The output shows hoo but not boo. When I use verbose output to see the dcc32 command I see
-D$;hoo
Clearly I can do it like this:
msbuild boohoo.dproj /p:Config=Release;DCC_Define="boo;hoo"
but naturally I want to use whatever conditionals are declared in the project options plus what I specify on the command line.
Is there any way for me to specify this property with reference to the value from the underlying configuration?

Disclaimer: don't use MsBuild myself yet, all taken from the docs and some IDE experimentation
According to MsBuild command line reference ( http://msdn.microsoft.com/en-us/library/ms164311.aspx ):
/property:name=value
Sets or overrides these project-level properties, where name is the
property name and value is the property value. Use a semicolon or a
comma to separate multiple properties, or specify each property
separately. /p is also acceptable. For example:
/property:WarningLevel=2;OutputDir=bin\Debug
setting or overriding is all you can do for a property value. Adding to a property value from the project file is either not possible or a case of a hidden feature.
But I guess what you could do is define a custom property in your dproj file with an " " as its default value:
<PropertyGroup>
<ExtraDefines> </ExtraDefines>
</PropertyGroup>
reference that in your defines statement
<DCC_Define>DUNIT;$(ExtraDefines);$(DCC_Define)</DCC_Define>
which in the IDE should be DUNIT;$(ExtraDefines)
and then specify it on the command line:
msbuild boohoo.dproj /p:Config=Release;ExtraDefines="hoo"
I did test adding the $(ExtraDefines) to the Include options for the project using the IDE. And at least that didn't barf at me, even without having the option defined in the dproj. The commandline the IDE produced from this was:
...rad studio\7.0\bin\dcc32.exe --no-config -B -Q -DDEBUG;DUNIT; -E....
Which seems to indicate that the $(ExtraDefines) got eliminated as it had no value. And that it should be picked up using MSBuild and specififying a value on the command line.

Almost 5 years later, but all answers are not quite elegant ))
Recently, I've faced the same problem
And here is the solution:
Usually, DCC_Define is defined in a .dproj file like this:
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>boo;$(DCC_Define)</DCC_Define>
We all have tried to define DCC_Define via /property:DCC_Define=blah-blah
But accordingly to How to: Build the Same Source Files with Different Options:
The property value that is specified on the command line takes precedence over any value that is set for the same property in the project file, and that value in the project file takes precedence over the value in an environment variable.
So, failure (that is the question here!)
BUT! How to: Use Environment Variables in a Build
To use an environment variable in an MSBuild project
Reference the environment variable the same way you would a variable declared in your project file. For example, the following
code references the BIN_PATH environment variable:
<FinalOutput>$(BIN_PATH)\MyAssembly.dll</FinalOutput>
So, we must define environment variable with the name DCC_Define and values of our ADDITIONAL conditionals
> set DCC_Define=hoo;doo;moo;foo
and then simply run
> msbuild boohoo.dproj /p:Config=Release
DCC32 will get then -Dboo;hoo;doo;moo;foo

Straightforward solution is to create a new build configuration (say, boohooRelease), add both boo and hoo conditional defines to it and compile as msbuild boohoo.dproj /p:Config=boohooRelease. Not exactly what you are trying to do, but it works.

I just tried the following and it worked, so don't know whether Microsoft has changed it:
msbuild "myApp.dproj" /t:build /property:DCC_Define="boo"
remember to add the double quote "", otherwise it won't work

Another way is to create a wrapper project file like this:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Full" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Full">
<CreateProperty Value="$(DCC_Define);$(ExtraDefines)">
<Output TaskParameter="Value" PropertyName="DCC_Define"/>
</CreateProperty>
</Target>
<Import Project="example.dproj" />
</Project>
and invoke like this:
msbuild.exe "/t:Clean;Full;Build" "/p:config=Debug" /p:ExtraDefines=SOME_DEFINE wrapper.proj
It is certainly less elegant but you don't have to modify the .dproj file.

Related

Ant: Are jarfile and destfile the same?

In the Ant documentation on the jar command, it says that the destfile attribute is required.
However there is an example at the bottom that uses the jarfile attribute and does not use the destfile attribute. Also, I have functioning code from a work colleague that uses the jarfile attribute in a build.xml file for a Netbeans project.
So it would seem that destfile is not required, or can be replaced by jarfile.
Are jarfile and destfile identical?
Are there cases where you should use one and cases where you should use the other?
Thanks in advance
Yes, jarfile is a deprecated alias for destfile.
The implementation of jar is a subclass of the implementation of zip - as is ear and war. Each of them has a special (zip|jar|war|ear)file attribute. With Ant 1.5 we decided to unify this to destfile and deprecate the task-specific attributes.
Obviously we forgot to update all references inside the manual :-)

Dynamic basedir for Ant in Eclipse

The title might not be the best so let me explain what I am trying to do.
I have made an Ant buildfile that will help me with Maven goals. It's so much easier having to scope to Ant view and choose what I want to do. The biggest benefit with this is that I can use it in almost any project. Whether I deploy to tomcat or jboss or sakai(:deploy) or I handle mutiple instaces of the same server or skip tests... worst case I just change some path properties.
The drawback right now is that I have to keep a copy of this buildfile in every project.
What I am trying to do is have only 1 buildfile, in the workspace, and dinamicaly optain, from eclipse, the current project that I am working on. Be it module or parent I can refine that later.
So basically change the basedir for ant tasks based on the selected project in eclipse.
I have tried Ant Runtime Properties but for some reason properties like
${project_path}
fail to give me what their description say. I get this:
Variable references empty selection: ${project_path}
I hope it is clear what I am trying to do. So my question, I know it's possible, I'm just missing something and I hope some of you can help me with this.
I believe the trouble is in the Ant Runtime properties. I'm not 100% sure how I should use those.
Thank you!
EDIT after comment and further investigation..
Make the projectdir available as basedir property for ant like that :
Window > Preferences > Ant > Runtime > Properties
and create a property named basedir with value either :
${project_loc}
or
${workspace_loc}/${project_name}
and
<project basedir="${basedir}">
<echo>$${basedir} = ${basedir}</echo>
</project>
will work as expected, means echoing eclipse/yourworkspace/projectdir
Maybe there are other ways, i.e. via Ant Addon Ant4Eclipse, which aims to make Eclipse settings available for ant, never used it.

AssemblyFileVersion causing build to fail

When I try to build my project, I get the following error:
error : Unable to update the AssemblyFileVersion for c:\builddir\MyProject\AssemblyInfo.cs: No stub entry for AssemblyFileVersion was found in the AssemblyInfo file.
I found this article, which implies that a "stub" property is required. So, in my AssemblyInfo.cs, I tried to specify one:
[assembly: AssemblyFileVersion("1.0.0")]
However, it isn't recognised. I finally came across this article, which says that you can't use the AssemblyFileVersion property with the CF. The targets file used by the build script is also used for building other, non CF projects, and needs to update the FileVersion for them.
Is it possible to put something in the AssemblyInfo.cs file, the target file or the build script that stops this from being an issue?
Yes, something like this:
#if !(WindowsCE || PocketPC)
[assembly: AssemblyFileVersion("1.0.0")]
#endif
If using the preprocessor in the manner described in the other answer doesn't work for you, consider putting the AssemblyFileVersion attribute into a separate source file, and conditionally including that source file in the project:
<Compile Include="AssemblyInfo.cs" />
<Compile Include="AssemblyInfo.AssemblyVersion.cs"
Condition="
'$(TargetPlatform)' == 'WindowsCE' OR
'$(TargetPlatform)' == 'PocketPC'"
/>
I'm not sure if there is already a property you can use in the project file, or if you would need to declare your own (perhaps $(Platform) is used for this?)

How do I get the target as a property in Ant?

Possibly one of those really terrible beginner questions where the manual will tell you everything, but, anyway, take this line below:
ant -Dfoo=bar buildme
in my build script, what is the property that holds "buildme"?
The list of targets invoked is available in the property
ant.project.invoked-targets
If there is a default target specified, then that will be the invoked target. If one or more targets are specified on the command line, these appear comma-separated in the property. Note that the property only becomes set once execution passes to a target - if you try to read the property outside of any target, it will be unset.
So, if the project has a default target 'zero':
$ ant one two
# ant.project.invoked-targets is set to:
one,two
and
$ ant
# ant.project.invoked-targets is set to (default):
zero
Seems like ant.project.invoked-targets is not available in ant 1.7.1
Not sure I understand your question, but "buildme" is the target to execute, not a property.
ant [options] [target [target2 [target3] ...]]
You "pick it" by creating the corresponding target:
<target name="buildme">
<!-- tasks that will execute here -->
</target>
As for the foo property, you "pick it" by using ${foo}.

Override the compiler attribute in an Ant javac task

I'm trying to override Ant compiler attributes via the command line so that all 'javac' tasks use my specified compiler.
The problem I've run into is that any target that sets its own value for compiler overrides the one that I set at the commmand line. So, even though I'm entering the following command.
ant -Dbuild.compiler=mycompiler
Any target that has the following is going to use the modern compiler instead of mycompiler because of that compiler="modern" attribute
<javac srcdir="."
destdir="${classes.dir}/core"
compiler="modern"
encoding="UTF-8">
<include name="org/**" />
<include name="com/**" />
<compilerarg line="${config.build.compilerarg}" />
</javac>
Is there any way to override this from the command line, or am I stuck editing the build file?
The Ant javac task documentation says:
It is possible to use different compilers. This can be specified by either setting the global build.compiler property, which will affect all tasks throughout the build, or by setting the compiler attribute, specific to the current task. Valid values for either the build.compiler property or the compiler attribute are:
It sounds as if you can either specify the global build.compiler property or set a specific compiler attribute.
So, it looks like you will need to modify your build file and either:
remove the compiler attribute from the javac calls and allow the
global build.compiler setting to
cascade down
change the values of the compiler
attribute from a hard-coded string
compiler="modern" to be property
compiler="${javac.compiler}"

Resources