Why Pre or Post-Build?
I’m trying to create my first shareware program in my free time. Using Delphi on my laptop for company work, it was the logical choice to make this project. With that comes adding some security measures and so I chose Armadillo (now SoftwarePassport). The way this protection works is by wrapping the program’s exe or dll which means it has to be done after building the main program. This protective wrapper needs to be in place even for development work, be that to test settings related to the protection itself or simply to avoid a large number of conditional defines to block code out.
For the last few days I’ve been trying to automate the process which involves running a windows application with certain parameters. Because there is not much information on how to successfully accomplish this, I decided to write this article to share the workaround that I found to be very good, at least until Delphi gains a more customizable builder.
The solution
The whole idea works around 2 concepts applied together: using Build Tools and Project Groups.
I’ll describe the process for the Post-Build situation in my particular case, but, by playing around with the build order, this can easily be adapted to Pre-Build too and you can even have several Pre and Post-Build tools being executed.
Step-by-step instructions
Let’s start by opening your project.
Now, right-click on the Project Group and select "Add New Project…".
Any type of project will do, I selected a console application and named it PostBuild, but again, any name will do. You can keep your project the Active one.
Save all that and choose a proper name for the .bdsgroup file.
Now right-click on the PostBuild project in the project explorer and select "Dependencies…": this is one of the most important steps because in here you can say that this project (PostBuild) depends on another one (your main project), so that it will always be built after your main one.
Now for the tool configuration.
In my particular case, I need to run the following command line:
"C:\Program Files\SoftwarePassport\Armadillo.exe" "D:\Dev\My Prog\Prot.arm" /P
So, let’s do 2 things here: add the Prot.arm file to the Post-Build project and create a Build Tool to handle .arm files.
The Build Tools dialog, or more specifically, the "Add…" sub-dialog, could use a bit more explanation in the help file but eventually I got it working as you might have guessed or I would not be writing this article!
The key points in this dialog are:
Title: Anything will do but using a descriptive title always helps
Default Extensions: *.arm (this is for my case for the example command-line above)
Command Line: This is the trickiest of them all, but after you get one working, they’re all easy. The trick here is not to use quotes on the program’s name but instead use the windows SFN (Short File Name). The reason is that, should you need to use quotes to enclose the path of your file, the IDE gets confused with too many quotes.
So, these are the wrong ways of adding that command line above:
C:\Program Files\SoftwarePassport\Armadillo.exe D:\Dev\My Prog\Prot.arm /P
"C:\Program Files\SoftwarePassport\Armadillo.exe" D:\Dev\My Prog\Prot.arm /P
C:\Program Files\SoftwarePassport\Armadillo.exe "D:\Dev\My Prog\Prot.arm" /P
"C:\Program Files\SoftwarePassport\Armadillo.exe" "D:\Dev\My Prog\Prot.arm" /P
This last one should work, if it were not for the IDE to be confused with it. So, what does work is this one:
C:\Progra~1\SoftwarePassport\Armadillo.exe "D:\Dev\My Prog\Prot.arm" /P
Notice the SFN on the program to be executed, thus leaving the quotes available for use on the file name. Of course, we don’t want this exactly as it is as it would be hard coded. We can use some Macros to make it more generic, so here are the Add Build Tool contents for my case:
Title: ArmProtect
Default Extensions: *.arm
Command Line: C:\Progra~1\SoftwarePassport\Armadillo.exe "$PATH$NAME" /P
Using these Macros is also the reason why I used SFN on the program and not on the filename! In this case, "$PATH$NAME" gets expanded to "D:\Dev\My Prog\Prot.arm".
Don't forget that this tool will only be used on the extensions indicated in this dialog.
You can also, at any point in time, manually run this command by right-clicking any *.arm file on your project and selecting the tool from the menu.
The final step to remember is to Build All Projects (you can give it a keyboard shortcut to make it easier to use and/or put it on your toolbar).
In short:1 - Add a PostBuild "void" project to your project group;
2 - Right click that project, select Dependencies and make it depend on your main project;
3 - Add the file you want to be processed after building your program to the PostBuild project;
4 - Create a Build Tool to run the proper command-line and associate it with that file’s extension (don't forget about using SFN for the program name);
5 - Always load the .bdsgroup instead of the .bdsproj and use Project -> Build All Projects whenever you want the Pre/Post-Build to work.
Final Notes
This process was tested with BDS 2006 and should probably work with BDS 2005 too but I haven’t tested in that IDE.
You may need to exit and re-open the IDE for it to acknowledge changes to Build Tools, especially when you just added a new one.
Adding a Pre-Build is also easy to achieve playing with the project’s dependencies: you will need to make your main project dependent on the PreBuild one.
If you need to add some step that does not depend on any type of file, simply make up some extension (use 4 or more characters to avoid conflicts with existing extensions) and create a void file of that extension to associate with the Build Tool, for instance, "nothing.step1".
If you want to customize the Build Current Project key to perform Build All Projects instead, take a look at the free GExperts Add-In.
I hope that this information is as valuable to those reading this as it is for me. I've yet to try out the new MSBUILD, so until then, this workaround works like a charm.
1 comment:
Of course you can always add cmd.exe as a build tool and execute .cmd files....
Post a Comment