2 tasks inside a msbuild loop - msbuild

I'm trying to achieve something like this:
<ItemGroup>
<Projects Include="projectpath1"/>
<Projects Include="projectpath2"/>
...
<ItemGroup/>
// foreach project {
<GetCss Project=%Project.Identity CssOutputs=#CssFiles/>
<MergeCss CssInputs=#CssFiles CssOutputFile="test.css"/>
// } execute GetCss then MergeCss foreach project
GetCss and MergeCss are custom inline tasks.
I don't want:
// foreach project {
<GetCss Project=%Project.Identity CssOutputs=#CssFiles/>
// }
// foreach project {
<MergeCss CssInputs=#CssFiles CssOutputFile="test.css"/>
// }
Thanks in advance for your help.

Based on your code, it looks like you'd want to perform target batching so that you could call both of the inline tasks for each of your Projects items. Here's an example of a batched target named GetAndMergeCss, with the assumption that your GetCss inline task takes a string for an input and the CssFiles listed for CssOuputs are MSBuild items to be consumed by your MergeCss inline task:
<ItemGroup>
<Projects Include="projectpath1"/>
<Projects Include="projectpath2"/>
</ItemGroup>
<Target Name="GetAndMergeCss" Outputs="%(Projects.Identity)">
<PropertyGroup>
<ThisProjectIdentity>%(Projects.Identity)</ThisProjectIdentity>
</PropertyGroup>
<Message Text="Preparing to get and merge css for project: $(ThisProjectIdentity)" />
<GetCss Project="$(ThisProjectIdentity)" CssOutputs="#(CssFiles)"/>
<!--Or this works too...<GetCss Project="%(Projects.Identity)" CssOutputs="#(CssFiles)"/>-->
<MergeCss CssInputs="#(CssFiles)" CssOutputFile="test.css"/>
</Target>

Related

msbuild task conditional operators in parameter value

Is there any way how to use conditional variables as parameters when calling MSBuild tasks?
for example, if we have text being string argument in MySampleTask msbuild task:
<MySampleTask text="if a not empty ? a : b" />
How to pass text string variable if we may have 2 local string variables a and b? How to achieve behavior in above code?
I'm not aware of such operator, but what you want is equivalent to
<MySampleTask text="$(a)" Condition="'$(a)' != ''" />
<MySampleTask text="$(b)" Condition="'$(a)' == ''" />
Or, same principle but applied to a property first; probably the most 'standard' way:
<PropertyGroup>
<a Condition="'$(a)' == ''">$(b)</a>
</PropertyGroup>
<MySampleTask text="$(a)" />

How do I enable "clickable" logs to the "Messages" window in intellij [duplicate]

I have an existing project that I want to build in the IntelliJ Community Edition 11.1.4 running on Ubuntu 12.04.1 LTS
In the Ant Build window I added the project's build.xml by clicking on the + button in the top left hand corner of the window and navigating to the file. The ant tasks associated with the build file are listed and I click on the green play button to run the ant build which commences as expected.
I was expecting to see compiler errors and have IntelliJ CE present those compiler errors and allow me to Jump to (the offending) Source having double clicked on the errors in the Messages window.
Instead, the messages window displays the following error which when I double-click on it takes me to the javac ant task in the build.xml file.
build.xml:389: Compile failed; see the compiler error output for details.
This is great advice and I very much want to follow it but I cannot because the compiler error is not displayed anywhere in the Messages window. Next and Previous Message do not navigate to an actual compiler error.
I want to know how to be able to see the compiler error messages in IntelliJ having run an Ant build.
I tried adding the -v flag to the Ant command line:field in Execution Properties. This made no difference to the behaviour.
I then tried down grading from Ant 1.8 to Ant 1.7. this time I did see a change in behaviour. the build does not run at all and I get the following error https://gist.github.com/4073149 at the terminal.
The javac ant task looks like this.
<target name="compile-only" depends="">
<stopwatch name="Compilation"/>
<javac destdir="${build.classes.dir}" debug="on" deprecation="off"
classpathref="base.path" excludes="/filtering/**/**">
<src path="${src.dir}"/>
<src path="${build.autogen.dir}"/>
</javac>
<!-- Copy all resource files to the output dir -->
<copy todir="${build.classes.dir}">
<fileset dir="${src.dir}">
<include name="**/*.properties"/>
<include name="**/*.gif"/>
<include name="**/*.png"/>
<include name="**/*.jpg"/>
<include name="**/*.svg"/>
<include name="**/*.jpeg"/>
<exclude name="**/.svn"/>
</fileset>
</copy>
<stopwatch name="Compilation" action="total"/>
IDEA just prints Ant's output. Try switching the output from the tree view to the plain text view using the corresponding button on the left of the messages panel:
If the output contains errors, you should be able to see them there.
Also it's much faster and easier to use IDEA provided incremental compilation (Build | Make).
When using plain (not tree) output for ant IntelliJ uses
file (line,col): error msg format for javac errors.
But error view parser only understands file:line: error msg format.
You could tweak it in PlainTextView class from antIntegration.jar
http://grepcode.com/file/repository.grepcode.com/java/ext/com.jetbrains/intellij-idea/10.0/com/intellij/lang/ant/config/execution/PlainTextView.java#98
I just changed addJavacMessage method to following and recompiled the class
``` java
public void addJavacMessage(AntMessage message, String url) {
final VirtualFile file = message.getFile();
if (message.getLine() > 0) {
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
if (file != null) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
String presentableUrl = file.getPresentableUrl();
builder.append(presentableUrl);
// builder.append(' ');
}
});
}
else if (url != null) {
builder.append(url);
// builder.append(' ');
}
// builder.append('(');
builder.append(':');
builder.append(message.getLine());
builder.append(':');
builder.append(' ');
// builder.append(message.getColumn());
// builder.append(")");
print(builder.toString(), ProcessOutputTypes.STDOUT);
}
finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
print(message.getText(), ProcessOutputTypes.STDOUT);
}
public void addException(AntMessage exception, boolean showFullTrace) {
String text = exception.getText();
showFullTrace = false;
if (!showFullTrace) {
int index = text.indexOf("\r\n");
if (index != -1) {
text = text.substring(0, index) + "\n";
}
}
print(text, ProcessOutputTypes.STDOUT);
}
```
And now I have clickable links in 'plain text' output mode of ant tool.
Note, that 'tree mode' shows line & columns correctly - I used IDEA 13 CE.
It would be nice if somebody to create pull request for Intellij regarding this issue.
Ant Correct usage in IntelliJ:
javac includeantruntime="false" srcdir="${src.dir}" fork="yes" executable="D:/jdk1.7/bin/javac"
destdir="${classes.dir}" includes="**/*.java" source="7" classpathref="library.classpath" ...
the most important:
executable="D:/jdk1.7/bin/javac"

Gradle task: how to wait for the file operation to complete

Here's what I'm trying to do:
Copy archive (zip) from buildscript dependencies to the temp directory
Unzip archive to another directory within build
Here's task to copy archive (works)
task copyTpcds(type: Copy) {
file('build/zip').mkdirs()
from buildscript.configurations.classpath
include 'tpcds*'
into 'build/zip'
}
And the task to unzip and then delete archive
task extractTpcds(type: Copy) {
def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
def outDir = file('build/cmd/tpcds')
outDir.mkdirs() // make sure the directory exists
from zipTree(file(names[0])) // generates error when
into outDir
// now remove copied zip file
//zipFile.delete() // deletes file before the extractions completes?
}
Here are few scenarios:
If I put both tasks into build.gradle and try to run anything, even just gradle tasks then I get this error: Neither path nor baseDir may be null or empty string. path='null' basedir='C:\dev\code\td\pdo\tpcds-tpg' from this code in the task #2: file(names[0])
If I comment out code in the 2nd task, 1st task would run and copy zip file to build/zip
Now I can uncomment code in the 2nd task (except deletion) and execute gradle extractTpcds it will run and extract the archive
So it seems to me that
File operations are evaluated across all tasks regardless of which tasks is executed
If I have a code that copies the file with some follow up code that tries to operate on the file being copied then that code will not wait for copy process to complete and will fail because file is not there yet
I'm at loss on how to deal with this and would greatly appreciate your suggestions
The following works for me, using Gradle 2.12 (and assuming that the zip file resides in files):
buildscript {
configurations {
classpath
}
dependencies {
classpath files("files/tpcds.zip")
}
}
def copyFiles = { ->
ant.mkdir(dir: "build/zip")
buildscript.configurations.classpath.each { def thisFile ->
if (thisFile.name ==~ /tpcds.*/) {
ant.copy(file: thisFile.absolutePath, todir: "build/zip")
}
}
}
tasks.whenTaskAdded { task ->
if (task.name == "extractTpcds") {
copyFiles()
}
}
task copyTpcds << {
copyFiles()
}
task extractTpcds(type: Copy) {
def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
def outDir = file('build/cmd/tpcds')
outDir.mkdirs() // make sure the directory exists
from zipTree(file(names[0])) // generates error when
into outDir
// now remove copied zip file
//zipFile.delete() // deletes file before the extractions completes?
}
An issue with the original involves an impedance mismatch vis-a-vis the ICE rule: Initialization phase, Configuration phase, and Execution phase. In particular, the specification of the Copy task is in Configuration phase; typically, task dependencies are enforced (e.g. dependsOn) during the Execution phase. The extractTpcds task has a dependency on other code during the Configuration phase.
In my example, there are are 2 cases:
gradle copyTpcds will call the copyFiles method during Execution phase. The << means "do this stuff last [during the Execution phase]".
gradle tasks will trigger the code in whenTaskAdded, during Configuration phase, and call copyFiles. Similarly for gradle extractTpcds
An alternative to this is simply to use the AntBuilder in both tasks, and avoid Type: Copy completely, as shown here:
buildscript {
configurations {
classpath
}
dependencies {
classpath files("files/tpcds.zip")
}
}
task copyTpcds << {
ant.mkdir(dir: "build/zip")
buildscript.configurations.classpath.each { def thisFile ->
if (thisFile.name ==~ /tpcds.*/) {
ant.copy(file: thisFile.absolutePath, todir: "build/zip")
}
}
}
task extractTpcds(dependsOn: 'copyTpcds') << {
def outDir = "build/cmd/tpcds"
ant.mkdir(dir: outDir)
def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
names.eachWithIndex { zipFile, index ->
if (index == 0) {
ant.unzip(src: zipFile, dest: outDir)
}
}
}
Something like this should work, but why do you need to delete the zip? chaining the tasks with dependsOn means you only need to run the second task and the copyTpcds will automatically run unless the inputs or outputs have changed (deleted)
task extractTpcds(type: Copy) {
dependsOn(copyTpcds) //make this execute after
def names = new FileNameFinder().getFileNames('build/zip', 'tpcds*')
def outDir = file('build/cmd/tpcds')
outDir.mkdirs() // make sure the directory exists
from zipTree(file(names[0])) // generates error when
into outDir
// now remove copied zip file
doLast { zipFile.delete() }// deletes file after the extractions completes
}

wix Managed Bootstrapper: Engine.EvaluateCondition() requires separate thread?

In my Managed Bootstrapper, I tried to call Engine.EvaluateCondition("MY_PROG_FOUND"); in Run() method. But it never evaluates and said something like: "This requires a running thread." and it never evaluates.
I'm trying to evaluate Bundle conditions in my managed bootstrapper but still no luck.
MY_PROG_FOUND is defined in Bundle code:
<util:RegistrySearch Id="PETRELINSTALLLOCATION"
Variable="MY_PROG_FOUND"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Value="$(var.my_prog_env_var)"
Result="exists"
/>
<bal:Condition Message="[WixBundleName] required the installation of My Program.">
<![CDATA[Installed OR (MY_PROG_FOUND)]]>
</bal:Condition>
How can I use Engine.EvaluateCondition() in managed bootstrapper? Does this requires to be called in a specific event, like DetectBegin()??
Any help would be really appreciated...
Thanks a bunch.
Later I figured out that the separate thread is active during event calls. So I tried it during DetectComplete event and it worked. But before that, I had to parse BootstrapperApplicationData.xml file to get WixBalCondition elements and get the collection into an array e.g. BalConditions[].
Here is my code snippet:
void BootstrapperApplication_DetectComplete(object sender, DetectCompleteEventArgs e)
{
string balCondtionMessages = string.Empty;
bool balConditionStatus = true;
foreach (var balCondition in bootAppData.BundleData.BalConditions)
{
if (!model.BootstrapperApplication.Engine.EvaluateCondition(balCondition.Condition))
{
balConditionStatus = false;
if (!String.IsNullOrEmpty(balCondtionMessages))
{
balCondtionMessages = balCondtionMessages + '\n' + "- " + balCondition.Message;
}
else
balCondtionMessages = "- " + balCondition.Message;
}
}
if (!balConditionStatus)
{
SetbalConditionMsg(balCondtionMessages);
}
}
This makes us parse for all conditions in our Bundle.wxs code, evaluate them and display the related message in our Custom Bootstrapper UI.

ItemUpdating called twice after ItemAdded in event receiver

I've created an event receiver to handle the ItemAdded and ItemUpdating events on a document library in SharePoint 2010.
I've encountered a problem where when I add a document to the library (e.g. by saving it back from Word) the ItemAdded method is correctly called however this is then followed by two calls to ItemUpdating. I have removed all code from my handlers to ensure that it's not something I'm doing inside that is causing the problem. They literally look like:
public override void ItemUpdating(SPItemEventProperties properties)
{
}
public override void ItemAdded(SPItemEventProperties properties)
{
}
Does anyone have a solution to this issue?
Here is my elements.xml file for the event receiver:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Receivers ListTemplateId="101">
<Receiver>
<Name>DocumentsEventReceiverItemUpdating</Name>
<Type>ItemUpdating</Type>
<Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
<Class>My.Namespace.DocumentsEventReceiver</Class>
<SequenceNumber>10000</SequenceNumber>
<Synchronization>Synchronous</Synchronization>
</Receiver>
<Receiver>
<Name>DocumentsEventReceiverItemAdded</Name>
<Type>ItemAdded</Type>
<Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
<Class>My.Namespace.DocumentsEventReceiver</Class>
<SequenceNumber>10000</SequenceNumber>
<Synchronization>Synchronous</Synchronization>
</Receiver>
</Receivers>
</Elements>
Problem is that In Document library event handlers during Item Updating also checking that Document is it in Check In mode or Check Out. That's why it is called twice.
You should put your code in
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
if (properties.AfterProperties["vti_sourcecontrolcheckedoutby"] == null && properties.BeforeProperties["vti_sourcecontrolcheckedoutby"] != null)
{
//do stuff
}
}
For further details Here is good article for describe whole situation of the Document's Events.