I’m thinking of rewriting Syn, but this time, with the lessons learned from Syn1, 2, and 3. While I don’t want to rewrite it (again), it’ll be a nice time to simplify the project, and give it a chance to actually function (well) as a LFS-esque package manager.
Hopefully, this can be the final rewrite.
I know there’s not been updates lately, but that’s due to having issues with glibc. I’ll post some words on that soon. In the meantime, enjoy some synfun images!




In this installment, I’ll cover pseudo code and some layouts I’ve chosen.
Most of this is hacked up quickly, but I expect it’ll work OK.
First up, the way a package looks:
package-1.0.syn.tar.gz (sourceball)
+-> synd/
+-> meta (meta data on the archive)
+-> build (the build script)
+-> buildrc (config flags and so forth)
+-> package-1.0.tar.gz (original source, pristine)
package-1.0.syn (binary package)
+-> syn/
+-> [usr/bin/etc/...]
+-> ...
+-> .filesums (MD5 sums of the contents)
+-> .meta-syn (Metainfo on the package)
package-1.0.syn.logs (logball)
+-> logs/
+-> build
+-> configure
+-> stage
+-> synlint (policy checks)
+-> ...
package-1.0.syn.sigs (MD5 sigs, GPG clearsigned)
package-1.0.syn.goodies (list of binaries & libraries)
(JSON)
Here’s my “database” (really a python dict) layout:
Status keys:
UNINSTALLED = "U"
BORKED = "B"
HALF_INSTALLED = "H"
INSTALLED = "I"
HALF_LINKED = "K"
LINKED = "L"
REMOVED = "R"
Package entry:
"package" : {
"linked" : "1.0",
"installed" : [
"4.3" : {
"status" : "I"
},
"1.0" : {
"status" : "L"
}
]
}
This will let me maintain a boatload of versions (in a sane way) of a single package.
Now that we have the DB basics out of the way, let’s go over some of the easy package manager stuff — installing and linking.
We’re ignoring dependencies at the moment :)
A lot of this was stolen (only in principal) from Debian. I like Debian’s method, so I figured I’d take what works and ditch what fails.
First think is the idea of a makefile build script. I called mine “build”.
I don’t like that people edit / override the build script in Debian to do something as simple as add a step or two. As a result, I opted to include an “assist” file. It’s called the “buildrc”, and like everything else, it’s in JSON.
During build, Syn will take these blocks and push them into the env under a standard name. This will let us pass flags / change what’s called for each step of the build file without actually editing the build file.
Similar to the rules file (but yet, also different) the build script contains three core steps:
configure, build, stage
configure’s job is to set up the package for a binary build, this is usually just running configure, some brand of autotools, or setup.py or something.
build’s job is to build the source into whatever format is ready to be installed. In most cases this is the core “make” call, and tons of gcc calls.
stage’s job is to put the files to be installed into the staging directory, to be archived.
The build file (in most cases ) is simply:
#!/usr/bin/make -f
include /usr/share/syn/build/synhelper.mk
The buildrc file:
{
"configure" : "./configure",
"build" : "make",
"stage" : "make install",
"ConfigFlags" : [
"--prefix=/usr"
],
"BuildFlags" : [
"-j3"
],
"StageFlags" : []
}
Let’s have a look at the included script:
configure::
$(CONFIGURE) $(CONFIG_FLAGS)
build::
$(BUILD) $(BUILD_FLAGS)
stage::
$(STAGE) $(STAGE_FLAGS) DESTDIR=$(S_DESTDIR)
This will run:
Configure: ./configure —prefix=/usr
Build: make -j3
Stage: make install DESTDIR=/tmp/syn/…/syn/
Optionally, you may also include “synpatch.mk” before the synhelper.mk to enable patching support. It will apply all patches in the synd/patches directory against the source during the configure step.
Right now it’s simple. It’s set up as:
configure::
@echo "Patching source"
patch -Np1 -i ../synd/patches/*
Works great :)
Eventually, I’ll add support to conditionally patch based on patch headers.
I’ll add more later (when I have more time ;) )
For implementation, I decided to split up the outward facing script into three parts.
This holds all the “major” actions, such as:
This holds all the development actions, such as:
This holds all database query actions, such as:
Next up: Rough cut algorithms
I’ve recently lost internet and cable at the house. Rather then read books, or do something productive with my time “offline”, I’ve decided to do what any sane person would — write a package manager.
Since I have it mostly completed, this will be a documentation of what I did do over the last four days, rather then a jot-down-progress-as-I-go type series. Since I still don’t have internet, beware lag!
I don’t muchly care for complexity, so I want to keep it simple. Dead simple. Simple to use, roll out builds (for the average power user), and manage.
Since I want to keep different package versions around (it’s fun to test for regressions), I want my package manager to be able to swap versions on-demand.
I want it safe to use. When it doubt, bork the internal state rather then bork the system.
Use Python (duh)
Use Pickle to maintain a dict as the “database”.
Use Similinks to link packages into the filesystem
When syn installs a package, it may be installed, but the package won’t be usable until it’s Linked. The workflow should be something similar to:
Uninstalled --> Half-Installed --> Installed --> Half-Linked --> Linked
Next up: Implementation!
Design by Simon Fletcher. Powered by Tumblr.
© Copyright 2010