Thursday, June 18, 2015

build glib in Visual Studio

Problem.


I've needed to build glib (actually finally I want to get libxml++, and glib is one of dependencies). Will do it static library with static runtime (/MT and /MTd) x64. Firstly I wanted to build only part of glib, but finally I built whole library successfully.

Tools and versions (my case):

  • Visual Studio 2013
  • Python (I have python 2.7)
  • Perl (I have ActivePerl x64) 
  • git client
  • x32 cygwin
  • far manager
  • notepad++
  • Compiled intl (version 20090911) in Visual Studio 2013 - [link]
  • Compiled pcre (version 8.37) in Visual Studio 2013 - [link]
  • Compiled libffi (version 3.2.1) in Visual Studio 2013 - [link]
  • Compiled zlib (version 1.2.8) in Visual Studio 2013 - [link]
glib version - it's near 2.45.3
Date: (02.07.2015 14:06:17)
Commit hash: e337fe31637fe868ab94b488caf9b4898a2a1040
just last commit from git for the moment of compilation.

Action


1. git clone git://git.gnome.org/glib

2. open x32 cygwin - Cygwin.bat

3. go to dir with glib sources

4. replace all '\r' to '' in files (I did it in notepad++):
  • autogen.sh
  • configure.ac
5. exec in cygwin:
  • ./autogen.sh
  • cd ./gio
  • make
it must finishes with error, but it will create file 'gdbus-daemon-generated.c' - it's everything what we need.
Now we don't need cygwin - can close it.

6.exec python script (I did it with python 2.7), located in 'glib/build/win32':
python setup.py --perl=C:\Perl64\bin\perl.exe

it's like ./configure. For example, it copies config.h.win32 to config.h with replacing some substrings to real value (for example - @MAJOR_VERSION@ to concrete number) - without it visual studio can't find config.h. Also here are exists './glib/win32-fixup.pl', but you don't need touch this file - I think it's deprecated.
But it's not fully-functional configure, bcs it doesn't create file 'gdbus-daemon-generated.c', and we still need to exec autogen & make before it.

7. open ./glib/build/win32/vs10/glib.sln


8. choose mode x64 (I will consider modes Debug_ExtPCRE and Release_ExtPCRE)

9. in project properties, general -> change 'dynamic library' to 'static library' for projects:
  • gio
  • glib
  • gmodule
  • gobject 
  • gthread

10. open 'property sheets' and delete all 'user macros' in sheet named 'glibgensrcsprops'

11. Create two property sheets - one for release x64, another for debug x64. I assume all 4 dependency libraries located in 'D:\projects\libraries\libxmlplusplus' and built by my instructions.

Release_ExtPCRE x64:
  • additional include directories
    • D:\projects\libraries\libxmlplusplus\intl\_build_x64_static_release_mt\include
    • D:\projects\libraries\libxmlplusplus\pcre-8.37\_build_x64_static_release_mt\include
    • D:\projects\libraries\libxmlplusplus\libffi-3.2.1\_build_x64_static_release_mt\include
    • D:\projects\libraries\libxmlplusplus\zlib-1.2.8\_build_x64_static_release_mt\include
  • additional library directories
    • D:\projects\libraries\libxmlplusplus\intl\_build_x64_static_release_mt\lib
    • D:\projects\libraries\libxmlplusplus\pcre-8.37\_build_x64_static_release_mt\Release
    • D:\projects\libraries\libxmlplusplus\libffi-3.2.1\_build_x64_static_release_mt\.libs
    • D:\projects\libraries\libxmlplusplus\zlib-1.2.8\_build_x64_static_release_mt\lib
  • input 
    • ws2_32.lib
    • winmm.lib
    • libffi_convenience.lib
    • Iphlpapi.lib
    • Dnsapi.lib
    • zlib.lib
    • pcre.lib
 Debug_ExtPCRE x64:
  • additional include directories
    • D:\projects\libraries\libxmlplusplus\intl\_build_x64_static_debug_mtd\include
    • D:\projects\libraries\libxmlplusplus\pcre-8.37\_build_x64_static_debug_mtd\include
    • D:\projects\libraries\libxmlplusplus\libffi-3.2.1\_build_x64_static_debug_mtd\include
    • D:\projects\libraries\libxmlplusplus\zlib-1.2.8\_build_x64_static_debug_mtd\include
  • additional library directories
    • D:\projects\libraries\libxmlplusplus\intl\_build_x64_static_debug_mtd\lib
    • D:\projects\libraries\libxmlplusplus\pcre-8.37\_build_x64_static_debug_mtd\Debug
    • D:\projects\libraries\libxmlplusplus\libffi-3.2.1\_build_x64_static_debug_mtd\.libs
    • D:\projects\libraries\libxmlplusplus\zlib-1.2.8\_build_x64_static_debug_mtd\lib
  • input 
    • ws2_32.lib
    • winmm.lib
    • libffi_convenience.lib
    • Iphlpapi.lib
    • Dnsapi.lib
    • zlib.lib
    • pcred.lib
add this property lists to every project in solution



12. Set static runtime (/MT and /MTd accordingly) for all projects except:
  • glib-install
  • gspawn-win32-helper
  • gspawn-win32-helper-console
glib-install - it's some strange thing - without code. gspawn-win32-helper and gspawn-win32-helper-console required some function (__wgetmainargs), which present only in dinamic library.

13. The goal of this step - get rid from dll export (if you don't do it - executables, which use libxml++ will have export O_o. So, you need make several replaces.
in 'glib\glib\gtypes.h':
  • '#          define GLIB_VAR __declspec(dllexport)' -> '#          define GLIB_VAR extern'
  • '#        define GLIB_VAR extern __declspec(dllimport)' -> '#        define GLIB_VAR extern'
in 'glib\config.h':
  • '#define _GLIB_EXTERN __declspec (dllexport) extern' -> '#define _GLIB_EXTERN extern'
in 'glib\gobject\gparamspecs.h' :
  • '#          define GOBJECT_VAR __declspec(dllexport)' -> '#          define GOBJECT_VAR extern'
  • #        define GOBJECT_VAR extern __declspec(dllimport)' -> '#        define GOBJECT_VAR extern'
14. find property sheet 'glibbuilddefinesprops' (for example, it's property sheet of 'glib-compile-resources' project), open 'user macros' and delete:
DllExportDefines    Dll_EXPORT


15. And finally one dirty hack) The point is - looks like glib usually used on Windows only as dynamic library. In dynamic libraries on Windows exists function DllMain, which in glib implemented to fill some internal structure with pointers to internal functions. When you build this library as static, there are no called DllMain, this structure is not initialized (filled by zeros), and glibmm has some global object, and everything crashes into constructor of this object, because it calles some glib function, and executed 'call' by address zero.
So, the point of my dirty hack is - initialize this internal structure in the first glib function, which called from glibmm.
so, in file glib -> glib_init.c


BOOL WINAPI DllMain (HINSTANCE hinstDLL,
                     DWORD     fdwReason,
                     LPVOID    lpvReserved);

HMODULE glib_dll;

BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
         DWORD     fdwReason,
         LPVOID    lpvReserved)
{
  switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
      glib_dll = hinstDLL;
      g_clock_win32_init ();
#ifdef THREADS_WIN32
      g_thread_win32_init ();
#endif
      glib_init ();
      break;

    case DLL_THREAD_DETACH:
#ifdef THREADS_WIN32
      g_thread_win32_thread_detach ();
#endif
      break;

    default:
      /* do nothing */
      ;
    }

  return TRUE;
}


replace by

HMODULE glib_dll;

int is_glib_initialized = 0;

void
glib_init_ctor (void)
{
    if (is_glib_initialized == 0)
    {
        glib_dll = 0;
        g_clock_win32_init ();
        g_thread_win32_init ();
        glib_init ();
        is_glib_initialized = 1;
    }
}


and in glib -> gthread-win32.c

void
g_mutex_init (GMutex *mutex)
{
  g_thread_impl_vtable.InitializeSRWLock (mutex);
}


replace by

extern void glib_init_ctor(void);
void
g_mutex_init (GMutex *mutex)
{
  glib_init_ctor();
  g_thread_impl_vtable.InitializeSRWLock (mutex);
}


16. build all

unsuccessful can be only: gspawn-win32-helper and gspawn-win32-helper-console. It's okay.

    Possible errors for googling people


    problem - you didn't called 'setup.py'  
    -----------------------------------------------
    1>  Copying config.h from config.h.win32...
    1>  The system cannot find the file specified
    -----------------------------------------------
    what to do - step 2 in this post

    2 comments: