**Building a single-file file distribution** Tcl and Tk have regular builds of their code as single file distributions. You currently (2022-06-15) need a Github login to access the results (due to anti-bot measures by Github). The builds are processed using Github's infrastructure and do things like running the test suite in lots of configurations, but we're interested on this page in the distribution building code: Tcl's is here: https://github.com/tcltk/tcl/blob/main/.github/workflows/onefiledist.yml Tk's is here: https://github.com/tcltk/tk/blob/main/.github/workflows/onefiledist.yml They use the Github workflow format (which is YAML following a particular schema). Of interest at the top is this: ====== on: [push] ====== which says "build whenever a new push to the git repository is done" (which is usually daily when we synch from `core.tcl-lang.org`) Then there's one actual workflow job per platform (doesn't have to be like that, but it's mighty convenient). Jobs contain a bunch of steps; the workflow succeeds when all the steps for all the jobs succeed. Success of a shell-scripted step is the usual Unix shell definition. ***A walkthrough of the Tcl/Linux build process*** Let's look at the stages for building Tcl for Linux: ====== - name: Checkout uses: actions/checkout@v3 ====== The "Checkout" stage just grabs the code from the Tcl repository (which repo is implicit in the workflow; Github knows that it is being run for the repo). ====== - name: Prepare run: | touch generic/tclStubInit.c generic/tclOOStubInit.c mkdir 1dist echo "VER_PATH=$(cd tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV working-directory: . ====== The "Prepare" step sets some stuff up by running a small shell script. The https://core.tcl-lang.org/tcl/file?name=tools/addVerToFile.tcl&ci=tip%|%`addVertoFile.tcl`%|% script is in the tools directory; we're storing the path to it in the multi-step shared environment so that we can find it easily. ====== - name: Configure run: ./configure --disable-symbols --disable-shared --enable-zipfs working-directory: unix ====== The "Configure" step runs the `configure` script in the `unix` directory. We're making a release build (no symbols) that is static (single file distributions should be this) and includes zipfs (I think that's enabled by default, but might as well be explicit as we definitely want it!) ====== - name: Build run: | make tclsh make shell SCRIPT="$VER_PATH $GITHUB_ENV" echo "TCL_ZIP=`pwd`/`echo libtcl*.zip`" >> $GITHUB_ENV working-directory: unix ====== The "Build" step does the build. In particular, we make `tclsh`, then call our `addVerToFile.tcl` script from earlier to add the real version data into the environment. Finally, we locate the library zip file (produced normally in the build) so that we can also find that easily later. After this step, the environment contains definitions for: * `VER_PATH` - The location of `addVerToFile.tcl` (not actually needed any more) * `TCL_VERSION` - The version of Tcl we've just built * `TCL_PATCHLEVEL` - The patchlevel of Tcl we've just built * `TCL_ZIP` - The location of the library ZIP We don't ''actually'' need `TCL_ZIP` for this build. Probably because the makefiles have gained smarts that used to be held externally. That's good. ====== - name: Package run: | cp ../unix/tclsh tclsh${TCL_PATCHLEVEL}_snapshot chmod +x tclsh${TCL_PATCHLEVEL}_snapshot tar -cf tclsh${TCL_PATCHLEVEL}_snapshot.tar tclsh${TCL_PATCHLEVEL}_snapshot working-directory: 1dist ====== The "Package" step (which works in its own directory) copies the `tclsh`, marks it as executable, and parcels it up into a TAR file (because that keeps the executable bit). We don't bother compressing it; the compression gains are going to be small (and Github's internal infrastructure compresses things anyway). ====== - name: Upload uses: actions/upload-artifact@v3 with: name: Tclsh ${{ env.TCL_PATCHLEVEL }} Linux single-file build (snapshot) path: 1dist/*.tar ====== The "Upload" step takes the built and packaged executable and ships it to the Github artifact distribution system. If we were to want to put the builds elsewhere, this is the step that would change. Other platforms follow a very similar model, but with different details. The packaging step for macOS is particularly messy, but the mess is pretty much localized to just there. Tk follows a similar model, but there's a few more steps to get things right (because Tk depends on more things than Tcl).