amalgamate.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #!/usr/bin/env python
  2. # coding: UTF-8
  3. # This Source Code Form is subject to the terms of the Mozilla Public
  4. # License, v. 2.0. If a copy of the MPL was not distributed with this
  5. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. from __future__ import print_function
  7. import argparse
  8. import os.path
  9. import re
  10. import io
  11. parser = argparse.ArgumentParser()
  12. parser.add_argument('version', help='file version')
  13. parser.add_argument('outfile', help='outfile with extension .c/.h')
  14. parser.add_argument('inputs', nargs='*', action='store', help='input filenames')
  15. args = parser.parse_args()
  16. outname = args.outfile.split("/")[-1]
  17. is_c = False
  18. if outname[-2:] == ".c":
  19. is_c = True
  20. pos = outname.find(".")
  21. if pos > 0:
  22. outname = outname[:pos]
  23. include_re = re.compile("^#[\s]*include (\".*\").*$")
  24. guard_re = re.compile("^#(?:(?:ifndef|define)\s*[A-Z_]+_H_|endif /\* [A-Z_]+_H_ \*/|endif // [A-Z_]+_H_|endif\s*/\*\s*!?[A-Z_]+_H[_]+\s*\*/)")
  25. print ("Starting amalgamating file "+ args.outfile)
  26. file = io.open(args.outfile, 'wt', encoding='utf8', errors='replace')
  27. file.write(u"""/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62541 SOURCES
  28. * visit http://open62541.org/ for information about this software
  29. * Git-Revision: %s
  30. */
  31. /*
  32. * Copyright (C) 2014-2018 the contributors as stated in the AUTHORS file
  33. *
  34. * This file is part of open62541. open62541 is free software: you can
  35. * redistribute it and/or modify it under the terms of the Mozilla Public
  36. * License v2.0 as stated in the LICENSE file provided with open62541.
  37. *
  38. * open62541 is distributed in the hope that it will be useful, but WITHOUT ANY
  39. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  40. * A PARTICULAR PURPOSE.
  41. */\n\n""" % args.version)
  42. if is_c:
  43. file.write(u'''#ifndef UA_DYNAMIC_LINKING_EXPORT
  44. # define UA_DYNAMIC_LINKING_EXPORT
  45. # define MDNSD_DYNAMIC_LINKING
  46. #endif
  47. /* Disable security warnings for BSD sockets on MSVC */
  48. #ifdef _MSC_VER
  49. # define _CRT_SECURE_NO_WARNINGS
  50. #endif
  51. #include "%s.h"
  52. ''' % outname)
  53. else:
  54. file.write(u'''#ifndef %s
  55. #define %s
  56. ''' % (outname.upper() + u"_H_", outname.upper() + u"_H_"))
  57. for fname in args.inputs:
  58. with io.open(fname, encoding='utf8', errors='replace') as infile:
  59. file.write(u"\n/*********************************** amalgamated original file \"" + fname + u"\" ***********************************/\n\n")
  60. print ("Integrating file '" + fname + "'...", end=""),
  61. for line in infile:
  62. inc_res = include_re.match(line)
  63. guard_res = guard_re.match(line)
  64. if not inc_res and not guard_res:
  65. file.write(line)
  66. # Ensure file is written to disk.
  67. file.flush()
  68. os.fsync(file.fileno())
  69. print ("done."),
  70. if not is_c:
  71. file.write(u"#endif /* %s */\n" % (outname.upper() + u"_H_"))
  72. # Ensure file is written to disk.
  73. # See https://stackoverflow.com/questions/13761961/large-file-not-flushed-to-disk-immediately-after-calling-close
  74. file.flush()
  75. os.fsync(file.fileno())
  76. file.close()
  77. print ("The size of "+args.outfile+" is "+ str(os.path.getsize(args.outfile))+" Bytes.")