Windows

        Building StarDict
            GTK
            libxml library
                I. building with prebuild binaries
                II. building libxml library from source
            stardict-editor project configuration for libxml
            Building libsigc++
            sapi-tts plugin
            Acrobat wordpick plugin
            Notes
        Solution structure
        Unicode
        Build the installer
            Warning
            Note
            Deploying Visual C++ library with StarDict
            StarDict Portable installer
        Debugging
        Running StarDict on another computer
        StarDict version
        Two copies of CRT
        Notes


StarDict can be compiled and run in windows.

Building StarDict

Use MS Visual Studio 2013 Update 2 to build StarDict.
Choose "Release" and "Win32".

Build stardict-editor.vcxproj will fail because of libxml2 problem.

GTK

You need to install developer packages into "msvc_2013\gtk" directory. Download All-in-one bundle gtk+-bundle_2.24.10-20120208_win32.zip at https://download.gnome.org/binaries/win32/gtk%2B/.

Download libiconv-1.9.1.bin.woe32.zip at http://sourceforge.net/projects/gettext/files/. Extract them into "msvc_2013\gtk\".

libxml library

stardict-editor project depends on libxml library (http://xmlsoft.org/). If you plan to build only StarDict, you do not need this library.

To build stardict-editor with libxml2 library you have two options: you may use either prebuild libxml2 binaries by Igor Zlatković. or build libxml2 from source. With prebuild binaries you'll be only able to build release version of stardict-editor. If you build libxml library from source, you'll be able to build both Release and Debug versions of stardict-editor.

See http://www.zlatkovic.com/libxml.en.html for details about libxml2 library on Windows.

I. building with prebuild binaries

1. Download libxml2-*.win32.zip from ftp://ftp.zlatkovic.com/libxml/
For example: libxml2-2.7.8.win32.zip

2. Unpack into msvc_2013, you'll get a msvc_2013/libxml2-*.win32 folder.

3. Rename libxml2-*.win32 to libxml2.

4. Rename msvc_2013/libxml2/lib to msvc_2013/libxml2/lib.release

But it still don't work as have link problem!
I tried "libxml2-2.9.3-win32-x86.7z", it still don't work!

II. building libxml library from source

1. download libxml archive (for example libxml2-2.7.7.tar.gz) from ftp://xmlsoft.org/libxml2/

    Note, I recommend against libxml2-2.7.8.tar.gz, it seems to be broken.

Or libxml2-2.9.12.tar.gz

2. extract the archive into msvc_2013, rename msvc_2013\libxml2-* to msvc_2013\libxml2-src

3. Windows menu->All Programs->Microsoft Visual Studio 2013->Visual Studio Tools->Visual Studio 2013 Command Prompt

4. cd to msvc_2013\libxml2-src\win32 in the opened console window.

5. Run "cscript configure.js help" to get a listing of all the build options (for your information only).

6. Building release version with default options.

As "libxml2-2.7.7.tar.gz":
For xmlschemas.c, you need to add a UTF-8 BOM in its head to fix the compile problem. Just use the notepad to open it then save.

cscript configure.js include=../../gtk/include lib=../../gtk/lib

As "libxml2-2.7.7.tar.gz":
Edit Makefile.msvc, change:
	LDFLAGS = $(LDFLAGS) /OPT:NOWIN98
to:
	LDFLAGS = $(LDFLAGS)

nmake /f Makefile.msvc

You may see multiple warning like:

c14n.c
c:\stardict\msvc_2013\libxml2-src\libxml.h(94) : warning C4005: 'LIBXML_STATIC' : macro redefinition
        command-line arguments : see previous definition of 'LIBXML_STATIC'

I think they can be ignored.

7. Build results are in msvc_2013\libxml2-src\win32\bin.msvc

8. Copy msvc_2013\libxml2-src\win32\bin.msvc\libxml2_a.lib to msvc_2013\libxml2\lib.release\libxml2_a.lib

It can over now!

9. remove msvc_2013\libxml2-src folder, then repeat step 2 to recreate this folder

10. buiding a debug version

cscript configure.js cruntime=/MDd include=../../gtk/include lib=../../gtk/lib
nmake /f Makefile.msvc

11. copy msvc_2013\libxml2-src\win32\bin.msvc\libxml2_a.lib to msvc_2013\libxml2\lib.debug\libxml2_a.lib

12. copy msvc_2013\libxml2-src\include to msvc\libxml2\include

stardict-editor project configuration for libxml

stardict-editor MS Visual C++ project is already configured to build with libxml2. You do not need to change settings unless you want a custom build.

stardict-editor links libxml statically. You need to adjust project settings as follows to build the project.

1. link with libxml2_a.lib library

2. define the following macros LIBXML_STATIC, LIBXSLT_STATIC, LIBEXSLT_STATIC and XMLSEC_STATIC in project settings. These macros must be globally defined!

3. libxml2 library and the project must use the same version of the c-runtime library. It may be multi-threaded vs. single-threaded, release vs. debug, linked statically or dynamically.

Building libsigc++

1. Download libsigc++ (https://download.gnome.org/sources/libsigc%2B%2B/), unpack it into msvc_2013 directory. You'll get a directory like "msvc_2013\libsigc++-2.5.1".

2. Rename it to "msvc_2013\libsigc++-src".

3. Build the libsigc++ project with MS Visual Studio 2013.
Use Visual Studio 2013 to open "MSVC_Net2010/libsigc++2.sln" file!

Choose libsigc++ project properties:
Change target file name from "sigc-vc110-2_0" to "sigc-vc120-2_0"!
Change Linker option from $(OutDir)sigc-vc110-2_0.dll to $(OutDir)sigc-vc120-2_0.dll 

Do Release build!

4. Copy

    Win32\Release\sigc-vc120-2_0.lib
    Win32\Release\sigc-vc120-2_0.dll

	into "msvc_2013\libsigc++\".

Solution 2 (But don't work fine when building StarDict):
Download libsigc++-2.10.8.tar.xz
Unpack it into msvc_2013 directory.
Rename it to "msvc_2013\libsigc++-src".

Run: Windows menu->All Programs->Visual Studio 2013->Visual Studio Tools->Visual Studio 2013 Command Prompt.
cd to msvc_2013\libsigc++-src/MSVC_NMake in the opened console window.
nmake /f Makefile.vc CFG=release

Copy vs12/release/Win32/
sigc-vc120-2_0.lib
sigc-vc120-2_0.dll
into "msvc_2013\libsigc++\".


sapi-tts plugin

For sapi-tts plugin, you need to install Microsoft Speech SDK. Download SpeechSDK51.exe file. Install it into "C:\Program Files\Microsoft Speech SDK 5.1" (into "C:\Program Files (x86)\Microsoft Speech SDK 5.1" on x64 platform).

Fix these compile errors in sphelper.h (only for x86):

1. add to the top of the file to prevent many errors

 #pragma warning( disable : 4430 )
 #pragma warning( disable : 4996 )
 

2. line 2372

    replace 

         for (const WCHAR * psz = (const WCHAR *)lParam; *psz; psz++) {}
 

    with 

         const WCHAR * psz;
         for (psz = (const WCHAR *)lParam; *psz; psz++) {}
 

3. line 2560

    replace 

     SPPHONEID* pphoneId = dsPhoneId;
 

    with 

     SPPHONEID* pphoneId = (SPPHONEID*)((WCHAR *)dsPhoneId);
 

4. line 2634

    replace 

   pphoneId += wcslen(pphoneId) + 1;
 

    with 

     pphoneId += wcslen((const wchar_t *)pphoneId) + 1;
 

Fix these compile warnings in sphelper.h (only for x64):

1. line 1194

    replace 

     if( ( ::GetVersionEx( &ver ) == TRUE ) && ( ver.dwMajorVersion >= 6 ) )
 

    with 

     if( ( ::GetVersionEx( &ver ) ) && ( ver.dwMajorVersion >= 6 ) )
 

Acrobat wordpick plugin

See stardict\dict\src\win32\acrobat\readme_msvc_2013.txt file.

Notes

For stardict_powerword_parsedata.cpp, you need to add a UTF-8 BOM in its head to fix the compile problem. Just use the notepad to open it then save.

For wordnet plugin files, they are the same:
partic.h
geom.h
newton.h
newton_env.h
newton.cpp
newton_env.cpp
partic.cpp
scene.cpp

And:
stardict_youdaodict.cpp
dict/src/dictmanagedlg.cpp
stardict_dictdotcn.cpp


There are two crash bug with vs2005 (and likely with vs2008, vs2010, vs2013), which you need to notice.

1. Use stardict_g_fopen instead of g_fopen. See http://bugzilla.gnome.org/show_bug.cgi?id=476810

2. Use fprintf_s instead of fprintf, or it will crash. This is a little strange.

libintl.h redefines *printf functions to libintl_*printf functions. That may be the cause of the crash. printf outputs nothing with console attached. Use printf_s instead, or better g_print.

There are two builds in vs2013: Debug and Release, you should choose Release version if you plan to distribute the result, you should choose Debug version for debugging the project.

You should can compile and run stardict successfully now. You cannot start stardict.exe in place, since a special directory structure is needed.

Solution structure

The StarDict solution consists of the following projects:

    stardict (stardict.dll) - a GUI part of StarDict packed into a dynamic library
    stardict-loader (stardict.exe) - an executable file that starts StarDict
    stardict-lib (stardict.lib) - a static library containing a non-GUI part of StarDict
    textouthook and textoutspy (textouthook.dll and textoutspy.dll) - implement scan words feature
    plugins - plugins loaded by StarDict and extending it functionality
    tests - test for StarDict
    //tools/stardict-editor (stardict-editor.dll) - a GUI application providing auxiliary tools
    //tools/stardict-editor-loader (stardict-editor.exe) - an executable file that starts StarDict-Editor
    acrobat-wordpick-plugin - Adobe Acrobat plugin for scan words feature 

You can remove stardict-editor.exe as stardict-editor.dll can't compile successfully!

Code of StarDict application is divided into a number of projects: stardict-lib, stardict, stardict-loader. stardict-lib mainly contains non-GUI code. It was put into a library in order to facilitate testing. The tests solution folder holds test projects, they normaly link the stardict-lib library. The GUI part of the code was put in the stardict project. The division into GUI and non-GUI parts is not strict. Feel free to move code from stardict to stardict-lib and back if needed. stardict and stardict-lib project contains almost all code of the application excluding plugins and auxiliary libraries. stardict-loader is a small project which primary job is to load the StarDict application. stardict-loader inspects OS environment, set up directories, set environment variables and finally loads stardict.dll. stardict-loader should have as few dependencies as possible, it must not depend on GTK for example. Now stardict-loader only uses C Runtime Library and Windows API functions. One of the tasks of stardict-loader is to find GTK directory and add to the dll load path, so stardict.dll can be successfully started. This project produces stardict-loader.exe executable file, it will be renamed to stardict.exe in release version. Configuring the project to output stardict.exe leads to debugging problems in Visual Studio.

Unicode

It's recommended to build Unicode (versus ANSI) version of StarDict. That's done by default. You need to define UNICODE macro in compiler command line to build Unicode version.

Build the installer

Grab and install NSIS: http://sourceforge.net/projects/nsis/
My file: nsis-3.07-setup.exe

http://gnuwin32.sourceforge.net/packages/gettext.htm
Download gettext-tools-0.13.1.bin.woe32.zip
Extract and install it as C:\Program Files (x86)\GnuWin32\

Create dict/stardict-unix-dist directory, extract the StarDict source tarball into it! 

Some of the required files cannot be created on Windows, you need Linux to prepare them.

1. Download gtk2-runtime-*.exe and put it into dict/redist/.

https://sourceforge.net/projects/stardict-4/files/gtk2-runtime/
Download gtk2-runtime-2.12.1.exe
You can still look at: https://sourceforge.net/projects/gtk-win/files/GTK%2B Runtime Environment/

2. Download Microsoft Visual C++ 2013 Redistributable Package and put into dict/redist/. The file is named vcredist_x86.exe.

3. From %PROGDIR%\Microsoft Visual Studio 12.0\VC\redist\x86, copy Microsoft.VC120.CRT to dict/redist/.

Use stardict-prepare-installer.js to build win32-install-dir directory structure. You must have all the required files in place before running the script. See comment at the head of the file for details of running the script.

To run the script, execute the command in Windows Console:
cd dict
cscript stardict-prepare-installer.js

stardict-prepare-installer.js will call the stardict-installer.nsi as NSIS will build the installer.

You will find stardict-*.exe

Warning

The libraries for Visual Studio often are updated after a release. For example, this can occur when you install a service pack. Visual Studio 2013 Update2 installs new version of C Runtime library as well as other libraries. Redistributable files in %PROGDIR%\Microsoft Visual Studio 12.0\VC\Redist\x86 are updated too. However, by default Visual Studio still bind applications to the original release version of libraries available. That is, after installing SP1, application built with Visual Studio require the libraries that were originally installed with Visual Studio 2013! For details see "Redistributing an Application and Binding It to Specific Libraries" at http://msdn.microsoft.com/en-us/library/cc664727.aspx.

In practice that means that after installing Update2.

1. You should continue to use vcredist_x86.exe for Visual Studio 2013.

2. %PROGDIR%\Microsoft Visual Studio 12.0\VC\redist\x86 folder now contains files that do not satisfy dependency requirements of produced applications. You need the pre-SP1 files.

Note

Deploying Visual C++ library with StarDict

StarDict application as well as related tools and DLLs depend upon Visual C++ libraries that must be installed on the target computer in order for application to start. The following libraries are needed: C Runtime Library, Standard C++ Library. They both are part of the Microsoft.VC120.CRT assembly.

There are two way to distribute Visual C++ DLLs.

1. Using Visual C++ Redistributable Package (VCRedist_x86.exe) to install libraries into global assembly cache. This methods requires administrative rights.

2. Installing Microsoft.VC120.CRT as a private assembly in application's folder.

Whenever possible we should install Visual C++ libraries into the native assembly cache (WinSxS folder). That makes the libraries available to all applications no matter where they are installed. In some cases we do not have administrative rights or we should not alter the target system as with the portable version of StarDict. We have to use the second method. Privite assembly are subject of restrictions. We are not free to choose the folder where the private assembly is placed into. That must either the application folder or a subfolder of it named after the assembly name. Of two variants a subfolder in StarDict folder seams the best one - no extra DLLs near stardict.exe. We may have a directory structure like this:

$INSTALLDIR\stardict.exe
//$INSTALLDIR\stardict-editor.exe
$INSTALLDIR\sigc-vc120-2_0.dll
$INSTALLDIR\TextOutHook.dll
$INSTALLDIR\TextOutSpy.dll
...
$INSTALLDIR\Microsoft.VC120.CRT\Microsoft.VC120.CRT.manifest
$INSTALLDIR\Microsoft.VC120.CRT\msvcp120.dll
$INSTALLDIR\Microsoft.VC100.CRT\msvcr120.dll
...

Having Microsoft.VC120.CRT installed this way, Visual C++ libraries will be successfully loaded by stardict.exe, stardict-editor.exe and other DLLs in the "$INSTALLDIR" folder, but not by stardict plugins residing in $INSTALLDIR\plugins folder. The reason for this is "Assembly Searching Sequence", see http://msdn.microsoft.com/en-us/library/aa374224(VS.85).aspx for more details.

There are a number of possibilites to make plugins load successfully.

1. Copy the Microsoft.VC120.CRT folder into plugins. That is we'll have two copies of the Microsoft.VC120.CRT assembly: the first in the $INSTALLDIR folder and the second in the $INSTALLDIR\plugins folder. This make StarDict to load two different copies of the C Runtime and Standard C++ Libraries. The first copy will be loaded by StarDict itself, and the second will be loaded by plugins, hopefully all plugins will share one copy of each library.

This solution is not acceptable for two reasons. 1) Multiple copies of the sample library in process address space, 2) extra disk space required to store two copies of the same file.

2. Link all plugins with C Runtime and Standard C++ libraries statically. In this case each plugin will have its own copy of the library. That is not acceptable again.

3. Move all plugins from the plugins folder directly to $INSTALLDIR. This clutters StarDict folder, but should work OK with a single copy of assembly.

4. Remove reference to Microsoft.VC120.CRT assembly out of plugin manifests. Since Microsoft.VC120.CRT is the only assembly in plugin minifests we can drop the manifest entirely. This make plugin use the copy of C Runtime and Standard C++ Libraries loaded by StarDict.exe. Plugins are only loaded by stardict.exe so we can be sure both libraries present in the process address space.

To disable embedding a manifest into a DLL follow these steps:

    In Visual Studio open project properties.
    In configuration select "All Configurations"
    Navigate to Configuration Properties -> Linker -> Manifest File in the tree on the left.
    Set "Generate Manifest" property to "No". 

StarDict Portable installer

To build StarDict Portable installer you need to install additional programs and components.

    Install PortableApps.com Platform. You need only Platform, but you may install any Suite if you want.
    Use "C:\PortableApps" as installation directory. You may use you other installation directory, but in that case you need to pass portinst parameter to stardict-prepare-install.js script. 
    Install PortableApps.com Installer
    Install FindProcDLL NSIS plug-in
        Download KillProcDll&FindProcDll.zip from http://nsis.sourceforge.net/FindProcDLL_plug-in
        Unpack the archive into "C:\Program Files (x86)\NSIS\Plugins" folder. The archive contains two DLLs: FindProcDLL.dll and KillProcDLL.dll. 

To build StarDict Portable installer, execute stardict-prepare-install.js with portable=yes parameter.

Debugging

For debug, use these codes:

 FILE *file;
 file=fopen("C:\\a.txt", "a+");
 fprintf(file, "a\n");
 fclose(file);

Note: when use fopen(), use "rb", never "r" (unless you know what you are doing).

StarDict sends debug messages, warnings, errors to console. Windows GUI applications do not attach to a console by default, hence all the aforementioned messages go nowhere.

There are two ways to make the output visible. You may attach StarDict to a windows console or open a log window. Both release and debug versions of StarDict allow to use console, while the log window is only available in the debug version.

To open window console pass --message-level option with non-zero parameter. The parameter specifies the amount of output to produce. The larger the value, the more verbose output will be. See StarDict help for more details. The --help option opens console as well. It prints a usage message and exits the application.

If you start StarDict with a shortcut, a new console windows is opened. It is closed with the application. If you start StarDict in an existing console window, the program do not open a new window, but prints all output to the existing one. Opening a new console has the disadvantage that if the application crushs, the console window closes so quickly you cannot read the error message.

Windows console has a limitation, it cannot show all unicode characters. To overcome this limitation StarDict can show output in a log window. The log window has no problems with showing unicode characters, but it can not fully duplicate console output. StarDict can show output of g_debug, g_error, g_warning and the like, g_print, g_printf(?) functions. You'll not see output from printf in the log window, for example. To enable the log window, build StarDict with ENABLE_LOG_WINDOW macro symbol.

All that windows console stuff is not much reliable, if it does not work, retreat to printing into a file or to the log window.

Running StarDict on another computer

You may encounter a problem running StarDict project compiled with VS 2013 on other computer not having VS 2013. You may see the following rather unclear error message "This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem." The error happens because StarDict application, plugin DLLs, hook DLLs are linked with CRT (C runtime library) dynamically and you may not have the appropriate version on that dll on the target computer.

If you build Release version of the project, you need to download and install Microsoft Visual C++ 2013 Redistributable Package (x86).

If you build Debug version of the project, you need a debug version of CRT which not redistributable. I see at least one reason why you may need to use the debug version of StarDict - to debug the project remotely. Microsoft prohibit do distribute the debug version of CRT, but I assume a developer may do that for debuging purpose. Anyway this how to install the debuging version of CRT onto the target machine.

1. In Visual Studio create new Setup Project, name it Setup-CRTDebug.

2. Right-click the project in the Solution Explorer, select Add -> Merge module.

3. In the file selection dialog select "C:\Program Files (x86)\Common Files\Merge Modules\Microsoft_VC120_DebugCRT_x86.msm".

4. Build the project.

5. You've created Setup-CRTDebug.msi setup file. Run it on the target machine. It installs debug version of CRT. In the course of executing you'll be asked to specify an installation directory somewhere under "C:\Program Files (x86)". Never mind. The installer does not copy anything there. It does not even create that folder.

6. Now you should be able to start StarDict.

StarDict version

StarDict version for MSVC build can be specified in the msvc_2013\stardictrc.rc.

Two copies of CRT

When StarDict is build with MS Visual Studio, the resulting application has two copies (maybe more) of C Runtime library. The first copy comes with GTK+ libraries, the second is supplied by Visual Studio. The C Runtime library from Visual Studio resides in msvcr120.dll, that is a part of Microsoft.VC120.CRT assembly. Where is C Runtime Library that comes with GTK+ library, I do not know, but it surely can not be in msvcr120.dll. Having two copies of the library is a headache. There are two copies of environment variables. Setting an environment variable with function from one library, does not make that variable set in the other library. For example,

_wputenv(L"LANG=ru") - sets LANG variable to ru in MS C Runtime Library

g_getenv("LANG") - returns the value of the LANG variable in GTK+ C Runtime Library.

This may be any value, wputenv does not change the environment variable in GTK+ C Runtime Library.

We may live with two copies of the library pretty fine aside from special cases. In particular we need to synchronize LANG environment variable. StarDict Loader sets LANG environment variable to customize GUI interface. It specifies the language to use in interface. StarDict loader defines LANG variable in MS CRT only, the GTK+ CRT is not available yet. If we do nothing about the environment variable LANG in GTK+ CRT library, gettext library will use the default language for user interface. In order for StarDict loader to influence the GUI translation we must set the LANG variable in the GTK+ CRT too.

Notes

StarDict's win32 port got many experience from ReciteWord (My another project, http://reciteword.sourceforge.net) and Pidgin: http://www.pidgin.im


Hu Zheng <huzheng_001@hotmail.com> http://www.huzheng.org

2022.8.24
