Using Catch for Jeff Langr’s TDD Book Chapter 2

Published on:
Tags: TDD, catch

As I'm a bit of a fan of Phil Nash's Catch test framework I decided to convert the code in Jeff Langr's book to use Catch. This post describes the changes that were required for the first tests, i.e. chapter 2.

Code for this project is here…

Basic changes

Catch is header only so is much simpler to incorporate than Google Mock/Test so the CMakeLists.txt can be much simpler. For the start of the chapter, this is sufficient:

1
2
3
4
5
6
7
8
9
10
11
12
project(chapterFirstExample)
cmake_minimum_required(VERSION 2.6)

include_directories(../../Catch/include)
add_definitions(-std=c++0x)
set(CMAKE_CXX_FLAGS "${CMAXE_CXX_FLAGS} -Wall")

set(sources
   main.cpp
   SoundexTest.cpp)
add_executable(test ${sources})
target_link_libraries(test pthread)

All we need to do is change the path to the Catch include directory, remove the link path and remove the link libraries.

Similarly, main.cpp is also simpler:

1
2
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

Strictly speaking we don't need main.cpp at all, but it simplifies the test code to keep it.

Read on →

Integrating Phil Nash’s Catch C++ Unit Test Framework Into Visual Studio

Published on:

After I adapted some existing code that used MSTest so that I was able to use Catch, I started to look at whether it was possible to do better; specifically I wanted to share source code between VS and Catch written for a console app and I wanted to retain the ability to generate standard VS TestResults files (*.trx).

The results were better than I expected; I found it was possible, with a little adaptation, to change the Catch internals so that I could do all that; so much so that I was able to reimplement the Catch self tests as Managed C++ test projects for VS2010 and VS2012 as well as Native C++ test projects.

You can find a fork of Catch here that implements this; hopefully Phil and I will be able to integrate this into the Catch mainline soon but until that is done I will do my best to keep the fork in sync with the code here.

You can find details on how to use it here and it looks like this:

VS2010:

VS2010

VS2012:

VS2012

Replacing MSTest With Phil Nash’s Catch Framework for VS2012 Native C++ Tests

Published on:
Tags: MSTest, TDD, c++, catch

In an earlier post I described how to share the same codebase for MSTest managed C++ code and Phil Nash's Catch framework. In VS2012, there's an option for 'Native' C++ tests; this article describes how to use Catch to share the codebase for Native tests too.

VS2012 and Native C++ Tests

In VS2012, you can create a managed C++ test project like this:

Managed C++

You can also create a Native test, like this:

Native C++

In my case, a native test looks something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace NativeTestProject
{      
  TEST_CLASS(UnitTest1)
  {
        NativeTestClass* m_data;
  public:
      UnitTest1()
        {}
        ~UnitTest1()
        {
        }
        TEST_METHOD_INITIALIZE(TestInit)
        {
            m_data = new NativeTestClass("Fred", 42);
        }
        TEST_METHOD_CLEANUP(TestCleanup)
        {
            delete m_data;
            m_data = NULL;
        }

      TEST_METHOD(TestMethod1)
      {
            ...
        }
Read on →

Replacing MSTest With Phil Nash’s Catch Framework for Managed C++ Tests

Published on:
Tags: MSTest, TDD, c++, catch

Visual Studio 2010 has an option for creating C++ unit tests, but these tests are 'managed' C++. There are a number of problems with such tests:

  1. The tests are slow to compile and slow to load/run.
  2. Tests tend to be more complicated than needed - the Managed C++ compiler does not allow C++ value types as member variables for example, so these have to be kept as pointers and new/delete used.
  3. The debugger doesn't understand C++ types very well, so when in managed code it is often not possible to view object values. Whilst it could be argued that using TDD should avoid most uses of the debugger, sometimes it's inevitable.
  4. Sometimes the Managed C++ debugger gets a 'mind of its own' and decides to run a test to completion part way through debugging. This can be frustrating!
  5. Sometimes, the process vstest.executionengine.x86.exe gets left running after the tests have completed whcih prevents the any new builds from compiling as the DLL is held open by the executionengine. There is a bug report for this but apparently no solution other than using taskkill as a pre-build event (http://stackoverflow.com/questions/13497168/vstest-executionengine-x86-exe-not-closing)

In the absence of Native C++ unit tests (note: VS2012 has these - see later) I wanted to be able to share the code base between MSTest managed tests and native tests so that the build system could happily run MSTest on its managed build and I could run native tests using Catch. This article describes my experiment to do this…

Differences in test philosophy

To persuade MSTest to look like Catch, we have to think about how the test needs to run. MSTest requires a class, but Catch does not. Catch allows multiple runs by using SECTIONs, but this doesn't figure in MSTest. So my first attempt used a TEST_CASE as a 'class' wrapper and a SECTION for each test method. This worked pretty well, except that it wasn't possible to specify individual tests to run (SECTIONs don't support tags).

Looking at the tests that I wanted convert, they tended to follow a pattern:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
namespace ManagedTestProject
{
    [TestClass]
    public ref class ClassNameForTest
    {
        // some data that needs to be initialized...
        Stuff* m_data;

      //Use TestInitialize to run code before running each test
      [TestInitialize()]
      void MyTestInitialize()
        {
            m_data = new Stuff(...);
        }

      //Use TestCleanup to run code after each test has run
      [TestCleanup()]
      void MyTestCleanup()
        {
            delete m_data;
            m_data = NULL;
        }

    public:
      [TestMethod]
        void Method1() {}

      [TestMethod]
        void Method2() {}
    };
}
Read on →

Debugging Phil Nash’s CATCH Framework With Gdb on Mingw32

Published on:
Tags: TDD, c++, catch, gdb

So you have Mingw (or gdb on Linux) and you'd like to use Phil Nash's CATCH testing framework. This article will go through some simple tests that we can construct and how to use it in that environment.

Throughout this document I use a test project that I've setup in C:\Projects\catch_gdb_example - I'll use the Mingw directory /c/Projects/catch_gdb_example to access it.

For testing, I was using the latest CATCH with Mingw32:

1
2
$ uname -a
MINGW32_NT-6.1 machine 1.0.18(0.48/3/2) 2012-11-21 22:34 i686 Msys
and Git:
1
2
$ git --version
git version 1.8.3.msysgit.0

First, CATCH your framework

There are two easy ways to get CATCH, and one that is slightly harder, so guess which one I chose? The easy way is download the source zip file, available from https://github.com/philsquared/Catch and unpack it - you can either use the full include headers (from catch/include) or the single header (from catch/single_include).

The alternative that I chose was to first download and install git for windows (http://msysgit.github.com/).

Then I cloned Phil's repository with:

1
2
cd /c/Projects/catch_gdb_example
git clone https://github.com/philsquared/Catch.git

…this clones the CATCH framework and puts it into the 'Catch' sub–directory.

Build a sanity check

Next create a cpp file (e.g. main.cpp) with the following contents:

1
2
3
4
5
6
7
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEST_CASE( "main/sanity check", "[sanity]" )
{
    REQUIRE(true);
}

Now a simple makefile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CC=g++
CFLAGS=-c -DDEBUG -I./Catch/include -g -Wall -pedantic -Wextra -std=c++0x
LDFLAGS=
SOURCES= \
    main.cpp
    
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=test.exe

all: $(SOURCES) $(EXECUTABLE)
  
$(EXECUTABLE): $(OBJECTS) 
  $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
  $(CC) $(CFLAGS) $< -o $@

clean:
  rm -rf *.o $(EXECUTABLE)

…and we can build the test with:

1
make

and run with:

1
2
3
4
5
6
7
8
User@machine /c/Projects/catch_gdb_example
$ make
g++ -c -DDEBUG -I./Catch/include -g -Wall -pedantic -Wextra -std=c++0x main.cpp -o main.o
g++  main.o -o test.exe

User@machine /c/Projects/catch_gdb_example
$ ./test.exe main/*
All tests passed (1 assertion in 1 test case)

Now for the debugger

Add the following failing test:

1
2
3
4
5
TEST_CASE("test/fails","[gdb]")
{
    int a = 1;
    REQUIRE(a == 0);
}
and recompile:
1
2
3
4
User@machine /c/Projects/catch_gdb_example
$ make
g++ -c -DDEBUG -I./Catch/include -g -Wall -pedantic -Wextra -std=c++0x main.cpp -o main.o
g++  main.o -o test.exe

Now you can run the test program and set it to break on the failure of test conditions:

Read on →

Deconstructing Compile Time FizzBuzz in C++ Without Boost

Published on:

Several years ago Adam Peterson published an article on how to implement FizzBuzz at cmpile time in C++. The code was clever, but had a dependency on Boost and didn't go into great detail on how it worked, so I thought I'd write it again from scratch and try to explain my workings. In this article I'm only going to show examples that would work for very small FizzBuzz sequences because, well, this is a learning exercise not a typing exercise!

At the end of this article you'll find the source that I used to run the examples below - up to 16 items in the sequence. Much of what follows is a variation on the code in chapter 5 of C++ Template Metaprogramming, in particular the use of mpl::vector and the 'tiny' sequence.

First, get an error message

To make this work, we first have persuade the compiler to print an error message to the console when we build the program, something like this:

1
2
3
4
5
6
7
8
9
10
11
struct void_;

template <class T0 = void_, class T1 = void_, class T2 = void_, class T3 = void_>
struct vector
{
    typedef vector type;
    typedef T0 T0;
    typedef T1 T1;
    typedef T2 T2;
    typedef T3 T3;
};
Read on →

Using Ruby Installer to Install Redcarpet and Github-linguist With Octopress on Windows

Published on:

This article follows three posts describing how to install Ruby 1.9.3 to use Octopress with redcarpet and github-linguist in a native MingW environment; using what I learnt in that process I've figured out how to use the Ruby Installer for Windows to do the same thing - this post describes how to do that. I plan to leave the original posts (starting here) in case they may provide inspiration for someone else with similar ambitions.

I wanted to use redcarpet/github-linguist for markdown in Octopress, however there's a dependency on the charlock_holmes Gem that requires native code libraries (file, ICU), some of which it needs to build. It turns out that we can do this with Ruby Installer

First, install Ruby…

Install and install ruby 1.9.3 (from rubyinstaller.org) Download the devkit (current version here) Unpack dev kit, e.g. into C:\Ruby193\devkit Setup the Ruby installation to work with the devkit:

1
2
ruby dk.rb init
ruby dk.rb install
All of this follows the regular instructions for installing Ruby and the devkit. <!– more –>

Install Python 2.7

Next, install Python 2.7, if you havn't already - this is required for pygments.rb. Make sure Python is in your path. Check in a Mingw window:

1
python --version

Additional tools for devkit

For some reason, the devkit doesn't come with tar, zip & patch so install these from MingW downloads. I used 7-zip to unpack the wget and xz and then used the binaries of those tools to get the rest; if you want you can just download the missing tools and unpack them with 7-zip, then copy the binaries manually.

If you want to use MingW, first you need to download and unpack xz, wget and dlls for openssl and liblzma; download wget from here , xz from here, openssl dlls from here and liblzma dlls from here. Unpack them all with 7-zip (unpack the tar files as well) and copy the binaries to the bin, etc and lib directories of your devkit (copying with Windows Explorer is fine).

Start the devkit using the msys.bat file located in the devkit root and check that they installed:

1
2
3
4
5
6
$ wget --version
GNU Wget 1.12 built on msys.
...
$ xz --version
xz (XZ Utils) 5.0.3
liblzma 5.0.3
Now you should be able to use MingW/MSYS to download and install the missing tools; create a temporary directory to unpack the files into and copy the files:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cd ~
mkdir tmp
cd tmp
wget http://sourceforge.net/projects/mingw/files/MSYS/Base/tar/tar-1.22-1/tar-1.22-1-msys-1.0.11-bin.tar.lzma
xz -d tar-1.22-1-msys-1.0.11-bin.tar.lzma
tar xvf tar-1.22-1-msys-1.0.11-bin.tar
wget http://sourceforge.net/projects/mingw/files/MSYS/Extension/zip/zip-3.0-1/zip-3.0-1-msys-1.0.14-bin.tar.lzma
xz -d zip-3.0-1-msys-1.0.14-bin.tar.lzma
tar xvf zip-3.0-1-msys-1.0.14-bin.tar
wget http://sourceforge.net/projects/mingw/files/MSYS/Extension/unzip/unzip-6.0-1/unzip-6.0-1-msys-1.0.13-bin.tar.lzma
xz -d unzip-6.0-1-msys-1.0.13-bin.tar.lzma
tar xvf unzip-6.0-1-msys-1.0.13-bin.tar
wget http://sourceforge.net/projects/mingw/files/MSYS/Extension/patch/patch-2.5.9-1/patch-2.5.9-1-msys-1.0.11-bin.tar.lzma
xz -d patch-2.5.9-1-msys-1.0.11-bin.tar.lzma
tar xvf patch-2.5.9-1-msys-1.0.11-bin.tar
wget http://sourceforge.net/projects/mingw/files/MSYS/Base/gzip/gzip-1.3.12-1/gzip-1.3.12-1-msys-1.0.11-bin.tar.lzma
xz -d gzip-1.3.12-1-msys-1.0.11-bin.tar.lzma
tar xvf gzip-1.3.12-1-msys-1.0.11-bin.tar
cp -r -v bin /
cp -r -v share /
cd .. 
Now we're ready to install the dependencies for the charlock_holmes Gem…

Build native libraries

We need some additional libraries for the Ruby Gem charlock_holmes. I've built them both with static linking here so that we don't need to worry about where the DLLs might have gone.

Download and build ICU (this post on compiling for qt and this post for compiling for OpenTTD both help):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cd ~
mkdir build32
cd ~/build32
wget http://download.icu-project.org/files/icu4c/4.6/icu4c-4_6-src.zip
unzip icu4c-4_6-src.zip
wget http://devs.openttd.org/~terkhen/libicu/libicu_4_6_mingw32.diff
wget http://devs.openttd.org/~terkhen/libicu/libicu_reduce_icudata_size.diff
cd icu
patch -p1 -i ../libicu_4_6_mingw32.diff
patch -p1 -i ../libicu_reduce_icudata_size.diff
cd source
./configure --prefix=/mingw --enable-static --disable-shared --disable-strict --disable-threads
#./configure --prefix=$PWD/../dist --enable-static --disable-shared --disable-strict --disable-threads
make && make install
cd ../..

Download and install libgnurx (required for file-5.08, also a dependency of charlock_holmes):

1
2
3
4
cd ~/build32
wget http://sourceforge.net/projects/mingw/files/Other/UserContributed/regex/mingw-regex-2.5.1/mingw-libgnurx-2.5.1-src.tar.gz
tar zxvf mingw-libgnurx-2.5.1-src.tar.gz
cd mingw-libgnurx-2.5.1
Apply the following patch for static build: (diff -up Makefile.in Makefile.in.new > ../mingw-libgnurx-static.patch)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
--- Makefile.in 2007-05-07 20:28:28 +0100
+++ Makefile.in.new     2013-09-23 12:44:15 +0100
@@ -56,7 +56,7 @@ SRCDIST_FILES = ${srcdir}/configure ${sr
 ZIPCMD = @ZIPCMD@
 ZIPEXT = @ZIPEXT@

-all: libgnurx-$(DLLVERSION).dll libgnurx.dll.a libregex.a @GNURX_LIB@
+all: libgnurx.a libgnurx-$(DLLVERSION).dll libgnurx.dll.a libregex.a @GNURX_LIB@

 Makefile: config.status Makefile.in
        ./config.status
@@ -69,6 +69,10 @@ $(OBJECTS): Makefile
 libgnurx-$(DLLVERSION).dll libgnurx.dll.a: $(OBJECTS)
        $(CC) $(CFLAGS) -shared -o libgnurx-$(DLLVERSION).dll $(LDFLAGS) $(OBJECTS)

+libgnurx.a: $(OBJECTS)
+       ar rcu $@ $(OBJECTS)
+       ranlib $@
+
 libregex.a: libgnurx.dll.a
        cp -p libgnurx.dll.a $@

@@ -81,6 +85,11 @@ install-dll:
        mkdir -p ${bindir}
        cp -p $(BINDIST_FILES) ${bindir}

+install-static: libgnurx.a
+       mkdir -p ${includedir} ${libdir}
+       cp -p ${srcdir}/regex.h ${includedir}
+       cp -p ${srcdir}/libgnurx.a ${libdir}
+
 install-dev:
        mkdir -p ${includedir} ${libdir}
        cp -p ${srcdir}/regex.h ${includedir}
Build and install:
1
2
3
patch -i ../mingw-libgnurx-static.patch
./configure -prefix=/mingw
make && make install-static
Optional: check that file-5.08 builds (note: no make install) without errors:
1
2
3
4
5
6
cd ~/build32
wget ftp://ftp.astron.com/pub/file/file-5.08.tar.gz
tar zxvf file-5.08.tar.gz
cd file-5.08
./configure --prefix=/mingw  --disable-shared --enable-static --with-pic
make

Install Octopress

Download Octopress (see also Octopress setup instructions). The easiest way to do this is to first install Git for Windows. Start Git Bash, and then (note: this example uses ~/build32 but you can put octopress where you like…):

1
2
cd /c/Ruby193/devkit/home/[user]/build32/
git clone git://github.com/imathis/octopress.git octopress

At this stage (back in MingW build environment):

1
2
3
4
5
6
7
8
9
10
11
cd ~/build32/octopress
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.1.0)
io-console (0.3)
json (1.5.5)
minitest (2.5.1)
rake (0.9.2.2)
rdoc (3.9.5)

Install bundler and the default bundle:

1
gem install bundler
1
2
3
4
5
6
7
8
9
10
11
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.1.0)
bundler (1.3.5)
io-console (0.3)
json (1.5.5)
minitest (2.5.1)
rake (0.9.2.2)
rdoc (3.9.5)
Then install the default bundle:
1
bundle install
Install the default Octopress theme, create a new test page and generate the site:
1
2
3
rake install
rake new_post["first post"]
rake generate
You should get the site built in octopress/public. Check that index.html is generated properly (size > 0).

At this point we have the default Octopress installed using rdiscount for markdown generation and we've setup the required libraries for redcarpet. Now we need to install charlock_holmes manually:

Install some updates required for github-linguist

Update the Gemfile to install pygments 0.3.7 - this is required so that we have the updated lexer Augeas (part contents of Gemfile):

1
gem 'pygments.rb', '~> 0.3.7'
and update the bundle:
1
2
bundle update pygments.rb
gem install rake-compiler
Now it should look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ bundle list
Gems included by the bundle:
  * RedCloth (4.2.9)
  * bundler (1.3.5)
  * chunky_png (1.2.5)
  * classifier (1.3.3)
  * compass (0.12.2)
  * directory_watcher (1.4.1)
  * fast-stemmer (1.0.1)
  * fssm (0.2.9)
  * haml (3.1.7)
  * jekyll (0.12.0)
  * kramdown (0.13.8)
  * liquid (2.3.0)
  * maruku (0.6.1)
  * posix-spawn (0.3.6)
  * pygments.rb (0.3.7)
  * rack (1.5.2)
  * rack-protection (1.5.0)
  * rake (0.9.2.2)
  * rb-fsevent (0.9.1)
  * rdiscount (2.0.7.3)
  * rubypants (0.2.0)
  * sass (3.2.9)
  * sass-globbing (1.0.0)
  * sinatra (1.4.2)
  * stringex (1.4.0)
  * syntax (1.0.0)
  * tilt (1.3.7)
  * yajl-ruby (1.1.0)

Create a patch file for pygments.rb:

1
2
3
4
5
6
7
8
9
10
11
--- popen.rb 2013-09-24 14:41:22 +0100
+++ popen.rb.new  2013-09-24 15:12:42 +0100
@@ -110,7 +110,7 @@
     def lexers
       begin
         lexerfile = File.expand_path('../../../lexers', __FILE_)
-        raw = File.open(lexer_file, "r").read
+        raw = File.open(lexer_file, "rb").read
         Marshal.load(raw)
       rescue Errno::ENOENT
         raise MentosError, "Error loading lexer file. Was it created and vendored?"

Now apply the patch to popen.rb in pygments.rb:

1
2
3
cd ~/local32/lib/ruby/gems/1.9.1/gems/pygments.rb-0.3.7/lib/pygments
patch -u -i ~/build32/pygments.rb.popen.rb.patch
cd ~/build32/octopress

Get and patch charlock_holmes

1
2
3
4
5
6
7
mkdir ~/build32/tmpgems
cd ~/build32/tmpgems
gem fetch charlock_holmes
gem spec charlock_holmes-0.6.9.4.gem --ruby > charlock_holmes.gemspec
gem unpack charlock_holmes-0.6.9.4.gem
mv -v charlock_holmes.gemspec charlock_holmes-0.6.9.4
cd charlock_holmes-0.6.9.4
Now modify ext/charlock_holmes/extconf.rb:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--- extconf.rb   2013-09-24 14:49:14 +0100
+++ extconf.rb.new    2013-09-24 14:51:54 +0100
@@ -9,7 +9,7 @@
   ret
 end
 
-if `which make`.strip.empty?
+if `sh which make`.strip.empty?
   STDERR.puts "\n\n"
   STDERR.puts "***************************************************************************************"
   STDERR.puts "*************** make required (apt-get install make build-essential) =( ***************"
@@ -37,7 +37,8 @@
   end
 end
 
-unless have_library 'icui18n' and have_header 'unicode/ucnv.h'
+#unless have_library 'icui18n' and have_library 'icuuc' and have_library 'regex' and have_header 'unicode/ucnv.h'
+unless have_library 'icudata' and have_library 'icuuc' and have_library 'icui18n' and have_library 'gnurx' and have_header 'unicode/ucnv.h'
   STDERR.puts "\n\n"
   STDERR.puts "***************************************************************************************"
   STDERR.puts "*********** icu required (brew install icu4c or apt-get install libicu-dev) ***********"
@@ -57,7 +58,7 @@
 
   sys("tar zxvf #{src}")
   Dir.chdir(dir) do
-    sys("./configure --prefix=#{CWD}/dst/ --disable-shared --enable-static --with-pic")
+    sys("sh ./configure --prefix=#{CWD}/dst/ --disable-shared --enable-static --with-pic")
     sys("patch -p0 < ../file-soft-check.patch")
     sys("make -C src install")
     sys("make -C magic install")
1
2
3
4
5
cd ext/charlock_holmes
patch -u -i /build32/charlock_holmes_extconf.rb.patch
cd ../..
gem build charlock_holmes.gemspec
gem install charlock_holmes-0.6.9.4.gem --platform=ruby

We should now have charlock_holmes installed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.1.0)
bundler (1.3.5)
charlock_holmes (0.6.9.4)
chunky_png (1.2.5)
classifier (1.3.3)
compass (0.12.2)
directory_watcher (1.4.1)
fast-stemmer (1.0.1)
fssm (0.2.9)
haml (3.1.7)
io-console (0.3)
jekyll (0.12.0)
json (1.5.5)
kramdown (0.13.8)
liquid (2.3.0)
maruku (0.6.1)
minitest (2.5.1)
posix-spawn (0.3.6)
pygments.rb (0.3.7, 0.3.4)
rack (1.5.2)
rack-protection (1.5.0)
rake (0.9.2.2)
rake-compiler (0.9.1)
rb-fsevent (0.9.1)
rdiscount (2.0.7.3)
rdoc (3.9.5)
RedCloth (4.2.9 x86-mingw32)
rubypants (0.2.0)
sass (3.2.9)
sass-globbing (1.0.0)
sinatra (1.4.2)
stringex (1.4.0)
syntax (1.0.0)
tilt (1.3.7)
yajl-ruby (1.1.0 x86-mingw32)

Add redcarpet to Octopress

1
cd ~/build32/octopress

Now we can modify the Gemfile to include redcarpet (part contents of Gemfile):

1
2
3
4
5
  gem 'rdiscount', '~> 2.0.7'
  gem "charlock_holmes", "~> 0.6.9.4"
  gem "github-linguist", "~> 2.4"
  gem 'redcarpet', '~> 2.1.1'
  gem 'pygments.rb', '~> 0.3.7'
And update the Gems:
1
2
cd ~/build32/octopress
bundle install

Test. Save this code into a file in (for example) /tmp/test.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
require 'rdiscount'
require 'charlockholmes'
require 'escape_utils'
require 'pygments'
require 'yaml'
require 'linguist/classifier'
require 'linguist/samples'
require 'linguist/file_blob'
require 'redcarpet'

puts "Ruby test"

#puts Pygments.highlight(File.read(FILE_), :lexer => 'ruby')

@rdiscount_extensions = "smart"

content = "Some text"
rd = RDiscount.new(content, @rdiscount_extensions)
html = rd.to_html

puts html

detection = CharlockHolmes::EncodingDetector.detect(html)

puts detection

fb = Linguist::FileBlob.new("c:\Ruby193\devkit\dk.rb")
puts fb.language.name

markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true)
puts markdown.render("This is *bongos c++ int main() { return 0 }, indeed.")

And run the test:

1
2
3
4
5
6
7
$ ruby test.rb
...
Ruby test
<p>Some <em>text</em></p>
{:type=>:text, :encoding=>"ISO-8859-2", :confidence=>40, :language=>"cs"}
Ruby
<p>This is <em>bongos</em> <code>c++ int main() { return 0 }</code>, indeed.</p>

Now modify _config.yml for octopress to generate redcarpet markdown:

1
2
3
markdown: redcarpet
redcarpet:
  extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data"]

Modify the 'frist post' created above to include some github markdown, e.g. (note: replace last [backtick]…):

1
Some text
c++ int main() { return 0; } “[backtick]

Some more text.

1
2

And regenerate:
rake generate
1
You should now have syntax highlighted code blocks, like this:
c++ int main() { return 0; } “`

Installing Ruby 1.9.3 in Windows With Redcarpet and Github Markdown

Published on:

This is the third of three posts describing how to install Ruby 1.9.3 native MingW environment. It's much simpler to use Ruby Installer to do this but if you want all the details of how to do it natively, read on…

If you're wondering why I did this, I wanted to use redcarpet/github-linguist for markdown in Octopress; there's a dependency on the charlock_holmes Gem that requires native code libraries (file, ICU), some of which it needs to build. I couldn't figure out how to make the Ruby Installer do this and I wanted to understand the process, so I did the whole thing from scratch. The first part is here and the second part is here.

Setup ruby. In the build location (/build32 if following the instructions)…

First, install Python 2.7, if you havn't already - this is required for pygments.rb. Make sure Python is in your path. Check in a Mingw window:

1
python --version

We need some additional libraries for the Ruby Gem charlock_holmes. I've built them both with static linking here so that we don't need to worry about where the DLLs might have gone. <!– more –>

Download and build ICU (this post on compiling for qt and this post for compiling for OpenTTD both help):

1
2
3
4
5
6
7
8
9
10
11
12
13
cd /build32
wget http://download.icu-project.org/files/icu4c/4.6/icu4c-4_6-src.zip
unzip icu4c-4_6-src.zip
wget http://devs.openttd.org/~terkhen/libicu/libicu_4_6_mingw32.diff
wget http://devs.openttd.org/~terkhen/libicu/libicu_reduce_icudata_size.diff
cd icu
patch -p1 -i ../libicu_4_6_mingw32.diff
patch -p1 -i ../libicu_reduce_icudata_size.diff
cd source
./configure --prefix=/mingw --enable-static --disable-shared --disable-strict --disable-threads
#./configure --prefix=$PWD/../dist --enable-static --disable-shared --disable-strict --disable-threads
make && make install
cd ../..

Download and install libgnurx (required for file-5.08, also a dependency of charlock_holmes):

1
2
3
4
cd /build32
wget http://sourceforge.net/projects/mingw/files/Other/UserContributed/regex/mingw-regex-2.5.1/mingw-libgnurx-2.5.1-src.tar.gz
tar zxvf mingw-libgnurx-2.5.1-src.tar.gz
cd mingw-libgnurx-2.5.1
Apply the following patch for static build: (diff -up Makefile.in Makefile.in.new > ../mingw-libgnurx-static.patch)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
--- Makefile.in 2007-05-07 20:28:28 +0100
+++ Makefile.in.new     2013-09-23 12:44:15 +0100
@@ -56,7 +56,7 @@ SRCDIST_FILES = ${srcdir}/configure ${sr
 ZIPCMD = @ZIPCMD@
 ZIPEXT = @ZIPEXT@

-all: libgnurx-$(DLLVERSION).dll libgnurx.dll.a libregex.a @GNURX_LIB@
+all: libgnurx.a libgnurx-$(DLLVERSION).dll libgnurx.dll.a libregex.a @GNURX_LIB@

 Makefile: config.status Makefile.in
        ./config.status
@@ -69,6 +69,10 @@ $(OBJECTS): Makefile
 libgnurx-$(DLLVERSION).dll libgnurx.dll.a: $(OBJECTS)
        $(CC) $(CFLAGS) -shared -o libgnurx-$(DLLVERSION).dll $(LDFLAGS) $(OBJECTS)

+libgnurx.a: $(OBJECTS)
+       ar rcu $@ $(OBJECTS)
+       ranlib $@
+
 libregex.a: libgnurx.dll.a
        cp -p libgnurx.dll.a $@

@@ -81,6 +85,11 @@ install-dll:
        mkdir -p ${bindir}
        cp -p $(BINDIST_FILES) ${bindir}

+install-static: libgnurx.a
+       mkdir -p ${includedir} ${libdir}
+       cp -p ${srcdir}/regex.h ${includedir}
+       cp -p ${srcdir}/libgnurx.a ${libdir}
+
 install-dev:
        mkdir -p ${includedir} ${libdir}
        cp -p ${srcdir}/regex.h ${includedir}
Build and install:
1
2
3
patch < ../mingw-libgnurx-static.patch
./configure -prefix=/mingw
make && make install-static
Optional: check that file-5.08 builds (note: no make install) without errors:
1
2
3
4
5
6
cd /build32
wget ftp://ftp.astron.com/pub/file/file-5.08.tar.gz
tar zxvf file-5.08.tar.gz
cd file-5.08
./configure --prefix=/mingw  --disable-shared --enable-static --with-pic
make
Download Octopress (see also Octopress setup instructions). The easiest way to do this is to first install Git for Windows. Start Git Bash, and then (note: this example uses /build32 but you can put octopress where you like…):
1
2
cd /c/mingw/build32
git clone git://github.com/imathis/octopress.git octopress

At this stage (back in MingW build environment):

1
2
3
4
5
6
7
8
9
10
11
cd /build32/octopress
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.1.0)
io-console (0.3)
json (1.5.5)
minitest (2.5.1)
rake (0.9.2.2)
rdoc (3.9.5)

Install bundler and the default bundle:

1
gem install bundler
1
2
3
4
5
6
7
8
9
10
11
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.1.0)
bundler (1.3.5)
io-console (0.3)
json (1.5.5)
minitest (2.5.1)
rake (0.9.2.2)
rdoc (3.9.5)
Then install the default bundle:
1
bundle install
Update the Gemfile to install pygments 0.3.7 - this is required so that we have the updated lexer Augeas:
1
gem 'pygments.rb', '~> 0.3.7'
and update the bundle:
1
bundle update pygments.rb
Now it should look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ bundle list
Gems included by the bundle:
  * RedCloth (4.2.9)
  * bundler (1.3.5)
  * chunky_png (1.2.5)
  * classifier (1.3.3)
  * compass (0.12.2)
  * directory_watcher (1.4.1)
  * fast-stemmer (1.0.1)
  * fssm (0.2.9)
  * haml (3.1.7)
  * jekyll (0.12.0)
  * kramdown (0.13.8)
  * liquid (2.3.0)
  * maruku (0.6.1)
  * posix-spawn (0.3.6)
  * pygments.rb (0.3.7)
  * rack (1.5.2)
  * rack-protection (1.5.0)
  * rake (0.9.2.2)
  * rb-fsevent (0.9.1)
  * rdiscount (2.0.7.3)
  * rubypants (0.2.0)
  * sass (3.2.9)
  * sass-globbing (1.0.0)
  * sinatra (1.4.2)
  * stringex (1.4.0)
  * syntax (1.0.0)
  * tilt (1.3.7)
  * yajl-ruby (1.1.0)

Create a patch file for pygments.rb:

1
2
3
4
5
6
7
8
9
10
11
--- popen.rb 2013-09-24 14:41:22 +0100
+++ popen.rb.new  2013-09-24 15:12:42 +0100
@@ -110,7 +110,7 @@
     def lexers
       begin
         lexerfile = File.expand_path('../../../lexers', __FILE_)
-        raw = File.open(lexer_file, "r").read
+        raw = File.open(lexer_file, "rb").read
         Marshal.load(raw)
       rescue Errno::ENOENT
         raise MentosError, "Error loading lexer file. Was it created and vendored?"

Now apply the patch to popen.rb in pygments.rb:

1
2
3
cd /local32/lib/ruby/gems/1.9.1/gems/pygments.rb-0.3.7/lib/pygments
patch -u -i /build32/pygments.rb.popen.rb.patch
cd /build32/octopress
Create a file named 'rake' in /local32/bin. This looks like the central section of rake.bat:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!C:/mingw/local32/bin/ruby

#--
# Copyright (c) 2003, 2004, 2005, 2006, 2007  Jim Weirich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#++

begin
  require 'rubygems'
rescue LoadError
end

require 'rake'

Rake.application.run
END
Install the default Octopress theme, create a new test page and generate the site:
1
2
3
rake install
rake new_post["first post"]
rake generate
You should get the site built in octopress/public. Check that index.html is generated properly (size > 0).

At this point we have the default Octopress installed using rdiscount for markdown generation and we've setup the required libraries for redcarpet. Now we need to install charlock_holmes manually:

1
2
3
4
5
6
7
8
gem install rake-compiler
mkdir /build32/tmp
cd /build32/tmp
gem fetch charlock_holmes
gem spec charlock_holmes-0.6.9.4.gem --ruby > charlock_holmes.gemspec
gem unpack charlock_holmes-0.6.9.4.gem
mv -v charlock_holmes.gemspec charlock_holmes-0.6.9.4
cd charlock_holmes-0.6.9.4
Now modify ext/charlock_holmes/extconf.rb:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
--- extconf.rb   2013-09-24 14:49:14 +0100
+++ extconf.rb.new    2013-09-24 14:51:54 +0100
@@ -9,7 +9,7 @@
   ret
 end
 
-if `which make`.strip.empty?
+if `sh which make`.strip.empty?
   STDERR.puts "\n\n"
   STDERR.puts "***************************************************************************************"
   STDERR.puts "*************** make required (apt-get install make build-essential) =( ***************"
@@ -37,7 +37,8 @@
   end
 end
 
-unless have_library 'icui18n' and have_header 'unicode/ucnv.h'
+#unless have_library 'icui18n' and have_library 'icuuc' and have_library 'regex' and have_header 'unicode/ucnv.h'
+unless have_library 'icudata' and have_library 'icuuc' and have_library 'icui18n' and have_library 'gnurx' and have_header 'unicode/ucnv.h'
   STDERR.puts "\n\n"
   STDERR.puts "***************************************************************************************"
   STDERR.puts "*********** icu required (brew install icu4c or apt-get install libicu-dev) ***********"
@@ -57,7 +58,7 @@
 
   sys("tar zxvf #{src}")
   Dir.chdir(dir) do
-    sys("./configure --prefix=#{CWD}/dst/ --disable-shared --enable-static --with-pic")
+    sys("sh ./configure --prefix=#{CWD}/dst/ --disable-shared --enable-static --with-pic")
     sys("patch -p0 < ../file-soft-check.patch")
     sys("make -C src install")
     sys("make -C magic install")
1
2
3
4
5
cd ext/charlock_holmes
patch -u -i /build32/charlock_holmes_extconf.rb.patch
cd ../..
gem build charlock_holmes.gemspec
gem install charlock_holmes-0.6.9.4.gem --platform=ruby

We should now have charlock_holmes installed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.1.0)
bundler (1.3.5)
charlock_holmes (0.6.9.4)
chunky_png (1.2.5)
classifier (1.3.3)
compass (0.12.2)
directory_watcher (1.4.1)
fast-stemmer (1.0.1)
fssm (0.2.9)
haml (3.1.7)
io-console (0.3)
jekyll (0.12.0)
json (1.5.5)
kramdown (0.13.8)
liquid (2.3.0)
maruku (0.6.1)
minitest (2.5.1)
posix-spawn (0.3.6)
pygments.rb (0.3.7, 0.3.4)
rack (1.5.2)
rack-protection (1.5.0)
rake (0.9.2.2)
rake-compiler (0.9.1)
rb-fsevent (0.9.1)
rdiscount (2.0.7.3)
rdoc (3.9.5)
RedCloth (4.2.9 x86-mingw32)
rubypants (0.2.0)
sass (3.2.9)
sass-globbing (1.0.0)
sinatra (1.4.2)
stringex (1.4.0)
syntax (1.0.0)
tilt (1.3.7)
yajl-ruby (1.1.0 x86-mingw32)
cd /build32/octopress

Now we can modify the Gemfile to include redcarpet:

1
2
3
4
5
  gem 'rdiscount', '~> 2.0.7'
  gem "charlock_holmes", "~> 0.6.9.4"
  gem "github-linguist", "~> 2.4"
  gem 'redcarpet', '~> 2.1.1'
  gem 'pygments.rb', '~> 0.3.7'
And update the Gems:
1
2
cd /build32/octopress
bundle install

Test. Save this code into a file in (for example) /tmp/test.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
require 'rdiscount'
require 'charlockholmes'
require 'escape_utils'
require 'pygments'
require 'yaml'
require 'linguist/classifier'
require 'linguist/samples'
require 'linguist/file_blob'
require 'redcarpet'

puts "Ruby test"

#puts Pygments.highlight(File.read(FILE_), :lexer => 'ruby')

@rdiscount_extensions = "smart"

content = "Some text"
rd = RDiscount.new(content, @rdiscount_extensions)
html = rd.to_html

puts html

detection = CharlockHolmes::EncodingDetector.detect(html)

puts detection

fb = Linguist::FileBlob.new("c:\Ruby193\devkit\dk.rb")
puts fb.language.name

markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :space_after_headers => true)
puts markdown.render("This is *bongos c++ int main() { return 0 }, indeed.")

And run the test:

1
2
3
4
5
6
7
$ ruby test.rb
...
Ruby test
<p>Some <em>text</em></p>
{:type=>:text, :encoding=>"ISO-8859-2", :confidence=>40, :language=>"cs"}
Ruby
<p>This is <em>bongos</em> <code>c++ int main() { return 0 }</code>, indeed.</p>

Now modify _config.yml for octopress to generate redcarpet markdown:

1
2
3
markdown: redcarpet
redcarpet:
  extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data"]

Modify the post created above to include some github markdown, e.g. (note: replace last [backtick]…):

1
Some text
c++ int main() { return 0; } “[backtick]

Some more text.

1
2

And regenerate:
rake generate “` You should now have syntax highlighted code blocks!

Installing Ruby 1.9.3 in Windows With MingW

Published on:
Tags: mingw, ruby, windows

This is the second of three posts describing how to install Ruby 1.9.3 native MingW environment. It's much simpler to use Ruby Installer to do this but if you want all the details of how to do it natively, read on…

If you 're wondering why I did this, I wanted to use redcarpet/github-linguist for markdown in Octopress; there's a dependency on the charlock_holmes Gem that requires native code libraries (file, ICU), some of which it needs to build. I couldn't figure out how to make the Ruby Installer do this and I wanted to understand the process, so I did the whole thing from scratch. The first part is here and the final part is here.

Setup Msys base system.

Download and build libyaml. Yaml requires a built DLL and needs it to be available so we build that manually (instructions for hacking a ruby gem very useful knowledge for this). Not sure if the first part to build and install the static libraries is required. We're hard coding the target location, but just need to get it to work…:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cd /build32
wget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz
tar zxvf yaml-0.1.4.tar.gz
cd yaml-0.1.4
./configure --prefix=/mingw CFLAGS="-DYAML_DECLARE_STATIC" 
make && make install
cd src
gcc -c -I../include -I../ -DHAVE_CONFIG_H -DYAML_DECLARE_EXPORT api.c
gcc -c -I../include -I../ -DHAVE_CONFIG_H -DYAML_DECLARE_EXPORT dumper.c
gcc -c -I../include -I../ -DHAVE_CONFIG_H -DYAML_DECLARE_EXPORT emitter.c
gcc -c -I../include -I../ -DHAVE_CONFIG_H -DYAML_DECLARE_EXPORT loader.c
gcc -c -I../include -I../ -DHAVE_CONFIG_H -DYAML_DECLARE_EXPORT parser.c
gcc -c -I../include -I../ -DHAVE_CONFIG_H -DYAML_DECLARE_EXPORT reader.c
gcc -c -I../include -I../ -DHAVE_CONFIG_H -DYAML_DECLARE_EXPORT scanner.c
gcc -c -I../include -I../ -DHAVE_CONFIG_H -DYAML_DECLARE_EXPORT writer.c
gcc -shared -o yaml.dll api.o dumper.o emitter.o loader.o parser.o reader.o scanner.o writer.o -Wl,--out-implib,libyaml.dll.a -Wl,--output-def,libyaml.def
cp yaml.dll /mingw/bin
cp libyaml.def libyaml.dll.a /mingw/lib
cd ..
<!– more –> Download and build libffi:
1
2
3
4
5
6
7
8
cd /build32
wget ftp://sourceware.org/pub/libffi/libffi-3.0.13.tar.gz
wget http://www.linuxfromscratch.org/patches/blfs/svn/libffi-3.0.13-includedir-1.patch
tar zxvf libffi-3.0.13.tar.gz
cd libffi-3.0.13
patch -Np1 < ../libffi-3.0.13-includedir-1.patch
./configure --prefix=/mingw
make && make install
Download and build gdbm
1
2
3
4
5
6
7
8
cd /build32
wget ftp://ftp.gnu.org/gnu/gdbm/gdbm-1.10.tar.gz
tar zxvf gdbm-1.10.tar.gz
wget https://raw.github.com/luislavena/knapsack-recipes/master/gdbm/1.10/0001-Mingw-port-of-gdbm-1.10.patch --no-check-certificate
cd gdbm-1.10
patch -p1 < ../0001-Mingw-port-of-gdbm-1.10.patch
./configure --prefix=/mingw --enable-shared
make && make install
Download and build termcap:
1
2
3
4
5
6
cd /build32
wget http://ftp.gnu.org/gnu/termcap/termcap-1.3.1.tar.gz
tar zxvf termcap-1.3.1.tar.gz
cd termcap-1.3.1
./configure --prefix=/mingw --enable-static
make && make install
Download and build readline:
1
2
3
4
cd /build32
wget ftp://ftp.cwru.edu/pub/bash/readline-6.2.tar.gz
tar zxvf readline-6.2.tar.gz
cd readline-6.2
Patch rldefs.h and util.c to make params const char. Patch _rl_strnicmp in util.c so that do{}while has trailing ';':
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
diff -rupN readline-6.2.orig//rldefs.h readline-6.2//rldefs.h
--- readline-6.2.orig//rldefs.h   2009-01-04 19:32:33 +0000
+++ readline-6.2//rldefs.h    2013-09-19 09:38:32 +0100
@@ -79,8 +79,8 @@ extern char *strchr (), *strrchr ();
 #define _rl_stricmp strcasecmp
 #define _rl_strnicmp strncasecmp
 #else
-extern int _rl_stricmp PARAMS((char *, char *));
-extern int _rl_strnicmp PARAMS((char *, char *, int));
+extern int _rl_stricmp PARAMS((const char *, const char *));
+extern int _rl_strnicmp PARAMS((const char *, const char *, int));
 #endif
 
 #if defined (HAVE_STRPBRK) && !defined (HAVE_MULTIBYTE)
diff -rupN readline-6.2.orig//util.c readline-6.2//util.c
--- readline-6.2.orig//util.c 2010-05-30 23:36:02 +0100
+++ readline-6.2//util.c  2013-09-19 09:38:57 +0100
@@ -369,10 +369,10 @@ _rl_strpbrk (string1, string2)
    doesn't matter (strncasecmp). */
 int
 _rl_strnicmp (string1, string2, count)
-     char *string1, *string2;
+     const char *string1, *string2;
      int count;
 {
-  register char *s1, *s2;
+  register const char *s1, *s2;
   int d;
 
   if (count <= 0 || (string1 == string2))
@@ -389,7 +389,7 @@ _rl_strnicmp (string1, string2, count)
         break;
       s2++;
     }
-  while (--count != 0)
+  while (--count != 0);
 
   return (0);
 }
@@ -397,9 +397,9 @@ _rl_strnicmp (string1, string2, count)
 / strcmp (), but caseless (strcasecmp). /
 int
 _rl_stricmp (string1, string2)
-     char *string1, *string2;
+     const char *string1, *string2;
 {
-  register char *s1, *s2;
+  register const char *s1, *s2;
   int d;
 
   s1 = string1;
Build:
1
2
3
patch -p1 < ../readline-6.2.patch
./configure --prefix=/mingw --enable-static
make && make install
Download and install openssl:
1
2
3
4
5
6
7
8
cd /build32
wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz
tar zxvf openssl-1.0.1e.tar.gz
cd openssl-1.0.1e
perl Configure mingw no-shared no-asm --prefix=/mingw
make depend
make
make install
Download and install ruby (note: dbm, pty and syslog will fail to configure, this is ok on Windows…no others should fail). For some reason we need the drive/path to the install location or it doesn't install any files…:
1
2
3
4
5
6
7
cd /build32
wget http://cache.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p448.tar.gz
tar zxvf ruby-1.9.3-p448.tar.gz
cd ruby-1.9.3-p448
./configure --prefix=C:/mingw/local32 --enable-shared --disable-install-doc
make
make install
Test…should output the version, e.g.:
1
2
$ ruby -v
ruby 1.9.3p448 (2013-06-27 revision 41675) [i386-mingw32]
Download and install rubygems:
1
2
3
4
5
cd /build32
wget http://production.cf.rubygems.org/rubygems/rubygems-2.0.7.tgz
tar zxvf rubygems-2.0.7.tgz
cd rubygems-2.0.7
ruby setup.rb 
Test (final part of this useful post):
1
2
3
4
5
$ gem list omniauth$ -r --all

** REMOTE GEMS ***

omniauth (1.1.4, 1.1.3, 1.1.2, 1.1.1, 1.1.0, 1.0.3, 1.0.2, 1.0.1, 1.0.0, 0.3.2, 0.3.0, 0.2.6, 0.2.5, 0.2.4, 0.2.3, 0.2.2, 0.2.1, 0.2.0, 0.1.6, 0.1.5, 0.1.4, 0.1.3, 0.1.2, 0.1.1, 0.1.0, 0.0.5, 0.0.4, 0.0.3, 0.0.1)
It works!

Setting Up Mingw Ready for Ruby 1.9.3 Install

Published on:
Tags: mingw, windows

This is the first of three posts describing how to install Ruby 1.9.3 native MingW environment. It's much simpler to use Ruby Installer to do this but if you want all the details of how to do it natively, read on…

If you 're wondering why I did this, I wanted to use redcarpet/github-linguist for markdown in Octopress; there's a dependency on the charlock_holmes Gem that requires native code libraries (file, ICU), some of which it needs to build. I couldn't figure out how to make the Ruby Installer do this and I wanted to understand the process, so I did the whole thing from scratch. The second part is here and the final part is here.

This is a prerequisite for installing Ruby 1.9.3 in a native Mingw environment on Windows.

Download and run mingw installer: mingw-get-setup.exe Select 'mingw-developer-toolkit' and apply changes. This installs a default msys and default packages. Start msys.bat (usually in C:\MinGW\msys\1.0).

Edit /etc/fstab to add:

1
2
3
c:/mingw        /mingw
c:/mingw/local32        /local32
c:/mingw/build32        /build32
<!– more –> Create a directory for app install and a build directory (similar to instructions for installing a base system)
1
2
3
4
5
6
mkdir /usr/local
mkdir /usr/local/bin
mkdir /c/mingw/opt
mkdir /c/mingw/build32 /c/mingw/local32
mkdir /c/mingw/opt/bin /local32/{bin,etc,include,lib,share}
mkdir /local32/lib/pkgconfig
Create a profile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cat > /local32/etc/profile.local << "EOF"
#
# /local32/etc/profile.local
#

alias dir='ls -la --color=auto'
alias ls='ls --color=auto'

PKG_CONFIG_PATH="/local32/lib/pkgconfig"
CPPFLAGS="-I/local32/include"
CFLAGS="-I/local32/include"
CXXFLAGS="-I/local32/include"
LDFLAGS="-L/local32/lib"
export PKG_CONFIG_PATH CPPFLAGS CFLAGS CXXFLAGS LDFLAGS

PATH="/local32/bin:$PATH"

# package build directory
LOCALBUILDDIR=/build32
# package installation prefix
LOCALDESTDIR=/local32
export LOCALBUILDDIR LOCALDESTDIR

EOF
and a user profile to load it:
1
2
3
4
5
6
cat >> /etc/profile << "EOF"
if [ -f /local32/etc/profile.local ]; then
        source /local32/etc/profile.local
fi

EOF
Remove unwanted automake's (following these Mingw install instructions):
1
mingw-get remove automake1.4 automake1.5 automake1.6 automake1.7 automake1.8
'exit' from all msys shells and restart. You should see the following mounts:
1
2
3
4
5
6
$ mount
...
c:\mingw\build32 on /build32 type user (binmode)
c:\mingw\local32 on /local32 type user (binmode)
c:\mingw on /mingw type user (binmode)
...
Add some additional packages:
1
2
3
mingw-get install base bzip2 expat gcc-g++ gettext gmp libarchive libpdcurses libpopt libunistring lua mingw-utils mpc mpfr pdcurses pkginfo pthreads-w32 zlib

mingw-get install msys-bash msys-bison msys-core-dev msys-crypt msys-cygutils msys-inetutils msys-unzip msys-wget msys-zip  
(optional) Run the mingw installer and mark mingw-tcl and mingw-tk for installation and apply changes. Check they are there:
1
2
cd /mingw
find . -name "tk.h"