Skip to content

Instantly share code, notes, and snippets.

@sveinse sveinse/pysndfile_build.sh
Last active Jul 29, 2019

Embed
What would you like to do?
Scheme for setting up pysndfile and libraries on Windows
#!/bin/bash -x
# The purpose of this script is to build a pysndfile wheel.
# The main purpose of generating a wheel, is to be able to distribute
# the wheel similar to the binary files, not needing to recompiling the
# module on every install.
disr="dist"
binaries="libsndfile_binaries_win32"
venv="venv-pysndfile"
python="winpty py -3"
# Pre cleanup
rm -rf "$venv"
# Create venv
$python -m venv "$venv"
pip="winpty "$(readlink -f "$venv/Scripts/pip")""
$pip install wheel numpy cython
# Unpack the binaries
mkdir -p "$venv/$dist"
tar -C "$venv/$dist" -xf "$binaries.tar.xz"
dir="$(readlink -f $venv/$dist)"
# Alternative 1) Download the official version from pypi
#$pip download --no-deps --no-binary=:all: pysndfile
#tar -xf pysndfile-*.tar.gz
#d=pysndfile-1*
# Alternative 2) Fetch the sources
git clone https://github.com/roebel/pysndfile.git pysndfile
d=pysndfile
# Generate the wheel
cd $d
$pip wheel . --verbose --no-deps \
--global-option=build_ext \
--global-option="-L$dir/lib" \
--global-option="-L$dir/include"
#!/bin/bash -x
# Setup a new venv and install the pysndfile wheel into it. It will
# also inject the libsndfile.dll into the venv, making it possible to
# use pysndfile
dist="dist"
binaries="libsndfile_binaries_win32"
venv="venv"
winpty="winpty"
python="py -3"
# Pre cleanup
rm -rf "$venv" "$dist"
# Create venv
$winpty $python -m venv "$venv"
# Setup new executables
python="$(readlink -f "$venv/Scripts/python")"
pip="$winpty "$(readlink -f "$venv/Scripts/pip")""
# Location of the python libraries
sp="$($python -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())')"
mkdir -p "$sp"
# Unpack the binary libraries
mkdir -p "$dist"
tar -C "$dist" -xf "${binaries}.tar.xz"
# Install pysndfile and inject dll into it
$pip install wheel pysndfile-*.whl
cp "$dist/lib/"*.dll "$sp/pysndfile/"
# Install the rest of the application here
# $pip install myapp
#!/bin/bash -x
# The purpose of this script is to generate a tarball containing the
# binary non-python libraries needed to run pysndfile.
#
# The official libsndfile isn't compiled with flac and ogg support, so another
# 3rd party distribution is used for this. Secondly the binary distributions
# of libsndfile doesn't come with a .lib file which is required for linking on
# Windows. The crude tool used in this script requires Visual Studio 2017
# to generate the required .lib file.
dist="dist"
binaries="libsndfile_binaries_win32"
venv="venv-pysndfile"
python="winpty py -3"
dll2lib="$(readlink -f win_dll2lib.py)"
# Pre cleanup
rm -rf "$dist" "$binaries"
# Create storage dirs
mkdir -p "$dist/lib" "$dist/include"
# Download the official windows release.
# Copy the headers from it
d=libsndfile-1.0.28-w32
url="http://www.mega-nerd.com/libsndfile/files/libsndfile-1.0.28-w32.zip"
curl -# "$url" -o "$d.zip"
unzip "$d.zip" -d "$d"
cp -av $d/include/*.h $d/include/*.hh $dist/include/
# Get the non-official windows build that includes support for flac and friends
# The library seems statically linked, so only the libsndfile32bit.dll is needed
d=libsndfile-binaries
git clone https://github.com/bastibe/libsndfile-binaries.git $d
( cd $d
git checkout 84cb164928f17c7ca0c1e5c40342c20ce2b90e8c) || exit 1
cp -av $d/libsndfile32bit.dll $dist/lib/
# Generate the libsndfile.lib from the dll:
# Please note that to be able to execute this, Visual Studio 2017 must be installed
( cd $dist/lib
$python "$dll2lib" libsndfile32bit.dll sndfile.lib
)
# Compile the binary
tar -C "$dist" -cvJf "${binaries}.tar.xz" .
""" A crude tool to generate a .lib from a .dll file """
import os
import sys
import subprocess
import tempfile
import re
# Bat script to convert DLL to a DEF file input
dumpbin = r'''
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars32.bat"
@ECHO on
DUMPBIN /exports "%1" >"%2"
'''
# Bat script to convert parsed DEF to LIB
libbat = r'''
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars32.bat"
@ECHO on
LIB /DEF:"%1" /OUT:"%2" /MACHINE:X86
'''
# Rudimentary argument checking
print(sys.argv)
if len(sys.argv) < 3:
raise Exception("Too few arguments")
# Get the file
infile = sys.argv[1]
deffile = infile.replace('.dll', '.def')
outfile = sys.argv[2]
expfile = outfile.replace('.lib', '.exp')
# Ensure the input exists
if not os.path.exists(infile):
raise FileNotFoundError(infile)
# Create a temp working directory
with tempfile.TemporaryDirectory() as tmpdirname:
# Write the temp bat script for dumping the DLL file and run it
bat = os.path.join(tmpdirname, 'run.bat')
with open(bat, 'w') as f:
f.write(dumpbin)
subprocess.check_call([bat, infile, deffile])
# Parse the output from dumpbin and make it into a file with
# EXPORTS
# method names...
out = 'EXPORTS\n'
with open(deffile, 'r') as f:
mode = 'header'
n = 0
i = 1
for line in f:
n += 1
l = line.strip()
s = re.split(r'\s+', l)
if len(s) != 4:
continue
try:
ordinal = int(s[0])
except ValueError:
continue
if ordinal != i:
continue
i += 1
out += s[3] + '\n'
# Write the def file
print(deffile)
with open(deffile, 'w') as f:
f.write(out)
# Write the temp bat script for generating the LIB file and run it
bat = os.path.join(tmpdirname, 'run.bat')
with open(bat, 'w') as f:
f.write(libbat)
subprocess.check_call([bat, deffile, outfile])
# Remove the temporary def file
os.remove(deffile)
os.remove(expfile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.