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', 'x86', 'elf', ['-fPIC'], 'S'),
18 ('linux', 'x86_64', 'elf', [''], 'S'),
19 ('mac', 'x86', 'macosx', ['-fPIC'], 'S'),
20 ('mac', 'x86_64', 'macosx', [''], 'S'),
21 ('win', 'x86', 'win32n', [''], 'asm'),
22 ('win', 'x86_64', 'nasm', [''], 'asm'),
25 # NON_PERL_FILES enumerates assembly files that are not processed by the
29 'src/crypto/poly1305/poly1305_arm_asm.S',
30 'src/crypto/chacha/chacha_vec_arm.S',
34 FILE_HEADER
= """# Copyright (c) 2014 The Chromium Authors. All rights reserved.
35 # Use of this source code is governed by a BSD-style license that can be
36 # found in the LICENSE file.
38 # This file is created by update_gypi_and_asm.py. Do not edit manually.
43 def FindCMakeFiles(directory
):
44 """Returns list of all CMakeLists.txt files recursively in directory."""
47 for (path
, _
, filenames
) in os
.walk(directory
):
48 for filename
in filenames
:
49 if filename
== 'CMakeLists.txt':
50 cmakefiles
.append(os
.path
.join(path
, filename
))
55 def NoTests(dent
, is_dir
):
56 """Filter function that can be passed to FindCFiles in order to remove test
60 return 'test.' not in dent
and not dent
.startswith('example_')
63 def OnlyTests(dent
, is_dir
):
64 """Filter function that can be passed to FindCFiles in order to remove
68 return '_test.' in dent
or dent
.startswith('example_')
71 def FindCFiles(directory
, filter_func
):
72 """Recurses through directory and returns a list of paths to all the C source
73 files that pass filter_func."""
76 for (path
, dirnames
, filenames
) in os
.walk(directory
):
77 for filename
in filenames
:
78 if filename
.endswith('.c') and filter_func(filename
, False):
79 cfiles
.append(os
.path
.join(path
, filename
))
82 for (i
, dirname
) in enumerate(dirnames
):
83 if not filter_func(dirname
, True):
89 def ExtractPerlAsmFromCMakeFile(cmakefile
):
90 """Parses the contents of the CMakeLists.txt file passed as an argument and
91 returns a list of all the perlasm() directives found in the file."""
93 with
open(cmakefile
) as f
:
96 if not line
.startswith('perlasm('):
98 if not line
.endswith(')'):
99 raise ValueError('Bad perlasm line in %s' % cmakefile
)
100 # Remove "perlasm(" from start and ")" from end
101 params
= line
[8:-1].split()
103 raise ValueError('Bad perlasm line in %s' % cmakefile
)
105 'extra_args': params
[2:],
106 'input': os
.path
.join(os
.path
.dirname(cmakefile
), params
[1]),
107 'output': os
.path
.join(os
.path
.dirname(cmakefile
), params
[0]),
113 def ReadPerlAsmOperations():
114 """Returns a list of all perlasm() directives found in CMake config files in
117 cmakefiles
= FindCMakeFiles('src')
119 for cmakefile
in cmakefiles
:
120 perlasms
.extend(ExtractPerlAsmFromCMakeFile(cmakefile
))
125 def PerlAsm(output_filename
, input_filename
, perlasm_style
, extra_args
):
126 """Runs the a perlasm script and puts the output into output_filename."""
127 base_dir
= os
.path
.dirname(output_filename
)
128 if not os
.path
.isdir(base_dir
):
129 os
.makedirs(base_dir
)
130 output
= subprocess
.check_output(
131 ['perl', input_filename
, perlasm_style
] + extra_args
)
132 with
open(output_filename
, 'w+') as out_file
:
133 out_file
.write(output
)
136 def ArchForAsmFilename(filename
):
137 """Returns the architecture that a given asm file should be compiled for
138 based on substrings in the filename."""
140 if 'x86_64' in filename
or 'avx2' in filename
:
142 elif ('x86' in filename
and 'x86_64' not in filename
) or '586' in filename
:
144 elif 'arm' in filename
:
147 raise ValueError('Unknown arch for asm filename: ' + filename
)
150 def WriteAsmFiles(perlasms
):
151 """Generates asm files from perlasm directives for each supported OS x
152 platform combination."""
155 for osarch
in OS_ARCH_COMBOS
:
156 (osname
, arch
, perlasm_style
, extra_args
, asm_ext
) = osarch
158 outDir
= '%s-%s' % key
160 for perlasm
in perlasms
:
161 filename
= os
.path
.basename(perlasm
['input'])
162 output
= perlasm
['output']
163 if not output
.startswith('src'):
164 raise ValueError('output missing src: %s' % output
)
165 output
= os
.path
.join(outDir
, output
[4:])
166 output
= output
.replace('${ASM_EXT}', asm_ext
)
168 if arch
== ArchForAsmFilename(filename
):
169 PerlAsm(output
, perlasm
['input'], perlasm_style
,
170 perlasm
['extra_args'] + extra_args
)
171 asmfiles
.setdefault(key
, []).append(output
)
173 for (key
, non_perl_asm_files
) in NON_PERL_FILES
.iteritems():
174 asmfiles
.setdefault(key
, []).extend(non_perl_asm_files
)
179 def PrintVariableSection(out
, name
, files
):
180 out
.write(' \'%s\': [\n' % name
)
181 for f
in sorted(files
):
182 out
.write(' \'%s\',\n' % f
)
187 crypto_c_files
= FindCFiles(os
.path
.join('src', 'crypto'), NoTests
)
188 ssl_c_files
= FindCFiles(os
.path
.join('src', 'ssl'), NoTests
)
190 with
open('boringssl.gypi', 'w+') as gypi
:
191 gypi
.write(FILE_HEADER
+ '{\n \'variables\': {\n')
193 PrintVariableSection(
194 gypi
, 'boringssl_lib_sources', crypto_c_files
+ ssl_c_files
)
196 perlasms
= ReadPerlAsmOperations()
198 for ((osname
, arch
), asm_files
) in sorted(
199 WriteAsmFiles(perlasms
).iteritems()):
200 PrintVariableSection(gypi
, 'boringssl_%s_%s_sources' %
201 (osname
, arch
), asm_files
)
203 gypi
.write(' }\n}\n')
205 test_c_files
= FindCFiles(os
.path
.join('src', 'crypto'), OnlyTests
)
206 test_c_files
+= FindCFiles(os
.path
.join('src', 'ssl'), OnlyTests
)
208 with
open('boringssl_tests.gypi', 'w+') as test_gypi
:
209 test_gypi
.write(FILE_HEADER
+ '{\n \'targets\': [\n')
212 for test
in sorted(test_c_files
):
213 test_name
= 'boringssl_%s' % os
.path
.splitext(os
.path
.basename(test
))[0]
214 test_gypi
.write(""" {
216 'type': 'executable',
218 'boringssl.gyp:boringssl',
223 # TODO(davidben): Fix size_t truncations in BoringSSL.
224 # https://crbug.com/429039
225 'msvs_disabled_warnings': [ 4267, ],
226 },\n""" % (test_name
, test
))
227 test_names
.append(test_name
)
231 test_gypi
.write(""" ],
233 'boringssl_test_targets': [\n""")
235 for test
in test_names
:
236 test_gypi
.write(""" '%s',\n""" % test
)
238 test_gypi
.write(' ],\n }\n}\n')
243 if __name__
== '__main__':