Slickening up the build cycle for compiled plugins

June 19th, 2008 by Kim Aldis - Viewed 8954 times -




1. compile with copy, 2. oops, error, file in use, 3. switch to XSI, 4. dig down and unload plugin, 5. switch to VS, 6. compile ……. yaddda ….. you know the drill.

For years I’ve been doing this and for years I’ve been meaning to get around to making it slicker but somehow there was never time. So the other day it rained – fit to burst – and I had a day inside with nothing else to do and this is what I ended up with.

Earlier attempts ended up in a puddle on the floor because for some reason the only links I could find to VSS command line building pointed me at VCBuild.exe, which is just a plain old mess. This time, though, I found a link to a list of command line options for devenv.exe – what you run to bring up the VS IDE – at the excelent codeproject.com and these are much more straightforward.

The process is fairly simple:

1. unload the plugin.
2. run a command line build using system()
3. copy over the dll (my build has this built in)
4. reload the plugin.
5. test
6. package

Step 2 involves a little bit of wrastling with .bat command line, um, features but really the code (at the end of this article) is quite simple. Because it’s scripted you can build entire plugin sets and package them in one go. The whole process takes only seconds because it’s self contained and it’s dead easy to stuff in some test code. You can easily slip back to the IDE when you need it and it makes working with a preferred text editor easier if that’s your bag.

There’s also the advantage that the build inherits the paths to libraries from the XSI version you’re working with. No more .bat file wrappers. Neat!

This example code is just a list of functions:

Build( solutionName, PluginName, forceRebuild ); // do the actual build.
GetConfig(); //gets the platform type (32/64)
Package( PluginName ); // package. Output name is hard coded in the example.

I stuff the plugin names in an array so I can build a bunch of them in one.

I also have a custom property I use with a dropdown list of my main projects along with build and package buttons.

And finally, I figure I might, next time it rains, get this working alongside package location. Who knows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
var sPlugins = new Array( "TinyCurveExtrude", "TinyCap" );
var slnName = sPlugins[0];
var sPluginName = slnName + "Plugin";
 
Build( slnName, sPluginName, false );
Package( sPluginName );
 
// build the solution. doRebuild is a boolean, forces a complete compile and build if true.
//
function Build( slnName, sPluginName, doRebuild ) {
	var oPlugin = Application.Plugins( sPluginName );
	var sPluginFileName = oPlugin.FileName;
 
	if ( !oPlugin ) {
		logmessage( "Can't find plugin to unload: " + sPluginName, siError );
		return;
	}
 
	Logmessage( "Unloading Plugin " + sPluginFileName );	
	Application.UnloadPlugin( sPluginFileName );
 
	var Cmd = BuildCmdRoot( slnName );
	var sConfig = GetConfig();
 
	var sOpt = (doRebuild) ? " /rebuild " : " /build ";
 
	if ( sConfig ) {
		system( Cmd + sOpt + sConfig + " & pause" );
	} else {
		Logmessage( "Build Failed", siError );
	}
 
	LogMessage( "ReLoading Plugin: " + sPluginFileName );
	Application.LoadPlugin( sPluginFileName );
 
} 
// get the platform type, 32 or 64 bit. Release is hard coded
//
function GetConfig() {
	var sPlatform = Application.Platform;
	Logmessage( sPlatform );
 
	if ( sPlatform.match( /win64/i ) ) return "\"Release x64|x64\"";
	if ( sPlatform.match( /win32/i ) ) return "\"Release|Win32\"";
 
	Logmessage( "Unsupported Platform: " + sPlatform, siError );
	return false;
}
 
// build the devenv.ex command line
// NOTE: this is set to work on a 64 bit system. Take out the (x86) and spaces 
// for 32 bit. Cross compile works well enough but you'll need the 64 bit libs
function BuildCmdRoot( sTargetName ) {
	var slnRoot = "c:\\fatty\\DEV\\CPP";
 
	var vcVars = "call \"C:\\Program Files (x86)\\Microsoft Visual Studio 8\\VC\\vcvarsall.bat\" x86";
 
	var slnPath = slnRoot + "\\" + sTargetName + "\\" + sTargetName + ".sln"
	var Cmd = vcVars + " & devenv " + slnPath;
	return Cmd;
}
 
// Package.
// ToDo: rebuild for package location.
//
function Package( sPluginName ) {
	logmessage( "Packaging ... " );
 
	var sOutputPath = "C:/Fatty/Dev/CPP/Release"
 
	var sPlatform = Application.Platform;
 
	var oPlugin = Application.Plugins( sPluginName );
	var sPluginFileName = oPlugin.FileName;
 
	var oAddOn = Application.CreateAddon();
 
	oAddOn.AddItem( siPluginAddonItemType, oPlugin.FileName );
 
	oAddOn.DefaultInstallationPath = siUserAddonPath;
	oAddOn.SubDirectory = sPluginName;
 
	var sPluginFileName = sOutputPath + "/" + sPluginName + "_" + sPlatform + ".xsiaddon"
 
	oAddOn.Save( sPluginFileName );
 
	logmessage( "Packaged to: " + sPluginFileName  );
}

4 Responses to “Slickening up the build cycle for compiled plugins”

  1. Graham Clark says:

    Great Kim, looks very useful, I’ll give it a go, I was about to try to automate this with my c# plugins, but try to do it from .net and drive XSIs unload and reload

  2. Reinhard Claus says:

    This will be useful, thanks for posting it. Related, but only useful for minor code changes, I find VS’s edit and continue feature quite neat. It lets you, after running into a breakpoint, or pausing the execution manually (pause button), go into the code and make changes. Before the execution is resumed (play button), VS will automatically recompile the code and replace the dll in memory without the need to unload/reload.

    required changes to project settings-
    1. linker settings>incremental linking : active
    2. c/c++ settings>dbg info format : program database for edit and continue
    3. c/c++ settings>code generation>function level linking : active

    This is nice for code tweaks. For larger changes I’d go with Kim’s method since I’ve had some issues with missing error output while recompiling. Also sometimes I get a “changes are too big” error :)

  3. Aiden Weatherby says:

    This is the exact reason I use eclipse to compile all my c++ stuff.

    I’m actually still compiling with the visual studio command line builder but it’s all controlled through a make file.

    So basically the make file does the unload which runs xsibatch to unload the plugin and clear all dlls then the plugin is compiled and dlls copied to workgroup xsibatch to load in the plugin and wahlaa all finished. :)

  4. Eric Cosky says:

    I have Visual Studio’s output file for the shader DLL set to the same place XSI would copy it to after installation of the SPDL, and the debugger settings configured to run XSI.exe as the app to debug. With this setup, I can make any changes I want to the plug in without ever having to re-install it – just press F5 to build & try out my latest changes. This has been good for iterating, especially when combined with edit-and-continue.

    That being said, nice tutorial and thanks for putting it up. I learned some stuff from it even if it solves the original problem differently than I do :)