Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Windows support and add Visual Studio NMake Makefiles #12

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,44 @@
* data/tdict-science.txt:
- Fix typo "อัลลอยด์" -> "อัลลอย".

2020-03-23 Ross Burton <ross.burton@intel.com>

configure.ac: remove duplicate AC_CONFIG_MACRO_DIR

Autoconf 2.70 will fatally error out if AC_CONFIG_MACRO_DIR is called
more than once:

| configure.ac:25: error: AC_CONFIG_MACRO_DIR can only be used once

* configure.ac:
- Remove duplicate AC_CONFIG_MACRO_DIR
2020-02-14 Chun-wei Fan <fanc999@yahoo.com.tw>

Add a set of NMake Makefiles
* configure.ac:
* Makefile.am:
* win32/*:
- Add a set of NMake Makefiles for Visual Studio 2008 and later,
for building libthai as a DLL as well as the pkg-config file.
Buliding the dictionary file and tests are also supported.

2020-02-14 Chun-wei Fan <fanc999@yahoo.com.tw>
Make libthai relocatable on native Windows

* src/thbrk/brk-common.c:
- Deduce location of DLL or statically-linked EXE and construct
path dynamically where thbrk.tri can be loaded.

2020-02-14 Chun-wei Fan <fanc999@yahoo.com.tw>

Don't use __attribute__((destructor)) on MSVC builds

* src/libthai.c:
* src/thbrk/brk-common.c:
- Instead define a DLLMain that does the same thing when libthai
is built as a DLL, on DLL_PROCESS_DETACH. Ensure that tests
builds as well since src/thbrk/brk-common.c is also used.

2020-03-23 Ross Burton <ross.burton@intel.com>

configure.ac: remove duplicate AC_CONFIG_MACRO_DIR
Expand Down
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
ACLOCAL_AMFLAGS = -I m4

SUBDIRS = include src data tests doc
SUBDIRS = include src data tests doc win32

EXTRA_DIST = \
build-aux/git-version-gen \
Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ AC_CONFIG_FILES([libthai.pc
tests/Makefile
doc/Makefile
doc/Doxyfile
win32/Makefile
win32/config-msvc.mak
])
AC_OUTPUT

Expand Down
6 changes: 5 additions & 1 deletion src/libthai.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@

#include "thbrk/thbrk-priv.h"

__attribute__ ((destructor)) void

#if defined (__GNUC__) || defined (__clang__)
__attribute__((destructor))
#endif
void
_libthai_on_unload ()
{
brk_free_shared_brk ();
Expand Down
115 changes: 114 additions & 1 deletion src/thbrk/brk-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,108 @@
#include "thbrk-utils.h"
#include "brk-common.h"

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>

#if !defined (__GNUC__) && !defined (__clang__)
#ifdef MSVC_BUILD_LIBTHAI_TESTS
/* Externally refer to brk_free_shared_brk() when building the tests for
* Visual Studio so that we do not need to depend on $(srcroot)\src\libthai.c
* to build the tests
*/
extern void brk_free_shared_brk ();
#define _libthai_on_unload brk_free_shared_brk

#else
extern void _libthai_on_unload ();
#endif /* MSVC_BUILD_LIBTHAI_TESTS */
#endif /* !__GNUC__ && !__clang__ */

/* This way, we can use the current directory where the .exe is if no DLL is built, such as in tests */
static HMODULE libthai_dll = NULL;

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

BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
libthai_dll = hinstDLL;
break;

#if !defined (__GNUC__) && !defined (__clang__)
/* fallback for lack of GCC's __attribute__((destructor)) */
case DLL_PROCESS_DETACH:
_libthai_on_unload ();
break;
#endif
}

return TRUE;
}

/*
* modelled around GLib's g_win32_get_package_installation_directory_of_module()
* without Cygwin support
*/
#ifndef __CYGWIN__
char *
libthai_get_installdir (HMODULE hmodule)
{
char *retval;
char *filename;
char *p;
wchar_t wc_fn[MAX_PATH];
size_t length;
size_t converted = 0;

/* NOTE: it relies that GetModuleFileNameW returns only canonical paths */
if (!GetModuleFileNameW (hmodule, wc_fn, MAX_PATH))
return NULL;

length = wcslen(wc_fn);
filename = (char *)malloc (sizeof(char) * (length * 2 + 1));
wcstombs_s(&converted, filename, length * 2, wc_fn, _TRUNCATE);

if ((p = strrchr (filename, '\\')) != NULL)
*p = '\0';

retval = (char *)malloc (sizeof(char) * (length * 2 + 1));
memcpy (retval, filename, strlen(filename));

do
{
p = strrchr (retval, '\\');
if (p == NULL)
break;

*p = '\0';

if (_stricmp (p + 1, "bin") == 0 ||
_stricmp (p + 1, "lib") == 0)
break;
}
while (p != NULL);

if (p == NULL)
{
free (retval);
retval = filename;
}
else
free (filename);

return retval;
}
#endif /* !__CYGWIN__ */
#endif /* _WIN32 */

#define DICT_NAME "thbrk"

static char *
Expand All @@ -58,9 +160,20 @@ brk_load_default_dict ()
free (path);
}

/* Then, fall back to default DICT_DIR macro */
/* Then, fall back to default DICT_DIR macro or relative $(datadir)\share\libthai for native Windows DLL */
if (!dict_trie) {
#if defined (_WIN32) && !defined (__CYGWIN__)
char *basedir = libthai_get_installdir (libthai_dll);
const char *sharedir = "share\\libthai\\" DICT_NAME ".tri";
size_t total_len = strlen (basedir) + strlen (sharedir) + 1; /* '+ 1' for the '\\' that we are using below */
char *filepath = (char *) malloc (sizeof (char) * (total_len + 1));
sprintf (filepath, "%s\\%s", basedir, sharedir);
dict_trie = trie_new_from_file (filepath);
free (filepath);
free (basedir);
#else
dict_trie = trie_new_from_file (DICT_DIR "/" DICT_NAME ".tri");
#endif
}

return dict_trie;
Expand Down
13 changes: 13 additions & 0 deletions win32/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
EXTRA_DIST = \
build-rules-msvc.mak \
config-msvc.mak \
create-lists-msvc.mak \
create-lists.bat \
create-pc.bat \
detectenv-msvc.mak \
generate-msvc.mak \
info-msvc.mak \
install.mak \
Makefile.vc \
README.txt \
$(NULL)
45 changes: 45 additions & 0 deletions win32/Makefile.vc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# NMake Makefile for building libthai on Windows

# The items below this line should not be changed, unless one is maintaining
# the NMake Makefiles. Customizations can be done in the following NMake Makefile
# portions (please see comments in the these files to see what can be customized):
#
# detectenv-msvc.mak
# config-msvc.mak

!include detectenv-msvc.mak

# Include the Makefile portion that enables features based on user input
!include config-msvc.mak

!if "$(VALID_CFGSET)" == "TRUE"


all: $(LIBTHAI_LIBS) $(LIBTHAI_DATA) all-build-info

# Include the Makefile portion to convert the source and header lists
# into the lists we need for compilation and introspection
!include create-lists-msvc.mak

tests: all $(libthai_tests_EXES)
@for %x in (ctype cell inp rend str wchar) do vs$(PDBVER)\$(CFG)\$(PLAT)\test_th%x.exe
vs$(PDBVER)\$(CFG)\$(PLAT)\thsort.exe ..\tests\sorttest.txt vs$(PDBVER)\$(CFG)\$(PLAT)\libthai-tests\out.txt
@fc ..\tests\sorted.txt vs$(PDBVER)\$(CFG)\$(PLAT)\libthai-tests\out.txt
@del vs$(PDBVER)\$(CFG)\$(PLAT)\libthai-tests\out.txt
@if "$(LIB_ONLY)" == "" @(for %x in (brk wbrk) do (set LIBTHAI_DICTDIR=$(MAKEDIR)\vs$(PDBVER)\$(CFG)\$(PLAT)\) & (vs$(PDBVER)\$(CFG)\$(PLAT)\test_th%x.exe))

# Include the build rules for sources, DLLs and executables
!include build-rules-msvc.mak

# Include the rules for build directory creation and code generation
!include generate-msvc.mak

!include install.mak

!else # "$(VALID_CFGSET)" == "TRUE"
all: help
@echo You need to specify a valid configuration, via
@echo CFG=release or CFG=debug
!endif # "$(VALID_CFGSET)" == "TRUE"

!include info-msvc.mak
54 changes: 54 additions & 0 deletions win32/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Instructions for building libthai on Visual Studio
==================================================
Building the libthai on Windows is now supported using Visual Studio.

You will need the following items to build libthai using Visual Studio:
-libiconv (including the libcharset headers and libraries) if building trietool.exe

Invoke the build by issuing the command:
nmake /f Makefile.vc CFG=[release|debug] [PREFIX=...] <option1=1 option2=1 ...>
where:

CFG: Required. Choose from a release or debug build. Note that
all builds generate a .pdb file for each .dll and .exe built--this refers
to the C/C++ runtime that the build uses.

PREFIX: Optional. Base directory of where the third-party headers, libraries
and needed tools can be found, i.e. headers in $(PREFIX)\include,
libraries in $(PREFIX)\lib and tools in $(PREFIX)\bin. If not
specified, $(PREFIX) is set as $(srcroot)\..\vs$(X)\$(platform), where
$(platform) is win32 for 32-bit builds or x64 for 64-bit builds, and
$(X) is the short version of the Visual Studio used, as follows:
2008: 9
2010: 10
2012: 11
2013: 12
2015, 2017, 2019: 14

Explanation of options, set by <option>=1 unless otherwise noted:
-----------------------------------------------------------------
LIB_ONLY: Disables building the Thai dictionary data file, which eliminates the need for
trietool.exe, which requires libiconv with libcharset to run.

LIBDATRIE_INCLUDE_BASE: Base directory where the headers of libdatrie can be found, which
is $(LIBDATRIE_INCLUDE_BASE)\datrie. If not specified,
$(PREFIX)\include is used for this value.

LIBDATRIE_LIB: Full path or name of .lib of libdatrie, if datrie.lib cannot be found in
in the paths indicated by %LIB% or $(PREFIX)\lib.
TRIETOOL: Location of the trietool.exe program from libdatrie, if LIB_ONLY is not specified.
If not specified, $(PREFIX)\bin\trietool.exe will be used for this value.

If you encounter C4819 warnings and/or C2001 errors (newline in constant), you will need to
set your system locale to English (United States) using Control Panel->Time and Region Settings->
Region->System Management->Encoding for non-Unicode programs, reboot, and clean up and retry
the build. Note that the /utf-8 compiler flag in Visual Studio 2015 or later is not sufficient.
Please note that warning C4819 should not be ignored, as it is an indication that the build
might have been done incorrectly.

An 'install' target is provided to copy the built items and public headers to appropriate
locations under $(PREFIX), a 'clean' target is provided to remove all the items that are
created during the build, and a 'tests' target is provided to build and run the test programs.
Note that it is necessary that the libdatrie DLL is found in %PATH% or is copied to $(outdir)
to run the test_thbrk and test_thwbrk test programs, if building against a DLL build of
libdatrie.
Loading