SCons, MSVS Projects and build targets.

Current Repository Revision: 11

The next stage in our development process was to see how we could create Microsoft Visual Studio projects using SCons. We already had some code in our example code to build a project for each directory by calling:

scons -Q msvs=true

There is an error in this code, however. If you try and build Visual Studio projects with the code at revision 10, you will end up with some files in the build directories named, for example, foobar.vcproj that only contain the text:

This is just a placeholder file.
The real project file is here:
C:\mycpp\mi_test_scons\src\foobar\foobar.vcproj

or something similar. This is because when using SCons with BuildDir(), the src directory still gets the real Visual Studio project, while the build directory just gets the place holder. However, our example code assumes that the project file in the build directory is a duplicate of the one in the src directory, and deletes the one in src (because we like to keep the source tree as clean as possible, and the project files are generated files, so we feel they should be in the build directory). The first task, therefore, was to fix this.

Creating the real project file in the build directory

We can change the code to delete the dummy project file and move the project file from src to build as a post-build action. The original code for the MI_BuildMSVSProject function in the mi_scons.py file (as revision at 10) ended with the code to delete the project file from the source:

# This causes a project to be built in both the build and
# source directories. so we need to delete the one in source
srcfile = env['currsdir']+env['pathsep']+str(outmsvs[0])
env.AddPostAction(outmsvs,Defaults.Delete(srcfile))

So we can easily change this to delete the build dummy file, and move the source one to the build directory:

# This causes a project to be built in the source directory,
# and a place holder project to be built in the build directory.
# We want the project in the build directory, so delete the one
# there already, and move the source directory project into the build
srcfile = env['currsdir']+env['pathsep']+str(outmsvs[0])
bldfile = env['currbdir']+env['pathsep']+str(outmsvs[0])
env.AddPostAction(outmsvs,Defaults.Delete(bldfile))
env.AddPostAction(outmsvs,Defaults.Move(bldfile,srcfile))

Specifying build targets

After changing the code as specified above, and running SCons with msvs=true to create the Visual Studio projects, one was loaded into Visual Studio (foobar.vcproj) and a build was attempted.

The first thing to note was that, when loading into Microsoft Visual Studio Express 2008, the project needed converting (even though SCons had been run with Visual Studio 2008). The conversion simply changed the VisualStudioProject element by changing the Version attribute from “8.00″ to “9.00″ and removing the attributes SccProjectName, SccLocalPath and TargetFrameworkVersion. Apart from removing some newlines and the SCons Data comment from the end, there were no other changes.

Once the project was loaded a build was attempted. This resulted in the error:

scons: *** Do not know how to make target `obj'.  Stop.

The obj bit of that error is the value that was specified as the buildtarget when calling the SCons Builder MSVSProject. According to the SCons manual:

buildtarget: An optional string, node, or list of strings or nodes (one per build variant), to tell the Visual Studio debugger what output target to use in what build variant. The number of buildtarget entries must match the number of variant entries.

As it stated  that the buildtarget string is optional, it was removed from the my_scons.py MI_BuildMSVSProject function, and SCons rerun to create the new projects. The foobar.vcproj file was reloaded into Visual Studio, and a build was again attempted. This made matters worse, with the errors:

IndexError: string index out of range:
File
  "C:\Python26\Lib\site-packages\scons-1.2.0\SCons\Script\Main.py",
  line 1264:
    _exec_main(parser, values)
File
  "C:\Python26\Lib\site-packages\scons-1.2.0\SCons\Script\Main.py",
  line 1229:
    _main(parser)
File
  "C:\Python26\Lib\site-packages\scons-1.2.0\SCons\Script\Main.py",
  line 868:
    if a[0] == '-':

These errors stem from the fact that the build target was now an empty string (it gives the same result if you specify buildtarget = “” to the MSVSProject Builder). The problem occurs because SCons creates the BuildCommandLine attribute in the project and appends the contents of buildtarget to the end of that command line as the target for SCons to build (it does the same for the ReBuildCommandLine and CleanCommandLine attributes). To avoid any problems with the command lines, SCons encloses the targets in quotes (actually, " as the vjproj file is XML). This is like calling SCons at the command line with:

scons -Q ""

If you do this you’ll find it gives the same error as Visual Studio.

This means that for each Visual Studio project the correct build target has to be specified. There are a few things to note about build targets:

  • In Windows, the ‘.exe’ extension is required on the end of an executable target, even if you specify the target name, e.g. Program(‘howdy’,'hello.c’) still requires: scons -Q howdy.exe
  • If the target is in a subdirectory, you must specify that subdirectory in the target name. This makes sense as two subdirectories could contain files (and, therefore, targets) with the same name. For example, a program named goodbye in the subdirectory test2 would require scons -Q test2\goodbye.exe to build on Windows (and scons -Q test2/goodbye for Linux).
  • If you are using BuildDir() to specify a build directory, then it is that directory which should be specified in the target name. In the mi_test_scons code, for example, to build bar.obj (under Windows – Linux would use bar.o) using scons -Q src\foobar\bar\bar.obj will fail, while scons -Q build\release\foobar\bar\bar.obj should succeed.
  • When specifying a build directory for the target any error messages about not knowing how to build targets will give the source directory.

With these things in mind we can go on to write the code necessary to correctly create Visual Studio Projects from our SCons build. The projects will be built for each library and executable, but not for every object file (as happens at present). This will be the subject of the next post.

The code changes given in this post (to create actual vcproj files in the build directory instead of just placeholders) is now committed as revision 11 in the example code.

Leave a Reply

You must be logged in to post a comment.