-
Notifications
You must be signed in to change notification settings - Fork 26
/
rconfigure.py
163 lines (126 loc) · 5.5 KB
/
rconfigure.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import os
import sys
import shutil
import subprocess
import platform
extensions = ['parquet','core_functions']
# check if there are any additional extensions being requested
if 'DUCKDB_R_EXTENSIONS' in os.environ:
extensions = extensions + os.environ['DUCKDB_R_EXTENSIONS'].split(",")
unity_build = 20
if 'DUCKDB_BUILD_UNITY' in os.environ:
try:
unity_build = int(DUCKDB_BUILD_UNITY)
except:
pass
debug_move_flag = ''
if 'DUCKDB_DEBUG_MOVE' in os.environ:
debug_move_flag = ' -DDUCKDB_DEBUG_MOVE'
# This requires the mother duckdb repo to be checked out in a parallel directory
# (or in a directory specified by the DUCKDB_PATH environment variable).
# Submodules can't be used because they break R CMD build
if 'DUCKDB_PATH' in os.environ:
duckdb_path = os.environ['DUCKDB_PATH']
else:
duckdb_path = os.path.join('../duckdb')
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), duckdb_path, 'scripts'))
import package_build
def open_utf8(fpath, flags):
import sys
if sys.version_info[0] < 3:
return open(fpath, flags)
else:
return open(fpath, flags, encoding="utf8")
extension_list = ""
for ext in extensions:
extension_list += ' -DDUCKDB_EXTENSION_{}_LINKED'.format(ext.upper())
extension_list += " -DDUCKDB_BUILD_LIBRARY"
libraries = []
if platform.system() == 'Windows':
libraries += ['ws2_32']
link_flags = ''
for libname in libraries:
link_flags += ' -l' + libname
# check if we are doing a build from an existing DuckDB installation
if 'DUCKDB_R_BINDIR' in os.environ and 'DUCKDB_R_CFLAGS' in os.environ and 'DUCKDB_R_LIBS' in os.environ:
existing_duckdb_dir = os.environ['DUCKDB_R_BINDIR']
compile_flags = os.environ['DUCKDB_R_CFLAGS'].replace('\\', '').replace(' ', ' ')
rlibs = [x for x in os.environ['DUCKDB_R_LIBS'].split(' ') if len(x) > 0]
# use existing installation: set up Makevars
with open_utf8(os.path.join('src', 'Makevars.in'), 'r') as f:
text = f.read()
compile_flags += package_build.include_flags(extensions)
compile_flags += extension_list
# find libraries
result_libs = package_build.get_libraries(existing_duckdb_dir, rlibs, extensions)
for rlib in result_libs:
libdir = rlib[0]
libname = rlib[1]
if libdir != None:
link_flags += ' -L' + libdir
if libname != None:
link_flags += ' -l' + libname
text = text.replace('{{ SOURCES }}', '')
text = text.replace('{{ INCLUDES }}', compile_flags.strip())
text = text.replace('{{ LINK_FLAGS }}', link_flags.strip())
# now write it to the output Makevars
with open_utf8(os.path.join('src', 'Makevars'), 'w+') as f:
f.write(text)
exit(0)
if not os.path.isfile(os.path.join(duckdb_path, 'scripts', 'amalgamation.py')):
print("Could not find amalgamation script!")
exit(1)
target_dir = os.path.join(os.getcwd(), 'src', 'duckdb')
linenr = bool(os.getenv("DUCKDB_R_LINENR", ""))
(source_list, include_list, original_sources) = package_build.build_package(target_dir, extensions, linenr, unity_build)
# Walk target_dir, find all source and include files, and terminate with newline,
# if not already present
for root, dirs, files in os.walk(target_dir):
for file in files:
if file.endswith('.cpp') or file.endswith('.hpp') or file.endswith('.c') or file.endswith('.h') or file.endswith('.cc'):
filename = os.path.join(root, file)
with open (filename, "r") as f:
lines = f.readlines()
if len(lines) > 0 and lines[-1][-1] != '\n':
with open (filename, "a") as fw:
fw.write("\n")
# object list, relative paths
script_path = os.path.dirname(os.path.abspath(__file__)).replace('\\', '/')
duckdb_sources = [package_build.get_relative_path(os.path.join(script_path, 'src'), x) for x in source_list]
object_list = ' '.join([x.rsplit('.', 1)[0] + '.o' for x in duckdb_sources])
# include list
include_list = ' '.join(['-I' + 'duckdb/' + x for x in include_list])
include_list += ' -I' + os.path.join('..', 'inst', 'include')
include_list += ' -Iduckdb'
include_list += extension_list
include_list += debug_move_flag
# add -Werror if enabled
if 'TREAT_WARNINGS_AS_ERRORS' in os.environ:
include_list += ' -Werror'
# read Makevars.in and replace the {{ SOURCES }} and {{ INCLUDES }} macros
with open_utf8(os.path.join('src', 'Makevars.in'), 'r') as f:
text = f.read()
text = text.replace('{{ HEADER }}', 'Generated by rconfigure.py, do not edit by hand')
text = text.replace('{{ INCLUDES }}', include_list)
if len(libraries) == 0:
text = text.replace('PKG_LIBS={{ LINK_FLAGS }}\n', '')
else:
text = text.replace('{{ LINK_FLAGS }}', link_flags.strip())
# now write it to the output Makevars
with open_utf8(os.path.join('src', 'Makevars'), 'w+') as f:
f.write(text)
# same dance for Windows
# read Makevars.in and replace the {{ SOURCES }} and {{ INCLUDES }} macros
with open_utf8(os.path.join('src', 'Makevars.in'), 'r') as f:
text = f.read()
text = text.replace('{{ HEADER }}', 'Generated by rconfigure.py, do not edit by hand')
include_list += " -DDUCKDB_PLATFORM_RTOOLS=1"
text = text.replace('{{ INCLUDES }}', include_list)
text = text.replace('{{ LINK_FLAGS }}', "-lws2_32 -L. -lrstrtmgr")
# now write it to the output Makevars
with open_utf8(os.path.join('src', 'Makevars.win'), 'w+') as f:
f.write(text)
# write sources.mk
text = "SOURCES=" + object_list + '\n'
with open_utf8(os.path.join('src', 'include', 'sources.mk'), 'w') as f:
f.write(text)