You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
6.9 KiB

4 years ago
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import
  3. import logging
  4. import os
  5. from pip._internal.cache import WheelCache
  6. from pip._internal.cli import cmdoptions
  7. from pip._internal.cli.base_command import RequirementCommand
  8. from pip._internal.exceptions import CommandError, PreviousBuildDirError
  9. from pip._internal.operations.prepare import RequirementPreparer
  10. from pip._internal.req import RequirementSet
  11. from pip._internal.req.req_tracker import RequirementTracker
  12. from pip._internal.resolve import Resolver
  13. from pip._internal.utils.temp_dir import TempDirectory
  14. from pip._internal.wheel import WheelBuilder
  15. logger = logging.getLogger(__name__)
  16. class WheelCommand(RequirementCommand):
  17. """
  18. Build Wheel archives for your requirements and dependencies.
  19. Wheel is a built-package format, and offers the advantage of not
  20. recompiling your software during every install. For more details, see the
  21. wheel docs: https://wheel.readthedocs.io/en/latest/
  22. Requirements: setuptools>=0.8, and wheel.
  23. 'pip wheel' uses the bdist_wheel setuptools extension from the wheel
  24. package to build individual wheels.
  25. """
  26. name = 'wheel'
  27. usage = """
  28. %prog [options] <requirement specifier> ...
  29. %prog [options] -r <requirements file> ...
  30. %prog [options] [-e] <vcs project url> ...
  31. %prog [options] [-e] <local project path> ...
  32. %prog [options] <archive url/path> ..."""
  33. summary = 'Build wheels from your requirements.'
  34. def __init__(self, *args, **kw):
  35. super(WheelCommand, self).__init__(*args, **kw)
  36. cmd_opts = self.cmd_opts
  37. cmd_opts.add_option(
  38. '-w', '--wheel-dir',
  39. dest='wheel_dir',
  40. metavar='dir',
  41. default=os.curdir,
  42. help=("Build wheels into <dir>, where the default is the "
  43. "current working directory."),
  44. )
  45. cmd_opts.add_option(cmdoptions.no_binary())
  46. cmd_opts.add_option(cmdoptions.only_binary())
  47. cmd_opts.add_option(cmdoptions.prefer_binary())
  48. cmd_opts.add_option(
  49. '--build-option',
  50. dest='build_options',
  51. metavar='options',
  52. action='append',
  53. help="Extra arguments to be supplied to 'setup.py bdist_wheel'.",
  54. )
  55. cmd_opts.add_option(cmdoptions.no_build_isolation())
  56. cmd_opts.add_option(cmdoptions.constraints())
  57. cmd_opts.add_option(cmdoptions.editable())
  58. cmd_opts.add_option(cmdoptions.requirements())
  59. cmd_opts.add_option(cmdoptions.src())
  60. cmd_opts.add_option(cmdoptions.ignore_requires_python())
  61. cmd_opts.add_option(cmdoptions.no_deps())
  62. cmd_opts.add_option(cmdoptions.build_dir())
  63. cmd_opts.add_option(cmdoptions.progress_bar())
  64. cmd_opts.add_option(
  65. '--global-option',
  66. dest='global_options',
  67. action='append',
  68. metavar='options',
  69. help="Extra global options to be supplied to the setup.py "
  70. "call before the 'bdist_wheel' command.")
  71. cmd_opts.add_option(
  72. '--pre',
  73. action='store_true',
  74. default=False,
  75. help=("Include pre-release and development versions. By default, "
  76. "pip only finds stable versions."),
  77. )
  78. cmd_opts.add_option(cmdoptions.no_clean())
  79. cmd_opts.add_option(cmdoptions.require_hashes())
  80. index_opts = cmdoptions.make_option_group(
  81. cmdoptions.index_group,
  82. self.parser,
  83. )
  84. self.parser.insert_option_group(0, index_opts)
  85. self.parser.insert_option_group(0, cmd_opts)
  86. def run(self, options, args):
  87. cmdoptions.check_install_build_global(options)
  88. index_urls = [options.index_url] + options.extra_index_urls
  89. if options.no_index:
  90. logger.debug('Ignoring indexes: %s', ','.join(index_urls))
  91. index_urls = []
  92. if options.build_dir:
  93. options.build_dir = os.path.abspath(options.build_dir)
  94. options.src_dir = os.path.abspath(options.src_dir)
  95. with self._build_session(options) as session:
  96. finder = self._build_package_finder(options, session)
  97. build_delete = (not (options.no_clean or options.build_dir))
  98. wheel_cache = WheelCache(options.cache_dir, options.format_control)
  99. with RequirementTracker() as req_tracker, TempDirectory(
  100. options.build_dir, delete=build_delete, kind="wheel"
  101. ) as directory:
  102. requirement_set = RequirementSet(
  103. require_hashes=options.require_hashes,
  104. )
  105. try:
  106. self.populate_requirement_set(
  107. requirement_set, args, options, finder, session,
  108. self.name, wheel_cache
  109. )
  110. preparer = RequirementPreparer(
  111. build_dir=directory.path,
  112. src_dir=options.src_dir,
  113. download_dir=None,
  114. wheel_download_dir=options.wheel_dir,
  115. progress_bar=options.progress_bar,
  116. build_isolation=options.build_isolation,
  117. req_tracker=req_tracker,
  118. )
  119. resolver = Resolver(
  120. preparer=preparer,
  121. finder=finder,
  122. session=session,
  123. wheel_cache=wheel_cache,
  124. use_user_site=False,
  125. upgrade_strategy="to-satisfy-only",
  126. force_reinstall=False,
  127. ignore_dependencies=options.ignore_dependencies,
  128. ignore_requires_python=options.ignore_requires_python,
  129. ignore_installed=True,
  130. isolated=options.isolated_mode,
  131. )
  132. resolver.resolve(requirement_set)
  133. # build wheels
  134. wb = WheelBuilder(
  135. finder, preparer, wheel_cache,
  136. build_options=options.build_options or [],
  137. global_options=options.global_options or [],
  138. no_clean=options.no_clean,
  139. )
  140. wheels_built_successfully = wb.build(
  141. requirement_set.requirements.values(), session=session,
  142. )
  143. if not wheels_built_successfully:
  144. raise CommandError(
  145. "Failed to build one or more wheels"
  146. )
  147. except PreviousBuildDirError:
  148. options.no_clean = True
  149. raise
  150. finally:
  151. if not options.no_clean:
  152. requirement_set.cleanup_files()
  153. wheel_cache.cleanup()