]> jfr.im git - irc/quakenet/newserv.git/blame - configure
Delete data for channels that have been disabled for 5 days.
[irc/quakenet/newserv.git] / configure
CommitLineData
d5713c3b
Q
1#!/usr/bin/env python
2
3import sys
4import os
5import platform
6import getopt
7
8LOG = None
9VERBOSE = False
10
11# standard line print
12def lprint(x):
13 print x
14 LOG.write(x + "\n")
15
16# verbose print
17def vprint(x=""):
18 if VERBOSE:
19 print x
20 LOG.write(x + "\n")
21
22# immediate (no newline) print
23def iprint(x):
24 sys.stdout.write(x)
25 sys.stdout.flush()
26 LOG.write(x)
27
28class IniParser:
29 def __init__(self, file):
30 self.__d = {}
31 sectiondata = None
32 for x in file.readlines():
33 x = x.replace("\r\n", "").replace("\n", "")
34 xs = x.strip()
35 if xs == "" or xs.startswith("#"):
36 continue
37
38 if x.startswith("[") and x.endswith("]"):
39 sectiondata = {}
40 keydata = []
41 self.__d[x[1:-1]] = (sectiondata, keydata)
42 continue
43
44 i = x.index("=")
45 key = x[:i]
46 sectiondata[key] = x[i+1:]
47 keydata.append((key, sectiondata[key]))
48
49 def has_key(self, key):
50 return self.__d.has_key(key)
51
52 def setdefault(self, key, value=None):
53 if self.has_key(key):
54 return self[key]
55 return value
56
57 def __getitem__(self, key):
58 return self.__d[key][0]
59
60 def keys(self, key):
61 return self.__d[key][1]
62
63class ConfigureIniParser(IniParser):
64 def __init__(self, file):
65 IniParser.__init__(self, file)
66
67 self.modules = {}
68 self.buildorder = []
69 self.updatemodules(self.keys("modules"))
70
71 self.selectlibs = {}
72 for k, v in self.setdefault("selectlibs", {}).items():
73 self.selectlibs[k] = v.split()
74
75 libs = self.setdefault("core", {"libs": ""})["libs"].split()
76 libs = [(x, self["lib%s" % x]) for x in libs]
77 for k, v in libs:
78 v.setdefault("libname", k)
79 v.setdefault("format", "lib%s.so")
80 v.setdefault("headerpath", None)
81 v.setdefault("additionaldirs", None)
82 v.setdefault("alwayspresent", None)
83
84 if v["additionaldirs"]:
85 v["additionaldirs"] = v["additionaldirs"].split()
86 v["libname"] = v["libname"].split()
87
88 self.libs = dict(libs)
89 self.searchincludes = self["search"]["include"].split()
90 self.searchlibs = self["search"]["lib"].split()
91 self.makes = {}
92 for k, v in self.setdefault("makes", {}).items():
93 self.makes[k] = v
94
95 self.osflags = {}
96 if self.has_key("osvars"):
97 for k, v in self.keys("osvars"):
98 self.osflags.setdefault(k, []).append(v)
99
100 self.subs = [("-%s-" % k, v) for k, v in self.setdefault("subs", {}).items()]
101 self.options = self["options"]
102
103 def configprint(self):
104 vprint("--- config --------------------------------------------")
105 for x in dir(self):
106 if x.startswith("_"):
107 continue
108 v = getattr(self, x)
109 if not isinstance(v, list) and not isinstance(v, dict):
110 continue
111 vprint("%-50s: %s" % (`x`, `v`))
112 vprint("--- config --------------------------------------------")
113
114 def updatemodules(self, x, workspace = None):
115 for k, v in x:
116 if workspace and workspace != ".":
117 name = workspace + "/" + k
118 else:
119 name = k
120 self.buildorder.append(name)
121 self.modules[name] = v.split()
122
123class MultiConfigureIniParser(ConfigureIniParser):
124 def __init__(self, files):
125 ConfigureIniParser.__init__(self, files[0][1])
126
127 for workspace, file in files[1:]:
128 c2 = IniParser(file)
129 if c2.has_key("modules"):
130 self.updatemodules(c2.keys("modules"), workspace)
131
132 if c2.has_key("search"):
133 if c2["search"].has_key("include"):
134 self.searchincludes = self.searchincludes + c2["search"]["include"].split()
135 if c2["search"].has_key("lib"):
136 self.searchlibs = self.searchlibs + c2["search"]["lib"].split()
137
138 if c2.has_key("options"):
139 self.options.update(c2["options"])
140
141def librarycheck(libraries, includes, libs):
142 def findlibrarypaths(library, x, includes, libs):
143 if x["alwayspresent"]:
144 return True
145 def locate(needle, haystack):
146 vprint()
147 vprint("searching for %s in: %s" % (needle, haystack))
148
149 for x in haystack:
150 p = os.path.join(x, needle)
151 if os.path.exists(p):
152 return x
153
154 found = []
155
156 def mergepaths(a, b):
157 ret = list(a[:])
158 for x in a:
159 for y in b:
160 ret.append(os.path.join(x, y))
161 return ret
162
163 libname = x["libname"]
164
165 searchdir = mergepaths(includes, libname)
166 incpath = locate(x["include"], searchdir)
167 if not incpath:
168 return
169
170 if x["headerpath"]:
171 incpath = os.path.abspath(os.path.join(incpath, x["headerpath"]))
172
173 searchdir = mergepaths(libs, libname)
174 if x["additionaldirs"]:
175 searchdir = mergepaths(searchdir, [""] + x["additionaldirs"])
176
177 for l in x.has_key("soname") and [x["soname"]] or libname:
178 libpath = locate(x["format"] % l, searchdir)
179 if libpath:
180 return libpath, l, incpath
181
182 libsfound = []
183 output = []
184
185 for k in libraries.keys():
186 iprint("checking for %s... " % k)
187 ret = findlibrarypaths(k, libraries[k], includes, libs)
188 if not ret:
189 lprint("failed")
190 continue
191
192 libsfound.append(k)
193
194 if ret is not True:
195 libpath, libname, incpath = ret
196 uk = k.upper()
197
198 x = libraries[k]
199 libline = "LIB%s=-L%s -l%s" % (uk, libpath, libname)
200 incline = "INC%s=-I%s" % (uk, incpath)
201 output.append(libline)
202 output.append(incline)
203
204 lprint("ok")
205 if ret is not True:
206 vprint("library path: %s" % libline)
207 vprint("include path: %s" % incline)
208
209 return output, libsfound
210
211def systemcheck(makes, osflags):
212 output = []
213
214 iprint("checking for system... ")
215 system = platform.system()
216 lprint(system)
217
218 iprint("checking for make version... ")
219 make = makes.setdefault(system, "gmake")
220 lprint(make)
221
222 for v in osflags.setdefault(system, []):
223 output.append(v)
224 return output, make
225
226def modulecheck(modules, libsfound, buildorder, selectlibs, overrides):
227 defaultselections = {}
228
229 for k, v in selectlibs.items():
230 if overrides.has_key(k):
231 assert overrides[k] in libsfound
232 libsfound.append(k)
233 defaultselections[k] = overrides[k]
234 else:
235 for x in v:
236 if x in libsfound:
237 libsfound.append(k)
238 defaultselections[k] = x
239 break
240
241 building = set()
242 for k, v in modules.items():
243 for x in v:
244 if x not in libsfound:
245 break
246 else:
247 building.add(k)
248
249 notfound = set(filter(lambda x: not os.path.exists(x), building))
250
251 cantbuild = set(modules) - building
252 building = building - notfound
253
254 orderedbuild = []
255 for x in buildorder:
256 if x in building:
257 orderedbuild.append(x)
258
259 build = ["DIRS=%s" % (" ".join(orderedbuild))]
260 return build, orderedbuild, notfound, cantbuild, defaultselections
261
262def writemakefile(inc, out, appendstart=None, appendend=None, silent=False):
263 p = open(out, "w")
264 p.write("## AUTOMATICALLY GENERATED -- EDIT %s INSTEAD\n\n" % inc)
265 if appendstart:
266 p.write("\n".join(appendstart))
267 p.write("\n")
268
269 f = open(inc, "r")
270 try:
271 for l in f.readlines():
272 p.write(l)
273 finally:
274 f.close()
275
276 if appendend:
277 p.write("\n".join(appendend))
278 p.write("\n")
279
280 p.close()
281 if not silent:
282 lprint("configure: wrote %s" % out)
283
284def writeconfigh(file, modules, defaultselections):
285 f = open(file, "w")
286 f.write("/* AUTOMATICALLY GENERATED -- DO NOT EDIT */\n")
287
288 for x in modules:
289 f.write("#define HAVE_%s\n" % x.upper())
290 for k, v in defaultselections.items():
291 f.write("#define USE_%s_%s\n" % (k.upper(), v.upper()))
292 f.close()
293
294 lprint("configure: wrote %s" % file)
295
296def configure(config, selectoverrides, workspaces):
297 # figure out make and any custom OS flags
298 flags, make = systemcheck(config.makes, config.osflags)
299
300 # find the libraries/includes we have and their paths
301 f, libsfound = librarycheck(config.libs, config.searchincludes, config.searchlibs)
302 for k, v in selectoverrides.items():
303 if not v in libsfound:
304 lprint("configure: can't set %s to %s as %s was not found." % (k, v, v))
305 return
306
307 flags = flags + f
308
309 # see which modules we can build
310 buildlines, building, notfound, cantbuild, defaultselections = modulecheck(config.modules, libsfound, config.buildorder, config.selectlibs, selectoverrides)
311
312 for k, v in defaultselections.items():
313 lprint("configure: selected %s as %s" % (v, k))
314 flags.append("LIB%s=$(LIB%s)" % (k.upper(), v.upper()))
315 flags.append("INC%s=$(INC%s)" % (k.upper(), v.upper()))
316
317 writemakefile("build.mk.in", "build.mk", appendend=flags + ["=".join(x) for x in config.options.items()] + ["DIRS=" + " ".join(building), "WORKSPACES=" + " ".join(workspaces)])
318
319 writeconfigh("config.h", libsfound, defaultselections)
320
321 lprint("configure: selected: %s" % " ".join(building))
322 if len(notfound) > 0:
323 lprint("configure: couldn't find: %s" % " ".join(notfound))
324
325 if len(cantbuild) > 0:
326 lprint("configure: can't select: %s" % " ".join(cantbuild))
327
328def usage():
329 print
330 print " Usage: %s [-h] [-v] [options]" % sys.argv[0]
331 print
332 print " Additional options are:"
333 for k, v in validopts.items():
334 print " --with-%s=[%s]" % (v[0], "|".join(v[1]))
335
336 print " -L [additional lib dir]"
337 print " -I [additional include dir]"
338 print " -m [additional module]"
339 print " -v: verbose"
340
341def main(workspacesfile):
342 global LOG, VERBOSE
343
344 workspacesconfig = IniParser(open(workspacesfile, "r"))
345
346 files = []
347 workspaces = []
348
349 for workspace in ["."] + workspacesconfig["workspaces"].keys():
350 path = workspace + "/configure.ini"
351 if os.path.exists(path):
352 print "found workspace: %s" % workspace
353 workspaces.append(workspace)
354 files.append( (workspace, open(path, "r")) )
355
356 local_path = workspace + "/configure.ini.local"
357 if os.path.exists(local_path):
358 files.append( (workspace, open(local_path, "r")) )
359
360 config = MultiConfigureIniParser(files)
361
362 mopts = []
363 validopts = {}
364 for k, v in config.selectlibs.items():
365 mopts.append("with-%s=" % k)
366 validopts["--with-%s" % k] = (k, v)
367
368 try:
369 opts, args = getopt.getopt(sys.argv[1:], "hvcI:L:m:", mopts)
370 except getopt.GetoptError, err:
371 print str(err)
372 usage()
373 return
374
375 overrides = {}
376 libs = []
377 includes = []
378 modules = []
379
380 for o, a in opts:
381 if validopts.has_key(o):
382 v = validopts[o]
383 if not a in v[1]:
384 usage()
385 return
386 overrides[v[0]] = a
387 elif o == "-h":
388 usage()
389 return
390 elif o == "-v":
391 VERBOSE = True
392 elif o == "-L":
393 libs.append(a)
394 elif o == "-I":
395 includes.append(a)
396 elif o == "-m":
397 modules.append(a)
398 else:
399 assert False, "bad option"
400
401 LOG = open(".configure.log", "w")
402 vprint("invoked as: %r" % sys.argv)
403 config.updatemodules([(x, "") for x in modules])
404 config.searchlibs.extend(libs)
405 config.searchincludes.extend(includes)
406 config.configprint()
407
408 configure(config, overrides, workspaces)
409
410if __name__ == "__main__":
411 main("workspaces.ini")