As I mentioned previously I'm multitasking between three clients at the moment, two of whose projects are based primarily around C++. It's interesting seeing the differences between all the languages, programming styles, and tools, involved. For a consultant - horrid word - it's a refreshing and enlightening experience.
However, it can also be an extremely frustrating one when the tools employed let you down. Today's work involves porting a GCC/Lex/Yacc codebase to Visual C++ 9 (aka Visual Studio 2008). And VC++ decided to bite me.
In hindsight, the situation seems straightforward in the extreme. Unfortunately, such straightforwardness is seldom apparent a priori, particularly so when one is on a tight deadline. (Since, if they have the luxury of time, clients usually work on the problems themselves, so I tend to be on a tight deadline most of the time.)
Anyway, having ported all of the extant C/C++ code in the project to a mutually-acceptible dialect that can be consumed by both GCC and VC++, I was left with the Lex/Yacc source. So, I russled up the Visual Studio Custom Build step, using the bison and flex tools provided by the GnuWin32 project. (This is the first time using these tools, and I have no complaints thus far.) All goes well, and the project is happily generating .cc/.hh files.
Completing this step requires only that I add the .cc files into the project. Since Visual Studio recognises .cc as a C++ extension, there should be nothing left to do. Unfortunately this is where things go to pot. I hit F7 (mice are too slow) and all things seemed to go well:
- all .c files compiled successfully (no warnings or errors).
- all .cpp files compiled successfully (no warnings or errors).
- all .y files yacc'd successfully. (Or is that bison'd successfully.)
- all .lex files (f)lex'd successfully
- each .cc files (generated via bison) caused the compiler to emit error C2471
For those unfamiliar with this error, here's the full text of the MSDN help page:
The compiler cannot write to the database file.
- Insufficient disk space.
- Volume is read-only.
- Sharing violation.
Obviously it's not the second issue. Checking the drive indicated that I had 3.5 GB free. So that leaves the sharing violation. Maybe.
My next thought was to ponder whether the IDE was being a little too helpful, in perhaps compiling the .cc file (generated, I conjectured, by a previous build attempt) at the same time as bison (via the custom build step described above) was trying to write to the source file. For sure, this doesn't help explain why the IDE was reporting that the program database file (vc90.pdb, fwiw), rather than the .cc file, was affected, but I figured it worth a stab.
Had I forgot to specify the requisite .cc file as an output for each .y file? Apparently not.
The specification of output file(s) for a custom build step enables the IDE to ensure that actions are carried out in the correct order. It being correct, I did a quick sanity check:
- edit a .y file
- compile the requisite .cc file
- see whether the .y file is "yacc'd" prior to the .cc being compiled
(As I'm happy to admit, on Windows I still reach for Visual Studio '98 for editing C and C++ source. I use Visual Studio 2005/8/10 for C++ only every other day or so, and don't feel like a master of my domain, so a double check is worthwhile.)
The check seemed worthwhile indeed, as the .y file was not "yacc'd". The dependencies work when I rebuild all, but not on a per (.cc)-file basis. Eureka!, I thought. Except that did not leave me with a solution. A web search for 'C2471 +"custom build"' yielded nothing. Eep. Panic ... starting ... to ... take ... hold.
At this point, given my time pressures, I "phoned a friend", my esteemed chum and occasional colleague, Garth Lancaster. Apart from a few unprintable things about software product "evolution", all Garth could advise was to "break up the project".
"But," I countered, "I've heaps of room, vc90.pdb is only 2MB and, besides, the dependencies between the .y and .cc file don't seem to work, so how is breaking up the project going to help, unless I want to organise .y/.cc dependencies at a project-file level. Which is highly yuck!"
"Look", I continued (despite the fact that Garth was at the end of a phone line 25km away), "if I edit another, say .cpp, file and then build, that works fine, and only the .cc compilations yield C2471."
With this, I inserted a space into a .cpp, pressed F7, and ...
... got a C2471!
Curses on my end. Sympathetic chuckles on the other end. A quick disabling of around 10 .c/.cpp files from the project. F7. All source files - c., .cpp, .lex, .y, .cc - all compile normally, save for several warnings (treated as errors, of course), regarding the arcane C generated in the .cc files; dealing with that's another story.
So, Visual Studio 2008 / Visual C++ 9 seems to have a strange intolerance for my project's complexity, though at 59 .c/cpp files, 8 .lex, 8 .y and 16 .cc files it hardly feels like I gave it a lot to cope with. That it led me up the garden path with the seemingly invalid warning and strange dependency behaviour was irksome; as Andy Keonig has recently pointed out, defects in tools can have disproportionately large effect. Hopefully by including the warning number in the title for this blog, anyone having similar issues stands a decent chance of coming across this blog, and Garth's advice: Break up your project(s)!
For this project, I'll be breaking up the project according to logical subdivisions, and not having to separate the .y and .cc processing.