diff --git a/ports/ci/appveyor/deploy.sh b/ports/ci/appveyor/deploy.sh index 37d1b15..9ab2ab6 100644 --- a/ports/ci/appveyor/deploy.sh +++ b/ports/ci/appveyor/deploy.sh @@ -18,5 +18,10 @@ # # Web-Site: http://webcamoid.github.io/ +cd ports/deploy +git clone https://github.com/webcamoid/DeployTools.git +cd ../.. + export PATH=/mingw64/bin:$PATH +export PYTHONPATH="${PWD}/ports/deploy/DeployTools" python3 ports/deploy/deploy.py diff --git a/ports/ci/travis/deploy.sh b/ports/ci/travis/deploy.sh index 561e7bd..9228b1c 100644 --- a/ports/ci/travis/deploy.sh +++ b/ports/ci/travis/deploy.sh @@ -22,6 +22,10 @@ if [ "${TRAVIS_OS_NAME}" = linux ]; then EXEC='sudo ./root.x86_64/bin/arch-chroot root.x86_64' fi +cd ports/deploy +git clone https://github.com/webcamoid/DeployTools.git +cd ../.. + DEPLOYSCRIPT=deployscript.sh if [ "${TRAVIS_OS_NAME}" = linux ]; then @@ -34,6 +38,7 @@ if [ "${TRAVIS_OS_NAME}" = linux ]; then export LC_ALL=C export HOME=$HOME export PATH="$TRAVIS_BUILD_DIR/.local/bin:\$PATH" +export PYTHONPATH="\$PWD/ports/deploy/DeployTools" export WINEPREFIX=/opt/.wine cd $TRAVIS_BUILD_DIR EOF diff --git a/ports/deploy/deploy.py b/ports/deploy/deploy.py index 45a54e9..bacad69 100644 --- a/ports/deploy/deploy.py +++ b/ports/deploy/deploy.py @@ -19,11 +19,11 @@ # # Web-Site: http://webcamoid.github.io/ -import tools.utils +from WebcamoidDeployTools import DTUtils if __name__ =='__main__': - system = tools.utils.DeployToolsUtils().system + system = DTUtils.Utils().system while True: try: diff --git a/ports/deploy/deploy_base.py b/ports/deploy/deploy_base.py deleted file mode 100644 index 7a149d6..0000000 --- a/ports/deploy/deploy_base.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Webcamoid, webcam capture application. -# Copyright (C) 2017 Gonzalo Exequiel Pedone -# -# Webcamoid 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. -# -# Webcamoid 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 Webcamoid. If not, see . -# -# Web-Site: http://webcamoid.github.io/ - -import os -import sys -import platform -import shutil - -import tools.utils - -class DeployBase(tools.utils.DeployToolsUtils): - def __init__(self): - super().__init__() - self.rootDir = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../..')) - self.buildDir = os.environ['BUILD_PATH'] if 'BUILD_PATH' in os.environ else self.rootDir - self.installDir = os.path.join(self.rootDir, 'ports/deploy/temp_priv/root') - self.rootInstallDir = '' - self.pkgsDir = os.path.join(self.rootDir, - 'ports/deploy/packages_auto', - sys.platform if os.name == 'posix' else os.name) - self.programVersion = '' - self.qmake = '' - - def __str__(self): - deployInfo = 'Python version: {}\n' \ - 'Root directory: {}\n' \ - 'Build directory: {}\n' \ - 'Install directory: {}\n' \ - 'Packages directory: {}\n' \ - 'System: {}\n' \ - 'Architecture: {}\n' \ - 'Target system: {}\n' \ - 'Target architecture: {}\n' \ - 'Number of threads: {}\n' \ - 'Program version: {}\n' \ - 'Make executable: {}\n' \ - 'Qmake executable: {}'. \ - format(platform.python_version(), - self.rootDir, - self.buildDir, - self.installDir, - self.pkgsDir, - self.system, - self.arch, - self.targetSystem, - self.targetArch, - self.njobs, - self.programVersion, - self.make, - self.qmake) - - return deployInfo - - def run(self): - print('Deploy info\n') - print(self) - print('\nPreparing for software packaging\n') - self.prepare() - - if not 'NO_SHOW_PKG_DATA_INFO' in os.environ \ - or os.environ['NO_SHOW_PKG_DATA_INFO'] != '1': - print('\nPackaged data info\n') - self.printPackageDataInfo() - - if 'PACKAGES_PREPARE_ONLY' in os.environ \ - and os.environ['PACKAGES_PREPARE_ONLY'] == '1': - print('\nPackage data is ready for merging\n') - else: - print('\nCreating packages\n') - self.package() - print('\nCleaning up') - self.cleanup() - print('Deploy finnished\n') - - def printPackageDataInfo(self): - packagedFiles = [] - - for root, _, files in os.walk(self.rootInstallDir): - for f in files: - packagedFiles.append(os.path.join(root, f)) - - packagedFiles = sorted(packagedFiles) - - for f in packagedFiles: - print(' ' + f) - - def prepare(self): - pass - - def package(self): - pass - - def cleanup(self): - shutil.rmtree(self.installDir, True) diff --git a/ports/deploy/deploy_mac.py b/ports/deploy/deploy_mac.py index affa234..a195408 100644 --- a/ports/deploy/deploy_mac.py +++ b/ports/deploy/deploy_mac.py @@ -28,14 +28,16 @@ import sys import threading import time -import deploy_base -import tools.binary_mach -import tools.qt5 +from WebcamoidDeployTools import DTDeployBase +from WebcamoidDeployTools import DTQt5 +from WebcamoidDeployTools import DTBinaryMach -class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): +class Deploy(DTDeployBase.DeployBase, DTQt5.Qt5Tools): def __init__(self): super().__init__() + rootDir = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../..')) + self.setRootDir(rootDir) self.installDir = os.path.join(self.buildDir, 'ports/deploy/temp_priv') self.pkgsDir = os.path.join(self.buildDir, 'ports/deploy/packages_auto', self.targetSystem) self.detectQt(os.path.join(self.buildDir, 'Manager')) @@ -48,8 +50,8 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): self.mainBinary = os.path.join(self.binaryInstallDir, self.programName) self.programVersion = self.detectVersion(os.path.join(self.rootDir, 'commons.pri')) self.detectMake() - self.binarySolver = tools.binary_mach.DeployToolsBinary() - self.binarySolver.readExcludeList(os.path.join(self.rootDir, 'ports/deploy/tools/exclude/exclude.{}.{}.txt'.format(os.name, sys.platform))) + self.binarySolver = DTBinaryMach.MachBinaryTools() + self.binarySolver.readExcludes(os.name, sys.platform) self.packageConfig = os.path.join(self.rootDir, 'ports/deploy/package_info.conf') self.dependencies = [] self.installerConfig = os.path.join(self.installDir, 'installer/config') diff --git a/ports/deploy/deploy_posix.py b/ports/deploy/deploy_posix.py index ee3c570..e941147 100644 --- a/ports/deploy/deploy_posix.py +++ b/ports/deploy/deploy_posix.py @@ -28,14 +28,16 @@ import sys import tarfile import threading -import deploy_base -import tools.binary_elf -import tools.qt5 +from WebcamoidDeployTools import DTDeployBase +from WebcamoidDeployTools import DTQt5 +from WebcamoidDeployTools import DTBinaryElf -class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): +class Deploy(DTDeployBase.DeployBase, DTQt5.Qt5Tools): def __init__(self): super().__init__() + rootDir = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../..')) + self.setRootDir(rootDir) self.installDir = os.path.join(self.buildDir, 'ports/deploy/temp_priv') self.pkgsDir = os.path.join(self.buildDir, 'ports/deploy/packages_auto', sys.platform) self.detectQt(os.path.join(self.buildDir, 'Manager')) @@ -52,8 +54,8 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): elif 'android' in xspec: self.targetSystem = 'android' - self.binarySolver = tools.binary_elf.DeployToolsBinary() - self.binarySolver.readExcludeList(os.path.join(self.rootDir, 'ports/deploy/tools/exclude/exclude.{}.{}.txt'.format(os.name, sys.platform))) + self.binarySolver = DTBinaryElf.ElfBinaryTools() + self.binarySolver.readExcludes(os.name, sys.platform) self.packageConfig = os.path.join(self.rootDir, 'ports/deploy/package_info.conf') self.dependencies = [] self.installerConfig = os.path.join(self.installDir, 'installer/config') diff --git a/ports/deploy/deploy_posix_windows.py b/ports/deploy/deploy_posix_windows.py index 191f331..3d9caa5 100644 --- a/ports/deploy/deploy_posix_windows.py +++ b/ports/deploy/deploy_posix_windows.py @@ -26,14 +26,16 @@ import sys import threading import zipfile -import deploy_base -import tools.binary_pecoff -import tools.qt5 +from WebcamoidDeployTools import DTDeployBase +from WebcamoidDeployTools import DTQt5 +from WebcamoidDeployTools import DTBinaryPecoff -class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): +class Deploy(DTDeployBase.DeployBase, DTQt5.Qt5Tools): def __init__(self): super().__init__() + rootDir = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../..')) + self.setRootDir(rootDir) self.targetSystem = 'posix_windows' self.installDir = os.path.join(self.buildDir, 'ports/deploy/temp_priv') self.pkgsDir = os.path.join(self.buildDir, 'ports/deploy/packages_auto/windows') @@ -46,8 +48,8 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): self.programName = os.path.splitext(os.path.basename(self.mainBinary))[0] self.programVersion = self.detectVersion(os.path.join(self.rootDir, 'commons.pri')) self.detectMake() - self.binarySolver = tools.binary_pecoff.DeployToolsBinary() - self.binarySolver.readExcludeList(os.path.join(self.rootDir, 'ports/deploy/tools/exclude/exclude.{}.{}.txt'.format(os.name, sys.platform))) + self.binarySolver = DTBinaryPecoff.PecoffBinaryTools() + self.binarySolver.readExcludes(os.name, sys.platform) self.packageConfig = os.path.join(self.rootDir, 'ports/deploy/package_info.conf') self.dependencies = [] self.installerConfig = os.path.join(self.installDir, 'installer/config') diff --git a/ports/deploy/deploy_windows.py b/ports/deploy/deploy_windows.py index 38152fc..4a54b0e 100644 --- a/ports/deploy/deploy_windows.py +++ b/ports/deploy/deploy_windows.py @@ -27,14 +27,16 @@ import sys import threading import zipfile -import deploy_base -import tools.binary_pecoff -import tools.qt5 +from WebcamoidDeployTools import DTDeployBase +from WebcamoidDeployTools import DTQt5 +from WebcamoidDeployTools import DTBinaryPecoff -class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): +class Deploy(DTDeployBase.DeployBase, DTQt5.Qt5Tools): def __init__(self): super().__init__() + rootDir = os.path.normpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../..')) + self.setRootDir(rootDir) self.installDir = os.path.join(self.buildDir, 'ports/deploy/temp_priv') self.pkgsDir = os.path.join(self.buildDir, 'ports/deploy/packages_auto/windows') self.detectQt(os.path.join(self.buildDir, 'Manager')) @@ -46,8 +48,8 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt): self.programName = os.path.splitext(os.path.basename(self.mainBinary))[0] self.programVersion = self.detectVersion(os.path.join(self.rootDir, 'commons.pri')) self.detectMake() - self.binarySolver = tools.binary_pecoff.DeployToolsBinary() - self.binarySolver.readExcludeList(os.path.join(self.rootDir, 'ports/deploy/tools/exclude/exclude.{}.{}.txt'.format(os.name, sys.platform))) + self.binarySolver = DTBinaryPecoff.PecoffBinaryTools() + self.binarySolver.readExcludes(os.name, sys.platform) self.packageConfig = os.path.join(self.rootDir, 'ports/deploy/package_info.conf') self.dependencies = [] self.installerConfig = os.path.join(self.installDir, 'installer/config') diff --git a/ports/deploy/tools/android.py b/ports/deploy/tools/android.py deleted file mode 100644 index f4c4eba..0000000 --- a/ports/deploy/tools/android.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Webcamoid, webcam capture application. -# Copyright (C) 2019 Gonzalo Exequiel Pedone -# -# Webcamoid 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. -# -# Webcamoid 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 Webcamoid. If not, see . -# -# Web-Site: http://webcamoid.github.io/ - -import os -import shutil -import xml.etree.ElementTree as ET - -import tools.utils - - -class AndroidTools(tools.utils.DeployToolsUtils): - def __init__(self): - super().__init__() - self.androidPlatform = '' - self.archMap = [('arm64-v8a' , 'aarch64', 'aarch64-linux-android'), - ('armeabi-v7a', 'arm' , 'arm-linux-androideabi'), - ('x86' , 'i686' , 'i686-linux-android' ), - ('x86_64' , 'x86_64' , 'x86_64-linux-android' )] - self.androidSDK = '' - self.androidNDK = '' - self.bundledInLib = [] - self.qtLibs = [] - self.localLibs = [] - - if 'ANDROID_HOME' in os.environ: - self.androidSDK = os.environ['ANDROID_HOME'] - - if 'ANDROID_NDK_ROOT' in os.environ: - self.androidNDK = os.environ['ANDROID_NDK_ROOT'] - elif 'ANDROID_NDK' in os.environ: - self.androidNDK = os.environ['ANDROID_NDK'] - - def detectAndroidPlatform(self, path=''): - for makeFile in self.detectMakeFiles(path): - with open(makeFile) as f: - for line in f: - if line.startswith('DESTDIR') and '=' in line: - buildPath = os.path.join(path, line.split('=')[1].strip()) - chunks = [part for part in buildPath.split(os.path.sep) if len(part) > 0] - - if len(chunks) >= 2: - self.androidPlatform = chunks[len(chunks) - 2] - - return - - def detectLibPaths(self): - if len(self.androidNDK) < 1: - return [] - - for arch in self.archMap: - if self.targetArch == arch[0]: - return [os.path.join(self.androidNDK, - 'toolchains', - 'llvm', - 'prebuilt', - 'linux-x86_64', - 'sysroot', - 'usr', - 'lib', - arch[1] + '-linux-android')] - - return [] - - def detectBinPaths(self): - if len(self.androidNDK) < 1: - return [] - - for arch in self.archMap: - if self.targetArch == arch[0]: - binPath = os.path.join(self.androidNDK, - 'toolchains', - 'llvm', - 'prebuilt', - 'linux-x86_64', - arch[2], - 'bin') - - return [binPath] - - return [] - - def fixQtLibs(self): - for root, dirs, files in os.walk(self.assetsIntallDir): - for f in files: - if f.endswith('.so'): - srcPath = os.path.join(root, f) - relPath = root.replace(self.assetsIntallDir, '')[1:] - prefix = 'lib' + relPath.replace(os.path.sep, '_') + '_' - lib = '' - - if f.startswith(prefix): - lib = f - else: - lib = prefix + f - - dstPath = os.path.join(self.libInstallDir, lib) - print(' {} -> {}'.format(srcPath, dstPath)) - self.move(srcPath, dstPath) - self.bundledInLib += [(lib, os.path.join(relPath, f))] - - def libBaseName(self, lib): - basename = os.path.basename(lib) - - return basename[3: len(basename) - 3] - - def fixLibsXml(self): - bundledInAssets = [] - assetsDir = os.path.join(self.rootInstallDir, 'assets') - - for root, dirs, files in os.walk(assetsDir): - for f in files: - srcPath = os.path.join(root.replace(assetsDir, '')[1:], f) - dstPath = os.path.sep.join(srcPath.split(os.path.sep)[1:]) - - if (len(dstPath) > 0): - bundledInAssets += [(srcPath, dstPath)] - - libsXml = os.path.join(self.rootInstallDir, 'res', 'values', 'libs.xml') - libsXmlTemp = os.path.join(self.rootInstallDir, 'res', 'values', 'libsTemp.xml') - - tree = ET.parse(libsXml) - root = tree.getroot() - oldFeatures = set() - oldPermissions = set() - resources = {} - - for array in root: - if not array.attrib['name'] in resources: - resources[array.attrib['name']] = set() - - for item in array: - if item.text: - lib = item.text.strip() - - if len(lib) > 0: - lib = '{}'.format(lib) - resources[array.attrib['name']].add(lib) - - qtLibs = set(['{};{}'.format(self.targetArch, self.libBaseName(lib)) for lib in self.qtLibs]) - - if 'qt_libs' in resources: - qtLibs -= resources['qt_libs'] - - qtLibs = '\n'.join(sorted(list(qtLibs))) - bundledInLib = set(['{}:{}'.format(lib[0], lib[1]) for lib in self.bundledInLib]) - - if 'bundled_in_lib' in resources: - bundledInLib -= resources['bundled_in_lib'] - - bundledInLib = '\n'.join(sorted(list(bundledInLib))) - bundledInAssets = set(['{}:{}'.format(lib[0], lib[1]) for lib in bundledInAssets]) - - if 'bundled_in_assets' in resources: - bundledInAssets -= resources['bundled_in_assets'] - - bundledInAssets = '\n'.join(sorted(list(bundledInAssets))) - - localLibs = sorted(list(set(self.localLibs))) - localLibs = set(['{};{}'.format(self.targetArch, ':'.join(localLibs)) for lib in localLibs]) - - if 'load_local_libs' in resources: - localLibs -= resources['load_local_libs'] - - localLibs = '\n'.join(sorted(list(localLibs))) - - replace = {'' : '', - '' : qtLibs, - '' : bundledInLib, - '': bundledInAssets, - '' : localLibs} - - with open(libsXml) as inFile: - with open(libsXmlTemp, 'w') as outFile: - for line in inFile: - for key in replace: - line = line.replace(key, replace[key]) - - outFile.write(line) - - os.remove(libsXml) - shutil.move(libsXmlTemp, libsXml) diff --git a/ports/deploy/tools/binary.py b/ports/deploy/tools/binary.py deleted file mode 100644 index f228c3a..0000000 --- a/ports/deploy/tools/binary.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Webcamoid, webcam capture application. -# Copyright (C) 2017 Gonzalo Exequiel Pedone -# -# Webcamoid 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. -# -# Webcamoid 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 Webcamoid. If not, see . -# -# Web-Site: http://webcamoid.github.io/ - -import os -import re -import subprocess # nosec -import threading -import time - -import tools - - -class DeployToolsBinary(tools.utils.DeployToolsUtils): - def __init__(self): - super().__init__() - self.detectStrip() - self.excludes = [] - - def isValid(self, path): - return False - - def find(self, path): - binaries = [] - - for root, _, files in os.walk(path): - for f in files: - binaryPath = os.path.join(root, f) - - if not os.path.islink(binaryPath) and self.isValid(binaryPath): - binaries.append(binaryPath) - - return binaries - - def dump(self, binary): - return {} - - def dependencies(self, binary): - return [] - - def allDependencies(self, binary): - deps = self.dependencies(binary) - solved = set() - - while len(deps) > 0: - dep = deps.pop() - - for binDep in self.dependencies(dep): - if binDep != dep and not binDep in solved: - deps.append(binDep) - - if self.system == 'mac': - i = dep.rfind('.framework/') - - if i >= 0: - dep = dep[: i] + '.framework' - - solved.add(dep) - - return solved - - def scanDependencies(self, path): - deps = set() - - for binPath in self.find(path): - for dep in self.allDependencies(binPath): - deps.add(dep) - - return sorted(deps) - - def name(self, binary): - return '' - - def detectStrip(self): - self.stripBin = self.whereBin('strip.exe' if self.system == 'windows' else 'strip') - - def strip(self, binary): - if self.stripBin == '': - return - - process = subprocess.Popen([self.stripBin, binary], # nosec - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - process.communicate() - - def stripSymbols(self, path): - threads = [] - - for binary in self.find(path): - thread = threading.Thread(target=self.strip, args=(binary,)) - threads.append(thread) - - while threading.active_count() >= self.njobs: - time.sleep(0.25) - - thread.start() - - for thread in threads: - thread.join() - - def readExcludeList(self, excludeList): - self.excludes = [] - - if os.path.exists(excludeList): - with open(excludeList) as f: - for line in f: - line = line.strip() - - if len(line) > 0 and line[0] != '#': - i = line.find('#') - - if i >= 0: - line = line[: i] - - line = line.strip() - - if len(line) > 0: - self.excludes.append(line) - - def isExcluded(self, path): - for exclude in self.excludes: - if self.targetSystem == 'windows' or self.targetSystem == 'posix_windows': - path = path.lower().replace('\\', '/') - exclude = exclude.lower() - - if re.fullmatch(exclude, path): - return True - - return False - - def resetFilePermissions(self, rootPath, binariesPath): - for root, dirs, files in os.walk(rootPath): - for d in dirs: - permissions = 0o755 - path = os.path.join(root, d) - - if self.system == 'mac': - os.chmod(path, permissions, follow_symlinks=False) - else: - os.chmod(path, permissions) - - for f in files: - permissions = 0o644 - path = os.path.join(root, f) - - if root == binariesPath and self.isValid(path): - permissions = 0o744 - - if self.system == 'mac': - os.chmod(path, permissions, follow_symlinks=False) - else: - os.chmod(path, permissions) diff --git a/ports/deploy/tools/binary_elf.py b/ports/deploy/tools/binary_elf.py deleted file mode 100644 index da119d8..0000000 --- a/ports/deploy/tools/binary_elf.py +++ /dev/null @@ -1,345 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Webcamoid, webcam capture application. -# Copyright (C) 2017 Gonzalo Exequiel Pedone -# -# Webcamoid 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. -# -# Webcamoid 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 Webcamoid. If not, see . -# -# Web-Site: http://webcamoid.github.io/ - -import fnmatch -import os -import re -import struct -import sys - -import tools.binary - - -class DeployToolsBinary(tools.binary.DeployToolsBinary): - def __init__(self): - super().__init__() - self.ldLibraryPath = os.environ['LD_LIBRARY_PATH'].split(':') if 'LD_LIBRARY_PATH' in os.environ else [] - self.libsSeachPaths = self.readLdconf() \ - + ['/usr/lib', - '/usr/lib64', - '/lib', - '/lib64', - '/usr/local/lib', - '/usr/local/lib64'] - self.emCodes = {3 : '386', - 40 : 'ARM', - 62 : 'X86_64', - 183: 'AARCH64'} - - def readLdconf(self, ldconf='/etc/ld.so.conf'): - if not os.path.exists(ldconf): - return [] - - confDir = os.path.dirname(ldconf) - libpaths = [] - - with open(ldconf) as f: - for line in f: - i = line.find('#') - - if i == 0: - continue - - if i >= 0: - line = line[: i] - - line = line.strip() - - if len(line) < 1: - continue - - if line.startswith('include'): - conf = line.split()[1] - - if not conf.startswith('/'): - conf = os.path.join(confDir, conf) - - dirname = os.path.dirname(conf) - - if os.path.exists(dirname): - for f in os.listdir(dirname): - path = os.path.join(dirname, f) - - if fnmatch.fnmatch(path, conf): - libpaths += self.readLdconf(path) - else: - libpaths.append(line) - - return libpaths - - def isValid(self, path): - with open(path, 'rb') as f: - return f.read(4) == b'\x7fELF' - - @staticmethod - def readString(f): - s = b'' - - while True: - c = f.read(1) - - if c == b'\x00': - break - - s += c - - return s - - @staticmethod - def readNumber(f, arch): - if arch == '32bits': - return struct.unpack('I', f.read(4))[0] - - return struct.unpack('Q', f.read(8))[0] - - @staticmethod - def readDynamicEntry(f, arch): - if arch == '32bits': - return struct.unpack('iI', f.read(8)) - - return struct.unpack('qQ', f.read(16)) - - # https://refspecs.linuxfoundation.org/lsb.shtml (See Core, Generic) - # https://en.wikipedia.org/wiki/Executable_and_Linkable_Format - def dump(self, binary): - # ELF file magic - ELFMAGIC = b'\x7fELF' - - # Sections - SHT_STRTAB = 0x3 - SHT_DYNAMIC = 0x6 - - # Dynamic section entries - DT_NULL = 0 - DT_NEEDED = 1 - DT_RPATH = 15 - DT_RUNPATH = 0x1d - - with open(binary, 'rb') as f: - # Read magic signature. - magic = f.read(4) - - if magic != ELFMAGIC: - return {} - - # Read the data structure of the file. - eiClass = '32bits' if struct.unpack('B', f.read(1))[0] == 1 else '64bits' - - # Read machine code. - f.seek(0x12, os.SEEK_SET) - machine = struct.unpack('H', f.read(2))[0] - - # Get a pointer to the sections table. - sectionHeaderTable = 0 - - if eiClass == '32bits': - f.seek(0x20, os.SEEK_SET) - sectionHeaderTable = self.readNumber(f, eiClass) - f.seek(0x30, os.SEEK_SET) - else: - f.seek(0x28, os.SEEK_SET) - sectionHeaderTable = self.readNumber(f, eiClass) - f.seek(0x3c, os.SEEK_SET) - - # Read the number of sections. - nSections = struct.unpack('H', f.read(2))[0] - - # Read the index of the string table that stores sections names. - shstrtabIndex = struct.unpack('H', f.read(2))[0] - - # Read sections. - f.seek(sectionHeaderTable, os.SEEK_SET) - neededPtr = [] - rpathsPtr = [] - runpathsPtr = [] - strtabs = [] - shstrtab = [] - - for section in range(nSections): - sectionStart = f.tell() - - # Read the a pointer to the virtual address in the string table - # that contains the name of this section. - sectionName = struct.unpack('I', f.read(4))[0] - - # Read the type of this section. - sectionType = struct.unpack('I', f.read(4))[0] - - # Read the virtual address of this section. - f.seek(sectionStart + (0x0c if eiClass == '32bits' else 0x10), os.SEEK_SET) - shAddr = self.readNumber(f, eiClass) - - # Read the offset in file to this section. - shOffset = self.readNumber(f, eiClass) - f.seek(shOffset, os.SEEK_SET) - - if sectionType == SHT_DYNAMIC: - # Read dynamic sections. - while True: - # Read dynamic entries. - dTag, dVal = self.readDynamicEntry(f, eiClass) - - if dTag == DT_NULL: - # End of dynamic sections. - break - elif dTag == DT_NEEDED: - # Dynamically imported libraries. - neededPtr.append(dVal) - elif dTag == DT_RPATH: - # RPATHs. - rpathsPtr.append(dVal) - elif dTag == DT_RUNPATH: - # RUNPATHs. - runpathsPtr.append(dVal) - elif sectionType == SHT_STRTAB: - # Read string tables. - if section == shstrtabIndex: - # We found the string table that stores sections names. - shstrtab = [shAddr, shOffset] - else: - # Save string tables for later usage. - strtabs += [[sectionName, shAddr, shOffset]] - - # Move to next section. - f.seek(sectionStart + (0x28 if eiClass == '32bits' else 0x40), os.SEEK_SET) - - # Libraries names and RUNPATHs are located in '.dynstr' table. - strtab = [] - - for tab in strtabs: - f.seek(tab[0] - shstrtab[0] + shstrtab[1], os.SEEK_SET) - - if self.readString(f) == b'.dynstr': - strtab = tab - - # Read dynamically imported libraries. - needed = set() - - for lib in neededPtr: - f.seek(lib + strtab[2], os.SEEK_SET) - needed.add(self.readString(f).decode(sys.getdefaultencoding())) - - # Read RPATHs - rpaths = set() - - for path in rpathsPtr: - f.seek(path + strtab[2], os.SEEK_SET) - rpaths.add(self.readString(f).decode(sys.getdefaultencoding())) - - # Read RUNPATHs - runpaths = set() - - for path in runpathsPtr: - f.seek(path + strtab[2], os.SEEK_SET) - runpaths.add(self.readString(f).decode(sys.getdefaultencoding())) - - return {'machine': machine, - 'imports': needed, - 'rpath': rpaths, - 'runpath': runpaths} - - return {} - - @staticmethod - def readRpaths(elfInfo, binDir): - rpaths = [] - runpaths = [] - - # http://amir.rachum.com/blog/2016/09/17/shared-libraries/ - for rpath in ['rpath', 'runpath']: - for path in elfInfo[rpath]: - if '$ORIGIN' in path: - path = path.replace('$ORIGIN', binDir) - - if not path.startswith('/'): - path = os.path.join(binDir, path) - - path = os.path.normpath(path) - - if rpath == 'rpath': - rpaths.append(path) - else: - runpaths.append(path) - - return rpaths, runpaths - - def libPath(self, lib, machine, rpaths, runpaths): - # man ld.so - searchPaths = rpaths \ - + self.ldLibraryPath \ - + runpaths \ - + self.libsSeachPaths - - for libdir in searchPaths: - path = os.path.join(libdir, lib) - - if os.path.exists(path): - depElfInfo = self.dump(path) - - if depElfInfo: - if 'machine' in depElfInfo and (machine == 0 or depElfInfo['machine'] == machine): - return path - elif 'links' in depElfInfo and len(depElfInfo['links']) > 0: - return path - - return '' - - def dependencies(self, binary): - elfInfo = self.dump(binary) - - if not elfInfo: - return [] - - rpaths, runpaths = self.readRpaths(elfInfo, os.path.dirname(binary)) - libs = [] - deps = [] - - if 'imports' in elfInfo: - deps = elfInfo['imports'] - elif 'links' in elfInfo: - deps = elfInfo['links'] - - machine = 0 - - if 'machine' in elfInfo: - machine = elfInfo['machine'] - - for lib in deps: - libpath = self.libPath(lib, machine, rpaths, runpaths) - - if len(libpath) > 0 and not self.isExcluded(libpath): - libs.append(libpath) - - return libs - - def name(self, binary): - dep = os.path.basename(binary)[3:] - - return dep[: dep.find('.')] - - def machineEMCode(self, binary): - info = self.dump(binary) - - if 'machine' in info: - if info['machine'] in self.emCodes: - return self.emCodes[info['machine']] - - return 'UNKNOWN' diff --git a/ports/deploy/tools/binary_mach.py b/ports/deploy/tools/binary_mach.py deleted file mode 100644 index 67c53a8..0000000 --- a/ports/deploy/tools/binary_mach.py +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Webcamoid, webcam capture application. -# Copyright (C) 2017 Gonzalo Exequiel Pedone -# -# Webcamoid 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. -# -# Webcamoid 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 Webcamoid. If not, see . -# -# Web-Site: http://webcamoid.github.io/ - -import os -import struct -import sys - -import tools.binary - - -class DeployToolsBinary(tools.binary.DeployToolsBinary): - def __init__(self): - super().__init__() - - # 32 bits magic number. - self.MH_MAGIC = 0xfeedface # Native endian - self.MH_CIGAM = 0xcefaedfe # Reverse endian - - # 64 bits magic number. - self.MH_MAGIC_64 = 0xfeedfacf # Native endian - self.MH_CIGAM_64 = 0xcffaedfe # Reverse endian - - def isValid(self, path): - try: - with open(path, 'rb') as f: - # Read magic number. - magic = struct.unpack('I', f.read(4))[0] - - if magic == self.MH_MAGIC \ - or magic == self.MH_CIGAM \ - or magic == self.MH_MAGIC_64 \ - or magic == self.MH_CIGAM_64: - return True - except: - pass - - return False - - # https://github.com/aidansteele/osx-abi-macho-file-format-reference - def dump(self, binary): - # Commands definitions - LC_REQ_DYLD = 0x80000000 - LC_LOAD_DYLIB = 0xc - LC_RPATH = 0x1c | LC_REQ_DYLD - LC_ID_DYLIB = 0xd - - dylibImports = [] - rpaths = [] - dylibId = '' - - with open(binary, 'rb') as f: - # Read magic number. - magic = struct.unpack('I', f.read(4))[0] - - if magic == self.MH_MAGIC or magic == self.MH_CIGAM: - is32bits = True - elif magic == self.MH_MAGIC_64 or magic == self.MH_CIGAM_64: - is32bits = False - else: - return {} - - # Read number of commands. - f.seek(12, os.SEEK_CUR) - ncmds = struct.unpack('I', f.read(4))[0] - - # Move to load commands - f.seek(8 if is32bits else 12, os.SEEK_CUR) - - for _ in range(ncmds): - # Read a load command and store it's position in the file. - loadCommandStart = f.tell() - loadCommand = struct.unpack('II', f.read(8)) - - # If the command list a library - if loadCommand[0] in [LC_LOAD_DYLIB, LC_RPATH, LC_ID_DYLIB]: - # Save the position of the next command. - nextCommand = f.tell() + loadCommand[1] - 8 - - # Move to the string - f.seek(loadCommandStart + struct.unpack('I', f.read(4))[0], os.SEEK_SET) - dylib = b'' - - # Read string until null character. - while True: - c = f.read(1) - - if c == b'\x00': - break - - dylib += c - s = dylib.decode(sys.getdefaultencoding()) - - if loadCommand[0] == LC_LOAD_DYLIB: - dylibImports.append(s) - elif loadCommand[0] == LC_RPATH: - rpaths.append(s) - elif loadCommand[0] == LC_ID_DYLIB: - dylibId = s - - f.seek(nextCommand, os.SEEK_SET) - else: - f.seek(loadCommand[1] - 8, os.SEEK_CUR) - - return {'imports': dylibImports, 'rpaths': rpaths, 'id': dylibId} - - @staticmethod - def solveRefpath(path): - if not path.startswith('@'): - return path - - searchPaths = [] - - if 'DYLD_LIBRARY_PATH' in os.environ: - searchPaths += os.environ['DYLD_LIBRARY_PATH'].split(':') - - if 'DYLD_FRAMEWORK_PATH' in os.environ: - searchPaths += os.environ['DYLD_FRAMEWORK_PATH'].split(':') - - if path.endswith('.dylib'): - dep = os.path.basename(path) - else: - i = path.rfind(os.sep, 0, path.rfind('.framework')) - dep = path[i + 1:] - - for fpath in searchPaths: - realPath = os.path.join(fpath, dep) - - if os.path.exists(realPath): - return realPath - - return '' - - def dependencies(self, binary): - machInfo = self.dump(binary) - - if not machInfo: - return [] - - libs = [] - - for mach in machInfo['imports']: - mach = self.solveRefpath(mach) - - if mach == '' or self.isExcluded(mach) or not os.path.exists(mach): - continue - - dirName = os.path.dirname(mach) - dirName = os.path.realpath(dirName) - baseName = os.path.basename(mach) - libs.append(os.path.join(dirName, baseName)) - - return libs - - def name(self, binary): - dep = os.path.basename(binary) - i = dep.find('.') - - if i >= 0: - dep = dep[: dep.find('.')] - - if 'Qt' in dep and not 'Qt5' in dep: - dep = dep.replace('Qt', 'Qt5') - - return dep diff --git a/ports/deploy/tools/binary_pecoff.py b/ports/deploy/tools/binary_pecoff.py deleted file mode 100644 index 15d1e15..0000000 --- a/ports/deploy/tools/binary_pecoff.py +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Webcamoid, webcam capture application. -# Copyright (C) 2017 Gonzalo Exequiel Pedone -# -# Webcamoid 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. -# -# Webcamoid 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 Webcamoid. If not, see . -# -# Web-Site: http://webcamoid.github.io/ - -import mimetypes -import os -import struct -import sys - -import tools.binary - - -class DeployToolsBinary(tools.binary.DeployToolsBinary): - def __init__(self): - super().__init__() - - def isValid(self, path): - mimetype, _ = mimetypes.guess_type(path) - - if mimetype == 'application/x-msdownload': - return True - - if mimetype != 'application/octet-stream': - return False - - with open(path, 'rb') as f: - if f.read(2) != b'MZ': - return [] - - f.seek(0x3c, os.SEEK_SET) - peHeaderOffset = struct.unpack('I', f.read(4)) - f.seek(peHeaderOffset[0], os.SEEK_SET) - peSignatue = f.read(4) - - if peSignatue != b'PE\x00\x00': - return False - - return True - - # https://msdn.microsoft.com/en-us/library/windows/desktop/ms680547(v=vs.85).aspx - # https://upload.wikimedia.org/wikipedia/commons/1/1b/Portable_Executable_32_bit_Structure_in_SVG_fixed.svg - def dump(self, binary): - dllImports = set() - - if not os.path.exists(binary) or not os.path.isfile(binary): - return dllImports - - with open(binary, 'rb') as f: - # Check DOS header signature. - if f.read(2) != b'MZ': - return [] - - # Move to COFF header. - f.seek(0x3c, os.SEEK_SET) - peHeaderOffset = struct.unpack('I', f.read(4)) - f.seek(peHeaderOffset[0], os.SEEK_SET) - peSignatue = f.read(4) - - # Check COFF header signature. - if peSignatue != b'PE\x00\x00': - return [] - - # Read COFF header. - coffHeader = struct.unpack('HHIIIHH', f.read(20)) - nSections = coffHeader[1] - sectionTablePos = coffHeader[5] + f.tell() - - # Read magic signature in standard COFF fields. - peType = 'PE32' if f.read(2) == b'\x0b\x01' else 'PE32+' - - # Move to data directories. - f.seek(102 if peType == 'PE32' else 118, os.SEEK_CUR) - - # Read the import table. - importTablePos, importTableSize = struct.unpack('II', f.read(8)) - - # Move to Sections table. - f.seek(sectionTablePos, os.SEEK_SET) - sections = [] - idataTablePhysical = -1 - - # Search for 'idata' section. - for _ in range(nSections): - # Read section. - section = struct.unpack('8pIIIIIIHHI', f.read(40)) - sectionName = section[0].replace(b'\x00', b'') - - # Save a reference to the sections. - sections += [section] - - if sectionName == b'idata' or sectionName == b'rdata': - idataTablePhysical = section[4] - - # If import table was defined calculate it's position in - # the file in relation to the address given by 'idata'. - if importTableSize > 0: - idataTablePhysical += importTablePos - section[2] - - if idataTablePhysical < 0: - return [] - - # Move to 'idata' section. - f.seek(idataTablePhysical, os.SEEK_SET) - dllList = set() - - # Read 'idata' directory table. - while True: - # Read DLL entries. - try: - dllImport = struct.unpack('IIIII', f.read(20)) - except: - break - - # Null directory entry. - if dllImport[0] | dllImport[1] | dllImport[2] | dllImport[3] | dllImport[4] == 0: - break - - # Locate where is located the DLL name in relation to the - # sections. - for section in sections: - if dllImport[3] >= section[2] \ - and dllImport[3] < section[1] + section[2]: - dllList.add(dllImport[3] - section[2] + section[4]) - - break - - for dll in dllList: - # Move to DLL name. - f.seek(dll, os.SEEK_SET) - dllName = b'' - - # Read string until null character. - while True: - c = f.read(1) - - if c == b'\x00': - break - - dllName += c - - try: - dllImports.add(dllName.decode(sys.getdefaultencoding())) - except: - pass - - return dllImports - - def dependencies(self, binary): - deps = [] - - for dep in self.dump(binary): - depPath = self.whereBin(dep) - - if len(depPath) > 0 and not self.isExcluded(depPath): - deps.append(depPath) - - return deps - - def name(self, binary): - dep = os.path.basename(binary) - - return dep[: dep.find('.')] diff --git a/ports/deploy/tools/exclude/exclude.nt.win32.txt b/ports/deploy/tools/exclude/exclude.nt.win32.txt deleted file mode 100644 index 490c564..0000000 --- a/ports/deploy/tools/exclude/exclude.nt.win32.txt +++ /dev/null @@ -1,2 +0,0 @@ -C:/Windows/System32/.* -C:/Program Files/.* diff --git a/ports/deploy/tools/exclude/exclude.posix.darwin.txt b/ports/deploy/tools/exclude/exclude.posix.darwin.txt deleted file mode 100644 index f1cd9cb..0000000 --- a/ports/deploy/tools/exclude/exclude.posix.darwin.txt +++ /dev/null @@ -1,2 +0,0 @@ -/usr/lib/.* -/System/Library/Frameworks/.* diff --git a/ports/deploy/tools/exclude/exclude.posix.freebsd12.txt b/ports/deploy/tools/exclude/exclude.posix.freebsd12.txt deleted file mode 100644 index 13025e4..0000000 --- a/ports/deploy/tools/exclude/exclude.posix.freebsd12.txt +++ /dev/null @@ -1,110 +0,0 @@ -# VDSO -(.*/)*ld-linux.so.2 -(.*/)*ld-linux-x86-64.so.2 - -# Glibc -(.*/)*libc.so.[0-9]+ -(.*/)*libdl.so.[0-9]+ -(.*/)*libm.so.[0-9]+ -(.*/)*libmvec.so.[0-9]+ -(.*/)*libpthread.so.[0-9]+ -(.*/)*libresolv.so.[0-9]+ -(.*/)*librt.so.[0-9]+ - -# GCC -(.*/)*libgcc_s.so.[0-9]+ -(.*/)*libgomp.so.[0-9]+ -(.*/)*libstdc\+\+.so.[0-9]+ - -# Core libraries -(.*/)*libSM.so.6 -(.*/)*libblkid.so.1 -(.*/)*libcap.so.2 -(.*/)*libcom_err.so.2 -(.*/)*libcrypto.so.1.0.0 -(.*/)*libdb-5.3.so -(.*/)*libdbus-1.so.3 -(.*/)*libexpat.so.1 -(.*/)*libfontconfig.so.1 -(.*/)*libfreetype.so.6 -(.*/)*libgcrypt.so.20 -(.*/)*libgmp.so.10 -(.*/)*libgpg-error.so.0 -(.*/)*libgssapi_krb5.so.2 -(.*/)*libharfbuzz.so.0 -(.*/)*libk5crypto.so.3 -(.*/)*libkeyutils.so.1 -(.*/)*libkrb5.so.3 -(.*/)*libkrb5support.so.0 -(.*/)*liblz4.so.1 -(.*/)*liblzma.so.5 -(.*/)*libmount.so.1 -(.*/)*libpcre.so.[0-9]+$ -(.*/)*libpcre16.so.0 -(.*/)*libssh2.so.1 -(.*/)*libssl.so.1.0.0 -(.*/)*libtasn1.so.6 -(.*/)*libusb-1.0.so.0 -(.*/)*libuuid.so.1 -(.*/)*libz.so.1 - -# Glib2 -(.*/)*libgio-2.0.so.0 -(.*/)*libglib-2.0.so.0 -(.*/)*libgmodule-2.0.so.0 -(.*/)*libgobject-2.0.so.0 - -# X11 -(.*/)*libX11-xcb.so.[0-9]+ -(.*/)*libX11.so.[0-9]+ -(.*/)*libXau.so.[0-9]+ -(.*/)*libXcursor.so.[0-9]+ -(.*/)*libXdamage.so.[0-9]+ -(.*/)*libXdmcp.so.[0-9]+ -(.*/)*libXext.so.[0-9]+ -(.*/)*libXfixes.so.[0-9]+ -(.*/)*libXi.so.[0-9]+ -(.*/)*libXinerama.so.[0-9]+ -(.*/)*libXrandr.so.[0-9]+ -(.*/)*libXrender.so.[0-9]+ -(.*/)*libXss.so.[0-9]+ -(.*/)*libXv.so.[0-9]+ -(.*/)*libXxf86vm.so.[0-9]+ -(.*/)*libglapi.so.[0-9]+ -(.*/)*libp11-kit.so.[0-9]+ -(.*/)*libxcb-dri2.so.[0-9]+ -(.*/)*libxcb-dri3.so.[0-9]+ -(.*/)*libxcb-glx.so.[0-9]+ -(.*/)*libxcb-icccm.so.[0-9]+ -(.*/)*libxcb-image.so.[0-9]+ -(.*/)*libxcb-keysyms.so.[0-9]+ -(.*/)*libxcb-present.so.[0-9]+ -(.*/)*libxcb-randr.so.[0-9]+ -(.*/)*libxcb-render-util.so.[0-9]+ -(.*/)*libxcb-render.so.[0-9]+ -(.*/)*libxcb-shape.so.[0-9]+ -(.*/)*libxcb-shm.so.[0-9]+ -(.*/)*libxcb-sync.so.[0-9]+ -(.*/)*libxcb-util.so.[0-9]+ -(.*/)*libxcb-xfixes.so.[0-9]+ -(.*/)*libxcb-xinerama.so.[0-9]+ -(.*/)*libxcb-xkb.so.[0-9]+ -(.*/)*libxcb.so.[0-9]+ -(.*/)*libxkbcommon-x11.so.[0-9]+ -(.*/)*libxkbcommon.so.[0-9]+ -(.*/)*libxshmfence.so.[0-9]+ - -# OpenGL -(.*/)*libdrm.so.2 -(.*/)*libgbm.so.1 -(.*/)*libEGL.so.1 -(.*/)*libGL.so.1 -(.*/)*libGLX.so.0 -(.*/)*libGLdispatch.so.0 - -# Use system library instead -(.*/)*libasound.so.2 -(.*/)*libpulse.so.0 -(.*/)*libpulse-simple.so.0 -(.*/)*libjack.so.0 -(.*/)*libv4l2.so.0 diff --git a/ports/deploy/tools/exclude/exclude.posix.linux.txt b/ports/deploy/tools/exclude/exclude.posix.linux.txt deleted file mode 100644 index 13025e4..0000000 --- a/ports/deploy/tools/exclude/exclude.posix.linux.txt +++ /dev/null @@ -1,110 +0,0 @@ -# VDSO -(.*/)*ld-linux.so.2 -(.*/)*ld-linux-x86-64.so.2 - -# Glibc -(.*/)*libc.so.[0-9]+ -(.*/)*libdl.so.[0-9]+ -(.*/)*libm.so.[0-9]+ -(.*/)*libmvec.so.[0-9]+ -(.*/)*libpthread.so.[0-9]+ -(.*/)*libresolv.so.[0-9]+ -(.*/)*librt.so.[0-9]+ - -# GCC -(.*/)*libgcc_s.so.[0-9]+ -(.*/)*libgomp.so.[0-9]+ -(.*/)*libstdc\+\+.so.[0-9]+ - -# Core libraries -(.*/)*libSM.so.6 -(.*/)*libblkid.so.1 -(.*/)*libcap.so.2 -(.*/)*libcom_err.so.2 -(.*/)*libcrypto.so.1.0.0 -(.*/)*libdb-5.3.so -(.*/)*libdbus-1.so.3 -(.*/)*libexpat.so.1 -(.*/)*libfontconfig.so.1 -(.*/)*libfreetype.so.6 -(.*/)*libgcrypt.so.20 -(.*/)*libgmp.so.10 -(.*/)*libgpg-error.so.0 -(.*/)*libgssapi_krb5.so.2 -(.*/)*libharfbuzz.so.0 -(.*/)*libk5crypto.so.3 -(.*/)*libkeyutils.so.1 -(.*/)*libkrb5.so.3 -(.*/)*libkrb5support.so.0 -(.*/)*liblz4.so.1 -(.*/)*liblzma.so.5 -(.*/)*libmount.so.1 -(.*/)*libpcre.so.[0-9]+$ -(.*/)*libpcre16.so.0 -(.*/)*libssh2.so.1 -(.*/)*libssl.so.1.0.0 -(.*/)*libtasn1.so.6 -(.*/)*libusb-1.0.so.0 -(.*/)*libuuid.so.1 -(.*/)*libz.so.1 - -# Glib2 -(.*/)*libgio-2.0.so.0 -(.*/)*libglib-2.0.so.0 -(.*/)*libgmodule-2.0.so.0 -(.*/)*libgobject-2.0.so.0 - -# X11 -(.*/)*libX11-xcb.so.[0-9]+ -(.*/)*libX11.so.[0-9]+ -(.*/)*libXau.so.[0-9]+ -(.*/)*libXcursor.so.[0-9]+ -(.*/)*libXdamage.so.[0-9]+ -(.*/)*libXdmcp.so.[0-9]+ -(.*/)*libXext.so.[0-9]+ -(.*/)*libXfixes.so.[0-9]+ -(.*/)*libXi.so.[0-9]+ -(.*/)*libXinerama.so.[0-9]+ -(.*/)*libXrandr.so.[0-9]+ -(.*/)*libXrender.so.[0-9]+ -(.*/)*libXss.so.[0-9]+ -(.*/)*libXv.so.[0-9]+ -(.*/)*libXxf86vm.so.[0-9]+ -(.*/)*libglapi.so.[0-9]+ -(.*/)*libp11-kit.so.[0-9]+ -(.*/)*libxcb-dri2.so.[0-9]+ -(.*/)*libxcb-dri3.so.[0-9]+ -(.*/)*libxcb-glx.so.[0-9]+ -(.*/)*libxcb-icccm.so.[0-9]+ -(.*/)*libxcb-image.so.[0-9]+ -(.*/)*libxcb-keysyms.so.[0-9]+ -(.*/)*libxcb-present.so.[0-9]+ -(.*/)*libxcb-randr.so.[0-9]+ -(.*/)*libxcb-render-util.so.[0-9]+ -(.*/)*libxcb-render.so.[0-9]+ -(.*/)*libxcb-shape.so.[0-9]+ -(.*/)*libxcb-shm.so.[0-9]+ -(.*/)*libxcb-sync.so.[0-9]+ -(.*/)*libxcb-util.so.[0-9]+ -(.*/)*libxcb-xfixes.so.[0-9]+ -(.*/)*libxcb-xinerama.so.[0-9]+ -(.*/)*libxcb-xkb.so.[0-9]+ -(.*/)*libxcb.so.[0-9]+ -(.*/)*libxkbcommon-x11.so.[0-9]+ -(.*/)*libxkbcommon.so.[0-9]+ -(.*/)*libxshmfence.so.[0-9]+ - -# OpenGL -(.*/)*libdrm.so.2 -(.*/)*libgbm.so.1 -(.*/)*libEGL.so.1 -(.*/)*libGL.so.1 -(.*/)*libGLX.so.0 -(.*/)*libGLdispatch.so.0 - -# Use system library instead -(.*/)*libasound.so.2 -(.*/)*libpulse.so.0 -(.*/)*libpulse-simple.so.0 -(.*/)*libjack.so.0 -(.*/)*libv4l2.so.0 diff --git a/ports/deploy/tools/qt5.py b/ports/deploy/tools/qt5.py deleted file mode 100644 index 51d1a11..0000000 --- a/ports/deploy/tools/qt5.py +++ /dev/null @@ -1,691 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Webcamoid, webcam capture application. -# Copyright (C) 2017 Gonzalo Exequiel Pedone -# -# Webcamoid 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. -# -# Webcamoid 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 Webcamoid. If not, see . -# -# Web-Site: http://webcamoid.github.io/ - -import configparser -import json -import os -import platform -import re -import shutil -import subprocess # nosec -import sys -import time -import xml.etree.ElementTree as ET - -import tools.utils - - -class DeployToolsQt(tools.utils.DeployToolsUtils): - def __init__(self): - super().__init__() - self.qmake = '' - self.qtIFW = '' - self.qtIFWVersion = '' - self.qtInstallBins = '' - self.qtInstallQml = '' - self.qtInstallPlugins = '' - self.qmlRootDirs = [] - self.qmlInstallDir = '' - self.dependencies = [] - self.binarySolver = None - self.installerConfig = '' - self.appIcon = '' - self.installerRunProgram = '' - self.adminRights = False - - def detectQt(self, path=''): - self.detectQmake(path) - self.qtInstallBins = self.qmakeQuery(var='QT_INSTALL_BINS') - self.qtInstallQml = self.qmakeQuery(var='QT_INSTALL_QML') - self.qtInstallPlugins = self.qmakeQuery(var='QT_INSTALL_PLUGINS') - self.detectQtIFW() - self.detectQtIFWVersion() - - def detectQmake(self, path=''): - for makeFile in self.detectMakeFiles(path): - with open(makeFile) as f: - for line in f: - if line.startswith('QMAKE') and '=' in line: - self.qmake = line.split('=')[1].strip() - - return - - if 'QMAKE_PATH' in os.environ: - self.qmake = os.environ['QMAKE_PATH'] - - def detectTargetBinaryFromQt5Make(self, path=''): - for makeFile in self.detectMakeFiles(path): - with open(makeFile) as f: - for line in f: - if line.startswith('TARGET') and '=' in line: - return os.path.join(path, line.split('=')[1].strip()) - - return '' - - def qmakeQuery(self, qmake='', var=''): - if qmake == '': - if 'QMAKE_PATH' in os.environ: - qmake = os.environ['QMAKE_PATH'] - else: - qmake = self.qmake - - try: - args = [qmake, '-query'] - - if var != '': - args += [var] - - process = subprocess.Popen(args, # nosec - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, _ = process.communicate() - - return stdout.strip().decode(sys.getdefaultencoding()) - except: - pass - - return '' - - @staticmethod - def detectVersion(proFile): - if 'DAILY_BUILD' in os.environ: - return 'daily' - - verMaj = '0' - verMin = '0' - verPat = '0' - - try: - with open(proFile) as f: - for line in f: - if line.startswith('VER_MAJ') and '=' in line: - verMaj = line.split('=')[1].strip() - elif line.startswith('VER_MIN') and '=' in line: - verMin = line.split('=')[1].strip() - elif line.startswith('VER_PAT') and '=' in line: - verPat = line.split('=')[1].strip() - except: - pass - - return verMaj + '.' + verMin + '.' + verPat - - def detectQtIFW(self): - if 'BINARYCREATOR' in os.environ: - self.qtIFW = os.environ['BINARYCREATOR'] - - return - - # Try official Qt binarycreator first because it is statically linked. - - if self.targetSystem == 'windows': - homeQt = 'C:\\Qt' - elif self.targetSystem == 'posix_windows': - if 'WINEPREFIX' in os.environ: - homeQt = os.path.expanduser(os.path.join(os.environ['WINEPREFIX'], - 'drive_c/Qt')) - else: - homeQt = os.path.expanduser('~/.wine/drive_c/Qt') - else: - homeQt = os.path.expanduser('~/Qt') - - binCreator = 'binarycreator' - - if self.targetSystem == 'windows' or self.targetSystem == 'posix_windows': - binCreator += '.exe' - - for root, _, files in os.walk(homeQt): - for f in files: - if f == binCreator: - self.qtIFW = os.path.join(root, f) - - return - - # binarycreator offered by the system is most probably dynamically - # linked, so it's useful for test purposes only, but not recommended - # for distribution. - self.qtIFW = self.whereBin(binCreator) - - def detectQtIFWVersion(self): - self.qtIFWVersion = '' - - if self.qtIFW == '': - return - - installerBase = os.path.join(os.path.dirname(self.qtIFW), - 'installerbase') - - if self.targetSystem == 'windows' or self.targetSystem == 'posix_windows': - installerBase += '.exe' - - self.qtIFWVersion = '2.0.0' - - if not os.path.exists(installerBase): - return - - if self.targetSystem == 'posix_windows': - installerBase = 'Z:' + installerBase.replace('/', '\\') - process = subprocess.Popen(['wine', # nosec - installerBase, - '--version'], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, _ = process.communicate(input=b'\n') - else: - process = subprocess.Popen([installerBase, # nosec - '--version'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, _ = process.communicate() - - for line in stdout.split(b'\n'): - if b'IFW Version:' in line: - self.qtIFWVersion = line.split(b' ')[2].replace(b'"', b'').replace(b',', b'').decode(sys.getdefaultencoding()) - - return - - @staticmethod - def listQmlFiles(path): - qmlFiles = set() - - if os.path.isfile(path): - baseName = os.path.basename(path) - - if baseName == 'qmldir' or path.endswith('.qml'): - qmlFiles.add(path) - else: - for root, _, files in os.walk(path): - for f in files: - if f == 'qmldir' or f.endswith('.qml'): - qmlFiles.add(os.path.join(root, f)) - - return list(qmlFiles) - - @staticmethod - def modulePath(importLine): - imp = importLine.strip().split() - path = imp[1].replace('.', '/') - majorVersion = imp[2].split('.')[0] - - if int(majorVersion) > 1: - path += '.{}'.format(majorVersion) - - return path - - def scanImports(self, path): - if not os.path.isfile(path): - return [] - - fileName = os.path.basename(path) - imports = set() - - if fileName.endswith('.qml'): - with open(path, 'rb') as f: - for line in f: - if re.match(b'^import \\w+' , line): - imports.add(self.modulePath(line.strip().decode(sys.getdefaultencoding()))) - elif fileName == 'qmldir': - with open(path, 'rb') as f: - for line in f: - if re.match(b'^depends ' , line): - imports.add(self.modulePath(line.strip().decode(sys.getdefaultencoding()))) - - return list(imports) - - def solvedepsQml(self): - qmlFiles = set() - - for path in self.qmlRootDirs: - path = os.path.join(self.rootDir, path) - - for f in self.listQmlFiles(path): - qmlFiles.add(f) - - solved = set() - solvedImports = set() - - while len(qmlFiles) > 0: - qmlFile = qmlFiles.pop() - - for imp in self.scanImports(qmlFile): - if imp in solvedImports: - continue - - sysModulePath = os.path.join(self.qtInstallQml, imp) - installModulePath = os.path.join(self.qmlInstallDir, imp) - - if os.path.exists(sysModulePath): - print(' {} -> {}'.format(sysModulePath, installModulePath)) - self.copy(sysModulePath, installModulePath) - solvedImports.add(imp) - self.dependencies.append(os.path.join(sysModulePath, 'qmldir')) - - for f in self.listQmlFiles(sysModulePath): - if not f in solved: - qmlFiles.add(f) - - solved.add(qmlFile) - - def solvedepsPlugins(self): - pluginsMap = { - 'Qt53DRenderer': ['sceneparsers', 'geometryloaders'], - 'Qt53DQuickRenderer': ['renderplugins'], - 'Qt5Declarative': ['qml1tooling'], - 'Qt5EglFSDeviceIntegration': ['egldeviceintegrations'], - 'Qt5Gui': ['accessible', - 'generic', - 'iconengines', - 'imageformats', - 'platforms', - 'platforminputcontexts', - 'styles'], - 'Qt5Location': ['geoservices'], - 'Qt5Multimedia': ['audio', 'mediaservice', 'playlistformats'], - 'Qt5Network': ['bearer'], - 'Qt5Positioning': ['position'], - 'Qt5PrintSupport': ['printsupport'], - 'Qt5QmlTooling': ['qmltooling'], - 'Qt5Quick': ['scenegraph', 'qmltooling'], - 'Qt5Sensors': ['sensors', 'sensorgestures'], - 'Qt5SerialBus': ['canbus'], - 'Qt5Sql': ['sqldrivers'], - 'Qt5TextToSpeech': ['texttospeech'], - 'Qt5WebEngine': ['qtwebengine'], - 'Qt5WebEngineCore': ['qtwebengine'], - 'Qt5WebEngineWidgets': ['qtwebengine'], - 'Qt5WebView': ['webview'], - 'Qt5XcbQpa': ['xcbglintegrations'] - } - - pluginsMap.update({lib + 'd': pluginsMap[lib] for lib in pluginsMap}) - - if self.targetSystem == 'android': - pluginsMap.update({lib + '_' + self.targetArch: pluginsMap[lib] for lib in pluginsMap}) - - plugins = [] - - for dep in self.binarySolver.scanDependencies(self.installDir): - libName = self.binarySolver.name(dep) - - if not libName in pluginsMap: - continue - - for plugin in pluginsMap[libName]: - if not plugin in plugins: - sysPluginPath = os.path.join(self.qtInstallPlugins, plugin) - pluginPath = os.path.join(self.pluginsInstallDir, plugin) - - if not os.path.exists(sysPluginPath): - continue - - print(' {} -> {}'.format(sysPluginPath, pluginPath)) - self.copy(sysPluginPath, pluginPath) - plugins.append(plugin) - self.dependencies.append(sysPluginPath) - - def solvedepsAndroid(self): - installPrefix = self.qmakeQuery(var='QT_INSTALL_PREFIX') - qtLibsPath = self.qmakeQuery(var='QT_INSTALL_LIBS') - jars = [] - permissions = set() - features = set() - initClasses = set() - libs = set() - - for f in os.listdir(self.libInstallDir): - basename = os.path.basename(f)[3:] - basename = os.path.splitext(basename)[0] - depFile = os.path.join(qtLibsPath, - basename + '-android-dependencies.xml') - - if os.path.exists(depFile): - tree = ET.parse(depFile) - root = tree.getroot() - - for jar in root.iter('jar'): - jars.append(jar.attrib['file']) - - if 'initClass' in jar.attrib: - initClasses.append(jar.attrib['initClass']) - - for permission in root.iter('permission'): - permissions.add(permission.attrib['name']) - - for feature in root.iter('feature'): - features.add(feature.attrib['name']) - - for lib in root.iter('lib'): - if 'file' in lib.attrib: - libs.add(lib.attrib['file']) - - self.localLibs = [os.path.basename(lib) for lib in libs] - - print('Copying jar files\n') - - for jar in sorted(jars): - srcPath = os.path.join(installPrefix, jar) - dstPath = os.path.join(self.rootInstallDir, - 'libs', - os.path.basename(jar)) - print(' {} -> {}'.format(srcPath, dstPath)) - self.copy(srcPath, dstPath) - - manifest = os.path.join(self.rootInstallDir, 'AndroidManifest.xml') - manifestTemp = os.path.join(self.rootInstallDir, 'AndroidManifestTemp.xml') - tree = ET.parse(manifest) - root = tree.getroot() - oldFeatures = set() - oldPermissions = set() - - for element in root: - if element.tag == 'uses-feature': - for key in element.attrib: - if key.endswith('name'): - oldFeatures.add(element.attrib[key]) - elif element.tag == 'uses-permission': - for key in element.attrib: - if key.endswith('name'): - oldPermissions.add(element.attrib[key]) - - features -= oldFeatures - permissions -= oldPermissions - featuresWritten = len(features) < 1 - permissionsWritten = len(permissions) < 1 - replace = {'-- %%INSERT_INIT_CLASSES%% --' : ':'.join(sorted(initClasses)), - '-- %%BUNDLE_LOCAL_QT_LIBS%% --': '1', - '-- %%USE_LOCAL_QT_LIBS%% --' : '1', - '-- %%INSERT_LOCAL_LIBS%% --' : ':'.join(sorted(libs)), - '-- %%INSERT_LOCAL_JARS%% --' : ':'.join(sorted(jars))} - - with open(manifest) as inFile: - with open(manifestTemp, 'w') as outFile: - for line in inFile: - for key in replace: - line = line.replace(key, replace[key]) - - outFile.write(line) - spaces = len(line) - line = line.lstrip() - spaces -= len(line) - - if line.startswith('\n'.format(feature)) - - featuresWritten = True - - if line.startswith('\n'.format(permission)) - - permissionsWritten = True - - os.remove(manifest) - shutil.move(manifestTemp, manifest) - - def writeQtConf(self): - prefix = self.binaryInstallDir - - if self.targetSystem == 'mac': - prefix = os.path.abspath(os.path.join(self.binaryInstallDir, '..')) - - paths = {'Plugins': os.path.relpath(self.pluginsInstallDir, prefix).replace('\\', '/'), - 'Imports': os.path.relpath(self.qmlInstallDir, prefix).replace('\\', '/'), - 'Qml2Imports': os.path.relpath(self.qmlInstallDir, prefix).replace('\\', '/')} - confPath = os.path.dirname(self.qtConf) - - if not os.path.exists(confPath): - os.makedirs(confPath) - - with open(self.qtConf, 'w') as qtconf: - qtconf.write('[Paths]\n') - - for path in paths: - qtconf.write('{} = {}\n'.format(path, paths[path])) - - @staticmethod - def readChangeLog(changeLog, appName, version): - if os.path.exists(changeLog): - with open(changeLog) as f: - for line in f: - if not line.startswith('{0} {1}:'.format(appName, version)): - continue - - # Skip first line. - f.readline() - changeLogText = '' - - for line_ in f: - if re.match('{} \d+\.\d+\.\d+:'.format(appName), line): - # Remove last line. - i = changeLogText.rfind('\n') - - if i >= 0: - changeLogText = changeLogText[: i] - - return changeLogText - - changeLogText += line_ - - return '' - - def createInstaller(self): - if not os.path.exists(self.qtIFW): - return False - - # Read package config - packageConf = configparser.ConfigParser() - packageConf.optionxform=str - packageConf.read(self.packageConfig, 'utf-8') - - # Create layout - componentName = 'com.{0}prj.{0}'.format(self.programName) - packageDir = os.path.join(self.installerPackages, componentName) - - if not os.path.exists(self.installerConfig): - os.makedirs(self.installerConfig) - - dataDir = os.path.join(packageDir, 'data') - metaDir = os.path.join(packageDir, 'meta') - - if not os.path.exists(dataDir): - os.makedirs(dataDir) - - if not os.path.exists(metaDir): - os.makedirs(metaDir) - - iconName = '' - - if self.appIcon != '' and os.path.exists(self.appIcon): - self.copy(self.appIcon, self.installerConfig) - iconName = os.path.splitext(os.path.basename(self.appIcon))[0] - - licenseOutFile = os.path.basename(self.licenseFile) - - if not '.' in licenseOutFile and \ - (self.targetSystem == 'windows' or \ - self.targetSystem == 'posix_windows'): - licenseOutFile += '.txt' - - self.copy(self.licenseFile, os.path.join(metaDir, licenseOutFile)) - self.copy(self.rootInstallDir, dataDir) - - configXml = os.path.join(self.installerConfig, 'config.xml') - appName = packageConf['Package']['appName'].strip() - - with open(configXml, 'w') as config: - config.write('\n') - config.write('\n') - config.write(' {}\n'.format(appName)) - - if 'DAILY_BUILD' in os.environ: - config.write(' 0.0.0\n') - else: - config.write(' {}\n'.format(self.programVersion)) - - config.write(' {}\n'.format(packageConf['Package']['description'].strip())) - config.write(' {}\n'.format(appName)) - config.write(' {}\n'.format(packageConf['Package']['url'].strip())) - - if iconName != '': - config.write(' {}\n'.format(iconName)) - config.write(' {}\n'.format(iconName)) - config.write(' {}\n'.format(iconName)) - - if self.installerRunProgram != '': - config.write(' {}\n'.format(self.installerRunProgram)) - config.write(' {}\n'.format(packageConf['Package']['runMessage'].strip())) - config.write(' {}\n'.format(appName)) - - config.write(' {}Uninstall\n'.format(appName)) - config.write(' true\n') - config.write(' {}\n'.format(self.installerTargetDir)) - config.write('\n') - - self.copy(self.installerScript, - os.path.join(metaDir, 'installscript.qs')) - - with open(os.path.join(metaDir, 'package.xml'), 'w') as f: - f.write('\n') - f.write('\n') - f.write(' {}\n'.format(appName)) - f.write(' {}\n'.format(packageConf['Package']['description'].strip())) - - if 'DAILY_BUILD' in os.environ: - f.write(' 0.0.0\n') - else: - f.write(' {}\n'.format(self.programVersion)) - - f.write(' {}\n'.format(time.strftime('%Y-%m-%d'))) - f.write(' {}\n'.format(componentName)) - f.write(' \n') - f.write(' \n'.format(packageConf['Package']['licenseDescription'].strip(), - licenseOutFile)) - f.write(' \n') - f.write(' \n') - f.write(' \n') - - if not 'DAILY_BUILD' in os.environ: - f.write(self.readChangeLog(self.changeLog, - appName, - self.programVersion)) - - f.write(' \n') - f.write(' true\n') - f.write(' true\n') - f.write(' false\n') - - if self.adminRights: - f.write(' true\n') - - f.write('\n') - - # Remove old file - if not os.path.exists(self.pkgsDir): - os.makedirs(self.pkgsDir) - - if os.path.exists(self.outPackage): - os.remove(self.outPackage) - - params = [] - - if self.targetSystem == 'posix_windows': - params = ['wine'] - - params += [self.qtIFW, - '-c', configXml, - '-p', self.installerPackages, - self.outPackage] - process = subprocess.Popen(params, # nosec - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - process.communicate() - - return True - - def copyAndroidTemplates(self): - installPrefix = self.qmakeQuery(var='QT_INSTALL_PREFIX') - sourcesPath = os.path.join(installPrefix, 'src') - templates = [os.path.join(sourcesPath, '3rdparty/gradle'), - os.path.join(sourcesPath, 'android/templates')] - - for template in templates: - self.copy(template, self.rootInstallDir, overwrite=False) - - deploymentSettingsPath = '' - - for f in os.listdir(self.standAloneDir): - if re.match('^android-.+-deployment-settings.json$' , f): - deploymentSettingsPath = os.path.join(self.standAloneDir, f) - - break - - if len(deploymentSettingsPath) < 1: - return - - with open(deploymentSettingsPath) as f: - deploymentSettings = json.load(f) - - properties = os.path.join(self.rootInstallDir, 'gradle.properties') - platform = self.androidPlatform.replace('android-', '') - javaDir = os.path.join(sourcesPath, 'android','java') - - with open(properties, 'w') as f: - if 'sdkBuildToolsRevision' in deploymentSettings: - f.write('androidBuildToolsVersion={}\n'.format(deploymentSettings['sdkBuildToolsRevision'])) - - f.write('androidCompileSdkVersion={}\n'.format(platform)) - f.write('buildDir=build\n') - f.write('qt5AndroidDir={}\n'.format(javaDir)) - - def createRccBundle(self): - rcc = os.path.join(os.path.dirname(self.qmake), 'rcc') - assetsDir = os.path.abspath(os.path.join(self.assetsIntallDir, '..')) - assetsFolder = os.path.relpath(self.assetsIntallDir, assetsDir) - qrcFile = os.path.join(self.assetsIntallDir, assetsFolder + '.qrc') - - params = [rcc, - '--project', - '-o', qrcFile] - process = subprocess.Popen(params, # nosec - cwd=self.assetsIntallDir, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - process.communicate() - - params = [rcc, - '--root=/{}'.format(assetsFolder), - '--binary', - '-o', self.assetsIntallDir + '.rcc', - qrcFile] - process = subprocess.Popen(params, # nosec - cwd=assetsDir, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - process.communicate() - - shutil.rmtree(self.assetsIntallDir, True) diff --git a/ports/deploy/tools/utils.py b/ports/deploy/tools/utils.py deleted file mode 100644 index 6f0edeb..0000000 --- a/ports/deploy/tools/utils.py +++ /dev/null @@ -1,255 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Webcamoid, webcam capture application. -# Copyright (C) 2017 Gonzalo Exequiel Pedone -# -# Webcamoid 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. -# -# Webcamoid 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 Webcamoid. If not, see . -# -# Web-Site: http://webcamoid.github.io/ - -import fnmatch -import hashlib -import multiprocessing -import os -import platform -import shutil -import subprocess # nosec -import sys - -class DeployToolsUtils: - def __init__(self): - self.make = '' - - if os.name == 'posix' and sys.platform.startswith('darwin'): - self.system = 'mac' - elif os.name == 'nt' and sys.platform.startswith('win32'): - self.system = 'windows' - elif os.name == 'posix': - self.system = 'posix' - else: - self.system = '' - - self.arch = platform.architecture()[0] - self.targetArch = self.arch - self.targetSystem = self.system - pathSep = ';' if self.system == 'windows' else ':' - self.sysBinsPath = [] - - if 'PATH' in os.environ: - self.sysBinsPath += \ - [path.strip() for path in os.environ['PATH'].split(pathSep)] - - self.njobs = multiprocessing.cpu_count() - - if self.njobs < 4: - self.njobs = 4 - - def detectTargetArch(self, binary=''): - if binary == '': - binary = self.mainBinary - - self.targetArch = platform.architecture(binary)[0] - - def whereBin(self, binary): - for path in self.sysBinsPath: - path = os.path.join(path, binary) - - if os.path.exists(path): - return path - - return '' - - def copy(self, src, dst='.', copyReals=False, overwrite=True): - if not os.path.exists(src): - return False - - if os.path.isdir(src): - if os.path.isfile(dst): - return False - - for root, dirs, files in os.walk(src): - for f in files: - fromF = os.path.join(root, f) - toF = os.path.relpath(fromF, src) - toF = os.path.join(dst, toF) - toF = os.path.normpath(toF) - self.copy(fromF, toF, copyReals, overwrite) - - for d in dirs: - fromD = os.path.join(root, d) - toD = os.path.relpath(fromD, src) - toD = os.path.join(dst, toD) - - try: - os.makedirs(os.path.normpath(toD)) - except: - pass - elif os.path.isfile(src): - if os.path.isdir(dst): - dst = os.path.realpath(dst) - dst = os.path.join(dst, os.path.basename(src)) - - dirname = os.path.dirname(dst) - - if not os.path.exists(dirname): - try: - os.makedirs(dirname) - except: - return False - - if os.path.exists(dst): - if not overwrite: - return True - - try: - os.remove(dst) - except: - return False - - if copyReals and os.path.islink(src): - realpath = os.path.realpath(src) - basename = os.path.basename(realpath) - os.symlink(os.path.join('.', basename), dst) - self.copy(realpath, - os.path.join(dirname, basename), - copyReals, - overwrite) - else: - try: - if self.system == 'windows': - shutil.copy(src, dst) - else: - shutil.copy(src, dst, follow_symlinks=False) - except: - return False - - return True - - - def move(self, src, dst='.', moveReals=False): - if not os.path.exists(src): - return False - - if os.path.isdir(src): - if os.path.isfile(dst): - return False - - for root, dirs, files in os.walk(src): - for f in files: - fromF = os.path.join(root, f) - toF = os.path.relpath(fromF, src) - toF = os.path.join(dst, toF) - toF = os.path.normpath(toF) - self.move(fromF, toF, moveReals) - - for d in dirs: - fromD = os.path.join(root, d) - toD = os.path.relpath(fromD, src) - toD = os.path.join(dst, toD) - - try: - os.makedirs(os.path.normpath(toD)) - except: - pass - elif os.path.isfile(src): - if os.path.isdir(dst): - dst = os.path.realpath(dst) - dst = os.path.join(dst, os.path.basename(src)) - - dirname = os.path.dirname(dst) - - if not os.path.exists(dirname): - try: - os.makedirs(dirname) - except: - return False - - if os.path.exists(dst): - try: - os.remove(dst) - except: - return False - - if moveReals and os.path.islink(src): - realpath = os.path.realpath(src) - basename = os.path.basename(realpath) - os.symlink(os.path.join('.', basename), dst) - self.move(realpath, os.path.join(dirname, basename), moveReals) - else: - try: - shutil.move(src, dst) - except: - return False - - return True - - def detectMake(self): - if 'MAKE_PATH' in os.environ: - self.make = os.environ['MAKE_PATH'] - - return - - makes = ['mingw32-make', 'make'] if self.system == 'windows' else ['make'] - ext = '.exe' if self.system == 'windows' else '' - - for make in makes: - makePath = self.whereBin(make + ext) - - if makePath != '': - self.make = makePath - - break - - def makeInstall(self, buildDir, params={}): - previousDir = os.getcwd() - os.chdir(buildDir) - params_ = [key + '=' + params[key] for key in params] - process = subprocess.Popen([self.make, 'install'] + params_, # nosec - stdout=subprocess.PIPE) - - process.communicate() - os.chdir(previousDir) - - return process.returncode - - @staticmethod - def sha256sum(fileName): - sha = hashlib.sha256() - - with open(fileName, 'rb') as f: - while True: - data = f.read(1024) - - if not data: - break - - sha.update(data) - - return sha.hexdigest() - - @staticmethod - def detectMakeFiles(makePath): - makeFiles = [] - - try: - for f in os.listdir(makePath): - path = os.path.join(makePath, f) - - if os.path.isfile(path) and fnmatch.fnmatch(f.lower(), 'makefile*'): - makeFiles += [path] - except: - pass - - return makeFiles