]>
git.ipfire.org Git - pakfire.git/blob - python/pakfire/builder.py
2 ###############################################################################
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
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. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
37 import packages
.packager
43 log
= logging
.getLogger("pakfire")
45 from config
import ConfigBuilder
46 from system
import system
47 from constants
import *
49 from errors
import BuildError
, BuildRootLocked
, Error
52 BUILD_LOG_HEADER
= """
54 | _ \ __ _| | __/ _(_)_ __ ___ | |__ _ _(_) | __| | ___ _ __
55 | |_) / _` | |/ / |_| | '__/ _ \ | '_ \| | | | | |/ _` |/ _ \ '__|
56 | __/ (_| | <| _| | | | __/ | |_) | |_| | | | (_| | __/ |
57 |_| \__,_|_|\_\_| |_|_| \___| |_.__/ \__,_|_|_|\__,_|\___|_|
60 Host : %(hostname)s (%(host_arch)s)
65 class BuildEnviron(object):
66 # The version of the kernel this machine is running.
67 kernel_version
= os
.uname()[2]
69 def __init__(self
, filename
=None, distro_name
=None, config
=None, configs
=None, arch
=None,
70 build_id
=None, logfile
=None, builder_mode
="release", use_cache
=None, **pakfire_args
):
72 assert builder_mode
in ("development", "release",)
73 self
.mode
= builder_mode
75 # Disable the build repository in release mode.
76 if self
.mode
== "release":
77 if pakfire_args
.has_key("disable_repos") and pakfire_args
["disable_repos"]:
78 pakfire_args
["disable_repos"] += ["build",]
80 pakfire_args
["disable_repos"] = ["build",]
82 # Save the build id and generate one if no build id was provided.
84 build_id
= "%s" % uuid
.uuid4()
86 self
.build_id
= build_id
90 self
.log
= log
.getChild(self
.build_id
)
91 # Propage everything to the root logger that we will see something
93 self
.log
.propagate
= 1
94 self
.log
.setLevel(logging
.INFO
)
96 # Add the given logfile to the logger.
97 h
= logging
.FileHandler(logfile
)
98 self
.log
.addHandler(h
)
100 # Format the log output for the file.
101 f
= logger
.BuildFormatter()
104 # If no logile was given, we use the root logger.
105 self
.log
= logging
.getLogger("pakfire")
107 # Log information about pakfire and some more information, when we
108 # are running in release mode.
109 if self
.mode
== "release":
111 "host_arch" : system
.arch
,
112 "hostname" : system
.hostname
,
113 "time" : time
.strftime("%a, %d %b %Y %H:%M:%S +0000", time
.gmtime()),
114 "version" : "Pakfire %s" % PAKFIRE_VERSION
,
117 for line
in BUILD_LOG_HEADER
.splitlines():
118 self
.log
.info(line
% logdata
)
120 # Create pakfire instance.
121 if pakfire_args
.has_key("mode"):
122 del pakfire_args
["mode"]
125 config
= ConfigBuilder(files
=configs
)
128 if distro_name
is None:
129 distro_name
= config
.get("builder", "distro", None)
130 config
.load_distro_config(distro_name
)
132 if not config
.has_distro():
133 log
.error(_("You have not set the distribution for which you want to build."))
134 log
.error(_("Please do so in builder.conf or on the CLI."))
135 raise ConfigError
, _("Distribution configuration is missing.")
137 self
.pakfire
= base
.Pakfire(
144 self
.distro
= self
.pakfire
.distro
145 self
.path
= self
.pakfire
.path
147 # Check if this host can build the requested architecture.
148 if not system
.host_supports_arch(self
.arch
):
149 raise BuildError
, _("Cannot build for %s on this host.") % self
.arch
151 # Where do we put the result?
152 self
.resultdir
= os
.path
.join(self
.path
, "result")
154 # Check weather to use or not use the cache.
155 if use_cache
is None:
156 # If use_cache is None, the user did not provide anything and
158 if self
.mode
== "development":
163 self
.use_cache
= use_cache
166 # If we have a plain makefile, we first build a source package and go with that.
168 if filename
.endswith(".%s" % MAKEFILE_EXTENSION
):
169 pkg
= packages
.Makefile(self
.pakfire
, filename
)
170 filename
= pkg
.dist(os
.path
.join(self
.resultdir
, "src"))
172 assert os
.path
.exists(filename
), filename
174 # Open source package.
175 self
.pkg
= packages
.SourcePackage(self
.pakfire
, None, filename
)
176 assert self
.pkg
, filename
178 # Log the package information.
179 self
.log
.info(_("Package information:"))
180 for line
in self
.pkg
.dump(long=True).splitlines():
181 self
.log
.info(" %s" % line
)
184 # Path where we extract the package and put all the source files.
185 self
.build_dir
= os
.path
.join(self
.path
, "usr/src/packages", self
.pkg
.friendly_name
)
190 # XXX need to make this configureable
192 "enable_loop_devices" : True,
193 "enable_ccache" : True,
194 "enable_icecream" : False,
195 "sign_packages" : True,
197 #self.settings.update(settings)
203 # Save the build time.
204 self
.build_time
= int(time
.time())
207 # Mount the directories.
213 # Setup domain name resolution in chroot.
216 # Extract all needed packages.
220 # Kill all still running processes.
221 util
.orphans_kill(self
.path
)
223 # Close pakfire instance.
226 # Umount the build environment.
235 Inherit architecture from distribution configuration.
237 return self
.distro
.arch
242 "build_date" : time
.strftime("%a, %d %b %Y %H:%M:%S +0000", time
.gmtime(self
.build_time
)),
243 "build_host" : socket
.gethostname(),
244 "build_id" : self
.build_id
,
245 "build_time" : self
.build_time
,
251 Shortcut to access the pakfire keyring.
253 (Makes also sure that it is properly initialized.)
257 if not self
.pakfire
.keyring
.initialized
:
258 self
.pakfire
.keyring
.init()
260 return self
.pakfire
.keyring
263 filename
= os
.path
.join(self
.path
, ".lock")
266 self
._lock
= open(filename
, "a+")
271 fcntl
.lockf(self
._lock
.fileno(), fcntl
.LOCK_EX | fcntl
.LOCK_NB
)
273 raise BuildRootLocked
, "Buildroot is locked"
282 def copyin(self
, file_out
, file_in
):
283 if file_in
.startswith("/"):
284 file_in
= file_in
[1:]
286 file_in
= self
.chrootPath(file_in
)
288 #if not os.path.exists(file_out):
291 dir_in
= os
.path
.dirname(file_in
)
292 if not os
.path
.exists(dir_in
):
295 self
.log
.debug("%s --> %s" % (file_out
, file_in
))
297 shutil
.copy2(file_out
, file_in
)
299 def copyout(self
, file_in
, file_out
):
300 if file_in
.startswith("/"):
301 file_in
= file_in
[1:]
303 file_in
= self
.chrootPath(file_in
)
305 #if not os.path.exists(file_in):
308 dir_out
= os
.path
.dirname(file_out
)
309 if not os
.path
.exists(dir_out
):
312 self
.log
.debug("%s --> %s" % (file_in
, file_out
))
314 shutil
.copy2(file_in
, file_out
)
316 def copy_result(self
, resultdir
):
317 # XXX should use find_result_packages
319 dir_in
= self
.chrootPath("result")
321 for dir, subdirs
, files
in os
.walk(dir_in
):
322 basename
= os
.path
.basename(dir)
323 dir = dir[len(self
.chrootPath()):]
325 file_in
= os
.path
.join(dir, file)
327 file_out
= os
.path
.join(
333 self
.copyout(file_in
, file_out
)
335 def find_result_packages(self
):
338 for dir, subdirs
, files
in os
.walk(self
.resultdir
):
340 if not file.endswith(".%s" % PACKAGE_EXTENSION
):
343 file = os
.path
.join(dir, file)
348 def extract(self
, requires
=None, build_deps
=True):
350 Gets a dependency set and extracts all packages
356 if self
.use_cache
and os
.path
.exists(self
.cache_file
):
357 # If we are told to use the cache, we just import the
361 # Add neccessary build dependencies.
362 requires
+= BUILD_PACKAGES
364 # If we have ccache enabled, we need to extract it
365 # to the build chroot.
366 if self
.settings
.get("enable_ccache"):
367 requires
.append("ccache")
369 # If we have icecream enabled, we need to extract it
370 # to the build chroot.
371 if self
.settings
.get("enable_icecream"):
372 requires
.append("icecream")
374 # Get build dependencies from source package.
376 for req
in self
.pkg
.requires
:
379 # Install all packages.
380 self
.log
.info(_("Install packages needed for build..."))
381 self
.install(requires
)
383 # Copy the makefile and load source tarballs.
385 self
.pkg
.extract(_("Extracting"), prefix
=self
.build_dir
)
387 def install(self
, requires
):
389 Install everything that is required in requires.
391 # If we got nothing to do, we quit immediately.
396 self
.pakfire
.install(requires
, interactive
=False,
397 allow_downgrade
=True, logger
=self
.log
)
399 # Catch dependency errors and log it.
400 except DependencyError
, e
:
403 def install_test(self
):
405 self
.pakfire
.localinstall(self
.find_result_packages(), yes
=True, allow_uninstall
=True, logger
=self
.log
)
407 # Dependency errors when trying to install the result packages are build errors.
408 except DependencyError
, e
:
409 # Dump all packages (for debugging).
414 def chrootPath(self
, *args
):
415 # Remove all leading slashes
418 if arg
.startswith("/"):
423 ret
= os
.path
.join(self
.path
, *args
)
424 ret
= ret
.replace("//", "/")
426 assert ret
.startswith(self
.path
)
430 def populate_dev(self
):
444 # If we need loop devices (which are optional) we create them here.
445 if self
.settings
["enable_loop_devices"]:
446 for i
in range(0, 7):
447 nodes
.append("/dev/loop%d" % i
)
450 # Stat the original node of the host system and copy it to
452 node_stat
= os
.stat(node
)
454 self
._create
_node
(node
, node_stat
.st_mode
, node_stat
.st_rdev
)
456 os
.symlink("/proc/self/fd/0", self
.chrootPath("dev", "stdin"))
457 os
.symlink("/proc/self/fd/1", self
.chrootPath("dev", "stdout"))
458 os
.symlink("/proc/self/fd/2", self
.chrootPath("dev", "stderr"))
459 os
.symlink("/proc/self/fd", self
.chrootPath("dev", "fd"))
463 Add DNS resolution facility to chroot environment by copying
464 /etc/resolv.conf and /etc/hosts.
466 for i
in ("/etc/resolv.conf", "/etc/hosts"):
469 def _create_node(self
, filename
, mode
, device
):
470 self
.log
.debug("Create node: %s (%s)" % (filename
, mode
))
472 filename
= self
.chrootPath(filename
)
474 # Create parent directory if it is missing.
475 dirname
= os
.path
.dirname(filename
)
476 if not os
.path
.exists(dirname
):
479 os
.mknod(filename
, mode
, device
)
482 self
.log
.debug("Destroying environment %s" % self
.path
)
484 if os
.path
.exists(self
.path
):
488 self
.log
.debug("Cleaning environemnt.")
490 # Remove the build directory and buildroot.
491 dirs
= (self
.build_dir
, self
.chrootPath("result"),)
494 if not os
.path
.exists(d
):
501 self
.log
.debug("Mounting environment")
502 for src
, dest
, fs
, options
in self
.mountpoints
:
503 mountpoint
= self
.chrootPath(dest
)
505 options
= "-o %s" % options
507 # Eventually create mountpoint directory
508 if not os
.path
.exists(mountpoint
):
509 os
.makedirs(mountpoint
)
511 cmd
= "mount -n -t %s %s %s %s" % \
512 (fs
, options
, src
, mountpoint
)
513 chroot
.do(cmd
, shell
=True)
515 def _umountall(self
):
516 self
.log
.debug("Umounting environment")
519 for src
, dest
, fs
, options
in reversed(self
.mountpoints
):
520 if not dest
in mountpoints
:
521 mountpoints
.append(dest
)
523 for dest
in mountpoints
:
524 mountpoint
= self
.chrootPath(dest
)
526 chroot
.do("umount -n %s" % mountpoint
, raiseExc
=0, shell
=True)
529 def mountpoints(self
):
532 # Make root as a tmpfs.
534 # ("pakfire_root", "/", "tmpfs", "defaults"),
538 # src, dest, fs, options
539 ("pakfire_proc", "/proc", "proc", "nosuid,noexec,nodev"),
540 ("/proc/sys", "/proc/sys", "bind", "bind"),
541 ("/proc/sys", "/proc/sys", "bind", "bind,ro,remount"),
542 ("/sys", "/sys", "bind", "bind"),
543 ("/sys", "/sys", "bind", "bind,ro,remount"),
544 ("pakfire_tmpfs", "/dev", "tmpfs", "mode=755,nosuid"),
545 ("/dev/pts", "/dev/pts", "bind", "bind"),
546 ("pakfire_tmpfs", "/run", "tmpfs", "mode=755,nosuid,nodev"),
549 # If selinux is enabled.
550 if os
.path
.exists("/sys/fs/selinux"):
552 ("/sys/fs/selinux", "/sys/fs/selinux", "bind", "bind"),
553 ("/sys/fs/selinux", "/sys/fs/selinux", "bind", "bind,ro,remount"),
556 # If ccache support is requested, we bind mount the cache.
557 if self
.settings
.get("enable_ccache"):
558 # Create ccache cache directory if it does not exist.
559 if not os
.path
.exists(CCACHE_CACHE_DIR
):
560 os
.makedirs(CCACHE_CACHE_DIR
)
563 (CCACHE_CACHE_DIR
, "/var/cache/ccache", "bind", "bind"),
571 # Add HOME manually, because it is occasionally not set
572 # and some builds get in trouble then.
574 "TERM" : os
.environ
.get("TERM", "dumb"),
578 "LANG" : os
.environ
.setdefault("LANG", "en_US.UTF-8"),
580 # Set the container that we can detect, if we are inside a
582 "container" : "pakfire-builder",
585 # Inherit environment from distro
586 env
.update(self
.pakfire
.distro
.environ
)
588 # Icecream environment settings
589 if self
.settings
.get("enable_icecream", False):
590 # Set the toolchain path
591 if self
.settings
.get("icecream_toolchain", None):
592 env
["ICECC_VERSION"] = self
.settings
.get("icecream_toolchain")
594 # Set preferred host if configured.
595 if self
.settings
.get("icecream_preferred_host", None):
596 env
["ICECC_PREFERRED_HOST"] = \
597 self
.settings
.get("icecream_preferred_host")
599 # Fake UTS_MACHINE, when we cannot use the personality syscall and
600 # if the host architecture is not equal to the target architecture.
601 if not self
.pakfire
.distro
.personality
and \
602 not system
.native_arch
== self
.pakfire
.distro
.arch
:
604 "LD_PRELOAD" : "/usr/lib/libpakfire_preload.so",
605 "UTS_MACHINE" : self
.pakfire
.distro
.arch
,
611 def installed_packages(self
):
613 Returns an iterator over all installed packages in this build environment.
615 # Get the repository of all installed packages.
616 repo
= self
.pakfire
.repos
.get_repo("@system")
618 # Return an iterator over the packages.
621 def write_config(self
):
622 # Cleanup everything in /etc/pakfire.
623 util
.rm(self
.chrootPath(CONFIG_DIR
))
625 for i
in (CONFIG_DIR
, CONFIG_REPOS_DIR
):
626 i
= self
.chrootPath(i
)
627 if not os
.path
.exists(i
):
630 # Write general.conf.
631 f
= open(self
.chrootPath(CONFIG_DIR
, "general.conf"), "w")
634 # Write builder.conf.
635 f
= open(self
.chrootPath(CONFIG_DIR
, "builder.conf"), "w")
636 f
.write(self
.distro
.get_config())
639 # Create pakfire configuration files.
640 for repo
in self
.pakfire
.repos
:
641 conf
= repo
.get_config()
646 filename
= self
.chrootPath(CONFIG_REPOS_DIR
, "%s.repo" % repo
.name
)
647 f
= open(filename
, "w")
648 f
.write("\n".join(conf
))
651 def do(self
, command
, shell
=True, personality
=None, logger
=None, *args
, **kwargs
):
654 # Environment variables
657 if kwargs
.has_key("env"):
658 env
.update(kwargs
.pop("env"))
660 self
.log
.debug("Environment:")
661 for k
, v
in sorted(env
.items()):
662 self
.log
.debug(" %s=%s" % (k
, v
))
664 # Update personality it none was set
666 personality
= self
.distro
.personality
668 # Make every shell to a login shell because we set a lot of
669 # environment things there.
671 command
= ["bash", "--login", "-c", command
]
673 if not kwargs
.has_key("chrootPath"):
674 kwargs
["chrootPath"] = self
.chrootPath()
678 personality
=personality
,
688 def build(self
, install_test
=True):
690 raise BuildError
, _("You cannot run a build when no package was given.")
692 # Search for the package file in build_dir and raise BuildError if it is not present.
693 pkgfile
= os
.path
.join(self
.build_dir
, "%s.%s" % (self
.pkg
.name
, MAKEFILE_EXTENSION
))
694 if not os
.path
.exists(pkgfile
):
695 raise BuildError
, _("Could not find makefile in build root: %s") % pkgfile
696 pkgfile
= "/%s" % os
.path
.relpath(pkgfile
, self
.chrootPath())
698 # Write pakfire configuration into the chroot.
701 # Create the build command, that is executed in the chroot.
703 "/usr/lib/pakfire/builder",
709 "--resultdir=/result",
713 self
.do(" ".join(build_command
), logger
=self
.log
)
716 self
.log
.error(_("Build failed."), exc_info
=True)
718 raise BuildError
, _("The build command failed. See logfile for details.")
720 # Sign all built packages with the host key (if available).
721 if self
.settings
.get("sign_packages"):
722 host_key
= self
.keyring
.get_host_key()
728 # Perform install test.
732 # Dump package information.
735 def shell(self
, args
=[]):
736 if not util
.cli_is_interactive():
737 self
.log
.warning("Cannot run shell on non-interactive console.")
740 # Install all packages that are needed to run a shell.
741 self
.install(SHELL_PACKAGES
)
743 # XXX need to set CFLAGS here
744 command
= "/usr/sbin/chroot %s %s %s" % \
745 (self
.chrootPath(), SHELL_SCRIPT
, " ".join(args
))
747 # Add personality if we require one
748 if self
.pakfire
.distro
.personality
:
749 command
= "%s %s" % (self
.pakfire
.distro
.personality
, command
)
751 for key
, val
in self
.environ
.items():
752 command
= "%s=\"%s\" " % (key
, val
) + command
754 # Empty the environment
755 command
= "env -i - %s" % command
757 self
.log
.debug("Shell command: %s" % command
)
759 shell
= os
.system(command
)
760 return os
.WEXITSTATUS(shell
)
762 def sign(self
, keyfp
):
763 assert self
.keyring
.get_key(keyfp
), "Key for signing does not exist"
765 # Find all files to process.
766 files
= self
.find_result_packages()
768 # Create a progressbar.
769 p
= util
.make_progress(_("Signing files (%s)") % keyfp
, len(files
))
773 # Update progressbar.
779 pkg
= packages
.open(self
.pakfire
, None, file)
791 for file in self
.find_result_packages():
792 pkg
= packages
.open(self
.pakfire
, None, file)
795 # If there are no packages, there is nothing to do.
801 self
.log
.info(_("Dumping package information:"))
803 dump
= pkg
.dump(long=True)
805 for line
in dump
.splitlines():
806 self
.log
.info(" %s" % line
)
807 self
.log
.info("") # Empty line.
810 def cache_file(self
):
812 self
.pakfire
.distro
.sname
, # name of the distribution
813 self
.pakfire
.distro
.release
, # release version
814 self
.pakfire
.distro
.arch
, # architecture
817 return os
.path
.join(CACHE_ENVIRON_DIR
, "%s.cache" %"-".join(comps
))
819 def cache_export(self
, filename
):
820 # Sync all disk caches.
823 # A list to store all mountpoints, so we don't package them.
826 # A list containing all files we want to package.
829 # Walk through the whole tree and collect all files
830 # that are on the same disk (not crossing mountpoints).
831 log
.info(_("Creating filelist..."))
832 root
= self
.chrootPath()
833 for dir, subdirs
, files
in os
.walk(root
):
834 # Search for mountpoints and skip them.
835 if not dir == root
and os
.path
.ismount(dir):
836 mountpoints
.append(dir)
839 # Skip all directories under mountpoints.
840 if any([dir.startswith(m
) for m
in mountpoints
]):
843 # Add all other files.
846 file = os
.path
.join(dir, file)
847 filelist
.append(file)
849 # Create a nice progressbar.
850 p
= util
.make_progress(_("Compressing files..."), len(filelist
))
853 # Create tar file and add all files to it.
854 f
= packages
.file.InnerTarFile
.open(filename
, "w:gz")
855 for file in filelist
:
860 f
.add(file, os
.path
.relpath(file, root
), recursive
=False)
863 # Finish progressbar.
867 filesize
= os
.path
.getsize(filename
)
869 log
.info(_("Cache file was successfully created at %s.") % filename
)
870 log
.info(_(" Containing %(files)s files, it has a size of %(size)s.") % \
871 { "files" : len(filelist
), "size" : util
.format_size(filesize
), })
873 def cache_extract(self
):
874 root
= self
.chrootPath()
875 filename
= self
.cache_file
877 f
= packages
.file.InnerTarFile
.open(filename
, "r:gz")
878 members
= f
.getmembers()
880 # Make a nice progress bar as always.
881 p
= util
.make_progress(_("Extracting files..."), len(members
))
883 # Extract all files from the cache.
885 for member
in members
:
890 f
.extract(member
, path
=root
)
893 # Finish progressbar.
897 # Re-read local repository.
898 self
.pakfire
.repos
.local
.update(force
=True)
900 # Update all packages.
901 self
.log
.info(_("Updating packages from cache..."))
902 self
.pakfire
.update(interactive
=False, logger
=self
.log
,
903 allow_archchange
=True, allow_vendorchange
=True, allow_downgrade
=True)
906 class Builder(object):
907 def __init__(self
, pakfire
, filename
, resultdir
, **kwargs
):
908 self
.pakfire
= pakfire
910 self
.filename
= filename
912 self
.resultdir
= resultdir
915 self
.pkg
= packages
.Makefile(self
.pakfire
, self
.filename
)
923 Create a temporary file in the build environment.
925 file = "/tmp/pakfire_%s" % util
.random_string()
935 return self
.pkg
.buildroot
939 return self
.pakfire
.distro
945 # Get all definitions from the package.
946 environ
.update(self
.pkg
.exports
)
948 # Overwrite some definitions by default values.
949 environ
.update(self
._environ
)
953 def do(self
, command
, shell
=True, personality
=None, cwd
=None, *args
, **kwargs
):
954 # Environment variables
955 log
.debug("Environment:")
956 for k
, v
in sorted(self
.environ
.items()):
957 log
.debug(" %s=%s" % (k
, v
))
959 # Update personality it none was set
961 personality
= self
.distro
.personality
964 cwd
= "/%s" % LOCAL_TMP_PATH
966 # Make every shell to a login shell because we set a lot of
967 # environment things there.
969 command
= ["bash", "--login", "-c", command
]
973 personality
=personality
,
976 logger
=logging
.getLogger("pakfire"),
982 def create_icecream_toolchain(self
):
984 out
= self
.do("icecc --build-native 2>/dev/null", returnOutput
=True, cwd
="/tmp")
988 for line
in out
.splitlines():
989 m
= re
.match(r
"^creating ([a-z0-9]+\.tar\.gz)", line
)
991 self
._environ
["ICECC_VERSION"] = "/tmp/%s" % m
.group(1)
993 def create_buildscript(self
, stage
):
994 file = "/tmp/build_%s" % util
.random_string()
996 # Get buildscript from the package.
997 script
= self
.pkg
.get_buildscript(stage
)
999 # Write script to an empty file.
1001 f
.write("#!/bin/sh\n\n")
1004 f
.write("\n%s\n" % script
)
1012 # Create buildroot and remove all content if it was existant.
1013 util
.rm(self
.buildroot
)
1014 os
.makedirs(self
.buildroot
)
1016 # Build icecream toolchain if icecream is installed.
1017 self
.create_icecream_toolchain()
1019 for stage
in ("prepare", "build", "test", "install"):
1020 self
.build_stage(stage
)
1022 # Run post-build stuff.
1023 self
.post_compress_man_pages()
1024 self
.post_remove_static_libs()
1025 self
.post_extract_debuginfo()
1027 # Package the result.
1028 # Make all these little package from the build environment.
1029 log
.info(_("Creating packages:"))
1031 for pkg
in reversed(self
.pkg
.packages
):
1032 packager
= packages
.packager
.BinaryPackager(self
.pakfire
, pkg
,
1033 self
, self
.buildroot
)
1034 pkg
= packager
.run(self
.resultdir
)
1038 def build_stage(self
, stage
):
1039 # Get the buildscript for this stage.
1040 buildscript
= self
.create_buildscript(stage
)
1042 # Execute the buildscript of this stage.
1043 log
.info(_("Running stage %s:") % stage
)
1046 self
.do(buildscript
, shell
=False)
1049 # Remove the buildscript.
1050 if os
.path
.exists(buildscript
):
1051 os
.unlink(buildscript
)
1053 def post_remove_static_libs(self
):
1054 keep_libs
= self
.pkg
.lexer
.build
.get_var("keep_libraries")
1055 keep_libs
= keep_libs
.split()
1058 self
.do("%s/remove-static-libs %s %s" % \
1059 (SCRIPT_DIR
, self
.buildroot
, " ".join(keep_libs
)))
1061 log
.warning(_("Could not remove static libraries: %s") % e
)
1063 def post_compress_man_pages(self
):
1065 self
.do("%s/compress-man-pages %s" % (SCRIPT_DIR
, self
.buildroot
))
1067 log
.warning(_("Compressing man pages did not complete successfully."))
1069 def post_extract_debuginfo(self
):
1072 # Check if we need to run with strict build-id.
1073 strict_id
= self
.pkg
.lexer
.build
.get_var("debuginfo_strict_build_id", "true")
1074 if strict_id
in ("true", "yes", "1"):
1075 args
.append("--strict-build-id")
1077 args
.append("--buildroot=%s" % self
.pkg
.buildroot
)
1078 args
.append("--sourcedir=%s" % self
.pkg
.sourcedir
)
1080 # Get additional options to pass to script.
1081 options
= self
.pkg
.lexer
.build
.get_var("debuginfo_options", "")
1082 args
+= options
.split()
1085 self
.do("%s/extract-debuginfo %s %s" % (SCRIPT_DIR
, " ".join(args
), self
.pkg
.buildroot
))
1087 log
.error(_("Extracting debuginfo did not complete with success. Aborting build."))
1091 if os
.path
.exists(self
.buildroot
):
1092 util
.rm(self
.buildroot
)