From a7c6750917f5dc2e1eaf34520f7e6b0e3d5e0d3c Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Tue, 6 Jul 2021 14:13:51 +0200 Subject: [PATCH 1/2] dirty: build: Build Python packages using pip. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * guix/build/python-build-system.scm … --- guix/build/python-build-system.scm | 109 +++++++++++------------------ 1 file changed, 42 insertions(+), 67 deletions(-) diff --git a/guix/build/python-build-system.scm b/guix/build/python-build-system.scm index 8ade1d5911..e4b63e131e 100644 --- a/guix/build/python-build-system.scm +++ b/guix/build/python-build-system.scm @@ -109,30 +109,6 @@ ;; and the scripts defined in entry-points will always be created. -(define setuptools-shim - ;; Run setup.py with "setuptools" being imported, which will patch - ;; "distutils". This is needed for packages using "distutils" instead of - ;; "setuptools" since the former does not understand the - ;; "--single-version-externally-managed" flag. - ;; Python code taken from pip 9.0.1 pip/utils/setuptools_build.py - (string-append - "import setuptools, tokenize;__file__='setup.py';" - "f=getattr(tokenize, 'open', open)(__file__);" - "code=f.read().replace('\\r\\n', '\\n');" - "f.close();" - "exec(compile(code, __file__, 'exec'))")) - -(define (call-setuppy command params use-setuptools?) - (if (file-exists? "setup.py") - (begin - (format #t "running \"python setup.py\" with command ~s and parameters ~s~%" - command params) - (if use-setuptools? - (apply invoke "python" "-c" setuptools-shim - command params) - (apply invoke "python" "./setup.py" command params))) - (error "no setup.py found"))) - (define* (sanity-check #:key tests? inputs outputs #:allow-other-keys) "Ensure packages depending on this package via setuptools work properly, their advertised endpoints work and their top level modules are importable @@ -142,26 +118,6 @@ without errors." (with-directory-excursion "/tmp" (invoke "python" sanity-check.py (site-packages inputs outputs))))) -(define* (build #:key use-setuptools? #:allow-other-keys) - "Build a given Python package." - (call-setuppy "build" '() use-setuptools?) - #t) - -(define* (check #:key tests? test-target use-setuptools? #:allow-other-keys) - "Run the test suite of a given Python package." - (if tests? - ;; Running `setup.py test` creates an additional .egg-info directory in - ;; build/lib in some cases, e.g. if the source is in a sub-directory - ;; (given with `package_dir`). This will by copied to the output, too, - ;; so we need to remove. - (let ((before (find-files "build" "\\.egg-info$" #:directories? #t))) - (call-setuppy test-target '() use-setuptools?) - (let* ((after (find-files "build" "\\.egg-info$" #:directories? #t)) - (inter (lset-difference string=? after before))) - (for-each delete-file-recursively inter))) - (format #t "test suite not run~%")) - #t) - (define (python-version python) (let* ((version (last (string-split python #\-))) (components (string-split version #\.)) @@ -195,31 +151,40 @@ running checks after installing the package." "/bin:" (getenv "PATH")))) -(define* (install #:key inputs outputs (configure-flags '()) use-setuptools? +;; Some packages expect 'build and 'check exist. If they don’t replacing them +;; or adding phases before/after will fail. Preserve them as dummy-phases. +(define* (build #:key outputs (configure-flags '()) use-setuptools? + #:allow-other-keys) + #t) + +(define* (check #:key outputs (configure-flags '()) use-setuptools? + #:allow-other-keys) + #t) + +(define* (install #:key outputs (configure-flags '()) use-setuptools? #:allow-other-keys) "Install a given Python package." - (let* ((out (python-output outputs)) - (python (assoc-ref inputs "python")) - (major-minor (map string->number - (take (string-split (python-version python) #\.) 2))) - (<3.7? (match major-minor - ((major minor) - (or (< major 3) (and (= major 3) (< minor 7)))))) - (params (append (list (string-append "--prefix=" out) - "--no-compile") - (if use-setuptools? - ;; distutils does not accept these flags - (list "--single-version-externally-managed" - "--root=/") - '()) - configure-flags))) - (call-setuppy "install" params use-setuptools?) - ;; Rather than produce potentially non-reproducible .pyc files on Pythons - ;; older than 3.7, whose 'compileall' module lacks the - ;; '--invalidation-mode' option, do not generate any. - (unless <3.7? - (invoke "python" "-m" "compileall" "--invalidation-mode=unchecked-hash" - out)))) + (let* ((out (assoc-ref outputs "out"))) + (setenv "HOME" "/tmp") ; silence warning + (invoke "pip" "install" + (string-append "--prefix=" out) + "--root=/" + ;; Hide pip’s own version check. Nothing we can do anyway. + "--disable-pip-version-check" + ;; Do not search and install dependencies. + "--no-deps" + ;; Do not search PyPi. + "--no-index" + ;; Don’t reinstall build dependencies into virtal environent, + ;; instead use local ones. Otherwise build process will fail + ;; finding dependencies. + "--no-build-isolation" + ;; Ignore installed packages, important for packages bundled by + ;; Python, like setuptools. + "--ignore-installed" + ;; Library is in the current directory. + ".") + #t)) (define* (wrap #:key inputs outputs #:allow-other-keys) (define (list-of-files dir) @@ -267,6 +232,15 @@ installed with setuptools." (utime file early-1980 early-1980)) #t)))) +;; python-wheel respects this virable and passes an invalid early timestamp to +;; Python’s zip module if not redefined to a later date. +(define* (set-SOURCE-DATE-EPOCH #:rest _) + "Set the 'SOURCE_DATE_EPOCH' environment variable. This is used by tools +that incorporate timestamps as a way to tell them to use a fixed timestamp. +See https://reproducible-builds.org/specs/source-date-epoch/." + (setenv "SOURCE_DATE_EPOCH" "315619200") + #t) + (define* (enable-bytecode-determinism #:rest _) "Improve determinism of pyc files." ;; Use deterministic hashes for strings, bytes, and datetime objects. @@ -297,6 +271,7 @@ by Cython." enable-bytecode-determinism) (add-after 'enable-bytecode-determinism 'ensure-no-cythonized-files ensure-no-cythonized-files) + (replace 'set-SOURCE-DATE-EPOCH set-SOURCE-DATE-EPOCH) (delete 'bootstrap) (delete 'configure) ;not needed (replace 'build build) -- 2.31.1