Skip to content

Instantly share code, notes, and snippets.

@JCGoran
Last active October 23, 2020 23:29
Show Gist options
  • Save JCGoran/e39c14ee6fdb03b4b405834ddf3d0be4 to your computer and use it in GitHub Desktop.
Save JCGoran/e39c14ee6fdb03b4b405834ddf3d0be4 to your computer and use it in GitHub Desktop.
Script for building and running cadmus
#!/usr/bin/env bash
# a POSIX-compatible shell script that builds cadmus the easy way
# requirements:
# - git
# - python3 (with pip and venv)
# - make
# - cmake
# - a C++ compiler (g++ will do)
# - pulseaudio
# - libGL (see for instance https://packages.debian.org/buster/libgl1)
# - one of the following shells: bash (default), zsh, tcsh, csh, fish
# on Debian- and Ubuntu- based distros, they can be installed using:
# apt-get install git python3-pip python3-venv make cmake g++ pulseaudio libgl1
CADMUS_USAGE='USAGE: `${SHELL} [NAME_OF_THIS_FILE].sh [build|run]` while in some (preferably empty) directory'
# env variables
# the path to the global python interpreter
# this should work on all distros, as long as `python3` is a symlink to `python`,
# but in case `python3` doesn't exist, we fall back to `python` (and hope it's the right one)
PYTHON="$(command -v python3 || command -v python)"
# NOTE: this cadmus repo contains the fix for the slider
REPO_CADMUS="${REPO_CADMUS:-https://github.com/mmarsalko/cadmus}"
# dir where it will be cloned
DESTINATION_CADMUS="${DESTINATION_CADMUS:-cadmus}"
# noise suppression repo
REPO_NOISESUP="${REPO_NOISESUP:-https://github.com/werman/noise-suppression-for-voice}"
# where it will be cloned
DESTINATION_NOISESUP="${DESTINATION_NOISESUP:-noise-suppression}"
# name of the dir with the environment (subdir of $DESTINATION_CADMUS)
VENV_CADMUS="${VENV_CADMUS:-environment}"
# since ${SHELL} returns the full path of the shell,
# we need to do a string comparison instead
# taken from:
# https://stackoverflow.com/a/8811800
contains(){
string="$1"
substring="$2"
if test "${string#*$substring}" != "$string"
then
return 0 # $substring is in $string
else
return 1 # $substring is not in $string
fi
}
# main build script
build_cadmus(){
# clone cadmus
git clone "${REPO_CADMUS}" "${DESTINATION_CADMUS}"
# add the noise-suppression-for-voice module
git -C "${DESTINATION_CADMUS}" submodule add "${REPO_NOISESUP}" "${DESTINATION_NOISESUP}"
# build the noise-suppression-for-voice library
# we only need the LADSPA plugin, which has no dependencies
cmake \
-B"${DESTINATION_CADMUS}/${DESTINATION_NOISESUP}/build" \
-H"${DESTINATION_CADMUS}/${DESTINATION_NOISESUP}" \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_VST_PLUGIN=NO \
-DBUILD_LV2_PLUGIN=NO
make -j -C "${DESTINATION_CADMUS}/${DESTINATION_NOISESUP}/build"
# path to shared object file of the LADSPA plugin
# TODO: maybe we could use `find` in case it's not there anymore at some point?
PATH_RNNOISE_DEFAULT="${DESTINATION_CADMUS}/${DESTINATION_NOISESUP}/build/bin/ladspa/librnnoise_ladspa.so"
# path where it will be copied
PATH_LIB_CADMUS="${DESTINATION_CADMUS}/src/main/resources/base/"
# make sure the shared object file exists
if [ -e "${PATH_RNNOISE_DEFAULT}" ]
then
# copy it to the dir indicated in the README (first make it if it doesn't exist)
mkdir -p "${PATH_LIB_CADMUS}"
cp -a "${PATH_RNNOISE_DEFAULT}" "${PATH_LIB_CADMUS}"
else
# in case noise-suppression-for-voice doesn't build it in the right location
printf "Error: the file ${PATH_RNNOISE_DEFAULT} doesn't exist!\n"
return 1
fi
# make the virtual environment (venv) in the dir `environment` (default name)
"${PYTHON}" -m venv "${DESTINATION_CADMUS}/${VENV_CADMUS}"
# activate the venv
# see table at:
# https://docs.python.org/3/library/venv.html
# for why we need so many checks for shells
# NOTE: this probably doesn't work on Windows
if contains "${SHELL}" "bash" || contains "${SHELL}" "zsh"
then
source "${DESTINATION_CADMUS}/${VENV_CADMUS}/bin/activate"
elif contains "${SHELL}" "fish"
then
. "${DESTINATION_CADMUS}/${VENV_CADMUS}/bin/activate.fish"
# the latter is probably redundant since "csh" is a substring of "tcsh"
elif contains "${SHELL}" "csh" || contains "${SHELL}" "tcsh"
then
source "${DESTINATION_CADMUS}/${VENV_CADMUS}/bin/activate.csh"
else
printf "Error: unknown shell ${SHELL}\n"
return 2
fi
# check it's actually running
if [ -n "${VIRTUAL_ENV}" ]
then
# re-set python so it's the one INSIDE the venv (otherwise pip installs it OUTSIDE the venv)
PYTHON="$(command -v python3 || command -v python)"
# for the exported variable, see:
# https://github.com/pypa/pip/issues/6773#issuecomment-515857335
export PYTHON_KEYRING_BACKEND="keyring.backends.null.Keyring"
# reset requirements without pinned versions
sed -i 's/==.*//g' "${DESTINATION_CADMUS}/requirements.txt"
# pin version of PyQt5 for older versions of pip, see:
# https://stackoverflow.com/a/59797479
sed -i 's/^PyQt5$/PyQt5==5.14.0/' "${DESTINATION_CADMUS}/requirements.txt"
# also pin PyInstaller to avoid the fbs error
sed -i 's/^PyInstaller$/PyInstaller==3.4/' "${DESTINATION_CADMUS}/requirements.txt"
# install cadmus-specific dependencies, and don't use cache
"${PYTHON}" -m pip install wheel --no-cache
"${PYTHON}" -m pip install -r "${DESTINATION_CADMUS}/requirements.txt" --no-cache
else
# otherwise abort
printf "The venv is not activated!\n"
return 3
fi
}
run_cadmus(){
# check the dir exists
if [ -d "${DESTINATION_CADMUS}/${VENV_CADMUS}" ]
then
# activate the venv
# see table at:
# https://docs.python.org/3/library/venv.html
# for why we need so many checks for shells
# NOTE: this probably doesn't work on Windows
if contains "${SHELL}" "bash" || contains "${SHELL}" "zsh"
then
source "${DESTINATION_CADMUS}/${VENV_CADMUS}/bin/activate"
elif contains "${SHELL}" "fish"
then
. "${DESTINATION_CADMUS}/${VENV_CADMUS}/bin/activate.fish"
# the latter is probably redundant since "csh" is a substring of "tcsh"
elif contains "${SHELL}" "csh" || contains "${SHELL}" "tcsh"
then
source "${DESTINATION_CADMUS}/${VENV_CADMUS}/bin/activate.csh"
else
printf "Error: unknown shell ${SHELL}\n"
return 2
fi
# check it's actually running
if [ -n "${VIRTUAL_ENV}" ]
then
# re-set python so it's the one INSIDE the venv
PYTHON="$(command -v python3 || command -v python)"
# run cadmus (inside the venv)
cd "${DESTINATION_CADMUS}"
"${PYTHON}" "src/main/python/main.py"
else
# otherwise abort
printf "The venv is not activated!\n"
return 3
fi
else
printf "Error: the directory ${DESTINATION_CADMUS}/${VENV_CADMUS} doesn't exist; make sure you are in the correct directory and that you're ran '$0 build' beforehand!\n"
return 4
fi
}
# option parser
parse_options(){
if [ "$#" -ne 1 ]
then
printf "${CADMUS_USAGE}\n"
return 255
else
case "$1" in
"build" )
build_cadmus
;;
"run" )
run_cadmus
;;
* )
printf "Error: unknown command - '$1'\n"
return 254
;;
esac
fi
}
parse_options "$@"
@rastla
Copy link

rastla commented Sep 27, 2020

Thanks for the script. However, I sadly can't get it to run.
After installing all the necessary requirements, I still get that error:

./cadmus-buildscript.sh: 105: source: not found The venv is not activated!

I'm using Ubuntu 20.04 with the Tilix Shell, which should use /bin/bash
I'm not quite sure what's happening, but as far as I can see it should use "/cadmus/environment/bin/activate" for the source command but can't find it?

If I manually go to that directory, the file is there and can also be executed by the terminal:
kevin@kevin-ubuntu:~/Dokumente/cadmus/environment/bin$ source activate (environment) kevin@kevin-ubuntu:~/Dokumente/cadmus/environment/bin$

@JCGoran
Copy link
Author

JCGoran commented Sep 27, 2020

Thanks for the script. However, I sadly can't get it to run.
After installing all the necessary requirements, I still get that error:

./cadmus-buildscript.sh: 105: source: not found The venv is not activated!

I'm using Ubuntu 20.04 with the Tilix Shell, which should use /bin/bash
I'm not quite sure what's happening, but as far as I can see it should use "/cadmus/environment/bin/activate" for the source command but can't find it?

If I manually go to that directory, the file is there and can also be executed by the terminal:
kevin@kevin-ubuntu:~/Dokumente/cadmus/environment/bin$ source activate (environment) kevin@kevin-ubuntu:~/Dokumente/cadmus/environment/bin$

You should explicitly run the script with bash, using bash [NAME_OF_FILE].sh, because running it with ./[NAME_OF_FILE].sh will activate the POSIX-like shell on your system (probably dash or similar), which doesn't have the source builtin (though, POSIX does define the dot (.), so in principle all occurrences of source should be replaceable with ., but I just blindly followed the Python venv activation docs on this when I wrote the script).

@rastla
Copy link

rastla commented Sep 29, 2020

Running it with bash and applying the fix from AnonymerNiklasistanonym worked. Thanks!

@alperyilmaz
Copy link

The build was finished successfully but cadmus didn't run.. here's the error message:

$ bash cadmus.sh run
Traceback (most recent call last):
  File "src/main/python/main.py", line 3, in <module>
    from PyQt5.QtGui import QIcon
ModuleNotFoundError: No module named 'PyQt5.QtGui'

python3-pyqt5 package is already installed and running pip install pyqt5 didn't help either.. (I'm using Pop OS 20.04)

@JCGoran
Copy link
Author

JCGoran commented Oct 6, 2020

It is possible that the currently installed (and cached) version of PyQt5 on your machine is older than the one required by cadmus, but since the above script modifies the requirements.txt file so it doesn't have specific version requirements, pip happily uses the cached versions.
You could try to force pip not to use the cache, so it installs the latest version of PyQt5 (and others), you just need to change the following line (currently 136) from:

"${PYTHON}" -m pip install -r "${DESTINATION_CADMUS}/requirements.txt"

into:

"${PYTHON}" -m pip install -r "${DESTINATION_CADMUS}/requirements.txt" --no-cache

@alperyilmaz
Copy link

Thanks @JCGoran for your kind response. Here's the current version of cadmus.sh that I have (between lines 129-146):

        # the requirements are a bit bizarre, so we re-set them without pinned versions
        #sed -i 's/==.*//g' "${DESTINATION_CADMUS}/requirements.txt"
       
        # changes suggested by @AnonymerNiklasistanonym https://gist.github.com/JCGoran/e39c14ee6fdb03b4b405834ddf3d0be4#gistcomment-3468749 
        # some requirements are a bit old so we update them to more current versions
        sed -i s/sip==4.19.8/sip==5.0.0/ "${DESTINATION_CADMUS}/requirements.txt"
        sed -i s/PyQt5==5.9.2/PyQt5==5.14.2/ "${DESTINATION_CADMUS}/requirements.txt"
        # install cadmus-specific dependencies
        # NOTE: the following error, or a similar one, may appear:
        # `fbs 0.9.0 has requirement PyInstaller==3.4, but you'll have pyinstaller 4.0 which is incompatible`
        # this makes no difference to properly running cadmus
        "${PYTHON}" -m pip install wheel
        "${PYTHON}" -m pip install -r "${DESTINATION_CADMUS}/requirements.txt" --no-cache
    else
        # otherwise abort
        printf "The venv is not activated!\n"
        return 3
    fi

I also applied changes from @AnonymerNiklasistanonym and still I get the same error 😞

@alperyilmaz
Copy link

Thanks @JCGoran for your kind response. Here's the current version of cadmus.sh that I have (between lines 129-146):

        # the requirements are a bit bizarre, so we re-set them without pinned versions
        #sed -i 's/==.*//g' "${DESTINATION_CADMUS}/requirements.txt"
       
        # changes suggested by @AnonymerNiklasistanonym https://gist.github.com/JCGoran/e39c14ee6fdb03b4b405834ddf3d0be4#gistcomment-3468749 
        # some requirements are a bit old so we update them to more current versions
        sed -i s/sip==4.19.8/sip==5.0.0/ "${DESTINATION_CADMUS}/requirements.txt"
        sed -i s/PyQt5==5.9.2/PyQt5==5.14.2/ "${DESTINATION_CADMUS}/requirements.txt"
        # install cadmus-specific dependencies
        # NOTE: the following error, or a similar one, may appear:
        # `fbs 0.9.0 has requirement PyInstaller==3.4, but you'll have pyinstaller 4.0 which is incompatible`
        # this makes no difference to properly running cadmus
        "${PYTHON}" -m pip install wheel
        "${PYTHON}" -m pip install -r "${DESTINATION_CADMUS}/requirements.txt" --no-cache
    else
        # otherwise abort
        printf "The venv is not activated!\n"
        return 3
    fi

I also applied changes from @AnonymerNiklasistanonym and still I get the same error 😞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment