amalgamate.py 2.9 KB

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