10
10
11
11
ROOT_DIR = os .path .abspath (os .path .join (__file__ , '..' , '..' ))
12
12
13
- def install_and_rebuild (args , install_args ):
13
+ # Run install.py to install headers.
14
+ def generate_headers (headers_dir , install_args ):
15
+ print ('Generating headers' )
16
+ subprocess .check_call ([
17
+ sys .executable ,
18
+ os .path .join (ROOT_DIR , 'tools/install.py' ),
19
+ 'install' ,
20
+ '--silent' ,
21
+ '--headers-only' ,
22
+ '--prefix' , '/' ,
23
+ '--dest-dir' , headers_dir ,
24
+ ] + install_args )
25
+
26
+ # Rebuild addons in parallel.
27
+ def rebuild_addons (args ):
28
+ headers_dir = os .path .abspath (args .headers_dir )
14
29
out_dir = os .path .abspath (args .out_dir )
15
30
node_bin = os .path .join (out_dir , 'node' )
16
31
if args .is_win :
@@ -21,71 +36,57 @@ def install_and_rebuild(args, install_args):
21
36
else :
22
37
node_gyp = os .path .join (ROOT_DIR , args .node_gyp )
23
38
24
- # Create a temporary directory for node headers.
25
- with tempfile .TemporaryDirectory () as headers_dir :
26
- # Run install.py to install headers.
27
- print ('Generating headers' )
28
- subprocess .check_call ([
29
- sys .executable ,
30
- os .path .join (ROOT_DIR , 'tools/install.py' ),
31
- 'install' ,
32
- '--silent' ,
33
- '--headers-only' ,
34
- '--prefix' , '/' ,
35
- '--dest-dir' , headers_dir ,
36
- ] + install_args )
37
-
38
- # Copy node.lib.
39
- if args .is_win :
40
- node_lib_dir = os .path .join (headers_dir , 'Release' )
41
- os .makedirs (node_lib_dir )
42
- shutil .copy2 (os .path .join (args .out_dir , 'node.lib' ),
43
- os .path .join (node_lib_dir , 'node.lib' ))
39
+ # Copy node.lib.
40
+ if args .is_win :
41
+ node_lib_dir = os .path .join (headers_dir , 'Release' )
42
+ os .makedirs (node_lib_dir )
43
+ shutil .copy2 (os .path .join (args .out_dir , 'node.lib' ),
44
+ os .path .join (node_lib_dir , 'node.lib' ))
44
45
45
- def rebuild_addon (test_dir ):
46
- print ('Building addon in' , test_dir )
47
- try :
48
- process = subprocess .Popen ([
49
- node_bin ,
50
- node_gyp ,
51
- 'rebuild' ,
52
- '--directory' , test_dir ,
53
- '--nodedir' , headers_dir ,
54
- '--python' , sys .executable ,
55
- '--loglevel' , args .loglevel ,
56
- ], stdout = subprocess .PIPE , stderr = subprocess .PIPE )
46
+ def node_gyp_rebuild (test_dir ):
47
+ print ('Building addon in' , test_dir )
48
+ try :
49
+ process = subprocess .Popen ([
50
+ node_bin ,
51
+ node_gyp ,
52
+ 'rebuild' ,
53
+ '--directory' , test_dir ,
54
+ '--nodedir' , headers_dir ,
55
+ '--python' , sys .executable ,
56
+ '--loglevel' , args .loglevel ,
57
+ ], stdout = subprocess .PIPE , stderr = subprocess .PIPE )
57
58
58
- # We buffer the output and print it out once the process is done in order
59
- # to avoid interleaved output from multiple builds running at once.
60
- return_code = process .wait ()
61
- stdout , stderr = process .communicate ()
62
- if return_code != 0 :
63
- print (f'Failed to build addon in { test_dir } :' )
64
- if stdout :
65
- print (stdout .decode ())
66
- if stderr :
67
- print (stderr .decode ())
59
+ # We buffer the output and print it out once the process is done in order
60
+ # to avoid interleaved output from multiple builds running at once.
61
+ return_code = process .wait ()
62
+ stdout , stderr = process .communicate ()
63
+ if return_code != 0 :
64
+ print (f'Failed to build addon in { test_dir } :' )
65
+ if stdout :
66
+ print (stdout .decode ())
67
+ if stderr :
68
+ print (stderr .decode ())
68
69
69
- except Exception as e :
70
- print (f'Unexpected error when building addon in { test_dir } . Error: { e } ' )
70
+ except Exception as e :
71
+ print (f'Unexpected error when building addon in { test_dir } . Error: { e } ' )
71
72
72
- test_dirs = []
73
- skip_tests = args .skip_tests .split (',' )
74
- only_tests = args .only_tests .split (',' ) if args .only_tests else None
75
- for child_dir in os .listdir (args .target ):
76
- full_path = os .path .join (args .target , child_dir )
77
- if not os .path .isdir (full_path ):
78
- continue
79
- if 'binding.gyp' not in os .listdir (full_path ):
80
- continue
81
- if child_dir in skip_tests :
82
- continue
83
- if only_tests and child_dir not in only_tests :
84
- continue
85
- test_dirs .append (full_path )
73
+ test_dirs = []
74
+ skip_tests = args .skip_tests .split (',' )
75
+ only_tests = args .only_tests .split (',' ) if args .only_tests else None
76
+ for child_dir in os .listdir (args .target ):
77
+ full_path = os .path .join (args .target , child_dir )
78
+ if not os .path .isdir (full_path ):
79
+ continue
80
+ if 'binding.gyp' not in os .listdir (full_path ):
81
+ continue
82
+ if child_dir in skip_tests :
83
+ continue
84
+ if only_tests and child_dir not in only_tests :
85
+ continue
86
+ test_dirs .append (full_path )
86
87
87
- with ThreadPoolExecutor () as executor :
88
- executor .map (rebuild_addon , test_dirs )
88
+ with ThreadPoolExecutor () as executor :
89
+ executor .map (node_gyp_rebuild , test_dirs )
89
90
90
91
def main ():
91
92
if sys .platform == 'cygwin' :
@@ -94,6 +95,10 @@ def main():
94
95
parser = argparse .ArgumentParser (
95
96
description = 'Install headers and rebuild child directories' )
96
97
parser .add_argument ('target' , help = 'target directory to build addons' )
98
+ parser .add_argument ('--headers-dir' ,
99
+ help = 'path to node headers directory, if not specified '
100
+ 'new headers will be generated for building' ,
101
+ default = None )
97
102
parser .add_argument ('--out-dir' , help = 'path to the output directory' ,
98
103
default = 'out/Release' )
99
104
parser .add_argument ('--loglevel' , help = 'loglevel of node-gyp' ,
@@ -108,7 +113,17 @@ def main():
108
113
action = 'store_true' , default = (sys .platform == 'win32' ))
109
114
args , unknown_args = parser .parse_known_args ()
110
115
111
- install_and_rebuild (args , unknown_args )
116
+ if args .headers_dir :
117
+ rebuild_addons (args )
118
+ else :
119
+ # When --headers-dir is not specified, generate headers into a temp dir and
120
+ # build with the new headers.
121
+ try :
122
+ args .headers_dir = tempfile .mkdtemp ()
123
+ generate_headers (args .headers_dir , unknown_args )
124
+ rebuild_addons (args )
125
+ finally :
126
+ shutil .rmtree (args .headers_dir )
112
127
113
128
if __name__ == '__main__' :
114
129
main ()
0 commit comments