I'm trying to create an Ant build that will run a target in every subfolder in a folder. I need this one in particular to only run at the subfolder level, because if I run it from the top folder and tel it to include subfolders, it scrambles the results.
I put the following together from suggestions I've seen, and it seems close but it's not working. A couple of points about it:
When I run this, I get "C:\Developer\SVN\trunk\DITA\xxx_conversion\test\${subdir} does not exist." (A subdirectory does exist, I have ...\test\testsub\xxx_xxx.dita)
The target named "script" works perfectly by itself. If I point it to a folder, it transforms what's in it and gives me the result I need.
In the foreach task if I change to just <dirset dir="."> as a test then the build succeeds, but it basically just runs the "script" target as is.
In the target named "script", if I change "*.dita" to "**\*.dita" it then includes the top level folder in its operation so the result is not what I need, which is just to take each .dita file in each subfolder and wrap it in a folder of the same name as the dita file:
Starting state: testsub\xxx_xxx.dita
Desired result: testsub\xxx_xxx\xxx_xxx.dita
Scrambled result: testsub\xxx_xxx\testsub\xxx_xxx.dita
If anyone can tell me what's wrong with this (possibly many things) that would be great:
<project name="move_and_wrap_dita_topics" default="script" basedir="C:\Developer\SVN\trunk\DITA\xxx_conversion\test">
<taskdef resource="net/sf/antcontrib/antlib.xml">
</taskdef>
<foreach target="script" param="worksheet" inheritall="true">
<path>
<dirset dir="${subDir}">
<include name="*"/>
</dirset>
</path>
</foreach>
<target name="script">
<copy todir="C:\Developer\SVN\trunk\DITA\xxx_conversion\cleaned" verbose="true">
<fileset dir="C:\Developer\SVN\trunk\DITA\xxx_conversion\test">
<include name="*.dita"/>
</fileset>
<scriptmapper language="javascript">
self.addMappedName(source.replace(source.split('.')[0], source.split('.')[0] + "/" + source.split('.')[0]));
</scriptmapper>
</copy>
</target>
</project>
As an alternative, if there's some way to just write the "include name" in the "script" task so that it skips the top folder completely and only rewrites starting at the subfolders, that would be even simpler. I've tried <include name="/*.dita"/>and all sorts of other variations but no luck.
Starting state: testsub\xxx_xxx.dita
Desired result: testsub\xxx_xxx\xxx_xxx.dita
This should be doable with a single regex mapper, you don't need the foreach at all:
<copy todir="C:\Developer\SVN\trunk\DITA\xxx_conversion\cleaned" verbose="true">
<fileset dir="C:\Developer\SVN\trunk\DITA\xxx_conversion\test"
includes="*/*.dita" />
<!-- use handledirsep to treat \ as if it were / in the source file name -->
<regexpmapper handledirsep="true" from="^(.*)/([^/]*)\.dita$"
to="\1/\2/\2.dita" />
</copy>
The includes="*/*.dita" will match .dita files that are one level below the base directory of the fileset, and the regex will convert testsub/xxx.dita in the source to testsub/xxx/xxx.dita in the destination. If you want to find files that are one-or-more levels deep then use */**/*.dita instead.
Related
I have a folder with files that have names starting with App_Web_ and ending with .dll. I don't know what's in between those parts and I don't know the number of files. I need MSBuild to move those files into another folder.
So I composed this:
<Move
SourceFiles="c:\source\App_Web_*.dll"
DestinationFolder="c:\target"
/>
but when the target runs I get the following output:
error MSB3680: The source file "c:\source\App_Web_*.dll" does not exist.
The files are definitely there.
What am I doing wrong? How do I have the files moved?
You cannot use regular expression directly in task parameters. You need to create an item containing list of files to move and pass its content to the task:
<ItemGroup>
<FilesToMove Include="c:\source\App_Web_*.dll"/>
</ItemGroup>
MSBuild will expand regular expression before passing it to the task executor. So later in some target you may invoke Move task:
<Target Name="Build">
<Move
SourceFiles="#(FilesToMove)"
DestinationFolder="C:\target"
/>
</Target>
Using Nant 0.92 (and previously 0.85 with same consequence)
I'm trying to call the delete task in NAnt to remove all files except the .dll file after calling msbuild (see the script below .. I'm referring to the delete in the "build" target). The delete task does not seem to execute.
The initial delete task works fine, and behaves as expected, removing all files from the specified build directory. The second delete task, after the compile however doesn't work.
I've tried just deleting everything (not using the exclude tag), tried explicitly setting failonerror and verbose to true. None of these make a difference. I've also tried using sleep to stop the process prior to the delete task, in case something in msbuild was not releasing the files in time for a delete. I've tried putting the delete into a separate target, still no luck.
The command obviously works prior to calling msbuild, and it works after msbuild if trying to delete from a directory other than the msbuild output target (i.e. copy the output files, then delete relevant files).
I'm sure that this is too fundamental a problem to be a bug, but I thought I'd ask anyway. Of course I'll use the workaround in the mean time of just copying the files to a different location delete what I don't need then move appropriately, but I'm curious about this.
I suspect, that unless this behaviour is by design (although I can find nothing in the NAnt documentation to suggest it is), then perhaps the msbuild process is locking the output files until NAnt process completes? This is my best guess. Further insights would be appreciated.
EDIT: also, if I explicitly set the \OutputPath switch of msbuild, then I don't have the same problem. It only appears that when the default OutputPath is used is the problem created.
NAnt build file:
<?xml version="1.0" encoding="utf-8" ?>
<project name="Reports.TestBench.PreBuild" default="postbuild.cleanup" basedir="." xmlns="http://nant.sourceforge.net/release/0.86-beta1/nant.xsd">
<property name="nant.settings.currentframework" value="net-4.0" />
<property name="project.StandardReports" value="${project::get-base-directory()}\Reports.StandardReports\Palladium.Reports.StandardReports.csproj" />
<property name="output.Dir" value="${project::get-base-directory()}\bin\debug\"/>
<property name="build.Type" value="debug"/>
<!--Deletes the pre-existing build files-->
<target name="clean">
<delete>
<fileset basedir="${output.Dir}">
<include name="*.*" />
</fileset>
</delete>
</target>
<!--Builds the projects to the specified build directory-->
<target name="build" depends="clean" description="Build the Palladium Reports Standard Reports application">
<msbuild project="${project.StandardReports}">
<arg value="/p:Configuration=${build.Type}" />
<!--arg value="/p:OutputPath=${path::get-full-path(buildDir.Client)}\Reports" /-->
<arg value="/t:Rebuild" />
</msbuild>
<delete failonerror="true" verbose="true">
<fileset basedir="${output.Dir}">
<include name="*.*" />
<exclude name="Palladium.Reports.StandardReports.dll" />
</fileset>
</delete>
</target>
</project>
Summary of NAnt output showing build success with no further messages:
[msbuild] Build succeeded.
[msbuild] 0 Warning(s)
[msbuild] 0 Error(s)
[msbuild]
[msbuild] Time Elapsed 00:00:03.19
BUILD SUCCEEDED
Total time: 3.5 seconds.
Try poking into NAnt source code - most likely the msbuild task creates an MSBuild engine and does not force it to close the files afterwards. Although looking at the MSDN docs, I don't really see a way to do it - MSBuild constructs lack a Dispose() function. There's a finalizer on classes such as ProjectInstance, so one could force it release the file handles by running in an application domain and closing the whole domain afterwards - that's quite a bit of work.
I have a problem executing all SQL files in a folder with sqlplus command
I can run one file or first file with this code
<apply executable="sqlplus" dir="." parallel="false">
<!-- <arg value="-S" /> -->
<arg line="${db.user}/${db.pwd}#'${db.sid}'" />
<arg value="#${db.run.build.script}" /> this is working, which is for executing one file
<!-- <arg value="--e source" /> -->
<srcfile/>
<fileset dir="..\..\Documents\test\Database\SQL\common\test"
casesensitive="no" description="take all sql files">
<patternset>
<include name="**/*.sql" />
</patternset>
</fileset>
</apply>
; but cannot proceed further with other files
I have tried various options with apply task; but still not succeed; I thought the second file hasn't "#" in the beginning that causes the problem.
any help will be highly appreciated.
OK, first of all: I've never used sqlplus :-)
But based on the post I've seen here: http://www.zorbathegeek.com/161/run-multiple-sqlplus-queries-via-dos-batch-file.html I understood that it's a must to provide # as a prefix to path to all the files that should be considered.
I see there multiple options, based on restrictions:
First check if you can provide in command line multiple of your files like this:
sqlplus [login details] #C:/<your_path>/<file1>.sql #C:/<your_path>/<file1>.sql
depending if it's possible or not, you should later decide if you need to create 1 file containing all the filenames prefixed with # (as the example provided in the reffered site) or not
Now how to do the prepending? I think it should be simple, just try to use Ant's parhconvert described: http://ant.apache.org/manual/Tasks/pathconvert.html
<fileset dir="..\..\Documents\test\Database\SQL\common\test" id="sql.files">
<include name="**/*.sql"/>
</fileset>
<pathconvert pathsep=" " property="prefixed.sql.files" refid="sql.files">
<map from="c:/" to="#c:/"/>
</pathconvert>
(where you should replace c:/ with the string that your file paths start with. Moreover, if you will dump to file, pathsep=" " should be probably replaced with pathsep="\n" as there might be a need to have one file per line, but this needs test)
then depending on the options of all in one file or all files on cmd line, you:
either need to dump it to tmp file and run using this tmp file name
http://ant.apache.org/manual/Tasks/echo.html
In this case, the file should be later deleted
use property prefixed.sql.files directly in your apply arg value like:
<arg value="${prefixed.sql.files}" />
The scenario is as follows:
Therea are three files :
test.xls
test.txt
test.doc
I am working with mqfte right now. When these files are transferred to another location the filenames must be as below :
result_xls.txt
result_txt.txt
result_doc.txt
Could anyone help on this?
Can this filename renaming done with ant scripts?
Try this:
<target name="test">
<copy todir="dest">
<fileset dir="src">
<include name="test*"/>
</fileset>
<globmapper from="test.*" to="result_*.txt"/>
</copy>
</target>
Input:
$ find src
src
src/test.doc
src/test.txt
src/test.xls
Output:
$ find dest/
dest/
dest/result_doc.txt
dest/result_txt.txt
dest/result_xls.txt
Sure, you can use the Move Ant Task http://ant.apache.org/manual/Tasks/move.html
I'm a make(1) guy by nature. What I want to do is the equivalent of this make fragment:
FILES = generated.cs
app.exe : $(FILES)
csc -out:$# $(FILES)
generated.cs :
echo "// generated file" > $#
That is, $(FILES) contains a list of files, some of which may be generated by other targets within the Makefile. This Just Works.
I would like to do the ~same thing with MSBuild. Unfortunately, my attempt has failed:
<Target Name="BuildGenerated"
Outputs="Generated.cs"
>
<WriteLinesToFile
File="Generated.cs"
Lines="// generated file"
Overwrite="True"
/>
</Target>
<ItemGroup>
<Compile Include="Generated.cs" />
</ItemGroup>
That is, use <Compile/> to include a generated file and have MSBuild deduce that since Generated.cs doesn't exist, it should find some <Target/> which will generate that file and then execute it.
It looks like the only way to do something like this is to add pre-build steps, but that seems like a hack. Are pre-build steps the only way to do this? Or is there some way to make MSBuild act like it has a brain?
Update 1: For reference, this would be the pre-build incantation needed to make it work, and (again) this is something I'd rather avoid if possible:
<PropertyGroup>
<CompileDependsOn>
BuildGenerated;$(CompileDependsOn)
</CompileDependsOn>
</PropertyGroup>
This would need to occur after the <Import Project="..." /> element(s) defining <CompileDependsOn/>.
The problem is that your file is a generated one and MsBuild parses the item and property group only once (at the beginning of your build). Thus, when MsBuild tries to include the generated.cs file, it is not created yet and MsBuild does include nothing at all.
A correct way of doing it would be to do the include part inside the BuildGenerated target which would cause it to be dynamically evaluated.
<Target Name="BuildGenerated"
Outputs="Generated.cs"
>
<WriteLinesToFile
File="Generated.cs"
Lines="// generated file"
Overwrite="True"
/>
<ItemGroup>
<Compile Include="Generated.cs" />
</ItemGroup>
</Target>
More information in my answer to this question : Bin folder not being copied with MSBuild, Teamcity
EDIT
Sorry, I did not read correctly your question. in your makefile, in the app.exe target (the default one) you explicitely call your generated.cs target. You can do the same with MsBuild.
By default, MsBuild search for the Build target (the 'all' in makefile), if your main target is "app.exe" you have to call BuildGenerated target within with one of the following option :
<Target Name="app.exe" DependsOnTargets="BuildGenerated>
<!-- Stuff here -->
</Target>
or
<Target Name="app.exe">
<CallTarget Targets="BuildGenerated"/>
<!-- Stuff here -->
</Target>
If you don't set a default target, you can do it either via commandline with the /t parameter or in the project declaration :
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="app.exe">