Fixed Mac installer.

This commit is contained in:
Gonzalo Exequiel Pedone 2020-06-11 17:38:57 -03:00
parent 3a2d692aa3
commit be30112a27
No known key found for this signature in database
GPG key ID: B8B09E63E9B85BAF
12 changed files with 117 additions and 439 deletions

View file

@ -94,9 +94,9 @@ script:
- chmod +x ports/ci/travis/build.sh - chmod +x ports/ci/travis/build.sh
- ports/ci/travis/build.sh - ports/ci/travis/build.sh
#after_success: after_success:
# - chmod +x ports/ci/travis/deploy.sh - chmod +x ports/ci/travis/deploy.sh
# - ports/ci/travis/deploy.sh - ports/ci/travis/deploy.sh
# - chmod +x ports/ci/travis/upload.sh # - chmod +x ports/ci/travis/upload.sh
# - ports/ci/travis/upload.sh # - ports/ci/travis/upload.sh

0
ChangeLog Normal file
View file

View file

@ -64,7 +64,7 @@ macx: LIBS += \
-framework IOKit \ -framework IOKit \
-framework IOSurface -framework IOSurface
LIBS += \ LIBS += \
-L$${OUT_PWD}/VCamUtils/$${BIN_DIR} -lVCamUtils -L$${OUT_PWD}/../VCamUtils/$${BIN_DIR} -lVCamUtils
isEmpty(STATIC_BUILD) | isEqual(STATIC_BUILD, 0) { isEmpty(STATIC_BUILD) | isEqual(STATIC_BUILD, 0) {
win32-g++: QMAKE_LFLAGS = -static -static-libgcc -static-libstdc++ win32-g++: QMAKE_LFLAGS = -static -static-libgcc -static-libstdc++

View file

@ -62,12 +62,12 @@ build_script:
C:\msys64\usr\bin\bash -lc "cd /c/projects/akvirtualcamera && ./ports/ci/appveyor/build.sh '%INSTALL_PREFIX%'" C:\msys64\usr\bin\bash -lc "cd /c/projects/akvirtualcamera && ./ports/ci/appveyor/build.sh '%INSTALL_PREFIX%'"
) )
#after_build: after_build:
# - if "%MSYS2_BUILD%" == "" ( - if "%MSYS2_BUILD%" == "" (
# ports\ci\appveyor\deploy.bat ports\ci\appveyor\deploy.bat
# ) else ( ) else (
# C:\msys64\usr\bin\bash -lc "cd /c/projects/akvirtualcamera && ./ports/ci/appveyor/deploy.sh" C:\msys64\usr\bin\bash -lc "cd /c/projects/akvirtualcamera && ./ports/ci/appveyor/deploy.sh"
# ) )
# - ports\ci\appveyor\push_artifacts.bat # - ports\ci\appveyor\push_artifacts.bat
# #
#deploy_script: #deploy_script:

View file

@ -38,7 +38,7 @@ win32 {
DEFAULT_PREFIX = C:/ DEFAULT_PREFIX = C:/
} }
} }
macx: DEFAULT_PREFIX = /Library/CoreMediaIO/Plug-Ins/DAL macx: DEFAULT_PREFIX = /Applications
isEmpty(PREFIX): PREFIX = $${DEFAULT_PREFIX} isEmpty(PREFIX): PREFIX = $${DEFAULT_PREFIX}

View file

@ -17,19 +17,12 @@ REM
REM Web-Site: http://webcamoid.github.io/ REM Web-Site: http://webcamoid.github.io/
if "%PLATFORM%" == "x86" ( if "%PLATFORM%" == "x86" (
set FF_ARCH=win32
set GST_ARCH=x86
set VC_ARGS=x86
set PYTHON_PATH=C:\%PYTHON_VERSION% set PYTHON_PATH=C:\%PYTHON_VERSION%
) else ( ) else (
set FF_ARCH=win64
set GST_ARCH=x86_64
set VC_ARGS=amd64
set PYTHON_PATH=C:\%PYTHON_VERSION%-x64 set PYTHON_PATH=C:\%PYTHON_VERSION%-x64
) )
set MAKE_PATH=%TOOLSDIR%\bin\%MAKETOOL%.exe set MAKE_PATH=%TOOLSDIR%\bin\%MAKETOOL%.exe
set GSTREAMER_DEV_PATH=C:\gstreamer\1.0\%GST_ARCH% set PATH=%QTDIR%\bin;%TOOLSDIR%\bin;%PATH%
set PATH=%QTDIR%\bin;%TOOLSDIR%\bin;%CD%\ffmpeg-%FFMPEG_VERSION%-%FF_ARCH%-shared\bin;%GSTREAMER_DEV_PATH%\bin;%PATH%
%PYTHON_PATH%\python.exe ports\deploy\deploy.py %PYTHON_PATH%\python.exe ports\deploy\deploy.py

View file

@ -18,73 +18,13 @@
# #
# Web-Site: http://webcamoid.github.io/ # Web-Site: http://webcamoid.github.io/
if [ "${ARCH_ROOT_BUILD}" = 1 ]; then if [ "${TRAVIS_OS_NAME}" = linux ]; then
EXEC='sudo ./root.x86_64/bin/arch-chroot root.x86_64' EXEC='sudo ./root.x86_64/bin/arch-chroot root.x86_64'
elif [ "${TRAVIS_OS_NAME}" = linux ] && [ -z "${ANDROID_BUILD}" ]; then
if [ -z "${DAILY_BUILD}" ]; then
EXEC="docker exec ${DOCKERSYS}"
else
EXEC="docker exec -e DAILY_BUILD=1 ${DOCKERSYS}"
fi
fi fi
DEPLOYSCRIPT=deployscript.sh DEPLOYSCRIPT=deployscript.sh
if [ "${ANDROID_BUILD}" = 1 ]; then if [ "${TRAVIS_OS_NAME}" = linux ]; then
export JAVA_HOME=$(readlink -f /usr/bin/java | sed 's:bin/java::')
export ANDROID_HOME="${PWD}/build/android-sdk"
export ANDROID_NDK="${PWD}/build/android-ndk"
export ANDROID_NDK_HOME=${ANDROID_NDK}
export ANDROID_NDK_PLATFORM=android-${ANDROID_PLATFORM}
export ANDROID_NDK_ROOT=${ANDROID_NDK}
export ANDROID_SDK_ROOT=${ANDROID_HOME}
export PATH="${JAVA_HOME}/bin/java:${PATH}"
export PATH="$PATH:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin"
export PATH="${PATH}:${ANDROID_HOME}/platform-tools"
export PATH="${PATH}:${ANDROID_HOME}/emulator"
export PATH="${PATH}:${ANDROID_NDK}"
export ORIG_PATH="${PATH}"
export KEYSTORE_PATH="${PWD}/keystores/debug.keystore"
nArchs=$(echo "${TARGET_ARCH}" | tr ':' ' ' | wc -w)
lastArch=$(echo "${TARGET_ARCH}" | awk -F: '{print $NF}')
if [ "${nArchs}" = 1 ]; then
export PATH="${PWD}/build/Qt/${QTVER}/android/bin:${PWD}/.local/bin:${ORIG_PATH}"
export BUILD_PATH=${PWD}/build-webcamoid-${lastArch}
python3 ports/deploy/deploy.py
else
pkgMerge=
for arch_ in $(echo "${TARGET_ARCH}" | tr ":" "\n"); do
if [ ! -z "${pkgMerge}" ]; then
pkgMerge=${pkgMerge}:
fi
pkgMerge=${pkgMerge}${PWD}/build-webcamoid-${arch_}
done
for arch_ in $(echo "${TARGET_ARCH}" | tr ":" "\n"); do
export PATH="${PWD}/build/Qt/${QTVER}/android/bin:${PWD}/.local/bin:${ORIG_PATH}"
export BUILD_PATH=${PWD}/build-webcamoid-${arch_}
if [ "${arch_}" = "${lastArch}" ]; then
export PACKAGES_PREPARE_ONLY=0
export PACKAGES_MERGE="${pkgMerge}"
else
export PACKAGES_PREPARE_ONLY=1
fi
export NO_SHOW_PKG_DATA_INFO=1
python3 ports/deploy/deploy.py
done
fi
mkdir -p "${PWD}/ports/deploy/packages_auto"
cp -rvf "${PWD}/build-webcamoid-${lastArch}/ports/deploy/packages_auto"/* \
"${PWD}/ports/deploy/packages_auto"
elif [ "${ARCH_ROOT_BUILD}" = 1 ]; then
sudo mount --bind root.x86_64 root.x86_64 sudo mount --bind root.x86_64 root.x86_64
sudo mount --bind $HOME root.x86_64/$HOME sudo mount --bind $HOME root.x86_64/$HOME
@ -113,17 +53,6 @@ EOF
${EXEC} bash $HOME/${DEPLOYSCRIPT} ${EXEC} bash $HOME/${DEPLOYSCRIPT}
sudo umount root.x86_64/$HOME sudo umount root.x86_64/$HOME
sudo umount root.x86_64 sudo umount root.x86_64
elif [ "${TRAVIS_OS_NAME}" = linux ]; then
cat << EOF > ${DEPLOYSCRIPT}
#!/bin/sh
export PATH="\$PWD/.local/bin:\$PATH"
xvfb-run --auto-servernum python3 ports/deploy/deploy.py
EOF
chmod +x ${DEPLOYSCRIPT}
${EXEC} bash ${DEPLOYSCRIPT}
elif [ "${TRAVIS_OS_NAME}" = osx ]; then elif [ "${TRAVIS_OS_NAME}" = osx ]; then
${EXEC} python3 ports/deploy/deploy.py ${EXEC} python3 ports/deploy/deploy.py
fi fi

View file

@ -38,34 +38,23 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt):
super().__init__() super().__init__()
self.installDir = os.path.join(self.buildDir, 'ports/deploy/temp_priv') 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.pkgsDir = os.path.join(self.buildDir, 'ports/deploy/packages_auto', self.targetSystem)
self.detectQt(os.path.join(self.buildDir, 'StandAlone')) self.detectQt(os.path.join(self.buildDir, 'Manager'))
self.rootInstallDir = os.path.join(self.installDir, 'Applications') self.rootInstallDir = os.path.join(self.installDir, 'Applications')
self.programName = 'webcamoid' self.programName = 'AkVirtualCamera'
self.appBundleDir = os.path.join(self.rootInstallDir, self.programName + '.app') self.appBundleDir = os.path.join(self.rootInstallDir, self.programName + '.plugin')
self.execPrefixDir = os.path.join(self.appBundleDir, 'Contents') self.execPrefixDir = os.path.join(self.appBundleDir, 'Contents')
self.binaryInstallDir = os.path.join(self.execPrefixDir, 'MacOS') self.binaryInstallDir = os.path.join(self.execPrefixDir, 'MacOS')
self.libInstallDir = os.path.join(self.execPrefixDir, 'Frameworks')
self.qmlInstallDir = os.path.join(self.execPrefixDir, 'Resources/qml')
self.pluginsInstallDir = os.path.join(self.execPrefixDir, 'Plugins')
self.qtConf = os.path.join(self.execPrefixDir, 'Resources/qt.conf')
self.qmlRootDirs = ['StandAlone/share/qml', 'libAvKys/Plugins']
self.mainBinary = os.path.join(self.binaryInstallDir, self.programName) self.mainBinary = os.path.join(self.binaryInstallDir, self.programName)
self.programVersion = self.detectVersion(os.path.join(self.rootDir, 'commons.pri')) self.programVersion = self.detectVersion(os.path.join(self.rootDir, 'commons.pri'))
self.detectMake() self.detectMake()
xspec = self.qmakeQuery(var='QMAKE_XSPEC')
if 'android' in xspec:
self.targetSystem = 'android'
self.binarySolver = tools.binary_mach.DeployToolsBinary() self.binarySolver = tools.binary_mach.DeployToolsBinary()
self.binarySolver.readExcludeList(os.path.join(self.rootDir, 'ports/deploy/exclude.{}.{}.txt'.format(os.name, sys.platform))) self.binarySolver.readExcludeList(os.path.join(self.rootDir, 'ports/deploy/exclude.{}.{}.txt'.format(os.name, sys.platform)))
self.packageConfig = os.path.join(self.rootDir, 'ports/deploy/package_info.conf') self.packageConfig = os.path.join(self.rootDir, 'ports/deploy/package_info.conf')
self.dependencies = [] self.dependencies = []
self.installerConfig = os.path.join(self.installDir, 'installer/config') self.installerConfig = os.path.join(self.installDir, 'installer/config')
self.installerPackages = os.path.join(self.installDir, 'installer/packages') self.installerPackages = os.path.join(self.installDir, 'installer/packages')
self.appIcon = os.path.join(self.execPrefixDir, 'Resources/{0}.icns'.format(self.programName)) self.appIcon = os.path.join(self.rootDir, 'share/TestFrame/webcamoid.png')
self.licenseFile = os.path.join(self.rootDir, 'COPYING') self.licenseFile = os.path.join(self.rootDir, 'COPYING')
self.installerRunProgram = '@TargetDir@/{0}.app/Contents/MacOS/{0}'.format(self.programName)
self.installerTargetDir = '@ApplicationsDir@/' + self.programName self.installerTargetDir = '@ApplicationsDir@/' + self.programName
self.installerScript = os.path.join(self.rootDir, 'ports/deploy/installscript.mac.qs') self.installerScript = os.path.join(self.rootDir, 'ports/deploy/installscript.mac.qs')
self.changeLog = os.path.join(self.rootDir, 'ChangeLog') self.changeLog = os.path.join(self.rootDir, 'ChangeLog')
@ -77,160 +66,14 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt):
print('Executing make install') print('Executing make install')
self.makeInstall(self.buildDir, self.installDir) self.makeInstall(self.buildDir, self.installDir)
self.detectTargetArch() self.detectTargetArch()
print('Copying Qml modules\n')
self.solvedepsQml()
print('\nCopying required plugins\n')
self.solvedepsPlugins()
print('\nCopying required libs\n')
self.solvedepsLibs()
print('\nWritting qt.conf file')
self.writeQtConf()
print('Stripping symbols') print('Stripping symbols')
self.binarySolver.stripSymbols(self.installDir) self.binarySolver.stripSymbols(self.installDir)
print('Resetting file permissions') print('Resetting file permissions')
self.binarySolver.resetFilePermissions(self.rootInstallDir, self.binarySolver.resetFilePermissions(self.rootInstallDir,
self.binaryInstallDir) self.binaryInstallDir)
print('Removing unnecessary files')
self.removeUnneededFiles(self.libInstallDir)
print('Fixing rpaths\n')
self.fixRpaths()
print('\nWritting build system information\n') print('\nWritting build system information\n')
self.writeBuildInfo() self.writeBuildInfo()
def solvedepsLibs(self):
deps = sorted(self.binarySolver.scanDependencies(self.installDir))
for dep in deps:
depPath = os.path.join(self.libInstallDir, os.path.basename(dep))
if dep != depPath:
print(' {} -> {}'.format(dep, depPath))
self.copy(dep, depPath, not dep.endswith('.framework'))
self.dependencies.append(dep)
@staticmethod
def removeUnneededFiles(path):
adirs = set()
afiles = set()
for root, dirs, files in os.walk(path):
for d in dirs:
if d == 'Headers':
adirs.add(os.path.join(root, d))
for f in files:
if f == 'Headers' or f.endswith('.prl'):
afiles.add(os.path.join(root, f))
for adir in adirs:
try:
shutil.rmtree(adir, True)
except:
pass
for afile in afiles:
try:
if os.path.islink(afile):
os.unlink(afile)
else:
os.remove(afile)
except:
pass
def fixLibRpath(self, mutex, mach):
rpath = os.path.join('@executable_path',
os.path.relpath(self.libInstallDir,
self.binaryInstallDir))
log = '\tFixed {}\n\n'.format(mach)
machInfo = self.binarySolver.dump(mach)
# Change rpath
if mach.startswith(self.binaryInstallDir):
log += '\t\tChanging rpath to {}\n'.format(rpath)
for oldRpath in machInfo['rpaths']:
process = subprocess.Popen(['install_name_tool', # nosec
'-delete_rpath', oldRpath, mach],
stdout=subprocess.PIPE)
process.communicate()
process = subprocess.Popen(['install_name_tool', # nosec
'-add_rpath', rpath, mach],
stdout=subprocess.PIPE)
process.communicate()
# Change ID
if mach.startswith(self.binaryInstallDir):
newMachId = machInfo['id']
elif mach.startswith(self.libInstallDir):
newMachId = mach.replace(self.libInstallDir, rpath)
else:
newMachId = os.path.basename(mach)
if newMachId != machInfo['id']:
log += '\t\tChanging ID to {}\n'.format(newMachId)
process = subprocess.Popen(['install_name_tool', # nosec
'-id', newMachId, mach],
stdout=subprocess.PIPE)
process.communicate()
# Change library links
for dep in machInfo['imports']:
if dep.startswith(rpath):
continue
if self.binarySolver.isExcluded(dep):
continue
basename = os.path.basename(dep)
framework = ''
inFrameworkPath = ''
if not basename.endswith('.dylib'):
frameworkPath = dep[: dep.rfind('.framework')] + '.framework'
framework = os.path.basename(frameworkPath)
inFrameworkPath = os.path.join(framework, dep.replace(frameworkPath + '/', ''))
newDepPath = os.path.join(rpath, basename if len(framework) < 1 else inFrameworkPath)
if dep != newDepPath:
log += '\t\t{} -> {}\n'.format(dep, newDepPath)
process = subprocess.Popen(['install_name_tool', # nosec
'-change', dep, newDepPath, mach],
stdout=subprocess.PIPE)
process.communicate()
mutex.acquire()
print(log)
mutex.release()
def fixRpaths(self):
path = os.path.join(self.execPrefixDir)
mutex = threading.Lock()
threads = []
for mach in self.binarySolver.find(path):
thread = threading.Thread(target=self.fixLibRpath, args=(mutex, mach,))
threads.append(thread)
while threading.active_count() >= self.njobs:
time.sleep(0.25)
thread.start()
for thread in threads:
thread.join()
@staticmethod
def searchPackageFor(cellarPath, path):
if not path.startswith(cellarPath):
return ''
return ' '.join(path.replace(cellarPath + os.sep, '').split(os.sep)[0: 2])
def commitHash(self): def commitHash(self):
try: try:
process = subprocess.Popen(['git', 'rev-parse', 'HEAD'], # nosec process = subprocess.Popen(['git', 'rev-parse', 'HEAD'], # nosec
@ -256,8 +99,18 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt):
return stdout.decode(sys.getdefaultencoding()).strip() return stdout.decode(sys.getdefaultencoding()).strip()
def writeBuildInfo(self): def writeBuildInfo(self):
try:
os.makedirs(self.pkgsDir)
except:
pass
resourcesDir = os.path.join(self.execPrefixDir, 'Resources') resourcesDir = os.path.join(self.execPrefixDir, 'Resources')
os.makedirs(self.pkgsDir)
try:
os.makedirs(resourcesDir)
except:
pass
depsInfoFile = os.path.join(resourcesDir, 'build-info.txt') depsInfoFile = os.path.join(resourcesDir, 'build-info.txt')
# Write repository info. # Write repository info.
@ -300,35 +153,6 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt):
print() print()
f.write('\n') f.write('\n')
os.environ['LC_ALL'] = 'C'
brew = self.whereBin('brew')
if len(brew) < 1:
return
process = subprocess.Popen([brew, '--cellar'], # nosec
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, _ = process.communicate()
cellarPath = stdout.decode(sys.getdefaultencoding()).strip()
# Write binary dependencies info.
packages = set()
for dep in self.dependencies:
packageInfo = self.searchPackageFor(cellarPath, dep)
if len(packageInfo) > 0:
packages.add(packageInfo)
packages = sorted(packages)
with open(depsInfoFile, 'a') as f:
for packge in packages:
print(' ' + packge)
f.write(packge + '\n')
@staticmethod @staticmethod
def hrSize(size): def hrSize(size):
i = int(math.log(size) // math.log(1024)) i = int(math.log(size) // math.log(1024))
@ -365,109 +189,6 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt):
return size return size
# https://asmaloney.com/2013/07/howto/packaging-a-mac-os-x-application-using-a-dmg/
def createPortable(self, mutex):
staggingDir = os.path.join(self.installDir, 'stagging')
if not os.path.exists(staggingDir):
os.makedirs(staggingDir)
self.copy(self.appBundleDir,
os.path.join(staggingDir, self.programName + '.app'))
imageSize = self.dirSize(staggingDir)
tmpDmg = os.path.join(self.installDir, self.programName + '_tmp.dmg')
volumeName = "{}-portable-{}".format(self.programName,
self.programVersion)
process = subprocess.Popen(['hdiutil', 'create', # nosec
'-srcfolder', staggingDir,
'-volname', volumeName,
'-fs', 'HFS+',
'-fsargs', '-c c=64,a=16,e=16',
'-format', 'UDRW',
'-size', str(math.ceil(imageSize * 1.1)),
tmpDmg],
stdout=subprocess.PIPE)
process.communicate()
process = subprocess.Popen(['hdiutil', # nosec
'attach',
'-readwrite',
'-noverify',
tmpDmg],
stdout=subprocess.PIPE)
stdout, _ = process.communicate()
device = ''
for line in stdout.split(b'\n'):
line = line.strip()
if len(line) < 1:
continue
dev = line.split()
if len(dev) > 2:
device = dev[0].decode(sys.getdefaultencoding())
break
time.sleep(2)
volumePath = os.path.join('/Volumes', volumeName)
volumeIcon = os.path.join(volumePath, '.VolumeIcon.icns')
self.copy(self.appIcon, volumeIcon)
process = subprocess.Popen(['SetFile', # nosec
'-c', 'icnC',
volumeIcon],
stdout=subprocess.PIPE)
process.communicate()
process = subprocess.Popen(['SetFile', # nosec
'-a', 'C',
volumePath],
stdout=subprocess.PIPE)
process.communicate()
appsShortcut = os.path.join(volumePath, 'Applications')
if not os.path.exists(appsShortcut):
os.symlink('/Applications', appsShortcut)
os.sync()
process = subprocess.Popen(['hdiutil', # nosec
'detach',
device],
stdout=subprocess.PIPE)
process.communicate()
packagePath = \
os.path.join(self.pkgsDir,
'{}-portable-{}-{}.dmg'.format(self.programName,
self.programVersion,
platform.machine()))
if not os.path.exists(self.pkgsDir):
os.makedirs(self.pkgsDir)
if os.path.exists(packagePath):
os.remove(packagePath)
process = subprocess.Popen(['hdiutil', # nosec
'convert',
tmpDmg,
'-format', 'UDZO',
'-imagekey', 'zlib-level=9',
'-o', packagePath],
stdout=subprocess.PIPE)
process.communicate()
mutex.acquire()
print('Created portable package:')
self.printPackageInfo(packagePath)
mutex.release()
def createAppInstaller(self, mutex): def createAppInstaller(self, mutex):
packagePath = self.createInstaller() packagePath = self.createInstaller()
@ -481,9 +202,8 @@ class Deploy(deploy_base.DeployBase, tools.qt5.DeployToolsQt):
def package(self): def package(self):
mutex = threading.Lock() mutex = threading.Lock()
threads = []
threads = [threading.Thread(target=self.createPortable, args=(mutex,))] packagingTools = []
packagingTools = ['dmg']
if self.qtIFW != '': if self.qtIFW != '':
threads.append(threading.Thread(target=self.createAppInstaller, args=(mutex,))) threads.append(threading.Thread(target=self.createAppInstaller, args=(mutex,)))

View file

@ -10,4 +10,77 @@ Component.prototype.beginInstallation = function()
Component.prototype.createOperations = function() Component.prototype.createOperations = function()
{ {
component.createOperations(); component.createOperations();
// Remove old plugin
if (installer.isInstaller()) {
component.addOperation("ConsumeOutput",
"AkPluginSymlink",
"/usr/bin/readlink",
"/Library/CoreMediaIO/Plug-Ins/DAL/@Name@.plugin");
if (installer.value("AkPluginSymlink") == "")
component.addElevatedOperation("Execute",
"rm",
"-rf",
"/Library/CoreMediaIO/Plug-Ins/DAL/@Name@.plugin");
}
// Create a symlink to the plugin.
component.addElevatedOperation("Execute",
"ln",
"-s",
"@TargetDir@/@Name@.plugin",
"/Library/CoreMediaIO/Plug-Ins/DAL/@Name@.plugin",
"UNDOEXECUTE",
"rm",
"-f",
"/Library/CoreMediaIO/Plug-Ins/DAL/@Name@.plugin");
// Set assistant daemon.
let daemonPlist = "/Library/LaunchAgents/org.webcamoid.cmio.AkVCam.Assistant.plist"
let plistContents = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
+ "<plist version=\"1.0\">\n"
+ " <dict>\n"
+ " <key>Label</key>\n"
+ " <string>org.webcamoid.cmio.AkVCam.Assistant</string>\n"
+ " <key>ProgramArguments</key>\n"
+ " <array>\n"
+ " <string>"
+ installer.value("TargetDir")
+ "/AkVirtualCamera.plugin/Contents/Resources/AkVCamAssistant"
+ "</string>\n"
+ " <string>--timeout</string>\n"
+ " <string>300.0</string>\n"
+ " </array>\n"
+ " <key>MachServices</key>\n"
+ " <dict>\n"
+ " <key>org.webcamoid.cmio.AkVCam.Assistant</key>\n"
+ " <true/>\n"
+ " </dict>\n"
+ " </dict>\n"
+ "</plist>\n";
component.addElevatedOperation("Delete", daemonPlist);
component.addElevatedOperation("AppendFile", daemonPlist, plistContents);
// Load assistant daemon.
component.addElevatedOperation("Execute",
"launchctl", "load", "-w", daemonPlist,
"UNDOEXECUTE",
"launchctl", "unload", "-w", daemonPlist);
if (installer.isUninstaller())
component.addElevatedOperation("Delete", daemonPlist);
if (installer.value("TargetDir") != "/Applications/" + installer.value("Name"))
component.addElevatedOperation("Execute",
"ln",
"-s",
"@TargetDir@",
"/Applications/@Name@",
"UNDOEXECUTE",
"rm",
"-f",
"/Applications/@Name@");
} }

View file

@ -10,44 +10,4 @@ Component.prototype.beginInstallation = function()
Component.prototype.createOperations = function() Component.prototype.createOperations = function()
{ {
component.createOperations(); component.createOperations();
component.addOperation("InstallIcons", "@TargetDir@/share/icons" );
component.addOperation("CreateDesktopEntry",
"Webcamoid.desktop",
"Name=Webcamoid\n"
+ "GenericName=Webcam Capture Software\n"
+ "GenericName[ca]=Programari de Captura de Càmera web\n"
+ "GenericName[de]=Webcam-Capture-Software\n"
+ "GenericName[el]=κάμερα συλλαμβάνει το λογισμικό\n"
+ "GenericName[es]=Programa para Captura de la Webcam\n"
+ "GenericName[fr]=Logiciel de Capture Webcam\n"
+ "GenericName[gl]=Programa de Captura de Webcam\n"
+ "GenericName[it]=Webcam Capture Software\n"
+ "GenericName[ja]=ウェブカメラのキャプチャソフトウェア\n"
+ "GenericName[ko]=웹캠 캡처 소프트웨어\n"
+ "GenericName[pt]=Software de Captura de Webcam\n"
+ "GenericName[ru]=Веб-камера захвата программного обеспечения\n"
+ "GenericName[zh_CN]=摄像头捕捉软件\n"
+ "GenericName[zh_TW]=攝像頭捕捉軟件\n"
+ "Comment=Take photos and record videos with your webcam\n"
+ "Comment[ca]=Fer fotos i gravar vídeos amb la seva webcam\n"
+ "Comment[de]=Maak foto's en video's opnemen met uw webcam\n"
+ "Comment[el]=Τραβήξτε φωτογραφίες και εγγραφή βίντεο με την κάμερα σας\n"
+ "Comment[es]=Tome fotos y grabe videos con su camara web\n"
+ "Comment[fr]=Prenez des photos et enregistrer des vidéos avec votre webcam\n"
+ "Comment[gl]=Facer fotos e gravar vídeos coa súa cámara web\n"
+ "Comment[it]=Scatta foto e registrare video con la tua webcam\n"
+ "Comment[ja]=ウェブカメラで写真や記録ビデオを撮影\n"
+ "Comment[ko]=웹캠으로 사진과 기록 비디오를 촬영\n"
+ "Comment[pt]=Tirar fotos e gravar vídeos com sua webcam\n"
+ "Comment[ru]=Возьмите фотографии и записывать видео с веб-камеры\n"
+ "Comment[zh_CN]=拍摄照片和录制视频与您的摄像头\n"
+ "Comment[zh_TW]=拍攝照片和錄製視頻與您的攝像頭\n"
+ "Keywords=photo;video;webcam;\n"
+ "Exec=" + installer.value("RunProgram") + "\n"
+ "Icon=webcamoid\n"
+ "Terminal=false\n"
+ "Type=Application\n"
+ "Categories=AudioVideo;Player;Qt;\n"
+ "StartupNotify=true\n");
} }

View file

@ -1,7 +1,6 @@
[Package] [Package]
appName = Webcamoid appName = AkVirtualCamera
description = Webcamoid, The ultimate webcam suite! description = AkVirtualCamera, virtual camera for Mac and Windows
url = https://webcamoid.github.io/ url = https://github.com/webcamoid/akvirtualcamera
titleColor = #3F1F7F titleColor = #3F1F7F
runMessage = Launch Webcamoid now!
licenseDescription = GNU General Public License v3.0 licenseDescription = GNU General Public License v3.0

View file

@ -47,6 +47,7 @@ class DeployToolsQt(tools.utils.DeployToolsUtils):
self.dependencies = [] self.dependencies = []
self.binarySolver = None self.binarySolver = None
self.installerConfig = '' self.installerConfig = ''
self.installerRunProgram = ''
def detectQt(self, path=''): def detectQt(self, path=''):
self.detectQmake(path) self.detectQmake(path)
@ -495,7 +496,7 @@ class DeployToolsQt(tools.utils.DeployToolsUtils):
packageConf.read(self.packageConfig, 'utf-8') packageConf.read(self.packageConfig, 'utf-8')
# Create layout # Create layout
componentName = 'com.{0}prj.{0}'.format(self.programName) componentName = 'com.webcamoidprj.{0}'.format(self.programName)
packageDir = os.path.join(self.installerPackages, componentName) packageDir = os.path.join(self.installerPackages, componentName)
if not os.path.exists(self.installerConfig): if not os.path.exists(self.installerConfig):
@ -541,11 +542,13 @@ class DeployToolsQt(tools.utils.DeployToolsUtils):
config.write(' <InstallerWindowIcon>{}</InstallerWindowIcon>\n'.format(iconName)) config.write(' <InstallerWindowIcon>{}</InstallerWindowIcon>\n'.format(iconName))
config.write(' <InstallerApplicationIcon>{}</InstallerApplicationIcon>\n'.format(iconName)) config.write(' <InstallerApplicationIcon>{}</InstallerApplicationIcon>\n'.format(iconName))
config.write(' <Logo>{}</Logo>\n'.format(iconName)) config.write(' <Logo>{}</Logo>\n'.format(iconName))
config.write(' <TitleColor>{}</TitleColor>\n'.format(packageConf['Package']['titleColor'].strip()))
config.write(' <RunProgram>{}</RunProgram>\n'.format(self.installerRunProgram)) if self.installerRunProgram != '':
config.write(' <RunProgramDescription>{}</RunProgramDescription>\n'.format(packageConf['Package']['runMessage'].strip())) config.write(' <RunProgram>{}</RunProgram>\n'.format(self.installerRunProgram))
config.write(' <StartMenuDir>{}</StartMenuDir>\n'.format(appName)) config.write(' <RunProgramDescription>{}</RunProgramDescription>\n'.format(packageConf['Package']['runMessage'].strip()))
config.write(' <MaintenanceToolName>{}MaintenanceTool</MaintenanceToolName>\n'.format(appName)) config.write(' <StartMenuDir>{}</StartMenuDir>\n'.format(appName))
config.write(' <MaintenanceToolName>Uninstall</MaintenanceToolName>\n')
config.write(' <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>\n') config.write(' <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>\n')
config.write(' <TargetDir>{}</TargetDir>\n'.format(self.installerTargetDir)) config.write(' <TargetDir>{}</TargetDir>\n'.format(self.installerTargetDir))
config.write('</Installer>\n') config.write('</Installer>\n')
@ -582,6 +585,7 @@ class DeployToolsQt(tools.utils.DeployToolsUtils):
f.write(' <Default>true</Default>\n') f.write(' <Default>true</Default>\n')
f.write(' <ForcedInstallation>true</ForcedInstallation>\n') f.write(' <ForcedInstallation>true</ForcedInstallation>\n')
f.write(' <Essential>false</Essential>\n') f.write(' <Essential>false</Essential>\n')
f.write(' <RequiresAdminRights>true</RequiresAdminRights>\n')
f.write('</Package>\n') f.write('</Package>\n')
# Remove old file # Remove old file