I was really daunted with the prospect of re-building my Linux box, and worse, having to build ModWars on it, especially since I had three separate projects and several source files contributing to my glorious green square!
I started simply by building my common library which was only a couple of files and didn't depend on anything. That was fine. My client library complained about a missing SDL.h file but luckily SDL has been installed along with Fedora so all I had to do there was find it and then point the compiler to that directory.
The tricky part was installing the actual client app which relies on wxWidgets. I had not built a wxWidgets app on my virtual PC so this was new ground. It didn't build of course - it complained about the wx header file. I searched the packages and couldn't find one for it so I downloaded it. Now how to build wxWidgets on linux? I looked through the files that began with "install" but couldn't see anything obvious but gtk seemed familiar so I tried typing in the instructions in there. It complained about the development files for GTK+ being missing *sigh*.
So, I thought I'd check the package manager for it and searched for GTK. I was confused to find wxGTK in there already installed even though I had searched the entire machine for the header file I needed. I found the gtk development files so proceeded to install that but I was really confused now - what is GTK anyway and if wxGTK is installed then why can't I find the header file?
Once I downloaded and installed the GTK files two things changed. Firstly, I found an installation of wxWidgets. That struck me as odd because according to my package manager it was already there. Unfortunately it was version 2.6 but I figured that would do for now. In there was the header file I needed. But I also found that the configure program for the 2.8 version of wxWidgets which I downloaded now worked so I thought I'd try building it anyway. That took a while...
I'll give the install file credit - the step-by-step instructions worked without a hitch once the GTK files were present so I now had a wxWidgets 2.8 installation installed. So I added the include file to my directory list in Code::Blocks and tried again. This time the setup.h file wasn't found. I remember having issues with this before, I really should blog my problems and solutions to those problems more thoroughly!
After searching wxWiki I found an article about the setup.h file and how the build process generates it for you. So I did a search and sure enough I found one lurking in the build folder I'd just built. I copied it to the correct location and re-built. It got further this time but hit a #error message of "No target! You should use the wx-config program for compilation flags!"
In all the examples for compiling wxWidgets they show a command line version using g++ and part of the command line is "wx-config --cxxflags" and "wx-config --libs". I had no idea what these did and no idea how to reproduce the same effect in Code::Blocks.
I took another approach and tried creating a wxWidgets project using the wizard. That worked so I then deleted the source files and added my own. This time it got past the weird errors and whined about my application class saying "expected class name".
Some further searching on the forums finally revealed the correct way to use the wx-config options. Under build options for the project, I had to select the Compiler | Other Options and type in 'wx-config --cxxflags' and under the Linker tab in the "Other linker options" type in "wx-config --libs". Performing these two steps got me to the same place as I had in my test project with the same compilation errors.
I then managed to find a tutorial video showing how to build a wxWidgets application in Code::Blocks and found that the wizard I had used was nothing like the one used in this video. Some further searching revealed that I was using an old version. Could that be the problem I wondered? In Fedora there is an automatic package update utility so I clicked on that and it found an update to Code::Blocks (along with a squillion other things) so I let that do it's thing.
A very long time later Fedora finished updating, rebooted and sure enough I had a new version of Code::Blocks with a new wxWidgets wizard. It still wasn't the latest version though so I registered on the CB forums so I could download the latest one. Now I just had to install the linux version of 7zip so I could extract it, and then figure out what to do with it.
Once I did this it seemed to take me a step backwards. The default project would no longer build, complaining once again about wx-config. Worse still, I had now lost my option to enter in linker options and it was complaining about that also.I figured I had screwed things up and at this point I could see no option but to re-install CB from scratch.
This got me back to where I was before I watched the video. I could build the sample app, but not Mod Wars. However, i managed to find the linker options and fixed the wxconfig --libs line and I was also able to figure out how to link in my mw-common, mw_client_lib and the SDL libraries so this reduced the errors down a bit. Now all I had left were an undefined reference to main, and missing vtables for the other wx classes. I'm assuming the remaining issues are down to code and not project settings. Unfortunately I've run out of time so I'll have to leave this issue until another day.
Saturday, February 24, 2007
Monday, February 12, 2007
Update on Inlines
Last night I discovered that it was inline functions that caused my linking problems though at the time I wasn't sure why. I've googled around a bit and now the cause has come clear. The process of inlining is usually done at compile time (not link time) and for the compiler to be able to inline the function it must be able to see its internal definition. In my code I just so happened to place these inline functions in the .cpp files. Had I placed them in the header file, it probably would have been fine. However, the reason I put them in the cpp file in the first place is that I specifically wanted to avoid any implementation code, no matter how minor, in the header file. So I'll leave it as it is, I'm sure the compiler will do a fine optimization job anyway.
Sunday, February 11, 2007
Inline Functions in Static Libraries
In a word - don't do it! Following my green block code, I wanted to render the grid and I figured I could do this in about ten minutes - ha! I put a couple of simple classes including a grid class in a library as this will be used by the server as well. The code compiled but would not link; I got the dreaded unresolved external.
I've had these before many times and I can usually fix them fairly quickly. Its usually a project setting in my case. I checked and rechecked all the project settings, I compared this project against Morde which used a similar setup but all to no avail. I wont bore you with the diagnostics. Suffice to say I eventually traced the problem down to the use of inline functions in the library.
I'm not entirely sure why you cant use inlines, and I'll read up on that to find out but the silly thing is that I never use inlines. I even read an article by Scott Meyers recently about why its generally a bad idea to use them so what on earth posessed me to start today? Well lesson learned I guess!
The grid doesn't render properly but I can fix that another day.
As a side note... usually I would have left this problem to another day. I was actually in the middle of watching a movie when it cropped up and I thought I could literally write this bit of code in 10 minutes. Usually if I hit a problem late in the evening I leave it and come back to it after some sleep but today something nagged me and I told myself that I simply had to fix it now otherwise it would hang over me. Sometimes you have to know when to call it a day. Other times you have to know when to just plough through a problem until it is resolved.
I've had these before many times and I can usually fix them fairly quickly. Its usually a project setting in my case. I checked and rechecked all the project settings, I compared this project against Morde which used a similar setup but all to no avail. I wont bore you with the diagnostics. Suffice to say I eventually traced the problem down to the use of inline functions in the library.
I'm not entirely sure why you cant use inlines, and I'll read up on that to find out but the silly thing is that I never use inlines. I even read an article by Scott Meyers recently about why its generally a bad idea to use them so what on earth posessed me to start today? Well lesson learned I guess!
The grid doesn't render properly but I can fix that another day.
As a side note... usually I would have left this problem to another day. I was actually in the middle of watching a movie when it cropped up and I thought I could literally write this bit of code in 10 minutes. Usually if I hit a problem late in the evening I leave it and come back to it after some sleep but today something nagged me and I told myself that I simply had to fix it now otherwise it would hang over me. Sometimes you have to know when to call it a day. Other times you have to know when to just plough through a problem until it is resolved.
Whoohoo We Have an Executeable!
Last time I managed to get a tutorial program running that nicely integrated SDL with wxWidgets. This weekend I started on the real dummy code for Mod Wars! What I mean by "real dummy" is that I know that anything I write at this stage will get rewritten or completely trashed at some point, but I'm at a stage where I want to start structuring my projects, thinking about naming conventions and that sort of thing.
So I started off by re-writing the tutorial program as if the output was what is desired for Mod Wars. One thing I did differently this time around is change my usual naming convention. Usually all my C++ code follows the Boost naming conventions of all underscore_separated lowercase_identifiers. However, wxWidgets doesn't use that kind of naming and my code just looked odd. So instead, for any code that works directly with wxWidgets including the classes I had to derive from those in their framework, I followed their naming conventions.
Furthermore, I had already decided to split out my client code into two parts - a generic library that wasn't specific to any particular Gui, and a Gui only portion that is. The reason for this is that (gosh did I already blog about this? I feel like I'm repeating myself! anyway...) I know that I want at least two front ends for the client - the real one with my Gui library of choice which is currently wxWidgets, and a console based front-end for running unit tests and hopefully for running scrips so that I can automate execution of the client code. The second reason is that Gui libraries are a pain in the a**! I tried at least half a dozen when looking for one for Mod Wars so if I tie myself into just one, I'm sure Murphy would see to it that I change it along the way.
Back to naming conventions then... in my library code I use my internal conventions and in Gui code I'll follow the conventions of the library I am using.
Wanna see the finished product? Here's a glorious screenshot for you!

What the **** is this you are probably thinking! Many moons ago when I first decided that I wanted to write games, I started to teach myself DirectX. I had no idea where to start and I found it very difficult. I was trying to recreate a block puzzle game that I had written in MFC years earlier. The screen was supposed to be filled with little coloured blocks and instead, after days of faffing around, all I managed to produce was a solitary green block in a very odd place! So now, whenever I start writing a game that needs any kind of graphics the first thing I do is just render a green block! It also fits nicely into the "do the simplest thing that could possibly work" mantra :-)
I'll render a grid next, honest!
So I started off by re-writing the tutorial program as if the output was what is desired for Mod Wars. One thing I did differently this time around is change my usual naming convention. Usually all my C++ code follows the Boost naming conventions of all underscore_separated lowercase_identifiers. However, wxWidgets doesn't use that kind of naming and my code just looked odd. So instead, for any code that works directly with wxWidgets including the classes I had to derive from those in their framework, I followed their naming conventions.
Furthermore, I had already decided to split out my client code into two parts - a generic library that wasn't specific to any particular Gui, and a Gui only portion that is. The reason for this is that (gosh did I already blog about this? I feel like I'm repeating myself! anyway...) I know that I want at least two front ends for the client - the real one with my Gui library of choice which is currently wxWidgets, and a console based front-end for running unit tests and hopefully for running scrips so that I can automate execution of the client code. The second reason is that Gui libraries are a pain in the a**! I tried at least half a dozen when looking for one for Mod Wars so if I tie myself into just one, I'm sure Murphy would see to it that I change it along the way.
Back to naming conventions then... in my library code I use my internal conventions and in Gui code I'll follow the conventions of the library I am using.
Wanna see the finished product? Here's a glorious screenshot for you!
What the **** is this you are probably thinking! Many moons ago when I first decided that I wanted to write games, I started to teach myself DirectX. I had no idea where to start and I found it very difficult. I was trying to recreate a block puzzle game that I had written in MFC years earlier. The screen was supposed to be filled with little coloured blocks and instead, after days of faffing around, all I managed to produce was a solitary green block in a very odd place! So now, whenever I start writing a game that needs any kind of graphics the first thing I do is just render a green block! It also fits nicely into the "do the simplest thing that could possibly work" mantra :-)
I'll render a grid next, honest!
Subscribe to:
Posts (Atom)
