Skip to content

Commit

Permalink
tidying API
Browse files Browse the repository at this point in the history
  • Loading branch information
gilesknap committed Sep 29, 2023
1 parent 519f403 commit 4e9712e
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 77 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,10 @@
"source.organizeImports.ruff": true,
"source.black": true,
}
},
"workbench.colorCustomizations": {
"activityBar.background": "#01333D",
"titleBar.activeBackground": "#014756",
"titleBar.activeForeground": "#F1FDFF"
}
}
10 changes: 0 additions & 10 deletions config/st.cmd

This file was deleted.

2 changes: 0 additions & 2 deletions src/ibek/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@
# global MODULES file used to determine order of build
MODULES = SUPPORT / "configure/MODULES"

# Folder containing Makefile.jinja
MAKE_FOLDER = IOC_FOLDER / "iocApp/src"
# Folder containing templates for IOC src etc.
TEMPLATES = Path(__file__).parent / "templates"
# Folder containing symlinks to useful files
Expand Down
26 changes: 22 additions & 4 deletions src/ibek/ioc_cmds/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@
from ibek.globals import EPICS_ROOT, IOC_FOLDER, SYMLINKS


def get_ioc_src():
"""
The generic ioc source folder is mounted into the container at
/epics/ioc-XXXXX and should always contain the ibek-support
submodule. Therefore we can find the ibek-support folder by looking
for the ibek-support folder.
Functions that use this should provide an override variable that allows
the ibek caller to specify the location.
"""
try:
ibek_support = list(EPICS_ROOT.glob("*/ibek-support"))[0]
except IndexError:
raise RuntimeError(
f"Could not find ibek-support in {EPICS_ROOT}."
"ibek should be run from inside a container with"
"a generic ioc source folder mounted at /epics/ioc-XXXXX"
)
return (ibek_support / "..").resolve()


def move_file(src: Path, dest: Path, binary: List[str]):
"""
Move a file / tree / symlink from src to dest, stripping symbols from
Expand Down Expand Up @@ -37,10 +58,7 @@ def extract_assets(destination: Path, source: Path, extras: List[Path], defaults
"""
asset_matches = "bin|configure|db|dbd|include|lib|template|config|*.sh"

try:
ibek_support = list(EPICS_ROOT.glob("*/ibek-support"))[0]
except IndexError:
raise RuntimeError(f"Could not find ibek-support in {EPICS_ROOT}")
ibek_support = get_ioc_src()

just_copy = (
[
Expand Down
52 changes: 35 additions & 17 deletions src/ibek/ioc_cmds/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,33 @@
IOC_DBDS,
IOC_FOLDER,
IOC_LIBS,
MAKE_FOLDER,
TEMPLATES,
NaturalOrderGroup,
)
from ibek.ioc_cmds.docker import build_dockerfile

from .assets import extract_assets
from .assets import extract_assets, get_ioc_src

ioc_cli = typer.Typer(cls=NaturalOrderGroup)


@ioc_cli.command()
def generate_makefile() -> None:
def generate_makefile(
folder_override: Annotated[
Optional[Path],
typer.Option(
help="Where to find the Makefile.jinja template.",
),
] = None
):
"""
get the dbd and lib files from all support modules and generate
iocApp/src/Makefile from iocApp/src/Makefile.jinja
"""

# Folder containing Makefile.jinja
make_folder = folder_override or get_ioc_src() / "ioc/iocApp/src"

# get all the dbd and lib files gathered from each support module
dbds: List[str] = []
libs: List[str] = []
Expand All @@ -38,12 +48,12 @@ def generate_makefile() -> None:
libs = [lib.strip() for lib in IOC_LIBS.read_text().split()]

# generate the Makefile from the template
template = Template((MAKE_FOLDER / "Makefile.jinja").read_text())
template = Template((make_folder / "Makefile.jinja").read_text())
# libraries are listed in reverse order of dependency
libs.reverse()
text = template.render(dbds=dbds, libs=libs)

with (MAKE_FOLDER / "Makefile").open("w") as stream:
with (make_folder / "Makefile").open("w") as stream:
stream.write(text)


Expand All @@ -58,6 +68,11 @@ def compile(
"""
path = IOC_FOLDER

# for developer convenience in a devcontainer we also call the idempotent
# functions that compile requires
make_source_template()
generate_makefile()

command = f"make -C {path} -j $(nproc) " + " ".join(ctx.args)
exit(subprocess.call(["bash", "-c", command]))

Expand Down Expand Up @@ -100,7 +115,7 @@ def generate_schema(
ioc_model = ioc_create_model(definitions)
schema = json.dumps(ioc_model.model_json_schema(), indent=2)
if output is None:
print(schema)
typer.echo(schema)
else:
output.write_text(schema)

Expand Down Expand Up @@ -130,22 +145,25 @@ def extract_runtime_assets(

@ioc_cli.command()
def make_source_template(
destination: Path = typer.Argument(
Path.cwd().parent / "ioc",
help="The root folder in which to place the IOC boilerplate",
)
destination: Annotated[
Optional[Path],
typer.Option(
help="Where to make the ioc folder. Defaults to under the "
"generic IOC source folder",
),
] = None
):
"""
Create a new IOC boilerplate source tree in the given folder.
Default is ../ioc. Typically call this when CWD is
<generic_ioc_root>/ibek-support as this is the standard
Dockerfile WORKDIR.
Default is ioc source repo / ioc .
"""
if destination.exists():
typer.echo(f"{destination} IOC source exists, skipping ...")
else:
if destination is None:
destination = get_ioc_src() / "ioc"

if not destination.exists():
if destination.is_symlink():
destination.unlink()
shutil.copytree(TEMPLATES / "ioc", destination)
typer.echo(f"Created IOC source tree in {destination}")

try:
IOC_FOLDER.unlink(missing_ok=True)
Expand Down
25 changes: 16 additions & 9 deletions src/ibek/support_cmds/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

import typer

from ibek.ioc_cmds.assets import get_ioc_src

try:
from git import Repo
except ImportError:
print("Git Python is not needed for runtime ibek usage")
pass # Git Python is not needed for runtime (container build time only)

from typing_extensions import Annotated

Expand Down Expand Up @@ -229,24 +231,29 @@ def compile(

@support_cli.command()
def generate_links(
module: str = typer.Argument(..., help="support module name"),
ibek_support: Annotated[
Path, typer.Option(help="Filepath to ibek-support root")
] = Path.cwd(),
Optional[Path],
typer.Option(
help="Filepath to ibek-support root"
"defaults to <generic IOC source folder>/ibek-support"
),
] = None,
):
"""
generate symlinks to the bob, pvi and support YAML for a compiled IOC
"""
# symlink the support YAML
from_path = ibek_support / module
support_yaml = from_path.glob("*.ibek.support.yaml")
print(f"looking for some support YAML in {ibek_support}, found {support_yaml}")
from_path = ibek_support or get_ioc_src() / "ibek-support"

support_yaml = from_path.glob("*/*.ibek.support.yaml")

to_path = SYMLINKS / "ibek"
to_path.mkdir(parents=True, exist_ok=True)
for yaml in support_yaml:
link_from = to_path / yaml.name
link_from.unlink(missing_ok=True)
typer.echo(f"symlinking {yaml} to {to_path}")
(to_path / yaml.name).symlink_to(yaml)
link_from.symlink_to(yaml)

# symlink the bob YAML
# TODO TODO
Expand All @@ -261,6 +268,6 @@ def generate_schema(
):
"""Produce JSON global schema for all <support_module>.ibek.support.yaml files"""
if output is None:
print(Support.get_schema())
typer.echo(Support.get_schema())
else:
output.write_text(Support.get_schema())
14 changes: 7 additions & 7 deletions src/ibek/templates/ioc/config/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ Launch this Generic IOC with configuration folder mounted over
Choices of contents of the config folder are:
1. start.sh ******************************************************************
If the config folder contains a start.sh script it will be executed.
This allows the instance implementer to provide a conmpletely custom
startup script.
2. ioc.yaml *************************************************************
1. ioc.yaml *************************************************************
If the config folder contains an ioc.yaml file we invoke the ibek tool to
generate the startup script and database. Then launch with the generated
startup script.
3. st.cmd + ioc.subst *********************************************************
2. st.cmd + ioc.subst *********************************************************
If the config folder contains a st.cmd script and a ioc.subst file then
optionally generate ioc.db from the ioc.subst file and use the st.cmd script
as the IOC startup script. Note that the expanded database file will
be generated in /tmp/ioc.db
3. start.sh ******************************************************************
If the config folder contains a start.sh script it will be executed.
This allows the instance implementer to provide a conmpletely custom
startup script.
4. empty config folder *******************************************************
If the config folder is empty the default startup script prints the message
you are reading now.
Expand Down
50 changes: 22 additions & 28 deletions src/ibek/templates/ioc/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,25 @@
# Here we support the following set of options for the contents of
# the config folder:
#
# 1. start.sh ******************************************************************
# If the config folder contains a start.sh script it will be executed.
# This allows the instance implementer to provide a conmpletely custom
# startup script.
#
# 2. ioc.yaml *************************************************************
# 1. ioc.yaml *************************************************************
# If the config folder contains an ioc.yaml file we invoke the ibek tool to
# generate the startup script and database. Then launch with the generated
# startup script.
#
# 3. st.cmd + ioc.subst *********************************************************
# 2. st.cmd + ioc.subst *********************************************************
# If the config folder contains a st.cmd script and a ioc.subst file then
# optionally generate ioc.db from the ioc.subst file and use the st.cmd script
# as the IOC startup script. Note that the expanded database file will
# be generated in /tmp/ioc.db
#
# 3. start.sh ******************************************************************
# If the config folder contains a start.sh script it will be executed.
# This allows the instance implementer to provide a conmpletely custom
# startup script.
#
# 4. empty config folder *******************************************************
# If the config folder is empty then this IOC will launch the example in
# ./example folder
# If the config folder is empty the default script that prints a message
# will run
#
# RTEMS IOCS - RTEMS IOC startup files can be generated using 2,3,4 above. For
# RTEMS we do not execute the ioc inside of the pod. Instead we:
Expand Down Expand Up @@ -65,42 +65,36 @@ ioc_startup=${CONFIG_DIR}/st.cmd
epics_db=/tmp/ioc.db


# 1. start.sh ******************************************************************

if [ -f ${override} ]; then
exec bash ${override}

elif [ -f ${ibek_src} ]; then
# 2. ioc.yaml ******************************************************************

# 1. ioc.yaml ******************************************************************
if [ -f ${ibek_src} ]; then

# Database generation script generated by ibek
db_src=/tmp/ioc.subst
final_ioc_startup=/tmp/st.cmd

# get ibek the support yaml files this ioc's support modules
defs=/workspaces/*/ibek-support/*/*.ibek.support.yaml
defs=/epics/links/ibek/*.ibek.support.yaml
ibek startup generate ${ibek_src} ${defs} --out ${final_ioc_startup} --db-out ${db_src}

# build expanded database using msi
if [ -f ${db_src} ]; then
includes=$(for i in ${SUPPORT}/*/db; do echo -n "-I $i "; done)
bash -c "msi -o${epics_db} ${includes} -S${db_src}"
fi
# 3. st.cmd + ioc.substitutions ************************************************
elif [ -f ${ioc_startup} ] ; then

# 2. st.cmd + ioc.substitutions ************************************************
elif [ -f ${ioc_startup} ] ; then

if [ -f ${CONFIG_DIR}/ioc.substitutions ]; then
# generate ioc.db from ioc.substitutions, including all templates from SUPPORT
includes=$(for i in ${SUPPORT}/*/db; do echo -n "-I $i "; done)
msi ${includes} -S ${CONFIG_DIR}/ioc.substitutions -o ${epics_db}
fi
final_ioc_startup=${ioc_startup}

# 4. empty config folder *******************************************************

else
final_ioc_startup=${TOP}/example/st.cmd

elif [ -f ${override} ]; then
exec bash ${override}
fi

# Launch the IOC ***************************************************************
Expand Down

0 comments on commit 4e9712e

Please sign in to comment.