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'], 'S'),
19 ('linux', 'x86_64', 'elf', [''], 'S'),
20 ('mac', 'x86', 'macosx', ['-fPIC'], 'S'),
21 ('mac', 'x86_64', 'macosx', [''], 'S'),
22 ('win', 'x86', 'win32n', [''], '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 filename
.endswith('.c') and filter_func(filename
, False):
81 cfiles
.append(os
.path
.join(path
, filename
))
84 for (i
, dirname
) in enumerate(dirnames
):
85 if not filter_func(dirname
, True):
91 def ExtractPerlAsmFromCMakeFile(cmakefile
):
92 """Parses the contents of the CMakeLists.txt file passed as an argument and
93 returns a list of all the perlasm() directives found in the file."""
95 with
open(cmakefile
) as f
:
98 if not line
.startswith('perlasm('):
100 if not line
.endswith(')'):
101 raise ValueError('Bad perlasm line in %s' % cmakefile
)
102 # Remove "perlasm(" from start and ")" from end
103 params
= line
[8:-1].split()
105 raise ValueError('Bad perlasm line in %s' % cmakefile
)
107 'extra_args': params
[2:],
108 'input': os
.path
.join(os
.path
.dirname(cmakefile
), params
[1]),
109 'output': os
.path
.join(os
.path
.dirname(cmakefile
), params
[0]),
115 def ReadPerlAsmOperations():
116 """Returns a list of all perlasm() directives found in CMake config files in
119 cmakefiles
= FindCMakeFiles('src')
121 for cmakefile
in cmakefiles
:
122 perlasms
.extend(ExtractPerlAsmFromCMakeFile(cmakefile
))
127 def PerlAsm(output_filename
, input_filename
, perlasm_style
, extra_args
):
128 """Runs the a perlasm script and puts the output into output_filename."""
129 base_dir
= os
.path
.dirname(output_filename
)
130 if not os
.path
.isdir(base_dir
):
131 os
.makedirs(base_dir
)
132 output
= subprocess
.check_output(
133 ['perl', input_filename
, perlasm_style
] + extra_args
)
134 with
open(output_filename
, 'w+') as out_file
:
135 out_file
.write(output
)
138 def ArchForAsmFilename(filename
):
139 """Returns the architectures that a given asm file should be compiled for
140 based on substrings in the filename."""
142 if 'x86_64' in filename
or 'avx2' in filename
:
144 elif ('x86' in filename
and 'x86_64' not in filename
) or '586' in filename
:
146 elif 'armx' in filename
:
147 return ['arm', 'aarch64']
148 elif 'armv8' in filename
:
150 elif 'arm' in filename
:
153 raise ValueError('Unknown arch for asm filename: ' + filename
)
156 def WriteAsmFiles(perlasms
):
157 """Generates asm files from perlasm directives for each supported OS x
158 platform combination."""
161 for osarch
in OS_ARCH_COMBOS
:
162 (osname
, arch
, perlasm_style
, extra_args
, asm_ext
) = osarch
164 outDir
= '%s-%s' % key
166 for perlasm
in perlasms
:
167 filename
= os
.path
.basename(perlasm
['input'])
168 output
= perlasm
['output']
169 if not output
.startswith('src'):
170 raise ValueError('output missing src: %s' % output
)
171 output
= os
.path
.join(outDir
, output
[4:])
172 output
= output
.replace('${ASM_EXT}', asm_ext
)
174 if arch
in ArchForAsmFilename(filename
):
175 PerlAsm(output
, perlasm
['input'], perlasm_style
,
176 perlasm
['extra_args'] + extra_args
)
177 asmfiles
.setdefault(key
, []).append(output
)
179 for (key
, non_perl_asm_files
) in NON_PERL_FILES
.iteritems():
180 asmfiles
.setdefault(key
, []).extend(non_perl_asm_files
)
185 def PrintVariableSection(out
, name
, files
):
186 out
.write(' \'%s\': [\n' % name
)
187 for f
in sorted(files
):
188 out
.write(' \'%s\',\n' % f
)
193 crypto_c_files
= FindCFiles(os
.path
.join('src', 'crypto'), NoTests
)
194 ssl_c_files
= FindCFiles(os
.path
.join('src', 'ssl'), NoTests
)
196 with
open('boringssl.gypi', 'w+') as gypi
:
197 gypi
.write(FILE_HEADER
+ '{\n \'variables\': {\n')
199 PrintVariableSection(
200 gypi
, 'boringssl_lib_sources', crypto_c_files
+ ssl_c_files
)
202 perlasms
= ReadPerlAsmOperations()
204 for ((osname
, arch
), asm_files
) in sorted(
205 WriteAsmFiles(perlasms
).iteritems()):
206 PrintVariableSection(gypi
, 'boringssl_%s_%s_sources' %
207 (osname
, arch
), asm_files
)
209 gypi
.write(' }\n}\n')
211 test_c_files
= FindCFiles(os
.path
.join('src', 'crypto'), OnlyTests
)
212 test_c_files
+= FindCFiles(os
.path
.join('src', 'ssl'), OnlyTests
)
214 with
open('boringssl_tests.gypi', 'w+') as test_gypi
:
215 test_gypi
.write(FILE_HEADER
+ '{\n \'targets\': [\n')
218 for test
in sorted(test_c_files
):
219 test_name
= 'boringssl_%s' % os
.path
.splitext(os
.path
.basename(test
))[0]
220 test_gypi
.write(""" {
222 'type': 'executable',
224 'boringssl.gyp:boringssl',
229 # TODO(davidben): Fix size_t truncations in BoringSSL.
230 # https://crbug.com/429039
231 'msvs_disabled_warnings': [ 4267, ],
232 },\n""" % (test_name
, test
))
233 test_names
.append(test_name
)
237 test_gypi
.write(""" ],
239 'boringssl_test_targets': [\n""")
241 for test
in test_names
:
242 test_gypi
.write(""" '%s',\n""" % test
)
244 test_gypi
.write(' ],\n }\n}\n')
249 if __name__
== '__main__':