mirror of
https://github.com/ryanvolz/radioconda.git
synced 2024-11-08 10:26:08 -05:00
Initial radioconda env file and render/build scripts.
This commit is contained in:
commit
d01cf91e82
140
.gitignore
vendored
Normal file
140
.gitignore
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
.vscode/
|
35
LICENSE
Normal file
35
LICENSE
Normal file
@ -0,0 +1,35 @@
|
||||
Radioconda installer code uses BSD-3-Clause license as stated below.
|
||||
Binary packages that come with radioconda have their own licensing terms
|
||||
and by installing radioconda you agree to the licensing terms of individual
|
||||
packages as well. These additional licenses can be found in the
|
||||
pkgs/<pkg-name>/info/licenses folder of your radioconda installation.
|
||||
|
||||
=============================================================================
|
||||
|
||||
Copyright (c) 2021, Ryan Volz
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
78
build_installer.py
Executable file
78
build_installer.py
Executable file
@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
import pathlib
|
||||
import re
|
||||
|
||||
platform_re = re.compile("^.*-(?P<platform>[(?:linux)(?:osx)(?:win)].*)$")
|
||||
|
||||
|
||||
def spec_dir_extract_platform(installer_spec_dir: pathlib.Path) -> str:
|
||||
spec_dir_name = installer_spec_dir.name
|
||||
|
||||
platform_match = platform_re.match(spec_dir_name)
|
||||
|
||||
if platform_match:
|
||||
return platform_match.group("platform")
|
||||
else:
|
||||
raise ValueError(
|
||||
f"Could not identify platform from directory name: {spec_dir_name}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from constructor import main as constructor_main
|
||||
|
||||
platform = constructor_main.cc_platform
|
||||
cwd = pathlib.Path(".").absolute()
|
||||
here = pathlib.Path(__file__).parent.absolute().relative_to(cwd)
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Build installer package(s) using conda constructor."
|
||||
" Additional command-line options will be passed to constructor."
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"installer_spec_dir",
|
||||
type=pathlib.Path,
|
||||
nargs="?",
|
||||
default=here / "installer_specs" / f"radioconda-{platform}",
|
||||
help=(
|
||||
"Installer specification directory (containing construct.yaml)"
|
||||
" for a particular platform (name ends in the platform identifier)."
|
||||
" (default: %(default)s)"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--output_dir",
|
||||
type=pathlib.Path,
|
||||
default=here / "dist",
|
||||
help=(
|
||||
"Output directory in which the installer package(s) will be placed."
|
||||
" (default: %(default)s)"
|
||||
),
|
||||
)
|
||||
|
||||
args, constructor_args = parser.parse_known_args()
|
||||
|
||||
platform = spec_dir_extract_platform(args.installer_spec_dir)
|
||||
|
||||
constructor_cmdline = [
|
||||
"constructor",
|
||||
args.installer_spec_dir,
|
||||
"--platform",
|
||||
platform,
|
||||
"--output-dir",
|
||||
args.output_dir,
|
||||
] + constructor_args
|
||||
|
||||
proc = subprocess.run(constructor_cmdline)
|
||||
|
||||
try:
|
||||
proc.check_returncode()
|
||||
except subprocess.CalledProcessError:
|
||||
sys.exit(1)
|
29
radioconda.yaml
Normal file
29
radioconda.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
name: radioconda
|
||||
channels:
|
||||
- conda-forge
|
||||
platforms:
|
||||
- linux-64
|
||||
- osx-64
|
||||
- win-64
|
||||
dependencies:
|
||||
- mamba
|
||||
- python
|
||||
|
||||
- digital_rf
|
||||
- gnuradio
|
||||
- gnuradio-osmosdr
|
||||
- gnuradio-satellites
|
||||
- gnuradio-soapy
|
||||
- gqrx
|
||||
- libiio
|
||||
#- libm2k
|
||||
- limesuite
|
||||
- pyadi-iio
|
||||
- rtl-sdr
|
||||
- soapysdr
|
||||
- soapysdr-module-lms7
|
||||
- soapysdr-module-plutosdr
|
||||
- soapysdr-module-remote
|
||||
- soapysdr-module-rtlsdr
|
||||
- soapysdr-module-uhd
|
||||
- uhd
|
187
rerender.py
Executable file
187
rerender.py
Executable file
@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env python3
|
||||
import pathlib
|
||||
import shutil
|
||||
|
||||
import conda_lock
|
||||
import yaml
|
||||
|
||||
|
||||
def render_lock_spec(
|
||||
lock_spec: conda_lock.src_parser.LockSpecification, conda_exe: str
|
||||
) -> conda_lock.src_parser.LockSpecification:
|
||||
create_env_dict = conda_lock.conda_lock.solve_specs_for_arch(
|
||||
conda=conda_exe,
|
||||
channels=lock_spec.channels,
|
||||
specs=lock_spec.specs,
|
||||
platform=lock_spec.platform,
|
||||
)
|
||||
pkgs = create_env_dict["actions"]["LINK"]
|
||||
spec_names = set(
|
||||
spec.split(sep=None, maxsplit=1)[0].split(sep="=", maxsplit=1)[0]
|
||||
for spec in lock_spec.specs
|
||||
)
|
||||
|
||||
rendered_specs = []
|
||||
for pkg in pkgs:
|
||||
if pkg["name"] in spec_names:
|
||||
rendered_specs.append("{name}={version}={build_string}".format(**pkg))
|
||||
|
||||
rendered_lock_spec = conda_lock.src_parser.LockSpecification(
|
||||
specs=sorted(rendered_specs),
|
||||
channels=lock_spec.channels,
|
||||
platform=lock_spec.platform,
|
||||
)
|
||||
|
||||
return rendered_lock_spec
|
||||
|
||||
|
||||
def render_constructor_specs(
|
||||
environment_file: pathlib.Path,
|
||||
version: str,
|
||||
company: str,
|
||||
license_file: pathlib.Path,
|
||||
output_dir: pathlib.Path,
|
||||
conda_exe: str,
|
||||
) -> dict:
|
||||
with environment_file.open("r") as f:
|
||||
env_yaml_data = yaml.safe_load(f)
|
||||
|
||||
installer_name = env_yaml_data["name"]
|
||||
platforms = env_yaml_data["platforms"]
|
||||
|
||||
if not license_file.exists():
|
||||
raise ValueError(f"Cannot find license file: {license_file}")
|
||||
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
constructor_specs = {}
|
||||
|
||||
for platform in platforms:
|
||||
constructor_name = f"{installer_name}-{platform}"
|
||||
|
||||
lock_spec = conda_lock.conda_lock.parse_environment_file(
|
||||
environment_file=environment_file, platform=platform
|
||||
)
|
||||
rendered_lock_spec = render_lock_spec(lock_spec, conda_exe)
|
||||
construct_dict = dict(
|
||||
name=installer_name,
|
||||
version=version,
|
||||
company=company,
|
||||
channels=rendered_lock_spec.channels,
|
||||
specs=rendered_lock_spec.specs,
|
||||
initialize_by_default=True,
|
||||
installer_type="all",
|
||||
keep_pkgs=True,
|
||||
license_file="LICENSE",
|
||||
register_python_default=False,
|
||||
write_condarc=True,
|
||||
)
|
||||
if platform.startswith("win"):
|
||||
construct_dict["post_install"] = "post_install.bat"
|
||||
else:
|
||||
construct_dict["post_install"] = "post_install.sh"
|
||||
|
||||
constructor_specs[constructor_name] = construct_dict
|
||||
|
||||
constructor_dir = output_dir / constructor_name
|
||||
if constructor_dir.exists():
|
||||
shutil.rmtree(constructor_dir)
|
||||
constructor_dir.mkdir(parents=True)
|
||||
|
||||
# copy license to the constructor directory
|
||||
shutil.copy(license_file, constructor_dir / "LICENSE")
|
||||
|
||||
# write the post_install scripts referenced in the construct dict
|
||||
if platform.startswith("win"):
|
||||
with (constructor_dir / "post_install.bat").open("w") as f:
|
||||
f.writelines((r"del /q %PREFIX%\pkgs\*.tar.bz2", ""))
|
||||
else:
|
||||
with (constructor_dir / "post_install.sh").open("w") as f:
|
||||
f.writelines((r"rm -f $PREFIX/pkgs/*.tar.bz2", ""))
|
||||
|
||||
construct_yaml_path = constructor_dir / "construct.yaml"
|
||||
with construct_yaml_path.open("w") as f:
|
||||
yaml.safe_dump(construct_dict, stream=f)
|
||||
|
||||
return constructor_specs
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
import datetime
|
||||
|
||||
here = pathlib.Path(__file__).parent.relative_to("")
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Re-render installer specification directories to be used by conda"
|
||||
" constructor."
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"environment_file",
|
||||
type=pathlib.Path,
|
||||
nargs="?",
|
||||
default=here / "radioconda.yaml",
|
||||
help=(
|
||||
"YAML file defining an installer distribution, with a 'name' string and"
|
||||
" 'channels', 'platforms', and 'dependencies' lists."
|
||||
" (default: %(default)s)"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--company",
|
||||
type=str,
|
||||
default="github.com/ryanvolz/radioconda",
|
||||
help=(
|
||||
"Name of the company/entity who is responsible for the installer."
|
||||
" (default: %(default)s)"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--license_file",
|
||||
type=pathlib.Path,
|
||||
default=here / "LICENSE",
|
||||
help=(
|
||||
"File containing the license that applies to the installer."
|
||||
" (default: %(default)s)"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--output_dir",
|
||||
type=pathlib.Path,
|
||||
default=here / "installer_specs",
|
||||
help=(
|
||||
"Output directory in which the installer specifications will be rendered."
|
||||
" (default: %(default)s)"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--conda-exe",
|
||||
type=str,
|
||||
default=None,
|
||||
help=(
|
||||
"Path to the conda (or mamba or micromamba) executable to use."
|
||||
" (default: search for conda/mamba/micromamba)"
|
||||
),
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
conda_exe = conda_lock.conda_lock.determine_conda_executable(
|
||||
conda_executable=args.conda_exe, mamba=True, micromamba=True
|
||||
)
|
||||
|
||||
dt = datetime.datetime.now()
|
||||
version = dt.strftime("%Y.%m.%d")
|
||||
|
||||
constructor_specs = render_constructor_specs(
|
||||
environment_file=args.environment_file,
|
||||
version=version,
|
||||
company=args.company,
|
||||
license_file=args.license_file,
|
||||
output_dir=args.output_dir,
|
||||
conda_exe=conda_exe,
|
||||
)
|
Loading…
Reference in New Issue
Block a user