Building PostGIS using Visual C++

I don’t like MinGW. I’ve been dreaming about building PostGIS using Visual C++ – the native development toolset for Windows platform – without being forced to install Unix-like environment inside Windows. Finally, I’ve got motivated enough and decided to make my dreams reality, so here is the story.

First, I collected all run-time dependencies required by PostGIS. I intentionally used the word run-time to indicate I’m not going to install MinGW neither Cygwin or any other GCC-for-Windows package. GNU make is also not required.

I use PostGIS source code from trunk in the Subversion repository.

Dependencies

There are only 3 software packages required:

  1. PostgreSQL 8.3.6official Win32 binaries and source code
  2. GEOS – build from sources, it’s safe to grab SVN trunk
  3. PROJ.4 – also build from sources and also from SVN trunk

I installed the PostgreSQL 8.3.6 without PostGIS extensions, as I’m going to provide my own :-), using default location c:\Program Files\PostgreSQL\8.3. The source code of PostgreSQL 8.3.6 went to d:\dev\postgresql\postgresql-8.3.6.

Short note on directories layout using for projects downloaded directly from repositories. Root path of source tree of each project have the same layout: D:\dev\PROJECT\_svn\trunk. For Visual Studio projects, these paths are defined as macros in postgis.vsprops (Visual C++ Property Sheet), so it should be easy to redefine them without any need to hack other project settings like Additional Include Directories and others.

Building GEOS using Visual C++ is quite an easy task:

D:\dev\geos\_svn\trunk> svn co http://svn.osgeo.org/geos/trunk .
D:\dev\geos\_svn\trunk> autogen.bat
D:\dev\geos\_svn\trunk> nmake /f makefile.vc

Building PROJ.4 is even easier:

D:\dev\proj4\_svn\trunk> svn co http://svn.osgeo.org/metacrs/proj/trunk/proj .
D:\dev\proj4\_svn\trunk> nmake /f makefile.vc

There is no need to copy any files from GEOS or PROJ.4 tree anywhere. DLL binaries (only) will be copied later.

Patching PostGIS sources

Now, it’s time to get ready for building PostGIS DLL.

After I took up the idea of building PostGIS using Visual C++, I realized there are number fixes required. Some of them have been already submitted to the SVN trunk: #125, #128, r3828, r3848, r3846 .

However, more patches were required as well as I had to prepare complete solution and projects for Visual Studio 2005. The last revision of PostGIS SVN trunk I used to build it using Visual C++ was r3938. In order to make it easier to discover what’s the complete set of changes required by Visual C++ here are two packages:

This is status summary reported by svn for my working copy of PostGIS trunk:

D:\dev\postgis\_svn\trunk>svn st
A      postgis_config.h.in.vc
M      liblwgeom\lex.yy.c
M      liblwgeom\wktparse.tab.c
M      liblwgeom\wktparse.lex
M      liblwgeom\vsprintf.c
M      liblwgeom\wktparse.y
A      platform
A      platform\win32
A      platform\win32\ChangeLog.txt
A      platform\win32\inttypes.h
A      platform\win32\README.txt
A      platform\win32\stdint.h
A      platform\win32\sys
A      platform\win32\sys\param.h
A      postgis\postgis.def
A      postgis\postgis.sql.vc
A      build
A      build\msvc80
A      build\msvc80\liblwgeom
A      build\msvc80\liblwgeom\liblwgeom.vcproj
A      build\msvc80\postgis.sln
A      build\msvc80\postgis.vsprops
A      build\msvc80\postgis_dll
A      build\msvc80\postgis_dll\postgis_dll.vcproj
A      build\msvc80\bootstrap
A      build\msvc80\bootstrap\bootstrap.vcproj
D:\dev\postgis\_svn\trunk>

Building PostGIS binaries

I think the easiest way to try this building procedure is to download the package with my working copy and unpack it somewhere on your disk. Alternatively, you can grab PostGIS sources directly from SVN, then diff & patch (manually) to apply changes from my working copy. The package includes Visual Studio solution located in trunk\build\msvc80 subdirectory. Here are the steps:

  1. Open solution file postgis.sln in Visual Studio 2005 or Visual Studio 2008 (in this case, projects will be converted automatically, just accept it).
  2. Go to Property Manager tab and double click on postgis.vsprops sheet.
  3. Expand Common Properties and go to User Macros dialog.
  4. Here, you need to verify and update (if your paths are different) four macros with locations of the PostGIS dependencies. Here are the macros with paths I used (screenshot):

    GEOS_SRC_ROOT = D:\dev\geos\_svn\trunk
    PROJ4_SRC_ROOT = D:\dev\proj\_svn\trunk
    POSTGRESQL_SRC_ROOT = D:\dev\postgresql\postgresql-8.3.6
    POSTGRESQL_ROOT = C:\Program Files\PostgreSQL\8.3

    Do NOT change any other macros than the four listed above, especially do not change POSTGIS_DLL_NAME macro.

  5. Click OK to accept your changes and save the Property Sheet. It’s a good idea to click on Save button on the small toolbar of Proprety Manager.

Everything is configured and ready to build: Build -> Build Solution or hit F7 (I tested only Debug build). Visual C++ compiler will flood the IDE Output window with nearly 1600 warnings. It is (probably) safe to ignore them. If you are lucky, after a few minutes postgis-1.4.dll binary is ready inside trunk\build\msvc80\debug directory.

Installing PostGIS extension

Now, it’s time to install all binaries:

  1. Install GEOS libraries (DLL):
    D:\dev\geos\_svn\trunk>copy source\geos.dll "c:\Program Files\PostgreSQL\8.3\bin"
    D:\dev\geos\_svn\trunk>copy source\geos_c.dll "c:\Program Files\PostgreSQL\8.3\bin"
  2. Install PROJ.4 library (DLL):
    D:\dev\proj\_svn\trunk>copy src\proj.dll "c:\Program Files\PostgreSQL\8.3\bin"
  3. Intall PostGIS library (DLL):
    D:\dev\postgis\_svn\trunk>copy build\msvc80\debug\postgis-1.4.dll "c:\Program Files\PostgreSQL\8.3\lib"

Double check if all libraries have been delivered:

C:\Program Files\PostgreSQL\8.3>ls -l lib\postgis-1.4.dll
-rw-rw-rw-  1 mloskot 0 770048 2009-03-29 02:10 lib\postgis-1.4.dll
C:\Program Files\PostgreSQL\8.3>ls -l bin\geos*
-rw-rw-rw-  1 mloskot 0 1236992 2009-03-28 21:02 bin\geos.dll
-rw-rw-rw-  1 mloskot 0 1056768 2009-03-28 21:02 bin\geos_c.dll
C:\Program Files\PostgreSQL\8.3>ls -l bin\proj.dll
-rw-rw-rw-  1 mloskot 0 233472 2009-03-29 00:58 bin\proj.dll

(don’t be confused seeing ls command, I have GnuWin32 installed.

The Moment of Truth

As a shortcut, I generated postgis.sql on my Linux box (based on SVN trunk r3938 too) and copied to trunk\postgis\postgis.sql.vc. This file is included in the postgis-r3938-msvc-build.zip as well as in the patch. The trunk\postgis\postgis.sql.vc refers to postgis-1.4 library. This is the reason why I warned above to not to change value of POSTGIS_DLL_NAME macro. Visual Studio automatically make a copy of the SQL script with new name trunk\postgis\postgis.sql (see configuration of bootstrap project).

All components are in place: binaries installed in PostgreSQL 8.3.6 directory, main SQL script prepared in trunk\postgis\postgis.sql and original version of trunk\spatial_ref_sys.sql file provided by SVN trunk. Moving on to create PostGIS-enaled database called test:

C:\Program Files\PostgreSQL\8.3>createdb -E UTF-8 -O mloskot test

It seems it’s not necessary to first enable PL/pgSQL langauge:

C:\Program Files\PostgreSQL\8.3>createlang plpgsql test
createlang: language "plpgsql" is already installed in database "test"

So, you can skip to loading PostGIS extensions:

C:\Program Files\PostgreSQL\8.3>psql -d test -f d:\dev\postgis\_svn\trunk\postgis\postgis.sql
BEGIN
psql:d:/dev/postgis/_svn/trunk/postgis/postgis.sql:34: NOTICE:  type "spheroid" is not yet defined
DETAIL:  Creating a shell type definition.
...
CREATE FUNCTION
psql:d:/dev/postgis/_svn/trunk/postgis/postgis.sql:2201: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "spatial_ref_sys_pkey" for table "spatial_ref_sys"
CREATE TABLE
psql:d:/dev/postgis/_svn/trunk/postgis/postgis.sql:2219: NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "geometry_columns_pk" for table "geometry_columns"
CREATE TABLE
...
CREATE FUNCTION
COMMIT

and definition of Spatial Reference Systems:

C:\Program Files\PostgreSQL\8.3>psql -d test -f d:\dev\postgis\_svn\trunk\spatial_ref_sys.sql
BEGIN
INSERT 0 1
...
INSERT 0 1
COMMIT
VACUUM

If every step explained above succeeded, the test database has been enabled with PostGIS features. Simple version check can confirm that it is:

C:\Program Files\PostgreSQL\8.3>psql -d test -c "SELECT postgis_version();"
            postgis_version
---------------------------------------
 1.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
(1 row)

For development purposes, to be sure in 100% I use my own build of PostGIS, I redefined value of build date macro in trunk\postgis_config.h.in.vc:

#define POSTGIS_BUILD_DATE "2009-03-29 (MSVC)"

and MSVC tag is reported as expected:

C:\Program Files\PostgreSQL\8.3>psql -d test -c "SELECT postgis_lib_build_date();"
 postgis_lib_build_date
------------------------
 2009-03-29 (MSVC)
(1 row)

Testing Visual C++ build of PostGIS

I have not run complete set of the regression tests. Chances are, that some functions do not work as expected or they may even crash! However, as a basic test I’ve run regress.sql on my installation. Here are file swith test output and errors log.

Summary

It works! The PostGIS sources (r3938 + patches) compile using Visual C++ compiler (tested only with 8.0). The PostGIS binaries link against all run-time dependencies. Basic tests run successfully.

Apparently, it’s not the end. Next steps include running the complete regression tests package. Also, I think it’s a good idea to rewrite Visual Studio solution and projects to NMAKE makefiles or – even better – prepare CMake configuration, which could serve well in both environments, Unix and Windows. If there is volunteer willing to prepare configuration for these builders, I very eager to help in testing it using Visual Studio 2005 and 2008. If it will be CMake, then I can test it on Linux too.

By the way, looks like we’re getting closer to make WKT Raster build-able using Visual C++ for Windows :-)

8 Responses to “Building PostGIS using Visual C++”

  1. GIS_CORE says:

    I was able to compile and successfully create the data base as stated above, many thanks to Mateusz Loskot.
    I am trying to add a new function to the dll library, however, after successfully compiling the postgis with the new function added, copying the dll back to the lib directory, the function faild to be recognized or added.
    Would you please assist me to add my own functions correctly to the library so they will be recognized, I mean if there is some kind of steps to follow or the files needs to be modified in order to add my new function.

    Thanks

  2. mloskot says:

    Hi GIS_CORE,
    I’m glad you’ve found it helpful.

    I suppose that you have not added the new function to postgis/postgis.def file. I configured PostGIS build to export functions using DEF file.

    BTW, if you’ll find a bug or something misconfigurated, reports are welcome.

  3. GIS_CORE says:

    I have added the function in the definition, the function can be added, however when trying to execute, the following error comes

    ERROR: invalid memory alloc request size 4294967293

    ********** Fehler **********

    ERROR: invalid memory alloc request size 4294967293
    SQL Status:XX000

    my function is really simple and here it is

    PG_FUNCTION_INFO_V1(CORE_TEST);
    Datum CORE_TEST(PG_FUNCTION_ARGS)
    {
    /* The macros for FLOAT8 hide its pass-by-reference nature. */
    float8 arg = PG_GETARG_FLOAT8(0);

    PG_RETURN_FLOAT8(arg + 1.0);

    }

    should i modify any other files.
    Thanks

  4. mloskot says:

    I think this error is not related to the function you added. It’s something wrong with PostGIS installation. Perhaps PostgreSQL vs PostGIS vs GEOS versions are incompatible.
    Have you checked if PostGIS functions work, like version reporting ones?

    There is something about similar problem on PostGIS mailing list.
    I really doubt this simple function causes problems, especially that very similar function is presented in the PostgreSQL manual.

  5. GIS_CORE says:

    I have checked several function of the postgis that i build using Mateusz Loskot build solution, all works fine. the problem are if i create any a new function similar to the examples in the Postgresql documentation

    http://www.postgresql.org/docs/8.3/interactive/xfunc-c.html

    the functions bring error when i create it in the database. the only data type that works with no error are int32.

    Is there any direction to solve the problem, its the same problem i faced when i try to create GIS function for postgresql using MinGW. the function i wrote like the above example is exactly from the Postgresql documentation.

  6. mloskot says:

    If you are using PostgreSQL 8.3, what I’ve understood from the fact you are reading docs for 8.3 and these functions do not work for you with MinGW buid as well as Visual C++ build, then something is wrong with these functions in the manual or you are doing something wrong.

    Anyway, it seems to has nothing to do with Visual C++ build I explained in this post. Likely, you need some support about PostgreSQL, so write to the mailing list or step in IRC channel #postgresql and ask PostgreSQL folks.

    Sorry, but I’m not here to provide you with general support about PostgreSQL, there are community tools for that purpose.

  7. baluku says:

    hi gurus,
    i have trouble compiling a c style program ( filename with extension cpp) written for visual C++.
    When i added the following #includes,
    >>> #include “spi.h”
    >>> #include “trigger.h”
    compilation errors say “error C2899: typename cannot be used outside a template declaration”.
    I need the above includes for postgres triggers.

    If the above #includes were removed, leaving behind
    >>>#include “postgres.h”
    >>>#include “fmgr.h”
    then there is no compilation error.

    A check on msdn reveals that the error is because in visual c++, the word “typename” is a keyword.
    Unfortunately, it happens ( coincidence) that postgres also uses the word “typename” in its header files, as in below –
    typedef struct ColumnDef
    {
    NodeTag type;
    char *colname; /* name of column */
    TypeName *typename; /* type of column */

    }

    I have thought of making visual c++ of not recognizing “typename” as a keyword, say, by turning some compiler options to forced c mode ( rather than c++).
    Is there indeed such an option? If not, is there a way to resolve my problem as described above?

    thanks and regards,
    baluku

  8. mloskot says:

    Try to compile your program as C not C++

Leave a Reply