/compile.py

https://github.com/Spacy/grub-fuse · Python · 183 lines · 156 code · 22 blank · 5 comment · 32 complexity · 2c40e4bb77cad0e5cdd2ed9fc3951cc6 MD5 · raw file

  1. #!/usr/bin/python
  2. import os, os.path, sys
  3. os.chdir(os.path.dirname(__file__))
  4. try: os.mkdir("build")
  5. except: pass
  6. import re
  7. from fnmatch import fnmatch
  8. from pipes import quote
  9. from pprint import pprint
  10. CFLAGS = "-g -Wall -Iinclude -Igrub-core/gnulib " + \
  11. "-Ibuild -DLIBDIR=\\\"/usr/local/lib\\\" " + \
  12. "-DHAVE_CONFIG_H=1 -DGRUB_UTIL=1 " + \
  13. "-DGRUB_FILE=__FILE__ " + \
  14. "-D_FILE_OFFSET_BITS=64 " + \
  15. "-fnested-functions " + \
  16. "-DAPPLE_CC "
  17. LDFLAGS = "-lfuse4x"
  18. configh = open("build/config.h", "w")
  19. configh.write("""
  20. #define PACKAGE_NAME "grub"
  21. #define PACKAGE_VERSION "1.0.0"
  22. #define HAVE_WORKING_O_NOFOLLOW 1
  23. #define HAVE_DECL_FWRITE_UNLOCKED 0
  24. #define HAVE_DECL_FPUTS_UNLOCKED 0
  25. #define __getopt_argv_const const
  26. #define _GL_UNUSED
  27. #if defined(__i386__)
  28. #define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
  29. #else
  30. #define NESTED_FUNC_ATTR
  31. #endif
  32. #if defined(__i386__)
  33. #define SIZEOF_LONG 4
  34. #define SIZEOF_VOID_P 4
  35. #elif defined(__x86_64__)
  36. #define SIZEOF_LONG 8
  37. #define SIZEOF_VOID_P 8
  38. #else
  39. #error "unknown arch"
  40. #endif
  41. #define GRUB_TARGET_SIZEOF_VOID_P SIZEOF_VOID_P
  42. char* strchrnul (const char *s, int c_in);
  43. """)
  44. for funcn in ["strcmp","strlen","strchr","strrchr","strdup","strtoull"]:
  45. configh.write("#define grub_" + funcn + " " + funcn + "\n")
  46. configh.close()
  47. open("build/config-util.h", "w").write("")
  48. re_grubmodinit = re.compile("GRUB_MOD_INIT\s*\((.+)\)")
  49. ofiles = []
  50. grubmods = []
  51. def compile(fn):
  52. basen,ext = os.path.splitext(fn)
  53. ofile = "build/" + basen.replace("/","_") + ".o"
  54. if ofile in ofiles: return # hm, whatever...
  55. cmd = "gcc -c " + CFLAGS + " " + quote(fn) + " -o " + quote(ofile)
  56. print cmd
  57. assert os.system(cmd) == 0
  58. ofiles.append(ofile)
  59. m = re_grubmodinit.search(open(fn).read())
  60. if m: grubmods.append(m.group(1))
  61. re_base_start = re.compile("^([a-z]+) = {")
  62. re_base_end = re.compile("^};")
  63. re_entry_stmnt = re.compile("^ *([a-z_0-9]+);$")
  64. re_entry = re.compile("^ *([a-z_0-9]+) = (.*);$")
  65. content = {} # type (e.g. 'program') -> list -> dict
  66. curentry = None
  67. for l in open("Makefile.util.def"):
  68. l = l.strip("\n")
  69. if l.strip() == "": continue
  70. if l.strip()[0:1] == "#": continue
  71. m = re_base_start.match(l)
  72. if m:
  73. typename = m.group(1)
  74. curentry = {}
  75. if typename not in content: content[typename] = []
  76. content[typename].append(curentry)
  77. continue
  78. m = re_base_end.match(l)
  79. if m:
  80. curentry = None
  81. continue
  82. if curentry is not None:
  83. if re_entry_stmnt.match(l): continue
  84. m = re_entry.match(l)
  85. assert m, "no match in " + repr(l)
  86. k,v = m.groups()
  87. if k not in curentry:
  88. curentry[k] = []
  89. curentry[k].append(v)
  90. libs = {}
  91. progs = {}
  92. for l in content["library"]:
  93. libs[l["name"][0]] = l
  94. for l in content["program"]:
  95. progs[l["name"][0]] = l
  96. # ------------
  97. def read_gnulib_makefile():
  98. re_vardef = re.compile("^([a-zA-Z_]+) *= *(.*)$")
  99. re_variadd = re.compile("^([a-zA-Z_]+) *\+= *(.*)$")
  100. re_filerules = re.compile("^([a-zA-Z_.\-\+/]+) *: *(.*)$")
  101. vars = {}
  102. fileiter = iter(open("grub-core/gnulib/Makefile.am"))
  103. for l in fileiter:
  104. while True:
  105. l = l.strip("\n")
  106. if l[-1:] == "\\":
  107. l = l[:-1]
  108. l += next(fileiter)
  109. else: break
  110. if l.strip() == "": continue
  111. if l.strip()[0:1] == "#": continue
  112. m = re_vardef.match(l)
  113. if m:
  114. k,v = m.groups()
  115. assert not k in vars
  116. vars[k] = v
  117. continue
  118. m = re_variadd.match(l)
  119. if m:
  120. k,v = m.groups()
  121. assert k in vars
  122. vars[k] += " " + v
  123. continue
  124. m = re_filerules.match(l)
  125. if m:
  126. # ignore
  127. continue
  128. if l[0:1] == "\t": # file rule part
  129. continue
  130. assert False, l + " not matched"
  131. return vars["libgnu_a_SOURCES"].split()
  132. # ------------
  133. prog = progs["grub-mount"]
  134. lddeps = []
  135. curtarget = prog
  136. while True:
  137. for f in curtarget["common"]:
  138. compile(f)
  139. for d in curtarget.get("ldadd", []):
  140. if fnmatch(d, "lib*.a"):
  141. lddeps.append(d)
  142. if not lddeps: break
  143. curtarget = libs[lddeps.pop(0)]
  144. for f in read_gnulib_makefile():
  145. if not fnmatch(f, "*.c"): continue
  146. compile("grub-core/gnulib/" + f)
  147. assert os.system("sh geninit.sh " + " ".join(map(quote, grubmods)) + " >build/grubinit.c") == 0
  148. compile("build/grubinit.c")
  149. # additional stuff
  150. compile("grub-core/gnulib/mempcpy.c")
  151. compile("grub-core/gnulib/strchrnul.c")
  152. compile("grub-core/gnulib/getopt.c")
  153. compile("grub-core/gnulib/getopt1.c")
  154. compile("grub-core/gnulib/rawmemchr.c")
  155. compile("grub-core/gnulib/basename-lgpl.c")
  156. cmd = "g++ " + LDFLAGS + " " + " ".join(map(quote, ofiles)) + " -o build/grub-mount"
  157. print cmd
  158. assert os.system(cmd) == 0