grub-fuse /compile.py

Language Python Lines 184
MD5 Hash 2c40e4bb77cad0e5cdd2ed9fc3951cc6
Repository https://github.com/Spacy/grub-fuse.git View Raw File
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/python

import os, os.path, sys

os.chdir(os.path.dirname(__file__))
try: os.mkdir("build")
except: pass

import re
from fnmatch import fnmatch
from pipes import quote
from pprint import pprint

CFLAGS = "-g -Wall -Iinclude -Igrub-core/gnulib " + \
	"-Ibuild -DLIBDIR=\\\"/usr/local/lib\\\" " + \
	"-DHAVE_CONFIG_H=1 -DGRUB_UTIL=1 " + \
	"-DGRUB_FILE=__FILE__ " + \
	"-D_FILE_OFFSET_BITS=64 " + \
	"-fnested-functions " + \
	"-DAPPLE_CC "
LDFLAGS = "-lfuse4x"

configh = open("build/config.h", "w")
configh.write("""
#define PACKAGE_NAME "grub"
#define PACKAGE_VERSION "1.0.0"
#define HAVE_WORKING_O_NOFOLLOW 1
#define HAVE_DECL_FWRITE_UNLOCKED 0
#define HAVE_DECL_FPUTS_UNLOCKED 0
#define __getopt_argv_const const
#define _GL_UNUSED

#if defined(__i386__)
#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
#else
#define NESTED_FUNC_ATTR
#endif

#if defined(__i386__)
#define SIZEOF_LONG 4
#define SIZEOF_VOID_P 4
#elif defined(__x86_64__)
#define SIZEOF_LONG 8
#define SIZEOF_VOID_P 8
#else
#error "unknown arch"
#endif
#define GRUB_TARGET_SIZEOF_VOID_P SIZEOF_VOID_P

char* strchrnul (const char *s, int c_in);
""")
for funcn in ["strcmp","strlen","strchr","strrchr","strdup","strtoull"]:
	configh.write("#define grub_" + funcn + " " + funcn + "\n")
configh.close()

open("build/config-util.h", "w").write("")

re_grubmodinit = re.compile("GRUB_MOD_INIT\s*\((.+)\)")
ofiles = []
grubmods = []
def compile(fn):
	basen,ext = os.path.splitext(fn)
	ofile = "build/" + basen.replace("/","_") + ".o"
	if ofile in ofiles: return # hm, whatever...
	cmd = "gcc -c " + CFLAGS + " " + quote(fn) + " -o " + quote(ofile)
	print cmd
	assert os.system(cmd) == 0
	ofiles.append(ofile)
	m = re_grubmodinit.search(open(fn).read())
	if m: grubmods.append(m.group(1))
	
re_base_start = re.compile("^([a-z]+) = {")
re_base_end = re.compile("^};")
re_entry_stmnt = re.compile("^ *([a-z_0-9]+);$")
re_entry = re.compile("^ *([a-z_0-9]+) = (.*);$")

content = {} # type (e.g. 'program') -> list -> dict
curentry = None

for l in open("Makefile.util.def"):
	l = l.strip("\n")
	if l.strip() == "": continue
	if l.strip()[0:1] == "#": continue
	m = re_base_start.match(l)
	if m:
		typename = m.group(1)
		curentry = {}
		if typename not in content: content[typename] = []
		content[typename].append(curentry)
		continue
	m = re_base_end.match(l)
	if m:
		curentry = None
		continue
	if curentry is not None:
		if re_entry_stmnt.match(l): continue
		m = re_entry.match(l)
		assert m, "no match in " + repr(l)
		k,v = m.groups()
		if k not in curentry:
			curentry[k] = []
		curentry[k].append(v)

libs = {}
progs = {}

for l in content["library"]:
	libs[l["name"][0]] = l
for l in content["program"]:
	progs[l["name"][0]] = l

# ------------

def read_gnulib_makefile():
	re_vardef = re.compile("^([a-zA-Z_]+) *= *(.*)$")
	re_variadd = re.compile("^([a-zA-Z_]+) *\+= *(.*)$")
	re_filerules = re.compile("^([a-zA-Z_.\-\+/]+) *: *(.*)$")
	
	vars = {}
	fileiter = iter(open("grub-core/gnulib/Makefile.am"))
	for l in fileiter:
		while True:
			l = l.strip("\n")
			if l[-1:] == "\\":
				l = l[:-1]
				l += next(fileiter)
			else: break
		if l.strip() == "": continue
		if l.strip()[0:1] == "#": continue
		m = re_vardef.match(l)
		if m:
			k,v = m.groups()
			assert not k in vars
			vars[k] = v
			continue
		m = re_variadd.match(l)
		if m:
			k,v = m.groups()
			assert k in vars
			vars[k] += " " + v
			continue
		m = re_filerules.match(l)
		if m:
			# ignore
			continue
		if l[0:1] == "\t": # file rule part
			continue
		assert False, l + " not matched"
	
	return vars["libgnu_a_SOURCES"].split()

# ------------

prog = progs["grub-mount"]
lddeps = []
curtarget = prog
while True:
	for f in curtarget["common"]:
		compile(f)
	for d in curtarget.get("ldadd", []):
		if fnmatch(d, "lib*.a"):
			lddeps.append(d)
	if not lddeps: break
	curtarget = libs[lddeps.pop(0)]

for f in read_gnulib_makefile():
	if not fnmatch(f, "*.c"): continue
	compile("grub-core/gnulib/" + f)

assert os.system("sh geninit.sh " + " ".join(map(quote, grubmods)) + " >build/grubinit.c") == 0
compile("build/grubinit.c")

# additional stuff
compile("grub-core/gnulib/mempcpy.c")
compile("grub-core/gnulib/strchrnul.c")
compile("grub-core/gnulib/getopt.c")
compile("grub-core/gnulib/getopt1.c")
compile("grub-core/gnulib/rawmemchr.c")
compile("grub-core/gnulib/basename-lgpl.c")

cmd = "g++ " + LDFLAGS + " " + " ".join(map(quote, ofiles)) + " -o build/grub-mount"
print cmd
assert os.system(cmd) == 0
Back to Top