[PATCH 1/3] mock cvs 2007-03: cross-compile support

Ken MacLeod ken at bitsko.slc.ut.us
Wed Jun 13 02:15:13 UTC 2007


This patch adds support for building RPMs for cross-compile targets.
It adds an option '--toolkit' to specify a cross-development toolkit
(and version) config for toolkits like DENX ELDK, TimeSys, MontaVista,
or Wind River.

The chroot (-r) configuration needs to supply the 'target_arch' and
cross-distribution-provided host tools yum archive (those packages
that normally install in the host system).  [These should move over to
the --toolkit config to allow unmodified host mock cfgs.]

The --toolkit configuration file supplies the following variables [to
be added to a doc somewhere]:

  base_arch (ppc, arm, mips)
    for the given 'target_arch' (eg. ppc_74xx, ppc_85xx)

  macros
    additional rpmbuild macros

  tk_rpmmacros
    points to where to put macros if the toolkit needs that (ELDK)

  tk_env
    set in the environment before calling rpmbuild (or the toolkit's
    equivalent) to set PATH, CROSS_COMPILE, etc.

  tk_fixup_cmd
    yum command (RPM to install) in the host (/) chroot after all else
    to fix things up for cross-building [should go away when everyone
    clean-builds, right?]

  tk_cross_chroot_setup_cmd
    'buildsys-build' to install for the /cross root (complete yum
    command)

  tk_cross_yum.conf
    yum.conf for the /cross root

  tk_target_chroot_chroot_cmd
    'buildsys-build' to install for the /target root (complete yum
    command)

  tk_target_yum.conf
    yum.conf for the /target root


---

 mock.py |  106 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 87 insertions(+), 19 deletions(-)

diff --git a/mock.py b/mock.py
index fc1b6aa..f072d78 100644
--- a/mock.py
+++ b/mock.py
@@ -246,15 +246,29 @@ class Root:
          
         self._prep_install()
         self.yum(cmd)
+
+        cross_cmd = cmd
+        for cross_fs in ('cross', 'target'):
+            if self.config.has_key('tk_' + cross_fs + '_yum.conf'):
+                if cmd[0:7] == 'install':
+                    cross_cmd = self.config['tk_' + cross_fs + '_chroot_setup_cmd']
+                self.yum(cross_cmd, cross_fs)
+
+        if self.config.has_key('tk_fixup_cmd') and cmd[0:7] == 'install':
+            self.yum(self.config['tk_fixup_cmd'])
+
         self._prep_build()
          
         if create_cache:
             self.pack()
 
-    def yum(self, cmd):
+    def yum(self, cmd, crossdir=None):
         """use yum to install packages/package groups into the chroot"""
         # mock-helper yum --installroot=rootdir cmd
-        basecmd = '%s --installroot %s' % (self.config['yum'], self.rootdir)
+        yumrootdir = self.rootdir
+        if crossdir is not None:
+            yumrootdir = os.path.join(yumrootdir, crossdir)
+        basecmd = '%s --installroot %s' % (self.config['yum'], yumrootdir)
         
         self._mount() # check it again        
         command = '%s %s' % (basecmd, cmd)
@@ -282,8 +296,9 @@ class Root:
         shutil.copy2(srpm, dest)
         rootdest = os.path.join(self.builddir, 'originals', srpmfn)
 
-        cmd = "%s -c 'rpm -Uvh --nodeps %s' %s" % (self.config['runuser'], 
-                          rootdest, self.config['chrootuser'])
+        cmd = "%s -c '%s rpm -Uvh --nodeps %s' %s" \
+              % (self.config['runuser'], self.config['tk_env'],
+                 rootdest, self.config['chrootuser'])
         (retval, output) = self.do_chroot(cmd)
         
         if retval != 0:
@@ -303,8 +318,10 @@ class Root:
         chrootspec = spec.replace(self.rootdir, '') # get rid of rootdir prefix
         # grab the .spec file from the specdir
         # run rpmbuild -bs --nodeps specfile
-        cmd = "%s -c 'rpmbuild -bs --target %s --nodeps %s' %s" % (self.config['runuser'], 
-                    self.target_arch, chrootspec, self.config['chrootuser'])
+        cmd = "%s -c '%s rpmbuild -bs %s --nodeps %s' %s" \
+              % (self.config['runuser'], self.config['tk_env'],
+                 self.config['tk_target_option'], chrootspec,
+                 self.config['chrootuser'])
         
         (retval, output) = self.do_chroot(cmd)
         if retval != 0:
@@ -355,9 +372,10 @@ class Root:
         srpmfn = os.path.basename(srpm_in)
         # run with --nodeps b/c of the check above we know we have our build
         # deps satisfied.
-        cmd = "cd /;%s -c 'rpmbuild --rebuild  --target %s --nodeps %s' %s" % (
-             self.config['runuser'], self.target_arch, srpm_in, 
-             self.config['chrootuser'])
+        cmd = "cd /;%s -c '%s rpmbuild --rebuild %s --nodeps %s' %s" \
+              % (self.config['runuser'], self.config['tk_env'],
+                 self.config['tk_target_option'], srpm_in,
+                 self.config['chrootuser'])
         
         self.state("build")
 
@@ -566,6 +584,17 @@ class Root:
         
         return rpmUtils.miscutils.unique(reqlist)
     
+    def write_yum_conf(self, yum_conf, crossdir=''):
+        if os.path.exists( os.path.join(self.rootdir, crossdir, 'etc', 'yum.conf')):
+            yum_conf_path = os.path.join('/', crossdir, 'etc', 'yum.conf')
+            cmd = "chown %s.%s %s" % (self.config['chrootuid'],
+                                      self.config['chrootgid'], yum_conf_path)
+            self.do_chroot(cmd, fatal = True)
+        yumconf = os.path.join(self.rootdir, crossdir, 'etc', 'yum.conf')
+        yumconf_fo = open(yumconf, 'w')
+        yumconf_content = yum_conf
+        yumconf_fo.write(yumconf_content)
+
     def _prep_install(self):
         """prep chroot for installation"""
         # make chroot dir
@@ -581,6 +610,12 @@ class Root:
                      os.path.join(self.rootdir, 'var/lock/rpm'),
                      os.path.join(self.rootdir, 'etc/yum.repos.d')]:
             self._ensure_dir(item)
+        if self.config.has_key('tk_cross_yum.conf'):
+            self._ensure_dir(os.path.join(self.rootdir, 'cross/etc'))
+            self._ensure_dir(os.path.join(self.rootdir, 'cross/var/lock/rpm'))
+        if self.config.has_key('tk_target_yum.conf'):
+            self._ensure_dir(os.path.join(self.rootdir, 'target/etc'))
+            self._ensure_dir(os.path.join(self.rootdir, 'target/var/lock/rpm'))
         
         self._mount()
 
@@ -623,15 +658,12 @@ class Root:
                 fo.close()
         
         # write in yum.conf into chroot
-        if os.path.exists( os.path.join(self.rootdir, 'etc', 'yum.conf')):
-            cmd = "chown %s.%s /etc/yum.conf" % (self.config['chrootuid'],
-                self.config['chrootgid'])
-            self.do_chroot(cmd, fatal = True)
-        yumconf = os.path.join(self.rootdir, 'etc', 'yum.conf')
-        yumconf_fo = open(yumconf, 'w')
-        yumconf_content = self.config['yum.conf']
-        yumconf_fo.write(yumconf_content)
-    
+        self.write_yum_conf(self.config['yum.conf'])
+        if self.config.has_key('tk_cross_yum.conf'):
+            self.write_yum_conf(self.config['tk_cross_yum.conf'], 'cross')
+        if self.config.has_key('tk_target_yum.conf'):
+            self.write_yum_conf(self.config['tk_target_yum.conf'], 'target')
+
         # files in /etc that need doing
         filedict = self.config['files']
         for key in filedict:
@@ -703,7 +735,8 @@ class Root:
         self.do_chroot(cmd, fatal = True)
         
         # rpmmacros default
-        macrofile_out = '%s%s/.rpmmacros' % (self.rootdir, self.homedir)
+        macrofile_out = '%s%s/%s' % (self.rootdir, self.homedir,
+                                     self.config['tk_rpmmacros'])
         if not os.path.exists(macrofile_out):
             rpmmacros = open(macrofile_out, 'w')
             rpmmacros.write(self.config['macros'])
@@ -740,6 +773,8 @@ def command_parse():
             help="do not clean chroot before building", default=True)
     parser.add_option("--arch", action ="store", dest="arch", 
             default=None, help="target build arch")
+    parser.add_option("--toolkit", action ="store", dest="toolkit",
+            default=None, help="cross-development toolkit config file name")
     parser.add_option("--debug", action ="store_true", dest="debug", 
             default=False, help="Output copious debugging information")
     parser.add_option("--resultdir", action="store", type="string", 
@@ -778,6 +813,7 @@ def setup_default_config_opts(config_opts):
     config_opts['debug'] = False
     config_opts['quiet'] = False
     config_opts['target_arch'] = 'i386'
+    config_opts['toolkit'] = None
     config_opts['files'] = {}
     config_opts['yum.conf'] = ''
     config_opts['macros'] = """
@@ -790,6 +826,13 @@ def setup_default_config_opts(config_opts):
     config_opts['files']['/etc/resolv.conf'] = "nameserver 192.168.1.1\n"
     config_opts['files']['/etc/hosts'] = "127.0.0.1 localhost localhost.localdomain\n"
 
+    # cross-development config options, default is native
+    config_opts['tk_env'] = ''
+    config_opts['tk_rpmmacros'] = '.rpmmacros'
+    # --target is late-bound in main() to allow command line or config
+    # override
+    # config_opts['tk_target_option'] = '--target %s' % config_opts['target_arch']
+
     # caching-related config options
     config_opts['rebuild_cache'] = False
     config_opts['use_cache'] = False
@@ -821,6 +864,22 @@ def set_config_opts_per_cmdline(config_opts, options):
     if options.uniqueext:
         config_opts['unique-ext'] = options.uniqueext
 
+    if options.toolkit:
+        config_opts['toolkit'] = options.toolkit
+
+def toolkit(config_path, config_opts, toolkit):
+    # read in toolkit config file by toolkit name
+    if toolkit.endswith('.cfg'):
+        cfg = '%s/%s' % (config_path, toolkit)
+    else:
+        cfg = '%s/%s.cfg' % (config_path, toolkit)
+        
+    if os.path.exists(cfg):
+        execfile(cfg)
+    else:
+        error("Could not find config file %s for toolkit %s" % (cfg, toolkit))
+        sys.exit(1)
+
 def do_clean(config_opts, init=0):
         my = None
         try:
@@ -946,7 +1005,16 @@ def main():
     
     # cmdline options override config options
     set_config_opts_per_cmdline(config_opts, options)
+
+    if config_opts['toolkit'] is not None:
+        toolkit(config_path, config_opts, config_opts['toolkit'])
     
+    # cmdline options override toolkit config options too
+    set_config_opts_per_cmdline(config_opts, options)
+
+    if not config_opts.has_key('tk_target_option'):
+        config_opts['tk_target_option'] = '--target %s' % config_opts['target_arch']
+
     # do whatever we're here to do
     if args[0] == 'clean':
         # unset a --no-clean




More information about the Fedora-buildsys-list mailing list