1 # Copyright (C) 2007-2008 Movial Oy
2 # Authors: Kalle Vahlman <kalle.vahlman@movial.fi>
3 # Timo Savola <tsavola@movial.fi>
12 from config import config
13 from config import parse as config_parse
18 image_type_default = 'jffs2'
21 parser = optparse.OptionParser(usage='%prog [<options>]')
25 help='do not clean env.faked and stripped directory',
26 dest='clean', action='store_false', default=True)
30 help='generate only a filesystem image',
31 dest='image_only', action='store_true')
35 help='type of generated filesystem image: %s [default: %s]' % \
36 (', '.join(image_type_list), image_type_default),
37 dest='image_type', metavar='TYPE',
38 choices=image_type_list, default=image_type_default)
41 '-r', '--rootfs-only',
42 help='generate only a stripped archive',
43 dest='rootfs_only', action='store_true')
46 '-d', '--devrootfs-only',
47 help='generate only an archive with development files',
48 dest='devrootfs_only', action='store_true')
50 opts, args = parser.parse_args()
55 config_parse('config.local')
56 config_parse('config')
57 config_parse('boards')
58 config_parse('rootfs')
60 f = os.popen('sb-conf cu')
64 build = Builder(target.strip())
65 build.include_paths(config.include_paths)
66 build.include_files(config.include_files)
67 build.filter_paths(config.exclude_paths)
68 build.filter_files(config.exclude_files)
69 build.filter_expressions(config.exclude_expressions)
70 build.add_paths(config.created_paths)
71 build.set_devices(config.devices)
72 build.set_change_owner(config.change_owner)
73 build.set_erase_size(config.boards[config.board].flash_erase_size)
74 build.set_pad_size(config.boards[config.board].flash_pad_size)
77 build.generate(opts.clean, build_target="rootfs")
79 build.generate(opts.clean, build_target=opts.image_type)
80 elif opts.devrootfs_only:
81 build.generate(opts.clean, build_target="devrootfs")
83 build.generate(opts.clean, build_target="all")
85 class Builder(object):
91 mknod = "fakeroot -i /tmp/env.faked -s /tmp/env.faked mknod"
92 chmod = "fakeroot -i /tmp/env.faked -s /tmp/env.faked chmod"
93 chown = "fakeroot -i /tmp/env.faked -s /tmp/env.faked chown"
94 mkfs = "fakeroot -i /tmp/env.faked -s /tmp/env.faked mkfs.jffs2"
95 tar = "fakeroot -i /tmp/env.faked -s /tmp/env.faked tar"
96 flash_erase_size = 0x4000
97 flash_pad_size = 0x3e00000
106 def __init__(self, mytarget):
107 self.target = mytarget
109 def include_paths(self, paths):
110 old_dir = os.getcwd()
113 # Traverse include_paths hierarchies and grab all files there
115 for root, dirs, files in os.walk(self.target + path):
117 self.file_list.append("%s/%s" % (root, f))
119 self.file_list.append(root)
123 def include_files(self, files):
124 old_dir = os.getcwd()
127 # Append included individual files
129 self.file_list.append(self.target + f)
133 def filter_paths(self, paths):
134 # Filter out files in excluded paths
135 for f in self.file_list:
137 if f == self.target + d or f.startswith(self.target + d + '/'):
138 self.remove_list.append(f)
140 def filter_files(self, files):
141 # Filter out excluded files
143 self.remove_list.append(self.target + f)
145 def filter_expressions(self, expressions):
146 # Filter out files matching excluded patterns
147 compiled_patterns = []
148 for pattern_str in expressions:
149 compiled_patterns.append(re.compile(pattern_str))
151 for f in self.file_list:
152 for pattern in compiled_patterns:
153 if pattern.search(f):
154 self.remove_list.append(f)
156 def add_paths(self, paths):
158 self.created_paths.append(path)
160 def set_devices(self, devices):
161 if devices is not None:
162 self.devices = devices
164 def set_change_owner(self, change_owner):
165 if change_owner is not None:
166 self.change_owner= change_owner
168 def set_erase_size(self, size):
170 self.flash_erase_size = size
172 def set_pad_size(self, size):
174 self.flash_pad_size = size
176 def generate(self, clean, build_target="all"):
177 copy_list = self.file_list
179 for f in self.remove_list:
185 n_files = len(copy_list)*1.0
186 current_percent = 0.0
189 old_dir = os.getcwd()
192 if os.path.exists(os.path.join(self.builddir, self.target)):
193 print "%s exists, please remove it and try again" % os.path.join(self.builddir, self.target)
196 # Copy the wanted files, strip binaries
197 print "Copying files..."
201 path = os.path.join(self.builddir, os.path.dirname(f))
205 if e.errno == errno.EEXIST:
208 if os.path.islink(f):
209 link_dest = os.readlink(f)
210 os.symlink(link_dest, os.path.join(self.builddir, f))
211 elif os.path.isdir(f):
213 os.makedirs(os.path.join(self.builddir, f))
215 if e.errno == errno.EEXIST:
219 if not f.endswith(".ko"):
220 os.system(self.strip + " " + os.path.join(path,os.path.basename(f)) + " &> /dev/null")
222 if (current_file/n_files)*100 > current_percent:
223 current_percent += 10.0
224 print "%0.1f%%" % current_percent,
229 # Create extra directory structure
230 print "\nCreating extra directories..."
231 for d in self.created_paths:
234 path = os.path.join(self.builddir, self.target, d)
238 if e.errno == errno.EEXIST:
241 # Remove always the fakeroot environment.
242 if os.path.exists("/tmp/env.faked"):
243 os.remove("/tmp/env.faked")
244 os.system("touch /tmp/env.faked")
246 # Create device nodes
247 print "Creating device nodes..."
248 for d in self.devices.keys():
250 if len(self.devices[d]) == 3:
251 device_type,major,minor = self.devices[d]
253 device_type,major,minor,mode = self.devices[d]
254 os.system("%s -m %s %s/%s/dev/%s %s %i %i" % (self.mknod, mode, self.builddir, self.target, d, device_type, major, minor))
257 print "Adjusting ownerships and permissions..."
258 # Make the whole fs root-owned
259 os.system("%s root.root -R %s/%s" % (self.chown, self.builddir, self.target))
262 os.system("%s go-r %s/%s/etc/ssh*key*" % (self.chmod, self.builddir, self.target))
264 # For /var/empty (sshd requires this):
265 os.system("%s go-rw /%s/%s/var/empty" % (self.chmod, self.builddir, self.target))
267 # /dev/null needs to be writable by all:
268 os.system("%s a+rw /%s/%s/dev/null" % (self.chmod, self.builddir, self.target))
270 # Set non-root owners
271 print "Setting non-root ownerships..."
272 for d in self.change_owner.keys():
276 if os.path.exists(os.path.join(self.builddir, self.target, dir)):
277 user,group = self.change_owner[d]
278 os.system("%s %s.%s -R %s/%s/%s " % (self.chown, user, group, self.builddir, self.target, dir))
280 if build_target is "all" or build_target is "rootfs":
281 print "Creating a rootfs..."
282 os.system("%s -c --one-file-system -C %s/%s -z -f %s/%s.tgz ." % (self.tar, self.builddir, self.target, self.builddir, self.target))
283 if build_target is "all" or build_target is "jffs2":
284 print "Creating a root image..."
285 os.system("%s -p%d -n -e%d -r %s/%s -o %s/%s.jffs2" % (self.mkfs, self.flash_pad_size, self.flash_erase_size, self.builddir, self.target, self.builddir, self.target))
286 if build_target is "all" or build_target is "devrootfs":
287 print "Creating a rootstrap..."
288 os.system("%s -c --one-file-system -C /targets/%s -z -f %s/%s-rootstrap.tgz ." % ("tar", self.target, self.builddir, self.target))
292 print "Build finished:"
293 if build_target is "all" or build_target is "rootfs":
294 s = os.stat(self.builddir + "/" + self.target + ".tgz");
295 print "\t%s/%s.tgz\t%0.2f MiB" % (self.builddir, self.target, s.st_size/1024.0/1024.0)
296 if build_target is "all" or build_target is "jffs2":
297 s = os.stat(self.builddir + "/" + self.target + ".jffs2");
298 print "\t%s/%s.jffs2\t%0.2f MiB" % (self.builddir, self.target, s.st_size/1024.0/1024.0)
299 if build_target is "all" or build_target is "devrootfs":
300 s = os.stat(self.builddir + "/" + self.target + "-rootstrap.tgz");
301 print "\t%s/%s-rootstrap.tgz\t%0.2f MiB" % (self.builddir, self.target, s.st_size/1024.0/1024.0)
305 os.remove("/tmp/env.faked")
306 os.system("rm -rf %s/%s" % (self.builddir, self.target))