diff --git a/CraftSettings.ini.template b/CraftSettings.ini.template index 5edb5a2e2..4e30492c4 100644 --- a/CraftSettings.ini.template +++ b/CraftSettings.ini.template @@ -1,220 +1,225 @@ ## You can use cmake like variables for values in the same section ${Variable} ## or for variables from a different section ${Section:Variable}. ## See Paths/${DOWNLOADDIR} [General] ## Here you set the ABI to be used. ## #platform-#abi-#compiler ## Valid combinations are: ## windows-msvc[2015, 2017]_[32, 64]-[cl, clang] ## windows-mingw_[32, 64]-[gcc, clang] ## linux-[32, 64]-[gcc, clang] ## macos-[32, 64]-clang ## freebsd-[32, 64]-clang ABI = windows-msvc2015_64-cl ## This option should be set to False if you use the msvc 201X Express Edition 64bit compiler ## in all other cases, simply keep this option commented out #Native=False ## This option can be used to enable a notification backend. ## As soon as the buildprocess of a project has finished a notification will be displayed. ## Possible Backends: ## Snore https://commits.kde.org/snorenotify. Snore supports multiple backends. ## Just 'craft snorenotify' ## To configure snorenotify for craft call 'snoresettings --appName snoresend' #Notify = Snore ## Speed up the merging of packages by using hard links UseHardlinks = True [Variables] ## Values here are usually set by craft and can be used for dynamic values ## To override the variables, uncomment them ## The working directory of Craft #CraftRoot = ## The directory of the Craft clone #CraftDir = [Paths] ## This is the location of your python installation. ## This value must be set. Python = C:\PROGRA~1\Python36 ## Some applications may need python 2.7 #Python27 = C:\python27 ## Craft ist able to fetch and install Msys itself, but if you prefer to use ## your own installation specify it here #Msys = C:\msys ## Here you change the download directory. ## If you want, so you can share the same download directory between ## mingw and msvc. ## The default value is craft/../download #DownloadDir = C:\kde\download ## This option defines the location for git checkouts. ## The default value is craft/../download/git #KDEGitDir = ${DOWNLOADDIR}\git ## This option defines the location for svn checkouts. ## The default value is craft/../download/svn #KDESVNDir = ${DOWNLOADDIR}\svn ## This option defines the location where the ccache files are stored. ## The default location is KDEROOT/build/ccache #CCACHE_DIR = C:\CCACHE\kf5 [Compile] ## the buildtype of this installation ## Possible Values: ## Release ## RelWithDebInfo ## Debug ## MinSizeRel BuildType = RelWithDebInfo ## Whether to use ninja (default: False) UseNinja = True ## Whether to use ccache (only avalible with mingw compiler) #UseCCache = True ## This option can be used to override the default make program ## change the value to the path of the executable you want to use instead. MakeProgram = jom [CMake] ## Fetch the translations for KDE projects when build from git KDE_L10N_AUTO_TRANSLATIONS = OFF [ShortPath] ## substitute pathes by drives ## This option is needed to avoid path limit problems in case of long base pathes ## and compiling big packages like qt ## If you disable it do _not_ use any paths longer than 6 letters in the ## directory settings Enabled = True ## each drive could be commented out to skip substution RootDrive = R: GitDrive = Q: #DownloadDrive = T: ## Experimental!!! ## Use Junctions to work around long paths. #EnableJunctions = True ## The directory where the junctions are created. #JunctionDir= ## A drive letter where JunctionDir is mounted to. ## When this variable is defined craft will mount the drive even if [ShortPath]Enabled == False #JunctionDrive = Z: [Blueprints] ## The location where the default blueprints are stored ## This is especially useful when using multiple Craft setups #BlueprintRoot = ${Variables:CraftRoot}/etc/blueprints/locations ## The locations of the recipes ## You can specify additional external locations in ; seperated list #Locations = C:\blueprints # Customer settings Settings = ${Variables:CraftRoot}/etc/BlueprintSettings.ini [BlueprintVersions] ## Allow to automatically update certain recipes once a day. EnableDailyUpdates = True [Packager] ## The archive type for packages. ## Possible values are: zip, 7z ## Todo: rename #7ZipArchiveType = 7z ## If set this will override the default package type. ## Possible values are: ### SevenZipPackager: An image of the files installed by the package ### MSIFragmentPackager ### NullsoftInstallerPackager: A nsis based installer including all dependencies ### CreateArchivePackager: An image including all dependencies #PackageType = SevenZipPackager ## Package the Source files too. PackageSrc = False +## Whether to package debug symbols +### by default debug symbols are stripped/removed from the package +### If PackageDebugSymbols is set to True, a separate archive with the symbols is created. +PackageDebugSymbols = False + ## A url to a Craft cache repository ## Sets a custom repository for the binary cache #RepositoryUrl = https://files.kde.org/craft/master/ ## Enable to fatch packages from a Craft cache repository ## See --use-cache and --no-cache in the Craft help. UseCache = True [CraftDebug] ## If you want to have verbose output, uncomment the following option ## and set it to positive integer for verbose output and to 0 ## (or disable it) for normal output. Currently the highest verbosity level ## is 3 (equal to 'craft -v -v -v'). level -1 equals 'craft -q' ## Default is Verbose = 0 #Verbose = 1 # Log environment, prints the current state of the environment befor an application is run LogEnvironment = True ## Prints time spend on various craft tasks MeasureTime = False ## Dump internal state of craftSettings to kdesettings.ini.dump #DumpSettings = True ## Print function Deprecation messages LogDeprecated = True [Environment] ## All values defined here will be populated to the environment #GIT_COMMITTER_EMAIL = foo@bar.com ## Set the ssh client for git and svn. #GIT_SSH = plink #SVN_SSH = plink [QtSDK] ## For advanced users only ## Whether to use prebuild Qt binaries. Enabled = False ## The path to the Qt sdk. Path = D:\Qt ## The version of Qt. Version = 5.9 ## The compiler version, if you are not sure what to use, have a look into the derectory set in QtSDK/Path. ## The compiler must be of the same type as General/KDECOMPILER. ## If you are using mingw please make sure you have installed the mingw using the Qt installer. Compiler = mingw482_32 [ContinuousIntegration] ## Changes the verbosity of some sub processes. ## Installed versions must match. ## Don't write to stderr Enabled = False ## Delete the build folder after the install ClearBuildFolder = False [CodeSigning] Enabled = False SubjectName = K Desktop Environment e.V. [Version] ConfigVersion = 4 diff --git a/bin/Package/PackageBase.py b/bin/Package/PackageBase.py index 3404af200..ef7c7d444 100644 --- a/bin/Package/PackageBase.py +++ b/bin/Package/PackageBase.py @@ -1,256 +1,256 @@ # # copyright (c) 2009 Ralf Habacker # from CraftBase import * from CraftCompiler import * from InstallDB import * from Blueprints.CraftPackageObject import * from Utils import CraftHash from Utils.CraftManifest import CraftManifest class PackageBase(CraftBase): """ provides a generic interface for packages and implements the basic stuff for all packages """ # uses the following instance variables # todo: place in related ...Base # rootdir -> CraftBase # package -> PackageBase # force -> PackageBase # category -> PackageBase # version -> PackageBase # packagedir -> PackageBase # imagedir -> PackageBase def __init__(self): CraftCore.log.debug("PackageBase.__init__ called") CraftBase.__init__(self) def qmerge(self): """mergeing the imagedirectory into the filesystem""" ## \todo is this the optimal place for creating the post install scripts ? if self.package.isInstalled: self.unmerge() copiedFiles = [] # will be populated by the next call if not utils.copyDir(self.imageDir(), CraftCore.standardDirs.craftRoot(), copiedFiles=copiedFiles): return False # add package to installed database -> is this not the task of the manifest files ? revision = self.sourceRevision() package = CraftCore.installdb.addInstalled(self.package, self.version, revision=revision) fileList = self.getFileListFromDirectory(CraftCore.standardDirs.craftRoot(), copiedFiles) package.addFiles(fileList) package.install() if (CraftCore.settings.getboolean("Packager", "CreateCache") or CraftCore.settings.getboolean("Packager", "UseCache")): package.setCacheVersion(self.cacheVersion()) return True def unmerge(self): """unmergeing the files from the filesystem""" CraftCore.log.debug("Packagebase unmerge called") packageList = CraftCore.installdb.getInstalledPackages(self.package) for package in packageList: fileList = package.getFilesWithHashes() self.unmergeFileList(CraftCore.standardDirs.craftRoot(), fileList) package.uninstall() return True def cleanBuild(self) -> bool: """cleanup currently used build dir""" if os.path.exists(self.buildDir()): utils.cleanDirectory(self.buildDir()) CraftCore.log.debug("cleaning build dir: %s" % self.buildDir()) return True def strip(self, fileName): """strip debugging informations from shared libraries and executables - mingw only!!! """ if self.subinfo.options.package.disableStriping or CraftCore.compiler.isMSVC() or not CraftCore.compiler.isGCCLike(): - CraftCore.log.debug(f"Skipping stripping of {fileName} -- either disabled or unsupported with this compiler") + CraftCore.log.warning(f"Skipping stripping of {fileName} -- either disabled or unsupported with this compiler") return True if OsUtils.isMac(): CraftCore.log.debug(f"Skipping stripping of files on macOS -- not implemented") return True if os.path.isabs(fileName): filepath = fileName else: CraftCore.log.warning("Please pass an absolute file path to strip") basepath = os.path.join(self.installDir()) filepath = os.path.join(basepath, "bin", fileName) return utils.system(["strip", "-s", filepath]) def createImportLibs(self, pkgName): """create the import libraries for the other compiler(if ANSI-C libs)""" basepath = os.path.join(self.installDir()) utils.createImportLibs(pkgName, basepath) def printFiles(self): packageList = CraftCore.installdb.getInstalledPackages(self.package) for package in packageList: fileList = package.getFiles() fileList.sort() for file in fileList: print(file[0]) return True def getAction(self, cmd=None): if not cmd: command = sys.argv[1] options = None # print sys.argv if (len(sys.argv) > 2): options = sys.argv[2:] else: command = cmd options = None # \todo options are not passed through by craft.py fix it return [command, options] def execute(self, cmd=None): """called to run the derived class this will be executed from the package if the package is started on its own it shouldn't be called if the package is imported as a python module""" CraftCore.log.debug("PackageBase.execute called. args: %s" % sys.argv) command, _ = self.getAction(cmd) return self.runAction(command) def fetchBinary(self) -> bool: if self.subinfo.options.package.disableBinaryCache: return False for url in [self.cacheLocation()] + self.cacheRepositoryUrls(): CraftCore.log.debug(f"Trying to restore {self} from cache: {url}.") manifest = CraftManifest.fromJson(CraftCore.cache.cacheJsonFromUrl(f"{url}/manifest.json")) fileEntry = manifest.get(str(self)).files files = [] for f in fileEntry: if f.version == self.version: files.append(f) latest = None if not files: CraftCore.log.debug(f"Could not find {self}={self.version} in {url}") continue latest = files[0] if url != self.cacheLocation(): downloadFolder = self.cacheLocation(os.path.join(CraftCore.standardDirs.downloadDir(), "cache")) else: downloadFolder = self.cacheLocation() localArchiveAbsPath = OsUtils.toNativePath(os.path.join(downloadFolder, latest.fileName)) localArchivePath, localArchiveName = os.path.split(localArchiveAbsPath) if url != self.cacheLocation(): if not os.path.exists(localArchiveAbsPath): os.makedirs(localArchivePath, exist_ok=True) fUrl = f"{url}/{latest.fileName}" if not utils.getFile(fUrl, localArchivePath, localArchiveName): CraftCore.log.warning(f"Failed to fetch {fUrl}") return False elif not os.path.isfile(localArchiveAbsPath): continue if not CraftHash.checkFilesDigests(localArchivePath, [localArchiveName], digests=latest.checksum, digestAlgorithm=CraftHash.HashAlgorithm.SHA256): CraftCore.log.warning(f"Hash did not match, {localArchiveName} might be corrupted") return False self.subinfo.buildPrefix = latest.buildPrefix if not (self.cleanImage() and utils.unpackFile(localArchivePath, localArchiveName, self.imageDir()) and self.internalPostInstall() and self.postInstall() and self.qmerge() and self.internalPostQmerge() and self.postQmerge()): return False return True return False @staticmethod def getFileListFromDirectory(imagedir, filePaths): """ create a file list containing hashes """ ret = [] algorithm = CraftHash.HashAlgorithm.SHA256 for filePath in filePaths: relativeFilePath = os.path.relpath(filePath, imagedir) digest = algorithm.stringPrefix() + CraftHash.digestFile(filePath, algorithm) ret.append((relativeFilePath, digest)) return ret @staticmethod def unmergeFileList(rootdir, fileList): """ delete files in the fileList if has matches """ for filename, filehash in fileList: fullPath = os.path.join(rootdir, os.path.normcase(filename)) if os.path.isfile(fullPath) or os.path.islink(fullPath): if filehash: algorithm = CraftHash.HashAlgorithm.getAlgorithmFromPrefix(filehash) currentHash = algorithm.stringPrefix() + CraftHash.digestFile(fullPath, algorithm) if not filehash or currentHash == filehash: OsUtils.rm(fullPath, True) else: CraftCore.log.warning( f"We can't remove {fullPath} as its hash has changed," f" that usually implies that the file was modified or replaced") elif not os.path.isdir(fullPath) and os.path.lexists(fullPath): CraftCore.log.debug(f"Remove a dead symlink {fullPath}") OsUtils.rm(fullPath, True) elif not os.path.isdir(fullPath): CraftCore.log.warning("file %s does not exist" % fullPath) containingDir = os.path.dirname(fullPath) if os.path.exists(containingDir) and not os.listdir(containingDir): CraftCore.log.info(f"Delete empty dir {containingDir}") utils.rmtree(containingDir) def runAction(self, command): functions = {"fetch": "fetch", "cleanimage": "cleanImage", "cleanbuild": "cleanBuild", "unpack": "unpack", "compile": "compile", "configure": "configure", "make": "make", "install": ["install", "internalPostInstall"], "post-install": "postInstall", "test": "unittest", "qmerge": ["qmerge", "internalPostQmerge"], "post-qmerge": "postQmerge", "unmerge": "unmerge", "package": "createPackage", "createpatch": "createPatch", "print-files": "printFiles", "checkdigest": "checkDigest", "fetch-binary": "fetchBinary"} if command in functions: try: steps = functions[command] if not isinstance(steps, list): steps = [steps] for step in steps: if not getattr(self, step)(): return False except AttributeError as e: raise BlueprintException(str(e), self.package, e) else: CraftCore.log.error("command %s not understood" % command) return False return True diff --git a/bin/Packager/CollectionPackagerBase.py b/bin/Packager/CollectionPackagerBase.py index 89a1efad2..1674af3c6 100644 --- a/bin/Packager/CollectionPackagerBase.py +++ b/bin/Packager/CollectionPackagerBase.py @@ -1,326 +1,329 @@ # -*- coding: utf-8 -*- # Copyright Hannah von Reth # copyright (c) 2010-2011 Patrick Spendrin # copyright (c) 2010 Andre Heinecke (code taken from the kdepim-ce-package.py) # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. import types import glob from Packager.PackagerBase import * from Blueprints.CraftDependencyPackage import DependencyType, CraftDependencyPackage from Blueprints.CraftPackageObject import * from Package.SourceOnlyPackageBase import * def toRegExp(fname, targetName) -> re: """ Read regular expressions from fname """ assert os.path.isabs(fname) if not os.path.isfile(fname): CraftCore.log.critical("%s not found at: %s" % (targetName.capitalize(), os.path.abspath(fname))) regex = [] with open(fname, "rt+") as f: for line in f: # Cleanup white spaces / line endings line = line.strip() if not line or line.startswith("#"): continue try: # accept forward and backward slashes line = line.replace("/", r"[/\\]") tmp = f"^{line}$" re.compile(tmp) # for debug regex.append(tmp) CraftCore.log.debug(f"{line} added to {targetName} as {tmp}") except re.error as e: raise Exception(f"{tmp} is not a valid regular expression: {e}") return re.compile(f"({'|'.join(regex)})", re.IGNORECASE) class PackagerLists(object): """ This class provides some staticmethods that can be used as pre defined black or whitelists """ @staticmethod def runtimeBlacklist(): return os.path.join(os.path.dirname(os.path.abspath(__file__)), "applications_blacklist.txt") @staticmethod def defaultWhitelist(): return [re.compile("^$")] @staticmethod def defaultBlacklist(): return [toRegExp(PackagerLists.runtimeBlacklist(), "blacklist")] class CollectionPackagerBase(PackagerBase): reMsvcDebugRt = re.compile(r"VCRUNTIME.*D\.DLL", re.IGNORECASE) @InitGuard.init_once def __init__(self, whitelists=None, blacklists=None): PackagerBase.__init__(self) if not whitelists: whitelists = [PackagerLists.defaultWhitelist] if not blacklists: blacklists = [PackagerLists.defaultBlacklist] if not self.whitelist_file: self.whitelist_file = whitelists if not self.blacklist_file: self.blacklist_file = blacklists self._whitelist = [] self._blacklist = [] self.scriptname = None self.__deployQtSdk = (OsUtils.isWin() and CraftCore.settings.getboolean("QtSDK", "Enabled", False) and CraftCore.settings.getboolean("QtSDK","PackageQtSDK",True)) self.__qtSdkDir = OsUtils.toNativePath(os.path.join(CraftCore.settings.get("QtSDK", "Path"), CraftCore.settings.get("QtSDK", "Version"), CraftCore.settings.get("QtSDK", "Compiler"))) if self.__deployQtSdk else None @property def whitelist(self): if not self._whitelist: for entry in self.whitelist_file: CraftCore.log.debug("reading whitelist: %s" % entry) if callable(entry): for line in entry(): self._whitelist.append(line) else: self.read_whitelist(entry) return self._whitelist @property def blacklist(self): if not self._blacklist: for entry in self.blacklist_file: CraftCore.log.debug("reading blacklist: %s" % entry) if callable(entry): if entry == PackagerLists.runtimeBlacklist: CraftCore.log.warn("Compat mode for PackagerLists.runtimeBlacklist -- please just use self.blacklist_file.append(\"myblacklist.txt\") instead of self.blacklist_file = [...]") self.read_blacklist(entry()) continue for line in entry(): self._blacklist.append(line) else: self.read_blacklist(entry) return self._blacklist def __imageDirPattern(self, package, buildTarget): """ return base directory name for package related image directory """ directory = "image" if package.subinfo.options.useBuildType == True: directory += '-' + package.buildType() directory += '-' + buildTarget return directory def __getImageDirectories(self): """ return the image directories where the files are stored """ imageDirs = [] depList = CraftDependencyPackage(self.package).getDependencies(depType=DependencyType.Runtime|DependencyType.Packaging, ignoredPackages=self.ignoredPackages) for x in depList: _package = x.instance if isinstance(_package, SourceOnlyPackageBase): CraftCore.log.debug(f"Ignoring package it is source only: {x}") continue imageDirs.append((x.instance.imageDir(), x.subinfo.options.package.disableStriping)) # this loop collects the files from all image directories CraftCore.log.debug(f"__getImageDirectories: package: {x}, version: {x.version}") if self.__deployQtSdk: imageDirs.append((self.__qtSdkDir, False)) return imageDirs def read_whitelist(self, fname): if not os.path.isabs(fname): fname = os.path.join(self.packageDir(), fname) """ Read regular expressions from fname """ try: self._whitelist.append(toRegExp(fname, "whitelist")) except Exception as e: raise BlueprintException(str(e), self.package) def read_blacklist(self, fname): if not os.path.isabs(fname): fname = os.path.join(self.packageDir(), fname) """ Read regular expressions from fname """ try: self._blacklist.append(toRegExp(fname, "blacklist")) except Exception as e: raise BlueprintException(str(e), self.package) def whitelisted(self, pathname): """ return True if pathname is included in the pattern, and False if not """ for pattern in self.whitelist: if pattern.search(pathname): CraftCore.log.debug(f"{pathname} is whitelisted: {pattern.pattern}") return True return False def blacklisted(self, filename): """ return False if file is not blacklisted, and True if it is blacklisted """ for pattern in self.blacklist: if pattern.search(filename): CraftCore.log.debug(f"{filename} is blacklisted: {pattern.pattern}") return True return False def _filterQtBuildType(self, filename): if not self.__deployQtSdk: return True filename = OsUtils.toNativePath(filename) if self.__qtSdkDir not in filename: return True if self.isBinary(filename): if not CraftCore.cache.findApplication("dependencies"): raise BlueprintException("Deploying a QtSdk depends on dev-util/dependencies", CraftPackageObject.get("dev-util/dependencies")) _, imports = CraftCore.cache.getCommandOutput("dependencies", f"-imports {filename}") rt = CollectionPackagerBase.reMsvcDebugRt.findall(imports) out = False if self.buildType() == "Debug": out = rt is not [] else: out = not rt if not out: CraftCore.log.debug(f"Skipp {filename} as it has the wrong build type: {rt}") return out return True def isDebugSymbolFile(self, fileName): _, ext = os.path.splitext(fileName) if ext in {".pdb"}: return True return False def isBinary(self, fileName): if os.path.islink(fileName): return False _, ext = os.path.splitext(fileName) if CraftCore.compiler.isWindows: if ext in {".dll", ".exe"}: return True else: if ext in {".so", ".dylib"} or os.access(fileName, os.X_OK): return True return False def traverse(self, root, whitelist=lambda f: True, blacklist=lambda g: False): """ Traverse through a directory tree and return every filename that the function whitelist returns as true and which do not match blacklist entries """ if blacklist(root) and not whitelist(root): return dirs = [root] while dirs: path = dirs.pop() for filePath in os.listdir(path): filePath = os.path.join(path, filePath) relFilePath = os.path.relpath(filePath, root) if blacklist(relFilePath) and not whitelist(relFilePath): continue if os.path.isdir(filePath) and not os.path.islink(filePath): dirs.append(filePath) elif os.path.isdir(filePath) and os.path.islink(filePath): yield filePath elif os.path.isfile(filePath): if self._filterQtBuildType(filePath): yield filePath def copyFiles(self, srcDir, destDir, dontStrip, symbolFiles : [str]=None) -> bool: """ Copy the binaries for the Package from srcDir to the imageDir directory """ CraftCore.log.debug("Copying %s -> %s" % (srcDir, destDir)) doSign = CraftCore.compiler.isWindows and CraftCore.settings.getboolean("CodeSigning", "Enabled", False) for entry in self.traverse(srcDir, self.whitelisted, self.blacklisted): entry_target = os.path.join(destDir, os.path.relpath(entry, srcDir)) if not utils.copyFile(entry, entry_target, linkOnly=False): return False if self.isBinary(entry_target): if dontStrip: self.strip(entry_target) if doSign: utils.sign([entry_target]) elif symbolFiles is not None and self.isDebugSymbolFile(entry_target): symbolFiles.append(entry_target) return True - def internalCreatePackage(self, packageSymbolFile=False) -> bool: + def internalCreatePackage(self, seperateSymbolFiles=False) -> bool: """ create a package """ archiveDir = self.archiveDir() CraftCore.log.debug("cleaning package dir: %s" % archiveDir) utils.cleanDirectory(archiveDir) - if packageSymbolFile: + if seperateSymbolFiles: + if not CraftCore.compiler.isMSVC(): + CraftCore.log.warning("Currently packaging symbol files is only supported with msvc") + return False symbolFiles = [] else: self.blacklist.append(re.compile(r".*\.pdb")) symbolFiles = None for directory, strip in self.__getImageDirectories(): if os.path.exists(directory): if not self.copyFiles(directory, archiveDir, strip, symbolFiles=symbolFiles): return False else: CraftCore.log.critical("image directory %s does not exist!" % directory) return False if symbolFiles: dbgDir = f"{archiveDir}-dbg" utils.cleanDirectory(dbgDir) for f in symbolFiles: dest = os.path.join(dbgDir, os.path.relpath(f, archiveDir)) utils.createDir(os.path.dirname(dest)) utils.moveFile(f, dest) if self.subinfo.options.package.movePluginsToBin: # Qt expects plugins and qml files below bin, on the target sytsem binPath = os.path.join(archiveDir, "bin") for path in [os.path.join(archiveDir, "plugins"), os.path.join(archiveDir, "qml")]: if os.path.isdir(path): if not utils.mergeTree(path, binPath): return False if not self.preArchive(): return False return True def preArchive(self): return True diff --git a/bin/Packager/PortablePackager.py b/bin/Packager/PortablePackager.py index 16f933252..9d99b393a 100644 --- a/bin/Packager/PortablePackager.py +++ b/bin/Packager/PortablePackager.py @@ -1,41 +1,46 @@ # # copyright (c) 2011 Hannah von Reth # from .CollectionPackagerBase import * from .SevenZipPackager import * from .NullsoftInstallerPackager import * class PortablePackager(CollectionPackagerBase, SevenZipPackager): """ Packager for portal 7zip archives """ @InitGuard.init_once def __init__(self, whitelists=None, blacklists=None): SevenZipPackager.__init__(self) CollectionPackagerBase.__init__(self, whitelists, blacklists) self.setupName = None - def createPortablePackage(self) -> bool: + def createPortablePackage(self, packageSymbols) -> bool: """create portable 7z package with digest files located in the manifest subdir""" self.setupName = self.defines.get("setupname", os.path.join(self.packageDestinationDir(), self.binaryArchiveName(includeRevision=True))) - if not os.path.isabs(self.setupName): - absSetupPath = os.path.join(self.packageDestinationDir(), self.setupName) + srcDir = self.defines.get("srcdir", self.archiveDir()) - srcdir = self.defines.get("srcdir", self.archiveDir()) + if not self._compress(self.setupName, srcDir, self.packageDestinationDir()): + return False + CraftHash.createDigestFiles(self.setupName) - return self._compress(self.setupName, srcdir, self.packageDestinationDir()) + if packageSymbols: + dbgDir = f"{srcDir}-dbg" + if os.path.exists(dbgDir): + dbgName = "{0}-dbg{1}".format(*os.path.splitext(self.setupName)) + if not self._compress(dbgName, dbgDir, self.packageDestinationDir()): + return False + CraftHash.createDigestFiles(dbgName) + return True def createPackage(self): """ create a package """ - if not self.internalCreatePackage(): - return False + packageSymbols = CraftCore.settings.get("Packager", "PackageDebugSymbols", False) - if not self.createPortablePackage(): - return False + if not self.internalCreatePackage(seperateSymbolFiles=packageSymbols): + return False - CraftHash.createDigestFiles(self.setupName) - - return True + return self.createPortablePackage(packageSymbols)