From 23f59b8aa3ca4f8cb0eb9c762092264c2a295620 Mon Sep 17 00:00:00 2001 From: Rick Guo Date: Thu, 20 Aug 2026 15:41:50 +0800 Subject: [PATCH 1/4] formula: add rscada/libmbus --- rscada/libmbus/0.10.2/libmbus_llar.gox | 120 +++++++++++++++++++++++++ rscada/libmbus/libmbus_cmp.gox | 12 +++ rscada/libmbus/versions.json | 4 + 3 files changed, 136 insertions(+) create mode 100644 rscada/libmbus/0.10.2/libmbus_llar.gox create mode 100644 rscada/libmbus/libmbus_cmp.gox create mode 100644 rscada/libmbus/versions.json diff --git a/rscada/libmbus/0.10.2/libmbus_llar.gox b/rscada/libmbus/0.10.2/libmbus_llar.gox new file mode 100644 index 00000000..d8f2dc27 --- /dev/null +++ b/rscada/libmbus/0.10.2/libmbus_llar.gox @@ -0,0 +1,120 @@ +import ( + "os" + "path/filepath" + "slices" + "strings" +) + +const consumerSource = `#include +#include + +int main(void) { + unsigned char ack = 0xE5; + mbus_frame frame; + mbus_handle *handle; + + memset(&frame, 0, sizeof(frame)); + if (mbus_parse(&frame, &ack, 1) != 0) { + return 1; + } + if (mbus_get_current_version() == 0) { + return 1; + } + + handle = mbus_context_serial("/dev/null"); + if (handle == 0) { + return 1; + } + mbus_context_free(handle); + return 0; +} +` + +id "rscada/libmbus" + +fromVer "0.10.2" + +defaults { + "shared": "OFF", + "fPIC": "ON", +} + +filter => { + for name, values in target.options { + if name != "shared" && name != "fPIC" { + return false + } + for value in values { + if value != "ON" && value != "OFF" { + return false + } + } + } + return true +} + +onBuild ctx => { + installDir := ctx.outputDir + shared := target.options["shared"][0] == "ON" + fPIC := target.options["fPIC"][0] == "ON" + + os.chdir(ctx.SourceDir)! + os.mkdirAll(filepath.join(ctx.SourceDir, "m4"), 0o755)! + if slices.contains(target.require["os"], "darwin") { + glibtoolize! "--copy", "--force" + } else { + libtoolize! "--copy", "--force" + } + autoreconf! "-fi" + + picFlag := "--without-pic" + if fPIC { + picFlag = "--with-pic" + } + + a := autotools.new(ctx.SourceDir, filepath.join(ctx.SourceDir, "_build"), installDir) + if shared { + a.configure "--enable-shared", "--disable-static", picFlag + } else { + a.configure "--disable-shared", "--enable-static", picFlag + } + a.build + a.install + + licenseDir := filepath.join(installDir, "licenses") + os.mkdirAll(licenseDir, 0o755)! + os.writeFile(filepath.join(licenseDir, "LICENSE"), os.readFile(filepath.join(ctx.SourceDir, "LICENSE"))!, 0o644)! + + pcPath := filepath.join(installDir, "lib", "pkgconfig", "libmbus.pc") + pc := string(os.readFile(pcPath)!) + pc = strings.replace(pc, "prefix="+installDir, "prefix=$${pcfiledir}/../..", 1) + pc = strings.replace(pc, "exec_prefix="+installDir, "exec_prefix=$${prefix}", 1) + pc = strings.replace(pc, "libdir="+filepath.join(installDir, "lib"), "libdir=$${prefix}/lib", 1) + pc = strings.replace(pc, "includedir="+filepath.join(installDir, "include"), "includedir=$${prefix}/include", 1) + os.writeFile(pcPath, []byte(pc), 0o644)! + + pkgconfig.use installDir + ctx.setMetadata pkgconfig.lookup("libmbus")! +} + +onTest ctx => { + installDir := ctx.outputDir + testDir := filepath.join(ctx.SourceDir, "_llar_consumer") + os.mkdirAll(testDir, 0o755)! + + sourcePath := filepath.join(testDir, "consumer.c") + os.writeFile(sourcePath, []byte(consumerSource), 0o644)! + + pkgconfig.use installDir + flagsFile := filepath.join(testDir, "libmbus.flags") + os.writeFile(flagsFile, []byte(pkgconfig.lookup("libmbus")!), 0o644)! + + binary := filepath.join(testDir, "consumer") + cc! sourcePath, "-o", binary, "@"+flagsFile + + if target.options["shared"][0] == "ON" { + os.setenv("LD_LIBRARY_PATH", filepath.join(installDir, "lib"))! + os.setenv("DYLD_LIBRARY_PATH", filepath.join(installDir, "lib"))! + } + exec! binary +} diff --git a/rscada/libmbus/libmbus_cmp.gox b/rscada/libmbus/libmbus_cmp.gox new file mode 100644 index 00000000..37d6fc88 --- /dev/null +++ b/rscada/libmbus/libmbus_cmp.gox @@ -0,0 +1,12 @@ +import "strings" + +func normalize(version string) string { + if strings.hasPrefix(version, "v") { + return version + } + return "v" + version +} + +compareVer (a, b) => { + return semver.Compare(normalize(a.Version), normalize(b.Version)) +} diff --git a/rscada/libmbus/versions.json b/rscada/libmbus/versions.json new file mode 100644 index 00000000..25903156 --- /dev/null +++ b/rscada/libmbus/versions.json @@ -0,0 +1,4 @@ +{ + "path": "rscada/libmbus", + "deps": {} +} From 4f377d48a201c8b7ef3bbe5ccdb756b6dbf8e18b Mon Sep 17 00:00:00 2001 From: Rick Guo Date: Tue, 8 Sep 2026 11:57:46 +0800 Subject: [PATCH 2/4] formula: fix darwin libtool bootstrap for rscada/libmbus --- rscada/libmbus/0.10.2/libmbus_llar.gox | 28 +++++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/rscada/libmbus/0.10.2/libmbus_llar.gox b/rscada/libmbus/0.10.2/libmbus_llar.gox index d8f2dc27..8e4e8f6c 100644 --- a/rscada/libmbus/0.10.2/libmbus_llar.gox +++ b/rscada/libmbus/0.10.2/libmbus_llar.gox @@ -1,8 +1,6 @@ import ( "os" "path/filepath" - "slices" - "strings" ) const consumerSource = `#include @@ -60,7 +58,11 @@ onBuild ctx => { os.chdir(ctx.SourceDir)! os.mkdirAll(filepath.join(ctx.SourceDir, "m4"), 0o755)! - if slices.contains(target.require["os"], "darwin") { + + if target.require["os"][0] == "darwin" { + if err := exec("glibtoolize", "--version"); err != nil { + exec! "brew", "install", "libtool" + } glibtoolize! "--copy", "--force" } else { libtoolize! "--copy", "--force" @@ -85,13 +87,19 @@ onBuild ctx => { os.mkdirAll(licenseDir, 0o755)! os.writeFile(filepath.join(licenseDir, "LICENSE"), os.readFile(filepath.join(ctx.SourceDir, "LICENSE"))!, 0o644)! - pcPath := filepath.join(installDir, "lib", "pkgconfig", "libmbus.pc") - pc := string(os.readFile(pcPath)!) - pc = strings.replace(pc, "prefix="+installDir, "prefix=$${pcfiledir}/../..", 1) - pc = strings.replace(pc, "exec_prefix="+installDir, "exec_prefix=$${prefix}", 1) - pc = strings.replace(pc, "libdir="+filepath.join(installDir, "lib"), "libdir=$${prefix}/lib", 1) - pc = strings.replace(pc, "includedir="+filepath.join(installDir, "include"), "includedir=$${prefix}/include", 1) - os.writeFile(pcPath, []byte(pc), 0o644)! + pcDir := filepath.join(installDir, "lib", "pkgconfig") + os.mkdirAll(pcDir, 0o755)! + pc := pkgconfig.new( + name = "libmbus", + description = "Open source M-bus (Meter-Bus) library.", + version = "0.10.2", + URL = "http://www.rscada.se/libmbus/", + libs = ["-L$${libdir}", "-lmbus", "-lm"], + cflags = ["-I$${includedir}"], + )! + out := os.create(filepath.join(pcDir, "libmbus.pc"))! + pc.writeTo(out)! + out.close()! pkgconfig.use installDir ctx.setMetadata pkgconfig.lookup("libmbus")! From 6265f58878f3e0eca6c009ee9628b7c4a449826b Mon Sep 17 00:00:00 2001 From: Rick Guo Date: Tue, 8 Sep 2026 15:37:53 +0800 Subject: [PATCH 3/4] formula: stop installing Homebrew libtool in libmbus --- rscada/libmbus/0.10.2/libmbus_llar.gox | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rscada/libmbus/0.10.2/libmbus_llar.gox b/rscada/libmbus/0.10.2/libmbus_llar.gox index 8e4e8f6c..f0ba01a2 100644 --- a/rscada/libmbus/0.10.2/libmbus_llar.gox +++ b/rscada/libmbus/0.10.2/libmbus_llar.gox @@ -59,10 +59,9 @@ onBuild ctx => { os.chdir(ctx.SourceDir)! os.mkdirAll(filepath.join(ctx.SourceDir, "m4"), 0o755)! + // Host package managers are not part of the formula. Use the libtoolize + // already on the runner (glibtoolize on Darwin) and fail if it is missing. if target.require["os"][0] == "darwin" { - if err := exec("glibtoolize", "--version"); err != nil { - exec! "brew", "install", "libtool" - } glibtoolize! "--copy", "--force" } else { libtoolize! "--copy", "--force" From e55e1263fc22941f32dbf7625278229384d38629 Mon Sep 17 00:00:00 2001 From: Rick Guo Date: Wed, 9 Sep 2026 15:37:55 +0800 Subject: [PATCH 4/4] fix(libmbus): bootstrap with portable libtoolize on Darwin macos-latest does not ship glibtoolize unless Homebrew libtool is installed. CI now installs it, and the formula prefers libtoolize with a glibtoolize fallback instead of hard-coding the Darwin name. --- .github/workflows/test.yml | 2 +- rscada/libmbus/0.10.2/libmbus_llar.gox | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 703cfd93..2bbf4e7e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -116,7 +116,7 @@ jobs: - name: Install macOS build dependencies if: runner.os == 'macOS' - run: brew install autoconf automake gperf groff + run: brew install autoconf automake libtool gperf groff - name: Set up Go uses: actions/setup-go@v7 diff --git a/rscada/libmbus/0.10.2/libmbus_llar.gox b/rscada/libmbus/0.10.2/libmbus_llar.gox index f0ba01a2..a064ab8b 100644 --- a/rscada/libmbus/0.10.2/libmbus_llar.gox +++ b/rscada/libmbus/0.10.2/libmbus_llar.gox @@ -59,12 +59,10 @@ onBuild ctx => { os.chdir(ctx.SourceDir)! os.mkdirAll(filepath.join(ctx.SourceDir, "m4"), 0o755)! - // Host package managers are not part of the formula. Use the libtoolize - // already on the runner (glibtoolize on Darwin) and fail if it is missing. - if target.require["os"][0] == "darwin" { + // GNU libtoolize is `libtoolize` on Linux and `glibtoolize` on Homebrew + // Darwin. Host package managers are not part of the formula. + if exec("libtoolize", "--copy", "--force") != nil { glibtoolize! "--copy", "--force" - } else { - libtoolize! "--copy", "--force" } autoreconf! "-fi"