Saturday, August 9, 2014

CMake Problems Windows 8.1 – Part 2

The second problem was with the paths to the test files generated in the make file.  When CMake generates a custom command for making the test directory and copying a test file, it uses the Unix style path forward slash separator regardless of the generator being used.  While cmd.exe on Windows does support these style paths, the md and copy commands do not (in fact the forward slash indicates an option like the minus does for Linux and MSYS commands).  This obviously causes problems with the custom commands.

In CMake, the file command supports a TO_NATIVE_PATH option, but when used, this command didn't work as expected (didn't do anything).  Apparently this is a known issue and according to what I read, this is not the purpose of this command anyway.  So instead, a ConvertPath function was added to the CMake build file, which if the MinGW generator is being used, changes forward slashes to back slashes and surrounds that path with double quotes to deal with paths that may have spaces in them (which doesn't occur with the MinGW generator like with the MSYS generator).  For any other generator, the path is not changed.

Another build problem was found with the awk program required for building.  When using MSYS with MinGW, MSYS included many of the Unix utilities including the awk program.  Fortunately, Git for Windows includes many of the MSYS utilities.  However, the gawk program is included instead (stands for GNU awk).  Also included is an awk script, but this shell script is meant to be run by the sh.exe command that is part of MSYS, which just calls gawk.  When run from cmd.exe the script doesn't work.

When looking for the awk program, CMake found this awk script and so an error occurred from the make command running under cmd.exe.  To make CMake find gawk.exe instead of this script, the CMake build file was modified to look for gawk first, and if this is not found, then looks for awk.  In fact, on Linux, awk is also called gawk, but there is an awk file that soft links to it, so that either can be used.

While testing a minor mismatch was found with encoder test #2 with recreator testing.  The issue was that lines with error now store the text of the line, which is recreated.  This change was made in the last commit but the expect results were not updated.

[commit 727f7d223f]

Build Problems on Windows 8.1 – Part 1

Several problems were discovered when attempting to build and run on Windows 8.1 using Qt Creator.  The first problem that occurred was with the copying of the test files from the source directory to the build (binary) directory.  This is accomplished by creating custom commands for each test file.  These custom commands generate a mkdir -p command to make the test directory if not already there and the cp command to copy the file.  Both of these commands are available on Linux and with MSYS on Windows.

When building on the command line on Windows using MSYS to create the make file or using the CMake GUI to generator the make file, the "MSYS Makefiles" generator is used.  This creates the make file assuming that the make command will be run using a Unix shell (specifically bash or the Bourne Again SHell).

On Windows when running CMake from Qt Creator, it uses the "MinGW Makefiles" generator to generator the make file.  This generator assumes that the make command is going to be run using cmd.exe, the Windows command prompt program, which Qt Creator uses cmd.exe to run the make command.  The make command uses the program under which it is run to execute commands in the make file like for custom commands.

The CMake build file needed to be modified to detect when the MinGW generator was being used and use the appropriate make directory and copy commands for cmd.exe.  Fortunately, the CMake CMAKE_GENERATOR variable is set to the generator is being used.  So, if the generator is MinGW Makefiles, the md and copy commands are used, otherwise the mkdir -p and cp and used.

Another problem with the md command is that if the directory already exists, the command returns an error and the make command aborts.  With Linux/MSYS, the -p option solves this problem.  With cmd.exe, the md command has no similar option.  The only solution that worked was using an if not exist command (so the md command is only performed when the test directory doesn't exist):
if not exist test-directory md test-directory
When the generator is not MinGW, CMake adds double quotes about each component of an individual command in the custom command if the component has a space in it, because otherwise the shell parse a path with a space incorrectly as two arguments and not one.  For this reason, the command variable could not be set to mkdir -p because it would create the command "mkdir -p" and this is not a valid command.  Therefore, the mkdir and -p had to be put into two separate variables.  This does not occur with the MinGW generator.

Installing QtCreator on Windows 8.1

Downloading Qt Creator was described a few posts ago.  The latest version of Qt Creator at the time is 3.1.2.  Open the qt‑creator‑opensource‑windows‑x86‑3.1.2.exe download file and click through, accepting the recommended Installation Folder, the license, and Start Menu shortcuts.  Accept the User Access Control if asked.  At the end go ahead and Launch Qt Creator as some post install configuration is needed.

Qt Creator should be able to find the various utilities and Qt 4.8.6 since these are on the path, but it does not appear to actually look for some of these, so these need to be configured manually.  In Qt Creator selected Tools and Options...  Click the Build & Run page.

On the Qt Versions tab, if Qt 4.8.6 was not auto-detected, it needs to be set manually.  Click the Add button and browse to the C:\Qt\4.8.6\bin directory and select the qmake.exe (just qmake if extensions are not displayed).  Click the Apply button.

On the Compilers tab, if MinGW was not auto-detected, it needs to be set manually.   as MinGW (x86 32bit in C:\mingw32\bin).  Click the Add button and select MinGW (from the drop down menu).  On the Compiler path field, click the Browse button and navigate to the C:\mingw32\bin directory and select g++.  Click the Apply button.

On the Debuggers tab, it GDB was not auto-detected, it needs to be set manually.  Click the Add and replace the default New Debugger name with something like GDB 7.7 (which is the version installed with MinGW).  Click the Browse... button and browse to This PC, Local Disk (C:) (or whatever it may be called), mingw32, bin, gdb and click the Open button.  Click the Apply button.

On the CMake tab, click the Browse... button and navigate to This PC, Local Disk (C:), Program Files (x86), Cmake 2.8, bin, cmake and click the Open button.  Click the Apply button.

Finally on the Kits tab, select the Desktop (default) under manual, which is italicized with a yellow triangle warning indicating it is not configured properly.  Under the Debugger field, select GDB 7.7 on the drop down (only debugger listed).  The warning should go away since the Compiler and Qt Version fields are already set.  Click the OK button.

The configuration can be testing by compiling one of the Examples.  On the Welcome page (icon on upper-left), select Examples.  I selected the first example: 2D Painting Example.  On the Configure Project page that appears next, click the Configure Project button.  Test building by clicking the Hammer icon (lower-left or type Ctrl+B).  After a few moments it should finish.  Click the Run/Play icon (or type Ctrl+R) to run the program.  It should present two rotating patterns.  Qt and Qt Creator have been successfully installed.

Installing Git on Windows 8.1

Finally, to obtain this project from this project's Git repository on GitHub, the Git utility is required.  The latest Git for Windows can be obtained from their home page (which has changed since I previously described how to install Git).  Click the Download button to download the latest version.

Open the download file (Git‑1.9.4‑preview20140611) and accept the User Control Access if asked.  Click through and accept the license.  On the Select Components dialog, select additional icons if desired and click through accepting the defaults.  It's not necessary to view the release notes, so disable and click Finish.

The paths to these programs along with Qt needs to be added to Windows.  From Windows Explorer, select This PC, right-click and select Properties, Advanced system settings, and on the Advanced tab, click Environment Variables...  Under System variables, scroll down to Path and add:
;C:\mingw32\bin;C:\Qt\4.8.6\bin;C:\Program Files (x86)\Git\bin
Select Path, click Edit..., add the string above to the end of Variable value, and click OK (the whole way out).  This will allow the utilities git, g++ (compiler), gdb (debugger) and qmake (how it is determined where Qt is installed) to be found on the command line or by a program that is started under Windows.  The path to the CMake directory should already have been added during CMake installation.

Installing CMake on Windows 8.1

Building project requires the CMake utility.  CMake can be obtained from the CMake download page.  For now I suggest installing the latest 2.8 version, which is 2.8.12.2.  There is a newer version (3.0.1 at this time), but Linux only has 2.8.7 (Linux Mint 13/Ubuntu 12.04) or 2.8.12.2 (with kubuntu backports or Linux Mint 17/Ubuntu 14.04).  This project only requires 2.8, so 2.8.12.2 for Windows is sufficient.

Open the cmake‑2.8.12.2‑win32‑x86.exe download file and accept the User Control Access if asked.  Click through and accept the license.  On the Install Options dialog, select the Add CMake to the system PATH for all users or current user as desired, and the Create CMake Desktop Icon if desired.   Continue clicking through and finally click Finish.

Installing Qt For MinGW on Windows 8.1

Download the latest Qt4 for Windows with MinGW at the Qt Project's download page.  Upon first opening this page, only the latest Qt5 version is shown (which at this time is 5.3.1).  To see more versions, click the Show Downloads button and scroll down to Qt 4.8 (4.8.6 at this moment).  Download the one for MinGW with GCC 4.8.2 (note that this download does not actually include MinGW).  While here, the latest version of Qt Creator can also be downloaded (3.1.2 at this moment).

For now, I plan to continue using Qt4 even though Qt5 has been out for a while.  I will describe installing the current latest Qt4.  The version present on Linux Mint 13 (Ubuntu 12.04) is 4.8.1 unless the kubuntu backports are being used to get the latest version of KDE, in which case 4.8.2 is present.  Linux Mint 17 (Ubuntu 14.04) has version 4.8.5.  These versions are sufficient so there is no need to install 4.8.6 for Linux.  (I don't know enough about Qt5, which is something that may be revisited some time in the future.)

Now Qt4 can be installed.  Open the qt-opensource-windows-x86-mingw482-4.8.6-1.exe download file and accept the User Account Control if asked.  Click though, accept license, continue clicking through, accept the default C:\Qt\4.8.6 installation location, and continue clicking through.  It will ask where the MinGW installation is located.  If MinGW was installed as previously described, the default C:\mingw32 can be accepted, so click Install.

At the end of the install process, the setup program will ask to Run Examples and Demos and Show Documentation.  This is not necessary, so disable these before clicking Finish.  These can be accessed by the Start Menu (Classic Shell) by Programs, Qt by Digia v4.8.6 (MinGW 4.8.2 OpenSource), Examples and Demos and Assistant.  From the Start Screen on Windows 8 I'm guessing the install throws all the programs on the Start Screen itself.  However, on Windows 8.1, click the Down Arrow (lower left where it says new apps installed), and scroll right to where the Qt by Digia v4.8.6 (MinGW 4.8.2 OpenS... programs are listed where Assistant and Examples and Demos will be.  These can be pinned to the Start Screen if desired (Pin to Start on right-click menu).

Installing MinGW on Windows 8.1

The procedure for installing MinGW (that came with GCC 4.6.2 at the time) was previously described.  Later once Qt was being utilized, the procedure for installing the QtSDK with MinGW (that came with the older GCC 4.4) was given, and then it was detailed how to connect the MinGW with GCC 4.6.2 to QtCreator since 4.4 was too old.

The Qt Project team no longer provides the QtSDK (that included the Qt library development files, MinGW and QtCreator).  Therefore, the Qt4 libraries and QtCreator now need to be installed separately.  The latest Qt4 (4.8.6) for MinGW does not actually come with MinGW, which needs to be install separately beforehand.  They suggest installing MinGW-w64 first (which includes GCC 4.8.2) and give a specific version to install.

MinGW-w64 can be downloaded from here.  This is revision 3 and there is now a revision 4 (they don't detail very well what was changed in revision 4), but I installed the recommended revision 3.  The download file is in 7-Zip format, which Windows 8.1 does not have native support for.   To install 7-Zip, go to the 7-Zip website and click the Download .msi (for 64-bit Windows 8 or Download .exe if using 32-bit Windows 8).  Once downloaded open the program.  (Don't install the 7z922.exe program, the default program on their SourceForge page, as it doesn't connect into Windows Explorer.)

MinGW can now be installed by extracting the i686-4.8.2-release-posix-dwarf-rt_v3-rev3.7z download file.  Right-click on this file, select 7-Zip, and Extract files...  Set the Extract to directory to C:\ and click OK.  This will install MinGW at C:\mingw32, which is the location Qt expects to find it.  Next post will describe installing Qt.

Wednesday, August 6, 2014

Upgrading MinGW on Windows

Upgrading GCC in MinGW to the latest version is easily accomplished.  Simply start the MSYS Shell and run the following commands (this worked on the MinGW installs on both Windows XP and 7):
mingw-get update
mingw-get upgrade
Use the command g++ --version to verify that GCC 4.8.1 has been installed.  Installing MinGW with the Qt libraries has been previously covered (see the Windows tagged posts).  However, it is probably be a good idea to update the procedure and repeat for Window 8 since only Windows XP and 7 were covered previously.  Plus, there are newer versions of Qt and MinGW.  Specifically I will provide the installation procedure for Windows 8.1 update 1, which I have running in a virtual machine.  All the tools necessary will be covered, including MinGW, Qt for MinGW, CMake and git in the following posts.

I obtained Windows 8 Pro via their $40 upgrade offer, otherwise I would not have bothered.  On my Windows 8.1 installation, I have Classic Shell installed.  This is not necessarily because I don't like the Modern (AKA Metro) UI, but it's just contrary works to the way I like to work.  In Classic Shell, I use the Classic start menu style as I don't like the Window 7 start menu style (I use the Classic Shell on Windows 7 for the same purpose).  Procedures for the classic start menu style and the start screen will be provided when appropriate.

Tuesday, August 5, 2014

Upgrading GCC on Linux Mint 13/Ubuntu 12.04

GCC on Linux Mint 13/Ubuntu 12.04 can be upgraded from the default GCC 4.6.3 by adding the tool chains repository.  Instructions can be found around the Internet, but I will briefly provide procedure that I used.  First, the python‑software‑properties package needs to be installed (it was already installed on my system):
sudo apt-get install python-software-properties
Now the tool chain repository can be added with these commands:
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
With this repository, the current GCC 4.6.3 can be upgraded to the most recent of the 4.6 series to 4.6.4.  However, the goal is to get a more recent version.  For this the g++-4.8 package needs to be installed:
sudo apt-get install g++-4.8
This should also bring the other required packages (gcc-4.8-base, gcc-4.8, cpp-4.8 and libstdc++-4.8-dev).  Once the 4.8 packages are installed, they need to be selected, otherwise the 4.6 commands will still be executed.  This is accomplished with the following commands:
sudo update-alternatives --remove-all gcc
sudo update-alternatives --remove-all g++
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50

For the first time, the first two commands are not needed.  I put these lines into a script file (named usegcc48), and created and second script identical to this except with the "4.8" changed to "4.6" to select the 4.6 commands (named usegcc46).  This way, it is easy to switch between the two versions (the execute bit needs to set on these scripts using the command chmod +x usegcc4*).

Monday, August 4, 2014

Project – C++11 Standard

Part of learning to use C++ more effectively should include the latest C++ standard, which at the moment is C++11.  Support for C++11 is being or has been implemented in compilers.  This project uses GCC (The GNU Compiler Collection), which is standard on Linux systems and can be installed on Windows systems (the MinGW program is the one recommended).  Sorry MAC OS-X users, I do not have access to MAC system to figure what is needed to build and run this project on OS-X even though OS-X is Linux like and shouldn't be much different than Linux.

Even though many of the recent GCC versions support various features of C++11 (which was previously known as C++0X before the standard was finalized) starting with GCC 4.3, all the C++11 features highlighted in the  The C++ Programming Language (Fourth Edition) by Bjarne Stroustrup require and more recent version of GCC, specifically GCC 4.8 or later.  Fortunately, this version is available both on Linux (the current Mint/Ubuntu LTS or Long-Term-Support versions) and MinGW (Windows).

The current version of GCC on Mint 13 LTS (Ubuntu 12.04 LTS) is only GCC 4.6.3.  Fortunately there is a way to update to GCC 4.8.1 by adding the tool chains repository.  On Mint 17 LTS (Ubuntu 14.04 LTS) GCC 4.8.2 is available.  The latest version installed with MinGW is also GCC 4.8.1.  However, since Qt is also required, it is easier to install Qt that includes MinGW, which happens to have GCC 4.8.2  GCC 4.8 should be sufficient for using the major C++11 features.  Details for upgrading and installing the necessary versions and tools will be provided in subsequent posts.

Sunday, August 3, 2014

Project – Better C++

The primary goals for this project was to get back to C++ programming, to learn using it more effectively after more than a decade doing only C programming, and to learn GUI programming.  Creating an incremental (interactive) BASIC compiler seemed to be an ideal way to accomplish this.  The GUI programming came later with the selection and use of the Qt toolkit.  Learning about the CMake build system and the git distributed revision control also came along the way.

After reading the book API Design For C++ by Martin Reddy recommended by a coworker, I started to get more of a taste for what C++ is capable of.  Even though this project is not an API (Application Programming Interface), when you think about it, any C++ class is an like API for other code that uses it.

I then picked up an old C++ book I purchased over two decodes ago when I was first learning C++, but couldn't get past the first chapter at the time.  I won't bother mentioning the title since this 1989 book is way out of date now (for example, C++ did not even have templates or the delete[] operator when the book was written).  Any way, I read the book and it wasn't really that bad, so I decided to pick up a more up to date book on C++.

I selected the book The C++ Programming Language (Fourth Edition) by Bjarne Stroustrup (the creator of C++).  I never liked older editions of this book, but decided to give this book a try since it includes the new C++11 standard.  I've picked up quite a bit that I did not previously know about C++ and I'm barely into the book at this point.  What I have realized that parts of what has been implemented in the project fails at being good C++ code.

One example is the memory management of tokens.  A lot of work went into tracking tokens.  There were two separate implementations in the attempt to make sure the ownership of the tokens and allocation of tokens worked properly - and to report any errors upon termination of the application.  The C++ facility of overloading the new and delete operators was used to accomplish this.  There is a better C++ facility using existing library classes that can be used to drastically simplify this.

Another example is the code table that holds information for all the BASIC program elements (commands, operators, functions, etc.).  The current solution is very much a straight C solution with C++ wrapped around it.  The current method on how code IDs are assigned is very kludgy (via an awk script that scans for special comments in a source file).  The method of how  associated codes are setup is also very kludgy (via elaborate C macros).  As a result, it is very easy to setup table entries incorrectly.  There must be a better way to accomplish this with C++ (though I'm not sure what that is yet).

Saturday, January 11, 2014

Program – Saving Text Of Error Lines

Now that two minor problems found during testing have been corrected, the next step in changing the program loading process is to handle lines with errors when loading the program.  This is accomplished by saving the text of the line with an error in the line information array (which also contains the offset into the program code, the code size, and error index if any of the line).

When a line has an error, the text of the line is stored in the new text variable in the line information for the line.  This variable is cleared when a line does not have an error.  Now, when the text of a line is requested (by the edit box when processing a program change signal), if the line has an error, this text is returned instead of recreating the code for the line (since there is no code for the line).

When a line is changed or inserted and the line has an error, a program change signal is no longer emitted.  Only the edit box changes and it already has the text of lines inserted with an error.  However, when a line is appended, a program change signal is always emitted regardless of whether it has an error (lines will only be appended during loading and the edit box will need the text for all lines including those with errors).

The program changed slot of the edit box class was modified to no longer check for lines with errors (by checking if the line text string was null) because the program unit attached no longer sends signals for lines with errors (if the change originated from the edit box).

[commit 4a110b2735]

Dictionary – Remove Correction

A minor problem was discovered with the dictionary class, which can be demonstrated by entering the single statement "a=0" into an empty program and then introducing an error on the line (for example, "a=0b") and entering the line.  Once the error is removed, the line is recreated incorrectly as " = 0" (note the space where the "a" should be).

When the statement is first entered, the "a" variable gets entered into the dictionary as "A" (because variable names are case insensitive).  When the error is introduced, the statement is dereferenced (both the variable "a" and the constant "0" should be removed from the dictionaries).  However, when the attempt to remove "a" from the hash in the dictionary, it does not match the "A" that was put into the hash originally.  The dictionary item is removed (from the key list).  When the "a" is added back, the dictionary sees that it is already in the hash because it was not correctly removed and returns it index and the name doesn't get added back to the key list, which still has an empty name for the index.

This problem was corrected by adding a case sensitivity argument to the remove functions of the dictionary and info dictionary classes with a default of case insensitive (same as for the add functions).  For dictionaries that use the case sensitive option (remark and string constant), they must also use it when removing dictionary entries.  The remove function converts the obtained key from the key list for the index specified to upper case for a case insensitive dictionary so that the hash is properly removed.

[commit d7dec3ca11]

Friday, January 10, 2014

Edit Box – New Program Correction

A problem was found with the New program command.  The problem occurs when clearing (New) the loaded program.  After clearing the program, as soon as a character is entered, a crash occurred.  The problem occurred because while the document in the edit box was cleared, several of the other variables were not, so the edit box tried to remove all the lines from the attached program unit that had already been removed.  The extra selections list, line count, modified line number, and modified line is new flag variables also needed to be reset.

[commit 96557e5562]

Wednesday, January 8, 2014

Program – Append Update Operation

Complicating the new loading process is the handling of lines with errors.  When a line containing an error is entered into the edit box, no recreation of the line is necessary since the edit box already has the text.  However, when a program is being loaded from a file and a line has an error,  the text of the line has to be entered into the edit box.

When the edit box retrieves the recreated text for a changed line, the program unit returns a null string for a line with an error.  For null strings (lines with errors), the edit box ignores the line since it already has the line in the document.  The program unit will be changed to return the line with an error, and it will not send a program change signal if the line originated by a change from the edit box document.  However, when the program class is loading a program from a file, it will send program change signals for lines with errors.

The program unit will need to know whether an update came from the edit box (no signal) or program load (send signal).  During the loading of the program, the lines are loaded sequentially and each will be added (appended) to the end of the program.  If the current program unit update routine was used as is, the new program load routine would need to maintain a line number which would be incremented for each line and passed to the update routine.

To simplify the program load routine and give the update routine the ability to determine the caller (edit box or program load), a new append operation was added (in addition to the insert, change and remove operations).  The update routine detects the append operation by whether the line number passed to it is set to a -1, which the program load routine will use as it adds lines to the end of the program (and it won't need to keep track of line numbers).

When the update routine sees the line number set to -1, it sets the operation to append and the line number to the current count of lines in the program.  Otherwise, the append operation is the same as the insert operation.  The operation enumeration was moved from the error list header file to the program model header file with the new append operation.  This enumeration was only in the error list header file for the set change index routine, but this routine had been removed though its definition was accidentally left behind (it was removed).

[commit b795a47120]

Tuesday, January 7, 2014

Program Loading Process

The main window class currently loads the entire text of the program read from the selected file.  This text is given to the edit box instance using the setPlainText function, which is overloaded from the QPlainTextEdit base class, and just resets the cursor valid flag before calling the base class function.

The document of the edit box then emits a document changed signal, which is processed and the attached program unit is updated.  The cursor valid flag prevents the program change and error signals from the updated program unit from being processed, otherwise an infinite loop would occur.  Once the cursor is moved (the cursor position is changed after the document is changed), the cursor valid flag is set and the errors are processed.

This process will be changed to where the new program class will load the program from the file into the program unit.  Later all the subroutines and functions that are included in the program file will be detected and each loaded into a separate program unit.  This change in the program loading process will be handled over several sets of changes and will be explained in the next set of posts.