• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2015, Google Inc.
2#
3# Permission to use, copy, modify, and/or distribute this software for any
4# purpose with or without fee is hereby granted, provided that the above
5# copyright notice and this permission notice appear in all copies.
6#
7# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15"""Enumerates source files for consumption by various build systems."""
16
17import optparse
18import os
19import subprocess
20import sys
21import json
22
23
24# OS_ARCH_COMBOS maps from OS and platform to the OpenSSL assembly "style" for
25# that platform and the extension used by asm files.
26OS_ARCH_COMBOS = [
27    ('ios', 'arm', 'ios32', [], 'S'),
28    ('ios', 'aarch64', 'ios64', [], 'S'),
29    ('linux', 'arm', 'linux32', [], 'S'),
30    ('linux', 'aarch64', 'linux64', [], 'S'),
31    ('linux', 'ppc64le', 'linux64le', [], 'S'),
32    ('linux', 'x86', 'elf', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'),
33    ('linux', 'x86_64', 'elf', [], 'S'),
34    ('mac', 'x86', 'macosx', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'),
35    ('mac', 'x86_64', 'macosx', [], 'S'),
36    ('win', 'x86', 'win32n', ['-DOPENSSL_IA32_SSE2'], 'asm'),
37    ('win', 'x86_64', 'nasm', [], 'asm'),
38]
39
40# NON_PERL_FILES enumerates assembly files that are not processed by the
41# perlasm system.
42NON_PERL_FILES = {
43    ('linux', 'arm'): [
44        'src/crypto/curve25519/asm/x25519-asm-arm.S',
45        'src/crypto/poly1305/poly1305_arm_asm.S',
46    ],
47    ('linux', 'x86_64'): [
48        'src/crypto/hrss/asm/poly_rq_mul.S',
49    ],
50}
51
52PREFIX = None
53EMBED_TEST_DATA = True
54
55
56def PathOf(x):
57  return x if not PREFIX else os.path.join(PREFIX, x)
58
59
60class Android(object):
61
62  def __init__(self):
63    self.header = \
64"""# Copyright (C) 2015 The Android Open Source Project
65#
66# Licensed under the Apache License, Version 2.0 (the "License");
67# you may not use this file except in compliance with the License.
68# You may obtain a copy of the License at
69#
70#      http://www.apache.org/licenses/LICENSE-2.0
71#
72# Unless required by applicable law or agreed to in writing, software
73# distributed under the License is distributed on an "AS IS" BASIS,
74# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75# See the License for the specific language governing permissions and
76# limitations under the License.
77
78# This file is created by generate_build_files.py. Do not edit manually.
79"""
80
81  def PrintVariableSection(self, out, name, files):
82    out.write('%s := \\\n' % name)
83    for f in sorted(files):
84      out.write('  %s\\\n' % f)
85    out.write('\n')
86
87  def WriteFiles(self, files, asm_outputs):
88    # New Android.bp format
89    with open('sources.bp', 'w+') as blueprint:
90      blueprint.write(self.header.replace('#', '//'))
91
92      #  Separate out BCM files to allow different compilation rules (specific to Android FIPS)
93      bcm_c_files = files['bcm_crypto']
94      non_bcm_c_files = [file for file in files['crypto'] if file not in bcm_c_files]
95      non_bcm_asm = self.FilterBcmAsm(asm_outputs, False)
96      bcm_asm = self.FilterBcmAsm(asm_outputs, True)
97
98      self.PrintDefaults(blueprint, 'libcrypto_sources', non_bcm_c_files, non_bcm_asm)
99      self.PrintDefaults(blueprint, 'libcrypto_bcm_sources', bcm_c_files, bcm_asm)
100      self.PrintDefaults(blueprint, 'libssl_sources', files['ssl'])
101      self.PrintDefaults(blueprint, 'bssl_sources', files['tool'])
102      self.PrintDefaults(blueprint, 'boringssl_test_support_sources', files['test_support'])
103      self.PrintDefaults(blueprint, 'boringssl_crypto_test_sources', files['crypto_test'])
104      self.PrintDefaults(blueprint, 'boringssl_ssl_test_sources', files['ssl_test'])
105
106    # Legacy Android.mk format, only used by Trusty in new branches
107    with open('sources.mk', 'w+') as makefile:
108      makefile.write(self.header)
109      makefile.write('\n')
110      self.PrintVariableSection(makefile, 'crypto_sources', files['crypto'])
111
112      for ((osname, arch), asm_files) in asm_outputs:
113        if osname != 'linux':
114          continue
115        self.PrintVariableSection(
116            makefile, '%s_%s_sources' % (osname, arch), asm_files)
117
118  def PrintDefaults(self, blueprint, name, files, asm_outputs={}):
119    """Print a cc_defaults section from a list of C files and optionally assembly outputs"""
120    blueprint.write('\n')
121    blueprint.write('cc_defaults {\n')
122    blueprint.write('    name: "%s",\n' % name)
123    blueprint.write('    srcs: [\n')
124    for f in sorted(files):
125      blueprint.write('        "%s",\n' % f)
126    blueprint.write('    ],\n')
127
128    if asm_outputs:
129      blueprint.write('    target: {\n')
130      for ((osname, arch), asm_files) in asm_outputs:
131        if osname != 'linux' or arch == 'ppc64le':
132          continue
133        if arch == 'aarch64':
134          arch = 'arm64'
135
136        blueprint.write('        linux_%s: {\n' % arch)
137        blueprint.write('            srcs: [\n')
138        for f in sorted(asm_files):
139          blueprint.write('                "%s",\n' % f)
140        blueprint.write('            ],\n')
141        blueprint.write('        },\n')
142      blueprint.write('    },\n')
143
144    blueprint.write('}\n')
145
146  def FilterBcmAsm(self, asm, want_bcm):
147    """Filter a list of assembly outputs based on whether they belong in BCM
148
149    Args:
150      asm: Assembly file lists to filter
151      want_bcm: If true then include BCM files, otherwise do not
152
153    Returns:
154      A copy of |asm| with files filtered according to |want_bcm|
155    """
156    return [(archinfo, filter(lambda p: ("/crypto/fipsmodule/" in p) == want_bcm, files))
157            for (archinfo, files) in asm]
158
159
160class AndroidCMake(object):
161
162  def __init__(self):
163    self.header = \
164"""# Copyright (C) 2019 The Android Open Source Project
165#
166# Licensed under the Apache License, Version 2.0 (the "License");
167# you may not use this file except in compliance with the License.
168# You may obtain a copy of the License at
169#
170#      http://www.apache.org/licenses/LICENSE-2.0
171#
172# Unless required by applicable law or agreed to in writing, software
173# distributed under the License is distributed on an "AS IS" BASIS,
174# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
175# See the License for the specific language governing permissions and
176# limitations under the License.
177
178# This file is created by generate_build_files.py. Do not edit manually.
179# To specify a custom path prefix, set BORINGSSL_ROOT before including this
180# file, or use list(TRANSFORM ... PREPEND) from CMake 3.12.
181
182"""
183
184  def PrintVariableSection(self, out, name, files):
185    out.write('set(%s\n' % name)
186    for f in sorted(files):
187      # Ideally adding the prefix would be the caller's job, but
188      # list(TRANSFORM ... PREPEND) is only available starting CMake 3.12. When
189      # sources.cmake is the source of truth, we can ask Android to either write
190      # a CMake function or update to 3.12.
191      out.write('  ${BORINGSSL_ROOT}%s\n' % f)
192    out.write(')\n')
193
194  def WriteFiles(self, files, asm_outputs):
195    # The Android emulator uses a custom CMake buildsystem.
196    #
197    # TODO(davidben): Move our various source lists into sources.cmake and have
198    # Android consume that directly.
199    with open('android-sources.cmake', 'w+') as out:
200      out.write(self.header)
201
202      self.PrintVariableSection(out, 'crypto_sources', files['crypto'])
203      self.PrintVariableSection(out, 'ssl_sources', files['ssl'])
204      self.PrintVariableSection(out, 'tool_sources', files['tool'])
205      self.PrintVariableSection(out, 'test_support_sources',
206                                files['test_support'])
207      self.PrintVariableSection(out, 'crypto_test_sources',
208                                files['crypto_test'])
209      self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test'])
210
211      for ((osname, arch), asm_files) in asm_outputs:
212        self.PrintVariableSection(
213            out, 'crypto_sources_%s_%s' % (osname, arch), asm_files)
214
215
216class Bazel(object):
217  """Bazel outputs files suitable for including in Bazel files."""
218
219  def __init__(self):
220    self.firstSection = True
221    self.header = \
222"""# This file is created by generate_build_files.py. Do not edit manually.
223
224"""
225
226  def PrintVariableSection(self, out, name, files):
227    if not self.firstSection:
228      out.write('\n')
229    self.firstSection = False
230
231    out.write('%s = [\n' % name)
232    for f in sorted(files):
233      out.write('    "%s",\n' % PathOf(f))
234    out.write(']\n')
235
236  def WriteFiles(self, files, asm_outputs):
237    with open('BUILD.generated.bzl', 'w+') as out:
238      out.write(self.header)
239
240      self.PrintVariableSection(out, 'ssl_headers', files['ssl_headers'])
241      self.PrintVariableSection(out, 'fips_fragments', files['fips_fragments'])
242      self.PrintVariableSection(
243          out, 'ssl_internal_headers', files['ssl_internal_headers'])
244      self.PrintVariableSection(out, 'ssl_sources', files['ssl'])
245      self.PrintVariableSection(out, 'crypto_headers', files['crypto_headers'])
246      self.PrintVariableSection(
247          out, 'crypto_internal_headers', files['crypto_internal_headers'])
248      self.PrintVariableSection(out, 'crypto_sources', files['crypto'])
249      self.PrintVariableSection(out, 'tool_sources', files['tool'])
250      self.PrintVariableSection(out, 'tool_headers', files['tool_headers'])
251
252      for ((osname, arch), asm_files) in asm_outputs:
253        self.PrintVariableSection(
254            out, 'crypto_sources_%s_%s' % (osname, arch), asm_files)
255
256    with open('BUILD.generated_tests.bzl', 'w+') as out:
257      out.write(self.header)
258
259      out.write('test_support_sources = [\n')
260      for filename in sorted(files['test_support'] +
261                             files['test_support_headers'] +
262                             files['crypto_internal_headers'] +
263                             files['ssl_internal_headers']):
264        if os.path.basename(filename) == 'malloc.cc':
265          continue
266        out.write('    "%s",\n' % PathOf(filename))
267
268      out.write(']\n')
269
270      self.PrintVariableSection(out, 'crypto_test_sources',
271                                files['crypto_test'])
272      self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test'])
273      self.PrintVariableSection(out, 'crypto_test_data',
274                                files['crypto_test_data'])
275      self.PrintVariableSection(out, 'urandom_test_sources',
276                                files['urandom_test'])
277
278
279class Eureka(object):
280
281  def __init__(self):
282    self.header = \
283"""# Copyright (C) 2017 The Android Open Source Project
284#
285# Licensed under the Apache License, Version 2.0 (the "License");
286# you may not use this file except in compliance with the License.
287# You may obtain a copy of the License at
288#
289#      http://www.apache.org/licenses/LICENSE-2.0
290#
291# Unless required by applicable law or agreed to in writing, software
292# distributed under the License is distributed on an "AS IS" BASIS,
293# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
294# See the License for the specific language governing permissions and
295# limitations under the License.
296
297# This file is created by generate_build_files.py. Do not edit manually.
298
299"""
300
301  def PrintVariableSection(self, out, name, files):
302    out.write('%s := \\\n' % name)
303    for f in sorted(files):
304      out.write('  %s\\\n' % f)
305    out.write('\n')
306
307  def WriteFiles(self, files, asm_outputs):
308    # Legacy Android.mk format
309    with open('eureka.mk', 'w+') as makefile:
310      makefile.write(self.header)
311
312      self.PrintVariableSection(makefile, 'crypto_sources', files['crypto'])
313      self.PrintVariableSection(makefile, 'ssl_sources', files['ssl'])
314      self.PrintVariableSection(makefile, 'tool_sources', files['tool'])
315
316      for ((osname, arch), asm_files) in asm_outputs:
317        if osname != 'linux':
318          continue
319        self.PrintVariableSection(
320            makefile, '%s_%s_sources' % (osname, arch), asm_files)
321
322
323class GN(object):
324
325  def __init__(self):
326    self.firstSection = True
327    self.header = \
328"""# Copyright (c) 2016 The Chromium Authors. All rights reserved.
329# Use of this source code is governed by a BSD-style license that can be
330# found in the LICENSE file.
331
332# This file is created by generate_build_files.py. Do not edit manually.
333
334"""
335
336  def PrintVariableSection(self, out, name, files):
337    if not self.firstSection:
338      out.write('\n')
339    self.firstSection = False
340
341    out.write('%s = [\n' % name)
342    for f in sorted(files):
343      out.write('  "%s",\n' % f)
344    out.write(']\n')
345
346  def WriteFiles(self, files, asm_outputs):
347    with open('BUILD.generated.gni', 'w+') as out:
348      out.write(self.header)
349
350      self.PrintVariableSection(out, 'crypto_sources',
351                                files['crypto'] +
352                                files['crypto_internal_headers'])
353      self.PrintVariableSection(out, 'crypto_headers',
354                                files['crypto_headers'])
355      self.PrintVariableSection(out, 'ssl_sources',
356                                files['ssl'] + files['ssl_internal_headers'])
357      self.PrintVariableSection(out, 'ssl_headers', files['ssl_headers'])
358
359      for ((osname, arch), asm_files) in asm_outputs:
360        self.PrintVariableSection(
361            out, 'crypto_sources_%s_%s' % (osname, arch), asm_files)
362
363      fuzzers = [os.path.splitext(os.path.basename(fuzzer))[0]
364                 for fuzzer in files['fuzz']]
365      self.PrintVariableSection(out, 'fuzzers', fuzzers)
366
367    with open('BUILD.generated_tests.gni', 'w+') as out:
368      self.firstSection = True
369      out.write(self.header)
370
371      self.PrintVariableSection(out, 'test_support_sources',
372                                files['test_support'] +
373                                files['test_support_headers'])
374      self.PrintVariableSection(out, 'crypto_test_sources',
375                                files['crypto_test'])
376      self.PrintVariableSection(out, 'crypto_test_data',
377                                files['crypto_test_data'])
378      self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test'])
379
380
381class GYP(object):
382
383  def __init__(self):
384    self.header = \
385"""# Copyright (c) 2016 The Chromium Authors. All rights reserved.
386# Use of this source code is governed by a BSD-style license that can be
387# found in the LICENSE file.
388
389# This file is created by generate_build_files.py. Do not edit manually.
390
391"""
392
393  def PrintVariableSection(self, out, name, files):
394    out.write('    \'%s\': [\n' % name)
395    for f in sorted(files):
396      out.write('      \'%s\',\n' % f)
397    out.write('    ],\n')
398
399  def WriteFiles(self, files, asm_outputs):
400    with open('boringssl.gypi', 'w+') as gypi:
401      gypi.write(self.header + '{\n  \'variables\': {\n')
402
403      self.PrintVariableSection(gypi, 'boringssl_ssl_sources',
404                                files['ssl'] + files['ssl_headers'] +
405                                files['ssl_internal_headers'])
406      self.PrintVariableSection(gypi, 'boringssl_crypto_sources',
407                                files['crypto'] + files['crypto_headers'] +
408                                files['crypto_internal_headers'])
409
410      for ((osname, arch), asm_files) in asm_outputs:
411        self.PrintVariableSection(gypi, 'boringssl_%s_%s_sources' %
412                                  (osname, arch), asm_files)
413
414      gypi.write('  }\n}\n')
415
416
417def FindCMakeFiles(directory):
418  """Returns list of all CMakeLists.txt files recursively in directory."""
419  cmakefiles = []
420
421  for (path, _, filenames) in os.walk(directory):
422    for filename in filenames:
423      if filename == 'CMakeLists.txt':
424        cmakefiles.append(os.path.join(path, filename))
425
426  return cmakefiles
427
428def OnlyFIPSFragments(path, dent, is_dir):
429  return is_dir or (path.startswith(
430      os.path.join('src', 'crypto', 'fipsmodule', '')) and
431      NoTests(path, dent, is_dir))
432
433def NoTestsNorFIPSFragments(path, dent, is_dir):
434  return (NoTests(path, dent, is_dir) and
435      (is_dir or not OnlyFIPSFragments(path, dent, is_dir)))
436
437def NoTests(path, dent, is_dir):
438  """Filter function that can be passed to FindCFiles in order to remove test
439  sources."""
440  if is_dir:
441    return dent != 'test'
442  return 'test.' not in dent
443
444
445def OnlyTests(path, dent, is_dir):
446  """Filter function that can be passed to FindCFiles in order to remove
447  non-test sources."""
448  if is_dir:
449    return dent != 'test'
450  return '_test.' in dent
451
452
453def AllFiles(path, dent, is_dir):
454  """Filter function that can be passed to FindCFiles in order to include all
455  sources."""
456  return True
457
458
459def NoTestRunnerFiles(path, dent, is_dir):
460  """Filter function that can be passed to FindCFiles or FindHeaderFiles in
461  order to exclude test runner files."""
462  # NOTE(martinkr): This prevents .h/.cc files in src/ssl/test/runner, which
463  # are in their own subpackage, from being included in boringssl/BUILD files.
464  return not is_dir or dent != 'runner'
465
466
467def NotGTestSupport(path, dent, is_dir):
468  return 'gtest' not in dent and 'abi_test' not in dent
469
470
471def SSLHeaderFiles(path, dent, is_dir):
472  return dent in ['ssl.h', 'tls1.h', 'ssl23.h', 'ssl3.h', 'dtls1.h', 'srtp.h']
473
474
475def FindCFiles(directory, filter_func):
476  """Recurses through directory and returns a list of paths to all the C source
477  files that pass filter_func."""
478  cfiles = []
479
480  for (path, dirnames, filenames) in os.walk(directory):
481    for filename in filenames:
482      if not filename.endswith('.c') and not filename.endswith('.cc'):
483        continue
484      if not filter_func(path, filename, False):
485        continue
486      cfiles.append(os.path.join(path, filename))
487
488    for (i, dirname) in enumerate(dirnames):
489      if not filter_func(path, dirname, True):
490        del dirnames[i]
491
492  return cfiles
493
494
495def FindHeaderFiles(directory, filter_func):
496  """Recurses through directory and returns a list of paths to all the header files that pass filter_func."""
497  hfiles = []
498
499  for (path, dirnames, filenames) in os.walk(directory):
500    for filename in filenames:
501      if not filename.endswith('.h'):
502        continue
503      if not filter_func(path, filename, False):
504        continue
505      hfiles.append(os.path.join(path, filename))
506
507      for (i, dirname) in enumerate(dirnames):
508        if not filter_func(path, dirname, True):
509          del dirnames[i]
510
511  return hfiles
512
513
514def ExtractPerlAsmFromCMakeFile(cmakefile):
515  """Parses the contents of the CMakeLists.txt file passed as an argument and
516  returns a list of all the perlasm() directives found in the file."""
517  perlasms = []
518  with open(cmakefile) as f:
519    for line in f:
520      line = line.strip()
521      if not line.startswith('perlasm('):
522        continue
523      if not line.endswith(')'):
524        raise ValueError('Bad perlasm line in %s' % cmakefile)
525      # Remove "perlasm(" from start and ")" from end
526      params = line[8:-1].split()
527      if len(params) < 2:
528        raise ValueError('Bad perlasm line in %s' % cmakefile)
529      perlasms.append({
530          'extra_args': params[2:],
531          'input': os.path.join(os.path.dirname(cmakefile), params[1]),
532          'output': os.path.join(os.path.dirname(cmakefile), params[0]),
533      })
534
535  return perlasms
536
537
538def ReadPerlAsmOperations():
539  """Returns a list of all perlasm() directives found in CMake config files in
540  src/."""
541  perlasms = []
542  cmakefiles = FindCMakeFiles('src')
543
544  for cmakefile in cmakefiles:
545    perlasms.extend(ExtractPerlAsmFromCMakeFile(cmakefile))
546
547  return perlasms
548
549
550def PerlAsm(output_filename, input_filename, perlasm_style, extra_args):
551  """Runs the a perlasm script and puts the output into output_filename."""
552  base_dir = os.path.dirname(output_filename)
553  if not os.path.isdir(base_dir):
554    os.makedirs(base_dir)
555  subprocess.check_call(
556      ['perl', input_filename, perlasm_style] + extra_args + [output_filename])
557
558
559def ArchForAsmFilename(filename):
560  """Returns the architectures that a given asm file should be compiled for
561  based on substrings in the filename."""
562
563  if 'x86_64' in filename or 'avx2' in filename:
564    return ['x86_64']
565  elif ('x86' in filename and 'x86_64' not in filename) or '586' in filename:
566    return ['x86']
567  elif 'armx' in filename:
568    return ['arm', 'aarch64']
569  elif 'armv8' in filename:
570    return ['aarch64']
571  elif 'arm' in filename:
572    return ['arm']
573  elif 'ppc' in filename:
574    return ['ppc64le']
575  else:
576    raise ValueError('Unknown arch for asm filename: ' + filename)
577
578
579def WriteAsmFiles(perlasms):
580  """Generates asm files from perlasm directives for each supported OS x
581  platform combination."""
582  asmfiles = {}
583
584  for osarch in OS_ARCH_COMBOS:
585    (osname, arch, perlasm_style, extra_args, asm_ext) = osarch
586    key = (osname, arch)
587    outDir = '%s-%s' % key
588
589    for perlasm in perlasms:
590      filename = os.path.basename(perlasm['input'])
591      output = perlasm['output']
592      if not output.startswith('src'):
593        raise ValueError('output missing src: %s' % output)
594      output = os.path.join(outDir, output[4:])
595      if output.endswith('-armx.${ASM_EXT}'):
596        output = output.replace('-armx',
597                                '-armx64' if arch == 'aarch64' else '-armx32')
598      output = output.replace('${ASM_EXT}', asm_ext)
599
600      if arch in ArchForAsmFilename(filename):
601        PerlAsm(output, perlasm['input'], perlasm_style,
602                perlasm['extra_args'] + extra_args)
603        asmfiles.setdefault(key, []).append(output)
604
605  for (key, non_perl_asm_files) in NON_PERL_FILES.iteritems():
606    asmfiles.setdefault(key, []).extend(non_perl_asm_files)
607
608  return asmfiles
609
610
611def ExtractVariablesFromCMakeFile(cmakefile):
612  """Parses the contents of the CMakeLists.txt file passed as an argument and
613  returns a dictionary of exported source lists."""
614  variables = {}
615  in_set_command = False
616  set_command = []
617  with open(cmakefile) as f:
618    for line in f:
619      if '#' in line:
620        line = line[:line.index('#')]
621      line = line.strip()
622
623      if not in_set_command:
624        if line.startswith('set('):
625          in_set_command = True
626          set_command = []
627      elif line == ')':
628        in_set_command = False
629        if not set_command:
630          raise ValueError('Empty set command')
631        variables[set_command[0]] = set_command[1:]
632      else:
633        set_command.extend([c for c in line.split(' ') if c])
634
635  if in_set_command:
636    raise ValueError('Unfinished set command')
637  return variables
638
639
640def main(platforms):
641  cmake = ExtractVariablesFromCMakeFile(os.path.join('src', 'sources.cmake'))
642  crypto_c_files = (FindCFiles(os.path.join('src', 'crypto'), NoTestsNorFIPSFragments) +
643                    FindCFiles(os.path.join('src', 'third_party', 'fiat'), NoTestsNorFIPSFragments))
644  fips_fragments = FindCFiles(os.path.join('src', 'crypto', 'fipsmodule'), OnlyFIPSFragments)
645  ssl_source_files = FindCFiles(os.path.join('src', 'ssl'), NoTests)
646  tool_c_files = FindCFiles(os.path.join('src', 'tool'), NoTests)
647  tool_h_files = FindHeaderFiles(os.path.join('src', 'tool'), AllFiles)
648
649  # third_party/fiat/p256.c lives in third_party/fiat, but it is a FIPS
650  # fragment, not a normal source file.
651  p256 = os.path.join('src', 'third_party', 'fiat', 'p256.c')
652  fips_fragments.append(p256)
653  crypto_c_files.remove(p256)
654
655  # BCM shared library C files
656  bcm_crypto_c_files = [
657      os.path.join('src', 'crypto', 'fipsmodule', 'bcm.c')
658  ]
659
660  # Generate err_data.c
661  with open('err_data.c', 'w+') as err_data:
662    subprocess.check_call(['go', 'run', 'err_data_generate.go'],
663                          cwd=os.path.join('src', 'crypto', 'err'),
664                          stdout=err_data)
665  crypto_c_files.append('err_data.c')
666
667  test_support_c_files = FindCFiles(os.path.join('src', 'crypto', 'test'),
668                                    NotGTestSupport)
669  test_support_h_files = (
670      FindHeaderFiles(os.path.join('src', 'crypto', 'test'), AllFiles) +
671      FindHeaderFiles(os.path.join('src', 'ssl', 'test'), NoTestRunnerFiles))
672
673  crypto_test_files = []
674  if EMBED_TEST_DATA:
675    # Generate crypto_test_data.cc
676    with open('crypto_test_data.cc', 'w+') as out:
677      subprocess.check_call(
678          ['go', 'run', 'util/embed_test_data.go'] + cmake['CRYPTO_TEST_DATA'],
679          cwd='src',
680          stdout=out)
681    crypto_test_files += ['crypto_test_data.cc']
682
683  crypto_test_files += FindCFiles(os.path.join('src', 'crypto'), OnlyTests)
684  crypto_test_files += [
685      'src/crypto/test/abi_test.cc',
686      'src/crypto/test/file_test_gtest.cc',
687      'src/crypto/test/gtest_main.cc',
688  ]
689  # urandom_test.cc is in a separate binary so that it can be test PRNG
690  # initialisation.
691  crypto_test_files = [
692      file for file in crypto_test_files
693      if not file.endswith('/urandom_test.cc')
694  ]
695
696  ssl_test_files = FindCFiles(os.path.join('src', 'ssl'), OnlyTests)
697  ssl_test_files += [
698      'src/crypto/test/abi_test.cc',
699      'src/crypto/test/gtest_main.cc',
700  ]
701
702  urandom_test_files = [
703      'src/crypto/fipsmodule/rand/urandom_test.cc',
704  ]
705
706  fuzz_c_files = FindCFiles(os.path.join('src', 'fuzz'), NoTests)
707
708  ssl_h_files = (
709      FindHeaderFiles(
710          os.path.join('src', 'include', 'openssl'),
711          SSLHeaderFiles))
712
713  def NotSSLHeaderFiles(path, filename, is_dir):
714    return not SSLHeaderFiles(path, filename, is_dir)
715  crypto_h_files = (
716      FindHeaderFiles(
717          os.path.join('src', 'include', 'openssl'),
718          NotSSLHeaderFiles))
719
720  ssl_internal_h_files = FindHeaderFiles(os.path.join('src', 'ssl'), NoTests)
721  crypto_internal_h_files = (
722      FindHeaderFiles(os.path.join('src', 'crypto'), NoTests) +
723      FindHeaderFiles(os.path.join('src', 'third_party', 'fiat'), NoTests))
724
725  files = {
726      'bcm_crypto': bcm_crypto_c_files,
727      'crypto': crypto_c_files,
728      'crypto_headers': crypto_h_files,
729      'crypto_internal_headers': crypto_internal_h_files,
730      'crypto_test': sorted(crypto_test_files),
731      'crypto_test_data': sorted('src/' + x for x in cmake['CRYPTO_TEST_DATA']),
732      'fips_fragments': fips_fragments,
733      'fuzz': fuzz_c_files,
734      'ssl': ssl_source_files,
735      'ssl_headers': ssl_h_files,
736      'ssl_internal_headers': ssl_internal_h_files,
737      'ssl_test': sorted(ssl_test_files),
738      'tool': tool_c_files,
739      'tool_headers': tool_h_files,
740      'test_support': test_support_c_files,
741      'test_support_headers': test_support_h_files,
742      'urandom_test': sorted(urandom_test_files),
743  }
744
745  asm_outputs = sorted(WriteAsmFiles(ReadPerlAsmOperations()).iteritems())
746
747  for platform in platforms:
748    platform.WriteFiles(files, asm_outputs)
749
750  return 0
751
752
753if __name__ == '__main__':
754  parser = optparse.OptionParser(usage='Usage: %prog [--prefix=<path>]'
755      ' [android|android-cmake|bazel|eureka|gn|gyp]')
756  parser.add_option('--prefix', dest='prefix',
757      help='For Bazel, prepend argument to all source files')
758  parser.add_option(
759      '--embed_test_data', type='choice', dest='embed_test_data',
760      action='store', default="true", choices=["true", "false"],
761      help='For Bazel or GN, don\'t embed data files in crypto_test_data.cc')
762  options, args = parser.parse_args(sys.argv[1:])
763  PREFIX = options.prefix
764  EMBED_TEST_DATA = (options.embed_test_data == "true")
765
766  if not args:
767    parser.print_help()
768    sys.exit(1)
769
770  platforms = []
771  for s in args:
772    if s == 'android':
773      platforms.append(Android())
774    elif s == 'android-cmake':
775      platforms.append(AndroidCMake())
776    elif s == 'bazel':
777      platforms.append(Bazel())
778    elif s == 'eureka':
779      platforms.append(Eureka())
780    elif s == 'gn':
781      platforms.append(GN())
782    elif s == 'gyp':
783      platforms.append(GYP())
784    else:
785      parser.print_help()
786      sys.exit(1)
787
788  sys.exit(main(platforms))
789