1
1
# MySQL Connector/Python - MySQL driver written in Python.
2
- # Copyright (c) 2014, 2016 , Oracle and/or its affiliates. All rights reserved.
2
+ # Copyright (c) 2014, 2017 , Oracle and/or its affiliates. All rights reserved.
3
3
4
4
# MySQL Connector/Python is licensed under the terms of the GPLv2
5
5
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
35
35
import os
36
36
import shlex
37
37
import struct
38
- from subprocess import Popen , PIPE , STDOUT
38
+ from subprocess import Popen , PIPE , STDOUT , check_call
39
39
import sys
40
40
import platform
41
+ import shutil
42
+
41
43
42
44
ARCH_64BIT = sys .maxsize > 2 ** 32 # Works with Python 2.6 and greater
43
45
py_arch = '64-bit' if ARCH_64BIT else '32-bit'
44
46
45
47
CEXT_OPTIONS = [
46
48
('with-mysql-capi=' , None ,
47
49
"Location of MySQL C API installation or path to mysql_config" ),
50
+ ('with-protobuf-include-dir=' , None ,
51
+ "Location of Protobuf include directory" ),
52
+ ('with-protobuf-lib-dir=' , None ,
53
+ "Location of Protobuf library directory" ),
54
+ ('with-protoc=' , None ,
55
+ "Location of Protobuf protoc binary" ),
56
+ ('extra-compile-args=' , None ,
57
+ "Extra compile args" )
48
58
]
49
59
50
60
CEXT_STATIC_OPTIONS = [
@@ -273,7 +283,11 @@ class BuildExtDynamic(build_ext):
273
283
274
284
def initialize_options (self ):
275
285
build_ext .initialize_options (self )
286
+ self .extra_compile_args = None
276
287
self .with_mysql_capi = None
288
+ self .with_protobuf_include_dir = None
289
+ self .with_protobuf_lib_dir = None
290
+ self .with_protoc = None
277
291
278
292
def _finalize_connector_c (self , connc_loc ):
279
293
"""Finalize the --with-connector-c command line argument
@@ -381,9 +395,6 @@ def _finalize_connector_c(self, connc_loc):
381
395
382
396
# We try to offer a nice message when the architecture of Python
383
397
# is not the same as MySQL Connector/C binaries.
384
- py_arch = '64-bit' if ARCH_64BIT else '32-bit'
385
- print ("# Python architecture: {0}" .format (py_arch ))
386
- print ("# Python ARCH_64BIT: {0}" .format (ARCH_64BIT ))
387
398
print ("# self.arch: {0}" .format (self .arch ))
388
399
if ARCH_64BIT != connc_64bit :
389
400
log .error ("Python is {0}, but does not "
@@ -395,14 +406,62 @@ def _finalize_connector_c(self, connc_loc):
395
406
sys .exit (1 )
396
407
397
408
def finalize_options (self ):
398
- self .set_undefined_options ('install' ,
399
- ('with_mysql_capi' , 'with_mysql_capi' ))
409
+ self .set_undefined_options (
410
+ 'install' ,
411
+ ('extra_compile_args' , 'extra_compile_args' ),
412
+ ('with_mysql_capi' , 'with_mysql_capi' ),
413
+ ('with_protobuf_include_dir' , 'with_protobuf_include_dir' ),
414
+ ('with_protobuf_lib_dir' , 'with_protobuf_lib_dir' ),
415
+ ('with_protoc' , 'with_protoc' ))
400
416
401
417
build_ext .finalize_options (self )
402
418
419
+ print ("# Python architecture: {0}" .format (py_arch ))
420
+ print ("# Python ARCH_64BIT: {0}" .format (ARCH_64BIT ))
421
+
403
422
if self .with_mysql_capi :
404
423
self ._finalize_connector_c (self .with_mysql_capi )
405
424
425
+ if not self .with_protobuf_include_dir :
426
+ self .with_protobuf_include_dir = \
427
+ os .environ .get ("MYSQLXPB_PROTOBUF_INCLUDE_DIR" )
428
+
429
+ if not self .with_protobuf_lib_dir :
430
+ self .with_protobuf_lib_dir = \
431
+ os .environ .get ("MYSQLXPB_PROTOBUF_LIB_DIR" )
432
+
433
+ if not self .with_protoc :
434
+ self .with_protoc = os .environ .get ("MYSQLXPB_PROTOC" )
435
+
436
+ def run_protoc (self ):
437
+ if self .with_protobuf_include_dir :
438
+ print ("# Protobuf include directory: {0}"
439
+ "" .format (self .with_protobuf_include_dir ))
440
+ else :
441
+ log .error ("Unable to find Protobuf include directory." )
442
+ sys .exit (1 )
443
+
444
+ if self .with_protobuf_lib_dir :
445
+ print ("# Protobuf library directory: {0}"
446
+ "" .format (self .with_protobuf_lib_dir ))
447
+ else :
448
+ log .error ("Unable to find Protobuf library directory." )
449
+ sys .exit (1 )
450
+
451
+ if self .with_protoc :
452
+ print ("# Protobuf protoc binary: {0}" .format (self .with_protoc ))
453
+ else :
454
+ log .error ("Unable to find Protobuf protoc binary." )
455
+ sys .exit (1 )
456
+
457
+ base_path = os .path .join (os .getcwd (), "src" , "mysqlxpb" , "mysqlx" )
458
+ command = [self .with_protoc , "-I" ]
459
+ command .append (os .path .join (base_path , "protocol" ))
460
+ command .extend (glob (os .path .join (base_path , "protocol" , "*.proto" )))
461
+ command .append ("--cpp_out={0}" .format (base_path ))
462
+ log .info ("# Running protoc command: {0}" .format (" " .join (command )))
463
+ check_call (command )
464
+
406
465
def fix_compiler (self ):
407
466
platform = get_platform ()
408
467
@@ -444,6 +503,18 @@ def fix_compiler(self):
444
503
# Add system headers to Extensions extra_compile_args
445
504
sysheaders = [ '-isystem' + dir for dir in cc .include_dirs ]
446
505
for ext in self .extensions :
506
+ # Add Protobuf include and library dirs
507
+ if ext .name == "_mysqlxpb" :
508
+ ext .include_dirs .append (self .with_protobuf_include_dir )
509
+ ext .library_dirs .append (self .with_protobuf_lib_dir )
510
+ if os .name == 'nt' :
511
+ ext .libraries .append ("libprotobuf" )
512
+ else :
513
+ ext .libraries .append ("protobuf" )
514
+ # Add extra compile args
515
+ if self .extra_compile_args :
516
+ ext .extra_compile_args .append (self .extra_compile_args )
517
+ # Add system headers
447
518
for sysheader in sysheaders :
448
519
if sysheader not in ext .extra_compile_args :
449
520
ext .extra_compile_args .append (sysheader )
@@ -454,16 +525,26 @@ def fix_compiler(self):
454
525
455
526
def run (self ):
456
527
"""Run the command"""
457
- if not self .with_mysql_capi :
458
- return
459
-
460
528
if os .name == 'nt' :
529
+ for ext in self .extensions :
530
+ # Add Protobuf include and library dirs
531
+ if ext .name == "_mysqlxpb" :
532
+ ext .include_dirs .append (self .with_protobuf_include_dir )
533
+ ext .library_dirs .append (self .with_protobuf_lib_dir )
534
+ ext .libraries .append ("libprotobuf" )
535
+ # Use the multithread, static version of the run-time library
536
+ ext .extra_compile_args .append ("/MT" )
537
+ # Add extra compile args
538
+ if self .extra_compile_args :
539
+ ext .extra_compile_args .extend (self .extra_compile_args )
540
+ self .run_protoc ()
461
541
build_ext .run (self )
462
542
else :
463
543
self .real_build_extensions = self .build_extensions
464
544
self .build_extensions = lambda : None
465
545
build_ext .run (self )
466
546
self .fix_compiler ()
547
+ self .run_protoc ()
467
548
self .real_build_extensions ()
468
549
469
550
@@ -474,17 +555,66 @@ class BuildExtStatic(BuildExtDynamic):
474
555
user_options = build_ext .user_options + CEXT_OPTIONS
475
556
476
557
def finalize_options (self ):
558
+ options_pairs = []
477
559
if not self .with_mysql_capi :
478
- self .set_undefined_options ('install' ,
479
- ('with_mysql_capi' , 'with_mysql_capi' ))
560
+ options_pairs .append (('with_mysql_capi' , 'with_mysql_capi' ))
561
+ if not self .with_protobuf_include_dir :
562
+ options_pairs .append (('with_protobuf_include_dir' ,
563
+ 'with_protobuf_include_dir' ))
564
+ if not self .with_protobuf_lib_dir :
565
+ options_pairs .append (('with_protobuf_lib_dir' ,
566
+ 'with_protobuf_lib_dir' ))
567
+ if not self .with_protoc :
568
+ options_pairs .append (('with_protoc' , 'with_protoc' ))
569
+ if options_pairs :
570
+ self .set_undefined_options ('install' , * options_pairs )
480
571
481
572
build_ext .finalize_options (self )
573
+
574
+ print ("# Python architecture: {0}" .format (py_arch ))
575
+ print ("# Python ARCH_64BIT: {0}" .format (ARCH_64BIT ))
576
+
482
577
self .connc_lib = os .path .join (self .build_temp , 'connc' , 'lib' )
483
578
self .connc_include = os .path .join (self .build_temp , 'connc' , 'include' )
579
+ self .protobuf_lib = os .path .join (self .build_temp , 'protobuf' , 'lib' )
580
+ self .protobuf_include = os .path .join (self .build_temp , 'protobuf' , 'include' )
484
581
485
582
if self .with_mysql_capi :
486
583
self ._finalize_connector_c (self .with_mysql_capi )
487
584
585
+ if not self .with_protobuf_include_dir :
586
+ self .with_protobuf_include_dir = \
587
+ os .environ .get ("MYSQLXPB_PROTOBUF_INCLUDE_DIR" )
588
+
589
+ if not self .with_protobuf_lib_dir :
590
+ self .with_protobuf_lib_dir = \
591
+ os .environ .get ("MYSQLXPB_PROTOBUF_LIB_DIR" )
592
+
593
+ if not self .with_protoc :
594
+ self .with_protoc = os .environ .get ("MYSQLXPB_PROTOC" )
595
+
596
+ if self .with_protobuf_include_dir :
597
+ print ("# Protobuf include directory: {0}"
598
+ "" .format (self .with_protobuf_include_dir ))
599
+ else :
600
+ log .error ("Unable to find Protobuf include directory." )
601
+ sys .exit (1 )
602
+
603
+ if self .with_protobuf_lib_dir :
604
+ print ("# Protobuf library directory: {0}"
605
+ "" .format (self .with_protobuf_lib_dir ))
606
+ else :
607
+ log .error ("Unable to find Protobuf library directory." )
608
+ sys .exit (1 )
609
+
610
+ if self .with_protoc :
611
+ print ("# Protobuf protoc binary: {0}" .format (self .with_protoc ))
612
+ else :
613
+ log .error ("Unable to find Protobuf protoc binary." )
614
+ sys .exit (1 )
615
+
616
+ self ._finalize_protobuf ()
617
+
488
618
def _finalize_connector_c (self , connc_loc ):
489
619
if not os .path .isdir (connc_loc ):
490
620
log .error ("MySQL C API should be a directory" )
@@ -503,6 +633,39 @@ def _finalize_connector_c(self, connc_loc):
503
633
if os .path .isfile (lib_file_path ) and not lib_file .endswith ('.a' ):
504
634
os .unlink (os .path .join (self .connc_lib , lib_file ))
505
635
636
+ def _finalize_protobuf (self ):
637
+ if not os .path .isdir (self .with_protobuf_lib_dir ):
638
+ log .error ("Protobuf library dir should be a directory" )
639
+ sys .exit (1 )
640
+
641
+ if not os .path .isdir (self .with_protobuf_include_dir ):
642
+ log .error ("Protobuf include dir should be a directory" )
643
+ sys .exit (1 )
644
+
645
+ if not os .path .exists (self .protobuf_lib ):
646
+ os .makedirs (self .protobuf_lib )
647
+
648
+ if not os .path .exists (self .protobuf_include ):
649
+ os .makedirs (self .protobuf_include )
650
+
651
+ log .info ("Copying Protobuf libraries" )
652
+ lib_files = glob (os .path .join (self .with_protobuf_lib_dir , "libprotobuf*" ))
653
+ for lib_file in lib_files :
654
+ if os .path .isfile (lib_file ):
655
+ log .info ("copying {0} -> {1}" .format (lib_file , self .protobuf_lib ))
656
+ shutil .copy2 (lib_file , self .protobuf_lib )
657
+
658
+ log .info ("Copying Protobuf header files" )
659
+ copy_tree (self .with_protobuf_include_dir , self .protobuf_include )
660
+
661
+ # Remove all but static libraries to force static linking
662
+ if os .name == "posix" :
663
+ log .info ("Removing non-static Protobuf libraries from {0}"
664
+ "" .format (self .protobuf_lib ))
665
+ for lib_file in os .listdir (self .protobuf_lib ):
666
+ lib_file_path = os .path .join (self .protobuf_lib , lib_file )
667
+ if os .path .isfile (lib_file_path ) and not lib_file .endswith (".a" ):
668
+ os .unlink (os .path .join (self .protobuf_lib , lib_file ))
506
669
507
670
def fix_compiler (self ):
508
671
BuildExtDynamic .fix_compiler (self )
@@ -514,7 +677,8 @@ def fix_compiler(self):
514
677
if os .name == 'posix' :
515
678
include_dirs .append (self .connc_include )
516
679
library_dirs .append (self .connc_lib )
517
- libraries .append ("mysqlclient" )
680
+ if self .with_mysql_capi :
681
+ libraries .append ("mysqlclient" )
518
682
519
683
# As we statically link and the "libmysqlclient.a" library
520
684
# carry no information what it depends on, we need to
@@ -523,9 +687,16 @@ def fix_compiler(self):
523
687
libraries .append ("rt" )
524
688
525
689
for ext in self .extensions :
526
- ext .include_dirs .extend (include_dirs )
527
- ext .library_dirs .extend (library_dirs )
528
- ext .libraries .extend (libraries )
690
+ if ext .name == "_mysql_connector" :
691
+ ext .include_dirs .extend (include_dirs )
692
+ ext .library_dirs .extend (library_dirs )
693
+ ext .libraries .extend (libraries )
694
+ elif ext .name == "_mysqlxpb" \
695
+ and platform .system () not in ["Darwin" , "Windows" ]:
696
+ ext .libraries .append ("rt" )
697
+ # Add extra compile args
698
+ if self .extra_compile_args :
699
+ ext .extra_compile_args .append (self .extra_compile_args )
529
700
530
701
531
702
class InstallLib (install_lib ):
@@ -574,13 +745,17 @@ class Install(install):
574
745
575
746
def initialize_options (self ):
576
747
install .initialize_options (self )
748
+ self .extra_compile_args = None
577
749
self .with_mysql_capi = None
750
+ self .with_protobuf_include_dir = None
751
+ self .with_protobuf_lib_dir = None
752
+ self .with_protoc = None
578
753
self .byte_code_only = None
579
754
self .static = None
580
755
581
756
def finalize_options (self ):
582
757
if self .static :
583
- log .info ("Linking CExtension statically with MySQL libraries" )
758
+ log .info ("Linking C Extension statically with libraries" )
584
759
self .distribution .cmdclass ['build_ext' ] = BuildExtStatic
585
760
586
761
if self .byte_code_only is None :
@@ -600,7 +775,7 @@ def finalize_options(self):
600
775
601
776
def run (self ):
602
777
if not self .need_ext :
603
- log .info ("Not Installing C Extension" )
778
+ log .info ("Not Installing MySQL C Extension" )
604
779
else :
605
- log .info ("Installing C Extension" )
780
+ log .info ("Installing MySQL C Extension" )
606
781
install .run (self )
0 commit comments