|
1 | 1 | import os |
2 | 2 | import sys |
| 3 | +import subprocess |
3 | 4 |
|
4 | | -# This dequote() business is required for some older versions |
5 | | -# of mysql_config |
6 | 5 |
|
7 | | - |
8 | | -def dequote(s): |
9 | | - if not s: |
10 | | - raise Exception( |
11 | | - "Wrong MySQL configuration: maybe https://bugs.mysql.com/bug.php?id=86971 ?" |
12 | | - ) |
13 | | - if s[0] in "\"'" and s[0] == s[-1]: |
14 | | - s = s[1:-1] |
15 | | - return s |
16 | | - |
17 | | - |
18 | | -_mysql_config_path = "mysql_config" |
19 | | - |
20 | | - |
21 | | -def mysql_config(what): |
22 | | - cmd = "{} --{}".format(_mysql_config_path, what) |
23 | | - print(cmd) |
24 | | - f = os.popen(cmd) |
25 | | - data = f.read().strip().split() |
26 | | - ret = f.close() |
27 | | - if ret: |
28 | | - if ret / 256: |
29 | | - data = [] |
30 | | - if ret / 256 > 1: |
31 | | - raise OSError("{} not found".format(_mysql_config_path)) |
32 | | - print(data) |
33 | | - return data |
| 6 | +def find_package_name(): |
| 7 | + """Get available pkg-config package name""" |
| 8 | + packages = ["mysqlclient", "mariadb"] |
| 9 | + for pkg in packages: |
| 10 | + try: |
| 11 | + cmd = f"pkg-config --exists {pkg}" |
| 12 | + print(f"Trying {cmd}") |
| 13 | + subprocess.check_call(cmd, shell=True) |
| 14 | + except subprocess.CalledProcessError as err: |
| 15 | + print(err) |
| 16 | + else: |
| 17 | + return pkg |
| 18 | + raise Exception("Can not find valid pkg-config") |
34 | 19 |
|
35 | 20 |
|
36 | 21 | def get_config(): |
37 | 22 | from setup_common import get_metadata_and_options, enabled, create_release_file |
38 | 23 |
|
39 | | - global _mysql_config_path |
40 | | - |
41 | 24 | metadata, options = get_metadata_and_options() |
42 | 25 |
|
43 | | - if "mysql_config" in options: |
44 | | - _mysql_config_path = options["mysql_config"] |
45 | | - else: |
46 | | - try: |
47 | | - mysql_config("version") |
48 | | - except OSError: |
49 | | - # try mariadb_config |
50 | | - _mysql_config_path = "mariadb_config" |
51 | | - try: |
52 | | - mysql_config("version") |
53 | | - except OSError: |
54 | | - _mysql_config_path = "mysql_config" |
55 | | - |
56 | | - extra_objects = [] |
57 | 26 | static = enabled(options, "static") |
58 | | - |
59 | 27 | # allow a command-line option to override the base config file to permit |
60 | 28 | # a static build to be created via requirements.txt |
61 | 29 | # |
62 | 30 | if "--static" in sys.argv: |
63 | 31 | static = True |
64 | 32 | sys.argv.remove("--static") |
65 | 33 |
|
66 | | - libs = os.environ.get("MYSQLCLIENT_LDFLAGS") |
67 | | - if libs: |
68 | | - libs = libs.strip().split() |
69 | | - else: |
70 | | - libs = mysql_config("libs") |
71 | | - library_dirs = [dequote(i[2:]) for i in libs if i.startswith("-L")] |
72 | | - libraries = [dequote(i[2:]) for i in libs if i.startswith("-l")] |
73 | | - extra_link_args = [x for x in libs if not x.startswith(("-l", "-L"))] |
74 | | - |
| 34 | + ldflags = os.environ.get("MYSQLCLIENT_LDFLAGS") |
75 | 35 | cflags = os.environ.get("MYSQLCLIENT_CFLAGS") |
76 | | - if cflags: |
77 | | - use_mysqlconfig_cflags = False |
78 | | - cflags = cflags.strip().split() |
79 | | - else: |
80 | | - use_mysqlconfig_cflags = True |
81 | | - cflags = mysql_config("cflags") |
82 | | - |
83 | | - include_dirs = [] |
84 | | - extra_compile_args = ["-std=c99"] |
85 | 36 |
|
86 | | - for a in cflags: |
87 | | - if a.startswith("-I"): |
88 | | - include_dirs.append(dequote(a[2:])) |
89 | | - elif a.startswith(("-L", "-l")): # This should be LIBS. |
90 | | - pass |
91 | | - else: |
92 | | - extra_compile_args.append(a.replace("%", "%%")) |
93 | | - |
94 | | - # Copy the arch flags for linking as well |
95 | | - try: |
96 | | - i = extra_compile_args.index("-arch") |
97 | | - if "-arch" not in extra_link_args: |
98 | | - extra_link_args += ["-arch", extra_compile_args[i + 1]] |
99 | | - except ValueError: |
100 | | - pass |
| 37 | + pkg_name = None |
| 38 | + static_opt = " --static" if static else "" |
| 39 | + if not (cflags and ldflags): |
| 40 | + pkg_name = find_package_name() |
| 41 | + if not cflags: |
| 42 | + cflags = subprocess.check_output( |
| 43 | + f"pkg-config{static_opt} --cflags {pkg_name}", encoding="utf-8", shell=True |
| 44 | + ) |
| 45 | + if not ldflags: |
| 46 | + ldflags = subprocess.check_output( |
| 47 | + f"pkg-config{static_opt} --libs {pkg_name}", encoding="utf-8", shell=True |
| 48 | + ) |
101 | 49 |
|
102 | | - if static: |
103 | | - # properly handle mysql client libraries that are not called libmysqlclient |
104 | | - client = None |
105 | | - CLIENT_LIST = [ |
106 | | - "mysqlclient", |
107 | | - "mysqlclient_r", |
108 | | - "mysqld", |
109 | | - "mariadb", |
110 | | - "mariadbclient", |
111 | | - "perconaserverclient", |
112 | | - "perconaserverclient_r", |
113 | | - ] |
114 | | - for c in CLIENT_LIST: |
115 | | - if c in libraries: |
116 | | - client = c |
117 | | - break |
118 | | - |
119 | | - if client == "mariadb": |
120 | | - client = "mariadbclient" |
121 | | - if client is None: |
122 | | - raise ValueError("Couldn't identify mysql client library") |
123 | | - |
124 | | - extra_objects.append(os.path.join(library_dirs[0], "lib%s.a" % client)) |
125 | | - if client in libraries: |
126 | | - libraries.remove(client) |
| 50 | + cflags = cflags.split() |
| 51 | + for f in cflags: |
| 52 | + if f.startswith("-std="): |
| 53 | + break |
127 | 54 | else: |
128 | | - if use_mysqlconfig_cflags: |
129 | | - # mysql_config may have "-lmysqlclient -lz -lssl -lcrypto", but zlib and |
130 | | - # ssl is not used by _mysql. They are needed only for static build. |
131 | | - for L in ("crypto", "ssl", "z", "zstd"): |
132 | | - if L in libraries: |
133 | | - libraries.remove(L) |
| 55 | + cflags += ["-std=c99"] |
134 | 56 |
|
135 | | - name = "mysqlclient" |
136 | | - metadata["name"] = name |
| 57 | + ldflags = ldflags.split() |
137 | 58 |
|
138 | 59 | define_macros = [ |
139 | 60 | ("version_info", metadata["version_info"]), |
140 | 61 | ("__version__", metadata["version"]), |
141 | 62 | ] |
142 | | - create_release_file(metadata) |
143 | | - del metadata["version_info"] |
| 63 | + |
| 64 | + # print(f"{cflags = }") |
| 65 | + # print(f"{ldflags = }") |
| 66 | + # print(f"{define_macros = }") |
| 67 | + |
144 | 68 | ext_options = dict( |
145 | | - library_dirs=library_dirs, |
146 | | - libraries=libraries, |
147 | | - extra_compile_args=extra_compile_args, |
148 | | - extra_link_args=extra_link_args, |
149 | | - include_dirs=include_dirs, |
150 | | - extra_objects=extra_objects, |
| 69 | + extra_compile_args=cflags, |
| 70 | + extra_link_args=ldflags, |
151 | 71 | define_macros=define_macros, |
152 | 72 | ) |
153 | | - |
154 | 73 | # newer versions of gcc require libstdc++ if doing a static build |
155 | 74 | if static: |
156 | 75 | ext_options["language"] = "c++" |
157 | 76 |
|
158 | | - print("ext_options:") |
| 77 | + print("Options for building extention module:") |
159 | 78 | for k, v in ext_options.items(): |
160 | | - print(" {}: {}".format(k, v)) |
| 79 | + print(f" {k}: {v}") |
| 80 | + |
| 81 | + create_release_file(metadata) |
| 82 | + del metadata["version_info"] |
161 | 83 |
|
162 | 84 | return metadata, ext_options |
163 | 85 |
|
164 | 86 |
|
165 | 87 | if __name__ == "__main__": |
166 | | - sys.stderr.write( |
167 | | - """You shouldn't be running this directly; it is used by setup.py.""" |
168 | | - ) |
| 88 | + from pprint import pprint |
| 89 | + |
| 90 | + metadata, config = get_config() |
| 91 | + print("# Metadata") |
| 92 | + pprint(metadata, sort_dicts=False, compact=True) |
| 93 | + print("\n# Extention options") |
| 94 | + pprint(config, sort_dicts=False, compact=True) |
0 commit comments