So this is a question for anyone who has had to integrate the building/compilation of legacy projects/code in a Team Build/MSBuild environment - specifically, Visual Basic 6 applications/projects.
Outside of writing a custom build Task (which I am not against) does anyone have any suggestions on how best to integrate compilation and versioning of legacy VB6 projects into MSBuild builds?
I'm aware of the FreeToDev msbuild tasks at CodePlex but they've been withdrawn at the moment.
Ideally I'm looking to version and compile the code as well as capture the compilation output (especially errors) for the msbuild log.
I've seen advice on encapsulating this functionality in a custom task, but really wondered if anyone has tried another solution (aside from executing shell commands) -
In essence, does anyone have a "cleaner" solution?
Ideally, executing commands using would be a last resort..
The VB6 task will be back on Monday. With regards to versioning, there is no explicit vb versioning task in the pack, however you could make use of the TfsVersion (TaskAction="GetVersion") and the File (TaskAction="Replace") tasks. If you think there is value in creating a new task to encapsulate / provide other functions, then please let me know and I will add it to the pack for the benefit of the whole community.
Apologies for the withdrawal, but come Monday I'm sure all will understand.
I am using Nant to build VB6 projects daily. This does resort using the Nant execute command to do the builds (we build 4 projects as part of one "solution").
It also allows you to label versions in your source control repository, get latest code, check in, check out, all the normal requirements, compile the update/setup programs copy the files to required locations and send emails of the results.
The logged results are fairly minimal though as you only get the output provided by a VB6 command line compile.
For versioning, I had to write a small app to extract the version number of my compiled executable and write it to a text file that Nant could then read and use (for labels, file names etc. (A bit of a pain but VB generated version numbers don't comply anyway).
For help with other non-core tasks see NAntContrib - from the NAnt link above.
Related
I have a project where there are files in a particular non-standard textual format. When these files are touched/modified, I want to run a certain custom compiler on them to generate XML, which is part of the output of the whole solution.
I'm considering creating a MSBuild task to do this. It will take as input the non-stadard file names and output the requisite XML files. The task will then be used in the other projects in the solution.
I want new developers on this project to have minimal setup. That means, I want to be able to take a clean copy of my solution directly from source control and have the build first build the custom task, then apply it as necessary to the other projects in the class.
I'm concerned that the build output of the project that builds the custom task needs to copy its output assembly to some known location so that the other projects can refer to it. What is the proper way of going about doing this?
You're about to walk into a mess here, because Visual Studio is going to lock the custom task Assembly when it's first used, thereby causing any further builds in Visual Studio (i.e. Build > Solution) to fail.
As #stijn commented, you should override the Build target and use another method of building the assembly with the custom task, e.g. using the Csc task or spawning another MSBuild.exe process (see answer to linked question).
The way I decided to go though was to create a separate solution, e.g. "Build Tools", containing the custom task assembly (among other tools), and required that it be built before anything else. I personally find the notion of checking-in prebuilt binaries of this source very unpalatable. If developers didn't want to build the Build Tools solution, they would copy the output from some nightly build.
Unfortunately there isn't an easy way of getting around "hardcoding" a known (relative) location. Using $(SolutionDir) usually works - just not if you try to run MSBuild on the project directly, instead of the solution (VS is a bit more intelligent when you open a project by itself).
I've just learned the hard way that Visual Studio 2010 and MSBuild extremely lenient when it comes to which vcxproj MSBuild files they will successfully execute - they will overlook missing configurations for subtasks and single files and still successfully execute the build tasks. However this is causing problems for me as it is leading to inconsistent builds across multiple configurations, plus due to the internal inconsistencies in the project files I cannot necessarily edit them in Visual Studio's property view.
So far I have managed to get rid of the most problematic inconsistencies by editing the vcxproj files by hand but this is not really an acceptable strategy given that this particular solution contains over 80 project files.
Is there a tool that can check an MSBuild file for internal consistency and highlight missing configurations along the lines of "your project files says it offers configurations X, Y and Z but the custom build task for file X only supports configurations X and Z"?
Update: The specific problem I am trying to solve right now as opposed to the more general problem of linting the vcxproj file is that of missing conditionals for certain configurations. Unfortunately adding and updating the conditionals seems to require a little more than I can safely accomplish using a find-and-replace tool. Doing it programmatically and correctly would most likely require DOM manipulation and given that I am rather familiar with the internal structure of the build files so far it appears that using a text editor that is able to do basic structural XML validation is the quickest way to accomplish the task at hand.
What I would really like to see however would be a tool that can at least highlight these problems automatically to cut down on the time spent tracking them down.
Configurations are, in general, a VS concept. They are not built-in to MSBuild but achieved using Conditional attributes on property groups. Most likely your project files are valid MSBuild projects, but some of them don't build with default parameters - I'd suggest not to edit them by hand, but either
use a find-and-replace tool to fix them
write a small app that uses Microsoft.Build.Construction API to inspect and fix the project files
There's nothing that would perform this for you, I'm afraid.
This request is currently tracked under https://github.com/dotnet/msbuild/issues/1777
This is not a real answer yet, but as soon as the issue gets resolved to a tangible solution, I'll update it here.
I have set up cruisecontrol.net cs for my project that has a number of modules and components that get build and get stored in folder by date on the build machine.The thing is that I need to make setup for the application(wpf non web) and the thing is that since there are a number of module and different solutions that build and finally make the product (dlls) etc.Any suggestion on comming up with a setup strategy that will create a nightly setup and also what setup package to use (something simpler or according to you that would take less time) I was planning to install something on the build machine that would pick up the files from the folder (what folder?) and make the setup...
A link to illustrate the point is Firefox's nightly build.
Any advice guys
Thanks in advance.
I am finding that this system is working pretty well for me. I assume VS 2005/2008 and C#, but the same principle works for other compilers and languages just substitute your own flavoring.
Using CC.NET
Check out all source with scheduleTrigger, if multiple locations use
Use MSBuild to build each solution that is required (assuming VS 2005/2008), or nant, or whatever build tool works best for compiling your component projects
Use MSBuild to create WIX installers, though I have also used MSBuild to create InnoSetup and Wise Installation Studio installations
Use MSBuild to update the AssemblyInfo.cs files for any projects that you want the build script to control
Use your source control command line to check-in updated AssemblyInfo.ca files
Finally use MSBuild to copy your output installer to a new folder in your drop server. I use the time stamp from the primary product executable to make a timestamp along with the generated version number to name the folder (../Builds/Product/v.M.m.r.p - DATE TIME/)
I also like to generate a build notice email at the end.
As for installer recommendations, there is a trade-off.
For fast generation, use a script installer like NSIS or Inno Setup. The drawback is not being Windows Installer compatible.
For Windows Installer products, using Wise or InstallShield are faster to generate the first time, but expensive tools and I find the maintenance on my installation scripts is high. Using WIX tends to be much more expensive the first time (learning curve + angle bracket-tax), but then easier to maintain as it is all XML and the command line tools are easy to use.
I have had some success with installation bundling with Inno Setup as Windows Installer bundling and chaining (at least for Windows XP) is a real pain.
We used Visual Build and Wise for our installer creation and find that highly intuitive and easy to create the set ups with. The actual CC.NET project does a few things, first thing is it checks to make sure all of the needed parts have been built successfully since the last time we created an installer (we allow installers on demand as well as scheduled every night) if they haven't been build successfully we rebuild all the componenets, once they have been (or if they already were) built successfully we then call VisualBUildPro and let it create the installer. Visual Build Pro, handles all the copying and the calling of Wise for the actual installer. Once the installer is created we publish it out to the destination where everyone expects it to be. We also have modified the XSL for the email publisher on the builds server, so everyone gets a link to the newest installer once it is published.
A few things about the nightly builds if you can you should try setting up a symbol server and have every installer upload symbols with source code information up to them. This is also a good point to have any documentation (D'Oxygen; SandCastle) Create and the time to run your FULL suite of testing that you have available.
Take a look at WiX. This toolset allows the setup project to be defined in XML form, and then generates the msi from this XML. The fact that the project is defined in XML gives you alot of flexibility to modify this XML on the fly during the build (if needed).
It integrates with MSBuild - see this article, and also works well with NAnt - see this article.
I know the ideal way to build projects is without requiring IDE based project files, since it theoretically causes all sort of trouble with automation and what not. But I've yet to work on a project that compiles on Windows that doesn't depend on the VisualStudio project (Ok, obviously some Open Source stuff gets done with Cygwin, but I'm being general here).
On the other hand if we just use VS to run a makefile, we loose all the benefits of the compile options window, and it becomes a pain to maintain the external makefile.
So how do people that use VS actually handle external makefiles? I have yet to find a painless system to do this...
Or in reality most people don't do this, although its preached as good practice?
Take a look at MSBuild!
MSBuild can work with the sln/csproj files from VS, so for simple projects you can just call them directly.
if you need more control, wrap the projects in your own build process, add your own tasks etc. - it is very extensible!
(I wanted to add a sample but this edior totally messed up the XML... sorry)
Ideally perhaps, in practice no.
Makefiles would be my preference as the build master, however, the developers spend all their time inside the visual studio IDE and when they make a change, it's to the vcproj file, not the makefile. So if I'm doing the global builds with makefiles, it's too easily put out of synch with the project/solution files in play by 8 or 10 others.
The only way I can stay in step with the whole team is to run devenv.exe on the solution files directly in my build process scripts.
There are very few makefiles in my builds, where there are they are in the pre-build or custom build sections or a separate utility project.
One possibility is to use CMake - you describe with a script how you project is to be built, and CMake generates the Visual Studio solution/project files for you.
And if you need to build your project from the command line, or in a continuous integration tool, you use CMake to generate a Makefile for NMake.
And if you project is a cross-platform one - you can run CMake to generate the makefiles for the toolchain of your choice.
A simple CMake script looks like this:
project(hello)
add_executable(hello hello.cpp)
Compare these two lines with a makefile or the way you setup a simple project in your favorite IDE.
In a nutshell CMake does not only cross-platform-enables your project it also makes it cross-IDE. If you like to just test your project with eclipse or KDevelop, or codeblocks, just run CMake to generate the corresponding project files.
Well, in practice it is no always so easy, but the CMake idea just rocks.
For example, if you consider using CMake with Visual Studio there is some tweaking required to obtain the familiar VS project feeling, main obstacle is to organize your header and source files, but it is possible - check the CMake wiki (and by writting a short script you might even simplify this task).
We use a NAnt script, which at the compile step calls MSBuild. Using NAnt allows us to perform both pre- and post-build tasks, such as setting version numbers to match source control revision numbers, collating code coverage information, assembling and zipping deployment sources. But still, at the heart of it, it's MSBuild that's actually doing the compiling.
You can integrate a NAnt build as a custom tool into the IDE, so that it can be used both on a build or continuous integration server and by the developers in the same way.
Personally, I use Rake to call msbuild on my solution or project. For regular development I use the IDE and all the benefits that provides.
Rake is set up so that I can just compile, compile and run tests or compile run tests and create deployable artifacts.
Once you have a build script it is really easy to start doing things like setting up continuous integration and using it to automate deployment.
You can also use most build tools from within the IDE if you follow these steps to set it up.
We use the devenv.exe (same exe that launches the IDE) to build our projects from the build scripts (or the command line). When specifying the /Build option the IDE is not displayed and everything is written back to the console (or the log file if you specify the /Out option)
See http://msdn.microsoft.com/en-us/library/xee0c8y7(VS.80).aspx for more information
Example:
devenv.exe [solution-file-name] /Build [project-name] /Rebuild "Release|Win32" /Out solution.log
where "Release|Win32" is the configuration as defined in the solution and solution.log is the file that gets the compiler output (which is quite handy when you need to figure out what went wrong in the compile)
We have a program that parses the vcproj files and generates makefile fragments from that. (These include the list of files and the #defines, and there is some limited support for custom build steps.) These fragments are then included by a master makefile which does the usual GNU make stuff.
(This is all for one of the systems we target; its tools have no native support for Visual Studio.)
This didn't require a huge amount of work. A day to set it up, then maybe a day or two in total to beat out some problems that weren't obvious immediately. And it works fairly well: the compiler settings are controlled by the master makefile (no more fiddling with those tiny text boxes), and yet anybody can add new files and defines to the build in the usual way.
That said, the combinatorical problems inherent to Visual Studio's treatment of build configurations remain.
Why would you want to have project that "compiles on Windows that doesn't depend on the VisualStudio project"? You already have a solution file - you can just use it with console build.
I'd advise you to use msbuild with conjunction with makefile, nant or even simple batch file if your build system is not as convoluted as ours...
Is there something I'm missing?
How about this code?
public TRunner CleanOutput()
{
ScriptExecutionEnvironment.LogTaskStarted("Cleaning solution outputs");
solution.ForEachProject(
delegate (VSProjectInfo projectInfo)
{
string projectOutputPath = GetProjectOutputPath(projectInfo.ProjectName);
if (projectOutputPath == null)
return;
projectOutputPath = Path.Combine(projectInfo.ProjectDirectoryPath, projectOutputPath);
DeleteDirectory(projectOutputPath, false);
string projectObjPath = String.Format(
CultureInfo.InvariantCulture,
#"{0}\obj\{1}",
projectInfo.ProjectName,
buildConfiguration);
projectObjPath = Path.Combine(productRootDir, projectObjPath);
DeleteDirectory(projectObjPath, false);
});
ScriptExecutionEnvironment.LogTaskFinished();
return ReturnThisTRunner();
}
public TRunner CompileSolution()
{
ScriptExecutionEnvironment.LogTaskStarted ("Compiling the solution");
ProgramRunner
.AddArgument(MakePathFromRootDir(productId) + ".sln")
.AddArgument("/p:Configuration={0}", buildConfiguration)
.AddArgument("/p:Platform=Any CPU")
.AddArgument("/consoleloggerparameters:NoSummary")
.Run(#"C:\Windows\Microsoft.NET\Framework\v3.5\msbuild.exe");
ScriptExecutionEnvironment.LogTaskFinished ();
return ReturnThisTRunner ();
}
You can find the rest of it here: http://code.google.com/p/projectpilot/source/browse/trunk/Flubu/Builds/BuildRunner.cs
I haven't tried it myself yet, but Microsoft has a Make implementation called NMake which seems to have a Visual Studio integration:
NMake
Creating NMake Projects
Visual Studio since VS2005, uses "msbuild" to define and run builds. When you fiddle with project settings in the Visual Studio designer - let's say you turn XML doc generation on or off, or you add a new dependency, or you add a new project or Assembly reference - Visual Studio will update the .csproj (or .vbproj, etc) file, which is an msbuild file.
Like Java's ant or Nant before it, msbuild uses an XML schema to describe the project and build. It is run from VS when you do a "F6" build, and you can also run it from the command line, without ever opening VS or running devenv.exe.
So, use the VS tool for development and command-line msbuild for automated builds - same build, and same project structure.
I would like to use Visual Studio 2008 to the greatest extent possible while effectively compiling/linking/building/etc code as if all these build processes were being done by the tools provided with MASM 6.11. The exact version of MASM does not matter, so long as it's within the 6.x range, as that is what my college is using to teach 16-bit assembly.
I have done some research on the subject and have come to the conclusion that there are several options:
Reconfigure VS to call the MASM 6.11 executables with the same flags, etc as MASM 6.11 would natively do.
Create intermediary batch file(s) to be called by VS to then invoke the proper commands for MASM's linker, etc.
Reconfigure VS's built-in build tools/rules (assembler, linker, etc) to provide an environment identical to the one used by MASM 6.11.
Option (2) was brought up when I realized that the options available in VS's "External Tools" interface may be insufficient to correctly invoke MASM's build tools, thus a batch file to interpret VS's strict method of passing arguments might be helpful, as a lot of my learning about how to get this working involved my manually calling ML.exe, LINK.exe, etc from the command prompt.
Below are several links that may prove useful in answering my question. Please keep in mind that I have read them all and none are the actual solution. I can only hope my specifying MASM 6.11 doesn't prevent anyone from contributing a perhaps more generalized answer.
Similar method used to Option (2), but users on the thread are not contactable:
http://www.codeguru.com/forum/archive/index.php/t-284051.html
(also, I have my doubts about the necessity of an intermediary batch file)
Out of date explanation to my question:
http://www.cs.fiu.edu/~downeyt/cop3402/masmaul.html
Probably the closest thing I've come to a definitive solution, but refers to a suite of tools from something besides MASM, also uses a batch file:
http://www.kipirvine.com/asm/gettingStarted/index.htm#16-bit
I apologize if my terminology for the tools used in each step of the code -> exe process is off, but since I'm trying to reproduce the entirety of steps in between completion of writing the code and generating an executable, I don't think it matters much.
There is a MASM rules file located at (32-bit system remove (x86)):
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCProjectDefaults\masm.rules
Copy that file to your project directory, and add it to the Custom Build Rules for your project. Then "Modify Rule File...", select the MASM build rule and "Modify Build Rule...".
Add a property:
User property type: String
Default value: *.inc
Description: Add additional MASM file dependencies.
Display name: Additional Dependencies
Is read only: False
Name: AdditionalDependencies
Property page name: General
Switch: [value]
Set the Additional Dependencies value to [AdditionalDependencies]. The build should now automatically detect changes to *.inc, and you can edit the properties for an individual asm file to specify others.
You can create a makefile project. In Visual Studio, under File / New / Project, choose Visual C++ / Makefile project.
This allows you to run an arbitrary command to build your project. It doesn't have to be C/C++. It doesn't even have to be a traditional NMake makefile. I've used it to compile a driver using a batch file, and using a NAnt script.
It should be fairly easy to get it to run the MASM 6.x toolchain.
I would suggest to define Custom Build rules depending on file extension.
(Visual Studio 2008, at least in Professinal Edition, can generate .rules files, which can be distributed). There you can define custom build tools for asm files. By using this approach, you should be able to leave the linker step as is.
Way back, we used MASM32 link text as IDE to help students learn assembly. You could check their batchfiles what they do to assemble and link.
instead of batch files, why not use the a custom build step defined on the file?
If you are going to use Visual Studio, couldn't you give them a skeleton project in C/C++ with the entry point for a console app calling a function that has en empty inline assembly block, and let them fill their results in it?
Why don't you use Irvine's guide? Irvine's library is nice and if you want, you can ignore it and work with Windows procs directly. I've searching for a guide like this, Irvine's was the best solution.