PiDP-8/I Software

Shrinking the test regime?
Log In

Shrinking the test regime?

(1) By Bill Cattey (poetnerd) on 2020-08-03 01:54:09 [link] [source]

With the shift of build-time image from v3d to v3d-patched, I think we can shrink the test regime.

The current test regime does a full build of every combination of options.

However, 3rd party software conditionals are now leaf nodes, being added after most of the build action is done:

  • cc8
  • e8

There is a bunch of 3rd party software that ALSO should move from dist to the RUNTIME packs because it is not needed for building.

  • music
  • advent
  • ba
  • k12
  • chess
  • dcp
  • focal69
  • uwfocal

Although certain language subsystems might move off dist, they get patched, so my inclination is to leave them on dist:

  • fortran-ii
  • fortran-iv
  • macrel

Proposal:

  1. Leave fortran-ii, fortran-iv, and macrel alone.
  2. Move the other 3rd party software out of dist and into the RUNTIME packs.
  3. Change the test regime to be permuted runs, not of the whole build, but of the options to os8-run appropriate to adding them to the RUNTIME packs.
  4. Retain the few permutations of the whole build that actually impact dist.
  5. Eliminate "os8-use-ock" because those packs always build even though we don't always use them.

Open question:

Do we actually need full-run builds of the configuration options:

  • os8-init?
  • os8-vtedit?

Help desired:

I'm not much of a perl jock, and I'm calling for a redo of test-os8-run. Will a phase with os8-run calls fit into the existing design of the program?

(2) By Bill Cattey (poetnerd) on 2020-08-05 03:04:28 in reply to 1 [source]

Further investigation and refreshing of my memory about 3rd party software:

With the advent of the framework to build subsystems like cc8 and e8 from source, the potential exists to build from source some of what has previously been copied in from either found binaries, or created tu56 images.

Proposed next step: Shift the copy-in of the subsystem tu56 files from the dist scripts to the boot-rk05 scripts.

dcp:

We do not have source for dcp. There were a pair of .BN files (DCP16.BN, DCP24.BN) that were saved into executable files (DCP16.SV and DCP24.SV) and a documentation file DCP.WU. All five files were put on the local.tu56 image.

chess:

Looks like a binary CHESS.SV was put on the local.tu56 image along with documentation in the file CHESS.TX. However a source file CHEKMO.PA is available at http://www.pdp8.net/pdp8cgi/os8_html?act=dir;fn=images/misc_dectapes/chekmo_misc.tu56;sort=name.

vtedit:

TECO.IN, VTEDIT.DC, and VTEDIT.TE were put on the local.tu56 image.

lcmod:

The .BI files for matching the v3d binary distribution for the system and BASIC lcmods (LCSYS.BI, UCSYS.BI, LCBAS.BI, UCBAS.BI) were put on the local.tu56 image.

Fortran update:

The local.tu56 image got FORLIB.RL, DLOG.RA. These are source files used to patch the v3d FORTRAN IV binary. They were added in checkin: https://tangentsoft.com/pidp8i/info/87aa1be98653b77a

Separate subsystems:

In media/os8/subsys/ are tu56 images:

  • The Colossal Cave Adventure: advent.tu56
  • BASIC demos and games: ba.tu56
  • FOCAL 69: focal69.tu56
  • Kermit12: k12.tu56
  • MUSIC: music.tu56
  • UW/FOCAL: uwfocal-v4e-1.tu56, uwfocal-v4e-2.tu56

(3) By Warren Young (tangent) on 2020-08-05 05:12:31 in reply to 2 [link] [source]

What would be ideal is if the current CC8 + E8 build schemes were generalized so you could create TU56 "package" tapes for everything that's strictly optional, with the os8-run build script isolating the details of how each one gets built.

What then follows is "apt for PDP-8" where a person can add, remove, or reinstall packages into an existing RK05 image on demand.

What this then does for the testing system is that it lets us build a base OS, archive it, and then test each package independently on that base OS, not in combination with all of the other packages that cannot possibly affect it, greatly reducing test combinations.

For example, given that FORTRAN II depends on SABR, if you package those separately, there's no point testing a build of SABR independently of FORTRAN II. If the FORTRAN II package test succeeds, SABR almost certainly works standalone. Then since CC8 depends on both of those, a successful test of CC8 probably proves that FORTRAN II and SABR are also working, so we should just test CC8.

This then suggests that this packaging tool produces more than just TU56 images, that there is metadata: this package depends on that one, this one has a custom test script to check whether it's working properly, etc.

To the extent that packages are independent of one another, we don't need to test all possible combinations. We'd end up isolating the combinatorial checking in the current system to base-level packages and build options like the upper/lowercase patch one, the TD8E vs TC08 issue, etc. We might end up with some dozens of base OS combinations which then get tested with each of the packages.

Instead of 2ⁿ tests where n is the number of packages, we end up with p×2ᵐ tests where m is the number of base OS configs and p is the number of leaves in the package dependency tree, with only the leaves tested, per above. The current n is 16, so 64k tests, but I'm thinking that m will be more like 4-6 and p maybe 12, so we end up with only hundreds of test combos.

The data structure for this is a dependency tree, a type of DAG. You do a depth-first traversal on it, marking all parent nodes as "working" when a leaf test succeeds, so that it skips parent node tests as long as at least one of their child tests succeeds. This does mean inner nodes can get tested if all of their child tests fail, which is good because if we find that CC8 fails but FORTRAN II succeeds, that tells us something interesting. Thus, each package still needs a test, even if we think it won't run most of the time.

As for your Perl concerns, I think the current test-os8-run program is quite easy to read. It should be easier to modify it than to completely reinvent it. Rather than trying every possible option, it probably wants a data structure that tells it which packages depend on which others, which then informs what combinations it needs to test.

(4) By Bill Cattey (poetnerd) on 2020-08-07 02:06:26 in reply to 3 [link] [source]

I've been meditating on what requirements have been implicitly implemented in the dist.os8 (soon to shift to boot-rk05) script.

make enables us to represent various "build from source" acts such that we can get to a point where all the pieces are ready to go into a .tu56 image. It also enables us to know when the image needs to be re-made as a consequence of source or configuration change.

auto.def enables us to represent configurable parameters.

The various .os8 scripts that create each 3rd party package .tu56 image knows the manifest of what's on the image and from where, in possibly complex build tree, it comes. It performs any needed post-make transformations.

Even so we need more than just the DAG to represent dependencies among packages.

Because some files in an OS/8 3rd party package live on SYS: and some live on DSK:, we need a way to represent the mapping of the contents of the .tu56 image onto the system packs in either SYS: or DSK:. This information needs to be used at install time, and should be used at dependency time to look for conflicts -- files on two packages that land on the same destination file. Last writer of the conflicting file wins. In a parallel make environment the last writer is non-deterministic.

So the metadata needs to name all the destination files as well as package dependencies.

(5) By Warren Young (tangent) on 2020-08-07 12:16:44 in reply to 4 [link] [source]

make...DAG...dependencies...

It occurs to me that make is a tool for implementing file dependency DAGs and transformation rules over that DAG.

What if there are two tools, one that ran at configure time, converting package descriptions to Makefile rules which are then loaded into the top-level Makefile, controlling calls to the package-building tool?

The description file (call it $srcdir/packages/cc8.pspec, as in "package specification") could look something like this:

provides: cc8
depends:  [ fortran-ii, sabr ]
inputs:   [ src/cc8/os8/* ]
outputs:  [ SYS:?8.SV, DSK:*.C ]
build:    bin/os8-run scripts/misc/cc8-tu56.os8

This results in a file $builddir/obj/packages/cc8.mk:

obj/packages/cc8.pkg: src/cc8/os8/*

...and an os8-run script based in part on the "build" string in the pspec file.

That string can be multi-line by the way, in the same way that Makefile rules can have multiple steps. I'm just showing a simple case where build is a single command. In fact, we could have build be implicit, with the example command above being the default generated when no explicit command is given.

The *.pkg output file gets built by an implicit rule .pspec.pkg which calls os8-run on that generated script to build bin/packages/cc8.tu56. PKG files are containers for the TU56 and other info distilled from the YAML package spec file. The most common method is a Zip, Tar, or CPIO file with special file contents, but I'm thinking sqlar would be a better choice, since we could parse the YAML data into a custom SQL table and query it directly rather than unpack the metadata file from the package and re-parse the data from a file.

For example, if you want to know what a package depends on:

$ sqlite3 bin/packages/cc8.pkg \
  select depends from metadata
fortran-ii
sabr

All of those queries can be wrapped into a third tool modeled on existing package management tools for installing, removing, and reinstalling those packages into SIMH media images. You can then say things like:

$ os8pkg install cc8
$ os8pkg --query --depends cc8   # wraps above sqlite3 command

Because some files in an OS/8 3rd party package live on SYS: and some live on DSK:, we need a way to represent the mapping of the contents of the .tu56 image onto the system packs in either SYS: or DSK:

The above pspec does that — "outputs" — though I don't really see why you need it. I mean, it would be nice if you could say something like "os8pkg --query --provides dsk:ps.c" and have it tell you "cc8.pkg", but that can be way post-1.0. What I'm asking is why the pre-alpha version needs any such feature.

Last writer of the conflicting file wins. In a parallel make environment the last writer is non-deterministic.

I'm not seeing why we need to solve that problem before 1.0. The initial version should just blindly unpack TU56 tapes onto the destination media. Last-one-wins is just fine for our initial purposes. Elaboration can wait.

If your worry is over multiple packages providing alternatives to each other, which necessarily conflict, then:

  1. We can add a "conflicts" declaration to the YAML package description, so the package installer (os8pkg) won't try to install both at the same time.

  2. At build time, use a clone of the pristine base OS image, not the same copy. Therefore, two builds can be making conflicting packages in parallel. We want to use a clone anyway so that "rm obj/os8pkg-tmp-ABCD1234.rk05" is the post-build cleanup step, rather than try to unwind the changes to restore the image to pristine condition.

(6) By Bill Cattey (poetnerd) on 2020-08-09 03:12:15 in reply to 5 [link] [source]

I've been struggling mightily with how to connect your design with what we have, or to articulate my gaps in understanding. It occurs to me that I'm unclear on where the line is drawn on the package builder between two activities:

  1. constructing the third party package binary blob that is copied into bootable packs and
  2. doing the copying from the binary blop into bootable packs.

I wonder if my difficulty saying, "What I don't understand is..." comes from flip-flopping between trying to apply the package builder for these two activities and getting lost.

Let's see if I can flesh out your example.

cc8 has lots of bits in Makefile.in:

CC_OS8_OBJS := \
    obj/cc8/os8/libc.sb \
    obj/cc8/os8/c8.sb \
    obj/cc8/os8/n8.sb \
    obj/cc8/os8/p8.sb

CC_OS8_SRCS := \
    @srcdir@/src/cc8/os8/header.sb

CC_OS8_DEMOS := \
    obj/cc8/os8/calc.c \
    obj/cc8/os8/fib.c \
    obj/cc8/os8/forth.c \
    obj/cc8/os8/hlb.c \
    obj/cc8/os8/pd.c \
    obj/cc8/os8/ps.c \

# Create the CC8 distribution DECtape image
bin/cc8.tu56: $(CC_OS8_OBJS) $(CC_OS8_SRCS) $(CC_OS8_DEMOS) $(CC8_TU56_SCRIPT) | $(OS8_TOOLTIME)
    $(OS8RUN) $(CC8_TU56_SCRIPT)

Does all this hand-tooled stuff in Makefile.in for building the package get subsumed by output driven from cc8.pspec? Does the package builder also put the builds of the object files into Makefile.in? That makes sense for things built on the POSIX side, but on the OS/8 side, there's considerable hand-tooling that goes into the builder os8 scripts. For example, look at the OCK FORTRAN IV builder script in scripts/os8/ock/fiv-build.os8. Or were you saying that multi-line build directives would replace scripts fiv-build.os8?

I presume that the actual builder, scripts/misc/cc8.os8 still is hand-tooled, and that the .os8 output driven by cc8.pspec replaces the hand-tooled lines in {ock,v3d}/boot-rk05.os8:

# Ian Schofield's CC8 compiler
# Don't install this in v3d-dist because we need
# v3d packs to build it.
begin default cc8
mount dt1 $os8mo/cc8.tu56 ro required
os8 COPY RKA0:<DTA1:*.SV
os8 COPY RKB0:<DTA1:*.SV/V
umount dt1
end default cc8

Perhaps now I understand why you question the value of the outputs pspec. If it is the responsibility of the build pspec to perform the copying, then the knowledge of what gets copied where would reside in the build pspec, so the benefit of having that information also in a outputs pspec seems smaller, possibly redundant. However, it could be that the outputs spec is able to generate implied copy commands, thereby leaving the build spec as possibly empty, if only destination copies are performed.

(Side note: If we constrain destinations as SYS: and DSK: then the builder doesn't need to care whether the output is a .tu56 third party package blob, or a .rk05, .rx01, or an rl01 destination bootable image. However, that may mean that we can't use it to auto-generate builders for destinations like bin/ock-fiv-obj.rk05 because the builder, scripts/os8/ock/fiv-builder.os8, has intimate knowledge of sources coming from RKA1: and binaries landing in RKB1:. That implementation was a hand-tooling recognizing the space available in the .rk05 image. But maybe it was never your intent to replace the .os8 from-source builder scripts.)

To make use of the dependency information, we have to be clear on the actual cc8 dependencies. I've reviewed the cc8 examples, and it uses the FORTRAN II run-time libraries, and SABR.SV. However, those dependencies in your .pspec file implicitly relate to other packages that have .pspec files. Currently fortran-ii is in a gray area where we have the scaffolding to make it an optional component, but we commented that hand-tooling out because we might be installing cc8. We could spin it out as a separately managed package or two. But there is a wrinkle: Patching. FORTRAN II and SABR get patches applied. So we need to represent performing patches, and management of patch files for packages. Not a problem, but something we will need if we start building baseline or mid-level images with this system.

Is it your thought to have the baseline OS be represented in a .pspec file? Or have I again missed the point -- that the fortran-ii option we already have in automake puts into Makefile.in and dynamically created os8-run activities what you expect would properly either do the copyin or complain about a missing package?

I have a concern about having a conflicts pspec: It creates a need for possibly independent third party development streams to begin to be aware of each other. My thinking was, "Let packages evolve as they will, and leave it to the person integrating multiple packages to act on warnings when particular collections collide." So my planned implementation was to have the package manager review what was getting installed and warn of collisions.

One other aspect of the package manager design I've been considering: Allowing multiple image output formats for the destination. Why should we constrain the package manager always to output a .tu56 image? If it could output either a .tu56 or a .rk05 it could be used to create bootable system packs as well as the third party packages that are assembled into said packs. Allowing .rx01 or .rx02 might turn out to be useful in the future

Can you say more about how the use of .mk files would be codified? Does the configure script keep track of the .mk files that get created/updated and concatenate them into Makefile.in or Makefile?

Since the parse of the pspec files happens before running of make how are the dependencies amongst the packages resolved? Is this a matter of all package files activated in options passed into automake ending up with the creation of lines in Makefile.in which then would complain if some required dependency isn't getting built?

I'm confused by the .pkg file. Why do we need it? Have I missed the point of having a package building tool?

I've spent a few hours struggling to either figure out how to implement your design or to articulate my gaps in understanding. I'm gonna post this and see if you can tease out the source of my confusion.

(7) By Warren Young (tangent) on 2020-08-09 04:12:30 in reply to 6 [link] [source]

I wonder if my difficulty saying, "What I don't understand is..." comes from flip-flopping between trying to apply the package builder for these two activities and getting lost.

The way I think of it is, if we have a package management system, then the question of what gets copied to the installation media amounts to a series of package manager commands.

This not only separates concerns between "build the base OS" and "install N optional packages," it isolates what constitutes a package to each individual package. This allows you to think of the final 20-ish OS/8 related things that get built in pieces, which makes reasoning about each one simpler.

Can you say more about how the use of .mk files would be codified?

I gave one example above. It's just a short Makefile snippet that gets pulled into the top-level Makefile, which modifies what gets built at that level and how.

Does the configure script keep track of the .mk files that get created/updated and concatenate them into Makefile.in or Makefile?

No. See...

Does all this hand-tooled stuff in Makefile.in for building the package get subsumed by output driven from cc8.pspec?

The steps to transform src/cc8/os8/*.c to obj/cc8/os8/*.sb remain outside the package system proper. There may be a sub-Makefile in src/cc8/os8 for creating those files, which the package building tool calls.

The point is that the package building tool does not become make. It calls it. Those rules should probably move outside of the top-level Makefile — which will simplify it — but they don't disappear into the package builder.

Small pieces loosely joined, yes?

Contrast header.sb which is a "source" file stored directly in Fossil. That simply gets listed in the package spec file's list of inputs along with some way of saying "This file on the host goes there under OS/8."

The same goes for the C demo programs, except that there's a tiny transform step in between to cope with differences in behavior between the two versions of CC8. So, do the transform, then copy the resulting files onto the package tape.

Or were you saying that multi-line build directives would replace scripts fiv-build.os8?

Most likely, the pspec file's "build" step calls os8-run on that script as part of building the package.

We're not so much reinventing whole new things as sharding the current monolithic build system into a multi-step affair. Not only will it simplify some matters by isolating concerns and reducing the number of things you have to think about at once, it'll let certain steps run in parallel because make will be able to see that this set of a dozen packages have no interdependencies.

Perhaps now I understand why you question the value of the outputs pspec.

There is such a thing in RPM, but it's only used as a sanity-check: the %install script in the RPM spec file is meant to take care of everything, but you separately list the set of files meant to appear in the package, which allows rpmbuild to detect when you have unpackaged files, multiply-listed files, etc.

What I'm questioning is whether we need that sort of sanity checking in v1.0. Nice later, but now?

If we constrain destinations as SYS: and DSK:

Do you mean per-package? If so, then CC8 can't be done as a single package: it puts things on both halves of the disk.

I'm not even sure you can do a split like cc8-compiler and cc8-examples, because the compiler on SYS: needs DSK:HEADER.SB.

Patching.

Most package management systems incorporate a patching feature, because popular OSes need changes to software that they cannot reasonably push upstream.

Sometimes it's simply expedient for the OS package to carry a small patch to make things work the way the OS packager likes. This explains, for example, why the MySQL package on Debian puts its DB files in a non-default location: they're carrying a patch to the stock /etc/my.cnf.

What's more relevant in our case is that it's sometimes too difficult to get the upstream project to accept a patch, so the OS package has to carry it. In our case, DEC doesn't even exist in any useful sense any more, so we must carry their last released patches plus any we want to apply locally as part of our binary packages.

Bottom line, this almost certainly is a "1.0" sort of feature, being necessary to make the scheme work usefully.

Is it your thought to have the baseline OS be represented in a .pspec file?

No. The Makefile and *.os8 scripts for that continue as they are, though likely with a lot of stuff ripped out so we end up with a minimal utility OS image for os8-run to use.

That in turn gets used to build some packages in parallel by making temporary clones of that OS/8 disk image and running multiple SIMH copies in parallel, each driven by an instance of os8-run.

the fortran-ii option we already have in automake puts into Makefile.in and dynamically created os8-run activities what you expect would properly either do the copyin or complain about a missing package?

The Automake piece of this is simply a list somewhere saying, "After you create the base OS images, you need to install this list of packages."

One key side point here: under this scheme, all packages always get built, even if they weren't selected at configure time. Otherwise, you can't install packages after mediainstall time.

Let packages evolve as they will, and leave it to the person integrating multiple packages to act on warnings when particular collections collide

Where do the warnings come from?

If the warnings are all file-based, then your idea assumes that the system keeps a DB of already-installed files and then says, "Package B already has File C installed, so you can't install Package A."

Well and good, but what about other conflicts like for IOT device IDs? What happens if you try to install a version of U/W FOCAL into a system without the device drivers that were hard-coded into its commands? Don't we basically need a virtual package that declares the "device drivers" in our OS/8 image so we can say that the uwfocal package depends on a certain set of drivers?

These examples may suck, but at the very least, I hope they spark ideas in you for better examples where two packages can't be installed, and there's no easy way for the package installer to realize this fact, so that it's best if the package builder just says, "If you install this, you can't have this other thing installed."

Maybe it needs to be tag-based rather than package name-based. The Spacewar package can claim something like "iot: 5-6; vc8e", meaning that the IOT instructions within assume use of a VC8e, rather than some other sort of point-plot display.

Why should we constrain the package manager always to output a .tu56 image?

For the same reason that Cygwin packages are based on tar, RPM on cpio, etc. You want a low-level archiving format that your target OS knows how to read directly so you can do low-level things like extracting a single file in a programmable way.

You don't want to be saying, "Okay, so this package is based on RX02 images this week, so I have to use device name RXB2: or whatever in my os8-run script packages..."

I'm confused by the .pkg file. Why do we need it? Have I missed the point of having a package building tool?

Because the binary media image isn't all there is to a "package." There's also metadata.

When you run rpm -q or dpkg-query on a RPM or DEB package file, it may query one of two sources: the DB of data on already-installed packages or the metadata within a package that hasn't yet been installed. Installation copies the latter into the former so that queries can then find the info in the system-wide metadata DB.

Some package managers also have features like post-install scripts. Those can't live in the binary media image. (TU56 in my examples.)

But likewise, this proposed sqlar based format can't be where the binary data for the package live — e.g. SYS:CC0.SV for CC8 — because SIMH can't read from SQLite DBs.

You may then say, "Okay, so put the metadata and post-install data into the TU56 image." And indeed, that's what some very simple package formats like Cygwin do, so you end up with /etc/pkginfo/pkgname/dependencies and such. But OS/8 lacks a hierarchical filesystem, so metadata and postinstall scripts and such will end up cluttering the disks.

I've spent a few hours struggling

All of this is meant as ideas to help you design the sort of thing that will help you solve your own problems. If it's causing more problems that it solves, feel free to ignore the ideas.

These ideas are meant to help, though.

(8) By Bill Cattey (poetnerd) on 2020-08-11 04:34:59 in reply to 7 [link] [source]

Ok. That helps me understand what you're trying to communicate.

It seems like 3 utilities are being called for:

  1. The config tool that generates the .mk include file for a given package.
  2. The packager tool that creates the package file.
  3. The manager tool that utilizes the package file to put it onto bootable media.

A couple side notes:

I was unfamiliar with the make include syntax. It does mean that we assume gnu make as our baseline platform. Do we already assume that?

Using a .tu56 image as the native OS/8 package data repository component is not as obvious as it might seem at first blush. OS/8 has terrible architecture when it comes to device sizing. A .tu56 image can hold 730 blocks of data. A .rk05 image can hold 3248 blocks in each of its two partitions. One can create "mythical DECtape images" of sizes up to 4096 blocks, but that requires a specially hacked version of PIP to perform the formatting. Stuff using such non-standard DECtape image sizes alleges to work under SIMH... A .rx01 image can hold a bit more than a stock .tu56 image, but doesn't seem worth the trouble. A .rx02 image can hold 1/3 of the amount of stuff that fits on a .rk05 but the file format is funky.

uwfocal lives on two .tu56 images right now.

I'm trying to think in terms of an architecture that might be able to be agnostic about whether a .tu56 or some other image is used.

Clarification of my thinking on "Constraining destination to SYS: and DSK:": What I was trying to say there was that all packages we currently install operate in terms of what lands on those two devices regardless of whether the package gets installed on a .tu56, .rk05, .rx01, or .rl01 bootable image.

Things get wierd if one wants to use the packager/manager tools for the OS. The ock build managed to break nicely into 4 .rk05 images that house source on the A partition and the built binaries on the B partition, with only a few special cases where content is copied out of A rather than B when building the ock-dist.rk05 image.

All of this reminds me of why I hand-tooled the .os8 scripts so extensively.

(9) By Warren Young (tangent) on 2020-08-11 04:52:54 in reply to 8 [link] [source]

Do we already assume [GNU make]?

Yes, we're already using GNU-specific features, including (hah!) -include. (See the end of Makefile.in.)

A .tu56 image can hold 730 blocks

We generally want more small packages in this scheme rather than a few large packages.

Given that, are we in danger of going over that for any likely packages? To take your uwfocal example, does that really want to be 2+ packages anyway, so you can install just some parts of it? (e.g. runtime, examples, doc.)

agnostic about whether a .tu56 or some other image is used.

Your call. The size issue aside, I think we should just pick something "large enough" and stick to it. I don't much care which it is. I only said "TU56" because that's what we're using today.

All of this reminds me of why I hand-tooled the .os8 scripts so extensively.

pspec files will likely require similar careful accommodations. Part of the basic requirements are a spec file design and interpreter strong enough to express our current and near-future requirements.

Thus the open-ended "build" step, for example.

(10) By Bill Cattey (poetnerd) on 2020-08-13 04:18:33 in reply to 9 [link] [source]

I've thrown together a short python script (~220 lines) that parses a .pspec file and has two commands to operate on that pspec file:

  • --mk which makes the .mk output.
  • --os8 which makes the .os8 output that would normally be in-line in the boot-rk05.os8 script

I didn't use YAML, I made a ridiculously simple parser that uses a section header to say what comes next.

The example below shows that I can write a tool driven by a pspec file that can generate what have heretofore been hand-made but automate-able makefile and os8run scripts.

Question: How do you envision the packages to be installed on v3d.rk05 or ock.rk05 would be specified? Would Makefile.in have blocks that would call <pkgname>.os8 that were conditional on the automake vars? Something like:

ifeq (@E8@)
PKGS += bin/E8.tu56
endif

Would that block live in the .mk file too? Example run of os8pkg v.0.0: (I don't use the build spec just yet.)

e8.pspec:

inputs:
src/e8/AUTHORS.md
doc/e8-manual.md
doc/e8-manual-pdf.css
doc/graphics/e8-buffer.svg
src/e8/README.TX
src/e8/e8cmds.tx
src/e8/e8srch.tx
src/e8/e8defs.pa
src/e8/e8base.pa
src/e8/e8file.pa
outputs:
SYS:<DTA0:E8.SV
DSK:<DTA0:E8CMDS.TX
DSK:<DTA0:E8SRCH.TX
build:
bin/os8-run scripts/misc/e8-tu56.os8

Output:

wdc-home-3:trunk wdc$ bin/os8pkg e8
Package name:e8
e8.mk: 
E8_SRCS:= \
    ./src/e8/AUTHORS.md\
    ./doc/e8-manual.md\
    ./doc/e8-manual-pdf.css\
    ./doc/graphics/e8-buffer.svg\
    ./src/e8/README.TX\
    ./src/e8/e8cmds.tx\
    ./src/e8/e8srch.tx\
    ./src/e8/e8defs.pa\
    ./src/e8/e8base.pa\
    ./src/e8/e8file.pa

E8_TU56_SCRIPT =  $(MISC_SCRIPTS_DIR)/e8-tu56.os8


bin/e8.tu56: $(E8_SRCS) $(E8_TU56_SCRIPT) | $(OS8_TOOLTIME)
    $(OS8RUN) $(E8_TU56_SCRIPT)


e8-tu56.os8: 
mount dt0 $os8mo/e8.tu56 ro required
os8 COPY SYS:<DTA0:E8.SV
os8 COPY DSK:<DTA0:E8CMDS.TX
os8 COPY DSK:<DTA0:E8SRCH.TX
umount dt0

(11) By Warren Young (tangent) on 2020-08-14 15:05:54 in reply to 10 [link] [source]

I've thrown together a short python script

Not checked in, apparently?

I didn't use YAML

I recommended YAML for a bunch of reasons.

  1. Parsers are hard once you get beyond simple cases. For example, does yours handle the option of multi-line build scripts, or are you going to be forced to externalize all of those so you can make a single-line call out to an external tool?

    Not that "yes" is a fatal answer to this concern. Just realize the tradeoffs up front and decide based on them.

  2. I assumed Python (v3 at least) would have such a thing built-in. "Batteries included," right? Apparently not.

    However, given that we already depend on pexpect, I don't see why adding pyyaml or whatever is a fatal flaw in this plan.

  3. One less language for a large chunk of the audience to learn.

    And if you're one of those that thinks tou don't already know YAML, you're probably wrong. :) JSON is a subset of YAML!

  4. Of the markup languages, the whitespace-indented flavor is the most Pythonic.

two commands to operate on that pspec file:

The common way these package building systems work is that they take a "verb" argument rather than an option, one of which is something like "all" to do all of the other steps in the proper order, with error checking between.

Thus:

os8pkg deps       # create .mk format dependency rules only
os8pkg script     # write the os8-run script only
os8pkg build      # create the .pkg file, assuming "script" ran
os8pkg install    # attempt to install the resulting package
os8pkg all        # do all of the above

For "install" mode, the default install target is the same RK05 that 0.script points at. If you want another target, you have to specify it as an option:

os8pkg install --target=bin/ock.rk05

The "all" mode in the command design above would likely pass such an argument to install into a temporary clone of the "clean" OS/8 image, so there are no conflicts with pre-existing stuff.

How do you envision the packages to be installed on v3d.rk05 or ock.rk05 would be specified?

Either:

  1. Inserted conditionally into Makefile.in by auto.def, as we do for the PCRE build options for the simulator when the configure step detects it presence.

  2. By including a generated *.mk file as we do for adrules.mk to simplify autodependency generation. (See tools/mkadrules.)

I suspect we want something of a mix of these: Tcl within auto.def that generates the *.mk output file as part of processing --*-os8-* options.

(12) By Bill Cattey (poetnerd) on 2020-08-16 01:36:55 in reply to 11 [link] [source]

With the proof of concept code I have, it's trivial to make the "commands" into "verbs". I used the argparse library, figuring that it would allow maximum flexibility. Basically I delete the dashes from the arg specs, and POOF! it's done.

The pspec parser is trivial and ugly:

_pspec_sections = ["inputs:", "outputs:", "build:"]

pspec = {}
for section in _pspec_sections:
    pspec [section] = []

location = ""
for ioline in pspec_file:
    line = ioline.strip()
    if line == "": continue
    elif line[0] == "#": continue
    elif line in _pspec_sections: location = line
    else:
        if location == "":
            print ("Don't know where to put: {" + line + "}.")
        else:
            pspec[location].append(line)
return pspec

Everything else then uses the ordered lists of lines in the sub-arrays of pspec. Funny thing about it: One can have more than one instance of each section, and it just appends the new lines. One can add more sections trivially.

Including the colon in the section name is indeed gross.

(13) By Bill Cattey (poetnerd) on 2020-08-16 04:30:44 in reply to 12 [link] [source]

I've checked in version 0 of the os8pkg.in file, so you can look at it.

It's really VERY simple right now. Although I have hooks for the commands, I'm not writing files, I'm just printing what would go in the files.

Q1: I'm thinking that the generated .os8 and .mk files should go in obj/. Do you agree?

I'm thinking that a conditional in the .mk file that would/would not add the package file to the list of packages is a reasonable way to do it.

Then we could have both OCK and V3D utilize the PKGS variable. The order of execution would be:

  1. os8pkg deps creates the .mk files that contains all the conditional increments on the PKGS variable.
  2. make includes the sundry .mk files that perform the creation of the relevant packages.
  3. make works through the dependencies and builds all the packages.
  4. For creating ock and v3d boot images make calls install on all the packages named in the PKGS variable.

Q2: Can you give me an example of how to get from os8opts for e8 in auto.def to a conditional I could put into e8.mk that would/would not act on the line.

Q3: Can you give me an example of the automake template generation code that would call os8pkg deps on .pspec files?

(14) By Warren Young (tangent) on 2020-08-16 18:54:13 in reply to 13 [link] [source]

I've checked in version 0 of...os8pkg

I moved it to branch os8pkg because this is going to take multiple steps to iterate toward something we can ship, and I suspect some of these steps will destabilize the software.

I realize that at the moment, it affects nothing, but if that state of affairs were to continue, we'd have useless software, right? :) It has to affect the build system if it's to be useful, and I see no reason why we'd expect it to be perfect in the next checkin.

It's really VERY simple right now.

Points of elaboration that I'm noticing right off:

  • The usage message says "..." for the package list arg, but that isn't super helpful. I'd fix this myself, but I don't want to dive into the argparse docs to figure out how.

  • Package args should accept ".pspec" appendages and remove them silently. That is, if I say "os8pkg deps e8.pspec", it should realize what I mean.

  • The build step for that package just calls os8-run as the Makefile currently does. Is that going to continue, or will the tool eventually write os8-run scripts and run them implicitly?

I'm just printing what would go in the files.

This mode should be retained behind a -n/--dry-run flag once it starts writing to files. You should just be able to change the file handle to "stdout" to effect this.

I'm thinking that the generated .os8 and .mk files should go in obj/. Do you agree?

In a subdirectory, sure: obj/os8pkg/$PKG.{mk,os8}

Then at the end of Makefile.in:

    -include obj/os8pkg/*.mk

These should be written at configure time using Tcl code that iterates over a glob expansion of scripts/os8pkg/*.pspec. It checks whether the pspec file is newer than the deps output and [re]-generates it if so.

(Yes, I'm provisionally classifying pspec files as "scripts." Got a better idea?)

Within the same loop, we build up the list of packages to build and install that gets injected into the Autosetup-written Makefile, but as I said above, we still generate the deps and other output files so the user can later say "os8pkg build pkg-i-left-out-earlier".

The order of execution would be...

Sensible.

Can you give me an example of how to get from os8opts for e8 in auto.def to a conditional I could put into e8.mk that would/would not act on the line.

I don't see why you'd do it that way. That's injecting separate logic into each .mk output instead of consolidating it in auto.def.

Instead, I'd take one of the foreach.*$os8opts blocks in auto.def and marry that to a Tcl glob call to control the expansion of a define call on a variable that gets injected into the Makefile, like OS8PKGS_INSTALLED.

Thus saying --disable-os8-e8 results in "e8" being left out of OS8PKGS_INSTALLED but the e8.mk files and such still get generated so a user can later say os8pkg build install e8.

This does imply you can give multiple verbs with the command. I'm not sure your parser allows it right now. You can either allow it, or make os8pkg all e8 smart enough not to do extra work, giving the same effect.

That said, "all" doesn't necessarily imply "install". It probably makes more sense if it does everything except install. Thus why build install is a sensible verb pairing.

code that would call os8pkg deps on .pspec files?

Within the loop above, call file mtime on both the pspec and mk files and compare the values to decide whether to re-generate the deps.

(15) By Bill Cattey (poetnerd) on 2020-09-01 02:37:24 in reply to 14 [link] [source]

Picking this back up after some time away...

I'm trying to connect the dots on what you've recommended.

I currently have these pieces:

Create a define of OS8PKGS_INSTALLED in a foreach {opt def desc} $os8opts loop.

That would look something like this:

set os8pkgs_installed ""
foreach {opt def desc} $os8opts {
    set val $os8bool($opt)
    if {$val} {
        <code that gets pkg_name from an option>
    }
    append os8pkgs_installed " $pkg_name"
}

When you say, to marry that to a call to tcl glob, I figure it's something like what I see at the end of auto.def:

foreach f [concat [glob "$builddir/bin/*"] [glob "$builddir/tools/*"]] {
    exec chmod +x $f
}

So there'd be a [glob "$srcdir/scripts/os8pkg/*.pspec"]

But then it seems like one would iterate over the glob, cut it apart into names, and look for the option that matches the name. Something like this:

foreach pspec [glob "$srcdir/scripts/os8pkg/*.pspec"] {
    set pkg_name [file rootname [file tail $pspec]]
    if {[info exits $os8bool($pkg_name)] and $os8bool($pkg_name)} {
        append os8pkgs_installed " $pkg_name"
}

Do I have to check for existence in the $os8bool array before fetching its value, or will I get 0 if it's not there?

Have I composed the and expression properly? (I'm learning TCL as I go from a dead stop right now.)

Is this what you had in mind?

(16) By Warren Young (tangent) on 2020-09-02 23:41:54 in reply to 15 [link] [source]

Do I have to check for existence in the $os8bool array before fetching its value, or will I get 0 if it's not there?

$ tclsh
% set os8bool(foo) x 
x
% puts $os8bool(bar)
can't read "os8bool(bar)": no such element in array
% if {[info exists os8bool(bar)]} { puts "it's there" } else { puts "nope" }
nope

I'm learning TCL as I go from a dead stop right now.

I haven't spoken Tcl fluently since about 2000. Through disuse, I'm reduced to pidgin level facility with the language.

I suggest you use tclsh interactively as above to piece together along with a Tcl syntax guide (such as this one) to help you over the initial hump.

Tcl isn't a free-form language like C, and it is rigid in different ways than Python. For an example of these two points, you can't write the example above as:

if {[info exists os8bool(bar)]} {
    puts "it's there"
}
else {
    puts "nope"
}

There's a single-character error in that program, and it's a whitespace character on top of that. (The extra newline before "else".) The thing is, there's a very good reason why it's a syntax error. It isn't arbitrary; it's consistent with the rules in the linked doc.

Is this what you had in mind?

You appear to have the basic idea.

Realize that I'm just throwing out ideas, not assigning work. If this helps you achieve your goals while also getting us a package manager, great. If it doesn't work for you, that's fine, too.

(17) By Bill Cattey (poetnerd) on 2020-09-12 04:52:14 in reply to 16 [link] [source]

The latest checkin scans for .pspec files in .../scripts/os8pkg. It creates or updates the .mk files in .../obj/os8pkg.

The .mk files can contain arbitrary build commands or have a default build that depends on the inputs and runs .../scripts/misc/<pkgname>.os8

Next step is to see how to replace the copyin lines in boot-rk05.os8 in v3d and ock by parsing and acting on the outputs specs.

(18) By Bill Cattey (poetnerd) on 2020-09-13 05:00:46 in reply to 17 [link] [source]

Look at the latest checkin of the branch. I think I've connected the dots to enable the configuration setup to pick up e8 and cc8 as packages for boot-rk05.os8 that builds ock.rk05 and v3d.rk05.

Also doc/os8pkg.md documents the command and the pspec file format.

(19) By Warren Young (tangent) on 2020-09-13 15:57:48 in reply to 18 [link] [source]

Okay, some comments, in no particular order:

  • The new loop in auto.def looks sensible, but I found several things that needed cleanup. I don't think this breaks anything, but given where I wind up at the end of this report, I could be wrong.

  • Don't check commented or ifdef'd-out code in. (The variable defs in Makefile.in that correspond to the old hand-rolled packages.) Just delete it. We can retrieve it from version control later, if need be.

    It's fine to use "#if 0" and block comments to disable code while you're working on a commit, but once you decide to commit, commit to the change.

    This isn't about esthetics or efficiency, it's about communication: a diff with minus signs on those lines and no corresponding plus-sign lines afterward communicates "this isn't needed any more" better than a block of comments afterward.

  • This appears to be unfinished code, and it isn't clear to me what should be done about it:

    # Not sure what we depend on here.
    # At the very least we build the magic includer.
    $(PKGS_INCLUDE):
        bin/os8pkg include @OS8_PKGS_INSTALLED@
    
  • There were a couple of problems with building in a freshly checked-out or cleaned tree, which I've fixed. (One predated the branch, so I fixed it on trunk and merged it in; the other was specific to os8pkg.)

That's all I have for now, because I got this error in my attempt to build the branch:

Format converting ./src/os8/ock/LANGUAGE/FORTRAN4/LIBRARY/TANH.RA
Format converting ./src/os8/ock/LANGUAGE/FORTRAN4/LIBRARY/XFIX.RA
Detaching rk1
Detaching rk0
Quitting simh.
Running script file: ./scripts/os8/all-tu56.os8
Building OS/8 v3d tu56 image
for td12k configuration of TD8E.
Pre-existing /usr/local/src/pidp8i/scratch/bin/v3d-td12k.tu56 found.  Saving as /usr/local/src/pidp8i/scratch/bin/v3d-td12k.tu56.save
gmake[1]: Leaving directory '/usr/local/src/pidp8i/scratch'
gmake: *** No rule to make target 'media/os8/scripts/v3d-dist-rk05.os8', needed by 'bin/v3d-dist.rk05'.  Stop.

(I guess only the last line matters, but I included the rest for context.)

A subsequent build attempt gave:

Pre-existing /usr/local/src/pidp8i/scratch/bin/v3d.rk05 found.  Saving as /usr/local/src/pidp8i/scratch/bin/v3d.rk05.save
Overwriting old /usr/local/src/pidp8i/scratch/bin/v3d.rk05.save
At line 3, /usr/local/src/pidp8i/scratch/bin/e8.tu56 must exist but was not found. Not mounting.

Fatal error encountered in /usr/local/src/pidp8i/scratch/obj/os8pkg/pkgs.os8 at line 3:
	mount dt1 $os8mo/e8.tu56 ro required
gmake[1]: *** [Makefile:727: bin/v3d.rk05] Error 255

(20) By Bill Cattey (poetnerd) on 2020-09-14 00:28:44 in reply to 19 [link] [source]

Re: Cleanups: Thanks. Those looks good.

Re: Commenting vs. checkins. Sensible.

Re: Unfinished code: What's there should work, but I'm unsure if there are additional dependencies needed.

Re: Fixes. Thanks. You solved a couple chicken-egg problems I hadn't troubled to test for.

Re: Errors: TLDR: Check your Makefile and Makefile.in. It looks like stuff is missing that is in the Makefile.in you committed and that I just updated to.

The first error looks like something has crept back into Makefile from before the move of the scripts/v3d-dist-rk05.os8 to its new home and new name scripts/v3d/dist-rk05.os8

The second error looks like a failed dependency. It's not building bin/e8.tu56.

If you have obj/os8pkg/e8.mk, and Makefile.in has the last line -include obj/os8pkg/*.mk, then you should get the dependency that builds it.

The e8.mk file should look like this:

E8_SRCS:= \
    ./src/e8/AUTHORS.md\
    ./doc/e8-manual.md\
    ./doc/e8-manual-pdf.css\
    ./doc/graphics/e8-buffer.svg\
    ./src/e8/README.TX\
    ./src/e8/e8cmds.tx\
    ./src/e8/e8srch.tx\
    ./src/e8/e8defs.pa\
    ./src/e8/e8base.pa\
    ./src/e8/e8file.pa

E8_TU56_SCRIPT =  $(MISC_SCRIPTS_DIR)/e8-tu56.os8


bin/e8.tu56: $(E8_SRCS) $(E8_TU56_SCRIPT) | $(OS8_TOOLTIME)
    $(OS8RUN) $(E8_TU56_SCRIPT)

Did I forget to fossil add scripts/os8pkg/e8.pspec?

(21) By Bill Cattey (poetnerd) on 2020-09-14 01:15:43 in reply to 20 [link] [source]

I know what the problem is with e8.tu56 being made. But I don't know how to fix it.

At issue: Although the .mk files create all the dependencies, there is nothing on Makefile.in that actually depends on the packages.

This came from the change when:

$(V3D_RUNTIME): $(V3D_RK05_SCRIPT) $(OS8_TOOLTIME) @CC8_TU56@ @E8_TU56@ | 
$(PIDP8I_SIM) $(OS8RUN_OUTFILES)
    $(OS8RUN)@OS8_OPTS@ $(V3D_RK05_SCRIPT)

became:

$(V3D_RUNTIME): $(V3D_RK05_SCRIPT) $(OS8_TOOLTIME) $(PKGS_INCLUDE) | 
$(PIDP8I_SIM) $(OS8RUN_OUTFILES)
    $(OS8RUN) @OS8_OPTS@ $(V3D_RK05_SCRIPT)

The @CC8_TU56@ @E8_TU56@ was the dependency trigger.

I think the way to fix this is to add code into the pspec loop at the end that would generate a block of Makefile.in code like this:

ALL_PKGS := \
    bin/e8.tu56 \
    bin/cc8.tu56

Then the unfinished code above makes sense. It changes to:

$(PKGS_INCLUDE): $(ALL_PKGS)
    bin/os8pkg include @OS8_PKGS_INSTALLED@

I know how to pass into Makefile.in a variable definition. So I knew how to set @OS8_PKGS_INSTALLED@.

How do I create the ALL_PKGS definition? What kind of care must be taken if there turn out to be no pspec files in .../scripts/os8pkg/?

(23) By Warren Young (tangent) on 2020-09-14 15:40:15 in reply to 21 [link] [source]

How do I create the ALL_PKGS definition?

I think you just want a regsub call in auto.def over the *.pspec list the script collects already.

What kind of care must be taken if there turn out to be no pspec files in .../scripts/os8pkg/?

Given that we ship those files, I think we can say there's always at least one there. If someone removes all of them manually, they've shot their own foot.

You can diagnose it if you like. I'd be inclined to consider it a fatal configure error. Our hypothetical hacker needs at least one package spec file or needs to rip out the whole mechanism.

(22) By Warren Young (tangent) on 2020-09-14 15:35:31 in reply to 20 [link] [source]

It looks like stuff is missing that is in the Makefile.in

I don't see how. To check, I did "fossil clean && ./configure && mmake" to force a clean checkout build. This time it ran to completion, but it blew past the same "fatal error":

Initializing directory of RKA1: in obj/ock-cusps-src.rk05
At line 3, /usr/local/src/pidp8i/scratch/bin/e8.tu56 must exist but was not found. Not mounting.

Fatal error encountered in /usr/local/src/pidp8i/scratch/obj/os8pkg/pkgs.os8 at line 3:
	mount dt1 $os8mo/e8.tu56 ro required

Saying "mmake" again shows that the build did not in fact complete, as it goes on to build a bunch of things, leading to this complaint:

At line 3, /usr/local/src/pidp8i/scratch/bin/e8.tu56 must exist but was not found. Not mounting.

Fatal error encountered in /usr/local/src/pidp8i/scratch/obj/os8pkg/pkgs.os8 at line 3:
	mount dt1 $os8mo/e8.tu56 ro required

Wondering then whether this was another parallel make issue, I started over clean and did a single-core "make". It built all of the prerequisite C software, then started in on the pieces that require SIMH, stopping with a repeat of the e8.tu56 complaint.

And it isn't wrong: bin/e8.tu56 is indeed not there. So, I said "make bin/e8.tu56", it ran to completion without complaint, and I restarted "make", and it then choked on missing bin/cc8.tu56. "make bin/cc8.tu56" fixed that, so I restarted "make" yet again. This time it ran to completion without error.

There remains one more problem, though: running "make" again redoes some work:

bin/os8pkg include  e8 cc8
bin/os8-run  ./scripts/os8/v3d/boot-rk05.os8
...etc...

That is, it rebuilds the packages and reinstalls them into the OCK image.

I believe all of this comes down to undeclared dependencies.

The e8.mk file should look like this:

It does.

Makefile.in has the last line -include obj/os8pkg/*.mk

It does.

Did I forget to fossil add scripts/os8pkg/e8.pspec?

I've got it, but you can check that yourself from your end: "fossil extra" reports files not committed.

Some developers make calling that part of their pre-commit process. I don't, because I don't keep my .fossil-settings/*-glob* rules as up-to-date as I should. ("fossil set | grep -- -glob")

If you want to get those rules tightened up so that "fossil extra" always gives an empty result when all files in the tree are accounted for one way or another, you're welcome to do so.

(24) By Bill Cattey (poetnerd) on 2020-09-15 03:48:39 in reply to 22 [link] [source]

Root cause of the error:

/usr/local/src/pidp8i/scratch/bin/e8.tu56 must exist but was not found. Not mounting.

is that nothing depends on the packages, and so nothing builds them. That was the point of my inquiry for how to define ALL_PKGS above.

It turned out that I didn't need to use regsub. I've just checked in an update that should fix the problem:

auto.def now defines OS8_PKGS_All and populates it with all found packages:

OS8_PKGS_All =  \
    $(E8_PKG_BIN) \
    $(CC8_PKG_BIN)

os8pkg now uses a high level name for the package file because it knows the format, but auto.def and Makefile.in do not. So now e8.mk contains:

E8_PKG_BIN = bin/e8.tu56

E8_TU56_SCRIPT =  $(MISC_SCRIPTS_DIR)/e8-tu56.os8

$(E8_PKG_BIN) : $(E8_SRCS) $(E8_TU56_SCRIPT) | $(OS8_TOOLTIME)
    $(OS8RUN) $(E8_TU56_SCRIPT)

I corrected the "incomplete command: in Makefile.in:

$(PKGS_INCLUDE):  $(OS8_PKGS_ALL)
    bin/os8pkg include @OS8_PKGS_INSTALLED@

But it does not fix the problem.

Although V3D_RUNTIME and OCK_RUNTIME depend on PKGS_INCLUDE, and PKGS_INCLUDE depends on OS8_PKGS_ALL and OS8_PKGS_ALL names all the package image files, the package image files do not build.

Any guess why?

(25) By Bill Cattey (poetnerd) on 2020-09-15 04:10:05 in reply to 24 [link] [source]

How come:

$(V3D_RUNTIME): $(V3D_RK05_SCRIPT) $(OS8_TOOLTIME) $(PKGS_INCLUDE) bin/e8.tu56 | $(PIDP8I_SIM) $(OS8RUN_OUTFILES)
    $(OS8RUN) @OS8_OPTS@ $(V3D_RK05_SCRIPT)

works to build bin/e8.tu56

but

$(V3D_RUNTIME): $(V3D_RK05_SCRIPT) $(OS8_TOOLTIME) $(PKGS_INCLUDE) ) $(E8_PKG_BIN)  | $(PIDP8I_SIM) $(OS8RUN_OUTFILES)
    $(OS8RUN) @OS8_OPTS@ $(V3D_RK05_SCRIPT)

does not?

the included e8.mk says:

E8_PKG_BIN = bin/e8.tu56

E8_TU56_SCRIPT =  $(MISC_SCRIPTS_DIR)/e8-tu56.os8

$(E8_PKG_BIN) : $(E8_SRCS) $(E8_TU56_SCRIPT) | $(OS8_TOOLTIME)
    $(OS8RUN) $(E8_TU56_SCRIPT)

That's where bin/e8.tu56 is defined. Why doesn't $(E8_PKG_BIN) or it's concatenation, OS8_PKGS_ALL work?

(26) By Warren Young (tangent) on 2020-09-15 07:48:43 in reply to 25 [link] [source]

Move -include obj/os8pkg/*.mk above the first use of variables defined in those files.

mkadrules gets away with its outputs being included last because it only defines transformation rules, not any variables used higher up.

(27) By Bill Cattey (poetnerd) on 2020-09-15 20:39:34 in reply to 26 [link] [source]

I discovered that it breaks EVERYTHING if you put the include too early in the file.

Originally I put it at around line 377, just before the assignment of Makefile variables that were imported from auto.def.

The resulting error was:

wdc-home-3:trunk wdc$ ./configure
Host System...x86_64-apple-darwin18.7.0
Build System...x86_64-apple-darwin18.7.0
C compiler... cc -g -O2
...
src/SIMH/PDP8/Makefile is unchanged
Created tools/simh-update from tools/simh-update.in
Packages selected:  e8 cc8
Packages variable:  $(E8_PKG_BIN) $(CC8_PKG_BIN)
Packages selected scripts:  \
    obj/os8pkg/e8.os8 \
    obj/os8pkg/cc8.os8

All packages:  \
    $(E8_PKG_BIN) \
    $(CC8_PKG_BIN)

Makefile is unchanged
wdc-home-3:trunk wdc$ make
cc  -c -w -O2 src/cc8/cross/code8.c -o obj/cc8/cross/code8.o
error: unable to open output file 'obj/cc8/cross/code8.o': 'No such file or
    directory'
1 error generated.
make: *** [obj/cc8/cross/code8.o] Error 1

However the most recent checkin with the include at the last minute, before the very first actual use of OS8_PKGS_SELECTED seems to work.

(28) By Bill Cattey (poetnerd) on 2020-10-26 03:38:12 in reply to 27 [link] [source]

Although it took me off on a tangent for a while, I've converted the advent.tu56 binary blob to a "Build from source using os8pkg" subsystem.

This has resulted in a much smaller, totally generic boot-rk05.os8 script:

# Install the final packages to our patched rk05 image
# to create the boot image we normally use.

copy $os8mo/v3d-patched.rk05 $os8mo/v3d.rk05
mount rk0 $os8mo/v3d.rk05 required

boot rk0

# Include our dynamically specified packages.
include $build/obj/os8pkg/pkgs.os8

# Squish our device as our last step!

os8 SQUISH DSK:/O
os8 SQUISH SYS:/O

With advent delivered as the proof of concept, it seems like the next step is to move the following subsystems off of v3d-patched.rk05 and under os8pkg:

  • music
  • ba
  • k12
  • chess
  • dcp
  • focal69
  • uwfocal
  • vtedit
  • LCMOD

One consideration is, "How far do we want to step away from binary blobs?"

The ba subsystem is all source code and obviously should be in a POSIX directory.

I think the way forward would be:

  1. Unpack ba into POSIX and migrate that as "from source" to os8pkg.
  2. Start the others as just copying binary blobs with comments in the .pspec file on how to unpack them into build-from-source where possible.

That solves all the easy, leaf node cases.

It seems to me that applying os8pkg to packages that are in the patched or TOOLTIME layers is a design/architectural gap I've not thought through.

Indeed, the boot-rk05.os8 script above assumes ALL subsystems managed os8pkg are leaf notes to add to the boot packs. It seems like I've cleverly avoided actually implementing a real package manager with cross-package dependency management. :-D

I suppose I could learn how far I can push the current archtecture by trying to build the ock with os8pkg.

Perhaps there's a more general approach than "all packages selected are includes into obj/os8pkgs/pkgs.os8".

Two corner cases that will drive the architecture forward:

  1. Being able to choose whether or not to install SABR.SV on TOOLTIME based on whether or not cc8 or FORTRAN II have been selected for inclusion.
  2. Getting FORLIB.RL and DLOG.RA out of the local.tu56 binary blob and making them available for the patching process.

It could be that we've already agreed on a scope that eliminates consideration of case 1: We currently build all packages, but we don't install them all onto the boot packs. Or perhaps the architecture based on that approach means that os8pkg learns how to delete stuff that would ordinarily be inherited from the TOOLTIME packs.

(29.2) By Warren Young (tangent) on 2020-10-26 15:05:36 edited from 29.1 in reply to 28 [link] [source]

the next step is to move the following...under os8pkg:

Sure, sensible.

One possible earlier step, though: do you have enough packages building and working properly yet to consider os8pkg stable enough to merge to trunk? If so, then we can announce it to the user list for early testing.

My rule of thumb is 3 reuses before something is considered proven reusable, but this is your call.

I'm not asking for perfect and finished, just to the point that creating the N+1'th package is likely to not need a destabilizing update to os8pkg to make it work. Minor updates on trunk are fine, following the "every commit on trunk builds and runs" rule.

LCMOD

That one seems tricky, particularly the uninstall step.

How far do we want to step away from binary blobs?

Taking your list:

  • music: I don't see that you have a choice; must be binary, no?
  • ba: I'd prefer that these were stored as POSIX ASCII files in our PiDP-8/I source tree — src/basic-games? — and copied to the package as *.BA following existing os8-cp -a rules.
  • k12: It's FOSS, so build from source for binary distribution.
  • chess: Same as K12 if sources are available
  • dcp, focal69: Treat it the same as OCK and such, for the same reasons
  • uwfocal: Probably the FOSS argument again
  • vtedit: Store the TECO macros and such as in-tree sources, as with *.BA

I've cleverly avoided actually implementing a real package manager with cross-package dependency management.

Aren't all of the above in fact leaf nodes, with no interdependencies?

At some point, you're going to have to define an OS/8 core that you can't pare back any further, which suffices only to load the first level of non-core packages. PIP, for example, should be in the OS/8 core, even though it's technically not in the "kernel", as it were, nor in CCL.

Harder cases are FORTRAN II and IV. I'm of a mind to consider them optional, which then means the dependency chain for Adventure is

ADVENT → F4 + FRTS → RALF → LOAD → core

Likewise, CC8 is:

CC8 → FORT + FORLIB → SABR + LIBSET → LOADER → core

OS/8 BASIC seems like a much easier case: definitely optional, installed only by configuration — e.g. ./configure --enable-os8-basic — or when os8pkg is asked to install something based on BASIC.

We currently build all packages, but we don't install them all onto the boot packs.

While there do exist package systems that always build from source as part of "install" — e.g. early versions of Homebrew, Gentoo, etc. — I'm not a big fan of them, particularly when it takes as much time as I expect this to take on a Pi. It's something to be done once, up front, so the user just installs and uninstalls packages without counting the cost.

(30) By Bill Cattey (poetnerd) on 2020-10-26 16:39:55 in reply to 29.2 [link] [source]

As pointed out in off-thread conversation, it's been quite a while since the last release. We want users to benefit from the new ock packs.

I think it is sensible to push os8pkg across the finish line for the next release, and to try and simplify the testing so as to get the benefit of the work.

I think the next steps are:

  1. Warren does a test build in the branch to get independent verification that cc8, e8, and advent build and work in the new regime.
  2. Bill pulls the os8pkg branch into the trunk.
  3. We announce a testing period.
  4. Bill migrates more packages to os8pkg.
  5. While 1-4 above work, we come to agreement on the revisions to the test regime.

(31) By Bill Cattey (poetnerd) on 2020-10-27 03:58:34 in reply to 30 [link] [source]

I've migrated the ba.tu56 binary blob controlled by option ba to sources in src/basic-games controlled by option basic-games and managed by scripts/os8pkg/basic-games.pspec.

I was delighted to discover that the build: section could be used to run os8-cp to copy the files to a new .tu56 image, obviating the need to create a scripts/misc/basic-games.os8 script whose sole purpose would be a bunch of cpto lines.

I was relieved realize that I needed to disallow wild carding in the outputs: section of a .pspec file before someone ran uninstall on cc8 and deleted all .SV files from SYS:.

There are a couple issue that I'm not sure how to fix:

  1. make always thinks it needs to refresh the package installs. It shouldn't. There's some dependency loop or something happening in auto.def, I think.
  2. I think the use of os8-cp in the build file needs another hook to delete the old .tu56 image. Perhaps a simple additional command rm -f basic-games.tu56 will suffice.

Anyway, bed time now.

(32) By Bill Cattey (poetnerd) on 2020-10-28 02:24:25 in reply to 31 [link] [source]

I have resolved the two issues.

Issue #1 is resolved with checkin 513d950f14. A typo in Makefile.in was depending on obj/os8pkgs/pkgs.os8 but the home of that file is os8pkg (singular). make -d generated 16M of log, but showed me the dependency failure.

Issue #2 is resolved with checkin f9134d40c3. I added the rm of the destination image to the builder script.

Are you able to confirm that the os8pkg branch builds for you with working advent, cc8, e8 and basic-games packages? They should install and uninstall on command as well.

When you confirm those things, we can pull the os8pkg branch into trunk.

(33) By Warren Young (tangent) on 2020-10-28 16:41:50 in reply to 32 [link] [source]

The complaints about the current length of os8pkg commands aside, which I brought up in the other thread, this is much better: far more useful to the end user. Thank you!

I do have ideas for improvement, but whether you do them now or consider them "v2.0" sorts of things is up to you.

The biggie is that I'd like the pspec language to be largely insensitive to whitespace, allowing the current files to be indented like Python code to make the sections clear, though without Python's dogmatic requirement for precise whitespace. Ideally, it should tolerate files like this:

    format: tu56

    inputs: 
        src/basic-games/*.BA
        src/basic-games/*.IN

    outputs:
        DSK:<DTA1:BINGO.BA
        ...            

So:

  1. Allow section values to be "cuddled" up with the section name when there's only one line as the value for that section, as will always be the case for format.

  2. Allow entirely blank lines. (May already do; didn't check.)

  3. Allow wildcards on the input side. (I saw the commit comment about wildcards wrecking things on the "outputs" side, so I'm not asking for that.)

Definitely in the v2.0 category is that there should be sanity checking and/or inference between the input and output sides, so that you either don't have to list the outputs explicitly — they're computed from the inputs and the format type — or if you decide you still should list them as you must now, that the tool checks that the inputs section doesn't list files that don't have a corresponding entry on the outputs side, and vice versa. I've seen good and useful packaging systems that do it both ways, so it's up to you which way you go.

Nit: Is there a good reason why src/basic-games/README.md is installed? That'll cause conflicts among packages. Given the lack of anything like /usr/share/doc/basic-games on OS/8, I think what you want instead is a brief BASGAM.TX sort of file, which refers the user to the README.md file on the host side. Probably also your new wiki article.

(34) By Bill Cattey (poetnerd) on 2020-10-29 00:59:59 in reply to 33 [link] [source]

I've updated doc/os8pkg to clarify that your many of your initial syntactic suggestions are already supported:

  • blank lines.
  • ignoring leading whitespace on a line allowing indenting.
  • comments (Begin a line with a #.)
  • wildcarding in the inputs: section.

I'm reluctant to allow the format: tu56 construct. It would mean making the line parser much more complicated. Right now it's very simple minded, and I like how the simplicity can be exploited:

  • You always know that a section begins with the section heading on its own line.
  • You always know that a section ends with the beginning of a new section.
  • You can have multiple instances of a section scattered through the pspec file, and the are coalesced into one actual section at run time.

The recently checked in kermit-12.pspec gives a pathological case where there is zero overlap between input and output. Indeed the evolution of kermit is such that the input file names get renamed when moved from a distribution onto the host for assembly. The name changes are documented in comments in the source code. For example, in src/kermit-12/k12enb.pal:

/	ASSEMBLY INSTRUCTIONS.

/	IT IS  ASSUMED  THE  SOURCE  FILE  K12ENB.PAL  HAS  BEEN  MOVED AND RENAMED TO
/	DSK:ENBOO.PA.

/	.PAL ENBOO<ENBOO/E/F	ASSEMBLE SOURCE PROGRAM
/	.LOAD ENBOO		LOAD THE BINARY FILE
/	.SAVE DEV ENBOO=2001	SAVE THE CORE-IMAGE FILE

Maybe it's ok that we steer clear of invoking make rules like .c.o to infer output from input. Indeed I advocate making the two lists explicit, because there is a judgment call of whether to put outputs on SYS: or DSK: that may be difficult to infer. Common cases would be .SV outputs land on SYS:, and everything else goes to DSK: but that inference may prove wrong.

(35) By Bill Cattey (poetnerd) on 2020-10-29 02:06:49 in reply to 33 [link] [source]

Re: NIT: Here's how I got to that point:

  1. I had originally had the outputs: set to DSK:<DTA1:*.*.
  2. I had considered a more refined set of outputs: but life was complicated by the existence of MONPLY.B1 and YAHTZE.IN so I stuck with DSK:<DTA1:*.*.
  3. I wanted a README.md file in the source tree.
  4. Installing *.* caused an attempt to install README.md that blew out because there were lines longer than 140 characters.
  5. I decided I wanted to keep README.MD on the packs so I hacked it to death with a broad sword, creating Usage and History sections. That got it to install.
  6. Then I implemented uninstall and realized that wild carding in the outputs: section was a very bad thing.
  7. With a quick ls -c1 and an emacs keyboard macro, I rolled the file names into an explicit outputs: section.
  8. Then your point about conflicts with README.MD was made.

The README.MD file isn't necessary to go onto the OS/8 packs. Indeed it duplicates information in the Wiki.

Seeing your improved explanation of Wiki vs. docs, I wonder if the README.md in the source tree should be much shorter and point at the wiki page, or if it should replace the wiki page.

The original Wiki page had a problem: Because the rows had no lines between them, and the program names were vertically centered, long descriptions were too easily mis-interpreted as belonging to different programs.

I think splitting history and usage into subsections is actually the wrong way to do it. Yes, it got me under 140 character lines, and it cleared up the confusion about which long description went with which program, but I think the price paid was too high.

Q1: Is it possible to fix the original markdown to have the program name be vertically at the top of the row?

Q2: Are there other ways to prevent confusion of row membership?

Q3: Am I right in believing that the markdown architecture uses very long lines as THE way to properly group items in a cell? We had tables in I forget which document that got fixed by going to long lines.

Q4: What would you like to see in a README.md in the basic-games source tree?

(36.1) By Warren Young (tangent) on 2020-10-30 00:15:49 edited from 36.0 in reply to 35 [link] [source]

I wonder if the README.md in the source tree should be much shorter and point at the wiki page, or if it should replace the wiki page.

Given that the DEC book these games come from is out of print, I'd say it falls under the "evergreen content" rule providing you don't intend to make continuing changes to the package.

If you do, then you probably want the wiki article contents in README.md so the docs track the file artifacts they describe.

Consider also that README.md is rendered in /dir URLs underneath the "Finder" view. Some projects mandate a README.md file at every directory level for this reason.

(Not me; ideally, sure, but if there's nothing to say, then say nothing.)

long descriptions were too easily mis-interpreted as belonging to different programs.

It may be worth changing to an HTML-style table so you can add borders between cells, maybe even zebra-striping on alternate rows.

Markdown tables pull their weight best when they fit in 80 columns, so the plain-text form and the HTML form have a clear mapping. If you need line wrapping, then you want HTML, not Markdown.

Is it possible to fix the original markdown to have the program name be vertically at the top of the row?

That would probably require a CSS skin edit on the repo.

Fossil skinning has a "drafts" feature you could use to experiment with this and advocate for a change. The current skin has plenty of things that could be improved, in fact. ("Terminal" blocks inside forum posts, for example.)

THE way to properly group items in a cell?

As far as I'm aware, yes.

What would you like to see in a README.md in the basic-games source tree?

If you decide you want both the embedded doc and the wiki article, then I'd say one is a brief description of the other, with a pointer. DRY, otherwise.

(37) By Bill Cattey (poetnerd) on 2020-10-30 03:06:18 in reply to 36.1 [link] [source]

Thank you for the additional thoughts. You have helped me clarify the vision.

Back in March, I was playing the YAHTZE game. There's actually a bug in the game. I don't know if it's because of bit rot or what. But in my very low priority queue is, "Find and fix the bug that I discovered in YAHTZE."

This means that I do intend for the BASIC games and demos directory to evolve. It's not just "These 5 things from 101 BASIC Computer Games." I consider it to be an evolving repository of good games and demos that gets occasional curation.

So... This means that README.md should become the definitive description of what's here and how it evolves over time. The WIKI page should point at the source.

It sounds like switching to HTML for the table is going to be the best way to do this document and then point to it from the Wiki page.

As a first step, I've removed it from the .pspec manifest and install.

As you suggest above, a BASGAM.TX or BASGAM.DC file should be created with instructions.

(38.1) By Warren Young (tangent) on 2020-10-30 03:40:14 edited from 38.0 in reply to 37 [link] [source]

an evolving repository of good games and demos that gets occasional curation.

Maybe not BASIC "games", then, but some other name. basic-prgs?

On that note, maybe each program gets a separate directory and its own README.md. In a sense, re-write the Ahl book, one chapter/directory at a time.

The WIKI page should point at the source.

…or be deleted entirely as unnecessary.

EDIT: That is, all of the wiki article contents move into the README.md file(s). Some of it may become the start of a /doc/basic-prgs.md, which points at the README.md file(s).

(39) By Bill Cattey (poetnerd) on 2020-10-31 04:04:36 in reply to 29.2 [link] [source]

Status update: The following packages have been converted to the new regime:

  • ba renamed to basic-games
  • k12 renamed to kermit-12
  • chess renamed to chekmo

kermit-12 needs testing.

Next will be vtedit which should be trivial.

Then I'll see about the LCMOD stuff. Having done the integration of LCMOD for ock, this is probably simpler than you think.

For dcp and focal69, you said to treat them the same as OCK and such, for the same reasons. This thread has gotten very long, and I've lost track of the specific of the "treatment" to which you refer. Can you refresh my memory?

(40.2) By Warren Young (tangent) on 2020-10-31 04:37:40 edited from 40.1 in reply to 39 [link] [source]

treat them the same as OCK and such

I'm just making a distinction between "DEC abandonware under license" and "FOSS". I don't think the OS/8 license would pass OSI review, if only for the "solely for non-commercial uses" bit.

However, within our project, since your creation of os8-run, we treat them as much the same: build from source, where possible.

chess renamed to chekmo

This is causing a build failure in the GitHub CI:

make: *** No rule to make target 'scripts/misc/chekmo-tu56.os8', needed by 'bin/chekmo.tu56'.  Stop.

Missing a checked-in file? Missing dependency?

(41) By Warren Young (tangent) on 2020-10-31 11:52:59 in reply to 40.2 [link] [source]

Missing a checked-in file?

It looks like scripts/misc/chekmo-tu56.os8 wasn't committed.

(42) By Bill Cattey (poetnerd) on 2020-10-31 14:59:58 in reply to 41 [link] [source]

Oops! Fixed.

I did do a fossil extras to look for what I might have forgotten to add. Alas I didn't see it.

This is a great opportunity for me to learn...

How can I set up a configuration to ignore stuff like obj/* and all ci-comment files and all files ending with ~?

(44) By Warren Young (tangent) on 2020-10-31 20:21:59 in reply to 42 [link] [source]

How can I set up a configuration to ignore stuff like obj/* and all ci-comment files and all files ending with ~?

A partial (and destructive) solution is fossil clean ; fossil undo which will show "NEW" lines for each file it restored, which now won't include any file we know is delete-able with the recent additions to the clean-glob setting. (After which fossil extra then behaves as you were probably wanting.)

I've posted to the Fossil forum asking for a non-destructive option. [1]

I didn't bother to add things like *~ as my local config doesn't create those. Feel free to adjust .fossil-settings/clean-glob as needed to cover your local use cases.

(47) By Warren Young (tangent) on 2020-11-01 17:32:40 in reply to 44 [link] [source]

fossil extra

You've got another missing file on the os8pkg branch:

gmake: *** No rule to make target 'scripts/misc/focal69-tu56.os8', needed by 'bin/focal69.tu56'. Stop.

My understanding is that you can get email notification of such things by clicking the Watch button at the top of the GitHub mirror of this repo.

(48) By Bill Cattey (poetnerd) on 2020-11-01 19:26:06 in reply to 47 [link] [source]

oops. Fixed.

(43) By Bill Cattey (poetnerd) on 2020-10-31 15:08:33 in reply to 40.2 [link] [source]

That points up one fine point...

With the README.md files, I've not been putting a copyright link because I've been unsure what to say for rights management of what is essentially a manifest file.

What is your recommendation for copyright boilerplate to add to the README.md files in src/{advent,basic-games,chekmo,kermit-12}?

(45) By Warren Young (tangent) on 2020-10-31 20:32:24 in reply to 43 [link] [source]

What is your recommendation for copyright boilerplate to add to the README.md files

That goes in COPYING.md at the top level, not buried down in the per-subdir README.md files. If you want to link from there to ../../COPYING.md#chekmo or similar, that's fine.

And yes, all of these packages should be so-vetted.

(46) By Bill Cattey (poetnerd) on 2020-11-01 05:00:22 in reply to 2 [link] [source]

A way to handle LCMOD.BI, UCMOD.BI, LCBAS.BI, UCBAS.BI as well as FORLIB.RL and DLOG.RA has suggested itself:

Copy the files into a sparse hierarchy that matches the ock hierarchy:

wdc-home-3:os8pkg wdc$ ls -R src/os8/v3d
BASIC		LANGUAGE	SYSTEM		logfile.txt

src/os8/v3d/BASIC:
LCBAS.BI	UCBAS.BI

src/os8/v3d/LANGUAGE:
FORTRAN4

src/os8/v3d/LANGUAGE/FORTRAN4:
DLOG.RA		FORLIB.RL

src/os8/v3d/SYSTEM:
LCSYS.BI	UCSYS.BI

Use scripting in dist-rk05.os8 or patched-rk05.os8 to perform cpto to fetch from source and then act on them as necessary.

I have done this with the LC/UC BI files. And am in the process of doing it for the FORTRAN IV files.

(49) By Bill Cattey (poetnerd) on 2020-11-02 02:58:48 in reply to 46 [link] [source]

The FORTRAN IV files have been done too. Although it's just a cpto of the FORLIB.RL binary blob from the source tree, rather than a build from source.

However, the path to build from source is straightforward:

  1. Unpack sources from al-4545d-sa-fr4-v3d-1.tu56, al-4546d-sa-fr4-v3d-2.tu56, and al-4547d-sa-fr4-v3d-3.tu56 into src/os8/v3d/LANGUAGE/FORTRAN4
  2. Create a forlib-patch.tu56 image using os8pkg that builds from source.
  3. Instead of putting forlib-patch.pspec in scripts/os8pkg we hide it somewhere else and have Makefile.in or some other agent use it.m (Because it's a patch, not a leaf node package.)

(50) By Bill Cattey (poetnerd) on 2020-11-03 22:44:47 in reply to 49 [link] [source]

The new os8pkg system has been merged into trunk. We now have our bootable system layers:

  1. Distribution .tu56 images built into
  2. the v3d-dist.rk05 image. Many leaf subsystems have been moved off this image. Patches are applied to this image to create
  3. v3d-patched.rk05 which we call @OS8_TOOLTIME@ which is used to perform other work, such as building
  4. the OS/8 Combined Kit (ock) dist, and
  5. patched bootable rk05 images.
  6. os8pkg manages software packages that live on the boot images we expect users to run, v3d.rk05 or ock.rk05.

Now comes the next step in refining the test regime: Architecting the test coverage, and the nature of the testing.

Note that we now also have the os8xplode tool that enables unpacking system packs and comparing the components.

(51) By Bill Cattey (poetnerd) on 2020-11-04 18:39:07 in reply to 50 [link] [source]

I have pondered the testing architecture, and I wonder if the current regime conflates two testing activities: repeatability and coverage.

The stated goal of the testing was, I believe, "confirm other software is ok as packages are selected and de-selected in the various configurations."

In practice, what the test runs gave us was confidence that the build was robust and repeatable, because we saw the same results after thousands of builds.

The re-factoring of installable components shrinks the variability of the dist and patched images significantly. The following is the list of components that can be de-selected from the dist image:

  • fortran-ii (libraries only. SABR, LIBSET, and LOADER are installed unconditionally because we don't yet have scaffolding to detect the cc8 requirement for it.)
  • fortran-iv
  • macrel (with a particular version of FUTIL if it's included).
  • basic

Note that the LCSYS.BI/UCSYS.BI scripts are copied in unconditionally, and run if the lcmod option is true.

Packages available for inclusion in the OS/8 RUNTIME packs, v3d.rk05 and ock.rk05:

  • advent
  • basic-games
  • cc8
  • chekmo
  • dcp
  • e8
  • focal69
  • kermit-12
  • music
  • uwfocal
  • vtedit

Items above in bold face are selected by default for inclusion.

The footprint of even the three packages on dist is very well understood.

I suggest that the paradigm of permuting package inclusion as a driver of test cases no longer useful, and that we should brainstorm a different approach.

(52) By Warren Young (tangent) on 2020-11-04 20:02:52 in reply to 51 [link] [source]

fortran-iv

I assume --disable-os8-fortran-iv + --enable-os8-advent breaks?

I mention it only because you bring up the FORTRAN II + CC8 case.

I suggest that the paradigm of permuting package inclusion as a driver of test cases no longer useful

I thought that was the initial point of this effort, and that package management just fell out of it at low cost.

A package permuter may still be useful to catch conflicts, missing dependencies, etc., but when/if that happens, it'll have a good chance of requiring a fix to the package manager rather than to one or more involved packages.

However, that is something to run near release time just as a sanity check. The more often run test scheme will probably do something like:

  1. Build a minimal V3D image (or reuse the one used in the build step)
  2. Install each package in succession on a clean copy of that image.
  3. Run canned tests encoded in the pspec file: can CC8 build a program, does that program run, etc.
  4. Uninstall each package, then diff the clean and sullied media: if there are substantive differences, it probably means "uninstall" is broken or similar.
  5. Install all packages together and re-run all tests. If a test breaks, it probably means you have a package conflict.
  6. Build OCK media paralleling the clean-copy V3D and goto 2.

(53) By Bill Cattey (poetnerd) on 2020-11-04 20:31:55 in reply to 52 [link] [source]

Run canned tests encoded in the pspec file

Yes.. That's the crux of the biscuit.

can CC8 build a program, does that program run, etc.

I was going to include an example of running cc8 and then ask how might we represent the expect sequence that test it. Unfortunately cc8 seems to be broken:

.R CC

>ps.c


IOER ERROR AT LOC 31271

We need to determine if this is something I broke with packaging or something gone sideways with the cc8 v2.0 integration in checkin 9c75595f59.

(54.1) By Bill Cattey (poetnerd) on 2020-11-04 22:05:02 edited from 54.0 in reply to 53 [link] [source]

It's v2.0, not my packaging. I performed:

fossil merge --backout 9c75595f59
rm bin/cc8.tu56
make
make run

The resulting packs build ps.c and run it just fine:

.EXE CCR
$JOB COMPILE AND RUN C PROGRAMME


>ps.c



                           1
                         1   1
                       1   2   1
                     1   3   3   1
                   1   4   6   4   1
                 1   5  10  10   5   1
               1   6  15  20  15   6   1
             1   7  21  35  35  21   7   1
           1   8  28  56  70  56  28   8   1
         1   9  36  84 126 126  84  36   9   1
       1  10  45 120 210 252 210 120  45  10   1
     1  11  55 165 330 462 462 330 165  55  11   1
   1  12  66 220 495 792 924 792 495 220  66  12   1
Completed

#END BATCH

(55) By Bill Cattey (poetnerd) on 2020-11-05 04:03:49 in reply to 54.1 [link] [source]

While we await help from Ian on cc8, let's brainstorm some basic smoke tests for different packages and see if an over-arching structure suggests itself:

e8

Recognizing that the output is going to have a dependency on the configured screen size, we could start it and "expect" some kind of screen draw.

advent

.R FRTS
*ADVENT$
Location of text database (ATEXT.DA) > 
Location of text index    (AINDX.DA) > 
Location of saved games   (ASAVE.DA) > 
Location of text input   (ADVENT.TX) > 
Welcome to Adventure!!  Would you like instructions? 

> no
You are standing at the end of a road before a small brick building. 
Around you is a forest.  A small stream flows out of the building and
down a gully.

> quit
Do you really want to quit now?

> y
OK! 

You scored  32 out of a possible 350 using     1 turns.
You are obviously a Rank Amateur.  Better luck next time.

To achieve the next higher rating, you need   4 more points.

.

chekmo

.R CHEKMO

CHEKMO-II
W. YOUR MOVE? BD

BR BN BB BQ BK BB BN BR
BP BP BP BP BP BP BP BP
-- ** -- ** -- ** -- **
** -- ** -- ** -- ** --
-- ** -- ** -- ** -- **
** -- ** -- ** -- ** --
WP WP WP WP WP WP WP WP
WR WN WB WQ WK WB WN WR

W. YOUR MOVE? ^C
.

focal-69

.LOAD FOCAL.BN/G
*T "HELLO WORLD"!
HELLO WORLD
*T 5.0
=    5.0000*L
3206
3217
3217
4617

.

uwfocal

.R UWF16K
*T 5.0!
 5.000000000E+00
*T PI
 3.141592654E+00*^C
.

basic-games

Pick one or more and run it.

kermit-12

TBA

dcp

Include a simple .SV or .BN file to disassemble and check output.

music

We can't test this just yet.

vtedit

I don't know how to test this.

(56) By Warren Young (tangent) on 2020-11-05 18:46:16 in reply to 55 [link] [source]

an over-arching structure

Each test can be Python code, eval'd in the os8pkg test context, with the os8script API available so the test can drive the simulator through our wrapper over pexpect.

e8, vtedit

This is basically the GUI testing problem recast in curses. I say we punt it for v1.0. If someone wants to come up with a curses-based test system, we can add tests for them later.

Until then: return True.

focal-69, uwfocal

I'm thinking these could develop into a full language regression test suite, which would then support your later efforts to create multiple uwfocal versions. The FOCAL,1969 tests could distinguish that version from other FOCALs, etc.

Basically, go through each language's manual and write a test for each claim, verifying it against the actual implementation.

This suggests we want a method of including potentially many tests from a subdirectory rather than write them directly in the pspec file. I'm thinking like test/os8pkg/uwfocal/*.py.

kermit-12

It should be possible to configure a loopback through SIMH telnet ports, so you can get two simulators running and transfer a file from one to the other, then back.

Include a simple .SV or .BN file

…or even do it on one of those that's always included. It'll result in a large output, but disk space for storing images produced by a 32 kWord machine is cheap. As long as I/O time doesn't become a problem, the test sizes can be effectively arbitrarily large.

(57) By Bill Cattey (poetnerd) on 2020-11-06 05:09:34 in reply to 56 [link] [source]

That means that every test is open coded, rather than table driven.

I wonder if there's a way to generalize it into a set of submissions/responses that could be table driven.

I also wonder if the os8script API is rich enough to handle the trial and recovery to boil the Q/A down to success.

By the way, I suspect that the test of v3d-dist.rk05 of "Use it to build the subsequent layers," is a pretty rigorous test.

(58.1) By Bill Cattey (poetnerd) on 2020-11-11 01:36:55 edited from 58.0 in reply to 57 [link] [source]

I've integrated the OCOMP Octal Compare and Dump utility into the dist boot images (so all higher layers get it.)

OCOMP is integrated into os8script.py, os8-run, and os8pkg verify to do a binary compare under OS/8.

One can do

os8pkg verify pkg1 .. pkgn

and grep for "Failed".

(59) By Warren Young (tangent) on 2020-11-11 12:45:07 in reply to 58.1 [link] [source]

Zippy!

(60) By Bill Cattey (poetnerd) on 2020-11-14 04:54:26 in reply to 59 [link] [source]

Check out tools/os8-progtest

(Note that it's not yet a .in file because I wanted quick turn-around on testing.)

wdc-home-3:trunk wdc$ tools/os8-progtest chekmo advent cc8 uwfocal
chekmo: Test Passes!
advent: Test Passes!
cc8: Test Passes!
uwfocal: Test Failed.
	Expecting: { 3\.500000000E\+00\*$}
	Got: {
?0<.0 
*
*}
wdc-home-3:trunk wdc$ tools/os8-progtest uwfocal
uwfocal: Test Passes!

uwfocal is fragile. It's the keyboard buffer.

Currently you can specify multiple tests, and the program exits with status -1 if any testing fails.

It's totally table driven, and indeed could be fed files. See the _test_strings and _test_replies arrays.

There is no conditional pathways. For example, if you run the test on advent after it's been run once, it fails, because we step through the dialog. If the dialog isn't needed we fail:

wdc-home-3:trunk wdc$ tools/os8-progtest advent
advent: Test Failed.
	Expecting: {LOCATION OF TEXT DATABASE\s+\(\S+\).*}
Got: {ADVENT$
WELCOME TO ADVENTURE!!  WOULD YOU LIKE INSTRUCTIONS? 

> }

Any thoughts on further expanding and systematizing this tester? Options I see are:

  1. Keep adding hard-coded sets of tests to the _test_strings and _test_replies arrays.
  2. Move os8-progtest into os8pkg.
  3. Define a syntax and parser to generate input from files.

Thoughts?

(61) By Warren Young (tangent) on 2020-11-14 08:51:09 in reply to 60 [link] [source]

It's totally table driven, and indeed could be fed files.

Yes, it should be. Imagine a complete CC8 test suite comprising hundreds of individual tests.

Just as a f'rinstance, we might have a separate test for each operator, even more than one test per operator to cover details like the fact that in native OS/8 CC8, & and && are implemented by the same code, which means && doesn't short-circuit! Should that change, we'll want a regression test that demonstrates it.

Consider how useful such a test suite would've been on this latest go-round: if the test suite didn't run, I wouldn't have merged the CC8 branch.

See the _test_strings and _test_replies arrays.

Those need to be sharded by program (e.g. scripts/test/package/cc8/ps/01.test or something) and then arranged into send/expect pairs. Once again, imagine when this gets to hundreds of tests: you don't want to be jumping up and down between these two separate dicts to match "expect" to "send".

if you run the test on advent after it's been run once, it fails

To the extent that any test depends on persistent state, it needs to reset that to a known state before running. In your Advent example, I assume there's a file you can delete to make the DB question to come back.

Move os8-progtest into os8pkg.

Consider these syntax ideas:

os8pkg test cc8                      # run all tests
os8pkg test cc8/operators            # run all operator tests
os8pkg test cc8/operators/bin-and    # test only the & operator

(62) By Bill Cattey (poetnerd) on 2020-11-15 03:31:24 in reply to 61 [link] [source]

Thanks for thinking about this.

I've not yet implemented everything you suggested. Merely the next step.

I finally caved and learned YAML. Why? Because I decided the testing needed state machines, and I wanted to be able to specify them.

Check out the latest version of os8-progtest. You will need to install pyyaml. I agree with the principle that one must do a proper reset for testing, however the situation with advent gave an opportunity to develop the state machine concept.

As currently implemented, it either steps through database, index, saved, and input states to instructions, or it jumps to instructions if instead of being prompted for the first file, it gets, WELCOME TO ADVENTURE!!.

Here is tools/testing/advent.yml:

program: advent
states: 
    'start': ["R FRTS\r",[["\n\\*", 'advent']]]
    'advent': ["ADVENT\e", [[ "LOCATION OF TEXT DATABASE\\s+\\(\\S+\\).*", 'database'],
                       ["WELCOME TO ADVENTURE!!", 'instructions']]]
    'database': ["\r", [["LOCATION OF TEXT INDEX\\s+\\(\\S+\\).*", 'index']]]
    'index': ["\r", [["LOCATION OF SAVED GAMES\\s+\\(\\S+\\).*", 'saved']]]
    'saved': ["\r", [["LOCATION OF TEXT INPUT\\s+\\(\\S+\\).*", 'input']]]
    'input': ["\r", [["WOULD YOU LIKE INSTRUCTIONS\\?.*", 'instructions']]]
    'instructions': ["n\r", [["\r\n> $", quit]]]
    'quit': ["quit\r", [["DO YOU REALLY WANT TO QUIT NOW\\?\r\n\r\n> ", 'yes']]]
    'yes': ["yes\r", [["\n\\.$", 'success']]]

Notice how each state says what the question is, and gives as the first array item the answer you give to the question, and what the expected answer is that brings us to the next named state.

There is a debug option to pretend all state changes are successful to make sure you reach the end success state. The code would also detect a fail state.

If there is no start state or if there is an attempt to go to an un-named state, you get an error.

While I let my brain cool down, I'll meditate on how this syntax would expand to allow multiple test cases.

(63) By Bill Cattey (poetnerd) on 2020-11-15 18:01:03 in reply to 62 [link] [source]

At the present time I don't want to implement sub tests.

Instead I felt that a list of tests was a more useful approach.

That is now implemented and cc8 can test ps, fib or both:

cc8.yml:

'ps':
    'start': ["EXE CCR\r", [["PROGRAMME\\s+>", 'progname']]]
    'progname': ["ps.c\r", [[".*924.*COMPLETED\r\n\r\n#END BATCH\r\n\r\n.$", 'success']]]
'fib':
    'start': ["EXE CCR\r", [["PROGRAMME\\s+>", 'progname']]]
    'progname': ["fib.c\r", [["OVERFLOW AT #18 = 2584\r\n\r\n#END BATCH\r\n\r\n.$", 'success']]]

Produces:

wdc-home-3:trunk wdc$ tools/os8-progtest cc8
cc8:ps Test Passes.
cc8:fib Test Passes.

I feel the tester has crossed over into being ready for production use. I see some decisions to be made:

Q1. Is the tester something we expect to use only at build time, (and therefore living in tools) or something we expect people to use all the time (and therefore living in bin.)

Previous comments by you showed a preference for including it in os8pkg and therefore an all-the-time usage model.

Q2. Depending on the answer to Q1, where should the test files live? I've currently got them in tools/testing because I came down on the other side of the all-the-time usage model. If we do opt for all-the-time use, then we probably need to pick a new home and move the tests out of tools.

Q3. Should we keep os8-progtest separate from os8pkg?

Here is why I think the answer is yes: Then we can conceive of tests that have nothing to do with subsystems we have packaged up.

The current architecture does not make any use of pspec files, or any of the other files built or used by os8pkg. There are no cross dependencies.

With these conclusions acting as the basis for the current implementation, are there ideas I have missed reviewing that pull in a different direction?

(64) By Warren Young (tangent) on 2020-11-16 00:11:16 in reply to 63 [link] [source]

only at build time,

Yes, or rather, only within the source tree. Thus we could ask someone to go back into the source tree and re-run a test when trying to diagnose a reported problem even if they'd installed via a binary OS image, for example.

a preference for including it in os8pkg and therefore an all-the-time usage model.

I don't see that those two are necessarily tied together, but the do-ocracy principle applies: you're doing the work, so you make the rules.

I've currently got them in tools/testing

I don't like having data subdirs of bin dirs. Regardless of the rest of this, wouldn't something like scripts/os8-progtest be more appropriate?

(65) By Bill Cattey (poetnerd) on 2020-11-16 05:05:55 in reply to 64 [link] [source]

Ok. I've moved tools/testing/* to scripts/os8-progtest/. Avoiding subdirs of a tools dir (because it's intended to host executables only) makes sense.

I've hooked os8-progtest.in into auto.def and Makefile.in.

I've also produced documentation in doc/os8-progtest.md.

Feel free to try crafting a test script.

(66.1) By Warren Young (tangent) on 2020-11-17 01:38:28 edited from 66.0 in reply to 65 [link] [source]

Regarding the new docs, aside from the spelling, grammar, Markdown, and whitespace fixes:

  • Split the "Positional Arguments" part of the args table away, since there's only one line. Now it's just prose. Also, you don't need to bold the header row: that's done in CSS.

  • Teased the progname arg discussion entirely apart from the options.

  • Explained a few of the options in more detail. There's more to be done; I didn't bother to look into what --destdir or --target do, for example.

  • While doing so for -d, I found the odd 0-14 value in the code, which is apparently arbitrary and may differ between programs. (Also, the DEBUG flag appears unused.) I'd prefer this was formalized into a logical scheme.

    In my own multi-level logging, I use the following scheme:

    Level Meaning
    1 Fatal error: scream and die
    2 Known problem: may be prefixed with "WARNING: " or similar
    3 Normal status; FYI stuff
    4 Internal status: noisy stuff that doesn't normally appear
    5 Verbose status: really noisy stuff

    In some programs, I have a sixth level between 1 and 2 for non-fatal errors, prefixed with "ERROR: " or similar. These levels are wrapped in functions, so I don't use the numbers explicitly, but instead make calls like "error('The frobnicator grobbled!')" yielding ERROR: The frobnicator grobbled!, which shows up only when the app is running in debug level > 1.

    Programs normally run from a terminal typically send Levels 3+ to STDOUT and levels below "normal" to STDERR. This is part of what gets wrapped by functions like error().

    Programs normally run in the background may prefix log lines with a tag to let you later filter the log for levels. It could be as simple as "2: " on a warning, for example. Such programs usually have a way to increase or decrease the log level without restarting it, so you can dial the noise up and down at need.

    This scheme lets you dial down the verbosity by hiding normal output, which some programs do instead with a --quiet flag or similar.

    It doesn't give you many choices for noisy output, but I find this freeing: if I have 14 levels of "noisy," how do I choose which one to use? Instead, I have "somewhat noisy" and "really noisy," which usually suffices. (Some programs use -v and -vv for a similar reason.) I suppose you could take the scale to 10 if you felt it was necessary, giving 6 levels of noisiness past "normal," but even that feels excessive to me. The tyranny of choice, you know?

  • Regularized the order of -x, --long-x-name ordering. I prefer long-then-short to explain then abbreviate.

  • Cut the ADVENT test down to just the essentials for the doc, then pointed the reader at the full test. Added whitespace to the latter so it fits into 72 columns, for readability on page-width screens with the default CSS fonts. (1024px or so.)

  • The expanded explanation in point 7 under "Crafting New State Machines" is only my supposition for the reason you had for this point. Did I guess correctly?