1#!/usr/bin/env python3 2# 3# Setup script for libxml2 and libxslt if found 4# 5import sys, os 6 7try: 8 from setuptools import setup, Extension 9except ImportError: 10 try: 11 # Using distutils, for python < 3.12 12 from distutils.core import setup, Extension 13 except ImportError: 14 # distutils is not present in python 3.12 and greater 15 print("setuptools is required for python >= 3.12") 16 sys.exit(1) 17 18# Below ROOT, we expect to find include, include/libxml2, lib and bin. 19# On *nix, it is not needed (but should not harm), 20# on Windows, it is set by configure.js. 21ROOT = r'@prefix@' 22 23# Thread-enabled libxml2 24with_threads = @WITH_THREADS@ 25 26# Features of libxml2 requiring external DLLs 27with_iconv = @WITH_ICONV@ 28with_zlib = @WITH_ZLIB@ 29with_lzma = @WITH_LZMA@ 30with_icu = @WITH_ICU@ 31 32icu_series = 69 33 34if icu_series is not None: 35 icu_series_s = str(icu_series) 36else: 37 icu_series_s = '' 38 39# If bundling DLLs, check the following to ensure things are correct 40# (Check the value of `icu_series` above as well) 41iconv_dll = 'iconv.dll' 42zlib_dll = 'zlib1.dll' 43lzma_dll = 'liblzma.dll' 44icu_dlls = ['icuuc%s.dll' % icu_series_s, 'icudt%s.dll' % icu_series_s] 45 46# If this flag is set (windows only), 47# a private copy of the dlls are included in the package. 48# If this flag is not set, the libxml2 and libxslt 49# dlls must be found somewhere in the PATH at runtime. 50WITHDLLS = 1 and sys.platform.startswith('win') 51 52if WITHDLLS: 53 def altImport(s): 54 s = s.replace("import libxml2mod","from libxmlmods import libxml2mod") 55 return s 56 57def missing(file): 58 if os.access(file, os.R_OK) == 0: 59 return 1 60 return 0 61 62try: 63 HOME = os.environ['HOME'] 64except: 65 HOME="C:" 66 67if sys.platform.startswith('win'): 68 libraryPrefix = 'lib' 69 platformLibs = [] 70else: 71 libraryPrefix = '' 72 platformLibs = ["m","z"] 73 74# those are examined to find 75# - libxml2/libxml/tree.h 76# - libxslt/xsltconfig.h 77includes_dir = [ 78"/usr/include", 79"/usr/local/include", 80"/opt/include", 81os.path.join(ROOT,'include'), 82HOME 83]; 84 85xml_includes="" 86for dir in includes_dir: 87 if not missing(dir + "/libxml2/libxml/tree.h"): 88 xml_includes=dir + "/libxml2" 89 break; 90 91if xml_includes == "": 92 print("failed to find headers for libxml2: update includes_dir") 93 sys.exit(1) 94 95# those are added in the linker search path for libraries 96libdirs = [ 97os.path.join(ROOT,'lib'), 98] 99 100xml_files = ["libxml2-api.xml", "libxml2-python-api.xml", 101 "libxml.c", "libxml.py", "libxml_wrap.h", "types.c", 102 "xmlgenerator.py", "README", "TODO", "drv_libxml2.py"] 103 104xslt_files = ["libxslt-api.xml", "libxslt-python-api.xml", 105 "libxslt.c", "libxsl.py", "libxslt_wrap.h", 106 "xsltgenerator.py"] 107 108if missing("libxml2-py.c") or missing("libxml2.py"): 109 try: 110 try: 111 import xmlgenerator 112 except: 113 import generator 114 except: 115 print("failed to find and generate stubs for libxml2, aborting ...") 116 print(sys.exc_info()[0], sys.exc_info()[1]) 117 sys.exit(1) 118 119 head = open("libxml.py", "r") 120 generated = open("libxml2class.py", "r") 121 result = open("libxml2.py", "w") 122 for line in head.readlines(): 123 if WITHDLLS: 124 result.write(altImport(line)) 125 else: 126 result.write(line) 127 for line in generated.readlines(): 128 result.write(line) 129 head.close() 130 generated.close() 131 result.close() 132 133with_xslt=0 134if missing("libxslt-py.c") or missing("libxslt.py"): 135 if missing("xsltgenerator.py") or missing("libxslt-api.xml"): 136 print("libxslt stub generator not found, libxslt not built") 137 else: 138 try: 139 import xsltgenerator 140 except: 141 print("failed to generate stubs for libxslt, aborting ...") 142 print(sys.exc_info()[0], sys.exc_info()[1]) 143 else: 144 head = open("libxsl.py", "r") 145 generated = open("libxsltclass.py", "r") 146 result = open("libxslt.py", "w") 147 for line in head.readlines(): 148 if WITHDLLS: 149 result.write(altImport(line)) 150 else: 151 result.write(line) 152 for line in generated.readlines(): 153 result.write(line) 154 head.close() 155 generated.close() 156 result.close() 157 with_xslt=1 158else: 159 with_xslt=1 160 161if with_xslt == 1: 162 xslt_includes="" 163 for dir in includes_dir: 164 if not missing(dir + "/libxslt/xsltconfig.h"): 165 xslt_includes=dir + "/libxslt" 166 break; 167 168 if xslt_includes == "": 169 print("failed to find headers for libxslt: update includes_dir") 170 with_xslt = 0 171 172if WITHDLLS: 173 # libxml dlls (expected in ROOT/bin) 174 dlls = [ 'libxml2.dll' ] 175 176 if with_zlib == 1: 177 dlls.append(zlib_dll) 178 if with_lzma == 1: 179 dlls.append(lzma_dll) 180 if with_iconv == 1: 181 dlls.append(iconv_dll) 182 if with_icu == 1: 183 dlls += icu_dlls 184 if with_xslt == 1: 185 dlls += ['libxslt.dll','libexslt.dll'] 186 187 packaged_dlls = [os.path.join(ROOT,'bin',dll) for dll in dlls] 188 189 # create __init__.py for the libxmlmods package 190 if not os.path.exists("libxmlmods"): 191 os.mkdir("libxmlmods") 192 open("libxmlmods/__init__.py","w").close() 193 194 packaged_dlls = [os.path.join(ROOT,'bin',dll) for dll in dlls] 195 196descr = "libxml2 package" 197modules = [ 'libxml2', 'drv_libxml2' ] 198if WITHDLLS: 199 modules.append('libxmlmods.__init__') 200c_files = ['libxml2-py.c', 'libxml.c', 'types.c' ] 201includes= [xml_includes] 202libs = [libraryPrefix + "xml2"] + platformLibs 203macros = [] 204if with_threads: 205 macros.append(('_REENTRANT','1')) 206if with_xslt == 1: 207 descr = "libxml2 and libxslt package" 208 if not sys.platform.startswith('win'): 209 # 210 # We are gonna build 2 identical shared libs with merge initializing 211 # both libxml2mod and libxsltmod 212 # 213 c_files = c_files + ['libxslt-py.c', 'libxslt.c'] 214 xslt_c_files = c_files 215 macros.append(('MERGED_MODULES', '1')) 216 else: 217 # 218 # On windows the MERGED_MODULE option is not needed 219 # (and does not work) 220 # 221 xslt_c_files = ['libxslt-py.c', 'libxslt.c', 'types.c'] 222 libs.insert(0, libraryPrefix + 'exslt') 223 libs.insert(0, libraryPrefix + 'xslt') 224 includes.append(xslt_includes) 225 modules.append('libxslt') 226 227 228extens=[Extension('libxml2mod', c_files, include_dirs=includes, 229 library_dirs=libdirs, 230 libraries=libs, define_macros=macros)] 231if with_xslt == 1: 232 extens.append(Extension('libxsltmod', xslt_c_files, include_dirs=includes, 233 library_dirs=libdirs, 234 libraries=libs, define_macros=macros)) 235 236if missing("MANIFEST"): 237 238 manifest = open("MANIFEST", "w") 239 manifest.write("setup.py\n") 240 for file in xml_files: 241 manifest.write(file + "\n") 242 if with_xslt == 1: 243 for file in xslt_files: 244 manifest.write(file + "\n") 245 manifest.close() 246 247if WITHDLLS: 248 ext_package = "libxmlmods" 249 if sys.version >= "2.2": 250 base = "lib/site-packages/" 251 else: 252 base = "" 253 data_files = [(base+"libxmlmods",packaged_dlls)] 254else: 255 ext_package = None 256 data_files = [] 257 258setup (name = "libxml2-python", 259 # On *nix, the version number is created from setup.py.in 260 # On windows, it is set by configure.js 261 version = "@LIBXML_VERSION@", 262 description = descr, 263 author = "Daniel Veillard", 264 author_email = "[email protected]", 265 url = "https://gitlab.gnome.org/GNOME/libxml2", 266 license="MIT License", 267 py_modules=modules, 268 ext_modules=extens, 269 ext_package=ext_package, 270 data_files=data_files, 271 ) 272 273sys.exit(0) 274 275