import sys;
import os;
import inspect;
import shutil;
from invoke import task;
MEDIASOUP_BUILDTYPE = os.getenv('MEDIASOUP_BUILDTYPE') or 'Release';
WORKER_DIR = os.path.dirname(os.path.abspath(
inspect.getframeinfo(inspect.currentframe()).filename
));
MEDIASOUP_OUT_DIR = os.getenv('MEDIASOUP_OUT_DIR') or f'{WORKER_DIR}/out';
MEDIASOUP_INSTALL_DIR = os.getenv('MEDIASOUP_INSTALL_DIR') or f'{MEDIASOUP_OUT_DIR}/{MEDIASOUP_BUILDTYPE}';
BUILD_DIR = os.getenv('BUILD_DIR') or f'{MEDIASOUP_INSTALL_DIR}/build';
PIP_INVOKE_DIR = f'{MEDIASOUP_OUT_DIR}/pip_invoke';
PIP_MESON_NINJA_DIR = f'{MEDIASOUP_OUT_DIR}/pip_meson_ninja';
PIP_PYLINT_DIR = f'{MEDIASOUP_OUT_DIR}/pip_pylint';
NUM_CORES = len(os.sched_getaffinity(0)) if hasattr(os, 'sched_getaffinity') else os.cpu_count();
PYTHON = os.getenv('PYTHON') or sys.executable;
MESON = os.getenv('MESON') or f'{PIP_MESON_NINJA_DIR}/bin/meson';
MESON_VERSION = os.getenv('MESON_VERSION') or '1.3.0';
MESON_ARGS = os.getenv('MESON_ARGS') if os.getenv('MESON_ARGS') else '--vsenv' if os.name == 'nt' else '';
NINJA_VERSION = os.getenv('NINJA_VERSION') or '1.10.2.4';
PYLINT_VERSION = os.getenv('PYLINT_VERSION') or '3.0.2';
NPM = os.getenv('NPM') or 'npm';
LCOV = f'{WORKER_DIR}/deps/lcov/bin/lcov';
DOCKER = os.getenv('DOCKER') or 'docker';
PTY_SUPPORTED = sys.stdout.isatty();
SHELL = '/bin/sh' if not os.name == 'nt' else None;
os.environ['PYTHONDONTWRITEBYTECODE'] = 'true';
if os.name == 'nt':
os.environ['NINJA'] = f'{PIP_MESON_NINJA_DIR}/bin/ninja.exe';
else:
os.environ['NINJA'] = f'{PIP_MESON_NINJA_DIR}/bin/ninja';
PYTHONPATH = os.getenv('PYTHONPATH') or '';
if os.name == 'nt':
os.environ['PYTHONPATH'] = f'{PIP_INVOKE_DIR};{PIP_MESON_NINJA_DIR};{PIP_PYLINT_DIR};{PYTHONPATH}';
else:
os.environ['PYTHONPATH'] = f'{PIP_INVOKE_DIR}:{PIP_MESON_NINJA_DIR}:{PIP_PYLINT_DIR}:{PYTHONPATH}';
@task
def meson_ninja(ctx):
if os.path.isfile(MESON):
return;
try:
ctx.run(
f'"{PYTHON}" -m pip install --system --upgrade --target="{PIP_MESON_NINJA_DIR}" pip setuptools',
echo=True,
hide=True,
shell=SHELL
);
except:
ctx.run(
f'"{PYTHON}" -m pip install --upgrade --target="{PIP_MESON_NINJA_DIR}" pip setuptools',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
pip_build_binaries = '--no-binary :all:' if os.path.isfile('/etc/NIXOS') or os.path.isdir('/etc/guix') else '';
ctx.run(
f'"{PYTHON}" -m pip install --upgrade --target="{PIP_MESON_NINJA_DIR}" {pip_build_binaries} meson=={MESON_VERSION} ninja=={NINJA_VERSION}',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task(pre=[meson_ninja])
def setup(ctx):
if MEDIASOUP_BUILDTYPE == 'Release':
try:
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
except:
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype release -Db_ndebug=true -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
elif MEDIASOUP_BUILDTYPE == 'Debug':
try:
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
except:
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype debug -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
else:
try:
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release -Db_pie=true -Db_staticpic=true --reconfigure {MESON_ARGS} "{BUILD_DIR}"',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
except:
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" setup --prefix "{MEDIASOUP_INSTALL_DIR}" --bindir "" --libdir "" --buildtype {MEDIASOUP_BUILDTYPE} -Db_ndebug=if-release -Db_pie=true -Db_staticpic=true {MESON_ARGS} "{BUILD_DIR}"',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def clean(ctx):
try:
shutil.rmtree(MEDIASOUP_INSTALL_DIR);
except:
pass;
@task
def clean_build(ctx):
try:
shutil.rmtree(BUILD_DIR);
except:
pass;
@task
def clean_pip(ctx):
try:
shutil.rmtree(PIP_MESON_NINJA_DIR);
except:
pass;
try:
shutil.rmtree(PIP_PYLINT_DIR);
except:
pass;
@task(pre=[meson_ninja])
def clean_subprojects(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" subprojects purge --include-cache --confirm',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def clean_all(ctx):
with ctx.cd(WORKER_DIR):
try:
ctx.run(
f'"{MESON}" subprojects purge --include-cache --confirm',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
except:
pass;
try:
shutil.rmtree(MEDIASOUP_OUT_DIR);
except:
pass;
@task(pre=[meson_ninja])
def update_wrap_file(ctx, subproject):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" subprojects update --reset {subproject}',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task(pre=[setup])
def flatc(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" compile -C "{BUILD_DIR}" flatbuffers-generator',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task(pre=[setup, flatc], default=True)
def mediasoup_worker(ctx):
if os.getenv('MEDIASOUP_WORKER_BIN'):
print('skipping mediasoup-worker compilation due to the existence of the MEDIASOUP_WORKER_BIN environment variable');
return;
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task(pre=[setup, flatc])
def libmediasoup_worker(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} libmediasoup-worker',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags libmediasoup-worker',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task(pre=[setup, flatc])
def xcode(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" setup --buildtype {MEDIASOUP_BUILDTYPE} --backend xcode "{MEDIASOUP_OUT_DIR}/xcode"',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def lint(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{NPM}" run lint --prefix scripts/',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
if not os.path.isdir(PIP_PYLINT_DIR):
ctx.run(
f'"{PYTHON}" -m pip install --upgrade --target="{PIP_PYLINT_DIR}" pylint=={PYLINT_VERSION}',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{PYTHON}" -m pylint tasks.py',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def format(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{NPM}" run format --prefix scripts/',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task(pre=[setup, flatc])
def test(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or '';
if os.name == 'nt':
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{BUILD_DIR}/mediasoup-worker-test.exe" --invisibles --use-colour=yes {mediasoup_test_tags}',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
else:
ctx.run(
f'"{LCOV}" --directory "{WORKER_DIR}" --zerocounters',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{BUILD_DIR}/mediasoup-worker-test" --invisibles --use-colour=yes {mediasoup_test_tags}',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task(pre=[setup, flatc])
def test_asan(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-test-asan',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-test-asan',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
mediasoup_test_tags = os.getenv('MEDIASOUP_TEST_TAGS') or '';
with ctx.cd(WORKER_DIR):
ctx.run(
f'ASAN_OPTIONS=detect_leaks=1 "{BUILD_DIR}/mediasoup-worker-test-asan" --invisibles --use-colour=yes {mediasoup_test_tags}',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def tidy(ctx):
mediasoup_tidy_checks = os.getenv('MEDIASOUP_TIDY_CHECKS') or '';
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{PYTHON}" ./scripts/clang-tidy.py -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy -clang-apply-replacements-binary=./scripts/node_modules/.bin/clang-apply-replacements -header-filter="(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)" -p="{BUILD_DIR}" -j={NUM_CORES} -checks={mediasoup_tidy_checks} -quiet',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task(pre=[setup, flatc])
def fuzzer(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" compile -C "{BUILD_DIR}" -j {NUM_CORES} mediasoup-worker-fuzzer',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{MESON}" install -C "{BUILD_DIR}" --no-rebuild --tags mediasoup-worker-fuzzer',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def fuzzer_run_all(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'LSAN_OPTIONS=verbosity=1:log_threads=1 "{BUILD_DIR}/mediasoup-worker-fuzzer" -artifact_prefix=fuzzer/reports/ -max_len=1400 fuzzer/new-corpus deps/webrtc-fuzzer-corpora/corpora/stun-corpus deps/webrtc-fuzzer-corpora/corpora/rtp-corpus deps/webrtc-fuzzer-corpora/corpora/rtcp-corpus',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def docker(ctx):
if os.getenv('DOCKER_NO_CACHE') == 'true':
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{DOCKER}" build -f Dockerfile --no-cache --tag mediasoup/docker:latest .',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
else:
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{DOCKER}" build -f Dockerfile --tag mediasoup/docker:latest .',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def docker_run(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{DOCKER}" run --name=mediasoupDocker -it --rm --privileged --cap-add SYS_PTRACE -v "{WORKER_DIR}/../:/mediasoup" mediasoup/docker:latest',
echo=True,
pty=True, shell=SHELL
);
@task
def docker_alpine(ctx):
if os.getenv('DOCKER_NO_CACHE') == 'true':
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{DOCKER}" build -f Dockerfile.alpine --no-cache --tag mediasoup/docker-alpine:latest .',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
else:
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{DOCKER}" build -f Dockerfile.alpine --tag mediasoup/docker-alpine:latest .',
echo=True,
pty=PTY_SUPPORTED,
shell=SHELL
);
@task
def docker_alpine_run(ctx):
with ctx.cd(WORKER_DIR):
ctx.run(
f'"{DOCKER}" run --name=mediasoupDockerAlpine -it --rm --privileged --cap-add SYS_PTRACE -v "{WORKER_DIR}/../:/mediasoup" mediasoup/docker-alpine:latest',
echo=True,
pty=True, shell=SHELL
);