# ChangeLog for gentoo/src/catalyst
# Copyright 2002-2003 Gentoo Technologies, Inc.; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo/src/catalyst/ChangeLog,v 1.7 2003/10/28 14:00:56 drobbins Exp $
-
+# $Header: /var/cvsroot/gentoo/src/catalyst/ChangeLog,v 1.8 2003/10/28 17:09:28 drobbins Exp $
+
+ 28 Oct 2003; Daniel Robbins <drobbins@gentoo.org>: Significant rework of code
+ structure. Everything is falling nicely into place.
+
28 Oct 2003; Daniel Robbins <drobbins@gentoo.org>: Exception handling fully-
integrated into current prototype code.
def __init__(self,myspec):
builder.generic.__init__(self,myspec)
self.settings["mainarch"]="x86"
+ self.settings["CHROOT"]="chroot"
class arch_x86(generic_x86):
"builder class for generic x86 (486+)"
generic_x86.__init__(self,myspec)
self.settings["CFLAGS"]="-O2 -mcpu=i686 -fomit-frame-pointer"
+class arch_i386(generic_x86):
+ def __init__(self,myspec):
+ generic_x86.__init__(self,myspec)
+ self.settings["CFLAGS"]="-O2 -march=i386 -fomit-frame-pointer"
+ self.settings["CHOST"]="i386-pc-linux-gnu"
+
+class arch_i486(generic_x86):
+ def __init__(self,myspec):
+ generic_x86.__init__(self,myspec)
+ self.settings["CFLAGS"]="-O2 -march=i486 -fomit-frame-pointer"
+ self.settings["CHOST"]="i486-pc-linux-gnu"
+
+class arch_i586(generic_x86):
+ def __init__(self,myspec):
+ generic_x86.__init__(self,myspec)
+ self.settings["CFLAGS"]="-O2 -march=i586 -fomit-frame-pointer"
+ self.settings["CHOST"]="i586-pc-linux-gnu"
+
+class arch_pentium_mmx(arch_i586):
+ def __init__(self,myspec):
+ arch_i586.__init__(self,myspec)
+ self.settings["HOSTUSE"]=["mmx"]
+
+class arch_i686(generic_x86):
+ def __init__(self,myspec):
+ generic_x86.__init__(self,myspec)
+ self.settings["CFLAGS"]="-O2 -march=i686 -fomit-frame-pointer"
+ self.settings["CHOST"]="i686-pc-linux-gnu"
+
+class arch_athlon(generic_x86):
+ def __init__(self,myspec):
+ generic_x86.__init__(self,myspec)
+ self.settings["CFLAGS"]="-O2 -march=athlon -fomit-frame-pointer"
+ self.settings["CHOST"]="i686-pc-linux-gnu"
+ self.settings["HOSTUSE"]=["mmx","3dnow"]
+
+class arch_athlon_xp(generic_x86):
+ #this handles XP and MP processors
+ def __init__(self,myspec):
+ generic_x86.__init__(self,myspec)
+ self.settings["CFLAGS"]="-O2 -march=athlon-xp -fomit-frame-pointer"
+ self.settings["CHOST"]="i686-pc-linux-gnu"
+ self.settings["HOSTUSE"]=["mmx","3dnow"]
+
class arch_pentium4(generic_x86):
- "builder class for Pentium 4"
def __init__(self,myspec):
generic_x86.__init__(self,myspec)
self.settings["CFLAGS"]="-O2 -march=pentium4 -fomit-frame-pointer -finline-functions -finline-limit=800"
self.settings["CHOST"]="i686-pc-linux-gnu"
self.settings["HOSTUSE"]=["mmx","sse"]
+class arch_pentium3(generic_x86):
+ def __init__(self,myspec):
+ generic_x86.__init__(self,myspec)
+ self.settings["CFLAGS"]="-O2 -march=pentium3 -fomit-frame-pointer -finline-functions -finline-limit=800"
+ self.settings["CHOST"]="i686-pc-linux-gnu"
+ self.settings["HOSTUSE"]=["mmx","sse"]
+
def register(foo):
"Inform main catalyst program of the contents of this plugin."
- foo.update({"pentium4":arch_pentium4,"x86":arch_x86})
+ foo.update({"pentium4":arch_pentium4,"x86":arch_x86,"i386":arch_i386,"i486":arch_i486,"i586":arch_i586,"i686":arch_i686,"athlon":arch_athlon,
+ "athlon-xp":arch_athlon_xp,"athlon-mp":arch_athlon_xp,"pentium3":arch_pentium3,"pentium-mmx":arch_pentium_mmx})
if len(sys.argv)==1 or sys.argv[1] in ["-h","--help"]:
usage()
sys.exit(1)
-
-def arg_parse(mydict, myvalids):
- "very wimpy argument parsing, just for the prototype"
- for x in sys.argv[1:]:
- foo=string.split(x,"=")
- if len(foo)!=2:
- die("Invalid arg syntax: "+x)
- else:
- if foo[0] not in myvalids:
- die("Invalid arg name: "+foo[0])
- mydict[foo[0]]=foo[1]
-
-def spec_dump(myspec):
- for x in myspec.keys():
- print x+": "+repr(myspec[x])
-
"""
Overview of catalyst operation
==============================
be a standard python dictionary. This spec dictionary contains all relevant
build-related information.
-* The spec object is passed to the appropriate subarch builder constructor.
- The subarch builder constructor updates the spec object with variables
- relevant to the sub-arch (pentium4, g3, etc.)
-
* The spec object is passed to the appropriate target constructor.
The target constructor updates the spec object to contain data relevant
to the particular target (stage1, stage3, grp, etc.)
#map current machine information from uname() to the mainarch we are running
#under
-machinemap={ "i386" : "x86",
- "i486" : "x86",
- "i586" : "x86",
- "i686" : "x86",
- "x86_64" : "amd64"
- }
-
-# map the mainarch we are running under to the mainarches we support for
-# building stages and LiveCDs. (for example, on amd64, we can build stages for
-# x86 or amd64.
-
-targetmap={ "x86" : ["x86"],
- "amd64" : ["x86","amd64"]
- }
-
-mymachine=os.uname()[4]
-if not machinemap.has_key(mymachine):
- die("Unknown machine type: "+mymachine)
-hostarch=machinemap[mymachine]
-print "Host architecture:",hostarch
-print "Supported architectures for targets:",string.join(targetmap[hostarch])
-print "Loading plugins:",
-archmap={}
-subarchmap={}
-for x in targetmap[hostarch]:
- fh=open("arch/"+x+".py")
- #this next line loads the plugin as a module and assigns it to archmap[x]
- archmap[x]=imp.load_module(x,fh,"arch/"+x+".py",(".py","r",imp.PY_SOURCE))
- #this next line registers all the subarches supported in the plugin
- archmap[x].register(subarchmap)
- fh.close()
- print x,
-print
-print "Available subarches:",string.join(subarchmap.keys())
-
import targets
targetmap={}
targets.register(targetmap)
#non-root callers can't go any further than here.
die("This script requires root privileges to operate.")
-#the spec begins!
-validspec=["version_stamp","target","subarch","rel_type","rel_version","snapshot","source_subpath"]
myspec={}
-
-"""
-local variables from spec:
-
-version_stamp 20031016 user (from spec)
-target stage3 user (from spec)
-subarch pentium4 user (from spec)
-rel_type default user (from spec) (was BUILDTYPE)
-rel_version 1.4 user (from spec) (was MAINVERSION)
-snapshot 20031016 user (from spec)
-source_subpath default-x86-1.4/stage2-pentium4-20031016 user (from spec)
-"""
-
-arg_parse(myspec,validspec)
-#need to verify that we have all required args here. Leaving this out for the prototype.
-if myspec["subarch"] not in subarchmap.keys():
- die("Sub-arch "+myspec["subarch"]+" not available.")
-
-#call builder constructor:
-mybuilder=subarchmap[myspec["subarch"]](myspec)
-if myspec["target"] not in targetmap.keys():
- die("Target "+myspec["target"]+" not available.")
-
#these would come from /etc/catalyst.conf:
myspec["storedir"]="/var/tmp/catalyst"
myspec["sharedir"]="/usr/share/catalyst"
myspec["distdir"]="/usr/portage/distfiles"
myspec["portdir"]="/usr/portage"
-#call target constructor:
-mytarget=targetmap[myspec["target"]](myspec)
-print
-spec_dump(myspec)
+#all the main program needs to do is figure out the target. The rest of the args go to the
+#target constructor
-mytarget.run()
+#call target constructor, pass our "myspec" settings as well as cmdline arguments for parsing
-#to test this program, type:
+addlargs={}
+arg_parse(myspec,addlargs)
+if not targetmap.has_key(myspec["target"]):
+ raise CatalystError,"Target \""+myspec["target"]+"\" not available."
+mytarget=targetmap[myspec["target"]](myspec,addlargs)
+mytarget.run()
# ./catalyst subarch=pentium4 version_stamp=20031016 target=stage3 rel_type=default rel_version=1.4 snapshot=20031016 source_subpath=default-x86-1.4/stage2-pentium4-20031016
-import sys
+import sys,string
+
+config_file_values=["storedir","sharedir","distdir","portdir"]
class CatalystError(Exception):
def __init__(self, message):
def warn(msg):
print "catalyst: "+msg
+def arg_parse(mydict,remaining={}):
+ global config_file_values
+ for x in sys.argv[1:]:
+ foo=string.split(x,"=")
+ if len(foo)!=2:
+ raise CatalystError, "Invalid arg syntax: "+x
+ remaining[foo[0]]=foo[1]
+ if not remaining.has_key("target"):
+ raise CatalystError, "Required value \"target\" not specified."
+ mydict["target"]=remaining["target"]
+ for x in config_file_values:
+ if not mydict.has_key(x):
+ raise CatalystError, "Required config file value \""+x+"\" not found."
+
+
+def addl_arg_parse(myspec,addlargs,requiredspec,validspec):
+ "helper function to help targets parse additional arguments"
+ global config_file_values
+ for x in addlargs.keys():
+ if x not in validspec and x not in config_file_values:
+ raise CatalystError, "Argument \""+x+"\" not recognized."
+ else:
+ myspec[x]=addlargs[x]
+ for x in requiredspec:
+ if not myspec.has_key(x):
+ raise CatalystError, "Required argument \""+x+"\" not specified."
+
+def spec_dump(myspec):
+ for x in myspec.keys():
+ print x+": "+repr(myspec[x])
+
-import os,stat
+import os,stat,string,imp
from catalyst_support import *
class generic_target:
- def __init__(self,myspec):
+ def __init__(self,myspec,addlargs):
+ addl_arg_parse(myspec,addlargs,self.required_values,self.valid_values)
self.settings=myspec
pass
class generic_stage_target(generic_target):
- def __init__(self,myspec):
- generic_target.__init__(self,myspec)
- #we'd want to make sure we have all the settings we need here
+ def __init__(self,myspec,addlargs):
+
+ self.required_values=["version_stamp","target","subarch","rel_type","rel_version","snapshot","source_subpath"]
+ self.valid_values=self.required_values
+ generic_target.__init__(self,addlargs,myspec)
+
+ #ensure we have all required user-supplied settings before proceeding
+ for x in requiredspec:
+ if not self.settings.has_key(x):
+ raise CatalystError, "Required value \""+x+"\" not specified."
+
+ # map the mainarch we are running under to the mainarches we support for
+ # building stages and LiveCDs. (for example, on amd64, we can build stages for
+ # x86 or amd64.
+
+ targetmap={ "x86" : ["x86"],
+ "amd64" : ["x86","amd64"]
+ }
+
+ machinemap={ "i386" : "x86",
+ "i486" : "x86",
+ "i586" : "x86",
+ "i686" : "x86",
+ "x86_64" : "amd64"
+ }
+
+
+ mymachine=os.uname()[4]
+ if not machinemap.has_key(mymachine):
+ raise CatalystError, "Unknown machine type "+mymachine
+ self.settings["hostarch"]=machinemap[mymachine]
+ print "Host architecture:",self.settings["hostarch"]
+ print "Supported architectures for targets:",string.join(targetmap[self.settings["hostarch"]])
+ print "Loading all valid plugins for this machine:",
+ self.archmap={}
+ self.subarchmap={}
+ for x in targetmap[self.settings["hostarch"]]:
+ fh=open("arch/"+x+".py")
+ #this next line loads the plugin as a module and assigns it to archmap[x]
+ self.archmap[x]=imp.load_module(x,fh,"arch/"+x+".py",(".py","r",imp.PY_SOURCE))
+ #this next line registers all the subarches supported in the plugin
+ self.archmap[x].register(self.subarchmap)
+ fh.close()
+ print x,
+ print
+ print "Available subarches:",string.join(self.subarchmap.keys())
+ #call arch constructor, pass our settings
+ self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
self.settings["target_subpath"]=self.settings["rel_type"]+"-"+self.settings["mainarch"]+"-"+self.settings["rel_version"]
self.settings["target_subpath"]+="/"+self.settings["target"]+"-"+self.settings["subarch"]+"-"+self.settings["version_stamp"]
st=self.settings["storedir"]
retval=os.system("tar xjpf "+self.settings["source_path"]+" -C "+self.settings["chroot_path"])
if retval!=0:
raise CatalystError,"Error unpacking tarball"
- for x in [[self.settings["portdir"],"/usr/portage"],[self.settings["distdir"],"/usr/portage/distfiles"],
+ retval=os.system("tar xjpf "+self.settings["snapshot_path"]+" -C "+self.settings["chroot_path"]+"/usr")
+ if retval!=0:
+ raise CatalystError,"Error unpacking snapshot"
+ for x in [[self.settings["distdir"],"/usr/portage/distfiles"],
["/proc","/proc"],["/dev","/dev"]]:
- retval=os.system("mount --bind "+x[0]+" "+x[1])
- if not retval:
+ if not os.path.exists(self.settings["chroot_path"]+x[1]):
+ os.makedirs(self.settings["chroot_path"]+x[1])
+
+ retval=os.system("mount --bind "+x[0]+" "+self.settings["chroot_path"]+x[1])
+ if retval!=0:
self.unbind()
raise CatalystError,"Couldn't bind mount "+x[0]
def unbind(self):
- pass
+ for x in ["/usr/portage/distfiles","/proc","/dev"]:
+ retval=os.system("umount "+self.settings["chroot_path"]+x)
+ if retval!=0:
+ warning("Couldn't umount bind mount: "+self.settings["chroot_path"]+x)
def setup(self):
#setup will leave everything in unbound state if there is a failure
self.unbind()
class snapshot_target(generic_target):
- def __init__(self):
+ def __init__(self,myspec,addlargs):
+ self.valid_values=["version_stamp","target"]
+ self.required_values=self.valid_values
+ generic_target.__init__(myspec,addlargs)
+
+ self.settings=myspec
+ if not self.settings.has_key("version_stamp"):
+ raise CatalystError, "Required value \"version_stamp\" not specified."
self.settings["target_subpath"]="portage-"+self.settings["version_stamp"]
st=self.settings["storedir"]
self.settings["snapshot_path"]=st+"/snapshots/"+self.settings["target_subpath"]+".tar.bz2"
self.settings["tmp_path"]=st+"/tmp/"+self.settings["target_subpath"]
def setup(self):
- #nothing to do here
- pass
+ x=self.settings["storedir"]+"/snapshots"
+ if not os.path.exists(x):
+ os.makedirs(x)
def run(self):
- print "Creating Portage tree snapshot "+snapversion+" from "+portdir+"..."
- mytmp=self.settings["tmp_path"]+"/"+self.settings["target_subpath"]
+ self.setup()
+ print "Creating Portage tree snapshot "+self.settings["version_stamp"]+" from "+self.settings["portdir"]+"..."
+ mytmp=self.settings["tmp_path"]
if os.path.exists(mytmp):
retval=os.system("rm -rf "+mytmp)
if retval != 0:
if retval != 0:
raise CatalystError,"Snapshot failure"
print "Compressing Portage snapshot tarball..."
- retval=os.system("( cd "+mytmp+"; tar cjf "+self.settings["snapshot_path"]+"/portage-"+self.settings["snapversion"]+".tar.bz2 portage )")
+ retval=os.system("tar cjf "+self.settings["snapshot_path"]+" -C "+mytmp+" portage")
if retval != 0:
raise CatalystError,"Snapshot creation failure"
self.cleanup()
raise CatalystError,"Snapshot cleanup failure"
class stage1_target(generic_stage_target):
- def __init__(self,spec):
- generic_stage_target.__init__(self,spec)
- pass
+ def __init__(self,spec,addlargs):
+ generic_stage_target.__init__(self,spec,addlargs)
class stage2_target(generic_stage_target):
- def __init__(self,spec):
- generic_stage_target.__init__(self,spec)
- pass
+ def __init__(self,spec,addlargs):
+ generic_stage_target.__init__(self,spec,addlargs)
class stage3_target(generic_stage_target):
- def __init__(self,spec):
- generic_stage_target.__init__(self,spec)
- pass
+ def __init__(self,spec,addlargs):
+ generic_stage_target.__init__(self,spec,addlargs)
class grp_target(generic_stage_target):
- def __init__(self,spec):
- generic_target.__init__(self,spec)
- pass
+ def __init__(self,spec,addlargs):
+ generic_stage_target.__init__(self,spec,addlargs)
class livecd_target(generic_stage_target):
- def __init__(self):
- generic_target.__init__(self)
- pass
+ def __init__(self,spec,addlargs):
+ generic_target.__init__(self,spec,addlargs)
def register(foo):
foo.update({"stage1":stage1_target,"stage2":stage2_target,"stage3":stage3_target,