1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can b
3 # found in the LICENSE file.
5 """Enumerates the BoringSSL source in src/ and generates two gypi files:
6 boringssl.gypi and boringssl_tests.gypi."""
13 # OS_ARCH_COMBOS maps from OS and platform to the OpenSSL assembly "style" for
14 # that platform and the extension used by asm files.
16 ('linux', 'arm', 'elf', [], 'S'),
17 ('linux', 'aarch64', 'linux64', [], 'S'),
18 ('linux', 'x86', 'elf', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'),
19 ('linux', 'x86_64', 'elf', [], 'S'),
20 ('mac', 'x86', 'macosx', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'),
21 ('mac', 'x86_64', 'macosx', [], 'S'),
22 ('win', 'x86', 'win32n', ['-DOPENSSL_IA32_SSE2'], 'asm'),
23 ('win', 'x86_64', 'nasm', [], 'asm'),
26 # NON_PERL_FILES enumerates assembly files that are not processed by the
30 'src/crypto/poly1305/poly1305_arm_asm.S',
31 'src/crypto/chacha/chacha_vec_arm.S',
32 'src/crypto/cpu-arm-asm.S',
36 FILE_HEADER
= """# Copyright (c) 2014 The Chromium Authors. All rights reserved.
37 # Use of this source code is governed by a BSD-style license that can be
38 # found in the LICENSE file.
40 # This file is created by update_gypi_and_asm.py. Do not edit manually.
45 def FindCMakeFiles(directory
):
46 """Returns list of all CMakeLists.txt files recursively in directory."""
49 for (path
, _
, filenames
) in os
.walk(directory
):
50 for filename
in filenames
:
51 if filename
== 'CMakeLists.txt':
52 cmakefiles
.append(os
.path
.join(path
, filename
))
57 def NoTests(dent
, is_dir
):
58 """Filter function that can be passed to FindCFiles in order to remove test
62 return 'test.' not in dent
and not dent
.startswith('example_')
65 def OnlyTests(dent
, is_dir
):
66 """Filter function that can be passed to FindCFiles in order to remove
70 return '_test.' in dent
or dent
.startswith('example_')
73 def FindCFiles(directory
, filter_func
):
74 """Recurses through directory and returns a list of paths to all the C source
75 files that pass filter_func."""
78 for (path
, dirnames
, filenames
) in os
.walk(directory
):
79 for filename
in filenames
:
80 if not filename
.endswith('.c') and not filename
.endswith('.cc'):
82 if not filter_func(filename
, False):
84 cfiles
.append(os
.path
.join(path
, filename
))
86 for (i
, dirname
) in enumerate(dirnames
):
87 if not filter_func(dirname
, True):
93 def ExtractPerlAsmFromCMakeFile(cmakefile
):
94 """Parses the contents of the CMakeLists.txt file passed as an argument and
95 returns a list of all the perlasm() directives found in the file."""
97 with
open(cmakefile
) as f
:
100 if not line
.startswith('perlasm('):
102 if not line
.endswith(')'):
103 raise ValueError('Bad perlasm line in %s' % cmakefile
)
104 # Remove "perlasm(" from start and ")" from end
105 params
= line
[8:-1].split()
107 raise ValueError('Bad perlasm line in %s' % cmakefile
)
109 'extra_args': params
[2:],
110 'input': os
.path
.join(os
.path
.dirname(cmakefile
), params
[1]),
111 'output': os
.path
.join(os
.path
.dirname(cmakefile
), params
[0]),
117 def ReadPerlAsmOperations():
118 """Returns a list of all perlasm() directives found in CMake config files in
121 cmakefiles
= FindCMakeFiles('src')
123 for cmakefile
in cmakefiles
:
124 perlasms
.extend(ExtractPerlAsmFromCMakeFile(cmakefile
))
129 def PerlAsm(output_filename
, input_filename
, perlasm_style
, extra_args
):
130 """Runs the a perlasm script and puts the output into output_filename."""
131 base_dir
= os
.path
.dirname(output_filename
)
132 if not os
.path
.isdir(base_dir
):
133 os
.makedirs(base_dir
)
134 output
= subprocess
.check_output(
135 ['perl', input_filename
, perlasm_style
] + extra_args
)
136 with
open(output_filename
, 'w+') as out_file
:
137 out_file
.write(output
)
140 def ArchForAsmFilename(filename
):
141 """Returns the architectures that a given asm file should be compiled for
142 based on substrings in the filename."""
144 if 'x86_64' in filename
or 'avx2' in filename
:
146 elif ('x86' in filename
and 'x86_64' not in filename
) or '586' in filename
:
148 elif 'armx' in filename
:
149 return ['arm', 'aarch64']
150 elif 'armv8' in filename
:
152 elif 'arm' in filename
:
155 raise ValueError('Unknown arch for asm filename: ' + filename
)
158 def WriteAsmFiles(perlasms
):
159 """Generates asm files from perlasm directives for each supported OS x
160 platform combination."""
163 for osarch
in OS_ARCH_COMBOS
:
164 (osname
, arch
, perlasm_style
, extra_args
, asm_ext
) = osarch
166 outDir
= '%s-%s' % key
168 for perlasm
in perlasms
:
169 filename
= os
.path
.basename(perlasm
['input'])
170 output
= perlasm
['output']
171 if not output
.startswith('src'):
172 raise ValueError('output missing src: %s' % output
)
173 output
= os
.path
.join(outDir
, output
[4:])
174 output
= output
.replace('${ASM_EXT}', asm_ext
)
176 if arch
in ArchForAsmFilename(filename
):
177 PerlAsm(output
, perlasm
['input'], perlasm_style
,
178 perlasm
['extra_args'] + extra_args
)
179 asmfiles
.setdefault(key
, []).append(output
)
181 for (key
, non_perl_asm_files
) in NON_PERL_FILES
.iteritems():
182 asmfiles
.setdefault(key
, []).extend(non_perl_asm_files
)
187 def PrintVariableSection(out
, name
, files
):
188 out
.write(' \'%s\': [\n' % name
)
189 for f
in sorted(files
):
190 out
.write(' \'%s\',\n' % f
)
195 crypto_c_files
= FindCFiles(os
.path
.join('src', 'crypto'), NoTests
)
196 ssl_c_files
= FindCFiles(os
.path
.join('src', 'ssl'), NoTests
)
198 # Generate err_data.c
199 with
open('err_data.c', 'w+') as err_data
:
200 subprocess
.check_call(['go', 'run', 'err_data_generate.go'],
201 cwd
=os
.path
.join('src', 'crypto', 'err'),
203 crypto_c_files
.append('err_data.c')
205 with
open('boringssl.gypi', 'w+') as gypi
:
206 gypi
.write(FILE_HEADER
+ '{\n \'variables\': {\n')
208 PrintVariableSection(
209 gypi
, 'boringssl_lib_sources', crypto_c_files
+ ssl_c_files
)
211 perlasms
= ReadPerlAsmOperations()
213 for ((osname
, arch
), asm_files
) in sorted(
214 WriteAsmFiles(perlasms
).iteritems()):
215 PrintVariableSection(gypi
, 'boringssl_%s_%s_sources' %
216 (osname
, arch
), asm_files
)
218 gypi
.write(' }\n}\n')
220 test_c_files
= FindCFiles(os
.path
.join('src', 'crypto'), OnlyTests
)
221 test_c_files
+= FindCFiles(os
.path
.join('src', 'ssl'), OnlyTests
)
223 with
open('boringssl_tests.gypi', 'w+') as test_gypi
:
224 test_gypi
.write(FILE_HEADER
+ '{\n \'targets\': [\n')
227 for test
in sorted(test_c_files
):
228 test_name
= 'boringssl_%s' % os
.path
.splitext(os
.path
.basename(test
))[0]
229 test_gypi
.write(""" {
231 'type': 'executable',
233 'boringssl.gyp:boringssl',
238 # TODO(davidben): Fix size_t truncations in BoringSSL.
239 # https://crbug.com/429039
240 'msvs_disabled_warnings': [ 4267, ],
241 },\n""" % (test_name
, test
))
242 test_names
.append(test_name
)
246 test_gypi
.write(""" ],
248 'boringssl_test_targets': [\n""")
250 for test
in test_names
:
251 test_gypi
.write(""" '%s',\n""" % test
)
253 test_gypi
.write(' ],\n }\n}\n')
258 if __name__
== '__main__':