Skip to content
Snippets Groups Projects
Commit a9c917de authored by Simon Rose's avatar Simon Rose
Browse files

Add tests for e3-sequencer compilation

This commit also modifies how driver.makefile processes .st/.stt files.
According to the SNL documentation, .stt files should not be pre-processed.
However, driver.makefile has historically been performing the exact same
actions to both types of files, counter to what the documentation said.
parent bb242afb
No related branches found
No related tags found
1 merge request!102Add tests for e3-sequencer compilation
...@@ -514,7 +514,7 @@ DBDFILES += $(patsubst %.stt,%_snl.dbd,$(notdir $(filter %.stt,${SRCS}))) ...@@ -514,7 +514,7 @@ DBDFILES += $(patsubst %.stt,%_snl.dbd,$(notdir $(filter %.stt,${SRCS})))
DBDFILES += $(patsubst %.gt,%.dbd,$(notdir $(filter %.gt,${SRCS}))) DBDFILES += $(patsubst %.gt,%.dbd,$(notdir $(filter %.gt,${SRCS})))
# snc location # snc location
SNCALL=$(shell ls -dv $(E3_SITEMODS_PATH)/sequencer/$(sequencer_VERSION)/bin/$(EPICS_HOST_ARCH) 2> /dev/null)) SNCALL=$(shell ls -dv $(E3_SITEMODS_PATH)/sequencer/$(sequencer_VERSION)/bin/$(EPICS_HOST_ARCH) 2> /dev/null)
SNC=$(lastword $(SNCALL))/snc SNC=$(lastword $(SNCALL))/snc
ifneq (,$(strip $(VLIBS))) ifneq (,$(strip $(VLIBS)))
...@@ -698,59 +698,35 @@ ${INSTALL_BINS}: $(addprefix ../,$(filter-out /%,${BINS})) $(filter /%,${BINS}) ...@@ -698,59 +698,35 @@ ${INSTALL_BINS}: $(addprefix ../,$(filter-out /%,${BINS})) $(filter /%,${BINS})
# Create SNL code from st/stt file. # Create SNL code from st/stt file.
# Important to have %.o: %.st and %.o: %.stt rule before %.o: %.c rule! # Important to have %.o: %.st and %.o: %.stt rule before %.o: %.c rule!
# Preprocess in any case because docu and implemented EPICS rules mismatch here.
CPPSNCFLAGS1 = $(filter -D%, ${OP_SYS_CFLAGS}) CPPSNCFLAGS1 = $(filter -D%, ${OP_SYS_CFLAGS})
CPPSNCFLAGS1 += $(filter-out ${OP_SYS_INCLUDE_CPPFLAGS} ,${CPPFLAGS}) ${CPPSNCFLAGS} CPPSNCFLAGS1 += $(filter-out ${OP_SYS_INCLUDE_CPPFLAGS} ,${CPPFLAGS}) ${CPPSNCFLAGS}
CPPSNCFLAGS1 += -I $(dir $(SNC))../../include CPPSNCFLAGS1 += -I $(dir $(SNC))../../include
SNCFLAGS += -r SNCFLAGS += -r
%.i: %.st
@echo ">> Preprocessing $(<F)"
$(CPP) ${CPPSNCFLAGS1} $< > $(*F).i
# 1) ESS uses 7.0.3.1 as the minimal EPICS BASE, so we don't need to check 3.13, %.c: %.i
# 2) We also need -c option in $(COMPILE.c) in order to compile generated source file properly
# 3) SNC (2.1.21) should use -o, because without them, snc returns $(*F).i.c instead of $(*F).c
# With the EPICS standard building rule, -o and mv are used.
#
# Tuesday, November 28 15:59:37 CET 2017, Jeong Han Lee
%$(OBJ) %_snl.dbd: %.st
@echo "" @echo ""
@echo ">> SNC building process .... " @echo ">> SNC building process .... "
@echo ">> SNC : $(SNC)" @echo ">> SNC : $(SNC)"
@echo ">> SNC_VERSION : $(sequencer_VERSION)" @echo ">> SNC_VERSION : $(sequencer_VERSION)"
@echo ">> Preprocessing $(<F)"
$(RM) $(*F).i
$(CPP) ${CPPSNCFLAGS1} $< > $(*F).i
@echo ">> Converting $(*F).i to $(*F).c"
$(RM) $@
@echo ">> SNC is defined as $(SNC)" @echo ">> SNC is defined as $(SNC)"
$(SNC) $(TARGET_SNCFLAGS) $(SNCFLAGS) $(*F).i -o $(*F).c.tmp $(SNC) $(TARGET_SNCFLAGS) $(SNCFLAGS) $(*F).i -o $(*F).c
@mv $(*F).c.tmp $(*F).c
@echo ">> Compiling $(*F).c" %_snl.dbd: %.c
$(RM) $@
$(COMPILE.c) -c ${SNC_CFLAGS} $(*F).c
@echo ">> Building $(*F)_snl.dbd" @echo ">> Building $(*F)_snl.dbd"
awk -F [\(\)] '/epicsExportRegistrar/ { print "registrar (" $$2 ")"}' $(*F).c > $(*F)_snl.dbd awk -F [\(\)] '/epicsExportRegistrar/ { print "registrar (" $$2 ")"}' $(*F).c > $(*F)_snl.dbd
%$(OBJ) %_snl.dbd: %.stt %.c: %.stt
@echo "" @echo ""
@echo ">> SNC building process .... " @echo ">> SNC building process .... "
@echo ">> SNC : $(SNC)" @echo ">> SNC : $(SNC)"
@echo ">> SNC_VERSION : $(sequencer_VERSION)" @echo ">> SNC_VERSION : $(sequencer_VERSION)"
@echo ">> Preprocessing $(<F)"
$(RM) $(*F).i
$(CPP) ${CPPSNCFLAGS1} $< > $(*F).i
@echo ">> Converting $(*F).i to $(*F).c"
$(RM) $@
@echo ">> SNC is defined as $(SNC)" @echo ">> SNC is defined as $(SNC)"
$(SNC) $(TARGET_SNCFLAGS) $(SNCFLAGS) $(*F).i -o $(*F).c.tmp $(SNC) $(TARGET_SNCFLAGS) $(SNCFLAGS) $< -o $(*F).c
@mv $(*F).c.tmp $(*F).c
@echo ">> Compiling $(*F).c"
$(RM) $@
$(COMPILE.c) -c ${SNC_CFLAGS} $(*F).c
@echo "Building $(*F)_snl.dbd"
awk -F [\(\)] '/epicsExportRegistrar/ { print "registrar(" $$2 ")"}' $(*F).c > $(*F)_snl.dbd
# Create GPIB code from *.gt file. # Create GPIB code from *.gt file.
......
import os
import pathlib
import subprocess
import pytest
from git import Repo
from .utils import Wrapper
GITLAB_URL = "https://gitlab.esss.lu.se"
TEST_SEQ_SRC = """
program test
ss ss1 {{
state init {{
when(delay(1)) {{
printf({});
}}
state init
}}
}}
"""
class SequencerBuild:
sequencer_url = f"{GITLAB_URL}/e3/wrappers/core/e3-sequencer.git"
def __init__(self, path: pathlib.Path):
self.epics_base = pathlib.Path(os.getenv("EPICS_BASE"))
self.base_version = self.epics_base.name.split("base-")[-1]
assert self.base_version
self.require_version = os.getenv("E3_REQUIRE_VERSION")
assert self.require_version
self.version = "sequencer_test"
self.host_arch = os.getenv("EPICS_HOST_ARCH")
assert self.host_arch
self.path = path / "e3-sequencer"
Repo.clone_from(self.sequencer_url, self.path)
self.config_dir = self.path / "configure"
self.config_dir.mkdir(exist_ok=True)
(self.config_dir / "RELEASE.local").write_text(
f"""EPICS_BASE := {self.epics_base}
E3_REQUIRE_VERSION := {self.require_version}"""
)
(self.config_dir / "CONFIG_MODULE.local").write_text(
f"E3_MODULE_VERSION := {self.version}"
)
self.cell_path = self.path / "cellMods"
make_arg = ["make", "-C", self.path]
results = subprocess.run(
make_arg + ["init"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding="utf-8",
)
assert results.returncode == 0
results = subprocess.run(make_arg + ["patch"])
assert results.returncode == 0
results = subprocess.run(make_arg + ["build"])
assert results.returncode == 0
results = subprocess.run(
make_arg + ["cellinstall", f"E3_CELL_PATH={self.cell_path}"]
)
assert results.returncode == 0
self.snc_path = (
self.cell_path
/ f"base-{self.base_version}"
/ f"require-{self.require_version}"
/ "sequencer"
/ self.version
/ "bin"
/ self.host_arch
/ "snc"
)
assert self.snc_path.is_file()
@pytest.fixture(scope="module")
def sequencer(tmp_path_factory):
path = tmp_path_factory.mktemp("sequencer_build")
yield SequencerBuild(path)
class SequencerWrapper(Wrapper):
def __init__(self, sequencer: SequencerBuild, path: pathlib.Path):
super().__init__(path)
self.sequencer = sequencer
self.add_var_to_config_module("SEQUENCER_DEP_VERSION", self.sequencer.version)
def run_make(self, *args):
return super().run_make(
*args,
f"E3_CELL_PATH={self.sequencer.cell_path}",
f"SNC={self.sequencer.snc_path}",
)
@pytest.fixture
def sequence_wrapper(sequencer, tmp_path):
yield SequencerWrapper(sequencer, tmp_path)
@pytest.mark.parametrize("extension", ["st", "stt"])
def test_compile_snl_file(sequence_wrapper: SequencerWrapper, extension):
snl_filename = "test_filename"
seq_source = sequence_wrapper.module_dir / f"{snl_filename}.{extension}"
seq_source.write_text(TEST_SEQ_SRC.format('""'))
sequence_wrapper.add_var_to_module_makefile(
"SOURCES", f"{snl_filename}.{extension}"
)
rc, *_ = sequence_wrapper.run_make("cellbuild")
assert rc == 0
assert (sequence_wrapper.build_dir / f"{snl_filename}.o").is_file()
assert (sequence_wrapper.build_dir / f"{snl_filename}_snl.dbd").is_file()
def test_preprocess_st_file(sequence_wrapper: SequencerWrapper):
snl_filename = "test_file.st"
seq_src = sequence_wrapper.module_dir / snl_filename
seq_src.write_text(
'#define MESSAGE "waiting\\n"\n' + TEST_SEQ_SRC.format("MESSAGE")
)
sequence_wrapper.add_var_to_module_makefile("SOURCES", snl_filename)
rc, *_ = sequence_wrapper.run_make("cellbuild")
assert rc == 0
def test_do_not_preprocess_stt_file(sequence_wrapper: SequencerWrapper):
snl_filename = "test_file"
seq_src = sequence_wrapper.module_dir / f"{snl_filename}.stt"
seq_src.write_text(
'#define MESSAGE "waiting\\n"\n' + TEST_SEQ_SRC.format("MESSAGE")
)
sequence_wrapper.add_var_to_module_makefile("SOURCES", f"{snl_filename}.stt")
rc, _, errs = sequence_wrapper.run_make("cellbuild")
assert rc == 2
assert (
f"No rule to make target `{snl_filename}.c', needed by `{snl_filename}_snl.dbd'"
in errs
)
assert not (sequence_wrapper.build_dir / f"{snl_filename}.i").is_file()
...@@ -15,12 +15,15 @@ class Wrapper: ...@@ -15,12 +15,15 @@ class Wrapper:
assert "EPICS_BASE" in test_env assert "EPICS_BASE" in test_env
assert "E3_REQUIRE_VERSION" in test_env assert "E3_REQUIRE_VERSION" in test_env
assert "EPICS_HOST_ARCH" in test_env
self.epics_base = Path(os.getenv("EPICS_BASE"))
self.base_version = self.epics_base.name.split("base-")[-1]
self.host_arch = os.getenv("EPICS_HOST_ARCH")
self.require_version = os.getenv("E3_REQUIRE_VERSION")
e3_require_config = ( e3_require_config = (
Path(os.environ.get("EPICS_BASE")) self.epics_base / "require" / self.require_version / "configure"
/ "require"
/ os.environ.get("E3_REQUIRE_VERSION")
/ "configure"
) )
assert e3_require_config.is_dir() assert e3_require_config.is_dir()
...@@ -38,6 +41,8 @@ class Wrapper: ...@@ -38,6 +41,8 @@ class Wrapper:
self.module_dir = self.path / module_path self.module_dir = self.path / module_path
self.module_dir.mkdir(parents=True) self.module_dir.mkdir(parents=True)
self.build_dir = self.module_dir / f"O.{self.base_version}_{self.host_arch}"
self.config_dir = self.path / "configure" self.config_dir = self.path / "configure"
self.config_dir.mkdir() self.config_dir.mkdir()
...@@ -61,7 +66,7 @@ REQUIRE_CONFIG:={e3_require_config} ...@@ -61,7 +66,7 @@ REQUIRE_CONFIG:={e3_require_config}
include $(REQUIRE_CONFIG)/CONFIG include $(REQUIRE_CONFIG)/CONFIG
include $(REQUIRE_CONFIG)/RULES_SITEMODS include $(REQUIRE_CONFIG)/RULES_SITEMODS
""" """
(self.makefile).write_text(makefile_contents) self.makefile.write_text(makefile_contents)
self.module_makefile = self.path / f"{name}.Makefile" self.module_makefile = self.path / f"{name}.Makefile"
module_makefile_contents = """ module_makefile_contents = """
...@@ -70,7 +75,7 @@ include $(E3_REQUIRE_TOOLS)/driver.makefile ...@@ -70,7 +75,7 @@ include $(E3_REQUIRE_TOOLS)/driver.makefile
EXCLUDE_ARCHS+=debug EXCLUDE_ARCHS+=debug
""" """
(self.module_makefile).write_text(module_makefile_contents) self.module_makefile.write_text(module_makefile_contents)
if include_dbd: if include_dbd:
self.add_file("test.dbd") self.add_file("test.dbd")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment