winres.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. # Brant Young, 2007
  4. "Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}"
  5. import os
  6. import re
  7. from waflib import Task, Utils
  8. from waflib.TaskGen import extension
  9. from waflib.Tools import c_preproc
  10. from waflib import Utils
  11. @extension('.rc')
  12. def rc_file(self, node):
  13. """
  14. Binds the .rc extension to a winrc task
  15. """
  16. obj_ext = '.rc.o'
  17. if self.env.WINRC_TGT_F == '/fo':
  18. obj_ext = '.res'
  19. rctask = self.create_task('winrc', node, node.change_ext(obj_ext))
  20. try:
  21. self.compiled_tasks.append(rctask)
  22. except AttributeError:
  23. self.compiled_tasks = [rctask]
  24. re_lines = re.compile(
  25. r'(?:^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*?)\s*$)|'\
  26. r'(?:^\w+[ \t]*(ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)[ \t]*(.*?)\s*$)',
  27. re.IGNORECASE | re.MULTILINE)
  28. class rc_parser(c_preproc.c_parser):
  29. """
  30. Calculates dependencies in .rc files
  31. """
  32. def filter_comments(self, node):
  33. """
  34. Overrides :py:meth:`waflib.Tools.c_preproc.c_parser.filter_comments`
  35. """
  36. code = node.read()
  37. if c_preproc.use_trigraphs:
  38. for (a, b) in c_preproc.trig_def:
  39. code = code.split(a).join(b)
  40. code = c_preproc.re_nl.sub('', code)
  41. code = c_preproc.re_cpp.sub(c_preproc.repl, code)
  42. ret = []
  43. for m in re.finditer(re_lines, code):
  44. if m.group(2):
  45. ret.append((m.group(2), m.group(3)))
  46. else:
  47. ret.append(('include', m.group(5)))
  48. return ret
  49. class winrc(Task.Task):
  50. """
  51. Compiles resource files
  52. """
  53. run_str = '${WINRC} ${WINRCFLAGS} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}'
  54. color = 'BLUE'
  55. def scan(self):
  56. tmp = rc_parser(self.generator.includes_nodes)
  57. tmp.start(self.inputs[0], self.env)
  58. return (tmp.nodes, tmp.names)
  59. def exec_command(self, cmd, **kw):
  60. if self.env.WINRC_TGT_F == '/fo':
  61. # Since winres include paths may contain spaces, they do not fit in
  62. # response files and are best passed as environment variables
  63. replace_cmd = []
  64. incpaths = []
  65. while cmd:
  66. # filter include path flags
  67. flag = cmd.pop(0)
  68. if flag.upper().startswith('/I'):
  69. if len(flag) == 2:
  70. incpaths.append(cmd.pop(0))
  71. else:
  72. incpaths.append(flag[2:])
  73. else:
  74. replace_cmd.append(flag)
  75. cmd = replace_cmd
  76. if incpaths:
  77. # append to existing environment variables in INCLUDE
  78. env = kw['env'] = dict(kw.get('env') or self.env.env or os.environ)
  79. pre_includes = env.get('INCLUDE', '')
  80. env['INCLUDE'] = pre_includes + os.pathsep + os.pathsep.join(incpaths)
  81. return super(winrc, self).exec_command(cmd, **kw)
  82. def quote_flag(self, flag):
  83. if self.env.WINRC_TGT_F == '/fo':
  84. # winres does not support quotes around flags in response files
  85. return flag
  86. return super(winrc, self).quote_flag(flag)
  87. def configure(conf):
  88. """
  89. Detects the programs RC or windres, depending on the C/C++ compiler in use
  90. """
  91. v = conf.env
  92. if not v.WINRC:
  93. if v.CC_NAME == 'msvc':
  94. if Utils.is_win32:
  95. conf.find_program('RC', var='WINRC', path_list=v.PATH)
  96. else:
  97. llvm_env_path = conf.environ.get('LLVM_PATH')
  98. llvm_path = None
  99. if llvm_env_path:
  100. llvm_path = llvm_env_path
  101. elif 'LLVM_PATH' in v:
  102. llvm_path = v['LLVM_PATH']
  103. paths = v.PATH
  104. if llvm_path:
  105. paths = [llvm_path] + v.PATH
  106. conf.find_program('llvm-rc', var='WINRC', path_list=paths)
  107. v.WINRC_TGT_F = '/fo'
  108. v.WINRC_SRC_F = ''
  109. else:
  110. conf.find_program('windres', var='WINRC', path_list=v.PATH)
  111. v.WINRC_TGT_F = '-o'
  112. v.WINRC_SRC_F = '-i'