Skip to content

Commit f0c996c

Browse files
authored
Add support for Manylinux2014 (#750)
1 parent 36553b0 commit f0c996c

9 files changed

+202
-40
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ src/urh/dev/native/lib/*.cpp
4848

4949
/tests/show_gui
5050

51-
51+
src/urh/*.txt
52+
src/urh/URHProject.xml
53+
.coverage*
54+
src/urh/dev/gr/scripts/top_block.py
5255

5356
misc/*

README.md

+26-11
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,37 @@ On Windows, URH can be installed with its [Installer](https://github.com/jopohl/
6767
If you get an error about missing ```api-ms-win-crt-runtime-l1-1-0.dll```, run Windows Update or directly install [KB2999226](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows).
6868

6969
### Linux
70-
#### Install via Package Manager
71-
URH is included in the repositories of many linux distributions such as __Arch Linux__, __Gentoo__, __Fedora__, __openSUSE__ or __NixOS__. There is also a package for __FreeBSD__. If available, simply use your package manager to install URH.
72-
73-
#### Generic Installation with pip (Ubuntu/Debian)
74-
URH is available on [PyPi](https://pypi.org/project/urh/) so you can install it with ``` pip ``` . For Ubuntu/Debian use the following commands to install URH including extensions for native SDR support.
70+
#### Generic Installation with pip (recommended)
71+
URH is available on [PyPi](https://pypi.org/project/urh/) so you can install it with
72+
```bash
73+
# IMPORTANT: Make sure your pip is up to date
74+
sudo python3 -m pip install --upgrade pip # Update your pip installation
75+
sudo python3 -m pip install urh # Install URH
76+
```
77+
This is the recommended way to install URH on Linux because it comes with __all native extensions__ precompiled.
78+
79+
##### udev rules
80+
In order to access your SDR as non-root user, install the according __udev rules__.
81+
For example, you can install the HackRF udev rules with the following commands.
7582

7683
```bash
77-
sudo apt update
78-
sudo apt install python3-numpy python3-psutil python3-pyqt5 g++ libpython3-dev python3-pip cython3
79-
# Install following packages for native support of corresponding SDR (before installing URH)
80-
sudo apt install libhackrf-dev liblimesuite-dev libbladerf-dev librtlsdr-dev libairspy-dev libuhd-dev libiio-dev
81-
sudo pip3 install urh
84+
sudo tee -a /etc/udev/rules.d/52-hackrf.rules >/dev/null <<-EOF
85+
ATTR{idVendor}=="1d50", ATTR{idProduct}=="604b", SYMLINK+="hackrf-jawbreaker-%k", MODE="660", GROUP="plugdev"
86+
ATTR{idVendor}=="1d50", ATTR{idProduct}=="6089", SYMLINK+="hackrf-one-%k", MODE="660", GROUP="plugdev"
87+
ATTR{idVendor}=="1fc9", ATTR{idProduct}=="000c", SYMLINK+="hackrf-dfu-%k", MODE="660", GROUP="plugdev"
88+
EOF
89+
sudo udevadm control --reload-rules
8290
```
91+
Make sure your current user is in the ```plugdev``` group to make these rules work.
92+
You find rules for other SDRs by searching for "```<SDR name>``` udev rules" in your favorite search engine.
93+
94+
#### Install via Package Manager
95+
URH is included in the repositories of many linux distributions such as __Arch Linux__, __Gentoo__, __Fedora__, __openSUSE__ or __NixOS__. There is also a package for __FreeBSD__. If available, simply use your package manager to install URH.
96+
97+
__Note__: For native support, you must install the according ```-dev``` package(s) of your SDR(s) such as ```hackrf-dev``` __before__ installing URH.
8398

8499
#### Docker Image
85-
The official URH docker image is available [here](https://hub.docker.com/r/jopohl/urh/).
100+
The official URH docker image is available [here](https://hub.docker.com/r/jopohl/urh/). It has all native backends included and ready to operate.
86101

87102
### MacOS
88103
#### Using DMG

data/azure-pipelines.yml

+19-14
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,41 @@ jobs:
2727
architecture: 'x64'
2828

2929
- script: |
30-
python -m pip install --upgrade pip
30+
python -m pip install --upgrade pip twine
3131
pip install -r data/requirements.txt
3232
sudo apt-get install libhackrf-dev librtlsdr-dev xvfb libxkbcommon-x11-0 x11-utils
3333
pip install twine setuptools wheel pytest pytest-xvfb pytest-cov pytest-faulthandler
3434
python -c "import tempfile, os; open(os.path.join(tempfile.gettempdir(), 'urh_releasing'), 'w').close()"
3535
displayName: 'Install dependencies'
3636
37-
- script: python setup.py build_ext --inplace
37+
- script: python src/urh/cythonext/build.py
3838
displayName: "Build extensions"
3939

4040
- script: python setup.py sdist
4141
displayName: "Build sdist"
4242
condition: eq(variables['python.version'], '3.7')
4343

44-
- script: twine upload --skip-existing dist/*.gz
45-
displayName: "Upload sdist to PyPi"
46-
condition: and(eq(variables['python.version'], '3.7'), contains(variables['Build.SourceBranch'], 'refs/tags/'))
44+
- script: |
45+
docker run --rm \
46+
-e PYVER=$(python -c "import sys; print('%s%s' % (sys.version_info.major, sys.version_info.minor))") \
47+
-v `pwd`:/io jopohl/urh_manylinux2014 /io/data/make_manylinux2014_wheels.sh
48+
displayName: "Build wheel"
49+
50+
- script: |
51+
pip install dist/*.whl
52+
urh --version
53+
xvfb-run urh autoclose
54+
displayName: 'Testrun'
55+
56+
- script: twine upload --skip-existing dist/*
57+
displayName: "PyPi Upload"
58+
condition: contains(variables['Build.SourceBranch'], 'refs/tags/')
4759
env:
4860
TWINE_USERNAME: $(twine.username)
4961
TWINE_PASSWORD: $(twine.password)
5062
TWINE_REPOSITORY_URL: "https://upload.pypi.org/legacy/"
5163

5264
- task: PublishBuildArtifacts@1
53-
condition: eq(variables['python.version'], '3.7')
5465
inputs:
5566
pathtoPublish: dist/
5667
artifactName: 'dist'
@@ -97,12 +108,6 @@ jobs:
97108
coverageType: lines
98109
baseBranchRef: refs/heads/master
99110

100-
- script: |
101-
pip install .
102-
urh --version
103-
xvfb-run urh autoclose
104-
displayName: 'Testrun'
105-
106111
- job: 'Windows'
107112
pool:
108113
vmImage: 'vs2017-win2016'
@@ -144,7 +149,7 @@ jobs:
144149
destinationFolder: src\urh\dev\native\lib\shared
145150
#cleanDestinationFolder: true
146151

147-
- script: python setup.py build_ext --inplace
152+
- script: python src/urh/cythonext/build.py
148153
displayName: "Build extensions"
149154

150155
- script: |
@@ -253,7 +258,7 @@ jobs:
253258
sudo make install
254259
displayName: "Install libusb and boost"
255260
256-
- script: python setup.py build_ext --inplace
261+
- script: python src/urh/cythonext/build.py
257262
displayName: "Build extensions"
258263

259264
- script: python setup.py bdist_wheel

data/make_manylinux2014_wheels.sh

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
3+
# for adapted jopohl/urh_manylinux
4+
5+
touch /tmp/urh_releasing
6+
for PYBIN in /opt/python/*$PYVER*/bin; do # for all if PYVER not set
7+
echo -e "\033[1mInstalling requirements for $PYBIN\033[0m"
8+
"${PYBIN}/pip" install -r /io/data/requirements.txt
9+
10+
cd /io || return
11+
echo -e "\033[1mBuilding extentions for $PYBIN\033[0m"
12+
"${PYBIN}/python3" setup.py build_ext "-j$(nproc)"
13+
14+
echo -e "\033[1mBuilding wheel for $PYBIN\033[0m"
15+
"${PYBIN}/pip" wheel --no-deps /io/ -w /wheelhouse/
16+
done
17+
18+
# Bundle external libs into wheels
19+
echo -e '\033[92mRepairing wheels...\033[0m'
20+
for whl in /wheelhouse/*.whl; do
21+
auditwheel repair "$whl" -w /io/dist/
22+
done
+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/bin/bash
2+
3+
# for plain quay.io/pypa/manylinux2014_x86_64
4+
5+
AIRSPY_VERSION="1.0.9"
6+
BLADERF_VERSION="2018.08"
7+
LIMESUITE_VERSION="20.01.0"
8+
SDRPLAY_VERSION="2.13"
9+
RTLSDR_VERSION="0.6.0"
10+
11+
echo -e '\033[92mInstalling dependencies...\033[0m'
12+
yum -y -q install wget cmake3 hackrf-devel uhd-devel\
13+
https://github.com/analogdevicesinc/libiio/releases/download/v0.19/libiio-0.19.g5f5af2e-centos-7-x86_64.rpm
14+
15+
build_airspy() {
16+
&> /dev/null
17+
tar xf /tmp/airspy.tar.gz -C /tmp
18+
cmake3 -Wno-dev -S /tmp/airspyone_host-$AIRSPY_VERSION -B /tmp/build_airspy > /dev/null
19+
make --silent -C /tmp/build_airspy > /dev/null
20+
make --silent -C /tmp/build_airspy install > /dev/null
21+
}
22+
23+
build_bladerf() {
24+
wget https://github.com/Nuand/bladeRF/archive/$BLADERF_VERSION.tar.gz -O /tmp/bladeRF.tar.gz &> /dev/null
25+
tar xf /tmp/bladeRF.tar.gz -C /tmp
26+
cmake3 -Wno-dev -S /tmp/bladeRF-$BLADERF_VERSION/host -B /tmp/build_blade > /dev/null
27+
make --silent -C /tmp/build_blade > /dev/null
28+
make --silent -C /tmp/build_blade install > /dev/null
29+
}
30+
31+
build_limesdr() {
32+
wget https://github.com/myriadrf/LimeSuite/archive/v$LIMESUITE_VERSION.tar.gz -O /tmp/lime.tar.gz &> /dev/null
33+
tar xf /tmp/lime.tar.gz -C /tmp
34+
cmake3 -Wno-dev -S /tmp/LimeSuite-$LIMESUITE_VERSION -B /tmp/build_lime > /dev/null
35+
make --silent -C /tmp/build_lime > /dev/null
36+
make --silent -C /tmp/build_lime install > /dev/null
37+
}
38+
39+
build_rtlsdr() {
40+
wget https://github.com/osmocom/rtl-sdr/archive/$RTLSDR_VERSION.tar.gz -O /tmp/rtlsdr.tar.gz &> /dev/null
41+
tar xf /tmp/rtlsdr.tar.gz -C /tmp
42+
cmake3 -Wno-dev -DDETACH_KERNEL_DRIVER=ON -S /tmp/rtl-sdr-$RTLSDR_VERSION -B /tmp/build_rtlsdr > /dev/null
43+
make --silent -C /tmp/build_rtlsdr > /dev/null
44+
make --silent -C /tmp/build_rtlsdr install > /dev/null
45+
}
46+
47+
build_sdrplay() {
48+
wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-$SDRPLAY_VERSION.1.run -O /tmp/sdrplay.run &> /dev/null
49+
bash /tmp/sdrplay.run --tar xf -C /tmp
50+
mv /tmp/mirsdrapi-rsp.h /usr/include
51+
mv /tmp/x86_64/* /usr/lib64
52+
ln -s /usr/lib64/libmirsdrapi-rsp.so.$SDRPLAY_VERSION /usr/lib64/libmirsdrapi-rsp.so
53+
}
54+
55+
echo -e '\033[92mCompiling SDR libs...\033[0m'
56+
build_airspy &
57+
build_bladerf &
58+
build_limesdr &
59+
build_rtlsdr &
60+
build_sdrplay &
61+
wait
62+
63+
touch /tmp/urh_releasing
64+
for PYBIN in /opt/python/*/bin; do
65+
echo -e "\033[1mInstalling requirements for $PYBIN\033[0m"
66+
"${PYBIN}/pip" install -r /io/data/requirements.txt > /dev/null
67+
68+
cd /io || return
69+
echo -e "\033[1mBuilding extentions for $PYBIN\033[0m"
70+
"${PYBIN}/python3" setup.py build_ext "-j$(nproc)" | grep --color=always "Skipping"
71+
72+
echo -e "\033[1mBuilding wheel for $PYBIN\033[0m"
73+
"${PYBIN}/pip" wheel --no-deps /io/ -w /wheelhouse/ > /dev/null
74+
done
75+
76+
# Bundle external libs into wheels
77+
echo -e '\033[92mRepairing wheels...\033[0m'
78+
for whl in /wheelhouse/*.whl; do
79+
auditwheel repair "$whl" -w /io/dist/
80+
done

data/manylinux2014.Dockerfile

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
FROM quay.io/pypa/manylinux2014_x86_64
2+
3+
RUN export AIRSPY_VERSION="1.0.9" \
4+
&& export BLADERF_VERSION="2018.08" \
5+
&& export LIMESUITE_VERSION="20.01.0" \
6+
&& export SDRPLAY_VERSION="2.13" \
7+
&& export RTLSDR_VERSION="0.6.0" \
8+
&& yum -y install wget cmake3 hackrf-devel uhd-devel https://github.com/analogdevicesinc/libiio/releases/download/v0.19/libiio-0.19.g5f5af2e-centos-7-x86_64.rpm \
9+
&& wget https://github.com/airspy/airspyone_host/archive/v$AIRSPY_VERSION.tar.gz -O /tmp/airspy.tar.gz \
10+
&& tar xf /tmp/airspy.tar.gz -C /tmp \
11+
&& cmake3 -Wno-dev -S /tmp/airspyone_host-$AIRSPY_VERSION -B /tmp/build_airspy \
12+
&& make -j$(nproc) -C /tmp/build_airspy \
13+
&& make -C /tmp/build_airspy install \
14+
&& wget https://github.com/Nuand/bladeRF/archive/$BLADERF_VERSION.tar.gz -O /tmp/bladeRF.tar.gz \
15+
&& tar xf /tmp/bladeRF.tar.gz -C /tmp \
16+
&& cmake3 -Wno-dev -S /tmp/bladeRF-$BLADERF_VERSION/host -B /tmp/build_blade \
17+
&& make -j$(nproc) -C /tmp/build_blade \
18+
&& make -C /tmp/build_blade install \
19+
&& wget https://github.com/myriadrf/LimeSuite/archive/v$LIMESUITE_VERSION.tar.gz -O /tmp/lime.tar.gz \
20+
&& tar xf /tmp/lime.tar.gz -C /tmp \
21+
&& cmake3 -S /tmp/LimeSuite-$LIMESUITE_VERSION -B /tmp/build_lime \
22+
&& make -j$(nproc) -C /tmp/build_lime \
23+
&& make -C /tmp/build_lime install \
24+
&& wget https://github.com/osmocom/rtl-sdr/archive/$RTLSDR_VERSION.tar.gz -O /tmp/rtlsdr.tar.gz \
25+
&& tar xf /tmp/rtlsdr.tar.gz -C /tmp \
26+
&& cmake3 -DDETACH_KERNEL_DRIVER=ON -S /tmp/rtl-sdr-$RTLSDR_VERSION -B /tmp/build_rtlsdr \
27+
&& make -j$(nproc) -C /tmp/build_rtlsdr \
28+
&& make -C /tmp/build_rtlsdr install \
29+
&& wget http://www.sdrplay.com/software/SDRplay_RSP_API-Linux-$SDRPLAY_VERSION.1.run -O /tmp/sdrplay.run \
30+
&& bash /tmp/sdrplay.run --tar xf -C /tmp \
31+
&& mv /tmp/mirsdrapi-rsp.h /usr/include \
32+
&& mv /tmp/x86_64/* /usr/lib64 \
33+
&& ln -s /usr/lib64/libmirsdrapi-rsp.so.$SDRPLAY_VERSION /usr/lib64/libmirsdrapi-rsp.so \
34+
&& rm -rf /tmp/* \
35+
&& yum clean all

setup.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
import shutil
32
import sys
43
import tempfile
54

@@ -31,7 +30,6 @@
3130
OPEN_MP_FLAG = "-fopenmp"
3231
NO_NUMPY_WARNINGS_FLAG = "-Wno-cpp"
3332

34-
3533
UI_SUBDIRS = ("actions", "delegates", "views")
3634
PLUGINS = [path for path in os.listdir("src/urh/plugins") if os.path.isdir(os.path.join("src/urh/plugins", path))]
3735
URH_DIR = "urh"
@@ -96,7 +94,8 @@ def get_extensions():
9694
for extension in extensions:
9795
extension.extra_compile_args.append(NO_NUMPY_WARNINGS_FLAG)
9896

99-
extensions = cythonize(extensions, compiler_directives=COMPILER_DIRECTIVES, quiet=True, compile_time_env=device_extras)
97+
extensions = cythonize(extensions, compiler_directives=COMPILER_DIRECTIVES, compile_time_env=device_extras,
98+
nthreads=0 if sys.platform == "win32" else os.cpu_count())
10099
return extensions
101100

102101

@@ -108,6 +107,7 @@ def read_long_description():
108107
except:
109108
return ""
110109

110+
111111
install_requires = ["numpy", "psutil", "cython"]
112112
if IS_RELEASE:
113113
install_requires.append("pyqt5")
@@ -120,7 +120,6 @@ def read_long_description():
120120
if sys.version_info < (3, 4):
121121
install_requires.append('enum34')
122122

123-
124123
setup(
125124
name="urh",
126125
version=version.VERSION,

src/urh/cythonext/build.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
def main():
1010
cur_dir = os.path.realpath(__file__)
1111
os.chdir(os.path.realpath(os.path.join(cur_dir, "..", "..", "..", "..")))
12-
#call([sys.executable, "setup.py", "clean", "--all"])
13-
call([sys.executable, "setup.py", "build_ext", "--inplace"])
12+
# call([sys.executable, "setup.py", "clean", "--all"])
13+
call([sys.executable, "setup.py", "build_ext", "--inplace", "-j{}".format(os.cpu_count())])
1414

1515

1616
if __name__ == "__main__":

src/urh/dev/native/ExtensionHelper.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
'initializedcheck': False,
1919
}
2020

21-
2221
DEVICES = {
2322
"airspy": {"lib": "airspy", "test_function": "open"},
2423
"bladerf": {"lib": "bladeRF", "test_function": "bladerf_open",
@@ -44,11 +43,11 @@
4443
"sdrplay": {"lib": "mir_sdr_api" if sys.platform == "win32" else "mirsdrapi-rsp",
4544
"test_function": "mir_sdr_ApiVersion",
4645
"api_version_check_code":
47-
"""
48-
#include<stdio.h>
49-
int main(void) {
50-
float version=0.0; mir_sdr_ApiVersion(&version); printf("%f", version); return 0;}
51-
"""}
46+
"""
47+
#include<stdio.h>
48+
int main(void) {
49+
float version=0.0; mir_sdr_ApiVersion(&version); printf("%f", version); return 0;}
50+
"""}
5251
}
5352

5453

@@ -193,7 +192,7 @@ def get_device_extensions_and_extras(library_dirs=None, include_dirs=None):
193192
print(" Environment variable {} is unset, try to automatically detect API version".format(env_name))
194193

195194
if ver is None:
196-
ver = check_api_version(compiler, params["api_version_check_code"], (params["lib"], ),
195+
ver = check_api_version(compiler, params["api_version_check_code"], (params["lib"],),
197196
library_dirs, include_dirs)
198197
device_extras[env_name] = ver
199198
print(" Using {}={}".format(env_name, ver))
@@ -267,6 +266,7 @@ def perform_health_check() -> str:
267266
include_directories = []
268267

269268
import numpy as np
269+
270270
include_directories.append(np.get_include())
271271

272272
cur_dir = os.path.dirname(os.path.realpath(__file__))
@@ -282,8 +282,11 @@ def perform_health_check() -> str:
282282

283283
dev_extensions, dev_extras = get_device_extensions_and_extras(library_dirs=library_directories,
284284
include_dirs=include_directories)
285+
sys.argv.append("-j{}".format(os.cpu_count()))
286+
285287
setup(
286288
name="urh",
287289
ext_modules=cythonize(dev_extensions, force=True,
288-
compile_time_env=dev_extras, compiler_directives=COMPILER_DIRECTIVES),
290+
compile_time_env=dev_extras, compiler_directives=COMPILER_DIRECTIVES,
291+
nthreads=0 if sys.platform == "win32" else os.cpu_count()),
289292
)

0 commit comments

Comments
 (0)