wic 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #!/usr/bin/env python
  2. # ex:ts=4:sw=4:sts=4:et
  3. # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
  4. #
  5. # Copyright (c) 2013, Intel Corporation.
  6. # All rights reserved.
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License version 2 as
  10. # published by the Free Software Foundation.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License along
  18. # with this program; if not, write to the Free Software Foundation, Inc.,
  19. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. #
  21. # DESCRIPTION 'wic' is the OpenEmbedded Image Creator that users can
  22. # use to generate bootable images. Invoking it without any arguments
  23. # will display help screens for the 'wic' command and list the
  24. # available 'wic' subcommands. Invoking a subcommand without any
  25. # arguments will likewise display help screens for the specified
  26. # subcommand. Please use that interface for detailed help.
  27. #
  28. # AUTHORS
  29. # Tom Zanussi <tom.zanussi (at] linux.intel.com>
  30. #
  31. __version__ = "0.2.0"
  32. # Python Standard Library modules
  33. import os
  34. import sys
  35. import optparse
  36. import logging
  37. from distutils import spawn
  38. # External modules
  39. scripts_path = os.path.abspath(os.path.dirname(__file__))
  40. lib_path = scripts_path + '/lib'
  41. sys.path.insert(0, lib_path)
  42. bitbake_exe = spawn.find_executable('bitbake')
  43. if bitbake_exe:
  44. bitbake_path = os.path.join(os.path.dirname(bitbake_exe), '../lib')
  45. sys.path.insert(0, bitbake_path)
  46. from bb import cookerdata
  47. from bb.main import bitbake_main, BitBakeConfigParameters
  48. else:
  49. bitbake_main = None
  50. from wic.utils.oe.misc import get_bitbake_var, BB_VARS
  51. from wic.utils.errors import WicError
  52. from wic import engine
  53. from wic import help as hlp
  54. def rootfs_dir_to_args(krootfs_dir):
  55. """
  56. Get a rootfs_dir dict and serialize to string
  57. """
  58. rootfs_dir = ''
  59. for key, val in krootfs_dir.items():
  60. rootfs_dir += ' '
  61. rootfs_dir += '='.join([key, val])
  62. return rootfs_dir.strip()
  63. def callback_rootfs_dir(option, opt, value, parser):
  64. """
  65. Build a dict using --rootfs_dir connection=dir
  66. """
  67. if not type(parser.values.rootfs_dir) is dict:
  68. parser.values.rootfs_dir = dict()
  69. if '=' in value:
  70. (key, rootfs_dir) = value.split('=')
  71. else:
  72. key = 'ROOTFS_DIR'
  73. rootfs_dir = value
  74. parser.values.rootfs_dir[key] = rootfs_dir
  75. def wic_create_subcommand(args, usage_str):
  76. """
  77. Command-line handling for image creation. The real work is done
  78. by image.engine.wic_create()
  79. """
  80. parser = optparse.OptionParser(usage=usage_str)
  81. parser.add_option("-o", "--outdir", dest="outdir",
  82. help="name of directory to create image in")
  83. parser.add_option("-e", "--image-name", dest="image_name",
  84. help="name of the image to use the artifacts from "
  85. "e.g. core-image-sato")
  86. parser.add_option("-r", "--rootfs-dir", dest="rootfs_dir", type="string",
  87. action="callback", callback=callback_rootfs_dir,
  88. help="path to the /rootfs dir to use as the "
  89. ".wks rootfs source")
  90. parser.add_option("-b", "--bootimg-dir", dest="bootimg_dir",
  91. help="path to the dir containing the boot artifacts "
  92. "(e.g. /EFI or /syslinux dirs) to use as the "
  93. ".wks bootimg source")
  94. parser.add_option("-k", "--kernel-dir", dest="kernel_dir",
  95. help="path to the dir containing the kernel to use "
  96. "in the .wks bootimg")
  97. parser.add_option("-n", "--native-sysroot", dest="native_sysroot",
  98. help="path to the native sysroot containing the tools "
  99. "to use to build the image")
  100. parser.add_option("-p", "--skip-build-check", dest="build_check",
  101. action="store_false", default=True, help="skip the build check")
  102. parser.add_option("-f", "--build-rootfs", action="store_true", help="build rootfs")
  103. parser.add_option("-c", "--compress-with", choices=("gzip", "bzip2", "xz"),
  104. dest='compressor',
  105. help="compress image with specified compressor")
  106. parser.add_option("-v", "--vars", dest='vars_dir',
  107. help="directory with <image>.env files that store "
  108. "bitbake variables")
  109. parser.add_option("-D", "--debug", dest="debug", action="store_true",
  110. default=False, help="output debug information")
  111. (options, args) = parser.parse_args(args)
  112. if len(args) != 1:
  113. logging.error("Wrong number of arguments, exiting\n")
  114. parser.print_help()
  115. sys.exit(1)
  116. if options.build_rootfs and not bitbake_main:
  117. logging.error("Can't build roofs as bitbake is not in the $PATH")
  118. sys.exit(1)
  119. if not options.image_name:
  120. missed = []
  121. for val, opt in [(options.rootfs_dir, 'rootfs-dir'),
  122. (options.bootimg_dir, 'bootimg-dir'),
  123. (options.kernel_dir, 'kernel-dir'),
  124. (options.native_sysroot, 'native-sysroot')]:
  125. if not val:
  126. missed.append(opt)
  127. if missed:
  128. print "The following build artifacts are not specified:"
  129. print " " + ", ".join(missed)
  130. sys.exit(1)
  131. if options.image_name:
  132. BB_VARS.default_image = options.image_name
  133. else:
  134. options.build_check = False
  135. if options.vars_dir:
  136. BB_VARS.vars_dir = options.vars_dir
  137. if options.build_check:
  138. print "Checking basic build environment..."
  139. if not engine.verify_build_env():
  140. print "Couldn't verify build environment, exiting\n"
  141. sys.exit(1)
  142. else:
  143. print "Done.\n"
  144. bootimg_dir = ""
  145. if options.image_name:
  146. if options.build_rootfs:
  147. argv = ["bitbake", options.image_name]
  148. if options.debug:
  149. argv.append("--debug")
  150. print "Building rootfs...\n"
  151. if bitbake_main(BitBakeConfigParameters(argv),
  152. cookerdata.CookerConfiguration()):
  153. sys.exit(1)
  154. rootfs_dir = get_bitbake_var("IMAGE_ROOTFS", options.image_name)
  155. kernel_dir = get_bitbake_var("DEPLOY_DIR_IMAGE", options.image_name)
  156. native_sysroot = get_bitbake_var("STAGING_DIR_NATIVE",
  157. options.image_name)
  158. else:
  159. if options.build_rootfs:
  160. print "Image name is not specified, exiting. (Use -e/--image-name to specify it)\n"
  161. sys.exit(1)
  162. wks_file = args[0]
  163. if not wks_file.endswith(".wks"):
  164. wks_file = engine.find_canned_image(scripts_path, wks_file)
  165. if not wks_file:
  166. print "No image named %s found, exiting. (Use 'wic list images' "\
  167. "to list available images, or specify a fully-qualified OE "\
  168. "kickstart (.wks) filename)\n" % args[0]
  169. sys.exit(1)
  170. image_output_dir = ""
  171. if options.outdir:
  172. image_output_dir = options.outdir
  173. if not options.image_name:
  174. rootfs_dir = ''
  175. if 'ROOTFS_DIR' in options.rootfs_dir:
  176. rootfs_dir = options.rootfs_dir['ROOTFS_DIR']
  177. bootimg_dir = options.bootimg_dir
  178. kernel_dir = options.kernel_dir
  179. native_sysroot = options.native_sysroot
  180. if rootfs_dir and not os.path.isdir(rootfs_dir):
  181. print "--roofs-dir (-r) not found, exiting\n"
  182. sys.exit(1)
  183. if not os.path.isdir(bootimg_dir):
  184. print "--bootimg-dir (-b) not found, exiting\n"
  185. sys.exit(1)
  186. if not os.path.isdir(kernel_dir):
  187. print "--kernel-dir (-k) not found, exiting\n"
  188. sys.exit(1)
  189. if not os.path.isdir(native_sysroot):
  190. print "--native-sysroot (-n) not found, exiting\n"
  191. sys.exit(1)
  192. else:
  193. not_found = not_found_dir = ""
  194. if not os.path.isdir(rootfs_dir):
  195. (not_found, not_found_dir) = ("rootfs-dir", rootfs_dir)
  196. elif not os.path.isdir(kernel_dir):
  197. (not_found, not_found_dir) = ("kernel-dir", kernel_dir)
  198. elif not os.path.isdir(native_sysroot):
  199. (not_found, not_found_dir) = ("native-sysroot", native_sysroot)
  200. if not_found:
  201. if not not_found_dir:
  202. not_found_dir = "Completely missing artifact - wrong image (.wks) used?"
  203. print "Build artifacts not found, exiting."
  204. print " (Please check that the build artifacts for the machine"
  205. print " selected in local.conf actually exist and that they"
  206. print " are the correct artifacts for the image (.wks file)).\n"
  207. print "The artifact that couldn't be found was %s:\n %s" % \
  208. (not_found, not_found_dir)
  209. sys.exit(1)
  210. krootfs_dir = options.rootfs_dir
  211. if krootfs_dir is None:
  212. krootfs_dir = {}
  213. krootfs_dir['ROOTFS_DIR'] = rootfs_dir
  214. rootfs_dir = rootfs_dir_to_args(krootfs_dir)
  215. print "Creating image(s)...\n"
  216. engine.wic_create(wks_file, rootfs_dir, bootimg_dir, kernel_dir,
  217. native_sysroot, scripts_path, image_output_dir,
  218. options.compressor, options.debug)
  219. def wic_list_subcommand(args, usage_str):
  220. """
  221. Command-line handling for listing available images.
  222. The real work is done by image.engine.wic_list()
  223. """
  224. parser = optparse.OptionParser(usage=usage_str)
  225. args = parser.parse_args(args)[1]
  226. if not engine.wic_list(args, scripts_path):
  227. logging.error("Bad list arguments, exiting\n")
  228. parser.print_help()
  229. sys.exit(1)
  230. def wic_help_topic_subcommand(args, usage_str):
  231. """
  232. Command-line handling for help-only 'subcommands'. This is
  233. essentially a dummy command that doesn nothing but allow users to
  234. use the existing subcommand infrastructure to display help on a
  235. particular topic not attached to any particular subcommand.
  236. """
  237. pass
  238. wic_help_topic_usage = """
  239. """
  240. subcommands = {
  241. "create": [wic_create_subcommand,
  242. hlp.wic_create_usage,
  243. hlp.wic_create_help],
  244. "list": [wic_list_subcommand,
  245. hlp.wic_list_usage,
  246. hlp.wic_list_help],
  247. "plugins": [wic_help_topic_subcommand,
  248. wic_help_topic_usage,
  249. hlp.get_wic_plugins_help],
  250. "overview": [wic_help_topic_subcommand,
  251. wic_help_topic_usage,
  252. hlp.wic_overview_help],
  253. "kickstart": [wic_help_topic_subcommand,
  254. wic_help_topic_usage,
  255. hlp.wic_kickstart_help],
  256. }
  257. def start_logging(loglevel):
  258. logging.basicConfig(filname='wic.log', filemode='w', level=loglevel)
  259. def main(argv):
  260. parser = optparse.OptionParser(version="wic version %s" % __version__,
  261. usage=hlp.wic_usage)
  262. parser.disable_interspersed_args()
  263. args = parser.parse_args(argv)[1]
  264. if len(args):
  265. if args[0] == "help":
  266. if len(args) == 1:
  267. parser.print_help()
  268. sys.exit(1)
  269. return hlp.invoke_subcommand(args, parser, hlp.wic_help_usage, subcommands)
  270. if __name__ == "__main__":
  271. try:
  272. sys.exit(main(sys.argv[1:]))
  273. except WicError as err:
  274. print >> sys.stderr, "ERROR:", err
  275. sys.exit(1)