diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8aea933..be891d7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -55,7 +55,7 @@ jobs: run: | MATRIX_INCLUDE=$( { - cibuildwheel --print-build-identifiers --platform linux --arch x86_64,aarch64,i686 | grep cp | jq -nRc '{"only": inputs, "os": "ubuntu-latest"}' \ + cibuildwheel --print-build-identifiers --platform linux --arch all | grep cp | jq -nRc '{"only": inputs, "os": "ubuntu-latest"}' \ && cibuildwheel --print-build-identifiers --platform macos --arch x86_64 | grep cp | jq -nRc '{"only": inputs, "os": "macos-13"}' \ && cibuildwheel --print-build-identifiers --platform macos --arch arm64 | grep cp | jq -nRc '{"only": inputs, "os": "macos-14"}' \ && cibuildwheel --print-build-identifiers --platform windows --arch x86,AMD64 | grep cp | jq -nRc '{"only": inputs, "os": "windows-latest"}' @@ -89,20 +89,8 @@ jobs: only: ${{ matrix.only }} env: CIBW_BUILD_VERBOSITY: 1 - CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 - CIBW_MANYLINUX_PYPY_X86_64_IMAGE: manylinux_2_28 - CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28 - CIBW_MANYLINUX_PPC64LE_IMAGE: manylinux_2_28 - CIBW_MANYLINUX_S390X_IMAGE: manylinux_2_28 - CIBW_MANYLINUX_PYPY_AARCH64_IMAGE: manylinux_2_28 - CIBW_MANYLINUX_PYPY_I686_IMAGE: manylinux_2_28 - CIBW_MUSLLINUX_X86_64_IMAGE: musllinux_1_2 - CIBW_MUSLLINUX_I686_IMAGE: musllinux_1_2 - CIBW_MUSLLINUX_AARCH64_IMAGE: musllinux_1_2 - CIBW_MUSLLINUX_PPC64LE_IMAGE: musllinux_1_2 - CIBW_MUSLLINUX_S390X_IMAGE: musllinux_1_2 - CIBW_BEFORE_BUILD: bash -c "make install_libmagic" - CIBW_TEST_COMMAND: python -c "import magic; assert magic.Magic(mime=True).from_buffer(b'\x00\x00\x00\x1cftypisom\x00\x00\x02\x00isomiso2mp41\x00') == 'video/mp4'" + CIBW_BEFORE_BUILD: bash "add_libmagic.sh" + CIBW_TEST_COMMAND: python -c "import magic; assert magic.Magic(mime=True).from_buffer(b'\x00\x00\x00\x1cftypiso5\x00\x00\x00\x01isomiso5hlsf\x00\x00') == 'video/mp4'" - uses: actions/upload-artifact@v4 with: diff --git a/Makefile b/Makefile deleted file mode 100644 index 0f524b7..0000000 --- a/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -SHELL := /bin/bash - -.PHONY: install_libmagic -## Install libmagic -install_libmagic: - # Mac https://formulae.brew.sh/formula/libmagic - # Debian https://packages.ubuntu.com/libmagic1 - # Alpine https://pkgs.alpinelinux.org/package/libmagic - # RHEL https://git.almalinux.org/rpms/file - # Windows https://github.com/julian-r/file-windows - ( ( ( \ - brew install libmagic \ - || ( apt-get update && apt-get install -y libmagic1 ) ) \ - || apk add --update libmagic ) \ - || yum install file-libs ) \ - || ( python -c 'import platform, sysconfig, io, zipfile, urllib.request; assert platform.system() == "Windows"; machine = "x86" if sysconfig.get_platform() == "win32" else "x64"; print(machine); zipfile.ZipFile(io.BytesIO(urllib.request.urlopen(f"https://github.com/julian-r/file-windows/releases/download/v5.44/file_5.44-build104-vs2022-{machine}.zip").read())).extractall(".")' && ls -ltra ) - # on cibuildwheel, the lib needs to exist in the project before running setup.py - # copy lib into the magic dir, regardless of platform - python -c "import subprocess; from magic.loader import load_lib; lib = load_lib()._name; print(f'linking {lib}'); subprocess.check_call(['cp', lib, 'magic'])" - # only on linux: additionally copy compiled db into magic dir - cp /usr/share/misc/magic.mgc magic || true - # check what was copied - ls -ltra magic - -.DEFAULT_GOAL := help -.PHONY: help -## Print Makefile documentation -help: - @perl -0 -nle 'printf("\033[36m %-15s\033[0m %s\n", "$$2", "$$1") while m/^##\s*([^\r\n]+)\n^([\w.-]+):[^=]/gm' $(MAKEFILE_LIST) | sort diff --git a/add_libmagic.sh b/add_libmagic.sh new file mode 100755 index 0000000..7db7b17 --- /dev/null +++ b/add_libmagic.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +install_source() { + version="file-5.45" + ( + tmpfile="$(mktemp)" && + curl -sSLo "${tmpfile}" "https://astron.com/pub/file/${version}.tar.gz" && + tar xvf "${tmpfile}" && + cd "${version}" && + ./configure && + make && + make install && + make installcheck && + cd .. && + rm -r "${version}" + ) || (cd .. && rm -r "${version}" && false) +} + +install_precompiled() { + # Mac https://formulae.brew.sh/formula/libmagic + # Debian https://packages.ubuntu.com/libmagic1 + # Alpine https://pkgs.alpinelinux.org/package/libmagic + # RHEL https://git.almalinux.org/rpms/file + # Windows https://github.com/julian-r/file-windows + if [ -n "$(which brew)" ]; then + brew install libmagic + elif [ -n "$(which apt-get)" ]; then + apt-get update + apt-get install -y libmagic1 + elif [ -n "$(which apk)" ]; then + apk add --update libmagic + elif [ -n "$(which yum)" ]; then + yum install file-libs + else + python -c 'import platform, sysconfig, io, zipfile, urllib.request; assert platform.system() == "Windows"; machine = "x86" if sysconfig.get_platform() == "win32" else "x64"; print(machine); zipfile.ZipFile(io.BytesIO(urllib.request.urlopen(f"https://github.com/julian-r/file-windows/releases/download/v5.44/file_5.44-build104-vs2022-{machine}.zip").read())).extractall(".")' && + ls -ltra + fi +} + +copy_libmagic() { + # on cibuildwheel, the lib needs to exist in the project before running setup.py + # copy lib into the magic dir, regardless of platform + libmagic_path="$(python -c 'from magic.loader import load_lib; print(load_lib()._name)')" && + cp "${libmagic_path}" "magic" && + # only on linux: additionally copy compiled db into magic dir + ( ( cp "/usr/local/share/misc/magic.mgc" "magic" || cp "/usr/share/misc/magic.mgc" "magic" ) || true ) && + # check what was copied + ls -ltra magic +} + +install_source || install_precompiled +copy_libmagic diff --git a/magic/loader.py b/magic/loader.py index 5150107..3778fde 100644 --- a/magic/loader.py +++ b/magic/loader.py @@ -39,6 +39,7 @@ def _lib_candidates(): for i in prefixes: yield os.path.join(here, i) yield os.path.join(os.path.abspath('.'), i) + yield os.path.join('/usr/local/lib', i) # on some linux systems (musl/alpine), find_library('magic') returns None # first try ldconfig with backup string in case of error yield subprocess.check_output(