Today I released “FAKE – F# Make” version 1.40.5.0. This release fixes some issues with CruiseControl.NET compatibility and improves the MSBuild task.
Important links:
Changes for CruiseControl.NET
Daniel Nauck created a FAKE task for CC.Net. This task allows a much easier configuration of FAKE. Please download the latest CC.NET build if you want to use it.
Daniel also created a FAKE build project on his server which showed us some compatibility issues:
- In FAKE:
- Race condition in FAKE’s trace functionality
- Better XML tracing if something fails
- The tracing buffer will be flushed after every build target
- Every task has a Timeout property (Default: 5 min.)
- Setting of environment variables fixed
- Showing labels in NUnit is now the default
- In Docu:
- In CC.NET:
@Daniel: Thank you very much for helping me on this CruiseControl.NET stuff. I really appreciate this.
MSBuild task changes
The MSBuild task in FAKE gets a sequence of project files and compiles them in the given order. This might be slow if you have lots of dependent projects. Then MSBuild might analyze the dependencies over and over again. To fix this issue I currently see two possible solutions:
- Generate a temporary solution file and use this for compilation.
- Analyze the given projects and remove all dependent projects from the list.
FAKE 1.40.5.0 implements the second idea. If you have a better idea please contact me.
Tags:
docu,
F#,
F-sharp Make,
Fake
Yesterday I released “FAKE – F# Make” version 1.33.0. This release has lots of small bug fixes and a couple of new features.
Important links:
Git helpers -Fake.Git.dll
Git is a distributed revision control system with an emphasis on speed. Git was initially designed and developed by Linus Torvalds for Linux kernel development. Every Git working directory is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server.
[Wikipedia]
In the last couple of months I worked on small helper library for controlling Git. This library is now released as part of “FAKE – F# Make”. You can find the source code at http://github.com/forki/FAKE/tree/master/src/app/Fake.Git/.
Features:
- Repository handling
- Submodules
- init, clone, information about submodules
- Branches
- checkout, create, delete, merge, rebase, tag, pull, push, reset, commit, …
- SHA1 calculation
Documentation generation with James Gregory’s docu tool
What’s a docu? A documentation generator for .Net that isn’t complicated, awkward, or difficult to use. Given an assembly and the XML that’s generated by Visual Studio, docu can produce an entire website of documentation with a single command.
[docu website]
Fake comes bundled with James Gregory’s documentations generator “docu”, which converts XML-Documentation comments into HTML files. All you need to do is downloading a template and calling the docu task inside your build script:
!+ (buildDir + "*.dll")
|> Scan
|> Docu (fun p ->
{p with
ToolPath = docuPath + "docu.exe"
TemplatesPath = templatesSrcDir
OutputPath = docsDir })
Since FAKE builds its own documentation with docu I started to add more (and hopefully better) XML doc comments. My plan is to describe more and more of the internal FAKE functions in the next releases. An updated HTML-document (generated via a docu task) can be found at http://www.navision-blog.de/fake/.
Side by side specification
For Test-driven development (TDD) it’s sometimes nice to have the specifications next to the implementation files since the specs are considered as documentation.
By using a tool like VSCommands it is possible to group the implementation with the specs (see also http://gist.github.com/457248).
This “side by side specification” makes TDD a lot easier but of course we don’t want to deploy the specification classes and the test data.
|
==> |
|
FAKE has a new feature which automatically removes all specification files and test framework references according to a given convention:
Target "BuildApp" (fun _ –>
!+ @"src\app\**\*.csproj"
|> Scan
|> Seq.map (
RemoveTestsFromProject
AllNUnitReferences // a default references convention
AllSpecAndTestDataFiles // a default file convention
)
|> MSBuildRelease buildDir "Build"
|> Log "AppBuild-Output: "
)
The conventions are simple functions and can be customized e.g.:
/// All Spec.cs or Spec.fs files and all files containing TestData
let AllSpecAndTestDataFiles elementName (s:string) =
s.EndsWith "Specs.cs" ||
s.EndsWith "Specs.fs" ||
(elementName = "Content" && s.Contains "TestData")
Miscellaneous
- SQL Server helpers are moved to Fake.SQL.dll
- Additional functions for attaching and detaching databases.
- FileHelper.CopyCached function was added
- Copies the files from a cache folder. If the files are not cached or the original files have a different write time the cache will be refreshed.
- EnvironmentHelper.environVarOrDefault added
- Retrieves the environment variable or a given default.
- Fixed Issue 3: toRelativePath calculates paths with ..\..\ if needed
- Added a build time report to the build output.
- XPathReplace and XMLPoke tasks added.
- Replaces text in an XML file at the location specified by an XPath expression.
- ILMerge task added
- Windows Installer XML (WiX) task added
Tags:
F#,
F-sharp Make,
Fake,
git,
SideBySideSpecification,
SQL Server,
TDD,
xml,
XPath
My colleague Mathias Meissner found a strange bug in the Dynamics NAV Client (occurs at least in the native clients for NAV 403, 501 and 601). It seems the following code creates a strange memory allocation issue. (Download sample)
OBJECT Codeunit 99500 NAV Bug
{
OBJECT-PROPERTIES
{
Date=17.06.10;
Time=14:30:30;
Modified=Yes;
Version List=;
}
PROPERTIES
{
OnRun=BEGIN
TestMiddleCase; // comment this line out and ReverseString works!
TestReverseString;
END;
}
CODE
{
PROCEDURE TestMiddleCase@5128500();
BEGIN
MiddleCase('fooo AnD bar');
END;
PROCEDURE TestReverseString@5128502();
VAR
l_String@5128500 : Text[1024];
l_Result@5128503 : Integer;
BEGIN
l_String :=
'1101101111011011110110111101101111011011110110111101101111011011' +
'1101101111011011110110111101101111011011110110111101101111011011' +
'1101101111011011110110111101101111011011110110111101101111011011' +
'1101101111011011110110111101101111011011110110111101101111011011' +
'1101101111011011110110111101101111011011110110111101101111011011' +
'1101101111011011110110111101101111011011110110111101101111011011' +
'1101101111011011110110111101101111011011110110111101101111011011' +
'1101101111011011110110111101101111011011110110111101101111011011';
IF STRLEN(l_String) <> 512 THEN
ERROR('Wrong strlen');
l_Result := TestReverseStringSub(l_String);
IF l_Result <> 512 THEN
ERROR('Error: Actual: ' + FORMAT(l_Result) + ' ' + ' Expected: 512');
END;
PROCEDURE TestReverseStringSub@5128521(p_String@5128500 : Text[1024]) r_Int : Integer;
VAR
l_StringMgt@5128501 : Codeunit 5128519;
BEGIN
p_String := ReverseString(p_String);
EXIT(STRLEN(p_String));
END;
PROCEDURE ReverseString@5128509(p_In@5128502 : Text[1024]) Result : Text[1024];
VAR
i@5128500 : Integer;
l_Length@5128501 : Integer;
BEGIN
l_Length := STRLEN(p_In) + 1;
FOR i := 1 TO l_Length - 1 DO
Result[i] := p_In[l_Length-i];
END;
PROCEDURE MiddleCase@1000000000(p_StringToConvert@1000000000 : Text[250]) ConvertedString : Text[250];
BEGIN
ConvertedString :=
UPPERCASE(COPYSTR(p_StringToConvert, 1, 1)) +
LOWERCASE(COPYSTR(p_StringToConvert, 2));
END;
BEGIN
END.
}
}
Since we don’t do anything evil here my only advice is to initialize every return parameter with a default value. This seems to fix the bug.
PROCEDURE ReverseString@5128509(p_In@5128502 : Text[1024]) Result : Text[1024];
VAR
i@5128500 : Integer;
l_Length@5128501 : Integer;
BEGIN
Result := ''; // Init return value – this fixes the issue!
l_Length := STRLEN(p_In) + 1;
FOR i := 1 TO l_Length - 1 DO
Result[i] := p_In[l_Length-i];
END;
Interestingly I didn’t find a smaller sample which reproduces this memory issue.
Tags:
bugs,
Dynamics NAV 2009