From: Michael Tremer Date: Sun, 24 Jan 2010 22:49:41 +0000 (+0100) Subject: naoki: New toolchain class. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=59cdb5f181463dc6c403a03ec8d81650a39a9d8a;p=ipfire-3.x.git naoki: New toolchain class. Allows a more flexible way to handle this... --- diff --git a/config/naoki.conf b/config/naoki.conf index c5701e201..940b7328f 100644 --- a/config/naoki.conf +++ b/config/naoki.conf @@ -12,3 +12,9 @@ version = %(epoch)s.0-prealpha2 ; A descriptive slogan slogan = "Gluttony" + + +[toolchain] + +; Counter of toolchain version +version = 0 diff --git a/naoki/__init__.py b/naoki/__init__.py index 27621f2d2..d177019d6 100644 --- a/naoki/__init__.py +++ b/naoki/__init__.py @@ -32,7 +32,9 @@ class Naoki(object): self.config = config self.config["toolchain"] = self.options.toolchain self.setup_logging() - + + self.toolchain = chroot.Toolchain() + self.log.info("Started naoki on %s" % time.strftime("%a, %d %b %Y %H:%M:%S")) # dump configuration to log @@ -101,62 +103,42 @@ class Naoki(object): print a elif action == "rebuild": + force = True if not self.packages: self.packages = package.list() - self.build() + force = False + self.build(force=force) + + + def build(self, force=False): + if config["toolchain"]: + self.toolchain.build() + return + if not self.toolchain.exists: + self.log.error("You need to build or download a toolchain first.") + return - def build(self): requeue = [] self.packages = package.depsort(self.packages) - while True: - if not self.packages: - return - + while self.packages: # Get first package that is to be done - build = Build(self.packages.pop(0)) + build = chroot.Environment(self.packages.pop(0)) if build.package.isBuilt: - if self.options.toolchain: + if not force: self.log.info("Skipping already built package %s..." % build.package.name) continue self.log.warn("Package is already built. Will overwrite.") - #if not build.package.canBuild: - # self.log.warn("Cannot build package %s. Requeueing. %s" % (build.package.name, build.package.toolchain_deps)) - # self.packages.append(build.package) - # continue + if not build.package.canBuild: + self.log.warn("Cannot build package %s." % build.package.name) + if not self.packages: + self.log.error("Blah") + return + self.log.warn("Requeueing. %s" % (build.package.name, build.package.toolchain_deps)) + self.packages.append(build.package) + continue self.log.info("Building %s..." % build.package.name) build.build() - - -class Build(object): - def __init__(self, package): - self.package = package - - self.environment = chroot.Environment(self.package) - - def init(self): - self.environment.init() - - if not self.package.toolchain: - self.extractAll() - - def extractAll(self): - packages = self.package.deps + self.package.build_deps - for pkg in config["mandatory_packages"]: - pkg = package.find(pkg) - if not pkg in packages: - packages.append(pkg) - - packages = package.depsolve(packages, recursive=True) - - for pkg in packages: - pkg.extract(self.environment.chrootPath()) - - def build(self): - self.package.download() - self.init() - self.environment.make("package") - diff --git a/naoki/chroot.py b/naoki/chroot.py index 7a9279834..dac2d9763 100644 --- a/naoki/chroot.py +++ b/naoki/chroot.py @@ -6,6 +6,7 @@ import os import random import stat +import package import util from constants import * from logger import getLog @@ -15,34 +16,27 @@ class Environment(object): self.package = package self.config = config - # Indication if we run in toolchain mode - self.toolchain = self.package.toolchain + self.toolchain = Toolchain() # mount/umount - self.umountCmds = [] - self.mountCmds = [] - - if not self.toolchain: - self.umountCmds.extend([ - "umount -n %s" % self.chrootPath("tools_i686"), - "umount -n %s" % self.chrootPath("proc"), - "umount -n %s" % self.chrootPath("sys"), - "umount -n %s" % self.chrootPath("usr", "src", "cache"), - "umount -n %s" % self.chrootPath("usr", "src", "packages"), - "umount -n %s" % self.chrootPath("usr", "src", "pkgs"), - "umount -n %s" % self.chrootPath("usr", "src", "src"), - "umount -n %s" % self.chrootPath("usr", "src", "tools"), - ]) - self.mountCmds.extend([ - "mount -n --bind %s/tools_i686 %s" % (TOOLCHAINSDIR, self.chrootPath("tools_i686")), - "mount -n -t proc naoki_chroot_proc %s" % self.chrootPath("proc"), - "mount -n -t sysfs naoki_chroot_sysfs %s" % self.chrootPath("sys"), - "mount -n --bind %s %s" % (os.path.join(CACHEDIR), self.chrootPath("usr", "src", "cache")), - "mount -n --bind %s %s" % (os.path.join(PACKAGESDIR), self.chrootPath("usr", "src", "packages")), - "mount -n --bind %s %s" % (os.path.join(PKGSDIR), self.chrootPath("usr", "src", "pkgs")), - "mount -n --bind %s %s" % (os.path.join(BASEDIR, "src"), self.chrootPath("usr", "src", "src")), - "mount -n --bind %s %s" % (os.path.join(TOOLSDIR), self.chrootPath("usr", "src", "tools")), - ]) + self.umountCmds = [ + "umount -n %s" % self.chrootPath("proc"), + "umount -n %s" % self.chrootPath("sys"), + "umount -n %s" % self.chrootPath("usr", "src", "cache"), + "umount -n %s" % self.chrootPath("usr", "src", "packages"), + "umount -n %s" % self.chrootPath("usr", "src", "pkgs"), + "umount -n %s" % self.chrootPath("usr", "src", "src"), + "umount -n %s" % self.chrootPath("usr", "src", "tools"), + ] + self.mountCmds = [ + "mount -n -t proc naoki_chroot_proc %s" % self.chrootPath("proc"), + "mount -n -t sysfs naoki_chroot_sysfs %s" % self.chrootPath("sys"), + "mount -n --bind %s %s" % (os.path.join(CACHEDIR), self.chrootPath("usr", "src", "cache")), + "mount -n --bind %s %s" % (os.path.join(PACKAGESDIR), self.chrootPath("usr", "src", "packages")), + "mount -n --bind %s %s" % (os.path.join(PKGSDIR), self.chrootPath("usr", "src", "pkgs")), + "mount -n --bind %s %s" % (os.path.join(BASEDIR, "src"), self.chrootPath("usr", "src", "src")), + "mount -n --bind %s %s" % (os.path.join(TOOLSDIR), self.chrootPath("usr", "src", "tools")), + ] self.buildroot = "buildroot.%d" % random.randint(0, 1024) self.log = None @@ -61,11 +55,12 @@ class Environment(object): def _init(self): self._setupLogging() + self.log.info("Setting up environment %s..." % self.chrootPath()) + if os.path.exists(self.chrootPath()): self.clean() # create dirs - self.log.debug("Creating directories...") dirs = ( CACHEDIR, PACKAGESDIR, @@ -89,7 +84,6 @@ class Environment(object): util.mkdir(item) # touch files - self.log.debug("Touching files...") files = ( "etc/fstab", "etc/mtab", @@ -99,15 +93,18 @@ class Environment(object): self._setupDev() self._setupUsers() - self._setupToolchain() + + self.toolchain.extract(self.chrootPath()) + + self.extractAll() + + self.toolchain.adjust(self.chrootPath()) def clean(self): util.rm(self.chrootPath()) def make(self, target): - file = self.package.filename - if not self.toolchain: - file = "/usr/src%s" % file[len(BASEDIR):] + file = "/usr/src%s" % self.package.filename[len(BASEDIR):] return self.doChroot("make -C %s -f %s %s" % \ (os.path.dirname(file), file, target), shell=True) @@ -124,28 +121,17 @@ class Environment(object): "TOOLS_DIR" : "/tools_i686", "TARGET" : "i686-ipfire-linux-gnu", "TARGET_MACHINE" : "i686", + "PATH" : "/sbin:/bin:/usr/sbin:/usr/bin:/tools_i686/sbin:/tools_i686/bin", + "BUILDROOT" : "/%s" % self.buildroot, + "CHROOT" : "1", }) - if self.toolchain: - env.update({ - "PATH" : "/tools_i686/sbin:/tools_i686/bin:%s" % os.environ["PATH"], - "TOOLCHAIN" : "1", - "PKGROOT" : PKGSDIR, - "ROOT" : self.chrootPath(), - "BASEDIR" : BASEDIR, - }) - else: - env.update({ - "PATH" : "/sbin:/bin:/usr/sbin:/usr/bin:/tools_i686/sbin:/tools_i686/bin", - "BUILDROOT" : "/%s" % self.buildroot, - "CHROOT" : "1", - }) if kwargs.has_key("env"): env.update(kwargs.pop("env")) self._mountall() - if not self.toolchain and not kwargs.has_key("chrootPath"): + if not kwargs.has_key("chrootPath"): kwargs["chrootPath"] = self.chrootPath() ret = util.do(command, @@ -156,13 +142,9 @@ class Environment(object): return ret - do = doChroot - def chrootPath(self, *args): return os.path.join(BUILDDIR, "environments", self.package.id, *args) - path = chrootPath - def _setupLogging(self): logfile = os.path.join(LOGDIR, self.package.id, "build.log") if not os.path.exists(os.path.dirname(logfile)): @@ -174,9 +156,6 @@ class Environment(object): self.log.addHandler(fh) def _setupDev(self): - if self.toolchain: - return - # files in /dev util.rm(self.chrootPath("dev")) util.mkdir(self.chrootPath("dev", "pts")) @@ -218,9 +197,6 @@ class Environment(object): self.mountCmds.append(devMntCmd) def _setupUsers(self): - if self.toolchain: - return - ## XXX Could be done better self.log.debug("Creating users") f = open("/etc/passwd") @@ -241,31 +217,6 @@ class Environment(object): break f.close() - def _setupToolchain(self): - symlinks = ( - ("bin/bash", "bin/bash"), - ("bin/cat", "bin/cat"), - ("bin/echo", "bin/echo"), - ("bin/stty", "bin/stty"), - ("bin/pwd", "bin/pwd"), - ("bin/sh", "bin/sh"), - # - ("bin/perl", "usr/bin/perl"), - # - ("lib/libgcc_s.so", "usr/lib/libgcc_s.so"), - ("lib/libgcc_s.so.1", "usr/lib/libgcc_s.so.1"), - ("lib/libstdc++.so", "usr/lib/libstdc++.so"), - ("lib/libstdc++.so.6", "usr/lib/libstdc++.so.6"), - ) - for src, dst in symlinks: - if os.path.exists(self.chrootPath(dst)): - continue - dir = os.path.dirname(self.chrootPath(dst)) - if not os.path.exists(dir): - util.mkdir(dir) - self.log.debug("Creating symlink /%s" % dst) - os.symlink("/tools_i686/%s" % src, self.chrootPath(dst)) - def _mountall(self): """mount 'normal' fs like /dev/ /proc/ /sys""" for cmd in self.mountCmds: @@ -275,3 +226,109 @@ class Environment(object): """umount all mounted chroot fs.""" for cmd in self.umountCmds: util.do(cmd, raiseExc=0, shell=True) + + def extractAll(self): + packages = self.package.deps + self.package.build_deps + for pkg in config["mandatory_packages"]: + pkg = package.find(pkg) + if not pkg in packages: + packages.append(pkg) + + packages = package.depsolve(packages, recursive=True) + + for pkg in packages: + pkg.extract(self.chrootPath()) + + def build(self): + self.package.download() + self.init() + + try: + self.make("package") + except Error: + if config["cleanup_on_failure"]: + self.clean() + raise + + if config["cleanup_on_success"]: + self.clean() + + +class Toolchain(object): + def __init__(self): + util.mkdir(TOOLCHAINSDIR) + + # Create a filename object + self.filename = "toolchain-i686.%s.tar.gz" % config["toolchain_version"] + + # Store the path including the filename + self.path = os.path.join(TOOLCHAINSDIR, self.filename) + + self.build_dir = os.path.join(BUILDDIR, "toolchains", + "tools_i686.%s" % config["toolchain_version"]) + + self.log = getLog() + + @property + def exists(self): + return os.path.exists(self.path) + + def download(self): + self.log.info("Downloading toolchain...") + pass + + def cmd(self, args=[]): + cmd = "%s" % os.path.join(TOOLSDIR, "toolchain") + if args: + cmd += " " + cmd += " ".join(args) + util.do(cmd, cwd=self.build_dir, shell=True, + env={ "TOOLS_DIR" : self.build_dir }) + + # TODO: + # - logging + def make(self, pkg, target): + env = config.environment.copy() + env.update({ + "BASEDIR" : BASEDIR, + "PATH" : "/tools_i686/sbin:/tools_i686/bin:%s" % os.environ["PATH"], + "PKGROOT" : PKGSDIR, + "ROOT" : self.build_dir, + "TARGET" : "i686-ipfire-linux-gnu", + "TARGET_MACHINE" : "i686", + "TOOLCHAIN" : "1", + "TOOLS_DIR" : "/tools_i686", + }) + + command = "make -C %s -f %s %s" % \ + (os.path.dirname(pkg.filename), pkg.filename, target) + + return util.do(command, shell=True, env=env) + + def build_package(self, pkg): + self.log.debug("Building %s..." % pkg.name) + + source_dir = os.path.join(self.build_dir, "usr/src") + + util.rm(source_dir) + util.mkdir(source_dir) + + return self.make(pkg, "package") + + def compress(self): + self.cmd(["compress", self.path, self.build_dir]) + + def extract(self, path): + self.cmd(["extract", self.path, os.path.join(path, "tools_i686")]) + + def adjust(self, path): + self.cmd(["adjust", path]) + + def build(self): + self.log.info("Building toolchain...") + packages = package.depsort(package.list(toolchain=True)) + for pkg in packages: + if pkg.isBuilt: + continue + self.build_package(pkg) + self.compress() diff --git a/naoki/constants.py b/naoki/constants.py index f4fadc691..09c3cdcde 100644 --- a/naoki/constants.py +++ b/naoki/constants.py @@ -11,10 +11,10 @@ CONFIGDIR = os.path.join(BASEDIR, "config") LOGDIR = os.path.join(BASEDIR, "logs") PKGSDIR = os.path.join(BASEDIR, "pkgs") PACKAGESDIR = os.path.join(BUILDDIR, "packages") -TOOLCHAINSDIR = os.path.join(BUILDDIR, "toolchains") TOOLSDIR = os.path.join(BASEDIR, "tools") TARBALLDIR = os.path.join(CACHEDIR, "tarballs") +TOOLCHAINSDIR = os.path.join(CACHEDIR, "toolchains") PATCHESDIR = os.path.join(CACHEDIR, "patches") CONFIGFILE = os.path.join(CONFIGDIR, "naoki.conf") @@ -23,14 +23,14 @@ class Config(object): _items = { "toolchain" : False, "mandatory_packages" : [ - "core/bash", "core/gcc", "core/glibc", "core/make", ], # # Cleanup settings - "cleanup_after_fail" : True, + "cleanup_on_failure" : False, + "cleanup_on_success" : True, # # Distro items "distro_name" : "unknown", @@ -86,6 +86,9 @@ class Config(object): "DISTRO_EPOCH" : self["distro_epoch"], "DISTRO_VERSION" : self["distro_version"], "DISTRO_SLOGAN" : self["distro_slogan"], + # + "CFLAGS" : "-O2 -fomit-frame-pointer", + "PARALLELISMFLAGS" : "-j6", } # Create a globally useable instance of the configuration diff --git a/naoki/package.py b/naoki/package.py index 2d029580c..0e144b07f 100644 --- a/naoki/package.py +++ b/naoki/package.py @@ -11,7 +11,10 @@ import util from constants import * from logger import getLog -def list(): +def list(toolchain=None): + if not toolchain: + toolchain = config["toolchain"] + pkgs = [] for dir in os.listdir(PKGSDIR): if not os.path.isdir(os.path.join(PKGSDIR, dir)): @@ -19,7 +22,7 @@ def list(): # If we work in toolchain mode we don't return the other # packages and if we are not, we don't return the toolchain packages. - if config["toolchain"]: + if toolchain: if dir != "toolchain": continue else: diff --git a/pkgs/Include b/pkgs/Include index 0e21eb4e0..308aa0d10 100644 --- a/pkgs/Include +++ b/pkgs/Include @@ -65,8 +65,7 @@ endef PKG_BUILD_DEPS += glibc gcc -CONFIGURE_ARCH = --build=$(TARGET) --host=$(TARGET) -CONFIGURE_OPTIONS = $(CONFIGURE_ARCH) --prefix=/usr +CONFIGURE_OPTIONS = --prefix=/usr ifeq "$(TARGET_MACHINE)" "x86_64" LINKER = /lib64/ld-linux-x86-64.so.2 @@ -75,7 +74,11 @@ else endif STAGE_PACKAGE_TARGETS = $(call reverse,$(PKG_PACKAGES_FILES)) -STAGE_DONE = $(ROOT)/.done +ifeq "$(TOOLCHAIN)" "1" + STAGE_DONE = $(ROOT)/$(PKG_NAME_REAL) +else + STAGE_DONE = $(ROOT)/.done +endif export CFLAGS CXXFLAGS BUILD_HOST diff --git a/pkgs/toolchain/adjust-toolchain/adjust-toolchain.nm b/pkgs/toolchain/adjust-toolchain/adjust-toolchain.nm deleted file mode 100644 index 870c45fc8..000000000 --- a/pkgs/toolchain/adjust-toolchain/adjust-toolchain.nm +++ /dev/null @@ -1,89 +0,0 @@ -############################################################################### -# # -# IPFire.org - A linux based firewall # -# Copyright (C) 2007, 2008 Michael Tremer & Christian Schmidt # -# # -# This program is free software: you can redistribute it and/or modify # -# it under the terms of the GNU General Public License as published by # -# the Free Software Foundation, either version 3 of the License, or # -# (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program. If not, see . # -# # -############################################################################### - -############################################################################### -# Definitions -############################################################################### - -include $(PKGROOT)/Include - -PKG_NAME = adjust-toolchain -PKG_VER = 0 -PKG_REL = 0 - -PKG_MAINTAINER = -PKG_GROUP = -PKG_URL = -PKG_LICENSE = -PKG_SUMMARY = - -define PKG_DESCRIPTION - Adjusts the toolchain settings. -endef - -PKG_TOOLCHAIN_DEPS = acl attr bash binutils bzip2 coreutils cpio diffutils \ - file findutils flex gawk gcc gettext glibc grep gzip kernel-headers m4 \ - make ncurses patch pax-utils perl sed tar texinfo xz - -############################################################################### -# Installation Details -############################################################################### - -define STAGE_BUILD - mv -v $(TOOLS_DIR)/bin/{ld,ld-old} - mv -v $(TOOLS_DIR)/bin/{ld-new,ld} - - gcc -dumpspecs | sed -e "s@$(TOOLS_DIR)@@g" \ - -e "/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}" \ - -e '/\*cpp:/{n;s@$$@ -isystem /usr/include@}' > \ - $$(dirname $$(gcc --print-libgcc-file-name))/specs -endef - -define STAGE_TEST - -mkdir -pv /tmp/$(PKG_NAME) - - # It is imperative at this point to ensure that the basic functions - # (compiling and linking) of the adjusted toolchain are working as expected. - # To do this, perform the following sanity checks: - cd /tmp/$(PKG_NAME) && echo "main(){}" > dummy.c - cd /tmp/$(PKG_NAME) && cc dummy.c -v -Wl,--verbose &> dummy.log - cd /tmp/$(PKG_NAME) && readelf -l a.out | \ - grep "Requesting program interpreter: /lib/ld-linux.*.so.2" - - # Now make sure that we're setup to use the correct startfiles: - cd /tmp/$(PKG_NAME) && grep -o '/usr/lib.*/crt[1in].*succeeded' dummy.log - - # Verify that the compiler is searching for the correct header files: - cd /tmp/$(PKG_NAME) && grep -B1 '^ /usr/include' dummy.log - - # Next, verify that the new linker is being used with the correct search paths: - cd /tmp/$(PKG_NAME) && grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g' - - # Next make sure that we're using the correct libc: - cd /tmp/$(PKG_NAME) && grep "/lib.*/libc.so.6 " dummy.log - - # Lastly, make sure GCC is using the correct dynamic linker: - cd /tmp/$(PKG_NAME) && \ - grep "found ld-linux.*so.2 at /lib/ld-linux.*so.2" dummy.log - - rm -rvf /tmp/$(PKG_NAME) -endef - -STAGE_INSTALL = diff --git a/pkgs/toolchain/binutils/binutils.nm b/pkgs/toolchain/binutils/binutils.nm index 10b416aca..ad24d07fa 100644 --- a/pkgs/toolchain/binutils/binutils.nm +++ b/pkgs/toolchain/binutils/binutils.nm @@ -10,7 +10,6 @@ define STAGE_BUILD RANLIB=$(TARGET)-ranlib \ ../$(THISAPP)/configure \ $(CONFIGURE_ARCH) \ - --target=$(TARGET) \ --prefix=$(TOOLS_DIR) \ --with-lib-path=$(TOOLS_DIR)/lib \ --disable-nls \ diff --git a/pkgs/toolchain/gcc/gcc.nm b/pkgs/toolchain/gcc/gcc.nm index cd2ee2162..0730ad377 100644 --- a/pkgs/toolchain/gcc/gcc.nm +++ b/pkgs/toolchain/gcc/gcc.nm @@ -3,7 +3,7 @@ include ../gcc-static/gcc-static.nm PKG_TOOLCHAIN_DEPS += binutils glibc -#PKG_PATCHES = $(THISAPP)-branch-startfiles-1.patch +PKG_PATCHES = $(THISAPP)-branch-startfiles-1.patch define STAGE_PREPARE_CMDS2 cd $(DIR_APP) && sed \ diff --git a/tools/toolchain b/tools/toolchain new file mode 100755 index 000000000..2ff556e44 --- /dev/null +++ b/tools/toolchain @@ -0,0 +1,63 @@ +#!/bin/sh + +case "${1}" in + adjust) + TARGET_PATH=${2} + TOOLS_DIR="${TARGET_PATH}/tools_i686" + + #if [ -z "${TOOLS_DIR}" ]; then + # echo "$0: TOOLS_DIR not set." >&2 + # exit 1 + #fi + + # If glibc is not compiled yet... + if [ -e "${TARGET_PATH}/lib/libc.so.6" ]; then + # Adjust linker + mv -f ${TOOLS_DIR}/bin/ld{-new,} + ln -sf ../../bin/ld \ + ${TOOLS_DIR}/$(${TOOLS_DIR}/bin/gcc -dumpmachine)/bin/ld + + # Adjust spec file + SPECS=$(dirname $(${TOOLS_DIR}/bin/gcc --print-libgcc-file-name))/specs + rm -f ${SPECS} + + ${TOOLS_DIR}/bin/gcc -dumpspecs | sed -e 's@/tools_i686@@g' \ + -e '/\*startfile_prefix_spec:/{n;s@.*@/usr/lib/ @}' \ + -e '/\*cpp:/{n;s@$@ -isystem /usr/include@}' > ${SPECS} + fi + + for i in bin/bash bin/cat bin/echo bin/stty bin/pwd bin/sh; do + if [ -e "${TARGET_PATH}/${i}" ]; then + continue + fi + mkdir -p $(dirname ${TARGET_PATH}/${i}) 2>/dev/null + ln -sf ../$(basename ${TOOLS_DIR})/${i} ${TARGET_PATH}/${i} + done + + for i in libgcc_s.so{,.1} libstdc++.so{,.6}; do + if [ -e "${TARGET_PATH}/usr/lib/${i}" ]; then + continue + fi + mkdir -p ${TARGET_PATH}/usr/lib 2>/dev/null + ln -sf ../../$(basename ${TOOLS_DIR})/lib/${i} ${TARGET_PATH}/usr/lib/${i} + done + ;; + + compress) + TARGET=${2} + COMPRESS_PATH=${3} + + # TODO: stripping/remove unneeded files + rm -rf ${COMPRESS_PATH}/{info,man,share/{doc,info,locale,man}} + + cd ${COMPRESS_PATH} && tar --posix -cfz ${TARGET} * + ;; + + extract) + ARCHIVE=${2} + TARGET_PATH=${3} + + tar xfz ${ARCHIVE} -C ${TARGET_PATH} + ;; + +esac