Last active
February 7, 2024 09:28
-
-
Save gvanem/4c5622bbbaa8cbf1da6c55f1e9d2f831 to your computer and use it in GitHub Desktop.
A GNU-makefile for Pycurl/MSVC (tired of 'setup.py build' problems on Windows). Put in 'src' directory of Pycurl and do 'make -f Makefile.MSVC clean install'
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # GNU makefile 4.x for pycurl (MSVC) | |
| # | |
| # By <[email protected]> 2013 - 2024. | |
| # | |
| THIS_FILE := $(firstword $(MAKEFILE_LIST)) | |
| DATE := $(shell date +%d-%B-%Y) | |
| YEAR := $(shell date +%Y) | |
| VERSION := 7.45.2 | |
| MODULE = pycurl | |
| # | |
| # Options: Change to suite. | |
| # | |
| # Use Python 3.x (=1) or Python 2.x (=0) | |
| # Can be used from the command-line too: | |
| # make -f Makefile.MSVC clean all USE_PY3=0 | |
| # | |
| # The bitness (x86/x64) of Python X must off-cource match the bitness | |
| # of libcurl / OpenSSL libs. | |
| # | |
| USE_PY3 ?= 1 | |
| USE_OPENSSL ?= 1 | |
| USE_WINSSL ?= 1 | |
| USE_WSOCK_TRACE ?= 1 | |
| # | |
| # Change to suite: | |
| # | |
| CURL_ROOT ?= ../.. | |
| OPENSSL_ROOT ?= ../../../Crypto/OpenSSL | |
| # | |
| # Change to suite. These are my .lib names: | |
| # | |
| CURL_LIB ?= $(CURL_ROOT)/lib/libcurl_imp-$(CPU).lib | |
| OPENSSL_LIBS ?= $(OPENSSL_ROOT)/lib/libcrypto_imp-$(CPU).lib \ | |
| $(OPENSSL_ROOT)/lib/libssl_imp-$(CPU).lib | |
| PY2_ROOT = $(subst \,/,$(shell py.exe -2 -c 'import sys; print(sys.prefix)')) | |
| PY3_ROOT = $(subst \,/,$(shell py.exe -3 -c 'import sys; print(sys.prefix)')) | |
| OBJ_DIR = objects | |
| # | |
| # This assumes you have at least one 'python.exe' on PATH found by | |
| # the Python launcher 'py.exe'. Usually 'c:\Windows\py.exe'. | |
| # | |
| # The 'LIB' env-var should already be setup to point to the location | |
| # of 'python*.lib'. But specify it anyway explicitly in '$(EX_LIBS)' below. | |
| # | |
| ifeq ($(USE_PY3),1) | |
| PYTHON_ROOT = $(PY3_ROOT) | |
| PYTHON_LIB = $(word 1, $(wildcard $(PYTHON_ROOT)/libs/python3*.lib)) | |
| PY_MAJOR = 3 | |
| else | |
| PYTHON_ROOT = $(PY2_ROOT) | |
| PYTHON_LIB = $(word 1, $(wildcard $(PYTHON_ROOT)/libs/python2*.lib)) | |
| PY_MAJOR = 2 | |
| endif | |
| PYTHON = py.exe -$(PY_MAJOR) | |
| PY_MINOR = $(shell $(PYTHON) -c 'import sys; print (sys.version_info.minor)') | |
| PY_VERSION = $(PY_MAJOR).$(PY_MINOR) | |
| # | |
| # Python prior to 3.4 prints version-info to 'stderr'. | |
| # Python after 3.4 prints version-info to 'stdout'. | |
| # Hence this method is unrealiable: | |
| # | |
| # PY_VERSION = $(shell $(PYTHON) -V 2>&1 | sed -e 's/Python //' -e 's/\.[0-9]$$//') | |
| # | |
| CC = cl | |
| CFLAGS = -nologo -MD -Zi -Ot -W3 -GF \ | |
| -I. \ | |
| -I$(PYTHON_ROOT)/include \ | |
| -I$(CURL_ROOT)/include \ | |
| -I./$(OBJ_DIR) \ | |
| -DWIN32_LEAN_AND_MEAN \ | |
| -D_WIN32_WINNT=0x0601 \ | |
| -DPYCURL_INTERNAL= \ | |
| -DPYCURL_AVOID_STDIO \ | |
| -DPYCURL_VERSION='$(VERSION)' \ | |
| # -D_WINSOCK_DEPRECATED_NO_WARNINGS | |
| LDFLAGS = -nologo -debug -verbose -map -incremental:no -dll -manifest -libpath:$(PYTHON_ROOT)/libs | |
| RCFLAGS = -nologo -r -I$(PYTHON_ROOT)/include | |
| ifeq ($(USE_PY3),1) | |
| LDFLAGS += -export:PyInit_pycurl | |
| else | |
| LDFLAGS += -export:initpycurl | |
| endif | |
| EX_LIBS = $(PYTHON_LIB) $(CURL_LIB) | |
| ifneq ($(USE_OPENSSL)$(USE_WINSSL),00) | |
| # $(error "Cannot have both 'USE_OPENSSL=1' and 'USE_WINSSL=1'.") | |
| CFLAGS += -DHAVE_CURL_SSL | |
| endif | |
| ifeq ($(USE_OPENSSL),1) | |
| CFLAGS += -I$(OPENSSL_ROOT)/include -DHAVE_CURL_OPENSSL | |
| EX_LIBS += $(OPENSSL_LIBS) | |
| endif | |
| ifeq ($(USE_WINSSL),1) | |
| CFLAGS += -DHAVE_CURL_WINSSL -DHAVE_CURL_SCHANNEL | |
| endif | |
| # | |
| # A 'wsock_trace-x64.lib' must be on 'LIB' path. | |
| # | |
| ifeq ($(USE_WSOCK_TRACE),1) | |
| OS_LIBS = wsock_trace-$(CPU).lib | |
| else | |
| OS_LIBS = ws2_32.lib | |
| endif | |
| OS_LIBS += kernel32.lib | |
| GENERATED = $(OBJ_DIR)/docstrings.c \ | |
| $(OBJ_DIR)/docstrings.h \ | |
| $(OBJ_DIR)/manifest.c | |
| SOURCES = easy.c \ | |
| easycb.c \ | |
| easyinfo.c \ | |
| easyopt.c \ | |
| easyperform.c \ | |
| module.c \ | |
| multi.c \ | |
| oscompat.c \ | |
| pythoncompat.c \ | |
| share.c \ | |
| stringcompat.c \ | |
| threadsupport.c \ | |
| util.c | |
| vpath %.c $(OBJ_DIR) | |
| SOURCES += $(OBJ_DIR)/docstrings.c \ | |
| $(OBJ_DIR)/manifest.c | |
| OBJECTS = $(addprefix $(OBJ_DIR)/, \ | |
| $(notdir $(SOURCES:.c=.obj))) | |
| ################################################################################# | |
| all: intro $(GENERATED) $(MODULE).pyd epilogue | |
| intro: | |
| ifeq ($(PYTHON_LIB),) | |
| $(error 'PYTHON_LIB' not found.) | |
| endif | |
| $(call green_msg, Building pycurl v. $(VERSION) using Python ver. $(PY_VERSION).) | |
| epilogue: | |
| $(call green_msg, Do a "make -f $(THIS_FILE) install" at own risk.) | |
| $(MODULE).pdb: $(MODULE).pyd | |
| $(MODULE).pyd: $(OBJECTS) $(OBJ_DIR)/$(MODULE).res $(EX_LIBS) | |
| link $(LDFLAGS) -out:$@ $^ $(OS_LIBS) > link.tmp | |
| @cat link.tmp >> $(MODULE).map | |
| mt -nologo -manifest [email protected] -outputresource:"$@;1" | |
| @rm -f $(MODULE).{exp,lib} | |
| @echo | |
| $(OBJ_DIR): | |
| mkdir $@ | |
| # | |
| # Just some test targets | |
| # | |
| get_manifest: $(MODULE).pyd | |
| mt -nologo -inputresource:$(MODULE).pyd -out:manifest.txt | |
| @echo | |
| test: | |
| $(call green_msg0, PY2_ROOT: "$(PY2_ROOT)".) | |
| $(call green_msg0, PY3_ROOT: "$(PY3_ROOT)".) | |
| $(call green_msg0, VERSION: "$(VERSION)".) | |
| $(OBJ_DIR)/%.obj: %.c | $(OBJ_DIR) | |
| $(CC) -c $(CFLAGS) -Fo$@ $< | |
| @echo | |
| $(OBJ_DIR)/$(MODULE).res: $(OBJ_DIR)/$(MODULE).rc | |
| rc $(RCFLAGS) -fo $@ $< | |
| @echo | |
| $(OBJ_DIR)/$(MODULE).rc: $(THIS_FILE) | |
| $(call generate, $@, //) | |
| $(file >> $@,$(PYCURL_RC)) | |
| $(OBJ_DIR)/manifest.c: $(THIS_FILE) | $(OBJ_DIR) | |
| $(call generate, $@, //) | |
| $(file > $@,$(MANIFEST_C)) | |
| $(OBJ_DIR)/docstrings.c $(OBJ_DIR)/docstrings.h: | $(OBJ_DIR) | |
| cd .. ; \ | |
| $(PYTHON) setup.py docstrings | |
| mv docstrings.[ch] $(OBJ_DIR) | |
| @echo | |
| install: $(MODULE).pyd $(MODULE).pdb ../python/curl/__init__.py | |
| - mkdir $(PYTHON_ROOT)/Lib/site-packages/curl | |
| cp --update $(MODULE).pyd $(MODULE).pdb $(PYTHON_ROOT)/Lib/site-packages | |
| cp --update ../python/curl/__init__.py $(PYTHON_ROOT)/Lib/site-packages/curl | |
| @echo | |
| clean: | |
| rm -fr $(OBJ_DIR) | |
| rm -f vc1*.pdb link.tmp $(MODULE).pyd.manifest | |
| vclean realclean: clean | |
| rm -f $(MODULE).{pyd,pdb,lib,map} .depend.MSVC | |
| comma := , | |
| $(OBJ_DIR)/cpp-filter.py: $(THIS_FILE) | $(OBJ_DIR) | |
| $(call generate, $@, #) | |
| $(file >> $@,if 1:) | |
| $(file >> $@,$(CPP_FILTER_PY)) | |
| # | |
| # To generated pre-processed output (in case something goes wrong). | |
| # | |
| %.i: %.c FORCE | $(OBJ_DIR)/cpp-filter.py | |
| $(CC) -E $(CFLAGS) $< | $(PYTHON) $(OBJ_DIR)/cpp-filter.py > $@ | |
| @echo | |
| FORCE: | |
| DEP_CFLAGS = -MM $(filter -D% -I%, $(CFLAGS)) | |
| DEP_REPLACE = sed -e 's/\(.*\)\.o: /\n\1.obj: /' | |
| # | |
| # Since this could be a Cygwin 'gcc': | |
| # | |
| DEP_CFLAGS += -DPy_PYPORT_H -DPYLONG_BITS_IN_DIGIT=30 -D_MSC_VER=1900 | |
| depend: $(THIS_FILE) $(GENERATED) | |
| gcc $(DEP_CFLAGS) $(SOURCES) | $(DEP_REPLACE) > .depend.MSVC | |
| @echo | |
| # | |
| # GNU-make macros. | |
| # | |
| # This assumes you have a MSys/Cygwin's 'echo.exe' with colour support. | |
| # | |
| BRIGHT_GREEN = \e[1;32m | |
| colour_msg = @echo -e '$(1)\e[0m' | |
| green_msg = $(call colour_msg,$(BRIGHT_GREEN)$(strip $(1))) | |
| green_msg0 = $(call colour_msg,$(BRIGHT_GREEN)$(1)) | |
| define generate | |
| $(call green_msg, Generating $(1)) | |
| $(file > $(1),$(call Warning,$(2))) | |
| endef | |
| define Warning | |
| $(1) | |
| $(1) DO NOT EDIT! This file was automatically generated | |
| $(1) from $(realpath $(THIS_FILE)) at $(DATE). | |
| $(1) Edit that file instead. | |
| $(1) | |
| endef | |
| define PYCURL_RC | |
| #include <winver.h> | |
| #include "patchlevel.h" /* In '$(PYTHON_ROOT)/include' */ | |
| #define RC_VERSION $(subst .,$(comma),$(VERSION)) | |
| #define RC_VER_STRING "$(VERSION)" | |
| #define PY_VER_STRING "$(PY_VERSION)" | |
| APPICON ICON "../doc/static/favicon.ico" | |
| VS_VERSION_INFO VERSIONINFO | |
| FILEVERSION RC_VERSION | |
| PRODUCTVERSION RC_VERSION | |
| FILEFLAGSMASK 0x3FL | |
| FILEFLAGS 0 | |
| FILEOS VOS__WINDOWS32 | |
| FILETYPE VFT_DLL | |
| FILESUBTYPE 0x0L | |
| BEGIN | |
| BLOCK "StringFileInfo" | |
| BEGIN | |
| BLOCK "040904B0" | |
| BEGIN | |
| VALUE "CompanyName", "Python interface to libcurl." | |
| VALUE "FileDescription", "Python interface to libcurl." | |
| VALUE "FileVersion", RC_VER_STRING ", Python " PY_VER_STRING "." | |
| VALUE "InternalName", "PycURL" | |
| VALUE "OriginalFilename", "$(MODULE).pyd." | |
| VALUE "ProductName", "Python$(PY_MAJOR) interface to libcurl." | |
| VALUE "ProductVersion", RC_VER_STRING " (MSVC) built on $(DATE)." | |
| VALUE "Comments", "" | |
| VALUE "LegalCopyright", "LGPL and an MIT/X derivative license.\r\n" | |
| "\t\t\tCopyright (C) 2001-2008 Kjetil Jacobsen.\r\n" | |
| "\t\t\tCopyright (C) 2001-2008 Markus F.X.J. Oberhumer." | |
| END | |
| END | |
| BLOCK "VarFileInfo" | |
| BEGIN | |
| VALUE "Translation", 0x409, 1200 | |
| END | |
| END | |
| #define MANIFEST_RESOURCE_ID 1 | |
| #define RT_MANIFEST 24 | |
| #if 0 | |
| /* | |
| * How to solve this problem: The below manifest is generated in the | |
| * link step. The link step also needs the .res file. Not sure a | |
| * manifest in a .res-file is a good idea anyway. | |
| */ | |
| MANIFEST_RESOURCE_ID RT_MANIFEST "$(MODULE).pyd.manifest" | |
| #endif | |
| endef | |
| define MANIFEST_C | |
| #pragma comment (linker, "/manifestdependency:type='win32'") | |
| #pragma comment (linker, "/manifestdependency:name='Microsoft.VC90.CRT'") | |
| #pragma comment (linker, "/manifestdependency:version='9.0.30411.0'") | |
| #pragma comment (linker, "/manifestdependency:processorArchitecture='$(PROCESSOR_ARCHITECTURE)'") | |
| #pragma comment (linker, "/manifestdependency:publicKeyToken='1fc8b3b9a1e18e3b'") | |
| endef | |
| define CPP_FILTER_PY | |
| import sys, os | |
| empty_lines = 0 | |
| while True: | |
| line = sys.stdin.readline() | |
| if not line: | |
| break | |
| line = line.rstrip() | |
| if line == "": | |
| empty_lines += 1 | |
| continue | |
| if line.lstrip().startswith("#line") or line.lstrip().startswith("# "): | |
| line = line.replace (r"\\", "/") | |
| print (line) | |
| if line == "}" or line == "};": | |
| print ("") | |
| print ("Removed %d empty lines." % empty_lines, file=sys.stderr) | |
| endef | |
| -include .depend.MSVC | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment