1# 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20# 21# 22# gen_win_dependencies.py 23# 24# base class for generating windows projects, containing the 25# dependency locator code shared between the test runner and 26# the make file generators 27# 28 29import os 30import sys 31import fnmatch 32import re 33import subprocess 34import string 35from collections import namedtuple 36 37if sys.version_info[0] >= 3: 38 # Python >=3.0 39 from io import StringIO 40else: 41 # Python <3.0 42 try: 43 from cStringIO import StringIO 44 except ImportError: 45 from StringIO import StringIO 46 47import gen_base 48import ezt 49 50UserMacro = namedtuple('UserMacro', ['name', 'value']) 51 52class SVNCommonLibrary: 53 54 def __init__(self, name, include_dirs, lib_dir, lib_name, version=None, 55 debug_lib_dir=None, debug_lib_name=None, dll_dir=None, 56 dll_name=None, debug_dll_dir=None, debug_dll_name=None, 57 defines=[], forced_includes=[], extra_bin=[], internal=False): 58 self.name = name 59 if include_dirs: 60 self.include_dirs = include_dirs if isinstance(include_dirs, list) \ 61 else [include_dirs] 62 else: 63 self.include_dirs = [] 64 self.defines = defines if not defines or isinstance(defines, list) else [defines] 65 self.lib_dir = lib_dir 66 self.lib_name = lib_name 67 self.version = version 68 self.dll_dir = dll_dir 69 self.dll_name = dll_name 70 71 self.forced_includes = forced_includes if not forced_includes \ 72 or isinstance(forced_includes, list) \ 73 else [forced_includes] 74 75 if debug_lib_dir: 76 self.debug_lib_dir = debug_lib_dir 77 else: 78 self.debug_lib_dir = lib_dir 79 80 if debug_lib_name: 81 self.debug_lib_name = debug_lib_name 82 else: 83 self.debug_lib_name = lib_name 84 85 if debug_dll_dir: 86 self.debug_dll_dir = debug_dll_dir 87 else: 88 self.debug_dll_dir = dll_dir 89 90 if debug_dll_name: 91 self.debug_dll_name = debug_dll_name 92 else: 93 self.debug_dll_name = dll_name 94 95 self.extra_bin = extra_bin 96 self.internal = internal 97 98class GenDependenciesBase(gen_base.GeneratorBase): 99 """This intermediate base class exists to be instantiated by win-tests.py, 100 in order to obtain information from build.conf and library paths without 101 actually doing any generation.""" 102 _extension_map = { 103 ('exe', 'target'): '.exe', 104 ('exe', 'object'): '.obj', 105 ('lib', 'target'): '.dll', 106 ('lib', 'object'): '.obj', 107 ('pyd', 'target'): '.pyd', 108 ('pyd', 'object'): '.obj', 109 ('so', 'target'): '.so', 110 ('so', 'object'): '.obj', 111 } 112 113 _libraries = {} # Dict of SVNCommonLibrary instances of found libraries 114 115 _optional_libraries = [ # List of optional libraries to suppress warnings 116 'db', 117 'intl', 118 'serf', 119 'sasl', 120 'swig', 121 'perl', 122 'python', 123 'py3c', 124 'ruby', 125 'java_sdk', 126 'openssl', 127 'apr_memcache', 128 129 # So optional, we don't even have any code to detect them on Windows 130 'magic', 131 'macos-plist', 132 'macos-keychain', 133 ] 134 135 # When build.conf contains a 'when = SOMETHING' where SOMETHING is not in 136 # this list, then the project is not generated on Windows. 137 _windows_when = [ 138 'INSTALL_APACHE_MODS', 139 # not 'SVN_USE_GMOCK', 140 ] 141 142 def parse_options(self, options): 143 self.apr_path = 'apr' 144 self.apr_util_path = 'apr-util' 145 self.apr_iconv_path = 'apr-iconv' 146 self.serf_path = None 147 self.bdb_path = None 148 self.httpd_path = None 149 self.libintl_path = None 150 self.zlib_path = 'zlib' 151 self.openssl_path = None 152 self.jdk_path = None 153 self.junit_path = None 154 self.swig_path = None 155 self.py3c_path = None 156 self.vs_version = '2002' 157 self.sln_version = '7.00' 158 self.vcproj_version = '7.00' 159 self.vcproj_extension = '.vcproj' 160 self.sqlite_path = 'sqlite-amalgamation' 161 self.skip_sections = { 'mod_dav_svn': None, 162 'mod_authz_svn': None, 163 'mod_dontdothat' : None, 164 'libsvn_auth_kwallet': None, 165 'libsvn_auth_gnome_keyring': None } 166 167 # Instrumentation options 168 self.disable_shared = None 169 self.static_apr = None 170 self.static_openssl = None 171 self.instrument_apr_pools = None 172 self.instrument_purify_quantify = None 173 self.sasl_path = None 174 self.cpp_defines = [] 175 self.user_macros = [] 176 177 # NLS options 178 self.enable_nls = None 179 180 for opt, val in options: 181 if opt == '--with-berkeley-db': 182 self.bdb_path = val 183 elif opt == '--with-apr': 184 self.apr_path = val 185 elif opt == '--with-apr-util': 186 self.apr_util_path = val 187 elif opt == '--with-apr-iconv': 188 self.apr_iconv_path = val 189 elif opt == '--with-serf': 190 self.serf_path = val 191 elif opt == '--with-httpd': 192 self.httpd_path = val 193 del self.skip_sections['mod_dav_svn'] 194 del self.skip_sections['mod_authz_svn'] 195 del self.skip_sections['mod_dontdothat'] 196 elif opt == '--with-libintl': 197 self.libintl_path = val 198 self.enable_nls = 1 199 elif opt == '--with-jdk': 200 self.jdk_path = val 201 elif opt == '--with-junit': 202 self.junit_path = val 203 elif opt == '--with-zlib': 204 self.zlib_path = val 205 elif opt == '--with-swig': 206 self.swig_path = val 207 elif opt == '--with-py3c': 208 self.py3c_path = val 209 elif opt == '--with-sqlite': 210 self.sqlite_path = val 211 elif opt == '--with-sasl': 212 self.sasl_path = val 213 elif opt == '--with-openssl': 214 self.openssl_path = val 215 elif opt == '--enable-purify': 216 self.instrument_purify_quantify = 1 217 self.instrument_apr_pools = 1 218 elif opt == '--enable-quantify': 219 self.instrument_purify_quantify = 1 220 elif opt == '--enable-pool-debug': 221 self.instrument_apr_pools = 1 222 elif opt == '--enable-nls': 223 self.enable_nls = 1 224 elif opt == '--disable-shared': 225 self.disable_shared = 1 226 elif opt == '--with-static-apr': 227 self.static_apr = 1 228 elif opt == '--with-static-openssl': 229 self.static_openssl = 1 230 elif opt == '-D': 231 self.cpp_defines.append(val) 232 elif opt == '--vsnet-version': 233 if val == '2002' or re.match('^7(\.\d+)?$', val): 234 self.vs_version = '2002' 235 self.sln_version = '7.00' 236 self.vcproj_version = '7.00' 237 self.vcproj_extension = '.vcproj' 238 elif val == '2003' or re.match('^8(\.\d+)?$', val): 239 self.vs_version = '2003' 240 self.sln_version = '8.00' 241 self.vcproj_version = '7.10' 242 self.vcproj_extension = '.vcproj' 243 elif val == '2005' or re.match('^9(\.\d+)?$', val): 244 self.vs_version = '2005' 245 self.sln_version = '9.00' 246 self.vcproj_version = '8.00' 247 self.vcproj_extension = '.vcproj' 248 elif val == '2008' or re.match('^10(\.\d+)?$', val): 249 self.vs_version = '2008' 250 self.sln_version = '10.00' 251 self.vcproj_version = '9.00' 252 self.vcproj_extension = '.vcproj' 253 elif val == '2010': 254 self.vs_version = '2010' 255 self.sln_version = '11.00' 256 self.vcproj_version = '10.0' 257 self.vcproj_extension = '.vcxproj' 258 elif val == '2012' or val == '11': 259 self.vs_version = '2012' 260 self.sln_version = '12.00' 261 self.vcproj_version = '11.0' 262 self.vcproj_extension = '.vcxproj' 263 elif val == '2013' or val == '12': 264 self.vs_version = '2013' 265 self.sln_version = '12.00' 266 self.vcproj_version = '12.0' 267 self.vcproj_extension = '.vcxproj' 268 elif val == '2015' or val == '14': 269 self.vs_version = '2015' 270 self.sln_version = '12.00' 271 self.vcproj_version = '14.0' 272 self.vcproj_extension = '.vcxproj' 273 elif val == '2017' or val == '15': 274 self.vs_version = '2017' 275 self.sln_version = '12.00' 276 self.vcproj_version = '14.1' 277 self.vcproj_extension = '.vcxproj' 278 elif val == '2019' or val == '16': 279 self.vs_version = '2019' 280 self.sln_version = '12.00' 281 self.vcproj_version = '14.2' 282 self.vcproj_extension = '.vcxproj' 283 elif re.match('^20\d+$', val): 284 print('WARNING: Unknown VS.NET version "%s",' 285 ' assuming VS2012. Your VS can probably upgrade') 286 self.vs_version = '2012' 287 self.sln_version = '12.00' 288 self.vcproj_version = '11.0' 289 self.vcproj_extension = '.vcxproj' 290 elif re.match('^1\d+$', val): 291 self.vs_version = val 292 self.sln_version = '12.00' 293 self.vcproj_version = val + '.0' 294 self.vcproj_extension = '.vcxproj' 295 else: 296 print('WARNING: Unknown VS.NET version "%s",' 297 ' assuming "%s"\n' % (val, '7.00')) 298 299 300 def __init__(self, fname, verfname, options, find_libs=True): 301 302 # parse (and save) the options that were passed to us 303 self.parse_options(options) 304 305 # Initialize parent 306 gen_base.GeneratorBase.__init__(self, fname, verfname, options) 307 308 # These files will be excluded from the build when they're not 309 # explicitly listed as project sources. 310 self._excluded_from_build = frozenset(self.private_includes 311 + self.private_built_includes) 312 313 if find_libs: 314 self.find_libraries(False) 315 316 def find_libraries(self, show_warnings): 317 "find required and optional libraries" 318 319 # Required dependencies 320 self._find_apr() 321 self._find_apr_util_etc() 322 self._find_zlib() 323 self._find_sqlite(show_warnings) 324 self._find_lz4() 325 self._find_utf8proc() 326 327 # Optional dependencies 328 self._find_httpd(show_warnings) 329 self._find_bdb(show_warnings) 330 self._find_openssl(show_warnings) 331 self._find_serf(show_warnings) 332 self._find_sasl(show_warnings) 333 self._find_libintl(show_warnings) 334 335 self._find_jdk(show_warnings) 336 337 # Swig (optional) dependencies 338 if self._find_swig(show_warnings): 339 self._find_perl(show_warnings) 340 # py3c is required to build python bindings, show check it first 341 if self._find_py3c(show_warnings): 342 self._find_python(show_warnings) 343 self._find_ruby(show_warnings) 344 345 def _find_apr(self): 346 "Find the APR library and version" 347 348 minimal_apr_version = (1, 4, 0) 349 350 if not self.apr_path: 351 sys.stderr.write("ERROR: Use '--with-apr' option to configure APR " + \ 352 "location.\n") 353 sys.exit(1) 354 355 inc_base = os.path.join(self.apr_path, 'include') 356 357 if os.path.isfile(os.path.join(inc_base, 'apr-1', 'apr_version.h')): 358 inc_path = os.path.join(inc_base, 'apr-1') 359 elif os.path.isfile(os.path.join(inc_base, 'apr_version.h')): 360 inc_path = inc_base 361 else: 362 sys.stderr.write("ERROR: 'apr_version' not found.\n") 363 sys.stderr.write("Use '--with-apr' option to configure APR location.\n") 364 sys.exit(1) 365 366 version_file_path = os.path.join(inc_path, 'apr_version.h') 367 txt = open(version_file_path).read() 368 369 vermatch = re.search(r'^\s*#define\s+APR_MAJOR_VERSION\s+(\d+)', txt, re.M) 370 major = int(vermatch.group(1)) 371 372 vermatch = re.search(r'^\s*#define\s+APR_MINOR_VERSION\s+(\d+)', txt, re.M) 373 minor = int(vermatch.group(1)) 374 375 vermatch = re.search(r'^\s*#define\s+APR_PATCH_VERSION\s+(\d+)', txt, re.M) 376 patch = int(vermatch.group(1)) 377 378 version = (major, minor, patch) 379 self.apr_version = apr_version = '%d.%d.%d' % version 380 381 if version < minimal_apr_version: 382 sys.stderr.write("ERROR: apr %s or higher is required " 383 "(%s found)\n" % ( 384 '.'.join(str(v) for v in minimal_apr_version), 385 self.apr_version)) 386 sys.exit(1) 387 388 suffix = '' 389 if major > 0: 390 suffix = '-%d' % major 391 392 defines = [] 393 if self.static_apr: 394 lib_name = 'apr%s.lib' % suffix 395 lib_dir = os.path.join(self.apr_path, 'LibR') 396 dll_dir = None 397 debug_dll_dir = None 398 dll_name = None 399 defines.extend(["APR_DECLARE_STATIC"]) 400 401 if not os.path.isdir(lib_dir) and \ 402 os.path.isfile(os.path.join(self.apr_path, 'lib', lib_name)): 403 # Installed APR instead of APR-Source 404 lib_dir = os.path.join(self.apr_path, 'lib') 405 debug_lib_dir = None 406 else: 407 debug_lib_dir = os.path.join(self.apr_path, 'LibD') 408 else: 409 lib_name = 'libapr%s.lib' % suffix 410 411 if os.path.isfile(os.path.join(self.apr_path, 'lib', lib_name)): 412 # Installed APR instead of APR-Source 413 lib_dir = os.path.join(self.apr_path, 'lib') 414 debug_lib_dir = None 415 else: 416 lib_dir = os.path.join(self.apr_path, 'Release') 417 if os.path.isfile(os.path.join(self.apr_path, 'Debug', lib_name)): 418 debug_lib_dir = os.path.join(self.apr_path, 'Debug') 419 else: 420 debug_lib_dir = None 421 422 dll_name = 'libapr%s.dll' % suffix 423 if os.path.isfile(os.path.join(lib_dir, dll_name)): 424 dll_dir = lib_dir 425 debug_dll_dir = debug_lib_dir 426 else: 427 dll_dir = os.path.join(self.apr_path, 'bin') 428 debug_dll_dir = None 429 430 extra_bin = [] 431 432 if dll_dir: 433 bin_files = os.listdir(dll_dir) 434 if debug_dll_dir and os.path.isdir(debug_dll_dir): 435 debug_bin_files = os.listdir(debug_dll_dir) 436 else: 437 debug_bin_files = bin_files 438 439 for bin in bin_files: 440 if bin in debug_bin_files: 441 if re.match('^(lib)?apr[-_].*' + suffix + '(d)?.dll$', bin): 442 extra_bin.append(bin) 443 444 self._libraries['apr'] = SVNCommonLibrary('apr', inc_path, lib_dir, lib_name, 445 apr_version, 446 debug_lib_dir=debug_lib_dir, 447 dll_dir=dll_dir, 448 dll_name=dll_name, 449 debug_dll_dir=debug_dll_dir, 450 defines=defines, 451 extra_bin=extra_bin) 452 453 def _find_apr_util_etc(self): 454 "Find the APR-util library and version" 455 456 minimal_aprutil_version = (1, 3, 0) 457 458 inc_base = os.path.join(self.apr_util_path, 'include') 459 460 if os.path.isfile(os.path.join(inc_base, 'apr-1', 'apu_version.h')): 461 inc_path = os.path.join(inc_base, 'apr-1') 462 elif os.path.isfile(os.path.join(inc_base, 'apu_version.h')): 463 inc_path = inc_base 464 else: 465 sys.stderr.write("ERROR: 'apu_version' not found.\n") 466 sys.stderr.write("Use '--with-apr-util' option to configure APR-Util location.\n") 467 sys.exit(1) 468 469 version_file_path = os.path.join(inc_path, 'apu_version.h') 470 txt = open(version_file_path).read() 471 472 vermatch = re.search(r'^\s*#define\s+APU_MAJOR_VERSION\s+(\d+)', txt, re.M) 473 major = int(vermatch.group(1)) 474 475 vermatch = re.search(r'^\s*#define\s+APU_MINOR_VERSION\s+(\d+)', txt, re.M) 476 minor = int(vermatch.group(1)) 477 478 vermatch = re.search(r'^\s*#define\s+APU_PATCH_VERSION\s+(\d+)', txt, re.M) 479 patch = int(vermatch.group(1)) 480 481 version = (major, minor, patch) 482 self.aprutil_version = aprutil_version = '%d.%d.%d' % version 483 484 if version < minimal_aprutil_version: 485 sys.stderr.write("ERROR: apr-util %s or higher is required " 486 "(%s found)\n" % ( 487 '.'.join(str(v) for v in minimal_aprutil_version), 488 aprutil_version)) 489 sys.exit(1) 490 491 suffix = '' 492 if major > 0: 493 suffix = '-%d' % major 494 495 defines = [] 496 if self.static_apr: 497 lib_name = 'aprutil%s.lib' % suffix 498 lib_dir = os.path.join(self.apr_util_path, 'LibR') 499 dll_dir = None 500 debug_dll_dir = None 501 dll_name = None 502 defines.extend(["APU_DECLARE_STATIC"]) 503 504 if not os.path.isdir(lib_dir) and \ 505 os.path.isfile(os.path.join(self.apr_util_path, 'lib', lib_name)): 506 # Installed APR-Util instead of APR-Util-Source 507 lib_dir = os.path.join(self.apr_util_path, 'lib') 508 debug_lib_dir = None 509 else: 510 debug_lib_dir = os.path.join(self.apr_util_path, 'LibD') 511 else: 512 lib_name = 'libaprutil%s.lib' % suffix 513 lib_dir = os.path.join(self.apr_util_path, 'Release') 514 515 if not os.path.isdir(lib_dir) and \ 516 os.path.isfile(os.path.join(self.apr_util_path, 'lib', lib_name)): 517 # Installed APR-Util instead of APR-Util-Source 518 lib_dir = os.path.join(self.apr_util_path, 'lib') 519 debug_lib_dir = lib_dir 520 else: 521 debug_lib_dir = os.path.join(self.apr_util_path, 'Debug') 522 523 dll_name = 'libaprutil%s.dll' % suffix 524 if os.path.isfile(os.path.join(lib_dir, dll_name)): 525 dll_dir = lib_dir 526 debug_dll_dir = debug_lib_dir 527 else: 528 dll_dir = os.path.join(self.apr_util_path, 'bin') 529 debug_dll_dir = None 530 531 extra_bin = [] 532 533 if dll_dir: 534 bin_files = os.listdir(dll_dir) 535 if debug_dll_dir and os.path.isdir(debug_dll_dir): 536 debug_bin_files = os.listdir(debug_dll_dir) 537 else: 538 debug_bin_files = bin_files 539 540 for bin in bin_files: 541 if bin in debug_bin_files: 542 if re.match('^(lib)?aprutil[-_].*' + suffix + '(d)?.dll$', bin): 543 extra_bin.append(bin) 544 545 self._libraries['aprutil'] = SVNCommonLibrary('apr-util', inc_path, lib_dir, 546 lib_name, 547 aprutil_version, 548 debug_lib_dir=debug_lib_dir, 549 dll_dir=dll_dir, 550 dll_name=dll_name, 551 debug_dll_dir=debug_dll_dir, 552 defines=defines, 553 extra_bin=extra_bin) 554 555 # Perhaps apr-util can also provide memcached support 556 if version >= (1, 3, 0) : 557 self._libraries['apr_memcache'] = SVNCommonLibrary( 558 'apr_memcache', inc_path, lib_dir, 559 None, aprutil_version, 560 defines=['SVN_HAVE_MEMCACHE']) 561 562 # And now find expat 563 # If we have apr-util as a source location, it is in a subdir. 564 # If we have an install package it is in the lib subdir 565 if os.path.exists(os.path.join(self.apr_util_path, 'xml/expat')): 566 inc_path = os.path.join(self.apr_util_path, 'xml/expat/lib') 567 lib_dir = os.path.join(self.apr_util_path, 'xml/expat/lib/LibR') 568 debug_lib_dir = os.path.join(self.apr_util_path, 'xml/expat/lib/LibD') 569 else: 570 inc_path = os.path.join(self.apr_util_path, 'include') 571 lib_dir = os.path.join(self.apr_util_path, 'lib') 572 debug_lib_dir = None 573 574 version_file_path = os.path.join(inc_path, 'expat.h') 575 576 if not os.path.exists(version_file_path): 577 sys.stderr.write("ERROR: '%s' not found.\n" % version_file_path); 578 sys.stderr.write("Use '--with-apr-util' option to configure APR-Util's XML location.\n"); 579 sys.exit(1) 580 581 txt = open(version_file_path).read() 582 583 vermatch = re.search(r'^\s*#define\s+XML_MAJOR_VERSION\s+(\d+)', txt, re.M) 584 major = int(vermatch.group(1)) 585 586 vermatch = re.search(r'^\s*#define\s+XML_MINOR_VERSION\s+(\d+)', txt, re.M) 587 minor = int(vermatch.group(1)) 588 589 vermatch = re.search(r'^\s*#define\s+XML_MICRO_VERSION\s+(\d+)', txt, re.M) 590 patch = int(vermatch.group(1)) 591 592 # apr-Util 0.9-1.4 compiled expat to 'xml.lib', but apr-util 1.5 switched 593 # to the more common 'libexpat.lib' 594 libname = 'libexpat.lib' 595 if not os.path.exists(os.path.join(lib_dir, 'libexpat.lib')): 596 libname = 'xml.lib' 597 598 version = (major, minor, patch) 599 xml_version = '%d.%d.%d' % version 600 601 self._libraries['xml'] = SVNCommonLibrary('expat', inc_path, lib_dir, 602 libname, xml_version, 603 debug_lib_dir = debug_lib_dir, 604 defines=['XML_STATIC']) 605 606 def _find_httpd(self, show_warnings): 607 "Find Apache HTTPD and version" 608 609 minimal_httpd_version = (2, 2, 0) 610 if not self.httpd_path: 611 return 612 613 inc_base = os.path.join(self.httpd_path, 'include') 614 615 if os.path.isfile(os.path.join(inc_base, 'apache26', 'ap_release.h')): 616 inc_path = os.path.join(inc_base, 'apache26') 617 elif os.path.isfile(os.path.join(inc_base, 'apache24', 'ap_release.h')): 618 inc_path = os.path.join(inc_base, 'apache24') 619 elif os.path.isfile(os.path.join(inc_base, 'apache22', 'ap_release.h')): 620 inc_path = os.path.join(inc_base, 'apache22') 621 elif os.path.isfile(os.path.join(inc_base, 'apache20', 'ap_release.h')): 622 inc_path = os.path.join(inc_base, 'apache20') 623 elif os.path.isfile(os.path.join(inc_base, 'apache2', 'ap_release.h')): 624 inc_path = os.path.join(inc_base, 'apache2') 625 elif os.path.isfile(os.path.join(inc_base, 'apache', 'ap_release.h')): 626 inc_path = os.path.join(inc_base, 'apache') 627 elif os.path.isfile(os.path.join(inc_base, 'ap_release.h')): 628 inc_path = inc_base 629 else: 630 if show_warnings: 631 print('WARNING: \'ap_release.h\' not found') 632 print("Use '--with-httpd' to configure openssl location."); 633 return 634 635 version_file_path = os.path.join(inc_path, 'ap_release.h') 636 txt = open(version_file_path).read() 637 638 vermatch = re.search(r'^\s*#define\s+AP_SERVER_MAJORVERSION_NUMBER\s+(\d+)', 639 txt, re.M) 640 major = int(vermatch.group(1)) 641 642 vermatch = re.search(r'^\s*#define\s+AP_SERVER_MINORVERSION_NUMBER\s+(\d+)', 643 txt, re.M) 644 minor = int(vermatch.group(1)) 645 646 vermatch = re.search(r'^\s*#define\s+AP_SERVER_PATCHLEVEL_NUMBER\s+(\d+)', 647 txt, re.M) 648 patch = int(vermatch.group(1)) 649 650 version = (major, minor, patch) 651 httpd_version = '%d.%d.%d' % version 652 653 if version < minimal_httpd_version: 654 if show_warnings: 655 print("WARNING: httpd %s or higher is required " 656 "(%s found)\n" % ( 657 '.'.join(str(v) for v in minimal_httpd_version), 658 httpd_version)) 659 return 660 661 lib_name = 'libhttpd.lib' 662 lib_base = self.httpd_path 663 664 debug_lib_dir = None 665 666 if os.path.isfile(os.path.join(lib_base, 'lib', lib_name)): 667 # Install location 668 lib_dir = os.path.join(lib_base, 'lib') 669 elif os.path.isfile(os.path.join(lib_base, 'Release', lib_name)): 670 # Source location 671 lib_dir = os.path.join(lib_base, 'Release') 672 if os.path.isfile(os.path.join(lib_base, 'Debug', lib_name)): 673 debug_lib_dir = os.path.join(lib_base, 'Debug') 674 675 # Our modules run inside httpd, so we don't have to find binaries 676 677 self._libraries['httpd'] = SVNCommonLibrary('httpd', inc_path, lib_dir, lib_name, 678 httpd_version, 679 debug_lib_dir=debug_lib_dir, 680 defines=['AP_DECLARE_EXPORT']) 681 682 # And now find mod_dav 683 684 if os.path.isfile(os.path.join(inc_path, 'mod_dav.h')): 685 # Install location, we are lucky 686 inc_path = inc_path 687 elif os.path.isfile(os.path.join(lib_base, 'modules/dav/main/mod_dav.h')): 688 # Source location 689 inc_path = os.path.join(lib_base, 'modules/dav/main') 690 else: 691 if show_warnings: 692 print("WARNING: Can't find mod_dav.h in the httpd directory") 693 return 694 695 lib_name = 'mod_dav.lib' 696 if os.path.isfile(os.path.join(lib_dir, lib_name)): 697 # Same location as httpd 698 lib_dir = lib_dir 699 elif os.path.isfile(os.path.join(lib_base, 'modules/dav/main/Release', lib_name)): 700 # Source location 701 lib_dir = os.path.join(lib_base, 'modules/dav/main/Release') 702 703 if os.path.isfile(os.path.join(lib_base, 'modules/dav/main/Debug', lib_name)): 704 debug_lib_dir = os.path.join(lib_base, 'modules/dav/main/Debug') 705 else: 706 debug_lib_dir = None 707 else: 708 if show_warnings: 709 print("WARNING: Can't find mod_dav.lib in the httpd directory") 710 return 711 712 self._libraries['mod_dav'] = SVNCommonLibrary('mod_dav', inc_path, lib_dir, lib_name, 713 httpd_version, 714 debug_lib_dir=debug_lib_dir) 715 716 def _find_zlib(self): 717 "Find the ZLib library and version" 718 719 minimal_zlib_version = (1, 2, 5) 720 721 if not self.zlib_path or not os.path.isdir(self.zlib_path): 722 sys.stderr.write("ERROR: '%s' not found.\n" % self.zlib_path); 723 sys.stderr.write("Use '--with-zlib' option to configure ZLib location.\n"); 724 sys.exit(1) 725 726 if os.path.isdir(os.path.join(self.zlib_path, 'include')): 727 # We have an install location 728 inc_path = os.path.join(self.zlib_path, 'include') 729 lib_path = os.path.join(self.zlib_path, 'lib') 730 731 # Different build options produce different library names :( 732 if os.path.exists(os.path.join(lib_path, 'zlibstatic.lib')): 733 # CMake default: zlibstatic.lib (static) and zlib.lib (dll) 734 lib_name = 'zlibstatic.lib' 735 elif os.path.exists(os.path.join(lib_path, 'zlibstat.lib')): 736 # Visual Studio project file default: zlibstat.lib (static) and zlibwapi.lib (dll) 737 lib_name = 'zlibstat.lib' 738 else: 739 # Standard makefile produces zlib.lib (static) and zdll.lib (dll) 740 lib_name = 'zlib.lib' 741 debug_lib_name = None 742 else: 743 # We have a source location 744 inc_path = lib_path = self.zlib_path 745 lib_name = 'zlibstat.lib' 746 debug_lib_name = 'zlibstatD.lib' 747 748 version_file_path = os.path.join(inc_path, 'zlib.h') 749 750 if not os.path.exists(version_file_path): 751 sys.stderr.write("ERROR: '%s' not found.\n" % version_file_path); 752 sys.stderr.write("Use '--with-zlib' option to configure ZLib location.\n"); 753 sys.exit(1) 754 755 txt = open(version_file_path).read() 756 vermatch = re.search( 757 r'^\s*#define\s+ZLIB_VERSION\s+"(\d+)\.(\d+)\.(\d+)(?:\.\d)?"', 758 txt, re.M) 759 760 version = tuple(map(int, vermatch.groups())) 761 self.zlib_version = '%d.%d.%d' % version 762 763 if version < minimal_zlib_version: 764 sys.stderr.write("ERROR: ZLib %s or higher is required " 765 "(%s found)\n" % ( 766 '.'.join(str(v) for v in minimal_zlib_version), 767 self.zlib_version)) 768 sys.exit(1) 769 770 self._libraries['zlib'] = SVNCommonLibrary('zlib', inc_path, lib_path, lib_name, 771 self.zlib_version, 772 debug_lib_name=debug_lib_name) 773 774 def _find_bdb(self, show_warnings): 775 "Find the Berkeley DB library and version" 776 777 # try default path to detect BDB support, unless different path is 778 # specified so to keep pre 1.10-behavior for BDB detection on Windows 779 bdb_path = 'db4-win32' 780 781 if self.bdb_path: 782 bdb_path = self.bdb_path 783 784 inc_path = os.path.join(bdb_path, 'include') 785 db_h_path = os.path.join(inc_path, 'db.h') 786 787 if not os.path.isfile(db_h_path): 788 if show_warnings and self.bdb_path: 789 print('WARNING: \'%s\' not found' % (db_h_path,)) 790 print("Use '--with-berkeley-db' to configure BDB location."); 791 return 792 793 # Obtain bdb version from db.h 794 txt = open(db_h_path).read() 795 796 maj_match = re.search(r'DB_VERSION_MAJOR\s+(\d+)', txt) 797 min_match = re.search(r'DB_VERSION_MINOR\s+(\d+)', txt) 798 patch_match = re.search(r'DB_VERSION_PATCH\s+(\d+)', txt) 799 800 if maj_match and min_match and patch_match: 801 ver = (int(maj_match.group(1)), 802 int(min_match.group(1)), 803 int(patch_match.group(1))) 804 else: 805 return 806 807 version = '%d.%d.%d' % ver 808 versuffix = '%d%d' % (ver[0], ver[1]) 809 810 # Before adding "60" to this list, see build/ac-macros/berkeley-db.m4. 811 if versuffix not in ( 812 '50', '51', '52', '53', 813 '40', '41', '42', '43', '44', '45', '46', '47', '48', 814 ): 815 return 816 817 lib_dir = os.path.join(bdb_path, 'lib') 818 lib_name = 'libdb%s.lib' % (versuffix,) 819 820 if not os.path.exists(os.path.join(lib_dir, lib_name)): 821 return 822 823 # Do we have a debug version? 824 debug_lib_name = 'libdb%sd.lib' % (versuffix,) 825 if not os.path.isfile(os.path.join(lib_dir, debug_lib_name)): 826 debug_lib_name = None 827 828 dll_dir = os.path.join(bdb_path, 'bin') 829 830 # Are there binaries we should copy for testing? 831 dll_name = os.path.splitext(lib_name)[0] + '.dll' 832 if not os.path.isfile(os.path.join(dll_dir, dll_name)): 833 dll_name = None 834 835 if debug_lib_name: 836 debug_dll_name = os.path.splitext(debug_lib_name)[0] + '.dll' 837 if not os.path.isfile(os.path.join(dll_dir, debug_dll_name)): 838 debug_dll_name = None 839 else: 840 debug_dll_name = None 841 842 # Usually apr-util doesn't find BDB on Windows, so we help apr-util 843 # by defining the value ourselves (Legacy behavior) 844 defines = ['APU_HAVE_DB=1', 'SVN_LIBSVN_FS_LINKS_FS_BASE'] 845 846 self._libraries['db'] = SVNCommonLibrary('db', inc_path, lib_dir, lib_name, 847 version, 848 debug_lib_name=debug_lib_name, 849 dll_dir=dll_dir, 850 dll_name=dll_name, 851 debug_dll_name=debug_dll_name, 852 defines=defines) 853 854 def _find_openssl(self, show_warnings): 855 "Find openssl" 856 857 if not self.openssl_path: 858 return 859 860 version_path = os.path.join(self.openssl_path, 'inc32/openssl/opensslv.h') 861 if os.path.isfile(version_path): 862 # We have an OpenSSL Source location 863 # For legacy reason 864 inc_dir = os.path.join(self.openssl_path, 'inc32') 865 if self.static_openssl: 866 lib_dir = os.path.join(self.openssl_path, 'out32') 867 bin_dir = None 868 else: 869 lib_dir = os.path.join(self.openssl_path, 'out32dll') 870 bin_dir = lib_dir 871 elif os.path.isfile(os.path.join(self.openssl_path, 872 'include/openssl/opensslv.h')): 873 version_path = os.path.join(self.openssl_path, 874 'include/openssl/opensslv.h') 875 inc_dir = os.path.join(self.openssl_path, 'include') 876 lib_dir = os.path.join(self.openssl_path, 'lib') 877 if self.static_openssl: 878 bin_dir = None 879 else: 880 bin_dir = os.path.join(self.openssl_path, 'bin') 881 else: 882 if show_warnings: 883 print('WARNING: \'opensslv.h\' not found') 884 print("Use '--with-openssl' to configure openssl location."); 885 return 886 887 txt = open(version_path).read() 888 889 vermatch = re.search( 890 r'#\s*define\s+OPENSSL_VERSION_TEXT\s+"OpenSSL\s+((\d+)\.(\d+).(\d+)([^ -]*))', 891 txt) 892 893 version = (int(vermatch.group(2)), 894 int(vermatch.group(3)), 895 int(vermatch.group(4))) 896 openssl_version = vermatch.group(1) 897 898 libcrypto = 'libcrypto' 899 libssl = 'libssl' 900 versuffix = '-%d_%d' % version[0:2] 901 if version < (1, 1, 0): 902 libcrypto = 'libeay32' 903 libssl = 'ssleay32' 904 versuffix = '' 905 906 self._libraries['openssl'] = SVNCommonLibrary('openssl', inc_dir, lib_dir, 907 '%s.lib' % (libssl,), 908 openssl_version, 909 dll_name='%s%s.dll' % 910 (libssl, versuffix), 911 dll_dir=bin_dir) 912 913 self._libraries['libcrypto'] = SVNCommonLibrary('openssl', inc_dir, lib_dir, 914 '%s.lib' % (libcrypto,), 915 openssl_version, 916 dll_name='%s%s.dll' % 917 (libcrypto, versuffix), 918 dll_dir=bin_dir) 919 920 def _find_perl(self, show_warnings): 921 "Find the right perl library name to link swig bindings with" 922 923 fp = os.popen('perl -MConfig -e ' + escape_shell_arg( 924 'print "$Config{libperl}\\n"; ' 925 'print "$Config{PERL_REVISION}.$Config{PERL_VERSION}.' 926 '$Config{PERL_SUBVERSION}\\n"; ' 927 'print "$Config{archlib}\\n"'), 'r') 928 try: 929 line = fp.readline() 930 if line: 931 perl_lib = line.strip() 932 else: 933 return 934 935 line = fp.readline() 936 if line: 937 perl_version = line.strip() 938 perl_ver = perl_version.split('.') 939 else: 940 return 941 942 line = fp.readline() 943 if line: 944 lib_dir = os.path.join(line.strip(), 'CORE') 945 inc_dir = lib_dir 946 finally: 947 fp.close() 948 949 perl_ver = tuple(map(int, perl_ver)) 950 forced_includes = [] 951 952 if perl_ver >= (5, 18, 0): 953 forced_includes.append('swigutil_pl__pre_perl.h') 954 955 self._libraries['perl'] = SVNCommonLibrary('perl', inc_dir, lib_dir, 956 perl_lib, perl_version, 957 forced_includes=forced_includes) 958 959 def _find_ruby(self, show_warnings): 960 "Find the right Ruby library name to link swig bindings with" 961 962 lib_dir = None 963 inc_dirs = [] 964 965 # Pass -W0 to stifle the "-e:1: Use RbConfig instead of obsolete 966 # and deprecated Config." warning if we are using Ruby 1.9. 967 fp = os.popen('ruby -rrbconfig -W0 -e ' + escape_shell_arg( 968 "puts RbConfig::CONFIG['ruby_version'];" 969 "puts RbConfig::CONFIG['LIBRUBY'];" 970 "puts RbConfig::CONFIG['libdir'];" 971 "puts RbConfig::CONFIG['rubyhdrdir'];" 972 "puts RbConfig::CONFIG['arch'];"), 'r') 973 try: 974 line = fp.readline() 975 if line: 976 ruby_version = line.strip() 977 978 line = fp.readline() 979 if line: 980 ruby_lib = line.strip() 981 982 line = fp.readline() 983 if line: 984 lib_dir = line.strip() 985 986 line = fp.readline() 987 if line: 988 inc_base = line.strip() 989 inc_dirs = [inc_base] 990 991 line = fp.readline() 992 if line: 993 inc_dirs.append(os.path.join(inc_base, line.strip())) 994 995 finally: 996 fp.close() 997 998 if not lib_dir: 999 return 1000 1001 # Visual C++ prior to VS2015 doesn't have a standard compliant snprintf 1002 if self.vs_version < '2015': 1003 defines = ['snprintf=_snprintf'] 1004 else: 1005 defines = [] 1006 1007 ver = ruby_version.split('.') 1008 ver = tuple(map(int, ver)) 1009 if ver >= (1, 8, 0): 1010 defines.extend(["HAVE_RB_ERRINFO"]) 1011 1012 forced_includes = [] 1013 1014 if ver >= (1, 8, 0): 1015 # Swig redefines NUM2LL as NUM2LONG if it isn't defined, but on Windows 1016 # ruby 1.8+ declares NUM2LL as a static inline function. 1017 # (LL2NUM and NUM2ULL don't have these problems) 1018 defines.extend(['NUM2LL=NUM2LL']) 1019 1020 if ver >= (1, 9, 0): 1021 forced_includes.append('swigutil_rb__pre_ruby.h') 1022 defines.extend(["SVN_SWIG_RUBY__CUSTOM_RUBY_CONFIG"]) 1023 1024 self._libraries['ruby'] = SVNCommonLibrary('ruby', inc_dirs, lib_dir, 1025 ruby_lib, ruby_version, 1026 defines=defines, 1027 forced_includes=forced_includes) 1028 1029 def _find_python(self, show_warnings): 1030 "Find the appropriate options for creating SWIG-based Python modules" 1031 1032 try: 1033 from distutils import sysconfig 1034 1035 inc_dir = sysconfig.get_python_inc() 1036 lib_dir = os.path.join(sysconfig.PREFIX, "libs") 1037 except ImportError: 1038 return 1039 1040 if sys.version_info[0] >= 3: 1041 if self.swig_version < (3, 0, 10): 1042 if show_warnings: 1043 print("WARNING: Subversion Python bindings for Python 3 require SWIG 3.0.10 or newer") 1044 return 1045 if self.swig_version < (4, 0, 0): 1046 opts = "-python -py3 -nofastunpack -modern" 1047 else: 1048 opts = "-python -py3 -nofastunpack" 1049 else: 1050 if not ((1, 3, 24) <= self.swig_version < (4, 0, 0)): 1051 if show_warnings: 1052 print("WARNING: Subversion Python bindings for Python 2 require 1.3.24 <= SWIG < 4.0.0") 1053 return 1054 opts = "-python -classic" 1055 1056 self.user_macros.append(UserMacro("SWIG_PY_OPTS", opts)) 1057 self._libraries['python'] = SVNCommonLibrary('python', inc_dir, lib_dir, None, 1058 sys.version.split(' ')[0]) 1059 1060 def _find_py3c(self, show_warnings): 1061 "Find the py3c library which is used in SWIG python bindings" 1062 show_warnings = True 1063 # Assume a default path, unless otherwise specified 1064 py3c_path = "py3c" 1065 1066 if self.py3c_path: 1067 py3c_path = self.py3c_path 1068 1069 py3c_path = os.path.abspath(py3c_path) 1070 inc_path = os.path.join(py3c_path, 'include') 1071 py3c_hdr_path = os.path.join(inc_path, 'py3c.h') 1072 1073 pc_path = os.path.join(py3c_path, 'py3c.pc.in') 1074 1075 if not os.path.isfile(py3c_hdr_path): 1076 if show_warnings: 1077 print('WARNING: "%s" not found' % py3c_hdr_path) 1078 print('Use "--with-py3c" to configure py3c location.') 1079 return False 1080 1081 with open(pc_path) as fp: 1082 txt = fp.read() 1083 1084 ver_match = re.search(r'Version:\s+([0-9.]+)', txt) 1085 1086 if not ver_match: 1087 if show_warnings: 1088 print("WARNING: Failed to find version in '%s'" % pc_path) 1089 return False 1090 1091 py3c_version = ver_match.group(1) 1092 1093 self._libraries['py3c'] = SVNCommonLibrary('py3c', inc_path, None, 1094 None, py3c_version) 1095 1096 return True 1097 1098 def _find_jdk(self, show_warnings): 1099 "Find details about an installed jdk" 1100 1101 jdk_path = self.jdk_path 1102 self.jdk_path = None # No jdk on errors 1103 1104 minimal_jdk_version = (1, 0, 0) # ### Provide sane default 1105 1106 if not jdk_path: 1107 jdk_ver = None 1108 try: 1109 try: 1110 # Python >=3.0 1111 import winreg 1112 except ImportError: 1113 # Python <3.0 1114 import _winreg as winreg 1115 key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 1116 r"SOFTWARE\JavaSoft\Java Development Kit") 1117 # Find the newest JDK version. 1118 num_values = winreg.QueryInfoKey(key)[1] 1119 for i in range(num_values): 1120 (name, value, key_type) = winreg.EnumValue(key, i) 1121 if name == "CurrentVersion": 1122 jdk_ver = value 1123 break 1124 1125 # Find the JDK path. 1126 if jdk_ver is not None: 1127 key = winreg.OpenKey(key, jdk_ver) 1128 num_values = winreg.QueryInfoKey(key)[1] 1129 for i in range(num_values): 1130 (name, value, key_type) = winreg.EnumValue(key, i) 1131 if name == "JavaHome": 1132 jdk_path = value 1133 break 1134 winreg.CloseKey(key) 1135 except (ImportError, EnvironmentError): 1136 pass 1137 1138 if not jdk_path or not os.path.isdir(jdk_path): 1139 return 1140 1141 try: 1142 # Apparently a 1.8 javac writes its version output to stderr, while 1143 # a 1.10 javac writes it to stdout. To catch them all, we redirect 1144 # stderr to stdout. 1145 outfp = subprocess.Popen([os.path.join(jdk_path, 'bin', 'javac.exe'), 1146 '-version'], stdout=subprocess.PIPE, 1147 stderr=subprocess.STDOUT).stdout 1148 line = outfp.read().decode('utf8') 1149 if line: 1150 vermatch = re.search(r'(([0-9]+(\.[0-9]+)+)(_[._0-9]+)?)', line, re.M) 1151 else: 1152 vermatch = None 1153 1154 if vermatch: 1155 version = tuple(map(int, vermatch.groups()[1].split('.'))) 1156 versionstr = vermatch.groups()[0] 1157 else: 1158 if show_warnings: 1159 print('Could not find installed JDK,') 1160 return 1161 outfp.close() 1162 except OSError: 1163 if show_warnings: 1164 print('Could not find installed JDK,') 1165 return 1166 1167 if version < minimal_jdk_version: 1168 if show_warnings: 1169 print('Found java jdk %s, but >= %s is required. ' 1170 'javahl will not be built.\n' % \ 1171 (versionstr, '.'.join(str(v) for v in minimal_jdk_version))) 1172 return 1173 1174 self.jdk_path = jdk_path 1175 inc_dirs = [ 1176 os.path.join(jdk_path, 'include'), 1177 os.path.join(jdk_path, 'include', 'win32'), 1178 ] 1179 1180 lib_dir = os.path.join(jdk_path, 'lib') 1181 1182 # The JDK provides .lib files, but we currently don't use these. 1183 self._libraries['java_sdk'] = SVNCommonLibrary('java-sdk', inc_dirs, 1184 lib_dir, None, 1185 versionstr) 1186 1187 def _find_swig(self, show_warnings): 1188 "Find details about an installed swig" 1189 1190 minimal_swig_version = (1, 3, 25) 1191 1192 if not self.swig_path: 1193 swig_exe = 'swig.exe' 1194 else: 1195 swig_exe = os.path.abspath(os.path.join(self.swig_path, 'swig.exe')) 1196 1197 if self.swig_path is not None: 1198 self.swig_exe = os.path.abspath(os.path.join(self.swig_path, 'swig.exe')) 1199 else: 1200 self.swig_exe = 'swig' 1201 1202 swig_version = None 1203 try: 1204 fp = subprocess.Popen([self.swig_exe, '-version'], 1205 stdout=subprocess.PIPE).stdout 1206 txt = fp.read().decode('utf8') 1207 if txt: 1208 vermatch = re.search(r'^SWIG\ Version\ (\d+)\.(\d+)\.(\d+)', txt, re.M) 1209 else: 1210 vermatch = None 1211 1212 if vermatch: 1213 swig_version = tuple(map(int, vermatch.groups())) 1214 fp.close() 1215 except OSError: 1216 swig_version = None 1217 1218 if not swig_version: 1219 if show_warnings: 1220 print('Could not find installed SWIG') 1221 return False 1222 1223 swig_ver = '%d.%d.%d' % (swig_version) 1224 if swig_version < minimal_swig_version: 1225 if show_warnings: 1226 print('Found swig %s, but >= %s is required. ' 1227 'the swig bindings will not be built.\n' % 1228 (swig_version, '.'.join(str(v) for v in minimal_swig_version))) 1229 return 1230 1231 try: 1232 fp = subprocess.Popen([self.swig_exe, '-swiglib'], 1233 stdout=subprocess.PIPE).stdout 1234 lib_dir = fp.readline().decode('utf8').strip() 1235 fp.close() 1236 except OSError: 1237 lib_dir = None 1238 fp.close() 1239 1240 if not lib_dir: 1241 if show_warnings: 1242 print('Could not find libdir of installed SWIG') 1243 return False 1244 1245 if (not self.swig_path and 1246 os.path.isfile(os.path.join(lib_dir, '../swig.exe'))): 1247 self.swig_path = os.path.dirname(lib_dir) 1248 1249 inc_dirs = [ 1250 'subversion/bindings/swig', 1251 'subversion/bindings/swig/proxy', 1252 'subversion/bindings/swig/include', 1253 ] 1254 1255 self.swig_libdir = lib_dir 1256 self.swig_version = swig_version 1257 1258 self._libraries['swig'] = SVNCommonLibrary('swig', inc_dirs, lib_dir, None, 1259 swig_ver) 1260 return True 1261 1262 def _get_serf_version(self, inc_dir): 1263 "Retrieves the serf version from serf.h" 1264 1265 # shouldn't be called unless serf is there 1266 assert inc_dir and os.path.exists(inc_dir) 1267 1268 serf_ver_maj = None 1269 serf_ver_min = None 1270 serf_ver_patch = None 1271 1272 # serf.h should be present 1273 if not os.path.exists(os.path.join(inc_dir, 'serf.h')): 1274 return None, None, None 1275 1276 txt = open(os.path.join(inc_dir, 'serf.h')).read() 1277 1278 maj_match = re.search(r'SERF_MAJOR_VERSION\s+(\d+)', txt) 1279 min_match = re.search(r'SERF_MINOR_VERSION\s+(\d+)', txt) 1280 patch_match = re.search(r'SERF_PATCH_VERSION\s+(\d+)', txt) 1281 if maj_match: 1282 serf_ver_maj = int(maj_match.group(1)) 1283 if min_match: 1284 serf_ver_min = int(min_match.group(1)) 1285 if patch_match: 1286 serf_ver_patch = int(patch_match.group(1)) 1287 1288 return serf_ver_maj, serf_ver_min, serf_ver_patch 1289 1290 def _find_serf(self, show_warnings): 1291 "Check if serf and its dependencies are available" 1292 1293 minimal_serf_version = (1, 3, 4) 1294 1295 if not self.serf_path: 1296 return 1297 1298 inc_dir = self.serf_path 1299 1300 if os.path.isfile(os.path.join(inc_dir, 'serf.h')): 1301 # Source layout 1302 lib_dir = self.serf_path 1303 debug_lib_dir = None 1304 inc_dir = self.serf_path 1305 elif os.path.isfile(os.path.join(self.serf_path, 'include/serf-1/serf.h')): 1306 # Install layout 1307 inc_dir = os.path.join(self.serf_path, 'include/serf-1') 1308 lib_dir = os.path.join(self.serf_path, 'lib') 1309 debug_lib_dir = None 1310 elif os.path.isfile(os.path.join(self.serf_path, 'include/serf-2/serf.h')): 1311 # Install layout 1312 inc_dir = os.path.join(self.serf_path, 'include/serf-2') 1313 lib_dir = os.path.join(self.serf_path, 'lib') 1314 debug_lib_dir = None 1315 else: 1316 if show_warnings: 1317 print('WARNING: \'serf.h\' not found') 1318 print("Use '--with-serf' to configure serf location."); 1319 return 1320 1321 version = self._get_serf_version(inc_dir) 1322 serf_version = '.'.join(str(v) for v in version) 1323 1324 if version < minimal_serf_version: 1325 if show_warnings: 1326 print('Found serf %s, but >= %s is required. ' 1327 'ra_serf will not be built.\n' % 1328 (serf_version, '.'.join(str(v) for v in minimal_serf_version))) 1329 return 1330 1331 serf_ver_maj = version[0] 1332 1333 if serf_ver_maj > 0: 1334 lib_name = 'serf-%d.lib' % (serf_ver_maj,) 1335 else: 1336 lib_name = 'serf.lib' 1337 1338 defines = ['SVN_HAVE_SERF', 'SVN_LIBSVN_RA_LINKS_RA_SERF'] 1339 1340 self._libraries['serf'] = SVNCommonLibrary('serf', inc_dir, lib_dir, 1341 lib_name, serf_version, 1342 debug_lib_dir=debug_lib_dir, 1343 defines=defines) 1344 1345 def _find_sasl(self, show_warnings): 1346 "Check if sals is available" 1347 1348 minimal_sasl_version = (2, 0, 0) 1349 1350 if not self.sasl_path: 1351 return 1352 1353 inc_dir = os.path.join(self.sasl_path, 'include') 1354 1355 version_file_path = os.path.join(inc_dir, 'sasl.h') 1356 1357 if not os.path.isfile(version_file_path): 1358 if show_warnings: 1359 print('WARNING: \'%s\' not found' % (version_file_path,)) 1360 print("Use '--with-sasl' to configure sasl location."); 1361 return 1362 1363 txt = open(version_file_path).read() 1364 1365 vermatch = re.search(r'^\s*#define\s+SASL_VERSION_MAJOR\s+(\d+)', txt, re.M) 1366 major = int(vermatch.group(1)) 1367 1368 vermatch = re.search(r'^\s*#define\s+SASL_VERSION_MINOR\s+(\d+)', txt, re.M) 1369 minor = int(vermatch.group(1)) 1370 1371 vermatch = re.search(r'^\s*#define\s+SASL_VERSION_STEP\s+(\d+)', txt, re.M) 1372 patch = int(vermatch.group(1)) 1373 1374 version = (major, minor, patch) 1375 sasl_version = '.'.join(str(v) for v in version) 1376 1377 if version < minimal_sasl_version: 1378 if show_warnings: 1379 print('Found sasl %s, but >= %s is required. ' 1380 'sals support will not be built.\n' % 1381 (sasl_version, '.'.join(str(v) for v in minimal_serf_version))) 1382 return 1383 1384 lib_dir = os.path.join(self.sasl_path, 'lib') 1385 1386 if os.path.isfile(os.path.join(lib_dir, 'libsasl.dll')): 1387 dll_dir = lib_dir 1388 dll_name = 'libsasl.dll' 1389 elif os.path.isfile(os.path.join(self.sasl_path, 'bin', 'libsasl.dll')): 1390 dll_dir = os.path.join(self.sasl_path, 'bin') 1391 dll_name = 'libsasl.dll' 1392 else: 1393 # Probably a static compilation 1394 dll_dir = None 1395 dll_name = None 1396 1397 self._libraries['sasl'] = SVNCommonLibrary('sasl', inc_dir, lib_dir, 1398 'libsasl.lib', sasl_version, 1399 dll_dir=dll_dir, 1400 dll_name=dll_name, 1401 defines=['SVN_HAVE_SASL']) 1402 1403 def _find_libintl(self, show_warnings): 1404 "Find gettext support" 1405 minimal_libintl_version = (0, 14, 1) 1406 1407 if not self.enable_nls or not self.libintl_path: 1408 return; 1409 1410 # We support 2 scenarios. 1411 if os.path.isfile(os.path.join(self.libintl_path, 'inc', 'libintl.h')) and\ 1412 os.path.isfile(os.path.join(self.libintl_path, 'lib', 'intl3_svn.lib')): 1413 1414 # 1. Subversion's custom libintl based on gettext 0.14.1 1415 inc_dir = os.path.join(self.libintl_path, 'inc') 1416 lib_dir = os.path.join(self.libintl_path, 'lib') 1417 dll_dir = os.path.join(self.libintl_path, 'bin') 1418 1419 lib_name = 'intl3_svn.lib' 1420 dll_name = 'intl3_svn.dll' 1421 elif os.path.isfile(os.path.join(self.libintl_path, \ 1422 'include', 'libintl.h')): 1423 # 2. A gettext install 1424 inc_dir = os.path.join(self.libintl_path, 'include') 1425 lib_dir = os.path.join(self.libintl_path, 'lib') 1426 dll_dir = os.path.join(self.libintl_path, 'bin') 1427 1428 lib_name = 'intl.lib' 1429 dll_name = 'intl.dll' 1430 else: 1431 if (show_warnings): 1432 print('WARNING: \'libintl.h\' not found') 1433 print("Use '--with-libintl' to configure libintl location.") 1434 return 1435 1436 version_file_path = os.path.join(inc_dir, 'libintl.h') 1437 txt = open(version_file_path).read() 1438 1439 match = re.search(r'^\s*#define\s+LIBINTL_VERSION\s+((0x)?[0-9A-Fa-f]+)', 1440 txt, re.M) 1441 1442 ver = int(match.group(1), 0) 1443 version = (ver >> 16, (ver >> 8) & 0xFF, ver & 0xFF) 1444 1445 libintl_version = '.'.join(str(v) for v in version) 1446 1447 if version < minimal_libintl_version: 1448 if show_warnings: 1449 print('Found libintl %s, but >= %s is required.\n' % \ 1450 (libintl_version, 1451 '.'.join(str(v) for v in minimal_libintl_version))) 1452 return 1453 1454 self._libraries['intl'] = SVNCommonLibrary('libintl', inc_dir, lib_dir, 1455 lib_name, libintl_version, 1456 dll_dir=dll_dir, 1457 dll_name=dll_name) 1458 1459 def _find_sqlite(self, show_warnings): 1460 "Find the Sqlite library and version" 1461 1462 minimal_sqlite_version = (3, 8, 2) 1463 1464 # For SQLite we support 3 scenarios: 1465 # - Installed in standard directory layout 1466 # - Installed in legacy directory layout 1467 # - Amalgamation compiled directly into our libraries 1468 1469 sqlite_base = self.sqlite_path 1470 1471 lib_dir = None 1472 dll_dir = None 1473 dll_name = None 1474 defines = [] 1475 1476 lib_name = 'sqlite3.lib' 1477 1478 if os.path.isfile(os.path.join(sqlite_base, 'include/sqlite3.h')): 1479 # Standard layout 1480 inc_dir = os.path.join(sqlite_base, 'include') 1481 lib_dir = os.path.join(sqlite_base, 'lib') 1482 1483 # We assume a static library, but let's support shared in this case 1484 if os.path.isfile(os.path.join(sqlite_base, 'bin/sqlite3.dll')): 1485 dll_dir = os.path.join(sqlite_base, 'bin') 1486 dll_name = 'sqlite3.dll' 1487 elif os.path.isfile(os.path.join(sqlite_base, 'inc/sqlite3.h')): 1488 # Standard layout 1489 inc_dir = os.path.join(sqlite_base, 'inc') 1490 lib_dir = os.path.join(sqlite_base, 'lib') 1491 1492 # We assume a static library, but let's support shared in this case 1493 if os.path.isfile(os.path.join(sqlite_base, 'bin/sqlite3.dll')): 1494 dll_dir = os.path.join(sqlite_base, 'bin') 1495 dll_name = 'sqlite3.dll' 1496 elif (os.path.isfile(os.path.join(sqlite_base, 'sqlite3.h')) 1497 and os.path.isfile(os.path.join(sqlite_base, 'sqlite3.c'))): 1498 # Amalgamation 1499 inc_dir = sqlite_base 1500 lib_dir = None 1501 lib_name = None 1502 defines.append('SVN_SQLITE_INLINE') 1503 else: 1504 sys.stderr.write("ERROR: SQLite not found\n") 1505 sys.stderr.write("Use '--with-sqlite' option to configure sqlite location.\n"); 1506 sys.exit(1) 1507 1508 version_file_path = os.path.join(inc_dir, 'sqlite3.h') 1509 1510 txt = open(version_file_path).read() 1511 1512 match = re.search(r'^\s*#define\s+SQLITE_VERSION\s+' 1513 r'"(\d+)\.(\d+)\.(\d+)(?:\.(\d))?"', txt, re.M) 1514 1515 version = match.groups() 1516 1517 # Sqlite doesn't add patch numbers for their ordinary releases 1518 if not version[3]: 1519 version = version[0:3] 1520 1521 version = tuple(map(int, version)) 1522 1523 sqlite_version = '.'.join(str(v) for v in version) 1524 1525 if version < minimal_sqlite_version: 1526 sys.stderr.write("ERROR: sqlite %s or higher is required " 1527 "(%s found)\n" % ( 1528 '.'.join(str(v) for v in minimal_sqlite_version), 1529 sqlite_version)) 1530 sys.exit(1) 1531 1532 self._libraries['sqlite'] = SVNCommonLibrary('sqlite', inc_dir, lib_dir, 1533 lib_name, sqlite_version, 1534 dll_dir=dll_dir, 1535 dll_name=dll_name, 1536 defines=defines) 1537 1538 def _find_lz4(self): 1539 "Find the LZ4 library" 1540 1541 # For now, we always use the internal (bundled) library. 1542 version_file_path = os.path.join('subversion', 'libsvn_subr', 1543 'lz4', 'lz4internal.h') 1544 txt = open(version_file_path).read() 1545 1546 vermatch = re.search(r'^\s*#define\s+LZ4_VERSION_MAJOR\s+(\d+)', 1547 txt, re.M) 1548 major = int(vermatch.group(1)) 1549 1550 vermatch = re.search(r'^\s*#define\s+LZ4_VERSION_MINOR\s+(\d+)', 1551 txt, re.M) 1552 minor = int(vermatch.group(1)) 1553 1554 vermatch = re.search(r'^\s*#define\s+LZ4_VERSION_RELEASE\s+(\d+)', 1555 txt, re.M) 1556 rel = vermatch.group(1) 1557 1558 lz4_version = '%d.%d.%s' % (major, minor, rel) 1559 self._libraries['lz4'] = SVNCommonLibrary('lz4', None, None, None, 1560 lz4_version, internal=True, 1561 defines=['SVN_INTERNAL_LZ4']) 1562 1563 def _find_utf8proc(self): 1564 "Find the Utf8proc library" 1565 1566 # For now, we always use the internal (bundled) library. 1567 version_file_path = os.path.join('subversion', 'libsvn_subr', 1568 'utf8proc', 'utf8proc_internal.h') 1569 txt = open(version_file_path).read() 1570 1571 vermatch = re.search(r'^\s*#define\s+UTF8PROC_VERSION_MAJOR\s+(\d+)', 1572 txt, re.M) 1573 major = int(vermatch.group(1)) 1574 1575 vermatch = re.search(r'^\s*#define\s+UTF8PROC_VERSION_MINOR\s+(\d+)', 1576 txt, re.M) 1577 minor = int(vermatch.group(1)) 1578 1579 vermatch = re.search(r'^\s*#define\s+UTF8PROC_VERSION_PATCH\s+(\d+)', 1580 txt, re.M) 1581 patch = int(vermatch.group(1)) 1582 1583 utf8proc_version = '%d.%d.%d' % (major, minor, patch) 1584 self._libraries['utf8proc'] = SVNCommonLibrary('utf8proc', None, None, 1585 None, utf8proc_version, 1586 internal=True, 1587 defines=['SVN_INTERNAL_UTF8PROC']) 1588 1589# ============================================================================ 1590# This is a cut-down and modified version of code from: 1591# subversion/subversion/bindings/swig/python/svn/core.py 1592# 1593if sys.platform == "win32": 1594 _escape_shell_arg_re = re.compile(r'(\\+)(\"|$)') 1595 1596 def escape_shell_arg(arg): 1597 # The (very strange) parsing rules used by the C runtime library are 1598 # described at: 1599 # http://msdn.microsoft.com/library/en-us/vclang/html/_pluslang_Parsing_C.2b2b_.Command.2d.Line_Arguments.asp 1600 1601 # double up slashes, but only if they are followed by a quote character 1602 arg = re.sub(_escape_shell_arg_re, r'\1\1\2', arg) 1603 1604 # surround by quotes and escape quotes inside 1605 arg = '"' + arg.replace('"', '"^""') + '"' 1606 return arg 1607 1608else: 1609 def escape_shell_arg(str): 1610 return "'" + str.replace("'", "'\\''") + "'" 1611