Skip to content

Commit

Permalink
Add distro.ml in obuilder-spec-opam package
Browse files Browse the repository at this point in the history
  • Loading branch information
benmandrew committed Apr 11, 2023
1 parent 59c4b29 commit b0a119d
Show file tree
Hide file tree
Showing 6 changed files with 369 additions and 0 deletions.
19 changes: 19 additions & 0 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,22 @@
ppx_deriving
ppx_sexp_conv
(ocaml (>= 4.10.2))))

(package
(name obuilder-spec-opam)
(synopsis "Build specification format -- opam support")
(description
"A library for constructing, reading and writing OBuilder build specification files.")
(depends
(fmt (>= 0.8.9))
sexplib
astring
dockerfile-opam
ppx_deriving
ppx_deriving_yojson
ppx_sexp_conv
(ocaml (>= 4.10.0))
(ocaml-version (>= 3.6.0))
(opam-format (>= 2.1.0))
(obuilder-spec (= :version))
(alcotest-lwt :with-test)))
154 changes: 154 additions & 0 deletions lib_spec_opam/distro.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
module OV = Ocaml_version
module D = Dockerfile_opam.Distro

type distro = [ D.distro | `Macos of [ `V12 | `V13 ] ] [@@deriving sexp]
type t = [ D.t | `Macos of [ `Latest | `V12 | `V13 ] ] [@@deriving sexp]
type os_family = [ D.os_family | `Macos ] [@@deriving sexp]

let os_family_of_distro (t : t) : os_family =
match t with
| #D.t as f -> (D.os_family_of_distro f :> os_family)
| `Macos _ -> `Macos

let os_family_to_string (os : os_family) =
match os with
| #D.os_family as os -> D.os_family_to_string os
| `Macos -> "macos"

let opam_repository (os : os_family) =
match os with
| #D.os_family as os -> D.opam_repository os
| `Macos -> "https://github.com/ocaml/opam-repository.git"

type status =
[ `Deprecated
| `Active of [ `Tier1 | `Tier2 | `Tier3 ]
| `Alias
| `Not_available ]
[@@deriving sexp]

let macos_distros = [ `Macos `V12; `Macos `V13 ]
let distros = (D.distros :> t list) @ macos_distros

let resolve_alias (d : t) : distro =
match d with
| #D.t as d -> (D.resolve_alias d :> distro)
| `Macos (`Latest | `V13) -> `Macos `V13
| `Macos `V12 -> `Macos `V12

let distro_status (d : t) : status =
match d with
| #D.t -> failwith "Using extended [distro_status] with non-MacOS distro. Use [D.distro_status] instead."
| `Macos _ ->
let resolved = resolve_alias d in
if (resolved : distro :> t) <> d then `Alias else `Active `Tier2

let latest_distros = (D.latest_distros :> t list) @ [ `Macos `Latest ]
let master_distro = (D.master_distro :> t)

let distro_arches ov (d : t) =
match d with
| #D.t as d -> D.distro_arches ov d
| `Macos _ when OV.(compare Releases.v4_02_0 ov) = -1 ->
[ `X86_64; `Aarch64 ]
| _ -> [ `X86_64 ]

let distro_supported_on a ov (d : t) = List.mem a (distro_arches ov d)

let distro_active_for arch (d : t) =
match (arch, d) with
| `X86_64, `Windows _ -> true
| _ -> distro_supported_on arch OV.Releases.latest d

let active_distros arch =
List.filter
(fun d -> match distro_status d with `Active _ -> true | _ -> false)
distros
|> List.filter (distro_active_for arch)

let active_tier1_distros arch =
List.filter
(fun d ->
match distro_status d with `Active `Tier1 -> true | _ -> false)
distros
|> List.filter (distro_active_for arch)

let active_tier2_distros arch =
List.filter
(fun d ->
match distro_status d with `Active `Tier2 -> true | _ -> false)
distros
|> List.filter (distro_active_for arch)

let active_tier3_distros arch =
List.filter
(fun d ->
match distro_status d with `Active `Tier3 -> true | _ -> false)
distros
|> List.filter (distro_active_for arch)

let builtin_ocaml_of_distro (d : t) =
match d with #D.t as d -> D.builtin_ocaml_of_distro d | `Macos _ -> None

let tag_of_distro (d : t) =
match d with
| #D.t as d -> D.tag_of_distro d
| `Macos (`Latest | `V13) -> "macos-homebrew-13"
| `Macos `V12 -> "macos-homebrew-12"

let distro_of_tag x =
match D.distro_of_tag x with
| None -> (
match x with
| "macos-homebrew-12" -> Some (`Macos `V12)
| "macos-homebrew-13" -> Some (`Macos `V13)
| "macos-homebrew" -> Some (`Macos `Latest)
| _ -> None)
| Some _ as x -> (x :> t option)

let human_readable_string_of_distro (d : t) =
match d with
| #D.t as d -> D.human_readable_string_of_distro d
| `Macos _ as d -> (
match resolve_alias d with
| `Macos `V12 -> "MacOS 12 (Monterey)"
| `Macos `V13 -> "MacOS 13 (Ventura)"
| _ -> failwith "Resolved to non-MacOS distro, bug in [resolve_alias]?")

let human_readable_short_string_of_distro (d : t) =
match d with
| #D.t as d -> D.human_readable_short_string_of_distro d
| `Macos _ -> "MacOS"

let is_same_distro (d1 : t) (d2 : t) =
match (d1, d2) with
| (#D.t as d1), (#D.t as d2) -> D.is_same_distro d1 d2
| `Macos _, `Macos _ -> true
| _ -> false

let latest_tag_of_distro (t : t) =
let latest = List.find (is_same_distro t) latest_distros in
tag_of_distro latest

type package_manager = [ D.package_manager | `Homebrew ] [@@deriving sexp]

let package_manager (d : t) : package_manager =
match d with #D.t as d -> (D.package_manager d :> package_manager) | `Macos _ -> `Homebrew

let bubblewrap_version (d : t) =
match d with #D.t as d -> D.bubblewrap_version d | `Macos _ -> None

let base_distro_tag ?win10_revision ?(arch = `X86_64) (d : t) =
match d with
| #D.t as d -> D.base_distro_tag ?win10_revision ~arch d
| `Macos _ as d -> (
(* TODO There is no docker image for these yet! *)
match resolve_alias d with
| `Macos `V12 -> ("macos/monterey", "12")
| `Macos `V13 -> ("macos/ventura", "13")
| _ -> failwith "Resolved to non-MacOS distro, bug in [resolve_alias]?")

let compare a b =
String.compare
(human_readable_string_of_distro a)
(human_readable_string_of_distro b)
132 changes: 132 additions & 0 deletions lib_spec_opam/distro.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
(* Distribution selections for various OPAM combinations, for Linux, Windows, and MacOS distributions *)

open Dockerfile_opam

type distro = [ Distro.distro | `Macos of [ `V12 | `V13 ] ] [@@deriving sexp]
(** Supported Docker container distributions without aliases. *)

type t = [ Distro.t | `Macos of [ `Latest | `V12 | `V13 ] ] [@@deriving sexp]
(** Supported Docker container distributions with aliases. *)

type os_family = [ Distro.os_family | `Macos ] [@@deriving sexp]
(** The operating system family a distro belongs to. *)

val os_family_of_distro : t -> os_family
(** [os_family_of_distro t] returns the OS family of the distro. *)

val os_family_to_string : os_family -> string
(** [os_family_to_string os] returns a string representing the OS
family. *)

val opam_repository : os_family -> string
(** [opam_repository os_family] returns the git URL to the default
Opam repository. *)

val is_same_distro : t -> t -> bool
(** [is_same_distro d1 d2] returns whether [d1] is the same distro as
[d2], regardless of their respective versions. *)

val compare : t -> t -> int
(** [compare a b] is a lexical comparison function for {!t}. *)

val resolve_alias : t -> distro
(** [resolve_alias t] will resolve [t] into a concrete version. This removes
versions such as [Latest]. *)

val distros : t list
(** Enumeration of the supported Docker container distributions. *)

val latest_distros : t list
(** Enumeration of the latest stable (ideally LTS) supported distributions. *)

val master_distro : t
(** The distribution that is the top-level alias for the [latest] tag
in the [ocaml/opam2] Docker Hub build. *)

val builtin_ocaml_of_distro : t -> string option
(** [builtin_ocaml_of_distro t] will return the OCaml version
supplied with the distribution packaging, and [None] if there
is no supported version. *)

val human_readable_string_of_distro : t -> string
(** [human_readable_string_of_distro t] returns a human readable
version of the distribution tag, including version information. *)

val human_readable_short_string_of_distro : t -> string
(** [human_readable_short_string_of_distro t] returns a human readable
short version of the distribution tag, excluding version information. *)

type package_manager =
[ Distro.package_manager | `Homebrew (** MacOS homebrew *) ]
[@@deriving sexp]
(** The package manager used by a distro. *)

val package_manager : t -> package_manager
(** [package_manager t] returns the type of package manager used
by that distribution. Many derived distributions (such as OracleLinux)
share the same package manager from a base distribution (such as CentOS). *)

val bubblewrap_version : t -> (int * int * int) option
(** [bubblewrap_version t] returns the version of bubblewrap available on that
distribution. *)

val tag_of_distro : t -> string
(** [tag_of_distro t] convert a distribution [t] to a Docker Hub tag. *)

val distro_of_tag : string -> t option
(** [distro_of_tag s] parses [s] into a {!t} distribution, and
[None] otherwise. *)

val latest_tag_of_distro : t -> string
(** [latest_tag_of_distro distro] will generate a Docker Hub
tag that is a convenient short form for the latest stable
release of a particular distribution. This tag will be
regularly rewritten to point to any new releases of the
distribution. *)

val base_distro_tag :
?win10_revision:Distro.win10_lcu ->
?arch:Ocaml_version.arch ->
t ->
string * string
(** [base_distro_tag ?arch t] will return a tuple of a Docker Hub
user/repository and tag for which the base image of a distribution
can be found (e.g. [opensuse/leap],[15.0] which maps to [opensuse/leap:15.0]
on the Docker Hub). This base image is in turn can be used to generate opam
and other OCaml tool Dockerfiles. [arch] defaults to [x86_64] and can vary
the base user/repository since some architecture are built elsewhere. *)

val distro_arches : Ocaml_version.t -> t -> Ocaml_version.arch list
(** [distro_arches ov t] returns the list of architectures that
distribution [t] is supported on for OCaml compiler version [ov] *)

val distro_supported_on : Ocaml_version.arch -> Ocaml_version.t -> t -> bool
(** [distro_supported_on arch ov distro] returns [true] if the
combination of CPU [arch], compiler version [ov] is available
on the distribution [distro]. *)

val active_distros : Ocaml_version.arch -> t list
(** [active_distros arch] returns the list of currently supported
distributions in the opam build infrastructure. Distributions
that are end-of-life upstream will rotate out of this list
regularly. *)

val active_tier1_distros : Ocaml_version.arch -> t list
(** Tier 1 distributions are those supported for the full matrix
of compiler versions in the opam build infrastructure.
The {{:https://github.com/ocurrent/docker-base-images}Docker base images}
will compile a base image for every OCaml version, so this
list should be added to sparingly. *)

val active_tier2_distros : Ocaml_version.arch -> t list
(** Tier 2 distributions are those supported for a limited set
of compiler versions in the opam build infrastructure. The
distros in this list are also tested for packages in the
opam repository. *)

val active_tier3_distros : Ocaml_version.arch -> t list
(** Tier 3 distributions are those supported for a limited set
of compiler versions in the opam build infrastructure. While
these distros will have base images compiled for them, they
are not widely tested. Distros maybe here as they are on the
way to being deprecated, or new and still experimental. *)
10 changes: 10 additions & 0 deletions lib_spec_opam/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(library
(name obuilder_spec_opam)
(public_name obuilder-spec-opam)
(preprocess (pps ppx_deriving.std ppx_deriving_yojson ppx_sexp_conv))
(libraries
dockerfile-opam
ocaml-version
obuilder-spec
sexplib
ppx_deriving_yojson.runtime))
1 change: 1 addition & 0 deletions lib_spec_opam/obuilder_spec_opam.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module Distro = Distro
53 changes: 53 additions & 0 deletions obuilder-spec-opam.opam
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "Build specification format -- opam support"
description:
"A library for constructing, reading and writing OBuilder build specification files."
maintainer: ["[email protected]"]
authors: [
"Antonin Décimo <[email protected]>"
"Arthur Wendling <[email protected]>"
"David Allsopp <[email protected]>"
"Kate <[email protected]>"
"Lucas Pluvinage <[email protected]>"
"Mark Elvers <[email protected]>"
"Patrick Ferris <[email protected]>"
"Thomas Gazagnaire <[email protected]>"
"Thomas Leonard <[email protected]>"
"Tim McGilchrist <[email protected]>"
]
license: "Apache-2.0"
homepage: "https://github.com/ocurrent/obuilder"
doc: "https://ocurrent.github.io/obuilder/"
bug-reports: "https://github.com/ocurrent/obuilder/issues"
depends: [
"dune" {>= "3.7"}
"fmt" {>= "0.8.9"}
"sexplib"
"astring"
"dockerfile-opam"
"ppx_deriving"
"ppx_deriving_yojson"
"ppx_sexp_conv"
"ocaml" {>= "4.10.0"}
"ocaml-version" {>= "3.6.0"}
"opam-format" {>= "2.1.0"}
"obuilder-spec" {= version}
"alcotest-lwt" {with-test}
"odoc" {with-doc}
]
build: [
["dune" "subst"] {dev}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
dev-repo: "git+https://github.com/ocurrent/obuilder.git"

0 comments on commit b0a119d

Please sign in to comment.