From 33d7f78feb9cb10387ecdfdb68dd0ef3c86cf115 Mon Sep 17 00:00:00 2001 From: Greg Pfeil Date: Sun, 1 Mar 2026 10:19:36 -0700 Subject: [PATCH 1/4] Update Haskell licensing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - removes redundant `AGPL-3.0-only` from Cabal package files - changes from “commercial” to “proprietary”, because that’s what’s _actually_ orthogonal to AGPL --- templates/haskell/.config/project/default.nix | 2 +- templates/haskell/LICENSE | 2 +- templates/haskell/LICENSE.commercial | 3 --- templates/haskell/LICENSE.proprietary | 3 +++ templates/haskell/core/{{project.name}}.cabal | 6 ++---- 5 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 templates/haskell/LICENSE.commercial create mode 100644 templates/haskell/LICENSE.proprietary diff --git a/templates/haskell/.config/project/default.nix b/templates/haskell/.config/project/default.nix index b68c002..f2d7f5a 100644 --- a/templates/haskell/.config/project/default.nix +++ b/templates/haskell/.config/project/default.nix @@ -16,7 +16,7 @@ "${dir}/LICENSE.AGPL-3.0-only".source = ../../LICENSE.AGPL-3.0-only; "${dir}/LICENSE.Universal-FOSS-exception-1.0".source = ../../LICENSE.Universal-FOSS-exception-1.0; - "${dir}/LICENSE.commercial".source = ../../LICENSE.commercial; + "${dir}/LICENSE.proprietary".source = ../../LICENSE.proprietary; }; in copyLicenses "core"; diff --git a/templates/haskell/LICENSE b/templates/haskell/LICENSE index a3f833f..d125966 100644 --- a/templates/haskell/LICENSE +++ b/templates/haskell/LICENSE @@ -1,5 +1,5 @@ LicenseListVersion: 3.27.0 -SPDX-License-Identifier: AGPL-3.0-only WITH Universal-FOSS-exception-1.0 OR LicenseRef-commercial +SPDX-License-Identifier: AGPL-3.0-only WITH Universal-FOSS-exception-1.0 OR LicenseRef-proprietary The individual licenses are included in files named “LICENSE.” with a suffix that matches each license’s identifier. diff --git a/templates/haskell/LICENSE.commercial b/templates/haskell/LICENSE.commercial deleted file mode 100644 index 3bc6320..0000000 --- a/templates/haskell/LICENSE.commercial +++ /dev/null @@ -1,3 +0,0 @@ -This software is available for commercial licensing with flexible terms. - -Contact licensing@technomadic.org for more information. diff --git a/templates/haskell/LICENSE.proprietary b/templates/haskell/LICENSE.proprietary new file mode 100644 index 0000000..7193f4b --- /dev/null +++ b/templates/haskell/LICENSE.proprietary @@ -0,0 +1,3 @@ +This software is available for proprietary licensing with flexible terms. + +Contact licensing@technomadic.org for more information. diff --git a/templates/haskell/core/{{project.name}}.cabal b/templates/haskell/core/{{project.name}}.cabal index 86556e9..bba1f65 100644 --- a/templates/haskell/core/{{project.name}}.cabal +++ b/templates/haskell/core/{{project.name}}.cabal @@ -9,14 +9,12 @@ description: {{project.description}} maintainer: Greg Pfeil author: Greg Pfeil copyright: 2025 Greg Pfeil --- TODO: Remove the redundant `OR AGPL-3.0-only` once --- haskell/hackage-server#1440 is fixed. -license: AGPL-3.0-only WITH Universal-FOSS-exception-1.0 OR AGPL-3.0-only OR LicenseRef-commercial +license: AGPL-3.0-only WITH Universal-FOSS-exception-1.0 OR LicenseRef-proprietary license-files: LICENSE LICENSE.AGPL-3.0-only LICENSE.Universal-FOSS-exception-1.0 - LICENSE.commercial + LICENSE.proprietary category: build-type: Custom extra-doc-files: From a63a0dc5c6fb1e9ce49bd9ded12a2e85e6f209be Mon Sep 17 00:00:00 2001 From: Greg Pfeil Date: Sun, 1 Mar 2026 10:20:10 -0700 Subject: [PATCH 2/4] Support parallel Haskell builds --- templates/haskell/cabal.project | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/templates/haskell/cabal.project b/templates/haskell/cabal.project index 681af77..ee5aa18 100644 --- a/templates/haskell/cabal.project +++ b/templates/haskell/cabal.project @@ -5,6 +5,11 @@ max-backjumps: -1 minimize-conflict-set: true reorder-goals: true +-- Maximize parallelism +jobs: $ncpus +if impl(ghc >= 9.8) + semaphore: True + flags: -- Ensure development of this project always uses @NoRecursion@, even if it -- causes the solver to fail. From 3250ae7c71553336bbb453f6a85b0f2a8753ec1a Mon Sep 17 00:00:00 2001 From: Greg Pfeil Date: Mon, 2 Mar 2026 00:57:59 -0700 Subject: [PATCH 3/4] Set up henforcer --- templates/haskell/.config/project/default.nix | 45 +++++++++++++++++-- templates/haskell/cabal.project | 6 +-- templates/haskell/core/{{project.name}}.cabal | 17 ++++--- 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/templates/haskell/.config/project/default.nix b/templates/haskell/.config/project/default.nix index f2d7f5a..780d483 100644 --- a/templates/haskell/.config/project/default.nix +++ b/templates/haskell/.config/project/default.nix @@ -9,17 +9,56 @@ project = { name = "{{project.name}}"; summary = "{{project.summary}}"; - ## TODO: Move something like this to Flaky. file = let - copyLicenses = dir: { + ## Cabal requires many files to exist at the package level, rather than + ## the repo level. This makes copies of the individual files into the + ## package directory. + ## + ## TODO: Move something like this to Flaky. + perPackageFiles = dir: { "${dir}/LICENSE".source = ../../LICENSE; "${dir}/LICENSE.AGPL-3.0-only".source = ../../LICENSE.AGPL-3.0-only; "${dir}/LICENSE.Universal-FOSS-exception-1.0".source = ../../LICENSE.Universal-FOSS-exception-1.0; "${dir}/LICENSE.proprietary".source = ../../LICENSE.proprietary; + ## We might want to put this somewhere else (like .config/henforcer/), + ## but that isn’t currently an option, because of flipstone/henforcer#7. + "${dir}/henforcer.toml".text = + lib.pm.generators.toTOML {} { + globalSection = {}; + sections = { + forAnyModule = { + ## doesn’t yet support nested attr sets + # allowedAliasUniqueness.allAliasesUniqueExcept = []; + maximumExportsPlusHeaderUndocumented = 0; + maximumExportsWithoutSince = 0; + moduleHeaderCopyrightMustExistNonEmpty = true; + ## We want to require a description, but just a “normal” + ## description, not the header field. + moduleHeaderDescriptionMustExistNonEmpty = false; + moduleHeaderLicenseMustExistNonEmpty = true; + }; + }; + } + ## NB: `toTOML` is really just an INI generator, so it can’t handle a + ## lot of syntax. This tacks some bits onto the end that the INI + ## generator does’t like. + + '' + # Exclude auto-generated `Paths` module + [[forPatternModules]] + pattern = "Paths_*" + [forPatternModules.rulesToIgnore] + all = true + + # Exclude auto-generated `Build_doctests` module + [[forSpecifiedModules]] + module = "Build_doctests" + [forSpecifiedModules.rulesToIgnore] + all = true + ''; }; in - copyLicenses "core"; + perPackageFiles "core"; }; imports = [./hlint.nix]; diff --git a/templates/haskell/cabal.project b/templates/haskell/cabal.project index ee5aa18..2ef86a3 100644 --- a/templates/haskell/cabal.project +++ b/templates/haskell/cabal.project @@ -11,9 +11,9 @@ if impl(ghc >= 9.8) semaphore: True flags: - -- Ensure development of this project always uses @NoRecursion@, even if it - -- causes the solver to fail. - +verify-no-recursion + -- Ensure development of this project always uses linters, even if it causes + -- the solver to fail. + +lint program-options ghc-options: diff --git a/templates/haskell/core/{{project.name}}.cabal b/templates/haskell/core/{{project.name}}.cabal index bba1f65..305d79f 100644 --- a/templates/haskell/core/{{project.name}}.cabal +++ b/templates/haskell/core/{{project.name}}.cabal @@ -83,9 +83,9 @@ flag noisy-deprecations -- Because disabling this flag won’t help the solver. manual: True -flag verify-no-recursion +flag lint description: - Compile with "NoRecursion" enabled. This is intended for developers of this + Build with linting plugins enabled. This is intended for developers of this package. default: False -- Because disabling this flag won’t help the solver. @@ -202,11 +202,16 @@ common defaults if flag(noisy-deprecations) cpp-options: -DSELLOUT_NOISY_DEPRECATIONS - if flag(verify-no-recursion) + if flag(lint) build-depends: no-recursion, ghc-options: -fplugin=NoRecursion + if impl(ghc >= 9.4) + build-depends: + henforcer ^>= {1.0.0}, + ghc-options: + -fplugin Henforcer library import: defaults @@ -224,6 +229,8 @@ test-suite doctests build-depends: doctest, {{project.name}}, + ghc-options: + -fno-warn-missing-import-lists if impl(ghc >= 8.10.1) ghc-options: -- `doctest` requires the package containing the doctests as a dependency @@ -235,11 +242,7 @@ test-suite doctests -- all of its warnings one way or another. if impl(ghc >= 8.0.1) ghc-options: - -Wno-missing-import-lists -Wno-safe - else - ghc-options: - -fno-warn-missing-import-lists if impl(ghc >= 8.4.1) ghc-options: -Wno-missing-export-lists From 66f6cc06e42316e6dceb412acd8b7ef0cca7647d Mon Sep 17 00:00:00 2001 From: Greg Pfeil Date: Mon, 2 Mar 2026 00:58:26 -0700 Subject: [PATCH 4/4] Reformat Cabal package description --- templates/haskell/core/{{project.name}}.cabal | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/haskell/core/{{project.name}}.cabal b/templates/haskell/core/{{project.name}}.cabal index 305d79f..84cf8fc 100644 --- a/templates/haskell/core/{{project.name}}.cabal +++ b/templates/haskell/core/{{project.name}}.cabal @@ -5,7 +5,8 @@ cabal-version: 3.0 name: {{project.name}} version: 0.0.1.0 synopsis: {{project.summary}} -description: {{project.description}} +description: + {{project.description}} maintainer: Greg Pfeil author: Greg Pfeil copyright: 2025 Greg Pfeil