zos.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. """distutils.zosccompiler
  2. Contains the selection of the c & c++ compilers on z/OS. There are several
  3. different c compilers on z/OS, all of them are optional, so the correct
  4. one needs to be chosen based on the users input. This is compatible with
  5. the following compilers:
  6. IBM C/C++ For Open Enterprise Languages on z/OS 2.0
  7. IBM Open XL C/C++ 1.1 for z/OS
  8. IBM XL C/C++ V2.4.1 for z/OS 2.4 and 2.5
  9. IBM z/OS XL C/C++
  10. """
  11. import os
  12. from ... import sysconfig
  13. from ...errors import DistutilsExecError
  14. from . import unix
  15. from .errors import CompileError
  16. _cc_args = {
  17. 'ibm-openxl': [
  18. '-m64',
  19. '-fvisibility=default',
  20. '-fzos-le-char-mode=ascii',
  21. '-fno-short-enums',
  22. ],
  23. 'ibm-xlclang': [
  24. '-q64',
  25. '-qexportall',
  26. '-qascii',
  27. '-qstrict',
  28. '-qnocsect',
  29. '-Wa,asa,goff',
  30. '-Wa,xplink',
  31. '-qgonumber',
  32. '-qenum=int',
  33. '-Wc,DLL',
  34. ],
  35. 'ibm-xlc': [
  36. '-q64',
  37. '-qexportall',
  38. '-qascii',
  39. '-qstrict',
  40. '-qnocsect',
  41. '-Wa,asa,goff',
  42. '-Wa,xplink',
  43. '-qgonumber',
  44. '-qenum=int',
  45. '-Wc,DLL',
  46. '-qlanglvl=extc99',
  47. ],
  48. }
  49. _cxx_args = {
  50. 'ibm-openxl': [
  51. '-m64',
  52. '-fvisibility=default',
  53. '-fzos-le-char-mode=ascii',
  54. '-fno-short-enums',
  55. ],
  56. 'ibm-xlclang': [
  57. '-q64',
  58. '-qexportall',
  59. '-qascii',
  60. '-qstrict',
  61. '-qnocsect',
  62. '-Wa,asa,goff',
  63. '-Wa,xplink',
  64. '-qgonumber',
  65. '-qenum=int',
  66. '-Wc,DLL',
  67. ],
  68. 'ibm-xlc': [
  69. '-q64',
  70. '-qexportall',
  71. '-qascii',
  72. '-qstrict',
  73. '-qnocsect',
  74. '-Wa,asa,goff',
  75. '-Wa,xplink',
  76. '-qgonumber',
  77. '-qenum=int',
  78. '-Wc,DLL',
  79. '-qlanglvl=extended0x',
  80. ],
  81. }
  82. _asm_args = {
  83. 'ibm-openxl': ['-fasm', '-fno-integrated-as', '-Wa,--ASA', '-Wa,--GOFF'],
  84. 'ibm-xlclang': [],
  85. 'ibm-xlc': [],
  86. }
  87. _ld_args = {
  88. 'ibm-openxl': [],
  89. 'ibm-xlclang': ['-Wl,dll', '-q64'],
  90. 'ibm-xlc': ['-Wl,dll', '-q64'],
  91. }
  92. # Python on z/OS is built with no compiler specific options in it's CFLAGS.
  93. # But each compiler requires it's own specific options to build successfully,
  94. # though some of the options are common between them
  95. class Compiler(unix.Compiler):
  96. src_extensions = ['.c', '.C', '.cc', '.cxx', '.cpp', '.m', '.s']
  97. _cpp_extensions = ['.cc', '.cpp', '.cxx', '.C']
  98. _asm_extensions = ['.s']
  99. def _get_zos_compiler_name(self):
  100. zos_compiler_names = [
  101. os.path.basename(binary)
  102. for envvar in ('CC', 'CXX', 'LDSHARED')
  103. if (binary := os.environ.get(envvar, None))
  104. ]
  105. if len(zos_compiler_names) == 0:
  106. return 'ibm-openxl'
  107. zos_compilers = {}
  108. for compiler in (
  109. 'ibm-clang',
  110. 'ibm-clang64',
  111. 'ibm-clang++',
  112. 'ibm-clang++64',
  113. 'clang',
  114. 'clang++',
  115. 'clang-14',
  116. ):
  117. zos_compilers[compiler] = 'ibm-openxl'
  118. for compiler in ('xlclang', 'xlclang++', 'njsc', 'njsc++'):
  119. zos_compilers[compiler] = 'ibm-xlclang'
  120. for compiler in ('xlc', 'xlC', 'xlc++'):
  121. zos_compilers[compiler] = 'ibm-xlc'
  122. return zos_compilers.get(zos_compiler_names[0], 'ibm-openxl')
  123. def __init__(self, verbose=False, force=False):
  124. super().__init__(verbose, force=force)
  125. self.zos_compiler = self._get_zos_compiler_name()
  126. sysconfig.customize_compiler(self)
  127. def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
  128. local_args = []
  129. if ext in self._cpp_extensions:
  130. compiler = self.compiler_cxx
  131. local_args.extend(_cxx_args[self.zos_compiler])
  132. elif ext in self._asm_extensions:
  133. compiler = self.compiler_so
  134. local_args.extend(_cc_args[self.zos_compiler])
  135. local_args.extend(_asm_args[self.zos_compiler])
  136. else:
  137. compiler = self.compiler_so
  138. local_args.extend(_cc_args[self.zos_compiler])
  139. local_args.extend(cc_args)
  140. try:
  141. self.spawn(compiler + local_args + [src, '-o', obj] + extra_postargs)
  142. except DistutilsExecError as msg:
  143. raise CompileError(msg)
  144. def runtime_library_dir_option(self, dir):
  145. return '-L' + dir
  146. def link(
  147. self,
  148. target_desc,
  149. objects,
  150. output_filename,
  151. output_dir=None,
  152. libraries=None,
  153. library_dirs=None,
  154. runtime_library_dirs=None,
  155. export_symbols=None,
  156. debug=False,
  157. extra_preargs=None,
  158. extra_postargs=None,
  159. build_temp=None,
  160. target_lang=None,
  161. ):
  162. # For a built module to use functions from cpython, it needs to use Pythons
  163. # side deck file. The side deck is located beside the libpython3.xx.so
  164. ldversion = sysconfig.get_config_var('LDVERSION')
  165. if sysconfig.python_build:
  166. side_deck_path = os.path.join(
  167. sysconfig.get_config_var('abs_builddir'),
  168. f'libpython{ldversion}.x',
  169. )
  170. else:
  171. side_deck_path = os.path.join(
  172. sysconfig.get_config_var('installed_base'),
  173. sysconfig.get_config_var('platlibdir'),
  174. f'libpython{ldversion}.x',
  175. )
  176. if os.path.exists(side_deck_path):
  177. if extra_postargs:
  178. extra_postargs.append(side_deck_path)
  179. else:
  180. extra_postargs = [side_deck_path]
  181. # Check and replace libraries included side deck files
  182. if runtime_library_dirs:
  183. for dir in runtime_library_dirs:
  184. for library in libraries[:]:
  185. library_side_deck = os.path.join(dir, f'{library}.x')
  186. if os.path.exists(library_side_deck):
  187. libraries.remove(library)
  188. extra_postargs.append(library_side_deck)
  189. break
  190. # Any required ld args for the given compiler
  191. extra_postargs.extend(_ld_args[self.zos_compiler])
  192. super().link(
  193. target_desc,
  194. objects,
  195. output_filename,
  196. output_dir,
  197. libraries,
  198. library_dirs,
  199. runtime_library_dirs,
  200. export_symbols,
  201. debug,
  202. extra_preargs,
  203. extra_postargs,
  204. build_temp,
  205. target_lang,
  206. )