'How to bundle system sonames into a cx_Freeze application?
I am building an application which would make use of htmltidy
, a library that cleans up bad HTML. There is a python binding which makes use of the soname libtidy.so
. However, I intend to distribute the application using cx_Freeze. How should I do this? Also, I would like this to be a multiplatform solution, rather than just for Linux.
I tried to simply copy the soname to the created /lib folder, but that does not seem to work, most likely because of the soname search paths.
I also tried to use the bin_includes
option in cx_Freeze setup.py, but that does not work either.
Script: testtidy.py
from tidylib import tidy_document
document, errors = tidy_document('''<p>fõo <img src="bar.jpg">''',
options={'numeric-entities':1})
print(document)
print(errors)
setup.py
import sys
from cx_Freeze import setup, Executable
# Dependencies are automatically detected, but it might need fine tuning.
# "packages": ["os"] is used as example only
build_exe_options = {"packages": ["os"],
"excludes": ["tkinter"],
"bin_includes": ["libtidy.so"]
}
base = None
setup(
name="testtidy",
version="0.1",
description="My application",
options={"build_exe": build_exe_options},
executables=[Executable("testtidy.py", base=base)],
)
Solution 1:[1]
The bin_includes
option presumably does not work because the given library name is not an existing path.
In your setup.py
, try to build an existing path to the tidy
library:
import ctypes
from distutils import sysconfig
import os
lib_dir = sysconfig.get_config_var('LIBDIR')
libtidy_name = ctypes.util.find_library('tidy')
libtidy_path = os.path.join(lib_dir, libtidy_name)
libtidy_path
should now contain the (symlink) path /usr/lib64/libtidy.so.58
, use it in the bin_includes
option:
build_exe_options = {...
"bin_includes": [libtidy_path]
}
After freezing, you should now see the symlink libtidy.so.58
and the the library itself libtidy.so.5.8.0
in the lib
subdirectory of the build directory.
This still might not be enough to solve your problem. Looking at the source code of the python binding tidylib
, starting from line 86, you will notice that it does not only rely on the soname libtidy.so
, it rather relies on ctypes.util.find_library('tidy')
and a pre-configured LIB_NAMES
list as fallback. I'm not sure whether the modification proposed above will suffice to make ctypes.util.find_library('tidy')
work in the frozen executable, if not we will still need to teach tidylib
to find the library by tweaking the LIB_NAMES
in the frozen executable.
EDIT:
Regarding building a multiplatform solution, see the cx_Freeze documentation:
cx_Freeze works on Windows, Mac and Linux, but on each platform it only makes an executable that runs on that platform. So if you want to freeze your programs for Windows, freeze it on Windows; if you want to run it on Macs, freeze it on a Mac.
You will thus need to make your source code run on the target platform, including htmltidy
and its python binding pytidylib
, and build the running code into an executable using cx_Freeze on that platform. Tweaks will probably be necessary there as well to let cx_Freeze include all dependencies of tidylib
correctly, and these tweaks may look different for each platform.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |