generate_build_files.py
Go to the documentation of this file.
1 # coding=utf8
2 
3 # Copyright (c) 2015, Google Inc.
4 #
5 # Permission to use, copy, modify, and/or distribute this software for any
6 # purpose with or without fee is hereby granted, provided that the above
7 # copyright notice and this permission notice appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14 # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 
17 """Enumerates source files for consumption by various build systems."""
18 
19 import optparse
20 import os
21 import subprocess
22 import sys
23 import json
24 
25 
26 # OS_ARCH_COMBOS maps from OS and platform to the OpenSSL assembly "style" for
27 # that platform and the extension used by asm files.
28 OS_ARCH_COMBOS = [
29  ('ios', 'arm', 'ios32', [], 'S'),
30  ('ios', 'aarch64', 'ios64', [], 'S'),
31  ('linux', 'arm', 'linux32', [], 'S'),
32  ('linux', 'aarch64', 'linux64', [], 'S'),
33  ('linux', 'ppc64le', 'linux64le', [], 'S'),
34  ('linux', 'x86', 'elf', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'),
35  ('linux', 'x86_64', 'elf', [], 'S'),
36  ('mac', 'x86', 'macosx', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'),
37  ('mac', 'x86_64', 'macosx', [], 'S'),
38  ('win', 'x86', 'win32n', ['-DOPENSSL_IA32_SSE2'], 'asm'),
39  ('win', 'x86_64', 'nasm', [], 'asm'),
40  ('win', 'aarch64', 'win64', [], 'S'),
41 ]
42 
43 # NON_PERL_FILES enumerates assembly files that are not processed by the
44 # perlasm system.
45 NON_PERL_FILES = {
46  ('linux', 'arm'): [
47  'src/crypto/curve25519/asm/x25519-asm-arm.S',
48  'src/crypto/poly1305/poly1305_arm_asm.S',
49  ],
50  ('linux', 'x86_64'): [
51  'src/crypto/hrss/asm/poly_rq_mul.S',
52  ],
53 }
54 
55 PREFIX = None
56 EMBED_TEST_DATA = True
57 
58 
59 def PathOf(x):
60  return x if not PREFIX else os.path.join(PREFIX, x)
61 
62 
63 class Android(object):
64 
65  def __init__(self):
66  self.header = \
67 """# Copyright (C) 2015 The Android Open Source Project
68 #
69 # Licensed under the Apache License, Version 2.0 (the "License");
70 # you may not use this file except in compliance with the License.
71 # You may obtain a copy of the License at
72 #
73 # http://www.apache.org/licenses/LICENSE-2.0
74 #
75 # Unless required by applicable law or agreed to in writing, software
76 # distributed under the License is distributed on an "AS IS" BASIS,
77 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78 # See the License for the specific language governing permissions and
79 # limitations under the License.
80 
81 # This file is created by generate_build_files.py. Do not edit manually.
82 """
83 
84  def PrintVariableSection(self, out, name, files):
85  out.write('%s := \\\n' % name)
86  for f in sorted(files):
87  out.write(' %s\\\n' % f)
88  out.write('\n')
89 
90  def WriteFiles(self, files, asm_outputs):
91  # New Android.bp format
92  with open('sources.bp', 'w+') as blueprint:
93  blueprint.write(self.header.replace('#', '//'))
94 
95  # Separate out BCM files to allow different compilation rules (specific to Android FIPS)
96  bcm_c_files = files['bcm_crypto']
97  non_bcm_c_files = [file for file in files['crypto'] if file not in bcm_c_files]
98  non_bcm_asm = self.FilterBcmAsm(asm_outputs, False)
99  bcm_asm = self.FilterBcmAsm(asm_outputs, True)
100 
101  self.PrintDefaults(blueprint, 'libcrypto_sources', non_bcm_c_files, non_bcm_asm)
102  self.PrintDefaults(blueprint, 'libcrypto_bcm_sources', bcm_c_files, bcm_asm)
103  self.PrintDefaults(blueprint, 'libssl_sources', files['ssl'])
104  self.PrintDefaults(blueprint, 'bssl_sources', files['tool'])
105  self.PrintDefaults(blueprint, 'boringssl_test_support_sources', files['test_support'])
106  self.PrintDefaults(blueprint, 'boringssl_crypto_test_sources', files['crypto_test'])
107  self.PrintDefaults(blueprint, 'boringssl_ssl_test_sources', files['ssl_test'])
108 
109  # Legacy Android.mk format, only used by Trusty in new branches
110  with open('sources.mk', 'w+') as makefile:
111  makefile.write(self.header)
112  makefile.write('\n')
113  self.PrintVariableSection(makefile, 'crypto_sources', files['crypto'])
114 
115  for ((osname, arch), asm_files) in asm_outputs:
116  if osname != 'linux':
117  continue
119  makefile, '%s_%s_sources' % (osname, arch), asm_files)
120 
121  def PrintDefaults(self, blueprint, name, files, asm_outputs={}):
122  """Print a cc_defaults section from a list of C files and optionally assembly outputs"""
123  blueprint.write('\n')
124  blueprint.write('cc_defaults {\n')
125  blueprint.write(' name: "%s",\n' % name)
126  blueprint.write(' srcs: [\n')
127  for f in sorted(files):
128  blueprint.write(' "%s",\n' % f)
129  blueprint.write(' ],\n')
130 
131  if asm_outputs:
132  blueprint.write(' target: {\n')
133  for ((osname, arch), asm_files) in asm_outputs:
134  if osname != 'linux' or arch == 'ppc64le':
135  continue
136  if arch == 'aarch64':
137  arch = 'arm64'
138 
139  blueprint.write(' linux_%s: {\n' % arch)
140  blueprint.write(' srcs: [\n')
141  for f in sorted(asm_files):
142  blueprint.write(' "%s",\n' % f)
143  blueprint.write(' ],\n')
144  blueprint.write(' },\n')
145  blueprint.write(' },\n')
146 
147  blueprint.write('}\n')
148 
149  def FilterBcmAsm(self, asm, want_bcm):
150  """Filter a list of assembly outputs based on whether they belong in BCM
151 
152  Args:
153  asm: Assembly file lists to filter
154  want_bcm: If true then include BCM files, otherwise do not
155 
156  Returns:
157  A copy of |asm| with files filtered according to |want_bcm|
158  """
159  return [(archinfo, filter(lambda p: ("/crypto/fipsmodule/" in p) == want_bcm, files))
160  for (archinfo, files) in asm]
161 
162 
163 class AndroidCMake(object):
164 
165  def __init__(self):
166  self.header = \
167 """# Copyright (C) 2019 The Android Open Source Project
168 #
169 # Licensed under the Apache License, Version 2.0 (the "License");
170 # you may not use this file except in compliance with the License.
171 # You may obtain a copy of the License at
172 #
173 # http://www.apache.org/licenses/LICENSE-2.0
174 #
175 # Unless required by applicable law or agreed to in writing, software
176 # distributed under the License is distributed on an "AS IS" BASIS,
177 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
178 # See the License for the specific language governing permissions and
179 # limitations under the License.
180 
181 # This file is created by generate_build_files.py. Do not edit manually.
182 # To specify a custom path prefix, set BORINGSSL_ROOT before including this
183 # file, or use list(TRANSFORM ... PREPEND) from CMake 3.12.
184 
185 """
186 
187  def PrintVariableSection(self, out, name, files):
188  out.write('set(%s\n' % name)
189  for f in sorted(files):
190  # Ideally adding the prefix would be the caller's job, but
191  # list(TRANSFORM ... PREPEND) is only available starting CMake 3.12. When
192  # sources.cmake is the source of truth, we can ask Android to either write
193  # a CMake function or update to 3.12.
194  out.write(' ${BORINGSSL_ROOT}%s\n' % f)
195  out.write(')\n')
196 
197  def WriteFiles(self, files, asm_outputs):
198  # The Android emulator uses a custom CMake buildsystem.
199  #
200  # TODO(davidben): Move our various source lists into sources.cmake and have
201  # Android consume that directly.
202  with open('android-sources.cmake', 'w+') as out:
203  out.write(self.header)
204 
205  self.PrintVariableSection(out, 'crypto_sources', files['crypto'])
206  self.PrintVariableSection(out, 'ssl_sources', files['ssl'])
207  self.PrintVariableSection(out, 'tool_sources', files['tool'])
208  self.PrintVariableSection(out, 'test_support_sources',
209  files['test_support'])
210  self.PrintVariableSection(out, 'crypto_test_sources',
211  files['crypto_test'])
212  self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test'])
213 
214  for ((osname, arch), asm_files) in asm_outputs:
216  out, 'crypto_sources_%s_%s' % (osname, arch), asm_files)
217 
218 
219 class Bazel(object):
220  """Bazel outputs files suitable for including in Bazel files."""
221 
222  def __init__(self):
223  self.firstSection = True
224  self.header = \
225 """# This file is created by generate_build_files.py. Do not edit manually.
226 
227 """
228 
229  def PrintVariableSection(self, out, name, files):
230  if not self.firstSection:
231  out.write('\n')
232  self.firstSection = False
233 
234  out.write('%s = [\n' % name)
235  for f in sorted(files):
236  out.write(' "%s",\n' % PathOf(f))
237  out.write(']\n')
238 
239  def WriteFiles(self, files, asm_outputs):
240  with open('BUILD.generated.bzl', 'w+') as out:
241  out.write(self.header)
242 
243  self.PrintVariableSection(out, 'ssl_headers', files['ssl_headers'])
244  self.PrintVariableSection(out, 'fips_fragments', files['fips_fragments'])
246  out, 'ssl_internal_headers', files['ssl_internal_headers'])
247  self.PrintVariableSection(out, 'ssl_sources', files['ssl'])
248  self.PrintVariableSection(out, 'crypto_headers', files['crypto_headers'])
250  out, 'crypto_internal_headers', files['crypto_internal_headers'])
251  self.PrintVariableSection(out, 'crypto_sources', files['crypto'])
252  self.PrintVariableSection(out, 'tool_sources', files['tool'])
253  self.PrintVariableSection(out, 'tool_headers', files['tool_headers'])
254 
255  for ((osname, arch), asm_files) in asm_outputs:
257  out, 'crypto_sources_%s_%s' % (osname, arch), asm_files)
258 
259  with open('BUILD.generated_tests.bzl', 'w+') as out:
260  out.write(self.header)
261 
262  out.write('test_support_sources = [\n')
263  for filename in sorted(files['test_support'] +
264  files['test_support_headers'] +
265  files['crypto_internal_headers'] +
266  files['ssl_internal_headers']):
267  if os.path.basename(filename) == 'malloc.cc':
268  continue
269  out.write(' "%s",\n' % PathOf(filename))
270 
271  out.write(']\n')
272 
273  self.PrintVariableSection(out, 'crypto_test_sources',
274  files['crypto_test'])
275  self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test'])
276  self.PrintVariableSection(out, 'crypto_test_data',
277  files['crypto_test_data'])
278  self.PrintVariableSection(out, 'urandom_test_sources',
279  files['urandom_test'])
280 
281 
282 class Eureka(object):
283 
284  def __init__(self):
285  self.header = \
286 """# Copyright (C) 2017 The Android Open Source Project
287 #
288 # Licensed under the Apache License, Version 2.0 (the "License");
289 # you may not use this file except in compliance with the License.
290 # You may obtain a copy of the License at
291 #
292 # http://www.apache.org/licenses/LICENSE-2.0
293 #
294 # Unless required by applicable law or agreed to in writing, software
295 # distributed under the License is distributed on an "AS IS" BASIS,
296 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
297 # See the License for the specific language governing permissions and
298 # limitations under the License.
299 
300 # This file is created by generate_build_files.py. Do not edit manually.
301 
302 """
303 
304  def PrintVariableSection(self, out, name, files):
305  out.write('%s := \\\n' % name)
306  for f in sorted(files):
307  out.write(' %s\\\n' % f)
308  out.write('\n')
309 
310  def WriteFiles(self, files, asm_outputs):
311  # Legacy Android.mk format
312  with open('eureka.mk', 'w+') as makefile:
313  makefile.write(self.header)
314 
315  self.PrintVariableSection(makefile, 'crypto_sources', files['crypto'])
316  self.PrintVariableSection(makefile, 'ssl_sources', files['ssl'])
317  self.PrintVariableSection(makefile, 'tool_sources', files['tool'])
318 
319  for ((osname, arch), asm_files) in asm_outputs:
320  if osname != 'linux':
321  continue
323  makefile, '%s_%s_sources' % (osname, arch), asm_files)
324 
325 
326 class GN(object):
327 
328  def __init__(self):
329  self.firstSection = True
330  self.header = \
331 """# Copyright (c) 2016 The Chromium Authors. All rights reserved.
332 # Use of this source code is governed by a BSD-style license that can be
333 # found in the LICENSE file.
334 
335 # This file is created by generate_build_files.py. Do not edit manually.
336 
337 """
338 
339  def PrintVariableSection(self, out, name, files):
340  if not self.firstSection:
341  out.write('\n')
342  self.firstSection = False
343 
344  out.write('%s = [\n' % name)
345  for f in sorted(files):
346  out.write(' "%s",\n' % f)
347  out.write(']\n')
348 
349  def WriteFiles(self, files, asm_outputs):
350  with open('BUILD.generated.gni', 'w+') as out:
351  out.write(self.header)
352 
353  self.PrintVariableSection(out, 'crypto_sources',
354  files['crypto'] +
355  files['crypto_internal_headers'])
356  self.PrintVariableSection(out, 'crypto_headers',
357  files['crypto_headers'])
358  self.PrintVariableSection(out, 'ssl_sources',
359  files['ssl'] + files['ssl_internal_headers'])
360  self.PrintVariableSection(out, 'ssl_headers', files['ssl_headers'])
361  self.PrintVariableSection(out, 'tool_sources',
362  files['tool'] + files['tool_headers'])
363 
364  for ((osname, arch), asm_files) in asm_outputs:
366  out, 'crypto_sources_%s_%s' % (osname, arch), asm_files)
367 
368  fuzzers = [os.path.splitext(os.path.basename(fuzzer))[0]
369  for fuzzer in files['fuzz']]
370  self.PrintVariableSection(out, 'fuzzers', fuzzers)
371 
372  with open('BUILD.generated_tests.gni', 'w+') as out:
373  self.firstSection = True
374  out.write(self.header)
375 
376  self.PrintVariableSection(out, 'test_support_sources',
377  files['test_support'] +
378  files['test_support_headers'])
379  self.PrintVariableSection(out, 'crypto_test_sources',
380  files['crypto_test'])
381  self.PrintVariableSection(out, 'crypto_test_data',
382  files['crypto_test_data'])
383  self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test'])
384 
385 
386 class GYP(object):
387 
388  def __init__(self):
389  self.header = \
390 """# Copyright (c) 2016 The Chromium Authors. All rights reserved.
391 # Use of this source code is governed by a BSD-style license that can be
392 # found in the LICENSE file.
393 
394 # This file is created by generate_build_files.py. Do not edit manually.
395 
396 """
397 
398  def PrintVariableSection(self, out, name, files):
399  out.write(' \'%s\': [\n' % name)
400  for f in sorted(files):
401  out.write(' \'%s\',\n' % f)
402  out.write(' ],\n')
403 
404  def WriteFiles(self, files, asm_outputs):
405  with open('boringssl.gypi', 'w+') as gypi:
406  gypi.write(self.header + '{\n \'variables\': {\n')
407 
408  self.PrintVariableSection(gypi, 'boringssl_ssl_sources',
409  files['ssl'] + files['ssl_headers'] +
410  files['ssl_internal_headers'])
411  self.PrintVariableSection(gypi, 'boringssl_crypto_sources',
412  files['crypto'] + files['crypto_headers'] +
413  files['crypto_internal_headers'])
414 
415  for ((osname, arch), asm_files) in asm_outputs:
416  self.PrintVariableSection(gypi, 'boringssl_%s_%s_sources' %
417  (osname, arch), asm_files)
418 
419  gypi.write(' }\n}\n')
420 
421 class CMake(object):
422 
423  def __init__(self):
424  self.header = \
425 R'''# Copyright (c) 2019 The Chromium Authors. All rights reserved.
426 # Use of this source code is governed by a BSD-style license that can be
427 # found in the LICENSE file.
428 
429 # This file is created by generate_build_files.py. Do not edit manually.
430 
431 cmake_minimum_required(VERSION 3.5)
432 
433 project(BoringSSL LANGUAGES C CXX)
434 
435 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
436  set(CLANG 1)
437 endif()
438 
439 if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
440  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fvisibility=hidden -fno-common -fno-exceptions -fno-rtti")
441  if(APPLE)
442  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
443  endif()
444 
445  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fno-common -std=c11")
446 endif()
447 
448 # pthread_rwlock_t requires a feature flag.
449 if(NOT WIN32)
450  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE=700")
451 endif()
452 
453 if(WIN32)
454  add_definitions(-D_HAS_EXCEPTIONS=0)
455  add_definitions(-DWIN32_LEAN_AND_MEAN)
456  add_definitions(-DNOMINMAX)
457  # Allow use of fopen.
458  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
459  # VS 2017 and higher supports STL-only warning suppressions.
460  # A bug in CMake < 3.13.0 may cause the space in this value to
461  # cause issues when building with NASM. In that case, update CMake.
462  add_definitions("-D_STL_EXTRA_DISABLED_WARNINGS=4774 4987")
463 endif()
464 
465 add_definitions(-DBORINGSSL_IMPLEMENTATION)
466 
467 # CMake's iOS support uses Apple's multiple-architecture toolchain. It takes an
468 # architecture list from CMAKE_OSX_ARCHITECTURES, leaves CMAKE_SYSTEM_PROCESSOR
469 # alone, and expects all architecture-specific logic to be conditioned within
470 # the source files rather than the build. This does not work for our assembly
471 # files, so we fix CMAKE_SYSTEM_PROCESSOR and only support single-architecture
472 # builds.
473 if(NOT OPENSSL_NO_ASM AND CMAKE_OSX_ARCHITECTURES)
474  list(LENGTH CMAKE_OSX_ARCHITECTURES NUM_ARCHES)
475  if(NOT NUM_ARCHES EQUAL 1)
476  message(FATAL_ERROR "Universal binaries not supported.")
477  endif()
478  list(GET CMAKE_OSX_ARCHITECTURES 0 CMAKE_SYSTEM_PROCESSOR)
479 endif()
480 
481 if(OPENSSL_NO_ASM)
482  add_definitions(-DOPENSSL_NO_ASM)
483  set(ARCH "generic")
484 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
485  set(ARCH "x86_64")
486 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
487  set(ARCH "x86_64")
488 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64")
489  # cmake reports AMD64 on Windows, but we might be building for 32-bit.
490  if(CMAKE_SIZEOF_VOID_P EQUAL 8)
491  set(ARCH "x86_64")
492  else()
493  set(ARCH "x86")
494  endif()
495 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
496  set(ARCH "x86")
497 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "i386")
498  set(ARCH "x86")
499 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "i686")
500  set(ARCH "x86")
501 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
502  set(ARCH "aarch64")
503 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
504  set(ARCH "aarch64")
505 # Apple A12 Bionic chipset which is added in iPhone XS/XS Max/XR uses arm64e architecture.
506 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64e")
507  set(ARCH "aarch64")
508 elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm*")
509  set(ARCH "arm")
510 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "mips")
511  # Just to avoid the “unknown processor” error.
512  set(ARCH "generic")
513 elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le")
514  set(ARCH "ppc64le")
515 else()
516  message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
517 endif()
518 
519 if(NOT OPENSSL_NO_ASM)
520  if(UNIX)
521  enable_language(ASM)
522 
523  # Clang's integerated assembler does not support debug symbols.
524  if(NOT CMAKE_ASM_COMPILER_ID MATCHES "Clang")
525  set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-g")
526  endif()
527 
528  # CMake does not add -isysroot and -arch flags to assembly.
529  if(APPLE)
530  if(CMAKE_OSX_SYSROOT)
531  set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -isysroot \"${CMAKE_OSX_SYSROOT}\"")
532  endif()
533  foreach(arch ${CMAKE_OSX_ARCHITECTURES})
534  set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch ${arch}")
535  endforeach()
536  endif()
537  else()
538  set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -gcv8")
539  enable_language(ASM_NASM)
540  endif()
541 endif()
542 
543 if(BUILD_SHARED_LIBS)
544  add_definitions(-DBORINGSSL_SHARED_LIBRARY)
545  # Enable position-independent code globally. This is needed because
546  # some library targets are OBJECT libraries.
547  set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
548 endif()
549 
550 include_directories(src/include)
551 
552 '''
553 
554  def PrintLibrary(self, out, name, files):
555  out.write('add_library(\n')
556  out.write(' %s\n\n' % name)
557 
558  for f in sorted(files):
559  out.write(' %s\n' % PathOf(f))
560 
561  out.write(')\n\n')
562 
563  def PrintExe(self, out, name, files, libs):
564  out.write('add_executable(\n')
565  out.write(' %s\n\n' % name)
566 
567  for f in sorted(files):
568  out.write(' %s\n' % PathOf(f))
569 
570  out.write(')\n\n')
571  out.write('target_link_libraries(%s %s)\n\n' % (name, ' '.join(libs)))
572 
573  def PrintSection(self, out, name, files):
574  out.write('set(\n')
575  out.write(' %s\n\n' % name)
576  for f in sorted(files):
577  out.write(' %s\n' % PathOf(f))
578  out.write(')\n\n')
579 
580  def WriteFiles(self, files, asm_outputs):
581  with open('CMakeLists.txt', 'w+') as cmake:
582  cmake.write(self.header)
583 
584  for ((osname, arch), asm_files) in asm_outputs:
585  self.PrintSection(cmake, 'CRYPTO_%s_%s_SOURCES' % (osname, arch),
586  asm_files)
587 
588  cmake.write(
589 R'''if(APPLE AND ARCH STREQUAL "aarch64")
590  set(CRYPTO_ARCH_SOURCES ${CRYPTO_ios_aarch64_SOURCES})
591 elseif(APPLE AND ARCH STREQUAL "arm")
592  set(CRYPTO_ARCH_SOURCES ${CRYPTO_ios_arm_SOURCES})
593 elseif(APPLE)
594  set(CRYPTO_ARCH_SOURCES ${CRYPTO_mac_${ARCH}_SOURCES})
595 elseif(UNIX)
596  set(CRYPTO_ARCH_SOURCES ${CRYPTO_linux_${ARCH}_SOURCES})
597 elseif(WIN32)
598  set(CRYPTO_ARCH_SOURCES ${CRYPTO_win_${ARCH}_SOURCES})
599 endif()
600 
601 ''')
602 
603  self.PrintLibrary(cmake, 'crypto',
604  files['crypto'] + ['${CRYPTO_ARCH_SOURCES}'])
605  self.PrintLibrary(cmake, 'ssl', files['ssl'])
606  self.PrintExe(cmake, 'bssl', files['tool'], ['ssl', 'crypto'])
607 
608  cmake.write(
609 R'''if(NOT WIN32 AND NOT ANDROID)
610  target_link_libraries(crypto pthread)
611 endif()
612 
613 if(WIN32)
614  target_link_libraries(bssl ws2_32)
615 endif()
616 
617 ''')
618 
619 class JSON(object):
620  def WriteFiles(self, files, asm_outputs):
621  sources = dict(files)
622  for ((osname, arch), asm_files) in asm_outputs:
623  sources['crypto_%s_%s' % (osname, arch)] = asm_files
624  with open('sources.json', 'w+') as f:
625  json.dump(sources, f, sort_keys=True, indent=2)
626 
627 def FindCMakeFiles(directory):
628  """Returns list of all CMakeLists.txt files recursively in directory."""
629  cmakefiles = []
630 
631  for (path, _, filenames) in os.walk(directory):
632  for filename in filenames:
633  if filename == 'CMakeLists.txt':
634  cmakefiles.append(os.path.join(path, filename))
635 
636  return cmakefiles
637 
638 def OnlyFIPSFragments(path, dent, is_dir):
639  return is_dir or (path.startswith(
640  os.path.join('src', 'crypto', 'fipsmodule', '')) and
641  NoTests(path, dent, is_dir))
642 
643 def NoTestsNorFIPSFragments(path, dent, is_dir):
644  return (NoTests(path, dent, is_dir) and
645  (is_dir or not OnlyFIPSFragments(path, dent, is_dir)))
646 
647 def NoTests(path, dent, is_dir):
648  """Filter function that can be passed to FindCFiles in order to remove test
649  sources."""
650  if is_dir:
651  return dent != 'test'
652  return 'test.' not in dent
653 
654 
655 def OnlyTests(path, dent, is_dir):
656  """Filter function that can be passed to FindCFiles in order to remove
657  non-test sources."""
658  if is_dir:
659  return dent != 'test'
660  return '_test.' in dent
661 
662 
663 def AllFiles(path, dent, is_dir):
664  """Filter function that can be passed to FindCFiles in order to include all
665  sources."""
666  return True
667 
668 
669 def NoTestRunnerFiles(path, dent, is_dir):
670  """Filter function that can be passed to FindCFiles or FindHeaderFiles in
671  order to exclude test runner files."""
672  # NOTE(martinkr): This prevents .h/.cc files in src/ssl/test/runner, which
673  # are in their own subpackage, from being included in boringssl/BUILD files.
674  return not is_dir or dent != 'runner'
675 
676 
677 def NotGTestSupport(path, dent, is_dir):
678  return 'gtest' not in dent and 'abi_test' not in dent
679 
680 
681 def SSLHeaderFiles(path, dent, is_dir):
682  return dent in ['ssl.h', 'tls1.h', 'ssl23.h', 'ssl3.h', 'dtls1.h', 'srtp.h']
683 
684 
685 def FindCFiles(directory, filter_func):
686  """Recurses through directory and returns a list of paths to all the C source
687  files that pass filter_func."""
688  cfiles = []
689 
690  for (path, dirnames, filenames) in os.walk(directory):
691  for filename in filenames:
692  if not filename.endswith('.c') and not filename.endswith('.cc'):
693  continue
694  if not filter_func(path, filename, False):
695  continue
696  cfiles.append(os.path.join(path, filename))
697 
698  for (i, dirname) in enumerate(dirnames):
699  if not filter_func(path, dirname, True):
700  del dirnames[i]
701 
702  cfiles.sort()
703  return cfiles
704 
705 
706 def FindHeaderFiles(directory, filter_func):
707  """Recurses through directory and returns a list of paths to all the header files that pass filter_func."""
708  hfiles = []
709 
710  for (path, dirnames, filenames) in os.walk(directory):
711  for filename in filenames:
712  if not filename.endswith('.h'):
713  continue
714  if not filter_func(path, filename, False):
715  continue
716  hfiles.append(os.path.join(path, filename))
717 
718  for (i, dirname) in enumerate(dirnames):
719  if not filter_func(path, dirname, True):
720  del dirnames[i]
721 
722  hfiles.sort()
723  return hfiles
724 
725 
727  """Parses the contents of the CMakeLists.txt file passed as an argument and
728  returns a list of all the perlasm() directives found in the file."""
729  perlasms = []
730  with open(cmakefile) as f:
731  for line in f:
732  line = line.strip()
733  if not line.startswith('perlasm('):
734  continue
735  if not line.endswith(')'):
736  raise ValueError('Bad perlasm line in %s' % cmakefile)
737  # Remove "perlasm(" from start and ")" from end
738  params = line[8:-1].split()
739  if len(params) < 2:
740  raise ValueError('Bad perlasm line in %s' % cmakefile)
741  perlasms.append({
742  'extra_args': params[2:],
743  'input': os.path.join(os.path.dirname(cmakefile), params[1]),
744  'output': os.path.join(os.path.dirname(cmakefile), params[0]),
745  })
746 
747  return perlasms
748 
749 
751  """Returns a list of all perlasm() directives found in CMake config files in
752  src/."""
753  perlasms = []
754  cmakefiles = FindCMakeFiles('src')
755 
756  for cmakefile in cmakefiles:
757  perlasms.extend(ExtractPerlAsmFromCMakeFile(cmakefile))
758 
759  return perlasms
760 
761 
762 def PerlAsm(output_filename, input_filename, perlasm_style, extra_args):
763  """Runs the a perlasm script and puts the output into output_filename."""
764  base_dir = os.path.dirname(output_filename)
765  if not os.path.isdir(base_dir):
766  os.makedirs(base_dir)
767  subprocess.check_call(
768  ['perl', input_filename, perlasm_style] + extra_args + [output_filename])
769 
770 
771 def ArchForAsmFilename(filename):
772  """Returns the architectures that a given asm file should be compiled for
773  based on substrings in the filename."""
774 
775  if 'x86_64' in filename or 'avx2' in filename:
776  return ['x86_64']
777  elif ('x86' in filename and 'x86_64' not in filename) or '586' in filename:
778  return ['x86']
779  elif 'armx' in filename:
780  return ['arm', 'aarch64']
781  elif 'armv8' in filename:
782  return ['aarch64']
783  elif 'arm' in filename:
784  return ['arm']
785  elif 'ppc' in filename:
786  return ['ppc64le']
787  else:
788  raise ValueError('Unknown arch for asm filename: ' + filename)
789 
790 
791 def WriteAsmFiles(perlasms):
792  """Generates asm files from perlasm directives for each supported OS x
793  platform combination."""
794  asmfiles = {}
795 
796  for osarch in OS_ARCH_COMBOS:
797  (osname, arch, perlasm_style, extra_args, asm_ext) = osarch
798  key = (osname, arch)
799  outDir = '%s-%s' % key
800 
801  for perlasm in perlasms:
802  filename = os.path.basename(perlasm['input'])
803  output = perlasm['output']
804  if not output.startswith('src'):
805  raise ValueError('output missing src: %s' % output)
806  output = os.path.join(outDir, output[4:])
807  if output.endswith('-armx.${ASM_EXT}'):
808  output = output.replace('-armx',
809  '-armx64' if arch == 'aarch64' else '-armx32')
810  output = output.replace('${ASM_EXT}', asm_ext)
811 
812  if arch in ArchForAsmFilename(filename):
813  PerlAsm(output, perlasm['input'], perlasm_style,
814  perlasm['extra_args'] + extra_args)
815  asmfiles.setdefault(key, []).append(output)
816 
817  for (key, non_perl_asm_files) in NON_PERL_FILES.items():
818  asmfiles.setdefault(key, []).extend(non_perl_asm_files)
819 
820  for files in asmfiles.values():
821  files.sort()
822 
823  return asmfiles
824 
825 
827  """Parses the contents of the CMakeLists.txt file passed as an argument and
828  returns a dictionary of exported source lists."""
829  variables = {}
830  in_set_command = False
831  set_command = []
832  with open(cmakefile) as f:
833  for line in f:
834  if '#' in line:
835  line = line[:line.index('#')]
836  line = line.strip()
837 
838  if not in_set_command:
839  if line.startswith('set('):
840  in_set_command = True
841  set_command = []
842  elif line == ')':
843  in_set_command = False
844  if not set_command:
845  raise ValueError('Empty set command')
846  variables[set_command[0]] = set_command[1:]
847  else:
848  set_command.extend([c for c in line.split(' ') if c])
849 
850  if in_set_command:
851  raise ValueError('Unfinished set command')
852  return variables
853 
854 
855 def main(platforms):
856  cmake = ExtractVariablesFromCMakeFile(os.path.join('src', 'sources.cmake'))
857  crypto_c_files = (FindCFiles(os.path.join('src', 'crypto'), NoTestsNorFIPSFragments) +
858  FindCFiles(os.path.join('src', 'third_party', 'fiat'), NoTestsNorFIPSFragments))
859  fips_fragments = FindCFiles(os.path.join('src', 'crypto', 'fipsmodule'), OnlyFIPSFragments)
860  ssl_source_files = FindCFiles(os.path.join('src', 'ssl'), NoTests)
861  tool_c_files = FindCFiles(os.path.join('src', 'tool'), NoTests)
862  tool_h_files = FindHeaderFiles(os.path.join('src', 'tool'), AllFiles)
863 
864  # BCM shared library C files
865  bcm_crypto_c_files = [
866  os.path.join('src', 'crypto', 'fipsmodule', 'bcm.c')
867  ]
868 
869  # Generate err_data.c
870  with open('err_data.c', 'w+') as err_data:
871  subprocess.check_call(['go', 'run', 'err_data_generate.go'],
872  cwd=os.path.join('src', 'crypto', 'err'),
873  stdout=err_data)
874  crypto_c_files.append('err_data.c')
875  crypto_c_files.sort()
876 
877  test_support_c_files = FindCFiles(os.path.join('src', 'crypto', 'test'),
878  NotGTestSupport)
879  test_support_h_files = (
880  FindHeaderFiles(os.path.join('src', 'crypto', 'test'), AllFiles) +
881  FindHeaderFiles(os.path.join('src', 'ssl', 'test'), NoTestRunnerFiles))
882 
883  crypto_test_files = []
884  if EMBED_TEST_DATA:
885  # Generate crypto_test_data.cc
886  with open('crypto_test_data.cc', 'w+') as out:
887  subprocess.check_call(
888  ['go', 'run', 'util/embed_test_data.go'] + cmake['CRYPTO_TEST_DATA'],
889  cwd='src',
890  stdout=out)
891  crypto_test_files += ['crypto_test_data.cc']
892 
893  crypto_test_files += FindCFiles(os.path.join('src', 'crypto'), OnlyTests)
894  crypto_test_files += [
895  'src/crypto/test/abi_test.cc',
896  'src/crypto/test/file_test_gtest.cc',
897  'src/crypto/test/gtest_main.cc',
898  ]
899  # urandom_test.cc is in a separate binary so that it can be test PRNG
900  # initialisation.
901  crypto_test_files = [
902  file for file in crypto_test_files
903  if not file.endswith('/urandom_test.cc')
904  ]
905  crypto_test_files.sort()
906 
907  ssl_test_files = FindCFiles(os.path.join('src', 'ssl'), OnlyTests)
908  ssl_test_files += [
909  'src/crypto/test/abi_test.cc',
910  'src/crypto/test/gtest_main.cc',
911  ]
912  ssl_test_files.sort()
913 
914  urandom_test_files = [
915  'src/crypto/fipsmodule/rand/urandom_test.cc',
916  ]
917 
918  fuzz_c_files = FindCFiles(os.path.join('src', 'fuzz'), NoTests)
919 
920  ssl_h_files = FindHeaderFiles(os.path.join('src', 'include', 'openssl'),
921  SSLHeaderFiles)
922 
923  def NotSSLHeaderFiles(path, filename, is_dir):
924  return not SSLHeaderFiles(path, filename, is_dir)
925  crypto_h_files = FindHeaderFiles(os.path.join('src', 'include', 'openssl'),
926  NotSSLHeaderFiles)
927 
928  ssl_internal_h_files = FindHeaderFiles(os.path.join('src', 'ssl'), NoTests)
929  crypto_internal_h_files = (
930  FindHeaderFiles(os.path.join('src', 'crypto'), NoTests) +
931  FindHeaderFiles(os.path.join('src', 'third_party', 'fiat'), NoTests))
932 
933  files = {
934  'bcm_crypto': bcm_crypto_c_files,
935  'crypto': crypto_c_files,
936  'crypto_headers': crypto_h_files,
937  'crypto_internal_headers': crypto_internal_h_files,
938  'crypto_test': crypto_test_files,
939  'crypto_test_data': sorted('src/' + x for x in cmake['CRYPTO_TEST_DATA']),
940  'fips_fragments': fips_fragments,
941  'fuzz': fuzz_c_files,
942  'ssl': ssl_source_files,
943  'ssl_headers': ssl_h_files,
944  'ssl_internal_headers': ssl_internal_h_files,
945  'ssl_test': ssl_test_files,
946  'tool': tool_c_files,
947  'tool_headers': tool_h_files,
948  'test_support': test_support_c_files,
949  'test_support_headers': test_support_h_files,
950  'urandom_test': urandom_test_files,
951  }
952 
953  asm_outputs = sorted(WriteAsmFiles(ReadPerlAsmOperations()).items())
954 
955  for platform in platforms:
956  platform.WriteFiles(files, asm_outputs)
957 
958  return 0
959 
960 ALL_PLATFORMS = {
961  'android': Android,
962  'android-cmake': AndroidCMake,
963  'bazel': Bazel,
964  'cmake': CMake,
965  'eureka': Eureka,
966  'gn': GN,
967  'gyp': GYP,
968  'json': JSON,
969 }
970 
971 if __name__ == '__main__':
972  parser = optparse.OptionParser(usage='Usage: %%prog [--prefix=<path>] [%s]' %
973  '|'.join(sorted(ALL_PLATFORMS.keys())))
974  parser.add_option('--prefix', dest='prefix',
975  help='For Bazel, prepend argument to all source files')
976  parser.add_option(
977  '--embed_test_data', type='choice', dest='embed_test_data',
978  action='store', default="true", choices=["true", "false"],
979  help='For Bazel or GN, don\'t embed data files in crypto_test_data.cc')
980  options, args = parser.parse_args(sys.argv[1:])
981  PREFIX = options.prefix
982  EMBED_TEST_DATA = (options.embed_test_data == "true")
983 
984  if not args:
985  parser.print_help()
986  sys.exit(1)
987 
988  platforms = []
989  for s in args:
990  platform = ALL_PLATFORMS.get(s)
991  if platform is None:
992  parser.print_help()
993  sys.exit(1)
994  platforms.append(platform())
995 
996  sys.exit(main(platforms))
generate_build_files.GYP.PrintVariableSection
def PrintVariableSection(self, out, name, files)
Definition: generate_build_files.py:398
generate_build_files.NoTests
def NoTests(path, dent, is_dir)
Definition: generate_build_files.py:647
generate_build_files.Android.PrintDefaults
def PrintDefaults(self, blueprint, name, files, asm_outputs={})
Definition: generate_build_files.py:121
generate_build_files.CMake.__init__
def __init__(self)
Definition: generate_build_files.py:423
generate_build_files.ReadPerlAsmOperations
def ReadPerlAsmOperations()
Definition: generate_build_files.py:750
generate_build_files.main
def main(platforms)
Definition: generate_build_files.py:855
generate_build_files.GN.PrintVariableSection
def PrintVariableSection(self, out, name, files)
Definition: generate_build_files.py:339
generate_build_files.CMake
Definition: generate_build_files.py:421
generate_build_files.Bazel.firstSection
firstSection
Definition: generate_build_files.py:223
generate_build_files.AndroidCMake.PrintVariableSection
def PrintVariableSection(self, out, name, files)
Definition: generate_build_files.py:187
generate_build_files.ExtractPerlAsmFromCMakeFile
def ExtractPerlAsmFromCMakeFile(cmakefile)
Definition: generate_build_files.py:726
generate_build_files.Android.header
header
Definition: generate_build_files.py:66
generate_build_files.GYP.__init__
def __init__(self)
Definition: generate_build_files.py:388
generate_build_files.GN.WriteFiles
def WriteFiles(self, files, asm_outputs)
Definition: generate_build_files.py:349
generate_build_files.NoTestsNorFIPSFragments
def NoTestsNorFIPSFragments(path, dent, is_dir)
Definition: generate_build_files.py:643
generate_build_files.CMake.PrintLibrary
def PrintLibrary(self, out, name, files)
Definition: generate_build_files.py:554
generate_build_files.AndroidCMake.WriteFiles
def WriteFiles(self, files, asm_outputs)
Definition: generate_build_files.py:197
generate_build_files.Eureka
Definition: generate_build_files.py:282
generate_build_files.FindCFiles
def FindCFiles(directory, filter_func)
Definition: generate_build_files.py:685
generate_build_files.Bazel.header
header
Definition: generate_build_files.py:224
generate_build_files.CMake.PrintSection
def PrintSection(self, out, name, files)
Definition: generate_build_files.py:573
generate_build_files.Android.PrintVariableSection
def PrintVariableSection(self, out, name, files)
Definition: generate_build_files.py:84
generate_build_files.Bazel.WriteFiles
def WriteFiles(self, files, asm_outputs)
Definition: generate_build_files.py:239
generate_build_files.GN.__init__
def __init__(self)
Definition: generate_build_files.py:328
generate_build_files.AndroidCMake.__init__
def __init__(self)
Definition: generate_build_files.py:165
generate_build_files.AndroidCMake.header
header
Definition: generate_build_files.py:166
generate_build_files.Android.__init__
def __init__(self)
Definition: generate_build_files.py:65
generate_build_files.CMake.WriteFiles
def WriteFiles(self, files, asm_outputs)
Definition: generate_build_files.py:580
generate_build_files.PerlAsm
def PerlAsm(output_filename, input_filename, perlasm_style, extra_args)
Definition: generate_build_files.py:762
generate_build_files.Bazel
Definition: generate_build_files.py:219
generate_build_files.Eureka.WriteFiles
def WriteFiles(self, files, asm_outputs)
Definition: generate_build_files.py:310
generate_build_files.GYP.header
header
Definition: generate_build_files.py:389
generate_build_files.FindCMakeFiles
def FindCMakeFiles(directory)
Definition: generate_build_files.py:627
generate_build_files.OnlyTests
def OnlyTests(path, dent, is_dir)
Definition: generate_build_files.py:655
generate_build_files.NoTestRunnerFiles
def NoTestRunnerFiles(path, dent, is_dir)
Definition: generate_build_files.py:669
generate_build_files.Bazel.__init__
def __init__(self)
Definition: generate_build_files.py:222
generate_build_files.CMake.PrintExe
def PrintExe(self, out, name, files, libs)
Definition: generate_build_files.py:563
generate_build_files.NotGTestSupport
def NotGTestSupport(path, dent, is_dir)
Definition: generate_build_files.py:677
generate_build_files.ArchForAsmFilename
def ArchForAsmFilename(filename)
Definition: generate_build_files.py:771
generate_build_files.WriteAsmFiles
def WriteAsmFiles(perlasms)
Definition: generate_build_files.py:791
xds_manager.items
items
Definition: xds_manager.py:55
generate_build_files.Eureka.PrintVariableSection
def PrintVariableSection(self, out, name, files)
Definition: generate_build_files.py:304
generate_build_files.GN
Definition: generate_build_files.py:326
generate_build_files.JSON
Definition: generate_build_files.py:619
generate_build_files.Android.FilterBcmAsm
def FilterBcmAsm(self, asm, want_bcm)
Definition: generate_build_files.py:149
generate_build_files.FindHeaderFiles
def FindHeaderFiles(directory, filter_func)
Definition: generate_build_files.py:706
generate_build_files.SSLHeaderFiles
def SSLHeaderFiles(path, dent, is_dir)
Definition: generate_build_files.py:681
generate_build_files.JSON.WriteFiles
def WriteFiles(self, files, asm_outputs)
Definition: generate_build_files.py:620
main
Definition: main.py:1
generate_build_files.Android.WriteFiles
def WriteFiles(self, files, asm_outputs)
Definition: generate_build_files.py:90
generate_build_files.GN.header
header
Definition: generate_build_files.py:330
generate_build_files.GYP.WriteFiles
def WriteFiles(self, files, asm_outputs)
Definition: generate_build_files.py:404
generate_build_files.Eureka.__init__
def __init__(self)
Definition: generate_build_files.py:284
generate_build_files.CMake.header
header
Definition: generate_build_files.py:424
generate_build_files.Android
Definition: generate_build_files.py:63
open
#define open
Definition: test-fs.c:46
generate_build_files.GN.firstSection
firstSection
Definition: generate_build_files.py:329
len
int len
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:46
generate_build_files.AllFiles
def AllFiles(path, dent, is_dir)
Definition: generate_build_files.py:663
generate_build_files.Eureka.header
header
Definition: generate_build_files.py:285
generate_build_files.GYP
Definition: generate_build_files.py:386
split
static void split(const char *s, char ***ss, size_t *ns)
Definition: debug/trace.cc:111
generate_build_files.AndroidCMake
Definition: generate_build_files.py:163
generate_build_files.ExtractVariablesFromCMakeFile
def ExtractVariablesFromCMakeFile(cmakefile)
Definition: generate_build_files.py:826
platform
Definition: test_arm_regression.c:18
generate_build_files.Bazel.PrintVariableSection
def PrintVariableSection(self, out, name, files)
Definition: generate_build_files.py:229
generate_build_files.PathOf
def PathOf(x)
Definition: generate_build_files.py:59
generate_build_files.OnlyFIPSFragments
def OnlyFIPSFragments(path, dent, is_dir)
Definition: generate_build_files.py:638


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:59:23