1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-07-23 00:45:29 +02:00

build: Import build.py and associated scripts from jami-project.

Bring over the build.py script and its associated scripts from the
scripts subdirectory of the jami-project.git as of commit
14a328b88007bff5ea21650fb00f6d4ead14cf02, with small changes to
simplify and drop unneeded parts and adapt to their new locations.

Change-Id: I500702854e45392a931ff7505e191b966015cd16
This commit is contained in:
Amin Bandali 2022-11-02 09:55:39 -04:00 committed by Sébastien Blin
parent adcdcc8c1e
commit 355c0e63d5
7 changed files with 1445 additions and 39 deletions

6
.gitignore vendored
View file

@ -19,12 +19,16 @@ changelog.html
obj/
build/
build-local/
install-local/
build-global/
install/
*.vcxproj
*.vcxproj.filters
*qmlcache.qrc
.deploy.stamp
*.log
*.pid
# auto-gen files
src/app/resources.qrc
src/app/qml.qrc

View file

@ -1,8 +1,8 @@
# Build instructions
There is basically two ways to build `client-qt`:
There are essentially two ways to build `client-qt`:
- Use `build.py` script which will build all Jami (daemon/client lib/client-qt)
- Use `build.py` script which will build all of Jami (daemon and client)
- Build only this client.
## Disclaimer
@ -55,14 +55,14 @@ Then, you can build the project
### With build.py
```bash
git clone https://review.jami.net/jami-project
```
Jami installer uses **python3 (minimum v3.6)**. If it's not installed, please install it:
The build.py Jami installer uses **python3 (minimum v3.6)**. If it's not installed,
please install it. Then run the following to initialize and update
the submodules to set them at the top of their latest commit (ideal
for getting the latest development versions; otherwise, you can use
`git submodule update --init` then checkout specific commits for each
submodule).
```bash
cd jami-project/
./build.py --init
```
@ -71,21 +71,24 @@ Then you will need to install dependencies:
- For GNU/Linux
```bash
./build.py --dependencies --qt # needs sudo
./build.py --dependencies # needs sudo
```
Then, you can build daemon and the client with:
Then, you can build daemon and the client using:
```bash
./build.py --install --qt
./build.py --install
```
And you will have the daemon in `daemon/bin/jamid` and the client in `client-qt/build-local/jami`. You also can run it with
If you use a Qt version that is not system-wide installed, you need to
specify its path using the `--qt` flag, e.g.
`./build.py --install --qt=/home/<username>/Qt/6.2.1/gcc_64`.
If you use a Qt version that is not wide-system installed you need to specify its path after the `--qt` flag, i. e., `./build.py --install --qt /home/<username>/Qt/6.2.1/gcc_64
Now you will have the daemon in `daemon/bin/jamid` and the client in
`build/bin/jami`. You can now run Jami using
```bash
./build.py --run --qt
./build.py --run
```
Notes:
@ -122,7 +125,7 @@ cmake can take some options:
e.g. (with Qt version from https://jami.net)
```
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=jami-project/install/client-qt -DCMAKE_PREFIX_PATH=/usr/lib/libqt-jami
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_PREFIX_PATH=/usr/lib/libqt-jami
```
After the build has finished, you are finally ready to launch jami in your build directory.
@ -208,9 +211,8 @@ Only 64-bit MSVC build can be compiled.
```bash
python build.py --install
cd client-qt
python build.py init
python build.py --qtver <your qt version>
python extras\scripts\build-windows.py init
python extras\scripts\build-windows.py --qtver <your qt version>
```
- Then you should be able to use the Visual Studio Solution file in client-qt folder **(Configuration = Release, Platform = x64)**
@ -221,15 +223,15 @@ Only 64-bit MSVC build can be compiled.
**Daemon**
- Make sure that dependencies is built by make-ring.py
- On MSVC folder (jami-project\daemon\MSVC):
- Make sure that dependencies is built by build.py
- On MSVC folder (daemon\MSVC):
```sh
cmake -DCMAKE_CONFIGURATION_TYPES="ReleaseLib_win32" -DCMAKE_VS_PLATFORM_NAME="x64" -G "Visual Studio 16 2019" -A x64 -T '$(DefaultPlatformToolset)' ..
python winmake.py -b daemon
```
- This will generate a `.lib` file in the path of ring-project\daemon\MSVC\x64\ReleaseLib_win32\bin
- This will generate a `.lib` file in the path of daemon\MSVC\x64\ReleaseLib_win32\bin
> Note: each dependencies contrib for daemon can also be updated individually <br>
> For example:
@ -240,15 +242,14 @@ Only 64-bit MSVC build can be compiled.
**Jami**
- Make sure that daemon, is built first
- Make sure that daemon is built first. Then,
```bash
cd client-qt
python build.py init
python build.py
python extras\scripts\build-windows.py init
python extras\scripts\build-windows.py
```
Note: if your qt version is different than 6.2.3, you need to use `python build.py --qtver <your qt version>`.
Note: if your qt version is different than 6.2.3, you need to use `python extras\scripts\build-windows.py --qtver <your qt version>`.
## Building On MacOS
@ -272,33 +273,31 @@ Then, you can build the project
**Build with build.py**
```bash
git clone https://review.jami.net/jami-project
cd jami-project
./build.py --init
./build.py --dependencies --qt
./build.py --install --qt
./build.py --dependencies
./build.py --install
```
If you use a Qt version that is installed in a different than standard location you need to specify its path
```bash
./build.py --install --qt QT_ROOT_DIRECTORY=your_qt_directory
QT_ROOT_DIRECTORY=your_qt_directory ./build.py --install
```
Built client could be find in `client-qt/build-local/Jami`
Built client could be find in `build/Jami`
## Packaging On Native Windows
- To be able to generate a msi package, first download and install [Wixtoolset](https://wixtoolset.org/releases/).
- In Visual Studio, download WiX Toolset Visual Studio Extension.
- Build client-qt project first, then the JamiInstaller project, msi package should be stored in jami-project\client-qt\JamiInstaller\bin\Release
- Build client-qt project first, then the JamiInstaller project, msi package should be stored in JamiInstaller\bin\Release
## Testing for Client-qt on Windows
- We currently use [GoogleTest](https://github.com/google/googletest) and [Qt Quick Test](https://doc.qt.io/qt-5/qtquicktest-index.html#introduction) in our product. To build and run tests, you could use the following command.
```
python build.py [runtests, pack]
python extras\scripts\build-windows.py [runtests, pack]
```
- Note that, for tests, the path of local storage files for jami will be changed based on following environment variables.
@ -309,11 +308,11 @@ Built client could be find in `client-qt/build-local/Jami`
%JAMI_CACHE_HOME% = %TEMP% + '\\jami_test\\.cache'
```
- These environment variables will be temporarily set when using make-client.py to run tests.
- These environment variables will be temporarily set when using build-windows.py to run tests.
## Debugging
Compile the client with `BUILD=Debug` and compile LibRingClient with
`-DCMAKE_BUILD_TYPE=Debug`
Compile the client with with `-DCMAKE_BUILD_TYPE=Debug`.
Then, if you want to enable logging when running `jami` launch it with `-d` or `--debug`
Then, if you want to enable logging when running `jami`, launch it
with `-d` or `--debug`.

696
build.py Executable file
View file

@ -0,0 +1,696 @@
#!/usr/bin/env python3
# build.py --- Convenience script for building and running Jami
# Copyright (C) 2016-2022 Savoir-faire Linux Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import argparse
import contextlib
import multiprocessing
import os
import platform
import shlex
import shutil
import subprocess
import sys
import time
OSX_DISTRIBUTION_NAME = "osx"
WIN32_DISTRIBUTION_NAME = "win32"
# vs vars
win_sdk_default = '10.0.16299.0'
win_toolset_default = '142'
APT_BASED_DISTROS = [
'debian',
'linuxmint',
'raspbian',
'trisquel',
'ubuntu',
]
DNF_BASED_DISTROS = [
'fedora', 'rhel',
]
PACMAN_BASED_DISTROS = [
'arch', 'parabola',
]
ZYPPER_BASED_DISTROS = [
'opensuse-leap',
]
FLATPAK_BASED_RUNTIMES = [
'org.gnome.Platform',
]
APT_INSTALL_SCRIPT = [
'apt-get update',
'apt-get install %(packages)s'
]
BREW_UNLINK_SCRIPT = [
'brew unlink %(packages)s'
]
BREW_INSTALL_SCRIPT = [
'brew update',
'brew install %(packages)s',
'brew link --force --overwrite %(packages)s'
]
RPM_INSTALL_SCRIPT = [
'dnf update',
'dnf install %(packages)s'
]
PACMAN_INSTALL_SCRIPT = [
'pacman -Sy',
'pacman -S --asdeps --needed %(packages)s'
]
ZYPPER_INSTALL_SCRIPT = [
'zypper update',
'zypper install %(packages)s'
]
ZYPPER_DEPENDENCIES = [
# build system
'autoconf', 'autoconf-archive', 'automake', 'cmake', 'make', 'patch', 'gcc-c++',
'libtool', 'which', 'pandoc','nasm', 'doxygen', 'graphviz',
# contrib dependencies
'curl', 'gzip', 'bzip2',
# daemon
'speexdsp-devel', 'speex-devel', 'libdbus-c++-devel', 'jsoncpp-devel', 'yaml-cpp-devel',
'yasm', 'libuuid-devel', 'libnettle-devel', 'libopus-devel', 'libexpat-devel',
'libgnutls-devel', 'msgpack-devel', 'libavcodec-devel', 'libavdevice-devel', 'pcre-devel',
'alsa-devel', 'libpulse-devel', 'libudev-devel', 'libva-devel', 'libvdpau-devel',
'libopenssl-devel', 'libavutil-devel',
]
ZYPPER_CLIENT_DEPENDENCIES = [
# lrc
'qt6-core-devel', 'qt6-dbus-devel', 'qt6-linguist-devel',
# client-qt
'qt6-svg-devel', 'qt6-multimedia-devel', 'qt6-declarative-devel',
'qt6-quickcontrols2-devel',
'qrencode-devel', 'NetworkManager-devel'
]
ZYPPER_QT_WEBENGINE = [
'qt6-webenginecore-devel',
'qt6-webenginequick-devel',
'qt6-webenginewidgets-devel'
]
DNF_DEPENDENCIES = [
'autoconf', 'autoconf-archive', 'automake', 'cmake', 'make', 'speexdsp-devel', 'pulseaudio-libs-devel',
'libtool', 'dbus-devel', 'expat-devel', 'pcre-devel', 'doxygen', 'graphviz',
'yaml-cpp-devel', 'boost-devel', 'dbus-c++-devel', 'dbus-devel',
'libXext-devel', 'libXfixes-devel', 'yasm',
'speex-devel', 'chrpath', 'check', 'astyle', 'uuid-c++-devel', 'gettext-devel',
'gcc-c++', 'which', 'alsa-lib-devel', 'systemd-devel', 'libuuid-devel',
'uuid-devel', 'gnutls-devel', 'nettle-devel', 'opus-devel', 'speexdsp-devel',
'yaml-cpp-devel', 'swig', 'jsoncpp-devel',
'patch', 'libva-devel', 'openssl-devel', 'libvdpau-devel', 'msgpack-devel',
'sqlite-devel', 'openssl-static', 'pandoc', 'nasm',
'bzip2'
]
DNF_CLIENT_DEPENDENCIES = [
'libnotify-devel',
'qt6-qtbase-devel',
'qt6-qtsvg-devel', 'qt6-qtmultimedia-devel', 'qt6-qtdeclarative-devel',
'qrencode-devel', 'NetworkManager-libnm-devel'
]
DNF_QT_WEBENGINE = [ 'qt6-qtwebengine-devel' ]
APT_DEPENDENCIES = [
'autoconf', 'autoconf-archive', 'autopoint', 'automake', 'cmake', 'make', 'dbus', 'doxygen', 'graphviz',
'g++', 'gettext', 'libasound2-dev', 'libavcodec-dev',
'libavdevice-dev', 'libavformat-dev', 'libboost-dev',
'libcppunit-dev', 'libdbus-1-dev',
'libdbus-c++-dev', 'libebook1.2-dev', 'libexpat1-dev', 'libgnutls28-dev',
'libgtk-3-dev', 'libjack-dev',
'libopus-dev', 'libpcre3-dev', 'libpulse-dev', 'libssl-dev',
'libspeex-dev', 'libspeexdsp-dev', 'libswscale-dev', 'libtool',
'libudev-dev', 'libyaml-cpp-dev', 'sip-tester', 'swig',
'uuid-dev', 'yasm', 'libjsoncpp-dev', 'libva-dev', 'libvdpau-dev', 'libmsgpack-dev',
'pandoc', 'nasm', 'dpkg-dev'
]
APT_CLIENT_DEPENDENCIES = [
'qt6-base-dev', 'qt6-tools-dev', 'qt6-tools-dev-tools',
'qt6-l10n-tools', 'libnotify-dev', 'libqt6sql6-sqlite',
'libqt6core5compat6-dev', 'libqt6networkauth6-dev',
'qt6-multimedia-dev', 'libqt6svg6-dev', 'qt6-declarative-dev',
'qml6-module-qt-labs-qmlmodels',
'qml6-module-qt5compat-graphicaleffects',
'qml6-module-qtqml-workerscript',
'qml6-module-qtmultimedia',
'qml6-module-qtquick', 'qml6-module-qtquick-controls',
'qml6-module-qtquick-dialogs', 'qml6-module-qtquick-layouts',
'qml6-module-qtquick-shapes', 'qml6-module-qtquick-window',
'qml6-module-qtquick-templates', 'qml6-module-qt-labs-platform',
'libqrencode-dev', 'libnm-dev'
]
APT_QT_WEBENGINE = [
'libqt6webengine6-data', 'libqt6webenginecore6-bin',
'qt6-webengine-dev', 'qt6-webengine-dev-tools',
'qml6-module-qtwebengine', 'qml6-module-qtwebchannel' ]
PACMAN_DEPENDENCIES = [
'autoconf', 'autoconf-archive', 'gettext', 'cmake', 'dbus', 'doxygen', 'graphviz',
'gcc', 'ffmpeg', 'boost', 'cppunit', 'libdbus', 'dbus-c++', 'libe-book', 'expat',
'jack', 'opus', 'pcre', 'libpulse', 'speex', 'speexdsp', 'libtool', 'yaml-cpp',
'swig', 'yasm', 'make', 'patch', 'pkg-config',
'automake', 'libva', 'libvdpau', 'openssl', 'pandoc', 'nasm'
]
PACMAN_CLIENT_DEPENDENCIES = [
# lrc
'qt6-base',
# client-qt
'qt6-declarative', 'qt6-5compat', 'qt6-multimedia',
'qt6-networkauth', 'qt6-shadertools',
'qt6-svg', 'qt6-tools',
'qrencode', 'libnm'
]
PACMAN_QT_WEBENGINE = [ 'qt6-webengine' ]
OSX_DEPENDENCIES = [
'autoconf', 'cmake', 'gettext', 'pkg-config', 'qt6',
'libtool', 'yasm', 'nasm', 'automake'
]
OSX_DEPENDENCIES_UNLINK = [
'autoconf*', 'cmake*', 'gettext*', 'pkg-config*', 'qt*', 'qt@6.*',
'libtool*', 'yasm*', 'nasm*', 'automake*', 'gnutls*', 'nettle*', 'msgpack*'
]
UNINSTALL_DAEMON_SCRIPT = [
'make -C daemon uninstall'
]
ASSUME_YES_FLAG = ' -y'
ASSUME_YES_FLAG_PACMAN = ' --noconfirm'
def run_powershell_cmd(cmd):
p = subprocess.Popen(["powershell.exe", cmd], stdout=sys.stdout)
p.communicate()
p.wait()
return
def run_dependencies(args):
if args.distribution == WIN32_DISTRIBUTION_NAME:
run_powershell_cmd(
'Set-ExecutionPolicy Unrestricted; .\\extras\\scripts\\install-deps-windows.ps1')
elif args.distribution in APT_BASED_DISTROS:
if args.assume_yes:
for i, _ in enumerate(APT_INSTALL_SCRIPT):
APT_INSTALL_SCRIPT[i] += ASSUME_YES_FLAG
execute_script(
APT_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, APT_DEPENDENCIES))})
if not args.no_webengine:
APT_CLIENT_DEPENDENCIES.extend(APT_QT_WEBENGINE)
execute_script(
APT_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, APT_CLIENT_DEPENDENCIES))})
elif args.distribution in DNF_BASED_DISTROS:
if args.assume_yes:
for i, _ in enumerate(DNF_INSTALL_SCRIPT):
DNF_INSTALL_SCRIPT[i] += ASSUME_YES_FLAG
execute_script(
RPM_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, DNF_DEPENDENCIES))})
if not args.no_webengine:
DNF_CLIENT_DEPENDENCIES.extend(DNF_QT_WEBENGINE)
execute_script(
RPM_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, DNF_CLIENT_DEPENDENCIES))})
elif args.distribution in PACMAN_BASED_DISTROS:
if args.assume_yes:
for i, _ in enumerate(PACMAN_INSTALL_SCRIPT):
PACMAN_INSTALL_SCRIPT[i] += ASSUME_YES_FLAG_PACMAN
execute_script(
PACMAN_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, PACMAN_DEPENDENCIES))})
if not args.no_webengine:
PACMAN_CLIENT_DEPENDENCIES.extend(PACMAN_QT_WEBENGINE)
execute_script(
PACMAN_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, PACMAN_CLIENT_DEPENDENCIES))})
elif args.distribution in ZYPPER_BASED_DISTROS:
if args.assume_yes:
for i, _ in enumerate(ZYPPER_INSTALL_SCRIPT):
ZYPPER_INSTALL_SCRIPT[i] += ASSUME_YES_FLAG
execute_script(
ZYPPER_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, ZYPPER_DEPENDENCIES))})
if not args.no_webengine:
ZYPPER_CLIENT_DEPENDENCIES.extend(ZYPPER_QT_WEBENGINE)
execute_script(
ZYPPER_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, ZYPPER_CLIENT_DEPENDENCIES))})
elif args.distribution == OSX_DISTRIBUTION_NAME:
execute_script(
BREW_UNLINK_SCRIPT,
{"packages": ' '.join(map(shlex.quote, OSX_DEPENDENCIES_UNLINK))},
False
)
execute_script(
BREW_INSTALL_SCRIPT,
{"packages": ' '.join(map(shlex.quote, OSX_DEPENDENCIES))},
False
)
elif args.distribution == WIN32_DISTRIBUTION_NAME:
print("The win32 version does not install dependencies with this script.\nPlease continue with the --install instruction.")
sys.exit(1)
elif args.distribution == 'guix':
print("Building the profile defined in 'guix/manifest.scm'...")
execute_script(['guix shell --manifest=guix/manifest.scm -- true'])
else:
print("Not yet implemented for current distribution (%s). Please continue with the --install instruction. Note: You may need to install some dependencies manually." %
args.distribution)
sys.exit(1)
def run_init():
# Extract modules path from '.gitmodules' file
module_names = []
with open('.gitmodules') as fd:
for line in fd.readlines():
if line.startswith('[submodule "'):
module_names.append(line[line.find('"')+1:line.rfind('"')])
subprocess.run(["git", "submodule", "update", "--init"], check=True)
subprocess.run(["git", "submodule", "foreach",
"git checkout master && git pull"], check=True)
for name in module_names:
hooks_dir = f'.git/modules/{name}/hooks'
if not os.path.exists(hooks_dir):
os.makedirs(hooks_dir)
copy_file("./extras/scripts/commit-msg", f'{hooks_dir}/commit-msg')
module_names_to_format = ['daemon']
for name in module_names_to_format:
hooks_dir = f'.git/modules/{name}/hooks'
execute_script(['./extras/scripts/format.sh --install %(path)s'],
{"path": hooks_dir})
subprocess.run(["git", "submodule", "update", "--recursive", "--init"],
check=True)
def copy_file(src, dest):
print(f'Copying: {src} to {dest}')
try:
shutil.copy2(src, dest)
# e.g. src and dest are the same file
except shutil.Error as e:
print(f'Error: {e}')
# e.g. source or destination doesn't exist
except IOError as e:
print(f'Error: {e.strerror}')
@contextlib.contextmanager
def cwd(path):
owd = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(owd)
def run_install(args):
# Platforms with special compilation scripts
if args.distribution == WIN32_DISTRIBUTION_NAME:
winmake = 'daemon/compat/msvc/winmake.py'
with cwd(os.path.dirname(winmake)):
execute_script(
f'python {winmake} -iv -t {args.toolset} -s {args.sdk} -b daemon')
build_windows = 'extras/scripts/build-windows.py'
execute_script(f'python {build_windows} init')
execute_script(f'python {build_windows}')
return True
# Unix-like platforms
environ = os.environ.copy()
install_args = ['-p', str(multiprocessing.cpu_count())]
if args.static:
install_args.append('-s')
if args.global_install:
install_args.append('-g')
if args.prefix:
install_args += ('-P', args.prefix)
if not args.priv_install:
install_args.append('-u')
if args.debug:
install_args.append('-d')
if args.no_libwrap:
install_args.append('-W')
if args.no_webengine:
install_args.append('-w')
if args.distribution == OSX_DISTRIBUTION_NAME:
# The `universal_newlines` parameter has been renamed to `text` in
# Python 3.7+ and triggering automatical binary to text conversion is
# what it actually does
proc = subprocess.run(["brew", "--prefix", "qt6"],
stdout=subprocess.PIPE, check=True,
universal_newlines=True)
environ['CMAKE_PREFIX_PATH'] = proc.stdout.rstrip("\n")
environ['CONFIGURE_FLAGS'] = '--without-dbus'
if not args.qt:
raise Exception('provide the Qt path using --qt=/qt/install/prefix')
install_args += ("-Q", args.qt)
else:
if args.distribution in ZYPPER_BASED_DISTROS:
# fix jsoncpp pkg-config bug, remove when jsoncpp package bumped
environ['JSONCPP_LIBS'] = "-ljsoncpp"
if args.qt:
install_args += ("-Q", args.qt)
command = ['extras/scripts/install.sh'] + install_args
if args.distribution == 'guix':
if args.global_install:
print('error: global install is not supported when using Guix.')
sys.exit(1)
# Run the build in an isolated container.
share_tarballs_args = []
if 'TARBALLS' in os.environ:
share_tarballs_args = ['--preserve=TARBALLS',
f'--share={os.environ["TARBALLS"]}']
else:
print('info: consider setting the TARBALLS environment variable '
'to a stable writable location to avoid loosing '
'cached tarballs')
# Note: we must expose /gnu/store because /etc/ssl/certs
# contains certs that are symlinks to store items.
command = ['guix', 'shell', '--manifest=guix/manifest.scm',
'--expose=/gnu/store', '--expose=/etc/ssl/certs',
'--expose=/usr/bin/env',
'--container', '--network'] + share_tarballs_args \
+ ['--'] + command
print(f'info: Building/installing using the command: {" ".join(command)}')
return subprocess.run(command, env=environ, check=True)
def run_uninstall(args):
execute_script(UNINSTALL_DAEMON_SCRIPT)
BUILD_DIR = 'build-global' if args.global_install else 'build'
if (os.path.exists(BUILD_DIR)):
UNINSTALL_CLIENT_SCRIPT = [
f'make -C {BUILD_DIR} uninstall',
f'rm -rf {BUILD_DIR}'
]
execute_script(UNINSTALL_CLIENT_SCRIPT)
def run_clean():
execute_script(['git clean -xfd',
'git submodule foreach git clean -xfd'])
def run_run(args):
run_env = os.environ
try:
if args.no_libwrap:
jamid_log = open("daemon.log", 'a')
jamid_log.write('=== Starting daemon (%s) ===' %
time.strftime("%d/%m/%Y %H:%M:%S"))
jamid_process = subprocess.Popen(
["./install/libexec/jamid", "-c", "-d"],
stdout=jamid_log,
stderr=jamid_log)
with open('daemon.pid', 'w') as f:
f.write(str(jamid_process.pid)+'\n')
client_log = open('jami.log', 'a')
client_log.write('=== Starting client (%s) ===' %
time.strftime("%d/%m/%Y %H:%M:%S"))
client_process = subprocess.Popen(["./install/bin/jami", "-d"],
stdout=client_log,
stderr=client_log,
env=run_env)
with open('jami.pid', 'w') as f:
f.write(str(client_process.pid)+'\n')
if args.debug and args.no_libwrap:
subprocess.call(['gdb', './install/libexec/jamid'])
if not args.background:
if args.no_libwrap:
jamid_process.wait()
client_process.wait()
except KeyboardInterrupt:
print("\nCaught KeyboardInterrupt...")
finally:
if args.background == False:
try:
# Only kill the processes if they are running, as they
# could have been closed by the user.
print("Killing processes...")
if args.no_libwrap:
jamid_log.close()
if jamid_process.poll() is None:
jamid_process.kill()
client_log.close()
if client_process.poll() is None:
client_process.kill()
except UnboundLocalError:
# Its okay! We crashed before we could start a process
# or open a file. All that matters is that we close
# files and kill processes in the right order.
pass
return True
def run_stop(args):
STOP_SCRIPT = ['xargs kill < jami.pid',
'xargs kill < daemon.pid']
execute_script(STOP_SCRIPT)
def execute_script(script, settings=None, fail=True):
if settings is None:
settings = {}
for line in script:
line = line % settings
rv = os.system(line)
if rv and fail:
print('Error executing script! Exit code: %s' %
rv, file=sys.stderr)
sys.exit(1)
def has_guix():
"""Check whether the 'guix' command is available."""
with open(os.devnull, 'w') as f:
try:
subprocess.run(["sh", "-c", "command -v guix"],
check=True, stdout=f)
except subprocess.CalledProcessError:
return False
else:
return True
def validate_args(parsed_args):
"""Validate the args values, exit if error is found"""
# Filter unsupported distributions.
supported_distros = \
[ OSX_DISTRIBUTION_NAME, WIN32_DISTRIBUTION_NAME, 'guix'] + \
APT_BASED_DISTROS + DNF_BASED_DISTROS + PACMAN_BASED_DISTROS \
+ ZYPPER_BASED_DISTROS + FLATPAK_BASED_RUNTIMES
if (parsed_args.distribution == 'no-check'
or 'JAMI_BUILD_NO_CHECK' in os.environ):
return
if parsed_args.distribution not in supported_distros:
print(f'WARNING: Distribution \'{parsed_args.distribution}\' is not '
f'supported. Choose one of: {", ".join(supported_distros)}. '
'Alternatively, you may force execution of this script '
'by providing the \'--distribution=no-check\' argument or by '
'exporting the JAMI_BUILD_NO_CHECK environment variable.',
file=sys.stderr)
sys.exit(1)
# On Windows, version 10 or later is needed to build Jami.
if parsed_args.distribution == WIN32_DISTRIBUTION_NAME:
if hasattr(sys, 'getwindowsversion') and sys.getwindowsversion()[0] < 10:
print('Windows 10 or later is needed to build Jami')
sys.exit(1)
def parse_args():
ap = argparse.ArgumentParser(description="Jami build tool")
ga = ap.add_mutually_exclusive_group(required=True)
ga.add_argument(
'--init', action='store_true',
help='Init Jami repository')
ga.add_argument(
'--dependencies', action='store_true',
help='Install Jami build dependencies')
ga.add_argument(
'--install', action='store_true',
help='Build and install Jami')
ga.add_argument(
'--clean', action='store_true',
help='Call "git clean" on every repository of the project'
)
ga.add_argument(
'--uninstall', action='store_true',
help='Uninstall Jami')
ga.add_argument(
'--run', action='store_true',
help='Run the Jami daemon and client')
ga.add_argument(
'--stop', action='store_true',
help='Stop the Jami processes')
ap.add_argument('--distribution')
ap.add_argument('--prefix')
ap.add_argument('--static', default=False, action='store_true')
ap.add_argument('--global-install', default=False, action='store_true')
ap.add_argument('--debug', default=False, action='store_true',
help='Build with debug support; run in GDB')
ap.add_argument('--background', default=False, action='store_true')
ap.add_argument('--no-priv-install', dest='priv_install',
default=True, action='store_false')
ap.add_argument('--qt', type=str,
help='Use the Qt path supplied')
ap.add_argument('--no-libwrap', dest='no_libwrap',
default=False, action='store_true',
help='Disable libwrap. Also set --disable-shared option to daemon configure')
ap.add_argument('-y', '--assume-yes', default=False, action='store_true',
help='Assume yes (do not prompt user) for dependency installations through the system package manager')
ap.add_argument('--no-webengine', dest='no_webengine',
default=False, action='store_true',
help='Do not use Qt WebEngine.')
dist = choose_distribution()
if dist == WIN32_DISTRIBUTION_NAME:
ap.add_argument('--toolset', default=win_toolset_default, type=str,
help='Windows use only, specify Visual Studio toolset version')
ap.add_argument('--sdk', default=win_sdk_default, type=str,
help='Windows use only, specify Windows SDK version')
parsed_args = ap.parse_args()
if parsed_args.distribution:
parsed_args.distribution = parsed_args.distribution.lower()
else:
parsed_args.distribution = dist
validate_args(parsed_args)
return parsed_args
def choose_distribution():
system = platform.system().lower()
if system == "linux" or system == "linux2":
if os.path.isfile("/etc/arch-release"):
return "arch"
try:
with open("/etc/os-release") as f:
for line in f:
k, v = line.split("=")
if k.strip() == 'ID':
return v.strip().replace('"', '').split(' ')[0]
except FileNotFoundError:
if has_guix():
return 'guix'
return 'Unknown'
elif system == "darwin":
return OSX_DISTRIBUTION_NAME
elif system == "windows":
return WIN32_DISTRIBUTION_NAME
return 'Unknown'
def main():
parsed_args = parse_args()
if parsed_args.dependencies:
run_dependencies(parsed_args)
elif parsed_args.init:
run_init()
elif parsed_args.clean:
run_clean()
elif parsed_args.install:
run_install(parsed_args)
elif parsed_args.uninstall:
run_uninstall(parsed_args)
elif parsed_args.run:
if (parsed_args.distribution == 'guix'
and 'GUIX_ENVIRONMENT' not in os.environ):
# Relaunch this script, this time in a pure Guix environment.
guix_args = ['shell', '--pure',
# to allow pulseaudio to connect to an existing server
"-E", "XAUTHORITY", "-E", "XDG_RUNTIME_DIR",
'--manifest=guix/manifest.scm', '--']
args = sys.argv + ['--distribution=guix']
print('Running in a guix shell spawned with: guix {}'
.format(str.join(' ', guix_args + args)))
os.execlp('guix', 'guix', *(guix_args + args))
else:
run_run(parsed_args)
elif parsed_args.stop:
run_stop(parsed_args)
if __name__ == "__main__":
main()

181
extras/scripts/commit-msg Executable file
View file

@ -0,0 +1,181 @@
#!/bin/sh
# From Gerrit Code Review 2.11.3
#
# Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
#
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unset GREP_OPTIONS
CHANGE_ID_AFTER="Bug|Issue"
MSG="$1"
# Check for, and add if missing, a unique Change-Id
#
add_ChangeId() {
clean_message=`sed -e '
/^diff --git .*/{
s///
q
}
/^Signed-off-by:/d
/^#/d
' "$MSG" | git stripspace`
if test -z "$clean_message"
then
return
fi
if test "false" = "`git config --bool --get gerrit.createChangeId`"
then
return
fi
# Does Change-Id: already exist? if so, exit (no change).
if grep -i '^Change-Id:' "$MSG" >/dev/null
then
return
fi
id=`_gen_ChangeId`
T="$MSG.tmp.$$"
AWK=awk
if [ -x /usr/xpg4/bin/awk ]; then
# Solaris AWK is just too broken
AWK=/usr/xpg4/bin/awk
fi
# How this works:
# - parse the commit message as (textLine+ blankLine*)*
# - assume textLine+ to be a footer until proven otherwise
# - exception: the first block is not footer (as it is the title)
# - read textLine+ into a variable
# - then count blankLines
# - once the next textLine appears, print textLine+ blankLine* as these
# aren't footer
# - in END, the last textLine+ block is available for footer parsing
$AWK '
BEGIN {
# while we start with the assumption that textLine+
# is a footer, the first block is not.
isFooter = 0
footerComment = 0
blankLines = 0
}
# Skip lines starting with "#" without any spaces before it.
/^#/ { next }
# Skip the line starting with the diff command and everything after it,
# up to the end of the file, assuming it is only patch data.
# If more than one line before the diff was empty, strip all but one.
/^diff --git / {
blankLines = 0
while (getline) { }
next
}
# Count blank lines outside footer comments
/^$/ && (footerComment == 0) {
blankLines++
next
}
# Catch footer comment
/^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) {
footerComment = 1
}
/]$/ && (footerComment == 1) {
footerComment = 2
}
# We have a non-blank line after blank lines. Handle this.
(blankLines > 0) {
print lines
for (i = 0; i < blankLines; i++) {
print ""
}
lines = ""
blankLines = 0
isFooter = 1
footerComment = 0
}
# Detect that the current block is not the footer
(footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) {
isFooter = 0
}
{
# We need this information about the current last comment line
if (footerComment == 2) {
footerComment = 0
}
if (lines != "") {
lines = lines "\n";
}
lines = lines $0
}
# Footer handling:
# If the last block is considered a footer, splice in the Change-Id at the
# right place.
# Look for the right place to inject Change-Id by considering
# CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first,
# then Change-Id, then everything else (eg. Signed-off-by:).
#
# Otherwise just print the last block, a new line and the Change-Id as a
# block of its own.
END {
unprinted = 1
if (isFooter == 0) {
print lines "\n"
lines = ""
}
changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):"
numlines = split(lines, footer, "\n")
for (line = 1; line <= numlines; line++) {
if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) {
unprinted = 0
print "Change-Id: I'"$id"'"
}
print footer[line]
}
if (unprinted) {
print "Change-Id: I'"$id"'"
}
}' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T"
}
_gen_ChangeIdInput() {
echo "tree `git write-tree`"
if parent=`git rev-parse "HEAD^0" 2>/dev/null`
then
echo "parent $parent"
fi
echo "author `git var GIT_AUTHOR_IDENT`"
echo "committer `git var GIT_COMMITTER_IDENT`"
echo
printf '%s' "$clean_message"
}
_gen_ChangeId() {
_gen_ChangeIdInput |
git hash-object -t commit --stdin
}
add_ChangeId

103
extras/scripts/format.sh Executable file
View file

@ -0,0 +1,103 @@
#!/usr/bin/env bash
# format.sh --- set up clang-format for source files
# Copyright (C) 2020-2022 Savoir-faire Linux Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
set -e
command_exists ()
{
type "$1" &> /dev/null ;
}
CFVERSION="9"
CLANGFORMAT=""
if command_exists clang-format-${CFVERSION}; then
CLANGFORMAT=clang-format-${CFVERSION}
else
if command_exists clang-format; then
CLANGFORMAT=clang-format
fi
fi
if ! command -v $CLANGFORMAT &> /dev/null; then
echo "Required version of clang-format not found"
exit 1
fi
format_file()
{
if [ -f "${1}" ]; then
$CLANGFORMAT -i -style=file "${1}" || true
fi
}
format_files()
{
for file in $1; do
echo -ne "Formatting: ${file}\\033[0K\\r"
format_file "${file}"
done
}
exit_if_no_files()
{
echo No files to format
exit 0
}
install_hook()
{
hooks_path=$1
if [ ! -d "$hooks_path" ]; then
echo "$hooks_path" path does not exist
exit 1
fi
echo Installing pre-commit hook in "$hooks_path"
echo "$(realpath $0)" > "$hooks_path"/pre-commit
chmod +x "$hooks_path"/pre-commit
}
display_help()
{
echo "Usage: $0 [OPTION...] -- Clang format source files with a .clang-format file" >&2
echo
echo " --all format all files instead of only committed ones"
echo " --install <path> install a pre-commit hook to run this script"
echo
}
if [ "$1" == "--help" ]; then
display_help
exit 0
fi
case "${1}" in
--all )
files=$(find src -regex '.*\.\(cpp\|hpp\|cc\|cxx\|h\)$') || true
echo Formatting all source files...
format_files "$files"
;;
--install )
install_hook "${2}"
;;
* )
files=$(git diff-index --cached --name-only HEAD | grep -iE '\.(cpp|cxx|cc|h|hpp)$') || exit_if_no_files
echo Formatting committed source files...
format_files "$files"
;;
esac

View file

@ -0,0 +1,236 @@
# Copyright (C) 2019-2022 Savoir-faire Linux Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
<#
This script should install dependencies required for building the Jami
Qt client on windows.
Required components not installed:
- Visual Studio
- build toolchains
- SDKs
- WiX + WiX Visual Studio extension
- Qt + Qt Visual Studio extension
#>
write-host "Installing jami-qt build dependencies for windows…" -ForegroundColor Green
Set-ExecutionPolicy Bypass -Scope Process -Force
$global:installed_packages = $null
Function choco_check_package([String] $package, [String] $version = "") {
# Query a package listing once
if ($null -eq $global:installed_packages) {
write-host "Getting installed package list from Chocolatey…" -ForegroundColor DarkCyan
$global:installed_packages = choco list -lo
}
# Check installed packages
$result = $global:installed_packages | Where-object {
$_.ToLower().StartsWith($package.ToLower())
}
if ($null -eq $result) {
# We don't have the package
write-host $package "not found." -ForegroundColor Yellow
return $false
}
if ("" -eq $version) {
# We have the package and don't care what version it is
write-host $package "found." -ForegroundColor Cyan
return $true
}
# We now check the results for a package of the specified version
$parts = $result.Split(' ')
Foreach ($part in $parts) {
if ($part -eq $version) {
# We have the package of the specified version
write-host $package $version "found." -ForegroundColor Cyan
return $true
}
}
# We don't have the package of the specified version
write-host $package $version "not found." -ForegroundColor Yellow
return $false
}
Function install_chocolatey {
# Install Chocolatey if not installed already
if (!(Test-Path "$($env:ProgramData)\chocolatey\choco.exe")) {
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString("https://chocolatey.org/install.ps1"))
if ( $LASTEXITCODE -eq 0 ) {
write-host "Chocolatey installation succeeded" -ForegroundColor Green
}
else {
write-host "Chocolatey installation failed" -ForegroundColor Red
exit $LASTEXITCODE
}
}
else {
write-host "Chocolatey already installed" -ForegroundColor DarkGreen
}
}
Function choco_install_package([String] $package, [String] $version = "") {
$package_installed = choco_check_package $package $version
if ($true -eq $package_installed) {
return
}
if ("" -ne $version) {
write-host "Installing" $package "@" $version
choco install -fy --allow-downgrade $package --version $version --acceptlicense
}
else {
write-host "Installing" $package
choco install -fy --allow-downgrade $package --acceptlicense
}
if ( $LASTEXITCODE -ne 0 ) {
write-host "Choco Packages Installation Failed" -ForegroundColor Red
exit 1
}
}
Function install_choco_packages($packages) {
Foreach ($i in $packages) {
choco_install_package $i.pkg $i.ver
}
write-host "Choco Packages Installation Succeeded" -ForegroundColor Green
}
Function download_file_to_temp($download_name, $url, $output_name) {
write-host "Downloading $download_name" -ForegroundColor DarkCyan
$output = $env:TEMP + "\$output_name"
(New-Object System.Net.WebClient).DownloadFile($url, $output)
if ( $LASTEXITCODE -eq 0 ) {
write-host "Download $download_name Succeeded" -ForegroundColor Green
}
else {
write-host "Download $download_name Failed" -ForegroundColor Red
exit $LASTEXITCODE
}
}
Function unzip_file_from_temp($unzip_name, $zip_file_name, $unzip_file_output_name) {
write-host "Unzipping $unzip_name" -ForegroundColor DarkCyan
$zip_path = $env:TEMP + "\$zip_file_name"
$unzip_path = $env:TEMP + "\$unzip_file_output_name"
Invoke-Expression("unzip -o $zip_path -d '$unzip_path'") | Out-Null
if ( $LASTEXITCODE -eq 0 ) {
write-host "Unzip $unzip_name Succeeded" -ForegroundColor Green
}
else {
write-host "Unzip $unzip_name Failed" -ForegroundColor Red
exit $LASTEXITCODE
}
}
Function run_batch($batch_cmd, $task_name) {
write-host $task_name -ForegroundColor DarkCyan
Start-Process "cmd.exe" $batch_cmd -Wait -NoNewWindow | Out-Null
if ( $LASTEXITCODE -eq 0 ) {
write-host "$task_name Succeeded" -ForegroundColor Green
}
else {
write-host "$task_name Failed" -ForegroundColor Red
exit $LASTEXITCODE
}
}
Function move_file_from_temp_to_msys64($file_name, $task_name) {
write-host $task_name -ForegroundColor DarkCyan
$file_path = $env:TEMP + "\$file_name"
Move-item -Path $file_path -Destination $msys2_path -Force
if ($LASTEXITCODE -eq 0) {
write-host "$task_name Succeeded" -ForegroundColor Green
}
else {
write-host "$task_name Failed" -ForegroundColor Red
exit $LASTEXITCODE
}
}
Function install_msys2_packages($packages) {
Foreach ($i in $packages) {
Invoke-Expression ("pacman -Q '$i'") | out-null
if ($LASTEXITCODE -eq 0) {
write-host $i "already installed" -ForegroundColor Cyan
continue
}
Invoke-Expression ("pacman -S '$i' --noconfirm")
if ($LASTEXITCODE -ne 0) {
write-host "Pacman Packages Installation Failed" -ForegroundColor Red
exit 1
}
}
write-host "Pacman Packages Installation Succeeded" -ForegroundColor Green
}
# Web installed msys2_64 bit to install make, gcc, perl, diffutils
$msys_packages = @("make", "gcc", "perl", "diffutils")
# Install 7zip, unzip, wget --version 1.19.4, cmake, git --version 2.10.2, pandoc, strawberryperl, msys2
$choco_packages = @(
[pscustomobject]@{pkg = "wget"; ver = "1.19.4" }
[pscustomobject]@{pkg = "git.install"; ver = "2.10.2" }
[pscustomobject]@{pkg = "7zip"; ver = "" }
[pscustomobject]@{pkg = "unzip"; ver = "" }
[pscustomobject]@{pkg = "cmake"; ver = "" }
[pscustomobject]@{pkg = "pandoc"; ver = "" }
[pscustomobject]@{pkg = "strawberryperl"; ver = "" }
[pscustomobject]@{pkg = "msys2"; ver = "" }
)
install_chocolatey
# Check for an existing msys2 install
# Note that choco installs msys2 in C:/tools/
if (!(Test-Path -Path "C:\msys64")) {
$Env:Path += ";C:\tools\msys64\usr\bin"
$msys2_path = "C:\tools\msys64\usr\bin"
if ((Test-Path -Path "C:\tools\msys64")) {
write-host "MSYS2 64 already installed" -ForegroundColor Green
}
else {
$choco_packages.Add([pscustomobject]@{pkg = "msys2"; ver = "" })
}
}
else {
write-host "MSYS2 64 already installed" -ForegroundColor Green
$Env:Path += ";C:\msys64\usr\bin"
$msys2_path = "C:\msys64\usr\bin"
}
install_choco_packages $choco_packages
install_msys2_packages $msys_packages
# Install VSNASM
download_file_to_temp 'VSNASM' "https://github.com/ShiftMediaProject/VSNASM/releases/download/0.5/VSNASM.zip" 'VSNASM.zip'
unzip_file_from_temp 'VSNASM' 'VSNASM.zip' 'VSNASM_UNZIP'
$batch_path = "/c set ISINSTANCE=1 &&" + $env:TEMP + "\VSNASM_UNZIP\install_script.bat"
run_batch $batch_path "Install VSNASM"
# Install VSYASM
download_file_to_temp 'VSYASM' "https://github.com/ShiftMediaProject/VSYASM/releases/download/0.4/VSYASM.zip" 'VSYASM.zip'
unzip_file_from_temp 'VSYASM' 'VSYASM.zip' 'VSYASM_UNZIP'
$batch_path = "/c set ISINSTANCE=1 &&" + $env:TEMP + "\VSYASM_UNZIP\install_script.bat"
run_batch $batch_path "Install VSYASM"
# Install yasm.exe (win64)
download_file_to_temp 'yasm.exe (win64)' "http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe" 'yasm.exe'
move_file_from_temp_to_msys64 'yasm.exe' 'Move yasm.exe (win64) to msys64 folder'
# Install gas-preprocessor.pl
download_file_to_temp 'gas-preprocessor.pl' "https://github.com/FFmpeg/gas-preprocessor/blob/master/gas-preprocessor.pl" 'gas-preprocessor.pl'
move_file_from_temp_to_msys64 'gas-preprocessor.pl' 'Move gas-preprocessor.pl to msys64 folder'
write-host "Done" -ForegroundColor Green

187
extras/scripts/install.sh Executable file
View file

@ -0,0 +1,187 @@
#!/usr/bin/env bash
# install.sh --- build and install Jami daemon and client
# Copyright (C) 2016-2022 Savoir-faire Linux Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# Build and install to a local prefix under this repository.
export OSTYPE
# Flags:
# -g: install globally instead for all users
# -s: link everything statically, no D-Bus communication. More likely to work!
# -p: number of processors to use
# -u: disable use of privileges (sudo) during install
# -W: disable libwrap and shared library
# -w: do not use Qt WebEngine
set -ex
# Qt_MIN_VER required for client-qt
QT_MIN_VER="6.2"
debug=
global=false
static=''
qtpath=''
proc='1'
priv_install=true
enable_libwrap=true
enable_webengine=true
while getopts gsc:dQ:P:p:uWw OPT; do
case "$OPT" in
g)
global='true'
;;
s)
static='-DENABLE_STATIC=true'
;;
d)
debug=true
;;
Q)
qtpath="${OPTARG}"
;;
P)
prefix="${OPTARG}"
;;
p)
proc="${OPTARG}"
;;
u)
priv_install='false'
;;
W)
enable_libwrap='false'
;;
w)
enable_webengine='false'
;;
\?)
exit 1
;;
esac
done
# $1: global-install?
# $2: private-install?
make_install() {
if [ "$1" = "true" ] && [ "$2" != "false" ]; then
sudo make install
# Or else the next non-sudo install will fail, because this generates some
# root owned files like install_manifest.txt under the build directory.
sudo chown -R "$USER" .
else
make install
fi
}
TOP="$(pwd)"
INSTALL_DIR="${TOP}/install" # local install directory
if [ "${global}" = "true" ]; then
BUILD_DIR="build-global"
else
BUILD_DIR="build"
fi
# jamid
DAEMON="${TOP}/daemon"
cd "$DAEMON"
# Build the contribs.
mkdir -p contrib/native
(
cd contrib/native
../bootstrap ${prefix:+"--prefix=$prefix"}
make -j"${proc}"
)
if [[ "${enable_libwrap}" != "true" ]]; then
# Disable shared if requested
if [[ "$OSTYPE" != "darwin"* ]]; then
CONFIGURE_FLAGS+=" --disable-shared"
fi
fi
BUILD_TYPE="Release"
if [ "${debug}" = "true" ]; then
BUILD_TYPE="Debug"
CONFIGURE_FLAGS+=" --enable-debug"
fi
# Build the daemon itself.
test -f configure || ./autogen.sh
if [ "${global}" = "true" ]; then
./configure ${CONFIGURE_FLAGS} ${prefix:+"--prefix=$prefix"}
else
./configure ${CONFIGURE_FLAGS} --prefix="${INSTALL_DIR}"
fi
make -j"${proc}" V=1
make_install "${global}" "${priv_install}"
# Verify system's version if no path provided.
if [ -z "$qtpath" ]; then
sys_qtver=""
if command -v qmake6 &> /dev/null; then
sys_qtver=$(qmake6 -v)
elif command -v qmake-qt6 &> /dev/null; then
sys_qtver=$(qmake-qt6 -v) # Fedora
elif command -v qmake &> /dev/null; then
sys_qtver=$(qmake -v)
else
echo "No valid Qt found"; exit 1;
fi
sys_qtver=${sys_qtver#*Qt version}
sys_qtver=${sys_qtver%\ in\ *}
installed_qtver=$(echo "$sys_qtver" | cut -d'.' -f 2)
required_qtver=$(echo $QT_MIN_VER | cut -d'.' -f 2)
if [[ $installed_qtver -ge $required_qtver ]] ; then
# Set qtpath to empty in order to use system's Qt.
qtpath=""
else
echo "No valid Qt found"; exit 1;
fi
fi
# client
cd "${TOP}"
mkdir -p "${BUILD_DIR}"
cd "${BUILD_DIR}"
client_cmake_flags=(-DCMAKE_BUILD_TYPE="${BUILD_TYPE}"
-DCMAKE_PREFIX_PATH="${qtpath}"
-DENABLE_LIBWRAP="${enable_libwrap}"
-DWITH_WEBENGINE="${enable_webengine}")
if [ "${global}" = "true" ]; then
client_cmake_flags+=(${prefix:+"-DCMAKE_INSTALL_PREFIX=$prefix"}
$static)
else
client_cmake_flags+=(-DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}"
-DLIBJAMI_BUILD_DIR="${DAEMON}/src")
fi
echo "info: Configuring $client client with flags: ${client_cmake_flags[*]}"
cmake .. "${client_cmake_flags[@]}"
make -j"${proc}" V=1
make_install "${global}" "${priv_install}"