From 6a5da68ccfb7ad00e61088a58d52f74ca0686858 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Tue, 24 Apr 2018 18:51:04 +0800 Subject: [PATCH] Add NMake Makefiles for Visual Studio builds This adds a set of Visual Studio NMake Makefiles that can be used to build libpsl, either as a DLL or as a static .lib. Building of the psl tool and the tests in tests/ (but not fuzz, since those tests use fmemopen(), that is not supported on Windows) are also supported. A simplified "install" target is provided that copies the build results to a default or set prefix with the pkg-config file so that other packages (such as libsoup) with build systems that depend on this .pc file can be built. These files make use of autotools stuff so that they have the up-to-date version info upon a release. Currently, only builds using the ICU runtime/builtin or with no runtime/builtin are supported with Visual Studio builds. --- Makefile.am | 2 +- configure.ac | 5 +- msvc/Makefile.am | 13 +++ msvc/Makefile.vc | 35 ++++++++ msvc/build-rules-msvc.mak | 110 ++++++++++++++++++++++++ msvc/config-msvc.mak.in | 137 ++++++++++++++++++++++++++++++ msvc/config.h.win32.in | 169 +++++++++++++++++++++++++++++++++++++ msvc/create-lists-msvc.mak | 61 +++++++++++++ msvc/create-lists.bat | 42 +++++++++ msvc/detectenv-msvc.mak | 152 +++++++++++++++++++++++++++++++++ msvc/generate-msvc.mak | 31 +++++++ msvc/install-msvc.mak | 14 +++ msvc/libpsl-pc.py | 32 +++++++ msvc/pc_base.py | 124 +++++++++++++++++++++++++++ msvc/replace.py | 115 +++++++++++++++++++++++++ src/Makefile.am | 4 +- src/libpsl-srcs.mk | 1 + 17 files changed, 1044 insertions(+), 3 deletions(-) create mode 100644 msvc/Makefile.am create mode 100644 msvc/Makefile.vc create mode 100644 msvc/build-rules-msvc.mak create mode 100644 msvc/config-msvc.mak.in create mode 100644 msvc/config.h.win32.in create mode 100644 msvc/create-lists-msvc.mak create mode 100644 msvc/create-lists.bat create mode 100644 msvc/detectenv-msvc.mak create mode 100644 msvc/generate-msvc.mak create mode 100644 msvc/install-msvc.mak create mode 100644 msvc/libpsl-pc.py create mode 100644 msvc/pc_base.py create mode 100644 msvc/replace.py create mode 100644 src/libpsl-srcs.mk diff --git a/Makefile.am b/Makefile.am index 0fb6c79..f85966b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ if ENABLE_MAN SUBDIRS += docs/libpsl endif endif -SUBDIRS += fuzz tests +SUBDIRS += fuzz tests msvc ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} diff --git a/configure.ac b/configure.ac index 72b136e..82af630 100644 --- a/configure.ac +++ b/configure.ac @@ -381,7 +381,10 @@ AC_CONFIG_FILES([Makefile fuzz/Makefile tests/Makefile docs/libpsl/Makefile docs/libpsl/version.xml - libpsl.pc:libpsl.pc.in]) + libpsl.pc:libpsl.pc.in + msvc/Makefile + msvc/config.h.win32 + msvc/config-msvc.mak]) AC_OUTPUT AC_MSG_NOTICE([Summary of build options: diff --git a/msvc/Makefile.am b/msvc/Makefile.am new file mode 100644 index 0000000..5d85a99 --- /dev/null +++ b/msvc/Makefile.am @@ -0,0 +1,13 @@ +EXTRA_DIST = \ + build-rules-msvc.mak \ + config.h.win32 \ + config-msvc.mak \ + create-lists.bat \ + create-lists-msvc.mak \ + detectenv-msvc.mak \ + generate-msvc.mak \ + install-msvc.mak \ + libpsl-pc.py \ + Makefile.vc \ + pc_base.py \ + replace.py diff --git a/msvc/Makefile.vc b/msvc/Makefile.vc new file mode 100644 index 0000000..722438e --- /dev/null +++ b/msvc/Makefile.vc @@ -0,0 +1,35 @@ +# NMake Makefile for building libpsl 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" + +# 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 + +all: $(PSL_LIB) $(PSL_UTILS) build-info + +tests: $(PSL_TEST_DATA) $(PSL_TESTS) build-info + +# 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 the Makefile portion that enables installing the build results +!include install-msvc.mak +!else +!error No CFG (or invalid CFG) value specified. Valid values are release or debug. +!endif \ No newline at end of file diff --git a/msvc/build-rules-msvc.mak b/msvc/build-rules-msvc.mak new file mode 100644 index 0000000..78923b7 --- /dev/null +++ b/msvc/build-rules-msvc.mak @@ -0,0 +1,110 @@ +# NMake Makefile portion for compilation rules +# Items in here should not need to be edited unless +# one is maintaining the NMake build files. The format +# of NMake Makefiles here are different from the GNU +# Makefiles. Please see the comments about these formats. + +# Inference rules for compiling the .obj files. +# Used for libs and programs with more than a single source file. +# Format is as follows +# (all dirs must have a trailing '\'): +# +# {$(srcdir)}.$(srcext){$(destdir)}.obj:: +# $(CC)|$(CXX) $(cflags) /Fo$(destdir) /c @<< +# $< +# << + +{..\src\}.c{$(CFG)\$(PLAT)\libpsl\}.obj:: + $(CC) $(BASE_CFLAGS) $(PSL_ADDITIONAL_CFLAGS) $(PSL_INCLUDES) /Fo$(CFG)\$(PLAT)\libpsl\ /c @<< +$< +<< + +{..\tools\}.c{$(CFG)\$(PLAT)\psl\}.obj:: + $(CC) $(BASE_CFLAGS) $(PSL_INCLUDES) /Fo$(CFG)\$(PLAT)\psl\ /c @<< +$< +<< + +# Make sure we generate suffixes_dafsa.c before trying to compile psl.c +$(CFG)\$(PLAT)\libpsl\psl.obj: $(CFG)\$(PLAT)\libpsl\suffixes_dafsa.c + +# Inference rules for building the test programs +# Used for programs with a single source file. +# Format is as follows +# (all dirs must have a trailing '\'): +# +# {$(srcdir)}.$(srcext){$(destdir)}.exe:: +# $(CC)|$(CXX) $(cflags) $< /Fo$*.obj /Fe$@ [/link $(linker_flags) $(dep_libs)] + +{..\tests\}.c{$(CFG)\$(PLAT)\}.exe: + @if not exist $(PSL_UTILS) $(MAKE) -f Makefile.vc $(PSL_MAKE_OPTIONS) $(PSL_UTILS) + @if not exist $(CFG)\$(PLAT)\tests $(MAKE) -f Makefile.vc $(PSL_MAKE_OPTIONS) $(CFG)\$(PLAT)\tests + $(CC) $(PSL_TEST_CFLAGS) $(PSL_INCLUDES) /Fo$(CFG)\$(PLAT)\tests\ /Fe$@ \ + $< /link $(LDFLAGS) $(PSL_LIB) $(PSL_ADDITIONAL_LIBS) + @if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;1 + +# Rules for building .lib files +!ifdef STATIC +$(PSL_LIB): $(CFG)\$(PLAT)\libpsl ..\config.h $(libpsl_OBJS) + lib $(ARFLAGS) /out:$@ @<< +$(libpsl_OBJS) +<< + +!else +$(PSL_LIB): $(PSL_DLL) +!endif + +# Rules for linking DLLs +# Format is as follows (the mt command is needed for MSVC 2005/2008 builds): +# $(dll_name_with_path): $(dependent_libs_files_objects_and_items) +# link /DLL [$(linker_flags)] [$(dependent_libs)] [/def:$(def_file_if_used)] [/implib:$(lib_name_if_needed)] -out:$@ @<< +# $(dependent_objects) +# << +# @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2 + +$(PSL_DLL): ..\config.h $(libpsl_OBJS) + link $(LDFLAGS) $(PSL_ADDITIONAL_LIBS) /DLL /out:$@ @<< +$(libpsl_OBJS) +<< + @if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2 + +# Rules for linking Executables +# Format is as follows (the mt command is needed for MSVC 2005/2008 builds): +# $(dll_name_with_path): $(dependent_libs_files_objects_and_items) +# link [$(linker_flags)] [$(dependent_libs)] -out:$@ @<< +# $(dependent_objects) +# << +# @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;1 + +$(CFG)\$(PLAT)\psl.exe: $(PSL_LIB) $(CFG)\$(PLAT)\psl $(psl_OBJS) + link $(LDFLAGS) $(PSL_LIB) $(PSL_ADDITIONAL_LIBS) /PDB:$(@R)-tool.pdb /out:$@ @<< +$(psl_OBJS) +<< + @if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;1 + +# Show the build configuration for this build +build-info: + @echo ------------------------------- + @echo Build configuration for libpsl: + @echo ------------------------------- + @echo Configuration/Platform: $(CFG)/$(PLAT) + @echo Library Build Type: $(PSL_LIBTYPE) + @echo Enabled Runtime: $(ENABLED_RUNTIME) + @echo Enabled Builtin: $(ENABLED_BUILTIN) + @if not "$(ENABLED_BUILTIN)" == "none" echo PSL File: $(PSL_FILE) + +clean: + @if exist $(CFG)\$(PLAT)\psl.dafsa del $(CFG)\$(PLAT)\psl.dafsa + @if exist $(CFG)\$(PLAT)\psl_ascii.dafsa del $(CFG)\$(PLAT)\psl_ascii.dafsa + @if exist .\libpsl.pc del /f /q .\libpsl.pc + @-del /f /q $(CFG)\$(PLAT)\*.exe + @-del /f /q $(CFG)\$(PLAT)\*.lib + @-del /f /q $(CFG)\$(PLAT)\*.pdb + @-del /f /q $(CFG)\$(PLAT)\*.dll.manifest + @-del /f /q $(CFG)\$(PLAT)\*.dll + @-del /f /q $(CFG)\$(PLAT)\*.ilk + @-if exist $(CFG)\$(PLAT)\tests del /f /q $(CFG)\$(PLAT)\tests\*.obj + @-del /f /q $(CFG)\$(PLAT)\libpsl\*.obj + @-del /f /q $(CFG)\$(PLAT)\libpsl\suffixes_dafsa.c + @-del /f /q ..\config.h + @-del /f /q vc$(PDBVER)0.pdb + @-rmdir /s /q $(CFG)\$(PLAT) diff --git a/msvc/config-msvc.mak.in b/msvc/config-msvc.mak.in new file mode 100644 index 0000000..adf1eff --- /dev/null +++ b/msvc/config-msvc.mak.in @@ -0,0 +1,137 @@ +# NMake Makefile portion for enabling features for Windows builds + +# You may change these lines to customize various items + +!ifndef PSL_FILE +PSL_FILE=..\list\public_suffix_list.dat +!endif + +!ifndef PSL_TESTFILE +PSL_TESTFILE=..\list\tests\tests.txt +!endif + +PSL_FILE_INPUT = $(PSL_FILE:\=/) +PSL_TESTFILE_INPUT = $(PSL_TESTFILE:\=/) + +# We only support using the ICU runtime and/or builtin, or no runtime +# and/or builtin for Visual Studio builds +!if "$(CFG)" == "Release" || "$(CFG)" == "release" +ICUUC_LIB = icuuc.lib +!else +ICUUC_LIB = icuucd.lib +!endif + +ICONV_LIB = iconv.lib +GETTEXT_LIB = intl.lib + +# Please do not change anything beneath this line unless maintaining the NMake Makefiles +# Version info + +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +PACKAGE_URL=@PACKAGE_URL@ + +# Bare minimum features and sources built into libpsl on Windows + +!if "$(PLAT)" == "x64" +SSIZE_T_DEF = signed __int64 +!else +SSIZE_T_DEF = signed int +!endif + +PSL_ADDITIONAL_LIBS = ws2_32.lib +PSL_ADDITIONAL_CFLAGS = /DBUILDING_PSL + +BASE_CFLAGS = \ + $(CFLAGS) \ + /D_CRT_SECURE_NO_WARNINGS \ + /D_CRT_NONSTDC_NO_WARNINGS \ + /DHAVE_CONFIG_H \ + /Dssize_t="$(SSIZE_T_DEF)" + +PSL_INCLUDES = /I..\include /I.. /I$(CFG)\$(PLAT)\libpsl /I$(PREFIX)\include + +# We build the psl.dll or psl.lib at least, with the psl.exe utility +PSL_LIB = $(CFG)\$(PLAT)\psl.lib +PSL_UTILS = $(CFG)\$(PLAT)\psl.exe + +PSL_TESTS = \ + $(CFG)\$(PLAT)\test-is-public.exe \ + $(CFG)\$(PLAT)\test-is-public-all.exe \ + $(CFG)\$(PLAT)\test-is-cookie-domain-acceptable.exe + +PSL_TEST_DATA = \ + $(CFG)\$(PLAT)\psl.dafsa \ + $(CFG)\$(PLAT)\psl_ascii.dafsa + +PSL_MAKE_OPTIONS = CFG^=$(CFG) + +!ifndef STATIC +!ifdef USE_LIBTOOL_DLLNAME +PSL_DLL_PREFIX = lib +PSL_DLL_SUFFIX = -5 +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) USE_LIBTOOL_DLLNAME^=$(USE_LIBTOOL_DLLNAME) +!else +PSL_DLL_PREFIX = +PSL_DLL_SUFFIX = +!endif +!endif + +PSL_DLL = $(CFG)\$(PLAT)\$(PSL_DLL_PREFIX)psl$(PSL_DLL_SUFFIX).dll + +# ENABLE_RUNTIME_ICU and ENABLE_BUILTIN_ICU are currently dummy arguments to NMake +ENABLED_RUNTIME = +ENABLED_BUILTIN = + +!ifndef DISABLE_RUNTIME +BASE_CFLAGS = $(BASE_CFLAGS) /DWITH_LIBICU=1 +ENABLED_RUNTIME = libicu +!else +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) DISABLE_RUNTIME^=1 +ENABLED_RUNTIME = none +!endif + +!ifndef DISABLE_BUILTIN +BASE_CFLAGS = $(BASE_CFLAGS) /DBUILTIN_GENERATOR_LIBICU=1 +ENABLED_BUILTIN = libicu +!else +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) DISABLE_BUILTIN^=1 +ENABLED_BUILTIN = none +!endif + +!ifdef STATIC +BASE_CFLAGS = $(BASE_CFLAGS) /DPSL_STATIC +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) STATIC^=1 +PSL_LIBTYPE = static +!else +PSL_LIBTYPE = DLL +!endif + +!if "$(DISABLE_RUNTIME)" == "" || "$(DISABLE_BUILTIN)" == "" +PSL_ADDITIONAL_LIBS = $(PSL_ADDITIONAL_LIBS) $(ICUUC_LIB) +PSL_TESTS = \ + $(PSL_TESTS) \ + $(CFG)\$(PLAT)\test-is-public-builtin.exe \ + $(CFG)\$(PLAT)\test-registrable-domain.exe +!endif + +!ifdef USE_GETTEXT +USE_ICONV=1 +PSL_ADDITIONAL_LIBS = $(PSL_ADDITIONAL_LIBS) $(GETTEXT_LIB) +BASE_CFLAGS = $(BASE_CFLAGS) /DUSE_GETTEXT=1 +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) USE_GETTEXT^=1 +!endif + +!ifdef USE_ICONV +PSL_ADDITIONAL_LIBS = $(PSL_ADDITIONAL_LIBS) $(ICONV_LIB) +BASE_CFLAGS = $(BASE_CFLAGS) /DUSE_ICONV=1 +PSL_MAKE_OPTIONS = $(PSL_MAKE_OPTIONS) USE_ICONV^=1 +!endif + +PSL_TEST_CFLAGS = $(BASE_CFLAGS) /DPSL_TESTFILE=\"$(PSL_TESTFILE_INPUT)\" /DPSL_FILE=\"$(PSL_FILE_INPUT)\" + +# Visual Studio 2013 or earlier does not have snprintf(), +# so use _snprintf() which seems to be enough for our purposes +!if $(VSVER) < 14 +PSL_TEST_CFLAGS = $(PSL_TEST_CFLAGS) /Dsnprintf=_snprintf +!endif diff --git a/msvc/config.h.win32.in b/msvc/config.h.win32.in new file mode 100644 index 0000000..b1f2525 --- /dev/null +++ b/msvc/config.h.win32.in @@ -0,0 +1,169 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* generate PSL data using libicu */ +/* #undef BUILTIN_GENERATOR_LIBICU */ + +/* generate PSL data using libidn */ +/* #undef BUILTIN_GENERATOR_LIBIDN */ + +/* generate PSL data using libidn2 */ +/* #undef BUILTIN_GENERATOR_LIBIDN2 */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#ifdef USE_GETTEXT +# define ENABLE_NLS 1 +#endif + +/* Define to 1 if you have `alloca', as a function or macro. */ +#ifdef _MSC_VER +# define alloca _alloca +#endif +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +/* #undef HAVE_ALLOCA_H */ + +/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the + CoreFoundation framework. */ +/* #undef HAVE_CFLOCALECOPYCURRENT */ + +/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in + the CoreFoundation framework. */ +/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ + +/* Define to 1 if you have the `clock_gettime' function. */ +#ifndef _MSC_VER +# define HAVE_CLOCK_GETTIME 1 +#endif + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#ifdef USE_GETTEXT +# define HAVE_DCGETTEXT 1 +#endif + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the `fmemopen' function. */ +/* #undef HAVE_FMEMOPEN */ + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#ifdef USE_GETTEXT +# define HAVE_GETTEXT 1 +#endif + +/* Define if you have the iconv() function and it works. */ +#ifdef USE_ICONV +# define HAVE_ICONV 1 +#endif + +/* Define to 1 if you have the header file. */ +#if !defined (_MSC_VER) || (_MSC_VER >= 1800) +# define HAVE_INTTYPES_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#if !defined (_MSC_VER) || (_MSC_VER >= 1600) +# define HAVE_STDINT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +# define HAVE_STRINGS_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strndup' function. */ +/* #undef HAVE_STRNDUP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#ifndef _MSC_VER +# define HAVE_UNISTD_H 1 +#endif + +/* Define to 1 or 0, depending whether the compiler supports simple visibility + declarations. */ +#ifndef _MSC_VER +# define HAVE_VISIBILITY 1 +#endif + +/* Define as const if the declaration of iconv() needs const. */ +/* #undef ICONV_CONST */ + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@PACKAGE_NAME@ @PACKAGE_VERSION@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "@PACKAGE_TARNAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "@PACKAGE_URL@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* generate PSL data using libicu */ +/* #undef WITH_LIBICU */ + +/* generate PSL data using libidn */ +/* #undef WITH_LIBIDN */ + +/* generate PSL data using libidn2 */ +/* #undef WITH_LIBIDN2 */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +# if defined (_MSC_VER) && (_MSC_VER < 1900) +# define inline __inline +# endif +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/msvc/create-lists-msvc.mak b/msvc/create-lists-msvc.mak new file mode 100644 index 0000000..324cee5 --- /dev/null +++ b/msvc/create-lists-msvc.mak @@ -0,0 +1,61 @@ +# Convert the source listing to object (.obj) listing in +# another NMake Makefile module, include it, and clean it up. +# This is a "fact-of-life" regarding NMake Makefiles... +# This file does not need to be changed unless one is maintaining the NMake Makefiles + +# For those wanting to add things here: +# To add a list, do the following: +# # $(description_of_list) +# if [call create-lists.bat header $(makefile_snippet_file) $(variable_name)] +# endif +# +# if [call create-lists.bat file $(makefile_snippet_file) $(file_name)] +# endif +# +# if [call create-lists.bat footer $(makefile_snippet_file)] +# endif +# ... (repeat the if [call ...] lines in the above order if needed) +# !include $(makefile_snippet_file) +# +# (add the following after checking the entries in $(makefile_snippet_file) is correct) +# (the batch script appends to $(makefile_snippet_file), you will need to clear the file unless the following line is added) +#!if [del /f /q $(makefile_snippet_file)] +#!endif + +# In order to obtain the .obj filename that is needed for NMake Makefiles to build DLLs/static LIBs or EXEs, do the following +# instead when doing 'if [call create-lists.bat file $(makefile_snippet_file) $(file_name)]' +# (repeat if there are multiple $(srcext)'s in $(source_list), ignore any headers): +# !if [for %c in ($(source_list)) do @if "%~xc" == ".$(srcext)" @call create-lists.bat file $(makefile_snippet_file) $(intdir)\%~nc.obj] +# +# $(intdir)\%~nc.obj needs to correspond to the rules added in build-rules-msvc.mak +# %~xc gives the file extension of a given file, %c in this case, so if %c is a.cc, %~xc means .cc +# %~nc gives the file name of a given file without extension, %c in this case, so if %c is a.cc, %~nc means a + +NULL= + +# Include libpsl source files +!include ..\src\libpsl-srcs.mk + +# Create the list of .obj files +!if [call create-lists.bat header libpsl-msvc.mak libpsl_OBJS] +!endif + +!if [for %c in ($(LIBPSL_SRCS)) do @if "%~xc" == ".c" @call create-lists.bat file libpsl-msvc.mak ^$(CFG)\^$(PLAT)\libpsl\%~nc.obj] +!endif + +!if [call create-lists.bat footer libpsl-msvc.mak] +!endif + +!if [call create-lists.bat header libpsl-msvc.mak psl_OBJS] +!endif + +!if [for %c in (..\tools\*.c) do @call create-lists.bat file libpsl-msvc.mak ^$(CFG)\^$(PLAT)\psl\%~nc.obj] +!endif + +!if [call create-lists.bat footer libpsl-msvc.mak] +!endif + +!include libpsl-msvc.mak + +!if [del /f /q libpsl-msvc.mak] +!endif diff --git a/msvc/create-lists.bat b/msvc/create-lists.bat new file mode 100644 index 0000000..ef60d5c --- /dev/null +++ b/msvc/create-lists.bat @@ -0,0 +1,42 @@ +@echo off +rem Simple .bat script for creating the NMake Makefile snippets. + +if not "%1" == "header" if not "%1" == "file" if not "%1" == "footer" goto :error_cmd +if "%2" == "" goto error_no_destfile + +if "%1" == "header" goto :header +if "%1" == "file" goto :addfile +if "%1" == "footer" goto :footer + +:header +if "%3" == "" goto error_var +echo %3 = \>>%2 +goto done + +:addfile +if "%3" == "" goto error_file +echo. %3 \>>%2 +goto done + +:footer +echo. $(NULL)>>%2 +echo.>>%2 +goto done + +:error_cmd +echo Specified command '%1' was invalid. Valid commands are: header file footer. +goto done + +:error_no_destfile +echo Destination NMake snippet file must be specified +goto done + +:error_var +echo A name must be specified for using '%1'. +goto done + +:error_file +echo A file must be specified for using '%1'. +goto done + +:done \ No newline at end of file diff --git a/msvc/detectenv-msvc.mak b/msvc/detectenv-msvc.mak new file mode 100644 index 0000000..2ca74d5 --- /dev/null +++ b/msvc/detectenv-msvc.mak @@ -0,0 +1,152 @@ +# Change this (or specify PREFIX= when invoking this NMake Makefile) if +# necessary, so that the libs and headers of the dependent third-party +# libraries can be located. For instance, if building from GLib's +# included Visual Studio projects, this should be able to locate the GLib +# build out-of-the-box if they were not moved. GLib's headers will be +# found in $(GLIB_PREFIX)\include\glib-2.0 and +# $(GLIB_PREFIX)\lib\glib-2.0\include and its import library will be found +# in $(GLIB_PREFIX)\lib. + +!if "$(PREFIX)" == "" +PREFIX = ..\..\vs$(VSVER)\$(PLAT) +!endif + +# Location of the PERL interpretor, for running glib-mkenums. glib-mkenums +# needs to be found in $(PREFIX)\bin. Using either a 32-bit or x64 PERL +# interpretor are supported for either a 32-bit or x64 build. + +!if "$(PERL)" == "" +PERL = perl +!endif + +# Location of the Python interpretor, for building introspection. The complete set +# of Python Modules for introspection (the giscanner Python scripts and the _giscanner.pyd +# compiled module) needs to be found in $(PREFIX)\lib\gobject-introspection\giscanner, and +# the g-ir-scanner Python script and g-ir-compiler utility program needs to be found +# in $(PREFIX)\bin, together with any DLLs they will depend on, if those DLLs are not already +# in your PATH. +# Note that the Python interpretor and the introspection modules and utility progam must +# correspond to the build type (i.e. 32-bit Release for 32-bit Release builds, and so on). +# +# For introspection, currently only Python 2.7.x is supported. This may change when Python 3.x +# support is added upstream in gobject-introspection--when this happens, the _giscanner.pyd must +# be the one that is built against the release series of Python that is used here. + +!if "$(PYTHON)" == "" +PYTHON = python +!endif + +# Location of the pkg-config utility program, for building introspection. It needs to be able +# to find the pkg-config (.pc) files so that the correct libraries and headers for the needed libraries +# can be located, using PKG_CONFIG_PATH. Using either a 32-bit or x64 pkg-config are supported for +# either a 32-bit or x64 build. + +!if "$(PKG_CONFIG)" == "" +PKG_CONFIG = pkg-config +!endif + +# The items below this line should not be changed, unless one is maintaining +# the NMake Makefiles. The exception is for the CFLAGS_ADD line(s) where one +# could use his/her desired compiler optimization flags, if he/she knows what is +# being done. + +# Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or +# VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir) +!if !defined(VCINSTALLDIR) && !defined(WINDOWSSDKDIR) +MSG = ^ +This Makefile is only for Visual Studio 2008 and later.^ +You need to ensure that the Visual Studio Environment is properly set up^ +before running this Makefile. +!error $(MSG) +!endif + +ERRNUL = 2>NUL +_HASH=^# + +!if ![echo VCVERSION=_MSC_VER > vercl.x] \ + && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \ + && ![echo PLAT=Win32 >> vercl.x] \ + && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \ + && ![echo PLAT=x64 >> vercl.x] \ + && ![echo $(_HASH)endif >> vercl.x] \ + && ![cl -nologo -TC -P vercl.x $(ERRNUL)] +!include vercl.i +!if ![echo VCVER= ^\> vercl.vc] \ + && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc] +!include vercl.vc +!endif +!endif +!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc] +!endif + +!if $(VCVERSION) > 1499 && $(VCVERSION) < 1600 +VSVER = 9 +!elseif $(VCVERSION) > 1599 && $(VCVERSION) < 1700 +VSVER = 10 +!elseif $(VCVERSION) > 1699 && $(VCVERSION) < 1800 +VSVER = 11 +!elseif $(VCVERSION) > 1799 && $(VCVERSION) < 1900 +VSVER = 12 +!elseif $(VCVERSION) > 1899 && $(VCVERSION) < 1910 +VSVER = 14 +!elseif $(VCVERSION) > 1909 && $(VCVERSION) < 2000 +VSVER = 15 +!else +VSVER = 0 +!endif + +!if "$(VSVER)" == "0" +MSG = ^ +This NMake Makefile set supports Visual Studio^ +9 (2008) through 14 (2015). Your Visual Studio^ +version is not supported. +!error $(MSG) +!elseif $(VSVER) < 15 +PDBVER = $(VSVER) +!else +PDBVER = 14 +!endif + +VALID_CFGSET = FALSE +!if "$(CFG)" == "release" || "$(CFG)" == "debug" +VALID_CFGSET = TRUE +!endif + +# One may change these items, but be sure to test +# the resulting binaries +!if "$(CFG)" == "release" +CFLAGS_ADD = /MD /O2 /MP /GL +!if $(VSVER) > 9 && $(VSVER) < 14 +# Undocumented "enhance optimized debugging" switch. Became documented +# as "/Zo" in VS 2013 Update 3, and is turned on by default in VS 2015. +CFLAGS_ADD = $(CFLAGS_ADD) /d2Zi+ +!endif +!else +CFLAGS_ADD = /MDd /Od +!endif + +!if "$(PLAT)" == "x64" +LDFLAGS_ARCH = /machine:x64 +!elseif "$(PLAT)" == "arm" +LDFLAGS_ARCH = /machine:arm +CFLAGS_ADD = $(CFLAGS_ADD) /DWINAPI_FAMILY=3 +!else +LDFLAGS_ARCH = /machine:x86 +!endif + +!if "$(VALID_CFGSET)" == "TRUE" +CFLAGS = $(CFLAGS_ADD) /W3 /Zi + +!if "$(ADDITIONAL_LIB_DIR)" != "" +ADDITIONAL_LIB_ARG = /libpath:$(ADDITIONAL_LIB_DIR) +!endif +LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib $(ADDITIONAL_LIB_ARG) /DEBUG + +!if "$(CFG)" == "debug" +LDFLAGS = $(LDFLAGS_BASE) +ARFLAGS = $(LDFLAGS_ARCH) +!else +LDFLAGS = $(LDFLAGS_BASE) /opt:ref /LTCG +ARFLAGS = $(LDFLAGS_ARCH) /LTCG +!endif +!endif diff --git a/msvc/generate-msvc.mak b/msvc/generate-msvc.mak new file mode 100644 index 0000000..2fd7697 --- /dev/null +++ b/msvc/generate-msvc.mak @@ -0,0 +1,31 @@ +# NMake Makefile portion for code generation and +# intermediate build directory creation +# Items in here should not need to be edited unless +# one is maintaining the NMake build files. + +# Create the build directories +$(CFG)\$(PLAT)\libpsl \ +$(CFG)\$(PLAT)\psl \ +$(CFG)\$(PLAT)\tests: + @-md $@ + +$(CFG)\$(PLAT)\libpsl\suffixes_dafsa.c: $(CFG)\$(PLAT)\libpsl $(PSL_FILE) ..\src\psl-make-dafsa + @echo Generating $@ + $(PYTHON) ..\src\psl-make-dafsa --output-format=cxx+ "$(PSL_FILE_INPUT)" $@ + +$(CFG)\$(PLAT)\psl.dafsa: $(CFG)\$(PLAT)\tests + @echo Generating $@ + $(PYTHON) ..\src\psl-make-dafsa --output-format=binary "$(PSL_FILE_INPUT)" $@ + +$(CFG)\$(PLAT)\psl_ascii.dafsa: $(CFG)\$(PLAT)\tests + @echo Generating $@ + $(PYTHON) ..\src\psl-make-dafsa --output-format=binary --encoding=ascii "$(PSL_FILE_INPUT)" $@ + +libpsl.pc: ..\libpsl.pc.in + @echo Generating $@ + $(PYTHON) libpsl-pc.py --name=$(PACKAGE_NAME) \ + --version=$(PACKAGE_VERSION) --url=$(PACKAGE_URL) --prefix=$(PREFIX) + +..\config.h: config.h.win32 + @echo Generating $@ + @copy $** $@ diff --git a/msvc/install-msvc.mak b/msvc/install-msvc.mak new file mode 100644 index 0000000..7afa50e --- /dev/null +++ b/msvc/install-msvc.mak @@ -0,0 +1,14 @@ +# NMake Makefile snippet for copying the built libraries, utilities and headers to +# a path under $(PREFIX). + +install: all libpsl.pc build-info + @if not exist $(PREFIX)\bin\ mkdir $(PREFIX)\bin + @if not exist $(PREFIX)\lib\pkgconfig\ mkdir $(PREFIX)\lib\pkgconfig + @if not exist $(PREFIX)\include @mkdir $(PREFIX)\include + @copy /b $(CFG)\$(PLAT)\psl.exe $(PREFIX)\bin + @copy /b $(CFG)\$(PLAT)\psl-tool.pdb $(PREFIX)\bin + @if "$(PSL_LIBTYPE)" == "DLL" copy /b $(PSL_DLL) $(PREFIX)\bin + @if "$(PSL_LIBTYPE)" == "DLL" copy /b $(CFG)\$(PLAT)\psl.pdb $(PREFIX)\bin + @copy /b $(CFG)\$(PLAT)\psl.lib $(PREFIX)\lib + @copy libpsl.pc $(PREFIX)\lib\pkgconfig + @for %h in (..\include\*.h) do @copy %h $(PREFIX)\include\%~nxh diff --git a/msvc/libpsl-pc.py b/msvc/libpsl-pc.py new file mode 100644 index 0000000..d6f2958 --- /dev/null +++ b/msvc/libpsl-pc.py @@ -0,0 +1,32 @@ +# !/usr/env/python +# Simple script to generate libpsl.pc from libpsl.pc.in +# for Visual Studio builds + +import sys +import argparse + +from replace import replace_multi +from pc_base import BasePCItems + +def main(argv): + parser = argparse.ArgumentParser(description='Setup basic libpsl.pc file info') + parser.add_argument('--name', help='Name of package', required=True) + parser.add_argument('--url', help='Package Home Page URL', required=True) + + base_pc = BasePCItems() + base_pc.setup(argv, parser) + args = parser.parse_args() + + pc_replace_items = {'@PACKAGE_NAME@': args.name, + '@PACKAGE_VERSION@': args.version, + '@PACKAGE_URL@': args.url} + + pc_replace_items.update(base_pc.base_replace_items) + + # Generate libpsl.pc + replace_multi(base_pc.top_srcdir + '/libpsl.pc.in', + base_pc.srcdir + '/libpsl.pc', + pc_replace_items) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) \ No newline at end of file diff --git a/msvc/pc_base.py b/msvc/pc_base.py new file mode 100644 index 0000000..285b6cd --- /dev/null +++ b/msvc/pc_base.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +# +# Simple utility script to generate the basic info +# needed in a .pc (pkg-config) file, used especially +# for introspection purposes + +# This can be used in various projects where +# there is the need to generate .pc files, +# and is copied from GLib's $(srcroot)/build/win32 + +# Author: Fan, Chun-wei +# Date: March 10, 2016 + +import os +import sys +import argparse + +class BasePCItems: + def __init__(self): + self.base_replace_items = {} + self.exec_prefix = '' + self.includedir = '' + self.libdir = '' + self.prefix = '' + self.srcdir = os.path.dirname(__file__) + self.top_srcdir = self.srcdir + '\\..' + self.version = '' + + def setup(self, argv, parser=None): + if parser is None: + parser = argparse.ArgumentParser(description='Setup basic .pc file info') + parser.add_argument('--prefix', help='prefix of the installed library', + required=True) + parser.add_argument('--exec-prefix', + help='prefix of the installed programs, \ + if different from the prefix') + parser.add_argument('--includedir', + help='includedir of the installed library, \ + if different from ${prefix}/include') + parser.add_argument('--libdir', + help='libdir of the installed library, \ + if different from ${prefix}/lib') + parser.add_argument('--version', help='Version of the package', + required=True) + args = parser.parse_args() + + self.version = args.version + + # check whether the prefix and exec_prefix are valid + if not os.path.exists(args.prefix): + raise SystemExit('Specified prefix \'%s\' is invalid' % args.prefix) + + # use absolute paths for prefix + self.prefix = os.path.abspath(args.prefix).replace('\\','/') + + # check and setup the exec_prefix + if getattr(args, 'exec_prefix', None) is None: + exec_prefix_use_shorthand = True + self.exec_prefix = '${prefix}' + else: + if args.exec_prefix.startswith('${prefix}'): + exec_prefix_use_shorthand = True + input_exec_prefix = args.prefix + args.exec_prefix[len('${prefix}'):] + else: + exec_prefix_use_shorthand = False + input_exec_prefix = args.exec_prefix + if not os.path.exists(input_exec_prefix): + raise SystemExit('Specified exec_prefix \'%s\' is invalid' % + args.exec_prefix) + if exec_prefix_use_shorthand is True: + self.exec_prefix = args.exec_prefix.replace('\\','/') + else: + self.exec_prefix = os.path.abspath(input_exec_prefix).replace('\\','/') + + # check and setup the includedir + if getattr(args, 'includedir', None) is None: + self.includedir = '${prefix}/include' + else: + if args.includedir.startswith('${prefix}'): + includedir_use_shorthand = True + input_includedir = args.prefix + args.includedir[len('${prefix}'):] + else: + if args.includedir.startswith('${exec_prefix}'): + includedir_use_shorthand = True + input_includedir = input_exec_prefix + args.includedir[len('${exec_prefix}'):] + else: + includedir_use_shorthand = False + input_includedir = args.includedir + if not os.path.exists(input_includedir): + raise SystemExit('Specified includedir \'%s\' is invalid' % + args.includedir) + if includedir_use_shorthand is True: + self.includedir = args.includedir.replace('\\','/') + else: + self.includedir = os.path.abspath(input_includedir).replace('\\','/') + + # check and setup the libdir + if getattr(args, 'libdir', None) is None: + self.libdir = '${prefix}/lib' + else: + if args.libdir.startswith('${prefix}'): + libdir_use_shorthand = True + input_libdir = args.prefix + args.libdir[len('${prefix}'):] + else: + if args.libdir.startswith('${exec_prefix}'): + libdir_use_shorthand = True + input_libdir = input_exec_prefix + args.libdir[len('${exec_prefix}'):] + else: + libdir_use_shorthand = False + input_libdir = args.libdir + if not os.path.exists(input_libdir): + raise SystemExit('Specified libdir \'%s\' is invalid' % + args.libdir) + if libdir_use_shorthand is True: + self.libdir = args.libdir.replace('\\','/') + else: + self.libdir = os.path.abspath(input_libdir).replace('\\','/') + + # setup dictionary for replacing items in *.pc.in + self.base_replace_items.update({'@VERSION@': self.version}) + self.base_replace_items.update({'@prefix@': self.prefix}) + self.base_replace_items.update({'@exec_prefix@': self.exec_prefix}) + self.base_replace_items.update({'@libdir@': self.libdir}) + self.base_replace_items.update({'@includedir@': self.includedir}) diff --git a/msvc/replace.py b/msvc/replace.py new file mode 100644 index 0000000..3aeceb1 --- /dev/null +++ b/msvc/replace.py @@ -0,0 +1,115 @@ +#!/usr/bin/python +# +# Simple utility script to manipulate +# certain types of strings in a file + +# This can be used in various projects where +# there is the need to replace strings in files, +# and is copied from GLib's $(srcroot)/win32 + +# Author: Fan, Chun-wei +# Date: September 03, 2014 + +import os +import sys +import re +import string +import argparse + +valid_actions = ['remove-prefix', + 'replace-var', + 'replace-str', + 'remove-str'] + +def open_file(filename, mode): + if sys.version_info[0] < 3: + return open(filename, mode=mode) + else: + return open(filename, mode=mode, encoding='utf-8') + +def replace_multi(src, dest, replace_items): + with open_file(src, 'r') as s: + with open_file(dest, 'w') as d: + for line in s: + replace_dict = dict((re.escape(key), value) \ + for key, value in replace_items.items()) + replace_pattern = re.compile("|".join(replace_dict.keys())) + d.write(replace_pattern.sub(lambda m: \ + replace_dict[re.escape(m.group(0))], line)) + +def replace(src, dest, instring, outstring): + replace_item = {instring: outstring} + replace_multi(src, dest, replace_item) + +def check_required_args(args, params): + for param in params: + if getattr(args, param, None) is None: + raise SystemExit('%s: error: --%s argument is required' % (__file__, param)) + +def warn_ignored_args(args, params): + for param in params: + if getattr(args, param, None) is not None: + print('%s: warning: --%s argument is ignored' % (__file__, param)) + +def main(argv): + + parser = argparse.ArgumentParser(description='Process strings in a file.') + parser.add_argument('-a', + '--action', + help='Action to carry out. Can be one of:\n' + 'remove-prefix\n' + 'replace-var\n' + 'replace-str\n' + 'remove-str', + choices=valid_actions) + parser.add_argument('-i', '--input', help='Input file') + parser.add_argument('-o', '--output', help='Output file') + parser.add_argument('--instring', help='String to replace or remove') + parser.add_argument('--var', help='Autotools variable name to replace') + parser.add_argument('--outstring', + help='New String to replace specified string or variable') + parser.add_argument('--removeprefix', help='Prefix of string to remove') + + args = parser.parse_args() + + input_string = '' + output_string = '' + + # We must have action, input, output for all operations + check_required_args(args, ['action','input','output']) + + # Build the arguments by the operation that is to be done, + # to be fed into replace() + + # Get rid of prefixes from a string + if args.action == 'remove-prefix': + check_required_args(args, ['instring','removeprefix']) + warn_ignored_args(args, ['outstring','var']) + input_string = args.removeprefix + args.instring + output_string = args.instring + + # Replace an m4-style variable (those surrounded by @...@) + if args.action == 'replace-var': + check_required_args(args, ['var','outstring']) + warn_ignored_args(args, ['instring','removeprefix']) + input_string = '@' + args.var + '@' + output_string = args.outstring + + # Replace a string + if args.action == 'replace-str': + check_required_args(args, ['instring','outstring']) + warn_ignored_args(args, ['var','removeprefix']) + input_string = args.instring + output_string = args.outstring + + # Remove a string + if args.action == 'remove-str': + check_required_args(args, ['instring']) + warn_ignored_args(args, ['var','outstring','removeprefix']) + input_string = args.instring + output_string = '' + + replace(args.input, args.output, input_string, output_string) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/src/Makefile.am b/src/Makefile.am index 089e27e..ae8474e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,5 @@ +include libpsl-srcs.mk + # suffixes.c must be created before psl.c is compiled BUILT_SOURCES = suffixes_dafsa.c @@ -6,7 +8,7 @@ CLEANFILES = suffixes_dafsa.c lib_LTLIBRARIES = libpsl.la -libpsl_la_SOURCES = psl.c lookup_string_in_fixed_set.c +libpsl_la_SOURCES = $(LIBPSL_SRCS) libpsl_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -DPSL_DISTFILE=\"$(PSL_DISTFILE)\" \ $(CFLAG_VISIBILITY) -DBUILDING_PSL libpsl_la_LIBADD = $(LTLIBICONV) $(LTLIBINTL) @INTL_MACOSX_LIBS@ diff --git a/src/libpsl-srcs.mk b/src/libpsl-srcs.mk new file mode 100644 index 0000000..8f22123 --- /dev/null +++ b/src/libpsl-srcs.mk @@ -0,0 +1 @@ +LIBPSL_SRCS = psl.c lookup_string_in_fixed_set.c \ No newline at end of file