gmake2_csharp.lua 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. --
  2. -- gmake2_csharp.lua
  3. -- Generate a C# project makefile.
  4. -- (c) 2016-2017 Jason Perkins, Blizzard Entertainment and the Premake project
  5. --
  6. local p = premake
  7. local gmake2 = p.modules.gmake2
  8. gmake2.cs = {}
  9. local cs = gmake2.cs
  10. local project = p.project
  11. local config = p.config
  12. local fileconfig = p.fileconfig
  13. --
  14. -- Add namespace for element definition lists for p.callarray()
  15. --
  16. cs.elements = {}
  17. --
  18. -- Generate a GNU make C++ project makefile, with support for the new platforms API.
  19. --
  20. cs.elements.makefile = function(prj)
  21. return {
  22. gmake2.header,
  23. gmake2.phonyRules,
  24. gmake2.csConfigs,
  25. gmake2.csProjectConfig,
  26. gmake2.csSources,
  27. gmake2.csEmbedFiles,
  28. gmake2.csCopyFiles,
  29. gmake2.csResponseFile,
  30. gmake2.shellType,
  31. gmake2.csAllRules,
  32. gmake2.csTargetRules,
  33. gmake2.targetDirRules,
  34. gmake2.csResponseRules,
  35. gmake2.objDirRules,
  36. gmake2.csCleanRules,
  37. gmake2.preBuildRules,
  38. gmake2.csFileRules,
  39. }
  40. end
  41. --
  42. -- Generate a GNU make C# project makefile, with support for the new platforms API.
  43. --
  44. function cs.generate(prj)
  45. p.eol("\n")
  46. local toolset = p.tools.dotnet
  47. p.callArray(cs.elements.makefile, prj, toolset)
  48. end
  49. --
  50. -- Write out the settings for a particular configuration.
  51. --
  52. cs.elements.configuration = function(cfg)
  53. return {
  54. gmake2.csTools,
  55. gmake2.target,
  56. gmake2.objdir,
  57. gmake2.csFlags,
  58. gmake2.csLinkCmd,
  59. gmake2.preBuildCmds,
  60. gmake2.preLinkCmds,
  61. gmake2.postBuildCmds,
  62. gmake2.settings,
  63. }
  64. end
  65. function gmake2.csConfigs(prj, toolset)
  66. for cfg in project.eachconfig(prj) do
  67. _x('ifeq ($(config),%s)', cfg.shortname)
  68. p.callArray(cs.elements.configuration, cfg, toolset)
  69. _p('endif')
  70. _p('')
  71. end
  72. end
  73. --
  74. -- Given a .resx resource file, builds the path to corresponding .resource
  75. -- file, matching the behavior and naming of Visual Studio.
  76. --
  77. function cs.getresourcefilename(cfg, fname)
  78. if path.getextension(fname) == ".resx" then
  79. local name = cfg.buildtarget.basename .. "."
  80. local dir = path.getdirectory(fname)
  81. if dir ~= "." then
  82. name = name .. path.translate(dir, ".") .. "."
  83. end
  84. return "$(OBJDIR)/" .. p.esc(name .. path.getbasename(fname)) .. ".resources"
  85. else
  86. return fname
  87. end
  88. end
  89. --
  90. -- Iterate and output some selection of the source code files.
  91. --
  92. function cs.listsources(prj, selector)
  93. local tr = project.getsourcetree(prj)
  94. p.tree.traverse(tr, {
  95. onleaf = function(node, depth)
  96. local value = selector(node)
  97. if value then
  98. _x('\t%s \\', value)
  99. end
  100. end
  101. })
  102. end
  103. ---------------------------------------------------------------------------
  104. --
  105. -- Handlers for individual makefile elements
  106. --
  107. ---------------------------------------------------------------------------
  108. function gmake2.csAllRules(prj, toolset)
  109. _p('all: prebuild $(EMBEDFILES) $(COPYFILES) $(TARGET)')
  110. _p('')
  111. end
  112. function gmake2.csCleanRules(prj, toolset)
  113. --[[
  114. -- porting from 4.x
  115. _p('clean:')
  116. _p('\t@echo Cleaning %s', prj.name)
  117. _p('ifeq (posix,$(SHELLTYPE))')
  118. _p('\t$(SILENT) rm -f $(TARGETDIR)/%s.* $(COPYFILES)', target.basename)
  119. _p('\t$(SILENT) rm -rf $(OBJDIR)')
  120. _p('else')
  121. _p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGETDIR)/%s) del $(subst /,\\\\,$(TARGETDIR)/%s.*)', target.name, target.basename)
  122. for target, source in pairs(cfgpairs[anycfg]) do
  123. _p('\t$(SILENT) if exist $(subst /,\\\\,%s) del $(subst /,\\\\,%s)', target, target)
  124. end
  125. for target, source in pairs(copypairs) do
  126. _p('\t$(SILENT) if exist $(subst /,\\\\,%s) del $(subst /,\\\\,%s)', target, target)
  127. end
  128. _p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))')
  129. _p('endif')
  130. _p('')
  131. --]]
  132. end
  133. function gmake2.csCopyFiles(prj, toolset)
  134. --[[
  135. -- copied from 4.x; needs more porting
  136. _p('COPYFILES += \\')
  137. for target, source in pairs(cfgpairs[anycfg]) do
  138. _p('\t%s \\', target)
  139. end
  140. for target, source in pairs(copypairs) do
  141. _p('\t%s \\', target)
  142. end
  143. _p('')
  144. --]]
  145. end
  146. function cs.getresponsefilename(prj)
  147. return '$(OBJDIR)/' .. prj.filename .. '.rsp'
  148. end
  149. function gmake2.csResponseFile(prj, toolset)
  150. _x('RESPONSE += ' .. gmake2.cs.getresponsefilename(prj))
  151. end
  152. function gmake2.csResponseRules(prj)
  153. local toolset = p.tools.dotnet
  154. local ext = gmake2.getmakefilename(prj, true)
  155. local makefile = path.getname(p.filename(prj, ext))
  156. local response = gmake2.cs.getresponsefilename(prj)
  157. _p('$(RESPONSE): %s', makefile)
  158. _p('\t@echo Generating response file', prj.name)
  159. _p('ifeq (posix,$(SHELLTYPE))')
  160. _x('\t$(SILENT) rm -f $(RESPONSE)')
  161. _p('else')
  162. _x('\t$(SILENT) if exist $(RESPONSE) del %s', path.translate(response, '\\'))
  163. _p('endif')
  164. local sep = os.istarget("windows") and "\\" or "/"
  165. local tr = project.getsourcetree(prj)
  166. p.tree.traverse(tr, {
  167. onleaf = function(node, depth)
  168. if toolset.fileinfo(node).action == "Compile" then
  169. _x('\t@echo %s >> $(RESPONSE)', path.translate(node.relpath, sep))
  170. end
  171. end
  172. })
  173. _p('')
  174. end
  175. function gmake2.csEmbedFiles(prj, toolset)
  176. local cfg = project.getfirstconfig(prj)
  177. _p('EMBEDFILES += \\')
  178. cs.listsources(prj, function(node)
  179. local fcfg = fileconfig.getconfig(node, cfg)
  180. local info = toolset.fileinfo(fcfg)
  181. if info.action == "EmbeddedResource" then
  182. return cs.getresourcefilename(cfg, node.relpath)
  183. end
  184. end)
  185. _p('')
  186. end
  187. function gmake2.csFileRules(prj, toolset)
  188. --[[
  189. -- porting from 4.x
  190. _p('# Per-configuration copied file rules')
  191. for cfg in p.eachconfig(prj) do
  192. _x('ifneq (,$(findstring %s,$(config)))', cfg.name:lower())
  193. for target, source in pairs(cfgpairs[cfg]) do
  194. p.make_copyrule(source, target)
  195. end
  196. _p('endif')
  197. _p('')
  198. end
  199. _p('# Copied file rules')
  200. for target, source in pairs(copypairs) do
  201. p.make_copyrule(source, target)
  202. end
  203. _p('# Embedded file rules')
  204. for _, fname in ipairs(embedded) do
  205. if path.getextension(fname) == ".resx" then
  206. _x('%s: %s', getresourcefilename(prj, fname), fname)
  207. _p('\t$(SILENT) $(RESGEN) $^ $@')
  208. end
  209. _p('')
  210. end
  211. --]]
  212. end
  213. function gmake2.csFlags(cfg, toolset)
  214. _p(' FLAGS =%s', gmake2.list(toolset.getflags(cfg)))
  215. end
  216. function gmake2.csLinkCmd(cfg, toolset)
  217. local deps = p.esc(config.getlinks(cfg, "dependencies", "fullpath"))
  218. _p(' DEPENDS =%s', gmake2.list(deps))
  219. _p(' REFERENCES = %s', table.implode(deps, "/r:", "", " "))
  220. end
  221. function gmake2.csProjectConfig(prj, toolset)
  222. -- To maintain compatibility with Visual Studio, these values must
  223. -- be set on the project level, and not per-configuration.
  224. local cfg = project.getfirstconfig(prj)
  225. local kindflag = "/t:" .. toolset.getkind(cfg):lower()
  226. local libdirs = table.implode(p.esc(cfg.libdirs), "/lib:", "", " ")
  227. _p('FLAGS += %s', table.concat(table.join(kindflag, libdirs), " "))
  228. local refs = p.esc(config.getlinks(cfg, "system", "fullpath"))
  229. _p('REFERENCES += %s', table.implode(refs, "/r:", "", " "))
  230. _p('')
  231. end
  232. function gmake2.csSources(prj, toolset)
  233. local cfg = project.getfirstconfig(prj)
  234. _p('SOURCES += \\')
  235. cs.listsources(prj, function(node)
  236. local fcfg = fileconfig.getconfig(node, cfg)
  237. local info = toolset.fileinfo(fcfg)
  238. if info.action == "Compile" then
  239. return node.relpath
  240. end
  241. end)
  242. _p('')
  243. end
  244. function gmake2.csTargetRules(prj, toolset)
  245. _p('$(TARGET): $(SOURCES) $(EMBEDFILES) $(DEPENDS) $(RESPONSE) | $(TARGETDIR)')
  246. _p('\t$(PRELINKCMDS)')
  247. _p('\t$(SILENT) $(CSC) /nologo /out:$@ $(FLAGS) $(REFERENCES) @$(RESPONSE) $(patsubst %%,/resource:%%,$(EMBEDFILES))')
  248. _p('\t$(POSTBUILDCMDS)')
  249. _p('')
  250. end
  251. function gmake2.csTools(cfg, toolset)
  252. _p(' CSC = %s', toolset.gettoolname(cfg, "csc"))
  253. _p(' RESGEN = %s', toolset.gettoolname(cfg, "resgen"))
  254. end