Created
May 11, 2022 16:47
-
-
Save tsibley/bfcf8ccbac1a32f76b529a47de1d6fe6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This file defines how PyOxidizer application building and packaging is | |
| # performed. See PyOxidizer's documentation at | |
| # https://pyoxidizer.readthedocs.io/en/stable/ for details of this | |
| # configuration file format. | |
| # Define how to bundle a Python interpreter + our Python code + shared | |
| # libraries + other resources into an executable and adjacent filesystem "lib/" | |
| # tree. | |
| def make_exe(): | |
| # Obtain the default PythonDistribution for our build target. We link this | |
| # distribution into our produced executable and extract the Python standard | |
| # library from it. | |
| python_dist = default_python_distribution() | |
| # This function creates a `PythonPackagingPolicy` instance, which | |
| # influences how executables are built and how resources are added to the | |
| # executable. You can customize the default behavior by assigning to | |
| # attributes and calling functions. | |
| packaging_policy = python_dist.make_python_packaging_policy() | |
| # Emit both classified resources (PythonModuleSource, etc) and unclassified | |
| # "File" resources, but only include the former in packaging by default. | |
| # Allow "File" resource to be explicitly added on a case-by-case basis. | |
| # See also our exe_resource_policy_decision(). | |
| packaging_policy.file_scanner_classify_files = True | |
| packaging_policy.file_scanner_emit_files = True | |
| packaging_policy.include_classified_resources = True | |
| packaging_policy.include_file_resources = False | |
| packaging_policy.allow_files = True | |
| # Embed included resources in the executable by default when possible (e.g. | |
| # pure Python modules and data files). When not possible (e.g. compiled | |
| # extension modules) place them on the filesystem in a "lib/" directory | |
| # adjacent to the executable. | |
| packaging_policy.resources_location = "in-memory" | |
| packaging_policy.resources_location_fallback = "filesystem-relative:lib" | |
| # Invoke a function to make additional packaging decisions for each emitted | |
| # resource. | |
| packaging_policy.register_resource_callback(exe_resource_policy_decision) | |
| # Configuration of the embedded Python interpreter. | |
| python_config = python_dist.make_python_interpreter_config() | |
| python_config.run_module = "nextstrain.cli" | |
| # Produce a PythonExecutable from a Python distribution, embedded | |
| # resources, and other options. The returned object represents the | |
| # standalone executable that will be built. | |
| exe = python_dist.to_python_executable( | |
| name = "nextstrain", | |
| packaging_policy = packaging_policy, | |
| config = python_config) | |
| # Invoke `pip install` with our Python distribution to install a single | |
| # package. `pip_install()` returns objects representing installed files. | |
| # `add_python_resources()` adds these objects to the binary, with a load | |
| # location as defined by the packaging policy's resource location | |
| # attributes. | |
| exe.add_python_resources(exe.pip_install(["nextstrain-cli==3.2.0"])) | |
| return exe | |
| def exe_resource_policy_decision(policy, resource): | |
| # Some pure Python packages use __file__ to locate their resources (instead | |
| # of the importlib APIs) and thus cannot be embedded. Locate the modules | |
| # and data resources of these packages on the filesystem as well. | |
| pkgs_requiring_file = ["botocore", "boto3", "docutils.parsers.rst", "docutils.writers"] | |
| if type(resource) == "PythonModuleSource": | |
| if resource.name in pkgs_requiring_file or any([resource.name.startswith(p + ".") for p in pkgs_requiring_file]): | |
| resource.add_location = "filesystem-relative:lib" | |
| if type(resource) in ("PythonPackageResource", "PythonPackageDistributionResource"): | |
| if resource.package in pkgs_requiring_file or any([resource.package.startswith(p + ".") for p in pkgs_requiring_file]): | |
| resource.add_location = "filesystem-relative:lib" | |
| # We ignore most "unclassified" Files (above) since our config discovers | |
| # and emits *both* classified (PythonModuleSource, etc) and unclassified | |
| # resources (File) and we prefer the former. However, a libffi shared | |
| # object that ships with the Linux wheel for cffi doesn't get classified | |
| # and thus must be caught here as a plain File. | |
| if type(resource) == "File": | |
| if resource.path.startswith("cffi.libs/libffi"): | |
| print("Adding " + resource.path + " to bundle") | |
| resource.add_include = True | |
| resource.add_location = "filesystem-relative:lib" | |
| # Materialize all the installation artifacts for the executable + external | |
| # resources into a directory. | |
| def make_installation_artifacts(exe): | |
| files = FileManifest() | |
| files.add_python_resource(".", exe) | |
| return files | |
| register_target("exe", make_exe) | |
| register_target("installation-artifacts", make_installation_artifacts, depends=["exe"], default=True) | |
| resolve_targets() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment