pts / pdfsizeopt

PDF file size optimizer
GNU General Public License v2.0
750 stars 65 forks source link

run on M1 Apple Silicon Mac within Docker #154

Closed pripple closed 1 year ago

pripple commented 2 years ago

Hi, I experience difficulties installing pdfsizeopt on an M1 (Apple Silicon) Mac. I have installed it successfully before on an Intel Mac, probably using Homebrew, but now it doesn’t work either with Homebrew or with Docker.

Homebrew

With Homebrew, the installation process for the dependency pts/utils/sam2p tries to copy a file to a folder with advanced privileges and quits with an error:

cp: /usr/local/bin/sam2p: Operation not permitted

Homebrew binaries should be installed to a specific Homebrew directory, that’s probably why it doesn’t work.

Docker

I then tried the suggested installation with Docker. As VirtualBox isn’t available on Apple Silicon, I installed Docker Desktop. However, using the command you provide, I first get the

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

and even though I can overcome this by adding --platform linux/amd64 to the command, I still get the error message

ImportError: No module named site

Help, please!

Is there anyone who could tell me how to get pdfsizeopt running on a M1 (Apple Silicon) Mac?

Thanks,

Lorenz

sbibauw commented 2 years ago

I'm afraid not only are there issues with the Homebrew installer (which was designed before the M1 changed the directories), but if you have macOS 12.5 (Monterey), Python 2 is no longer available and I'm not sure how pdfsizeopt can work with Python 3 (requires code updates). Otherwise, one would have to install pyenv to have a 2.7 instance of Python available.

pripple commented 1 year ago

After spending quite a lot of time trying to set it up both on my M1 Mac and on an Ubuntu Linux installation on a virtual machine on that Mac, I have given up and now, every time I need the program, I start an old Intel Machine with a virtual Ubuntu Linux installation where I can run pdfsizeopt without any problems. What a pity that all those innovations cause good and stable programs not to work anymore …

rbubley commented 1 year ago

The key problem I found when trying to make it work natively, rather than in Docker, was that pdfsizeopt relies on an old version of Ghostscript-- and I couldn't find source code to this old version to compile on Apple Silicon.

If you find the source, do post a link...

rbubley commented 1 year ago

In fact, I have now managed to get pdfsizeopt to work on an M1 Mac.

Approximate instructions (there may be things unique to my system that I have forgotten to note, and there are probably things that could be done better - but at least it works):

Follow the usual installation instructions for MacOS. Remove some components in pdfsizeopt_libexec and ensure their counterparts are installed from homebrew, in particular for qpdf and jbig2

For ghostscript: Get source code from ftp://ftp.gnu.org/gnu/ghostscript/gnu-ghostscript-9.14.1.tar.xz

tar xJvf gnu-ghostscript-9.14.1.tar.xz     
cd gnu-ghostscript-9.14.1 
./autogen.sh 

Apply this patch: (thanks to https://github.com/chrstphrchvz/macports-ports/blob/197bfa253db6d2dcb589197fa99d2bd19793fa10/print/ghostscript/files/patch-base_fapi_ft.c.diff )

i.e. insert the following lines at line 112 of base/fapi_ft.c:

static void delete_inc_int_info(gs_fapi_server * a_server,
                     FT_IncrementalRec * a_inc_int_info);

#ifndef FT_CALLBACK_DEF
#ifdef __cplusplus
#define FT_CALLBACK_DEF( x )  extern "C"  x
#else
#define FT_CALLBACK_DEF( x )  static  x
#endif
#endif

( Then run:

LDFLAGS=-L/opt/homebrew/lib CPPFLAGS=-I/opt/homebrew/include ./configure --without-jbig2dec  --without-libidn     
make

Copy ./bin/gs to pdfsizeopt_libexec/pdfsizeopt_gs/gs

pts commented 1 year ago

@rbubley, thank you for porting Ghostscript!

I've created a separate issue for supporting Apple Silicon outside Docker: https://github.com/pts/pdfsizeopt/issues/158

pts commented 1 year ago

@pripple: I was surprised that Docker on a Mac with Apple Silicon fails with ImportError: No module named site, while it succeeds on a Mac with 32-bit or 64-bit Intel processor. After some experimenting, I was able to find the root cause: sys.path[-1] was initialized to '/proc/self/exe', which doesn't work with the Intel processor emulation done by Docker. The fix is to change it to sys.executable ('/bin/python').

Here is a workaround which works with a Mac with Apple Silicon:

$ docker run -v "$PWD:/workdir" -u "$(id -u):$(id -g)" --rm -it --platform linux/amd64 ptspts/pdfsizeopt python -E -B -s -S -c "import sys; sys.path[0] = sys.argv[0] = sys.argv.pop(1); sys.path[-1] = sys.executable; import encodings; import m" /bin/pdfsizeopt deptest/deptest.pdf

Based on the workaround, I have updated the /bin/python program within the ptspts/pdfsizeopt Docker image so that now it works out-of-the box on Macs with Apple Silicon.

pripple commented 1 year ago

Thank you so much for resolving these issues! 🍻

I’ve been reading about your progress in my inbox with excitement, not having the knowledge or time to step in. I just tried the new binary install (without docker, as I wouldn’t need it for anything but pdfsizeopt) and the optimisation worked like a charm!

Best regards, Lorenz