Set Wix property to TFS build location - tfs

I have been trying to find an answer to my question and could not find it; hence I will put the solution here. I hope it is helpful to others.
Problem:
I want my Wix project to build in TFS 2010 build process. As part of this, I want the source files location for my Wix to point to the build location of the TFS. For example, I want:
<File Id="ABC" KeyPath="yes" source="C:\Builds\1\MyBuild\assembly.dll" />
to be:
<File Id="ABC" KeyPath="yes" source="$(var.TFSLOCATION)\assembly.dll" />
The 'TFSLOCATION' is a wix property that needs to be populated with the location of TFS build. This needs to happen during the build process, where the build location path is passed to the Wix project.
Solution:
I read the following article:
http://www.ageektrapped.com/blog/setting-properties-for-wix-in-msbuild/
So this is what I did to my Wix project file (wixproj):
In order to set wix property from TFS MSBuild process the wix project file needs two changes:
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<ProductVersion>3.5</ProductVersion>
<SourceLocation Condition="'$(SourceLocation)' == '' ">UNKNOWN</SourceLocation>
<ProjectGuid>{cae7e273-2de5-4a60-9c4f-9da5f094caf5}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>N4S.MSO.BAM.Installer</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>LOCATION=$(SourceLocation)</DefineConstants>
</PropertyGroup>
In the above xml, please note the following two lines:
<SourceLocation Condition="'$(SourceLocation)' == '' ">UNKNOWN</SourceLocation>
<DefineConstants>LOCATION=$(SourceLocation)</DefineConstants>
The first line specifies a property 'SourceLocation' and sets it to a default 'UNKNOWN' value, if is is not set. The second line defines a constant called 'LOCATION' in the 'Release' configuration. The value of this constant is set to the value of 'SourceLocation' property.
Now, you need to make the following changes to your Product.wxs file (or whatever the name of your wxs file is).
Define a wix property first.
<?define TFSLOCATION="$(var.LOCATION)"?>
Now, update the File elements.
<File Id="ABC" KeyPath="yes" source="$(var.TFSLOCATION)\assembly.dll" />
TFS 2010 build template change
Open the TFS 2010 build template.
Look for a task 'Run MSBuild for Project'.
Open the properties for this task and go to 'CommandLineArguments' property.
Set the value for this property to:
String.Format("/p:SourceLocation={0}", BinariesDirectory)
Done
You now have a wix property populated from your TFS build process.

If you set a reference in your wixproj file to the project(s) you are building you can reference their target paths. So if you have two projects MyProject and MyProjectInstaller, set a reference in MyProjectInstaller to MyProject.
Now in the product.wxs file your File elements would look like this:
<File Id='EXE' Name='$(var.MyProject.TargetDir)\MyProject.exe' />
<File Id='DLL' Name='$(var.MyProject.TargetDir)\MyProject.dll' />
...
The benefit to this is that the target dir is correct regardless of whether you're building locally or on a build server.

Answering the question so it doesn't show up with no answers even though the answer is in the question.

I ended up using the same approach, but with a few important improvements.
1) I passed both the SourcesDirectory and the BinariesDirectory from TFS build process template to MSBuild as separate properties, so that I have access to both of them.
2) So that the resulting MSBuild properties are available to every task executed in the MSBuild project, I added them to $(CustomPropertiesForBuild) in the BeforeBuild target.
3) Rrather than adding the DefineContants element to the PropertyGroup, I added a CreateProperty to the BeforeBuild target.
2 and 3 were done for the following reason having to do with running multiple Wix project solutions in a single TFS build. If you define the constant as originally suggested, two things can happen.
First, if you run heat.exe in your WiX project as part of a build that has multiple WiX projects, an issue can occur where the DevEnv holds onto the process handles and the constant is not redefined on each run unless you clean the Output folder and release the file handle.
Second, if for any reason one of your Wix projects does not get built (the configuration does not specify to build it or the specified configuration is invalid for the project) then for some reason, the MSBuild property gets reset to null and thus the constant is redefined as null, so you lose the property. If on the other hand, you define the property by overriding the BeforeBuild target, everything works properly.
Note that you have to override the BeforeBuild property, not the BeforeEndToEndIteration property, for this to work correctly.

Related

Xarmin iOS MSBuild - Missing OutputPath?

I am currently building my Xamarmin iOS project from the command line:
MSBuild "C:\code\MyProject.iOS.csproj" /t:Build /p:Configuration=Ad-Hoc;Platform=iPhone;ServerAddress=MACIP;ServerUser=MACUSER
It fails with the following error:
The OutputPath property is not set for project 'MyProject.iOS.csproj'.
Please check to make sure that you have specified a valid combination
of Configuration and Platform for this project.
However, I there is an OutputPath set when I examine the CSPROJ.
I can get around this by forcing an "OutputPath" parameter at the command line:
OutputPath="C:\builds\xamarin\cellar-ios"
Note: OutputPath="C:\builds\xamarin\cellar-ios\" does not work and build fails (notice ending back slash)
However this creates a strange folder structure where it appends the filename:
Thoughts on what I'm doing wrong here? I feel the setup is very close!
EDIT
Using the following parameters I'm able to get it to work. Note I still have to manually include the OutputPath but this gets me by for now.
/t:Build /p:Configuration=Ad-Hoc;Platform=iPhone;ServerAddress=SERVER_IP;ServerUser=USER;ServerPassword=PASS;OutputPath=bin\iPhone\Ad-Hoc\
For any customized OutputPath of your .csproj, it should be picked up by xbuild/msbuild within the .csproj or provided as a property.
One thing you can do to customize the output path of the IPA would be to use a custom MSBuild target to copy the IPA to a folder of your choice(You could use a move task if you needed):
i.e. (Inside your .csproj):
<PropertyGroup>
<CreateIpaDependsOn>
$(CreateIpaDependsOn);
CopyIpa
</CreateIpaDependsOn>
</PropertyGroup>
<Target Name="CopyIpa"
Condition="'$(OutputType)' == 'Exe'
And '$(ComputedPlatform)' == 'iPhone'
And '$(BuildIpa)' == 'true'">
<Copy
SourceFiles="$(IpaPackagePath)"
DestinationFolder="$(OutputPath)"
/>
</Target>
You then set the DestinationFolder to the desired output folder.
This is found in our KB articles here: https://kb.xamarin.com/customer/portal/articles/2061038-can-i-change-the-output-path-of-the-ipa-file-

Replacement for xmltask in Gradle

I am trying to migrate my projects from Eclipse + Ant to Android Studio + Gradle. All of them have special builds for different app stores with different tracking ids, ad ids and so on. On Eclipse I had a ant xmltask that set the values of this ids in their respective xml files. For example I had:
<xmltask source="res/values/admob.xml" dest="res/values/admob.xml">
<replace path="//string[#name='bottom_ad_unit_id']/text()" withText="${bottomAdUnitId}"/>
</xmltask>
For each store I only had to set bottomAdUnitId with the correct id and call run the task.
Is there something similar in Gradle that would allow me to do the same thing?
You could just use Gradle's Ant support.
ant.taskdef(name: 'xmltask', classpath: 'path/to/xmltask.jar', classname: 'com.oopsconsultancy.xmltask.ant.XmlTask')
ant.xmltask(source: 'res/values/admob.xml', dest: 'res/values/admob.xml') {
replace(path: '//string[#name='bottom_ad_unit_id']/text()', withText: "${bottomAdUnitId}")
}

composite component ending up in wrong directory with jboss jsf tools and m2eclipse?

When using JBOSS Tools, M2E and M2E-WTP creating a new composite component wants to put the newly created component in the wrong directory. It also looks for components in the wrong directory.
It should be putting it in the directory:
src/main/webapp/resources/components/group-name/tagname.xhtml
but instead it is looking for it (and a quick fix creates file) in:
target/m2e-wtp/web-resources/resources/components/group-name/tagname.xhtml
Here are the versions I am using:
JBoss Tools RichFaces for Eclipse Version:
3.2.1.v20110730-1214-H169-Final
M2E - Maven Integration for Eclipse
Version: 1.0.0.20110607-2117
Maven Integration for WTP
Version: 0.13.1.20110728-1800
Update:
Seems to pick the first path in .settings/org.eclipse.wst.common.component file. Changing the non m2e to be first seems to make it want to put it in the right place.
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="hcbb">
<wb-resource deploy-path="/" source-path="/src/main/webapp"/>
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<property name="context-root" value="hcbb"/>
<property name="java-output-path" value="/hcbb/target/classes"/>
</wb-module>
</project-modules>
However, it is still complaining about missing or invalid attributes and not doing auto completion on the custom components.. Not sure if JSF Tools even does that though.
I believe this issue is fixed in later release of joss tools 3.3.x.
If not please open bug and we'll look at it.

Ant Fileset Expansion doesn't work

I get a very confusing reaction from my ant build-file and I'm wondering whether I'm just not clever enough or this might actually be a bug.
I've got the following property set globally in my project:
<property name="lib.dir" location="lib"/>
Then I'll try to add some files out of this directory into a jar file via fileset (more than one resource):
<fileset dir="${basedir}" includes="lib/*filename*"/>
There should be (and exist) 3 different libraries, which are matched that way. However, if I try to use the following, it doesn't work and no files are included:
<fileset dir="${basedir}" includes="${lib.dir}/*filename*"/>
Note that the only differences lies in the usage of the global property. Now the simple question: why does the first version work as advertised, but the second doesn't?
Please check the actual value of "lib.dir" just before and maybe after the task that uses the "fileset" expression. Just to make sure, that it hasn't been changed accidently after you've set it globally. The <echo/> task can help.
Maybe I got the solution. The description of the locationattribute is:
Sets the property to the absolute filename of the given file. If the value of this attribute is an absolute path, it is left unchanged (with / and \ characters converted to the current platforms conventions). Otherwise it is taken as a path relative to the project's basedir and expanded.
Simply use the value attribute instead of location. Here's a test script to show the difference:
<project name="test">
<property name="test1" location="lib"></property>
<property name="test2" value="lib"></property>
<target name="target" description="description">
<echo>${test1}</echo>
<echo>${test2}</echo>
</target>
</project>
The output on my system is as follows:
Buildfile: D:\Develop\workspace-jabber\scrapbook\build.xml
target:
[echo] D:\Develop\workspace-jabber\scrapbook\lib
[echo] lib
BUILD SUCCESSFUL
Total time: 307 milliseconds
I have found a clue to the answer, but not the whole thing yet.
I runned both versions of the fileset with ant -debug and here is what happens.
In the working, not-using-property version, I get the following output:
fileset: Setup scanner in dir [pathToDir] with patternSet{ includes: [lib/*filename*] excludes: [] }
whereas in the should-be-working-but-doesn't version I get:
fileset: Setup scanner in dir [pathToDir] with patternSet{ includes: [ [pathToDir]/lib/*filename*] excludes: [] }
As you can see, ant add's the [pathToDir] in the regexp, thus searching for
[pathToDir]/[pathToDir]/lib/*filename*
which obviously doesn't exist. Problem now: how do I have to modify my version to have it working properly?
When creating the property (is it done global or in a target?), does the directory lib exist? If not, the location attribute does not work - use a value attribute instead or better define the property after creating the directory.
As indicated above, the problem was that ${lib.dir} too contained the whole path, thus searching for [pathToDir]/[pathToDir]/lib/filename.
To clip away the unwanted [pathToDir] in the ${lib.dir} property, I now used the task. I got now the following, but imho not so nice looking solution:
<basename property="lib.dir.rel" file="${lib.dir}"/>
<fileset dir="${basedir}" includes="${lib.dir.rel}/*filename*"/>
P.S.: On a second look, I found that Andreas_D also found the right reason and a good suggestion yesterday, which I must have overlooked :-/

What are the MSBuild project level properties for Delphi?

The Delphi documentation for MSBuild says
/property:name=value sets or overrides
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
I can't find a list of available properties, here's what I know so far:
WarningLevel
OutputDir (dcc32 -e equivalent)
Config
I'd like to get a complete list, but I'm most interested in being able to override the Defines (dcc32 -d equivalent). And if these can be lined up against dcc32 equivalents that'd be icing!
You can find most of the parameters in the msbuild script C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Borland.Delphi.Targets when you look at the CoreCompile target.
ExeOutput="$(DCC_ExeOutput)"
BplOutput="$(DCC_BplOutput)"
DcuOutput="$(DCC_DcuOutput)"
DcpOutput="$(DCC_DcpOutput)"
HppOutput="$(DCC_HppOutput)"
ObjOutput="$(DCC_ObjOutput)"
BpiOutput="$(DCC_BpiOutput)"
DependencyCheckOutputName = "$(DCC_DependencyCheckOutputName)"
UnitSearchPath="$(UnitSearchPath)"
ResourcePath="$(ResourcePath)"
IncludePath="$(IncludePath)"
ObjPath="$(_ObjectPath)"
UnitAlias="$(DCC_UnitAlias)"
ConsoleTarget="$(DCC_ConsoleTarget)"
Define="$(DCC_Define)"
FindError="$(DCC_FindError)"
MapFile="$(DCC_MapFile)"
Hints="$(DCC_Hints)"
CBuilderOutput="$(DCC_CBuilderOutput)"
BaseAddress="$(DCC_BaseAddress)"
UsePackage="$(_UsePackage)"
MakeModifiedUnits="$(DCC_MakeModifiedUnits)"
BuildAllUnits="$(DCC_BuildAllUnits)"
NameSpace="$(NameSpace)"
OldDosFileNames="$(DCC_OldDosFileNames)"
Quiet="$(DCC_Quiet)"
DebugInfoInExe="$(DCC_DebugInfoInExe)"
DebugVN="$(DCC_DebugVN)"
RemoteDebug="$(DCC_RemoteDebug)"
OutputNeverBuildDcps="$(DCC_OutputNeverBuildDcps)"
NoConfig="true"
OutputDRCFile="$(DCC_OutputDRCFile)"
OutputDependencies="$(DCC_OutputDependencies)"
OutputXMLDocumentation="$(DCC_OutputXMLDocumentation)"
DefaultNamespace="$(DCC_DefaultNamespace)"
Platform="$(DCC_Platform)"
UnsafeCode="$(DCC_UnsafeCode)"
Warnings="$(DCC_Warnings)"
Alignment="$(DCC_Alignment)"
MinimumEnumSize="$(DCC_MinimumEnumSize)"
FullBooleanEvaluations="$(DCC_FullBooleanEvaluations)"
AssertionsAtRuntime="$(DCC_AssertionsAtRuntime)"
DebugInformation="$(DCC_DebugInformation)"
ImportedDataReferences="$(DCC_ImportedDataReferences)"
LongStrings="$(DCC_LongStrings)"
IOChecking="$(DCC_IOChecking)"
WriteableConstants="$(DCC_WriteableConstants)"
LocalDebugSymbols="$(DCC_LocalDebugSymbols)"
RunTimeTypeInfo="$(DCC_RunTimeTypeInfo)"
Optimize="$(DCC_Optimize)"
OpenStringParams="$(DCC_OpenStringParams)"
IntegerOverflowCheck="$(DCC_IntegerOverflowCheck)"
RangeChecking="$(DCC_RangeChecking)"
TypedAtParameter="$(DCC_TypedAtParameter)"
PentiumSafeDivide="$(DCC_PentiumSafeDivide)"
StrictVarStrings="$(DCC_StrictVarStrings)"
GenerateStackFrames="$(DCC_GenerateStackFrames)"
ExtendedSyntax="$(DCC_ExtendedSyntax)"
SymbolReferenceInfo="$(DCC_SymbolReferenceInfo)"
StackSize="$(DCC_StackSize)"
ImageBase="$(DCC_ImageBase)"
Description="$(DCC_Description)"
DelaySign="$(DCC_DelaySign)"
KeyFile="$(DCC_KeyFile)"
KeyContainer="$(DCC_KetContainer)"
CodePage="$(DCC_CodePage)"
SYMBOL_DEPRECATED="$(DCC_SYMBOL_DEPRECATED)"
SYMBOL_LIBRARY="$(DCC_SYMBOL_LIBRARY)"
SYMBOL_PLATFORM="$(DCC_SYMBOL_PLATFORM)"
SYMBOL_EXPERIMENTAL="$(DCC_SYMBOL_EXPERIMENTAL)"
UNIT_LIBRARY="$(DCC_UNIT_LIBRARY)"
UNIT_PLATFORM="$(DCC_UNIT_PLATFORM)"
UNIT_DEPRECATED="$(DCC_UNIT_DEPRECATED)"
UNIT_EXPERIMENTAL="$(DCC_UNIT_EXPERIMENTAL)"
HRESULT_COMPAT="$(DCC_HRESULT_COMPAT)"
HIDING_MEMBER="$(DCC_HIDING_MEMBER)"
HIDDEN_VIRTUAL="$(DCC_HIDDEN_VIRTUAL)"
GARBAGE="$(DCC_GARBAGE)"
BOUNDS_ERROR="$(DCC_BOUNDS_ERROR)"
ZERO_NIL_COMPAT="$(DCC_ZERO_NIL_COMPAT)"
STRING_CONST_TRUNCED="$(DCC_STRING_CONST_TRUNCED)"
FOR_LOOP_VAR_VARPAR="$(DCC_FOR_LOOP_VAR_VARPAR)"
TYPED_CONST_VARPAR="$(DCC_TYPED_CONST_VARPAR)"
ASG_TO_TYPED_CONST="$(DCC_ASG_TO_TYPED_CONST)"
CASE_LABEL_RANGE="$(DCC_CASE_LABEL_RANGE)"
FOR_VARIABLE="$(DCC_FOR_VARIABLE)"
CONSTRUCTING_ABSTRACT="$(DCC_CONSTRUCTING_ABSTRACT)"
COMPARISON_FALSE="$(DCC_COMPARISON_FALSE)"
COMPARISON_TRUE="$(DCC_COMPARISON_TRUE)"
COMPARING_SIGNED_UNSIGNED="$(DCC_COMPARING_SIGNED_UNSIGNED)"
COMBINING_SIGNED_UNSIGNED="$(DCC_COMBINING_SIGNED_UNSIGNED)"
UNSUPPORTED_CONSTRUCT="$(DCC_UNSUPPORTED_CONSTRUCT)"
FILE_OPEN="$(DCC_FILE_OPEN)"
FILE_OPEN_UNITSRC="$(DCC_FILE_OPEN_UNITSRC)"
BAD_GLOBAL_SYMBOL="$(DCC_BAD_GLOBAL_SYMBOL)"
DUPLICATE_CTOR_DTOR="$(DCC_DUPLICATE_CTOR_DTOR)"
INVALID_DIRECTIVE="$(DCC_INVALID_DIRECTIVE)"
PACKAGE_NO_LINK="$(DCC_PACKAGE_NO_LINK)"
PACKAGED_THREADVAR="$(DCC_PACKAGED_THREADVAR)"
IMPLICIT_IMPORT="$(DCC_IMPLICIT_IMPORT)"
HPPEMIT_IGNORED="$(DCC_HPPEMIT_IGNORED)"
NO_RETVAL="$(DCC_NO_RETVAL)"
USE_BEFORE_DEF="$(DCC_USE_BEFORE_DEF)"
FOR_LOOP_VAR_UNDEF="$(DCC_FOR_LOOP_VAR_UNDEF)"
UNIT_NAME_MISMATCH="$(DCC_UNIT_NAME_MISMATCH)"
NO_CFG_FILE_FOUND="$(DCC_NO_CFG_FILE_FOUND)"
IMPLICIT_VARIANTS="$(DCC_IMPLICIT_VARIANTS)"
UNICODE_TO_LOCALE="$(DCC_UNICODE_TO_LOCALE)"
LOCALE_TO_UNICODE="$(DCC_LOCALE_TO_UNICODE)"
IMAGEBASE_MULTIPLE="$(DCC_IMAGEBASE_MULTIPLE)"
SUSPICIOUS_TYPECAST="$(DCC_SUSPICIOUS_TYPECAST)"
PRIVATE_PROPACCESSOR="$(DCC_PRIVATE_PROPACCESSOR)"
UNSAFE_TYPE="$(DCC_UNSAFE_TYPE)"
UNSAFE_CODE="$(DCC_UNSAFE_CODE)"
UNSAFE_CAST="$(DCC_UNSAFE_CAST)"
OPTION_TRUNCATED="$(DCC_OPTION_TRUNCATED)"
WIDECHAR_REDUCED="$(DCC_WIDECHAR_REDUCED)"
DUPLICATES_IGNORED="$(DCC_DUPLICATES_IGNORED)"
UNIT_INIT_SEQ="$(DCC_UNIT_INIT_SEQ)"
LOCAL_PINVOKE="$(DCC_LOCAL_PINVOKE)"
MESSAGE_DIRECTIVE="$(DCC_MESSAGE_DIRECTIVE)"
TYPEINFO_IMPLICITLY_ADDED="$(DCC_TYPEINFO_IMPLICITLY_ADDED)"
XML_WHITESPACE_NOT_ALLOWED="$(DCC_XML_WHITESPACE_NOT_ALLOWED)"
XML_UNKNOWN_ENTITY="$(DCC_XML_UNKNOWN_ENTITY)"
XML_INVALID_NAME_START="$(DCC_XML_INVALID_NAME_START)"
XML_INVALID_NAME="$(DCC_XML_INVALID_NAME)"
XML_EXPECTED_CHARACTER="$(DCC_XML_EXPECTED_CHARACTER)"
XML_CREF_NO_RESOLVE="$(DCC_XML_CREF_NO_RESOLVE)"
XML_NO_PARM="$(DCC_XML_NO_PARM)"
XML_NO_MATCHING_PARM="$(DCC_XML_NO_MATCHING_PARM)"
So to set the defines you could use the DCC_Define parameter like this:
msbuild yourproject.dproj /p:DCC_Define=MY_DEFINE
Others you will find in the .dproj file of your project
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
So it is Configuration and not Config. At least in Delphi 2007.
You might want to learn more about msbuild in general to understand the scripts better and learn how you could make your own msbuild scripts to drive a build machine.
Disclaimer: This information is from a Delphi 2007 setup

Resources