Build instructions for Microsoft Visual C 11 (2012)

Max Satula edited this page Jul 6, 2014 · 7 revisions

Goal

The procedure documented here will produce a Ledger 3.0 executable that will run natively under all recent versions of Microsoft Windows. In order to support both 32-bit and 64-bit operating systems, a 32-bit executable will be built.

The Microsoft Visual C++ 11 compiler will be used (comes with Visual Studio 2012). Other Microsoft compilers might work, but I haven't tried them.

These instructions assume that you are familiar with the operation of Visual Studio. Also, you are probably pretty patient.

Another windows build process can be found at ledger-windows-build.

Command prompt

Whenever a compiler command line is used in the procedure below, use the "VS2012 x86 Native Tools Command Prompt" that is found in the Start Menu in the Visual Studio 2012 group. This will ensure that the correct compiler is used.

CMake

The CMake build system used by ledger is able to produce project files for Visual Studio 2012, which is a big help.

So, first obtain CMake for windows. It is available at http://www.cmake.org/cmake/resources/software.html (Choose "Binary distributions", Win32 installer.)

Install it. Since CMake will be invoked from the command line, choose one of the installation options that adds CMake to the system path, or plan to manually add it to the system path before you build ledger.

Boost

Ledger depends on the C++ Boost libraries. The current version of the Boost libraries is not available as a binary download that is compatible with Visual C++ 11. (Boost Pro offers some slightly out-of-date binary installers at http://www.boostpro.com/download/, but these will install Boost in a hard-coded location depending on your Visual C++ version, and Visual C++ 11 is not one of your choices.)

So I decided to build the Boost libraries from source. It would probably be possible to download a select set of libraries, but I chose to "cut to the chase" and download the whole Boost library from http://www.boost.org/users/download/

Although the CMakeLists file at the top of the ledger source tree will eventually try to find Boost version 1.46.0 or later, ledger does not currently compile successfully against 1.46.0. I built ledger against version 1.53.0, which is the most current version available at this time.

I found it convenient to locate all of the library dependencies under a single ledger-dependencies parent directory. You will be jumping around between these directories a lot.

Unzip the Boost zip file in that directory. Note the path to this directory. Later, you will need to tell CMake about this path as BOOST_ROOT (more on this later.)

From a Visual Studio command prompt run bootstrap.bat, which will compile the "b2" build tool that Boost uses.

Relative to the root of the boost directory, edit tools/build/v2/user-config.jam. Find the line that says "# using msvc : 10.0 ;". Uncomment that line (remove the leading # sign) and change the 10.0 to an 11.0.

From the boost root directory, run each of the following commands:

b2 link=shared threading=multi --layout=tagged
b2 link=shared threading=multi

There will be a lot of warnings that you are using an unknown compiler version. However, these do not affect the build results.

This will result in a bunch of library files under the boost root directory /stage/lib. Each library will appear twice with two different filenames, for example:

boost_atomic-mt.dll
boost_atomic-vc110-mt-1_53.dll

The first version of each library (with the simplified filename) is produced by the b2 invocation with "--layout=tagged".

Surely you are wondering why you need two versions of every library. CMake will not be able to find the boost libraries unless it sees the versions with the simplified filenames. This ought to be enough. Unfortunately, when you actually compile ledger, if you only have the libraries with the simplified filenames, you will get a linker error indicating that the linker is looking for the file with the non-simplified filename. I have no idea why this happened, but I had 300MB of disk space to spare for an extra copy of every library, so I decided not to fight it.

Also, at run-time ledger will dynamically link to the non-simplified filenames.

Tip: When using b2, if you have a processor with multiple cores, use the -j option to specify how many cores you want to use during the build process. For example, if you have four cores, specify -j4.

vsyasm (a non-standard assembler)

The MPIR library that is coming up in a future section requires a non-standard assembler to build. Apparently the authors of these numeric libraries are very focused on performance, and this assembler produces high-performance code for x86.

vsyasm can be downloaded at http://yasm.tortall.net/Download.html. Choose Win32 VS2010 zip. Extract this zip file, and copy the four files starting with vsyasm into your Visual C++ bin directory (e.g. C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin).

MPIR (Drop-in replacement for GMP)

Ledger relies on GMP, but some Internet searching revealed that it is very hard to get GMP built using MSVC.

However, thanks to this page produced by Brian Gladman (http://gladman.plushost.co.uk/oldsite/computing/gmp4win.php), I found an alternative library named MPIR that can be built with MSVC, and is drop-in compatible with GMP.

The MPIR web page is at http://mpir.org/. I downloaded the source tarball from that page and extracted it to my ledger-dependencies directory. Rename the parent mpir directory to just "mpir". You will need to tell CMake that this is GMP_PATH (more on this later.)

Brian Gladman has provided a Visual Studio project that allows this library to be built, but it is a Visual Studio 2010 solution. I couldn't get it to work, but not because it was for 2010 instead of 2012. There were plenty of other problems.

Instead, in the win/ subdirectory of the MPIR root directory, there are files named configure.bat and make.bat that work just fine. Edit configure.bat and change all occurrences of VS90COMNTOOLS to VS110COMNTOOLS.

Then run the following commands

configure ABI=32
make

When this finished, in the top-level directory will be a file named mpir.h. There may or may not also be a file named gmp.h (I didn't note this.) If there isn't, copy mpir.h to gmp.h.

In the mpir/win directory, there is now an mpir.lib. Copy that to gmp.lib in the same directory. You will need to tell CMake that this is GMP_LIB (more on this later.)

MPFR

Again, thanks to Brian Gladman at http://gladman.plushost.co.uk/oldsite/computing/gmp4win.php, I got a head start on an MPFR built.

MPFR can be downloaded from http://www.mpfr.org/mpfr-current/#download. Extract it to the same parent directory where you extracted mfir -- the mfir and mpfr directories must be siblings of each other.

Then, Brian Gladman has produced a Visual Studio 2010 project that can build this code. It is available at http://gladman.plushost.co.uk/oldsite/computing/mpfr-3.0.0.build.vc10.zip. Extract that zip file to somewhere that is not the MPFR directory. You can take a shot at reading the readme.vc10.txt file to figure out what you are really supposed to do. It appears that you are supposed to copy the Visual Studio project files into the MPFR directory tree, and rename the mpfr directory tree to just "mpfr". You will need to tell CMake that this is MPFR_PATH (more on this later.)

However, this by itself does not work. The project files refer to the MPFR source code at the ../.. path, and there is no source code there. The project will not build this way.

So I moved all of the files and directories from the mpfr/src up one level to the mpfr directory.

Then you will also have to hand-modify lib_mpfr.vcxproj as a text file, and find all of the references to config.h, gmp-impl.h, and gmp.h so that they point to files in ......\mpir. For example, the reference to gmp-impl.h should look like:

<ClInclude Include="..\..\..\mpir\gmp-impl.h" />

When you open lib_mpfr.sln, it will be converted from a Visual Studio 2010 project to a Visual Studio 2012 project without difficulty.

Finally, build the Release configuration of lib_mpfr. This will result in a library at mpfr/lib/Win32/Release/mpfr.lib. You will need to tell CMake that this is MPFR_LIB (more on this later.)

Ledger

That is all of the dependencies that you will be able to put together on the Windows platform. Ledger can do without the rest of them. So now it is time to build ledger.

The source code for Ledger can be cloned from github (https://github.com/ledger/ledger).

From a Visual Studio command prompt, cd to the root of the ledger source tree.

Edit CMakeLists.txt in that directory, and add lines like this near the top of the file:

set(GMP_PATH F:\\Downloads\\DevelopmentTools\\mpir)
set(GMP_LIB F:\\Downloads\\DevelopmentTools\\mpir\\win)
set(MPFR_PATH F:\\Downloads\\DevelopmentTools\\mpfr)
set(MPFR_LIB F:\\Downloads\\DevelopmentTools\\mpfr\\build.vc10\\lib\\Win32\\Release)

But you should substitute your own paths, as I reminded you to note in the previous MPIR and MPFR sections.

At the command prompt, type

set BOOST_ROOT=(the path to where you extracted the boost source as I reminded you in the Boost section)

Now run the command

cmake -G "Visual Studio 11"

I really hope this goes well for you.

There will be some messages about missing components, but only optional ones. At the end hopefully you will see a success message. If there is an ALL_BUILD.vcxproj file in your ledger directory, you're ready to build.

Almost. A file named system.hh has been generated in the ledger directory. There are a few defines near the top of that file that Visual C++ does not like:

#define HAVE_REALPATH            
#define HAVE_GETPWUID            
#define HAVE_GETPWNAM            
#define HAVE_ISATTY              1

The first three need to have a value of 0. And HAVE_ISATTY doesn't work, even though CMake thinks it found isatty. So that needs to change to a 0 to. The end result is:

#define HAVE_REALPATH            0
#define HAVE_GETPWUID            0
#define HAVE_GETPWNAM            0
#define HAVE_ISATTY              0

Open ALL_BUILD.vcxproj. Select the Release build configuration.

If you have multiple cores and would like to save yourself some time, edit the project properties for libledger. Under Configuration Properties, C/C++, General, choose Yes for the Multi-processor Compilation option.

Edit the project properties for ledger and for MathTests. For each one, under Linker, Advanced, choose No for "Image Has Safe Exception Handlers".

For each one, under Linker, Input, Additional dependencies, add F:\Downloads\DevelopmentTools\mpfr\build.vc10\lib\Win32\Release\mpfr.lib and F:\Downloads\DevelopmentTools\mpir\win\gmp.lib (correcting for the paths you noted for GMP_LIB and MPFR_LIB.)

Finally, build the solution.

If it worked, under the top-level ledger directory there is now a Release directory containing ledger.exe.

Running

This executable is statically linked to the MPIR and MPFR libraries, but it is dynamically linked to the boost libraries. For this executable to run, the system must be able to find the necessary boost libraries. One way to do that would be to copy them from the boost/stage/lib directory into the ledger/Release directory. That's what I did.

You only need three libraries, but they must have the verbose filenames, not the simplified filenames that CMake required in order to find boost in the first place.

The three files are:

boost_filesystem-vc110-mt-1_53.dll
boost_regex-vc110-mt-1_53.dll
boost_system-vc110-mt-1_53.dll

Once you have those three files, you should be able to run

ledger --version

Or any of your other favorite ledger commands, and see something good.

Instructions are current as of June 2013

Open-source projects change over time. So it is probably important to note that these instructions were written in June 2013.

The ledger source code was obtained directly from github and was at version 3.0 20130529. See my notes about the necessary source code changes in the ledger section above.

The boost libraries were at version 1.53.0.

The MPIR library was at version 2.6.0.

The MPFR library was at version 3.1.2.