c.pm 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. -- pm includefile to compile *host* C programs.
  2. -- Standard Lua boilerplate.
  3. local io_open = io.open
  4. local string_gsub = string.gsub
  5. local string_gfind = string.gfind
  6. local string_find = string.find
  7. local table_insert = table.insert
  8. local table_getn = table.getn
  9. local filetime = pm.filetime
  10. -- Define some variables.
  11. CCOMPILER = "gcc"
  12. CC = "%CCOMPILER% %CBUILDFLAGS% %CDYNINCLUDES% %CINCLUDES% %CDEFINES% %CEXTRAFLAGS% -c -o %out% %in%"
  13. CPROGRAM = "%CCOMPILER% %CBUILDFLAGS% %CLINKFLAGS% %CEXTRAFLAGS% -o %out% %in% %CLIBRARIES%"
  14. AR = "%RM% %out% && ar cr %out% %in% && ranlib %out%"
  15. CBUILDFLAGS = {"-g"}
  16. CINCLUDES = EMPTY
  17. CDEFINES = EMPTY
  18. CEXTRAFLAGS = EMPTY
  19. CLINKFLAGS = EMPTY
  20. CDYNINCLUDES = EMPTY
  21. CLIBRARIES = EMPTY
  22. --- Manage C file dependencies ----------------------------------------------
  23. local dependency_cache = {}
  24. local function calculate_dependencies(filename, includes)
  25. -- Cache values, so we don't recalculate dependencies needlessly.
  26. local o = dependency_cache[filename]
  27. if o then
  28. return o
  29. end
  30. local deps = {}
  31. deps[filename] = true
  32. local calcdeps = 0
  33. calcdeps = function(filename, file)
  34. file = file or io.open(filename)
  35. if not file then
  36. return
  37. end
  38. local localincludes = string_gsub(filename, "/[^/]*$", "")
  39. if localincludes then
  40. localincludes = {localincludes, unpack(includes)}
  41. else
  42. localincludes = includes
  43. end
  44. for line in file:lines() do
  45. local _, _, f = string_find(line, '^[ \t]*#[ \t]*include[ \t]*["<]([^"]+)[">]')
  46. if f then
  47. for _, path in ipairs(localincludes) do
  48. local subfilename = path.."/"..f
  49. local subfile = io.open(subfilename)
  50. if subfile then
  51. if not deps[subfilename] then
  52. deps[subfilename] = true
  53. calcdeps(subfilename, subfile)
  54. end
  55. break
  56. end
  57. end
  58. end
  59. end
  60. -- Explicit close to avoid having to wait for the garbage collector
  61. -- to free up the underlying fd.
  62. file:close()
  63. end
  64. calcdeps(filename)
  65. o = {}
  66. for i, _ in pairs(deps) do
  67. table_insert(o, i)
  68. end
  69. dependency_cache[filename] = o
  70. return o
  71. end
  72. -- This clause specialises 'simple' to add support for smart dependencies of C
  73. -- files.
  74. simple_with_clike_dependencies = simple {
  75. class = "simple_with_clike_dependencies",
  76. makedepends = {"%CDEPENDS%"},
  77. __init = function(self, p)
  78. simple.__init(self, p)
  79. -- If we're a class, don't verify.
  80. if ((type(p) == "table") and p.class) then
  81. return
  82. end
  83. -- If dynamicheaders is an object, turn it into a singleton list.
  84. if self.dynamicheaders then
  85. if (type(self.dynamicheaders) ~= "table") then
  86. self:__error("doesn't know what to do with dynamicheaders, which ",
  87. "should be a list or an object but was a ", type(self.dynamicheaders))
  88. end
  89. if self.dynamicheaders.class then
  90. self.dynamicheaders = {self.dynamicheaders}
  91. end
  92. end
  93. end,
  94. __dependencies = function(self, inputs, outputs)
  95. local cincludes = self.CINCLUDES
  96. if (type(cincludes) == "string") then
  97. cincludes = {cincludes}
  98. end
  99. local includes = {}
  100. for _, i in ipairs(cincludes) do
  101. local _, _, p = string_find(i, "^-I[ \t]*(.+)$")
  102. if p then
  103. table_insert(includes, p)
  104. end
  105. end
  106. local depends = calculate_dependencies(inputs[1], includes)
  107. if not depends then
  108. self:__error("could not determine the dependencies for ",
  109. pm.rendertable(inputs))
  110. end
  111. if pm.verbose then
  112. pm.message('"', inputs[1], '" appears to depend on ',
  113. pm.rendertable(depends))
  114. end
  115. return depends
  116. end,
  117. __buildadditionalchildren = function(self)
  118. self.CDYNINCLUDES = ""
  119. if self.dynamicheaders then
  120. for _, i in ipairs(self.dynamicheaders) do
  121. local o = i:__build()
  122. if o[1] then
  123. self.CDYNINCLUDES = self.CDYNINCLUDES..' "-I'..string_gsub(o[1], "/[^/]*$", "")..'"'
  124. end
  125. end
  126. end
  127. end
  128. }
  129. -- These are the publically useful clauses.
  130. cfile = simple_with_clike_dependencies {
  131. class = "cfile",
  132. command = {"%CC%"},
  133. outputs = {"%U%-%I%.o"},
  134. }
  135. cprogram = simple {
  136. class = "cprogram",
  137. command = {"%CPROGRAM%"},
  138. outputs = {"%U%-%I%"},
  139. }
  140. clibrary = simple {
  141. class = "clibrary",
  142. command = {
  143. "%AR%"
  144. },
  145. outputs = {"%U%-%I%.a"},
  146. }