Skip to content

Commit

Permalink
Add compiler constraints
Browse files Browse the repository at this point in the history
So now you can write:

ocaml-version: [ >= "4.00.0" ]

in a package description (a .opam file) and the package will only be considered in the constraint solving if the current compiler version satisfies the constraint.
  • Loading branch information
samoht committed Jul 4, 2012
1 parent 0542833 commit 6ff4f04
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 15 deletions.
32 changes: 24 additions & 8 deletions src/client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,11 @@ let get_archive t nv =
Filename.link src dst;
dst

let current_ocaml_version t =
let alias = File.Config.ocaml_version t.config in
let aliases = File.Aliases.read (Path.G.aliases t.global) in
List.assoc alias aliases

type env = {
add_to_env : (string * string) list;
add_to_path: dirname;
Expand All @@ -704,8 +709,7 @@ let expand_env t env =

(* XXX: We should get the ones defined in the dependents packages as well *)
let get_env t =
let aliases = File.Aliases.read (Path.G.aliases t.global) in
let ocaml_version = List.assoc (File.Config.ocaml_version t.config) aliases in
let ocaml_version = current_ocaml_version t in
let comp_f = Path.G.compiler t.global ocaml_version in
let comp = File.Comp.read comp_f in

Expand Down Expand Up @@ -927,7 +931,22 @@ module Heuristic = struct
)

let resolve action_k t l_request =
let l_pkg = NV.Set.fold (fun nv l -> debpkg_of_nv action_k t nv :: l) t.available [] in
(* Remove the package which does not fullfil the compiler constraints *)
let ocaml_version =
if File.Config.ocaml_version t.config = Alias.of_string Globals.default_compiler_version then
match OCaml_V.current () with
| None -> assert false
| Some v -> v
else
current_ocaml_version t in
let filter nv =
let opam = File.OPAM.read (Path.G.opam t.global nv) in
match File.OPAM.ocaml_version opam with
| None -> true
| Some (r,v) -> OCaml_V.compare ocaml_version r v in
let available = NV.Set.filter filter t.available in

let l_pkg = NV.Set.fold (fun nv l -> debpkg_of_nv action_k t nv :: l) available [] in

match
List.fold_left
Expand Down Expand Up @@ -1153,11 +1172,8 @@ let config request =
Globals.msg "%s\n" (String.concat " " includes)

| Compil c ->
let comp =
let alias = File.Config.ocaml_version t.config in
let aliases = File.Aliases.read (Path.G.aliases t.global) in
let oversion = List.assoc alias aliases in
File.Comp.safe_read (Path.G.compiler t.global oversion) in
let oversion = current_ocaml_version t in
let comp = File.Comp.read (Path.G.compiler t.global oversion) in
let names =
List.filter
(fun n -> NV.Set.exists (fun nv -> NV.name nv = n) t.installed)
Expand Down
16 changes: 14 additions & 2 deletions src/file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ module OPAM = struct
libraries : section list;
syntax : section list;
others : (string * value) list;
ocaml_version: ocaml_constraint option;
}

let empty = {
Expand All @@ -347,6 +348,7 @@ module OPAM = struct
libraries = [];
syntax = [];
others = [];
ocaml_version = None;
}

let create nv =
Expand All @@ -367,6 +369,7 @@ module OPAM = struct
let s_license = "license"
let s_authors = "authors"
let s_homepage = "homepage"
let s_ocaml_version = "ocaml-version"

(* to convert to cudf *)
(* see [Debcudf.add_inst] for more details about the format *)
Expand All @@ -387,6 +390,7 @@ module OPAM = struct
s_conflicts;
s_libraries;
s_syntax;
s_ocaml_version;
]

let valid_fields =
Expand All @@ -407,6 +411,7 @@ module OPAM = struct
let conflicts t = t.conflicts
let libraries t = t.libraries
let syntax t = t.syntax
let ocaml_version t = t.ocaml_version

let with_depends t depends = { t with depends }
let with_build t build = { t with build }
Expand Down Expand Up @@ -455,7 +460,12 @@ module OPAM = struct
Variable (s_conflicts, make_and_formula t.conflicts);
Variable (s_libraries, make_list (Section.to_string |> make_string) t.libraries);
Variable (s_syntax, make_list (Section.to_string |> make_string) t.syntax);
] @ List.map (fun (s, v) -> Variable (s, v)) t.others;
] @ (
match t.ocaml_version with
| None -> []
| Some v -> [ Variable (s_ocaml_version, make_constraint v) ]
) @
List.map (fun (s, v) -> Variable (s, v)) t.others;
}
]
} in
Expand Down Expand Up @@ -492,13 +502,15 @@ module OPAM = struct
let conflicts = assoc_list s s_conflicts parse_and_formula in
let libraries = assoc_list s s_libraries (parse_list (parse_string |> Section.of_string)) in
let syntax = assoc_list s s_syntax (parse_list (parse_string |> Section.of_string)) in
let ocaml_version = assoc_option s s_ocaml_version parse_constraint in
let others =
Utils.filter_map (function
| Variable (x,v) -> if List.mem x useful_fields then None else Some (x,v)
| _ -> None
) s in
{ name; version; maintainer; substs; build; remove;
depends; depopts; conflicts; libraries; syntax; others }
depends; depopts; conflicts; libraries; syntax; others;
ocaml_version; }
end

module Dot_install_raw = struct
Expand Down
3 changes: 3 additions & 0 deletions src/file.mli
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ module OPAM: sig
(** Package version *)
val version: t -> version

(** Compiler constraint *)
val ocaml_version: t -> ocaml_constraint option

(** Package maintainer *)
val maintainer: t -> string

Expand Down
28 changes: 28 additions & 0 deletions src/file_format.ml
Original file line number Diff line number Diff line change
Expand Up @@ -323,3 +323,31 @@ let make_cnf_formula l =
| _ -> (Group orl) :: cnf
) [] l in
List cnf

let parse_relop = function
| "=" -> `Eq
| ">=" -> `Geq
| ">" -> `Gt
| "<=" -> `Leq
| "<" -> `Lt
| _ -> invalid_arg "parse_relop"

let parse_constraint = function
| List [ Symbol r; String v ] ->
(try (parse_relop r, Types.OCaml_V.of_string v)
with _ -> bad_format "Expecting a relop, got %s" r)
| x -> bad_format "Expecting a constraint, got %s" (kind x)

let string_of_relop = function
| `Eq -> "="
| `Geq -> ">="
| `Gt -> ">"
| `Leq -> "<="
| `Lt -> "<"
| _ -> invalid_arg "parse_relop"

let make_constraint (r, v) =
List [
Symbol (string_of_relop r);
String (Types.OCaml_V.to_string v);
]
6 changes: 6 additions & 0 deletions src/file_format.mli
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,9 @@ val make_and_formula : and_formula -> value

(** Build a CNF formula *)
val make_cnf_formula : cnf_formula -> value

(** Parse a simple constraint *)
val parse_constraint: value -> ocaml_constraint

(** Build a simple constraint *)
val make_constraint: ocaml_constraint -> value
16 changes: 16 additions & 0 deletions src/types.ml
Original file line number Diff line number Diff line change
Expand Up @@ -414,16 +414,31 @@ end

type nv = NV.t

type relop = [`Eq|`Geq|`Gt|`Leq|`Lt]

(* OCaml version *)
module OCaml_V: sig
include Abstract
val current: unit -> t option
val compare: t -> relop -> t -> bool
end = struct
include Base

let current () =
match Run.ocaml_version () with
| None -> None
| Some o -> Some (of_string o)

let compare v1 r v2 =
let v1 = to_string v1 in
let v2 = to_string v2 in
match r with
| `Eq -> Debian.Version.equal v1 v2
| `Geq -> Debian.Version.compare v1 v2 >= 0
| `Gt -> Debian.Version.compare v1 v2 > 0
| `Leq -> Debian.Version.compare v1 v2 <= 0
| `Lt -> Debian.Version.compare v1 v2 < 0

end

module Alias: Abstract = Base
Expand Down Expand Up @@ -714,3 +729,4 @@ let string_of_config = function

type and_formula = Debian.Format822.vpkglist
type cnf_formula = Debian.Format822.vpkgformula
type ocaml_constraint = relop * OCaml_V.t
7 changes: 7 additions & 0 deletions src/types.mli
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,18 @@ end
(** Shortcut to NV.t *)
type nv = NV.t


type relop = [`Eq|`Geq|`Gt|`Leq|`Lt]

(** OCaml version *)
module OCaml_V: sig
include Abstract

(** Return the version of the compiler currently installed *)
val current: unit -> t option

(** Compare OCaml versions *)
val compare: t -> relop -> t -> bool
end

(** OPAM version *)
Expand Down Expand Up @@ -426,3 +432,4 @@ module Alias: Abstract

type and_formula = Debian.Format822.vpkglist
type cnf_formula = Debian.Format822.vpkgformula
type ocaml_constraint = relop * OCaml_V.t
10 changes: 6 additions & 4 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -211,17 +211,19 @@ switch-alias:
$(OPAM) remove P3.1~weird-version.test P4.2
$(CHECK) -l switch-alias P1.1 P2.1
$(OPAM) switch -alias test $(OCAMLVERSION) -clone
$(CHECK) -l switch-alias P1.1 P2.1
$(OPAM) switch -list
$(CHECK) -l switch-alias-test P1.1 P2.1
$(OPAM) switch 4.00.0
$(OPAM) install P1
$(CHECK) -l switch-alias-4.00 P1.1

switch-env-packages:
$(OPAM) switch dummy
$(OPAM) switch 3.12.1
ifeq ($(REPOKIND), git)
$(CHECK) -l switch-env-packages P1.1 P2.1 P3.1~weird-version.test P4.3
else
$(CHECK) -l switch-env-packages P1.2 P2.1 P3.1~weird-version.test P4.3
endif
./test-TEST.sh $(OPAM_ROOT)/dummy/build/P4.3/P4.env "1"
./test-TEST.sh $(OPAM_ROOT)/3.12.1/build/P4.3/P4.env "1"

switch:
$(MAKE) fresh
Expand Down
2 changes: 1 addition & 1 deletion tests/compilers/dummy.comp → tests/compilers/3.12.1.comp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
opam-version: "1"
name: "test"
name: "3.12.1"
preinstalled: true
env: [
[ TEST="1" ]
Expand Down
6 changes: 6 additions & 0 deletions tests/compilers/4.00.0.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
opam-version: "1"
name: "4.00.0"
preinstalled: true
env: [
[ TEST="1" ]
]
1 change: 1 addition & 0 deletions tests/packages/P1-2.opam
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ opam-version: "1"

package "P1" {
version: "2"
ocaml-version: [ < "4.00.0" ]
maintainer: "contact@ocamlpro.com"
substs: [ "P1.config" ]
libraries: [ "p1" ]
Expand Down

0 comments on commit 6ff4f04

Please sign in to comment.