Subject: Windows compilation [Was: Re: BEEP: Tomas Nilsson]
From: Martin Stjernholm <mast@lysator.liu.se>
Date: Sat, 1 Oct 2011 AD 11:48:14 -0400

郭雪松  wrote:

> Some month ago, I tried to setup a cross compiling environment, to
> build pike for windows. But failed.
>  
> Can anyone provide a real runable HOWTO? 

Unfortunately the windows build method is a complete embarrassment. It's
too bad that it still works well enough so that noone has bothered
fixing a sensible replacement (one that really works, that is).

You need a unix and a windows box sharing a file system (one virted in
the other is the usual setup). On windows you need Visual Studio 2008.
2005 may also work - I don't know anymore.

Then you check out the nt-tools branch from git. On the windows box you
install pike and make a bat script that runs the compilation server.
Mine looks like this:

  set BUILD_ROOT=l:/mast-home/Pike/NT-build/vc9

  set PIKE_BUILD_ARCH=%1
  if "%PIKE_BUILD_ARCH%" == "" set PIKE_BUILD_ARCH=i386

  if %PIKE_BUILD_ARCH% == i386 (
    set MSVC_ARCH=x86
    set SPRSHD_PORT=4711
  )
  if %PIKE_BUILD_ARCH% == x86_64 (
    set MSVC_ARCH=amd64
    set SPRSHD_PORT=4712
  )
  if %PIKE_BUILD_ARCH% == ia64 (
    set MSVC_ARCH=ia64
    set SPRSHD_PORT=4713
  )

  if "%MSVC_ARCH%" == "" (
    echo Unknown PIKE_BUILD_ARCH "%PIKE_BUILD_ARCH%"
    goto exit
  )

  set PIKE_BUILD_ROOT=%BUILD_ROOT%/%PIKE_BUILD_ARCH%
  set CRT_MSM_PATH=c:/Program Files (x86)/Common Files/Merge Modules

  set GNUWIN_ROOT=c:/gnuwin32
  call "%GNUWIN_ROOT%/bin/set_gnuwin32.bat" -s gnuwin32 -l EN
  set PKG_CONFIG_PATH=%GNUWIN_ROOT%/lib/pkgconfig
  set INCLUDE=%GNUWIN_ROOT%/include;%GNUWIN_ROOT%/include/freetype2
  set LIB=%GNUWIN_ROOT%/lib

  set JAVA_ROOT=c:/Program Files (x86)/Java/jdk1.6.0_24
  set INCLUDE=%JAVA_ROOT%/include;%JAVA_ROOT%/include/win32;%INCLUDE%
  set LIB=%JAVA_ROOT%/lib;%LIB%
  set PATH=%JAVA_ROOT%/jre/bin/server;%PATH%

  call "c:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/vcvarsall.bat" %MSVC_ARCH%

  rem Some packages come from both GnuWin32 and the GTK bundle. If there's
  rem no other reason, we prefer the GTK versions since we'll have to include
  rem them anyway.
  set GTK_ROOT=%PIKE_BUILD_ROOT%/gtk+2.12.11
  set PATH=%GTK_ROOT%/bin;%PATH%
  set PKG_CONFIG_PATH=%GTK_ROOT%/lib/pkgconfig;%PKG_CONFIG_PATH%
  set INCLUDE=%GTK_ROOT%/include;%INCLUDE%
  set LIB=%GTK_ROOT%/lib;%LIB%

  set KFW_ROOT=%PIKE_BUILD_ROOT%/kfw-3-2-2-final
  set INCLUDE=%KFW_ROOT%/inc/krb5;%INCLUDE%
  set LIB=%KFW_ROOT%/lib/i386;%LIB%

  set PGSQL_ROOT=%PIKE_BUILD_ROOT%/pgsql
  set INCLUDE=%PGSQL_ROOT%/include;%INCLUDE%
  set LIB=%PGSQL_ROOT%/lib;%LIB%

  set INCLUDE=%PIKE_BUILD_ROOT%/include;%INCLUDE%
  set LIB=%PIKE_BUILD_ROOT%/lib;%LIB%
  set PATH=%PIKE_BUILD_ROOT%/bin;%PATH%;C:/Program Files (x86)/Pike/bin;C:/Program Files (x86)/Windows Installer XML v2;C:\Program Files\Debugging Tools for Windows (x64);C:\Program Files (x86)\CMake 2.6\bin;C:/MinGW

  echo PIKE_BUILD_ARCH=%PIKE_BUILD_ARCH%
  echo PIKE_BUILD_ROOT=%PIKE_BUILD_ROOT%
  echo CRT_MSM_PATH=%CRT_MSM_PATH%
  echo .
  echo INCLUDE=%INCLUDE%
  echo .
  echo LIB=%LIB%
  echo .
  echo PATH=%PATH%
  echo .
  echo PKG_CONFIG_PATH=%PKG_CONFIG_PATH%
  echo .
  echo SPRSHD_PORT=%SPRSHD_PORT%
  echo .

  :loop
  "c:\Program Files (x86)\Pike\bin\pike" %BUILD_ROOT%\..\nt-tools\tools\sprshd %SPRSHD_PORT% 192.168.200.2 127.0.0.1 10.0.2.2
  goto loop

The sprshd script at the end is the compilation server which you'll find
in the nt-tools branch. It listens to %SPRSHD_PORT% and allows
connections from the following ip's.

On the unix box you run nt-tools/init_nt to start up the
cross-compilation environment. It uses a file ~/.init_ntrc to set up the
path mappings. Here are the relevant parts of mine:

  #!/bin/sh

  #DEBUG=yes

  test -z "$NTHOST" && NTHOST=127.0.0.1

  CC=rntcl

  unset MAKE_PARALLEL

  NTMOUNT1=/home/mast
  NTDRIVE1=l:/mast-home
  NTMOUNT2=/export
  NTDRIVE2=l:
  NTMOUNT3=/net/lister.roxen.com/export
  NTDRIVE3=l:

  export NTHOST

The NTMOUNT/NTDRIVE stuff are the mappings between windows and unix
paths. After you run init_nt, you should be able to use configure and
make as usual in the pike tree, but all compilation takes place on
windows.

That's the easy part, really. The more time consuming bit (at least if
one is accustomed to the convenient linux package repositories) is to
set up all libraries and tools on windows so you get a working build
environment.

In particular it's important to keep track on how you link to crt's.
Preferably pike and all libs should use the same crt, but if you
download prebuilt libs you probably can't get that.

If everything works, then "make wix" is the top level command that'll
give you a complete installer msi.

Below are some notes I collected when I battled with it the last time.
It was about two years ago, so it's a little bit dated. Notably I only
got a 32 bit toolchain - we really ought to fix a full 64 bit
compilation environment.


Directories:

install		The original install or source packages for the
		libraries that are installed right now.

install/tools	Packages for various build tools.

{vc8,vc9,...}
		The first level of subdirectories reflects the build
		environment, or more specifically which libc/CRT
		things have been linked to since that often prohibit
		mixing libs.

		vc8 is Visual Studio 2005, vc9 is Visual Studio 2008.
		Other future possibilities could include MinGW.

{vc8,vc9,...}/{i386,x86_64}
		Second level is the Windows target architecture. Also
		known as x86 and x64, respectively.

{vc8,vc9,...}/lib-build
		Build trees for locally built libs. There are often
		symlinks to built stuff in here, so be careful with
		rm.

{vc8,vc9,...}/{i386,x86_64}/include
		Part of the INCLUDE path.

{vc8,vc9,...}/{i386,x86_64}/lib
		Part of the LIB path.

{vc8,vc9,...}/{i386,x86_64}/bin
		Part of PATH. Should also contain any dlls that
		libraries require, so that pike can run directly in
		the build tree.

{vc8,vc9,...}/{i386,x86_64}/dll
		This directory contains placeholders for the dlls that
		need to be included in the install package.
		install.pike searches for these in PATH. The contents
		of the files here are not important; they can be zero
		length. The MS CRT dlls shouldn't be here, though (see
		CRT_MSM_PATH below instead).

{vc8,vc9,...}/{i386,x86_64}/install-tree
		This directory contains other files that needs to be
		added to the installation. The paths below this
		directory will be mirrored below the pike installation
		directory.

{vc8,vc9,...}/{i386,x86_64}/gtk+2*
		Some bundles are kept in their own trees to avoid a
		mess.

nt-tools	From the Pike git.

Misc notes:

o  Visual Studio, Microsoft SDK, WiX, Java JDK, and the full GnuWin32
   suite are assumed to be installed locally.

o  Lib packages are as far as possible installed as-is with either the
   i386/x86_64 libs (if they contain only one architecture) or vc8/vc9
   dirs (if they contain several architectures) as install root. Then
   symlinks are used as necessary to make libs, dlls and include files
   appear in the right places.

o  Libs compiled for MinGW tend to not mix with "real" native libs such
   as those produced by the GnuWin32 project (even though they ought
   to).

o  Note that it's easy to get several different runtime libs in
   different parts, e.g. most prebuilt libs are linked statically to a
   CRT while pike is linked dynamically to the dll CRT. Malloc'ed
   blocks and fd's can't be mixed between the CRTs, so e.g. a block
   allocated by malloc() in a lib can't be freed by free() in the pike
   module.

   The pike core and all modules use the same CRT. Everything else
   must assume that the CRTs might be different.

o  For VC8 and VC9, libs should be built for the dynamic nondebug CRT
   as far as possible.

o  VC8 and later has new complicated dependency tracking stuff which
   affects the dll CRTs. This is only supported in the wix installer
   which includes the msm files for the CRT in the package.

o  The environment variable CRT_MSM_PATH points to the directory
   containing the merge modules for the Microsoft CRTs to be bundled
   in the wix installer. bin/install.pike needs it when it's used with
   --release-crt or --debug-crt.

o  cccl is heavily modified. It is symlinked from the bin dirs.

o  Notes about compiling in MinGW:
   o  Using --out-implib to MinGW's ld.exe (at least version 2.17.50
      20060824) produces an import library that doesn't work with VC9.
      The Microsoft linker compains with "warning LNK4078: multiple
      '.text' sections found with different attributes" and the app
      crashes immediately when any function in the dll is called.

      A workaround for this is to instead use --output-def to ld.exe
      to create a .def file and then create the import library with
      Microsoft's lib.exe:

      lib /def:my_library.def

o  Gmp (VC8):
   o  Changed to dynamic CRT.
   o  Define HAVE_STRNLEN in config-vc8.p0.

o  Gmp (VC9):
   o  Using the dll version which in turn uses the dynamic CRT.

o  Nettle:
   o  LICENSE PROBLEM: The two cryptos Blowfish and Serpent are
      released under GPL, while the rest of Nettle is LGPL or more
      free. The two problematic cryptos have been removed.
   o  Compiled in MSYS as follows:
      CC=cccl CFLAGS="-MD -O2" ./configure --prefix=$PIKE_BUILD_ROOT
   o  libnettle.a has to be copied to nettle.lib for some post-targets
      to work.
   o  There's some newline confusion in testsuite/sexp-conv-test that
      causes it to fail if it isn't patched.

o  PCRE:
   o  Compiled in MSYS as follows:
      ./configure --disable-cpp --enable-utf8 \
		  --enable-unicode-properties --prefix=$PIKE_BUILD_ROOT
   o  Using the dll version since the static one got CRT problems.
   o  Had to make the import lib (pcre.lib) manually due to the
      --out-implib problem described above. Started from the "make
      pcre.dll" target (which cuts out much of the libtool
      gooblegook).

o  MySQL 3.23.53:
   o  Changed to dynamic CRT.
   o  Define HAVE_STRNLEN in include/config-win.h

o  MySQL 5.0.51: Using the Windows binary dist, dll variant.

o  SQLite:
   o  The header comes from the "sqlite-amalgamation" package.
   o  The dll comes from the "sqlitedll" binary package for Windows.
   o  There's no import library in the binary package, so one was
      create locally using:

      lib /def:sqlite3.def

o  GTK2:
   o  Pike must be configured --without-GTK to allow GTK2 to be
      configured correctly, since the config cache names overlap
      between GTK and GTK2.

o  Java:
   o  A JRE (including jvm.dll) shouldn't get bundled by install.pike.
      It's up to the user to install a JRE separately.

o  GSS-API:
   o  DLLs are intentionally not bundled since the user is required to
      install and configure Kerberos support separately anyway.

o  See http://support.microsoft.com/kb/131313 for instructions on how
   to create an import library directly from a dll.

o  VC9 doesn't always install the 32-bit cl.exe. To get it installed,
   choose to install VC# as well as VC++.
   https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=295538

o  Don't enable Just-in-time debugging in MSVS; the debug popup can
   cause programs to hang in the build process. To disable, delete
   these registry keys:

     HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger
     HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\DbgManagedDebugger

   And on 64-bit systems also these:

     HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger
     HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\DbgManagedDebugger

   See:
     http://msdn.microsoft.com/en-us/library/k8kf6y2a.aspx
     http://msdn.microsoft.com/en-us/library/5hs4b7a6.aspx

   Note: It's possible that the method below will also disable the JIT
   debugger popups.

o  In Vista there's a popup anyway. To disable: Find the registry path

     HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting

   and set/create the "Disabled" and "DontShowUI" DWORD keys with value 1.
   See http://msdn.microsoft.com/en-us/library/bb513638.aspx.

o  To enable UNC paths in cmd.exe: Under the registry path

     HKEY_CURRENT_USER\Software\Microsoft\Command Processor

   add the DisableUNCCheck REG_DWORD and set the value to 0x1 (Hex).
   See http://support.microsoft.com/kb/156276

   cmd.exe still behaves kinda funky when the current dir is a UNC
   path though, but that's mainly a problem in interactive use. A
   workaround is to use pushd/popd: http://support.microsoft.com/kb/317379

o  Windows Vista often and for unknown reasons thinks that the network
   changes and pops up the "Set Network Location" wizard when it
   boots. To disable that, create this key:

     HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Network\NewNetworkWindowOff

   The value doesn't matter. See
   http://msdn.microsoft.com/en-us/library/cc733147.aspx.

o  Autologon to a user that autostart sprshd might be convenient. To
   enable that, go to:

     HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon

   Create these keys:

     AutoAdminLogon: string, value "1"
     DefaultUserName: string
     DefaultPassword: string
     DefaultDomainName: string (if required)

o  WinDbg is the debugger to use in the field:

     http://www.microsoft.com/whdc/devtools/debugging/default.mspx

   To get it to download the symbols for the windows libs, go to
   File/Symbol File Paths..., enter:

     SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols

   and check "reload".

Links:

o  GnuWin32: http://gnuwin32.sourceforge.net/
o  MinGW: http://www.mingw.org/
o  MinGW32 packages repository: http://mingwrep.sourceforge.net/
o  GTK for Windows: http://www.mpir.org/
o  GMP port to VC: http://fp.gladman.plus.com/computing/gmp4win.htm
o  YASM: http://www.tortall.net/projects/yasm/wiki
o  Interesting article about the MS CRT installation mess:
   http://www.codeproject.com/cpp/vcredists_x86.asp
o  Script for running cl.exe like a cc: http://cccl.sourceforge.net/
o  Simple tool for generating import libraries from dlls (untested):
   http://www.geocities.com/SiliconValley/5806/implib32.htm
o  Complex tool for generating import libraries from dlls (untested):
   http://implib.sourceforge.net/

Return to results