From d4e1b63c191c2d062bf5005111e480e3ffe7541a Mon Sep 17 00:00:00 2001 From: Gabi Davar Date: Sat, 4 Jul 2015 23:07:30 +0300 Subject: [PATCH] msvc build fixes and enchantments. * fix build broken by recent changes * place all build artifacts to OBJDIR * explicitly add manifest (VC9/10) * modernize python bindings creation * some minor refactoring --- .gitignore | 7 ++ lib/Makefile.msvc | 166 ++++++++++++++++++++++-------------- lib/nghttp2_hd.c | 2 +- lib/nghttp2_hd.h | 2 +- lib/nghttp2_priority_spec.c | 6 +- lib/nghttp2_session.c | 16 ++-- python/setup.py.in | 21 ++--- 7 files changed, 130 insertions(+), 90 deletions(-) diff --git a/.gitignore b/.gitignore index b80564ff..7adeac3d 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,10 @@ test-driver # test logs generated by `make check` *.log *.trs + +lib/MSVC_obj/ +_VC_ROOT/ +.depend.MSVC +*.pyd +*.egg-info/ +python/nghttp2.c diff --git a/lib/Makefile.msvc b/lib/Makefile.msvc index edc6d740..294e9f72 100644 --- a/lib/Makefile.msvc +++ b/lib/Makefile.msvc @@ -10,50 +10,68 @@ # Choose your weapons: # Set 'USE_CYTHON=1' to build and install the 'nghttp2.pyd' Python extension. # -USE_CYTHON = 1 +THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) -_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g') -_VERSION := $(subst ., ,$(_VERSION)) -VER_MAJOR = $(word 1,$(_VERSION)) -VER_MINOR = $(word 2,$(_VERSION)) -VER_MICRO = $(word 3,$(_VERSION)) -VERSION = $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO) -VERSION_NUM = ($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO) +USE_CYTHON := 1 +#USE_CYTHON := 0 -GENERATED = 'Generated by $(realpath Makefile.MSVC)' +_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g') +_VERSION := $(subst ., ,$(_VERSION)) +VER_MAJOR := $(word 1,$(_VERSION)) +VER_MINOR := $(word 2,$(_VERSION)) +VER_MICRO := $(word 3,$(_VERSION)) +VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO) +VERSION_NUM := ($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO) + +GENERATED := 'Generated by $(realpath Makefile.MSVC)' + +OBJ_DIR := MSVC_obj +#SUFFIX :=-vc90-mt-x86 # # Where to copy nghttp2.dll + lib + headers to. # Note: 'make install' is not in default targets. Do it explicitly. # -VC_ROOT = $(realpath $(VCINSTALLDIR)) -INSTALL_BIN = $(VC_ROOT)/bin -INSTALL_LIB = $(VC_ROOT)/lib -INSTALL_HDR = $(VC_ROOT)/include +TARGET_DIR ?= ../_VC_ROOT +VC_ROOT := $(abspath $(TARGET_DIR)) +INSTALL_BIN := $(VC_ROOT)/bin +INSTALL_LIB := $(VC_ROOT)/lib +INSTALL_HDR := $(VC_ROOT)/include +DLL_R := $(OBJ_DIR)/nghttp2$(SUFFIX).dll +DLL_D := $(OBJ_DIR)/nghttp2d$(SUFFIX).dll +LIB_R := $(OBJ_DIR)/nghttp2-static.lib +LIB_D := $(OBJ_DIR)/nghttp2d-static.lib +IMP_R := $(OBJ_DIR)/nghttp2.lib +IMP_D := $(OBJ_DIR)/nghttp2d.lib # # Build for DEBUG-model and RELEASE at the same time. # -TARGETS = nghttp2.lib nghttp2.dll nghttp2_imp.lib \ - nghttp2d.lib nghttp2d.dll nghttp2d_imp.lib +TARGETS := $(LIB_R) $(DLL_R) $(IMP_R) \ + $(LIB_D) $(DLL_D) $(IMP_D) EXT_LIBS = -OBJ_DIR = MSVC_obj - -NGHTTP2_PDB_R = $(OBJ_DIR)/nghttp2.pdb -NGHTTP2_PDB_D = $(OBJ_DIR)/nghttp2d.pdb +NGHTTP2_PDB_R := $(OBJ_DIR)/nghttp2.pdb +NGHTTP2_PDB_D := $(OBJ_DIR)/nghttp2d.pdb CC = cl -CFLAGS = -I./includes -Dssize_t=long -D_U_="" +LD := link +AR := lib +#CC := icl +#LD := xilink +#AR := xilib +RC := rc +CFLAGS := -I./includes -Dssize_t=long -D_U_="" -CFLAGS_R = -nologo -MD -W3 -Zi -Fd./$(NGHTTP2_PDB_R) -CFLAGS_D = -nologo -MDd -W3 -Zi -Fd./$(NGHTTP2_PDB_D) \ +CFLAGS_R := -nologo -MD -W3 -Z7 -DBUILDING_NGHTTP2 +CFLAGS_D := -nologo -MDd -W3 -Z7 -DBUILDING_NGHTTP2 \ -Ot -D_DEBUG -GF -RTCs -RTCu # -RTCc -GS -LDFLAGS = -nologo -machine:x64 -map -debug -incremental:no # -verbose +LDFLAGS := -nologo -MAP -debug -incremental:no -opt:ref,icf -MANIFEST # -verbose -NGHTTP2_SRC = nghttp2_pq.c \ + +NGHTTP2_SRC := nghttp2_pq.c \ nghttp2_map.c \ nghttp2_queue.c \ nghttp2_frame.c \ @@ -74,10 +92,16 @@ NGHTTP2_SRC = nghttp2_pq.c \ nghttp2_mem.c \ nghttp2_http.c -NGHTTP2_OBJ_R = $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj))) -NGHTTP2_OBJ_D = $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj))) +NGHTTP2_OBJ_R := $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj))) +NGHTTP2_OBJ_D := $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj))) -all: intro $(OBJ_DIR) $(TARGETS) +.PHONY: all intro test_ver install copy_headers_and_libs \ + install_nghttp2_pyd_0 install_nghttp2_pyd_1 \ + build_nghttp2_pyd_0 build_nghttp2_pyd_1 \ + clean_nghttp2_pyd_0 clean_nghttp2_pyd_1 + + +all: intro $(OBJ_DIR) $(TARGETS) build_nghttp2_pyd_$(USE_CYTHON) @echo 'Welcome to NgHTTP2 (release + debug).' @echo 'Do a "make -f Makefile.MSVC install" at own risk!' @@ -95,73 +119,88 @@ $(OBJ_DIR): - mkdir $(OBJ_DIR) install: includes/nghttp2/nghttp2.h includes/nghttp2/nghttp2ver.h \ - nghttp2.dll nghttp2.lib nghttp2_imp.lib \ - nghttp2d.dll nghttp2d.lib nghttp2d_imp.lib \ - copy_headers_and_libs install_nghttp2_pyd_$(USE_CYTHON) + $(TARGETS) \ + copy_headers_and_libs install_nghttp2_pyd_$(USE_CYTHON) # # This MUST be done before using the 'install_nghttp2_pyd_1' rule. # copy_headers_and_libs: - - mkdir $(INSTALL_HDR)/nghttp2 + - mkdir -p $(INSTALL_HDR)/nghttp2 $(INSTALL_BIN) $(INSTALL_LIB) cp --update $(addprefix includes/nghttp2/, nghttp2.h nghttp2ver.h) $(INSTALL_HDR)/nghttp2 - cp --update nghttp2.dll nghttp2d.dll $(NGHTTP2_PDB_R) $(NGHTTP2_PDB_D) $(INSTALL_BIN) - cp --update nghttp2.lib nghttp2d.lib nghttp2_imp.lib nghttp2d_imp.lib $(INSTALL_LIB) + cp --update $(DLL_R) $(DLL_D) $(NGHTTP2_PDB_R) $(NGHTTP2_PDB_D) $(INSTALL_BIN) + cp --update $(IMP_R) $(IMP_D) $(LIB_R) $(LIB_D) $(INSTALL_LIB) @echo -nghttp2.lib: $(NGHTTP2_OBJ_R) - lib -nologo -out:$@ $^ +$(LIB_R): $(NGHTTP2_OBJ_R) + $(AR) -nologo -out:$@ $^ @echo -nghttp2d.lib: $(NGHTTP2_OBJ_D) - lib -nologo -out:$@ $^ +$(LIB_D): $(NGHTTP2_OBJ_D) + $(AR) -nologo -out:$@ $^ @echo -nghttp2.dll nghttp2_imp.lib: $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res - link $(LDFLAGS) -dll -out:nghttp2.dll -implib:nghttp2_imp.lib \ - $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS) + +$(IMP_R): $(DLL_R) + +$(DLL_R): $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res + $(LD) $(LDFLAGS) -dll -out:$@ -implib:$(IMP_R) $(NGHTTP2_OBJ_R) -PDB:$(NGHTTP2_PDB_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS) + mt -nologo -manifest $@.manifest -outputresource:$@\;2 @echo -nghttp2d.dll nghttp2d_imp.lib: $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res - link $(LDFLAGS) -dll -out:nghttp2d.dll -implib:nghttp2d_imp.lib \ - $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS) +$(IMP_D): $(DLL_D) + +$(DLL_D): $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res + $(LD) $(LDFLAGS) -dll -out:$@ -implib:$(IMP_D) $(NGHTTP2_OBJ_D) -PDB:$(NGHTTP2_PDB_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS) + mt -nologo -manifest $@.manifest -outputresource:$@\;2 @echo -install_nghttp2_pyd_0: ; -install_nghttp2_pyd_1: $(addprefix ../python/, setup.py.in nghttp2.pyx) +WIN_OBJDIR:=$(shell cygpath -w $(abspath $(OBJ_DIR))) +WIN_OBJDIR:=$(subst \,/,$(WIN_OBJDIR)) + +../python/setup.py: ../python/setup.py.in $(THIS_MAKEFILE) cd ../python ; \ echo '# $(GENERATED). DO NOT EDIT.' > setup.py ; \ sed -e 's/@top_srcdir@/../' \ - -e 's/@top_builddir@/../' \ - -e 's/@PACKAGE_VERSION@/$(VERSION)/' setup.py.in >> setup.py ; \ - cython -v nghttp2.pyx ; \ - python setup.py install + -e 's%@top_builddir@%$(WIN_OBJDIR)%' \ + -e 's/@PACKAGE_VERSION@/$(VERSION)/' setup.py.in >> setup.py ; + +build_nghttp2_pyd_0: ; + +build_nghttp2_pyd_1: $(addprefix ../python/, setup.py nghttp2.pyx) + cd ../python ; \ + python setup.py build_ext -i -f bdist_wininst + +install_nghttp2_pyd_0: ; + +install_nghttp2_pyd_1: $(addprefix ../python/, setup.py nghttp2.pyx) + cd ../python ; \ + pip install . clean_nghttp2_pyd_0: ; clean_nghttp2_pyd_1: cd ../python ; \ - rm -f setup.py nghttp2.c ; \ - rm -fR build/* + rm -fR build dist -$(OBJ_DIR)/r_%.obj: %.c +$(OBJ_DIR)/r_%.obj: %.c $(THIS_MAKEFILE) $(CC) $(CFLAGS_R) $(CFLAGS) -Fo$@ -c $< @echo -$(OBJ_DIR)/d_%.obj: %.c +$(OBJ_DIR)/d_%.obj: %.c $(THIS_MAKEFILE) $(CC) $(CFLAGS_D) $(CFLAGS) -Fo$@ -c $< @echo -$(OBJ_DIR)/r_nghttp2.res: nghttp2.rc - rc -nologo -D_RELEASE -Fo $@ $< +$(OBJ_DIR)/r_nghttp2.res: $(OBJ_DIR)/nghttp2.rc $(THIS_MAKEFILE) + $(RC) -nologo -D_RELEASE -Fo $@ $< @echo -$(OBJ_DIR)/d_nghttp2.res: nghttp2.rc - rc -nologo -D_DEBUG -Fo $@ $< +$(OBJ_DIR)/d_nghttp2.res: $(OBJ_DIR)/nghttp2.rc $(THIS_MAKEFILE) + $(RC) -nologo -D_DEBUG -Fo $@ $< @echo -includes/nghttp2/nghttp2ver.h: includes/nghttp2/nghttp2ver.h.in +includes/nghttp2/nghttp2ver.h: includes/nghttp2/nghttp2ver.h.in $(THIS_MAKEFILE) sed < includes/nghttp2/nghttp2ver.h.in \ -e 's/@PACKAGE_VERSION@/$(VERSION)/g' \ -e 's/@PACKAGE_VERSION_NUM@/($(VERSION_NUM))/g' > $@ @@ -201,8 +240,6 @@ define RES_FILE VALUE "OriginalFilename", "nghttp2" DBG ".dll" VALUE "ProductName", "NGHTTP2." VALUE "ProductVersion", VER_STR - VALUE "PrivateBuild", "The privat build of ." - VALUE "SpecialBuild", "" END END BLOCK "VarFileInfo" @@ -214,20 +251,19 @@ endef export RES_FILE -nghttp2.rc: Makefile.MSVC +$(OBJ_DIR)/nghttp2.rc: Makefile.MSVC @echo 'Generating $@...' @echo ' /* $(GENERATED). DO NOT EDIT.' > $@ @echo ' */' >> $@ @echo "$$RES_FILE" >> $@ clean: - rm -f $(OBJ_DIR)/* nghttp2_imp.exp nghttp2_imp.exp \ - nghttp2.map nghttp2d.map nghttp2.rc includes/nghttp2/nghttp2ver.h + rm -f $(OBJ_DIR)/* includes/nghttp2/nghttp2ver.h @echo vclean realclean: clean clean_nghttp2_pyd_$(USE_CYTHON) - rm -f $(TARGETS) nghttp2.pdb nghttp2d.pdb nghttp2_imp.exp nghttp2d_imp.exp .depend.MSVC - - rmdir $(OBJ_DIR) + - rm -rf $(OBJ_DIR) + - rm -f .depend.MSVC # # Use gcc to generated the dependencies. No MSVC specific args please! diff --git a/lib/nghttp2_hd.c b/lib/nghttp2_hd.c index 83191211..edf9ecee 100644 --- a/lib/nghttp2_hd.c +++ b/lib/nghttp2_hd.c @@ -1274,7 +1274,7 @@ static size_t get_max_index(nghttp2_hd_context *context) { return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH - 1; } -nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context, +NGHTTP2_EXTERN nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) { assert(INDEX_RANGE_VALID(context, idx)); if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) { diff --git a/lib/nghttp2_hd.h b/lib/nghttp2_hd.h index 1b9ca7e9..bf40ab05 100644 --- a/lib/nghttp2_hd.h +++ b/lib/nghttp2_hd.h @@ -356,7 +356,7 @@ int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv, int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size); /* For unittesting purpose */ -nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context, +NGHTTP2_EXTERN nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index); /* For unittesting purpose */ diff --git a/lib/nghttp2_priority_spec.c b/lib/nghttp2_priority_spec.c index cd254b1f..377f37bd 100644 --- a/lib/nghttp2_priority_spec.c +++ b/lib/nghttp2_priority_spec.c @@ -24,7 +24,7 @@ */ #include "nghttp2_priority_spec.h" -void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, +NGHTTP2_EXTERN void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, int32_t stream_id, int32_t weight, int exclusive) { pri_spec->stream_id = stream_id; @@ -32,13 +32,13 @@ void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec, pri_spec->exclusive = exclusive != 0; } -void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec) { +NGHTTP2_EXTERN void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec) { pri_spec->stream_id = 0; pri_spec->weight = NGHTTP2_DEFAULT_WEIGHT; pri_spec->exclusive = 0; } -int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) { +NGHTTP2_EXTERN int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) { return pri_spec->stream_id == 0 && pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT && pri_spec->exclusive == 0; } diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 819b32a7..502dd920 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -75,7 +75,7 @@ static int is_non_fatal(int lib_error_code) { return lib_error_code < 0 && lib_error_code > NGHTTP2_ERR_FATAL; } -int nghttp2_is_fatal(int lib_error_code) { +NGHTTP2_EXTERN int nghttp2_is_fatal(int lib_error_code) { return lib_error_code < NGHTTP2_ERR_FATAL; } @@ -172,13 +172,13 @@ static int session_terminate_session(nghttp2_session *session, return 0; } -int nghttp2_session_terminate_session(nghttp2_session *session, +NGHTTP2_EXTERN int nghttp2_session_terminate_session(nghttp2_session *session, uint32_t error_code) { return session_terminate_session(session, session->last_proc_stream_id, error_code, NULL); } -int nghttp2_session_terminate_session2(nghttp2_session *session, +NGHTTP2_EXTERN int nghttp2_session_terminate_session2(nghttp2_session *session, int32_t last_stream_id, uint32_t error_code) { return session_terminate_session(session, last_stream_id, error_code, NULL); @@ -6552,7 +6552,7 @@ int nghttp2_session_consume(nghttp2_session *session, int32_t stream_id, return 0; } -int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) { +NGHTTP2_EXTERN int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) { int rv; if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) { @@ -6568,7 +6568,7 @@ int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) { return 0; } -int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id, +NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id, size_t size) { int rv; nghttp2_stream *stream; @@ -6596,7 +6596,7 @@ int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id, return 0; } -int nghttp2_session_set_next_stream_id(nghttp2_session *session, +NGHTTP2_EXTERN int nghttp2_session_set_next_stream_id(nghttp2_session *session, int32_t next_stream_id) { if (next_stream_id <= 0 || session->next_stream_id > (uint32_t)next_stream_id) { @@ -6615,10 +6615,10 @@ int nghttp2_session_set_next_stream_id(nghttp2_session *session, return 0; } -uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session) { +NGHTTP2_EXTERN uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session) { return session->next_stream_id; } -int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) { +NGHTTP2_EXTERN int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) { return session->last_proc_stream_id; } diff --git a/python/setup.py.in b/python/setup.py.in index 7f9de481..3abaddea 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -21,14 +21,10 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -import sys -from distutils.core import setup -from distutils.extension import Extension - -if sys.platform == "win32": - LIBS = ['nghttp2_imp', 'ws2_32'] -else: - LIBS = ['nghttp2'] +from setuptools import setup, Extension +from Cython.Build import cythonize + +LIBS = ['nghttp2'] setup( name = 'python-nghttp2', @@ -38,12 +34,13 @@ setup( author_email = 'tatsuhiro.t@gmail.com', url = 'https://nghttp2.org/', keywords = [], - ext_modules = [Extension("nghttp2", - ["nghttp2.c"], + ext_modules = cythonize([Extension("nghttp2", + ["nghttp2.pyx"], include_dirs=['@top_srcdir@/lib', '@top_srcdir@/lib/includes', '@top_builddir@/lib/includes'], - library_dirs=['@top_builddir@/lib/.libs'], - libraries=LIBS)], + library_dirs=['@top_builddir@/lib/.libs', + '@top_builddir@'], + libraries=LIBS)]), long_description='TBD' )