Permalink
Browse files

Towards the complete support of "opam switch".

Future works :
- preprocessing options remain to be pass to the compiler
- when installing a package, the $PATH must be modified in order to use the chosen compiler
  • Loading branch information...
1 parent 4458cfa commit 7892d49aa5e53707517cbfa1393642ef3e39e7a5 @tuong tuong committed May 21, 2012
Showing with 232 additions and 24 deletions.
  1. +35 −23 src/client.ml
  2. +93 −0 src/file.ml
  3. +19 −0 src/file.mli
  4. +8 −0 src/path.ml
  5. +15 −0 src/path.mli
  6. +14 −0 src/repositories.ml
  7. +30 −0 src/repositories.mli
  8. +4 −0 src/types.ml
  9. +4 −0 src/types.mli
  10. +7 −1 tests/Makefile
  11. +3 −0 tests/packages/3.11.2.comp
View
@@ -785,26 +785,38 @@ let remote action =
Globals.error_and_exit "%s is not a remote index" n in
update_config (List.filter ((!=) repo) repos)
-let switch name =
- log "switch %s" (OCaml_V.to_string name);
- (* let t = load_state () in *)
- failwith "TODO"
-
-(*
- let compile compil =
- failwith "TODO" in
- if Filename.check_suffix name ".compil" then begin
- (* we switch to a fresh OCaml install *)
- let compil = File.Compil.parse (Run.U.read name) in
- let name = File.Compil.name compil in
- let compil_f = Path.compil t.home name in
- if Path.file_exists compil_f then
- Globals.error_and_exit "Compiler spec %s already exists" name;
- File.Compil.add compil_f compil;
- compile compil
- end else begin
- let compil_f = Path.compil t.home name in
- let compil = File.Compil.find compil_f in
- compile compil
- end
-*)
+let switch oversion =
+ log "switch %s" (OCaml_V.to_string oversion);
+ let t = load_state () in
+
+ let () =
+ if Dirname.exists (Path.C.root (Path.C.create t.global oversion)) then
+ ()
+ else
+ (* The chosen version does not exist. We build it. *)
+ let comp = File.Comp.read (Path.G.compilers t.global oversion) in
+ let comp_src = File.Comp.src comp in
+ let ocaml_tgz =
+ Path.G.compilers_dir t.global // Printf.sprintf "%s%s"
+ (OCaml_V.to_string oversion)
+ (let suff = ".tar.gz" in
+ if Stdlib_filename.check_suffix comp_src suff then
+ suff
+ else
+ Globals.error_and_exit "Unknown file format (%s)" comp_src) in
+ let () = Repositories.Raw.rsync [`A ; `R] comp_src ocaml_tgz in
+ let build_dir = Path.C.build_ocaml t.compiler in
+ let () = Filename.extract ocaml_tgz build_dir in
+
+ match
+ Dirname.exec build_dir
+ [ Printf.sprintf "./configure %s -prefix %s" (*-bindir %s/bin -libdir %s/lib -mandir %s/man*)
+ (String.concat " " (File.Comp.configure comp))
+ (Dirname.to_string (Path.C.ocaml t.compiler))
+ (* NOTE In case it exists 2 '-prefix', in general the script ./configure will only consider the last one, others will be discarded. *)
+ ; Printf.sprintf "make %s" (String.concat " " (File.Comp.make comp))
+ ; Printf.sprintf "make install" ]
+ with
+ | 0 -> ()
+ | error -> Globals.error_and_exit "compilation of OCaml failed (%d)" error in
+ File.Config.write (Path.G.config t.global) (File.Config.with_ocaml_version t.config oversion)
View
@@ -223,6 +223,7 @@ module Config = struct
}
let with_repositories t repositories = { t with repositories }
+ let with_ocaml_version t ocaml_version = { t with ocaml_version }
let opam_version t = t.opam_version
let repositories t = t.repositories
@@ -601,6 +602,93 @@ module Dot_config = struct
module Sections = MK (struct let get t = t.sections end)
end
+module Comp = struct
+
+ let internal = "comp"
+
+ type t = {
+ opam_version : OPAM_V.t ;
+ src : string ;
+
+ patches : string list ;
+ configure : string list ;
+ make : string list ;
+ bytecomp : string list ;
+ asmcomp : string list ;
+ bytelink : string list ;
+ asmlink : string list ;
+ packages : string list ;
+
+ (*requires :*)
+ (*pp : *)
+ }
+
+ let empty = {
+ opam_version = OPAM_V.of_string Globals.opam_version;
+ src = "";
+
+ patches = [];
+ configure = [];
+ make = [];
+ bytecomp = [];
+ asmcomp = [];
+ bytelink = [];
+ asmlink = [];
+ packages = [];
+ }
+
+ let s_src = "src"
+ let s_patches = "patches"
+ let s_configure = "configure"
+ let s_make = "make"
+ let s_bytecomp = "bytecomp"
+ let s_asmcomp = "asmcomp"
+ let s_bytelink = "bytelink"
+ let s_asmlink = "asmlink"
+ let s_packages = "packages"
+
+ let configure t = t.configure
+ let make t = t.make
+ let src t = t.src
+
+ let of_string filename str =
+ let file = Syntax.of_string filename str in
+ let s = file.contents in
+
+ let opam_version =
+ assoc s s_opam_version (parse_string |> OPAM_V.of_string) in
+ let src = assoc s s_src parse_string in
+
+ let patches = assoc_string_list s s_patches in
+ let configure = assoc_string_list s s_configure in
+ let make = assoc_string_list s s_make in
+ let bytecomp = assoc_string_list s s_bytecomp in
+ let asmcomp = assoc_string_list s s_asmcomp in
+ let bytelink = assoc_string_list s s_bytecomp in
+ let asmlink = assoc_string_list s s_asmlink in
+ let packages = assoc_string_list s s_packages in
+
+ { opam_version; src;
+ patches; configure; make; bytecomp; asmcomp; bytelink; asmlink; packages;
+ }
+
+ let to_string filename s =
+ Syntax.to_string filename {
+ filename = Filename.to_string filename;
+ contents = [
+ Variable (s_patches , make_list make_string s.patches);
+ Variable (s_configure, make_list make_string s.configure);
+ Variable (s_make , make_list make_string s.make);
+ Variable (s_bytecomp , make_list make_string s.bytecomp);
+ Variable (s_asmcomp , make_list make_string s.asmcomp);
+ Variable (s_bytelink , make_list make_string s.bytelink);
+ Variable (s_asmlink , make_list make_string s.asmlink);
+ Variable (s_packages , make_list make_string s.packages);
+ ]
+ }
+
+end
+
module Subst = struct
let internal = "subst"
@@ -725,3 +813,8 @@ module Subst = struct
include Subst
include Make (Subst)
end
+
+module Comp = struct
+ include Comp
+ include Make (Comp)
+end
View
@@ -45,9 +45,13 @@ module Config: sig
(** Creation *)
val create: OPAM_V.t -> repository list -> OCaml_V.t -> t
+ (** OCaml version updates *)
+ val with_ocaml_version : t -> OCaml_V.t -> t
+
(** Repository updates *)
val with_repositories: t -> repository list -> t
+
(** Return the OPAM version *)
val opam_version: t -> OPAM_V.t
@@ -123,6 +127,21 @@ module Reinstall: IO_FILE with type t = NV.Set.t
(** List of updated packages: [$opam/$repo/$repo/updated] *)
module Updated: IO_FILE with type t = NV.Set.t
+(** Compiler version [$opam/compilers/] *)
+module Comp : sig
+
+ include IO_FILE
+
+ (** Return the url of the compiler *)
+ val src : t -> string
+
+ (** Options to give to the "./configure" command *)
+ val configure : t -> string list
+
+ (** Options to give to the "make" command *)
+ val make : t -> string list
+end
+
(** {2 Configuration files} *)
(** .install files *)
View
@@ -45,6 +45,10 @@ module G = struct
let opam t nv = opam_dir t // (NV.to_string nv ^ ".opam")
+ let compilers_dir t = t / "compilers"
+
+ let compilers t ov = compilers_dir t // (OCaml_V.to_string ov ^ ".comp")
+
let available t = available (opam_dir t)
let available_versions t n =
@@ -78,12 +82,16 @@ module C = struct
let bin t = t / "bin"
+ let ocaml t = t / "ocaml"
+
let installed t = t // "installed"
let build_dir t = t / "build"
let build t nv = build_dir t / NV.to_string nv
+ let build_ocaml t = build_dir t / "_"
+
let build_install t nv = build t nv // (N.to_string (NV.name nv) ^ ".install")
let build_config t nv = build t nv // (N.to_string (NV.name nv) ^ ".config")
View
@@ -34,6 +34,12 @@ module G : sig
(** OPAM files: {i $opam/opam/$NAME.$VERSION.opam} *)
val opam: t -> NV.t -> filename
+ (** Compiler files : {i $opam/compilers/$OVERSION.comp} *)
+ val compilers: t -> OCaml_V.t -> filename
+
+ (** Compiler files : {i $opam/compilers/} *)
+ val compilers_dir: t -> dirname
+
(** List all the available packages:
{i $opam/opam/$NAME.$VERSION.opam} *)
val available: t -> NV.Set.t
@@ -84,6 +90,10 @@ module C : sig
(** Installed binaries: {i $opam/$OVERSION/bin} *)
val bin: t -> dirname
+ (** Directory containing "bin" and "lib"
+ {i $opam/$OVERSION/ocaml} *)
+ val ocaml : t -> dirname
+
(** List of installed packages with their version:
{i $opam/$OVERSION/installed} *)
val installed: t -> filename
@@ -93,6 +103,11 @@ module C : sig
{i $opam/$OVERSION/build/$NAME-$VERSION} *)
val build: t -> NV.t -> dirname
+ (** Tempory folders used to decompress and compile
+ the OCaml compiler:
+ {i $opam/$OVERSION/build/_} *)
+ val build_ocaml: t -> dirname
+
(** Tempory folder: {i $opam/$OVERSION/build} *)
val build_dir: t -> dirname
View
@@ -51,3 +51,17 @@ let upload root r =
run "upload" root r [];
(* XXX *)
()
+
+module Raw = struct
+
+ let rsync l src dst =
+ match l with
+ | [`A ; `R] | [`R ; `A] ->
+ let dst = Filename.to_string dst in
+ let err =
+ Run.command "rsync -ar %s %s" src dst in
+ if err <> 0 then
+ Globals.error_and_exit "rsync (%S, %S) command failed (%d)" src dst err
+ | _ -> failwith "TODO"
+
+end
View
@@ -0,0 +1,30 @@
+(***********************************************************************)
+(* *)
+(* Copyright 2012 OCamlPro *)
+(* Copyright 2012 INRIA *)
+(* *)
+(* All rights reserved. This file is distributed under the terms of *)
+(* the GNU Public License version 3.0. *)
+(* *)
+(* TypeRex is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(***********************************************************************)
+
+open Types
+open Path
+open File
+
+val init : R.t -> Repo_config.t -> unit
+val update : R.t -> Repo_config.t -> unit
+val upload : R.t -> Repo_config.t -> unit
+val download : R.t -> Repo_config.t -> NV.t -> unit
+
+module Raw : sig (* MOVE each value in a [repo/$REPO/raw.ml] file ? *)
+
+ val rsync : [ `A | `R ] list -> string -> filename -> unit
+(* val svn : *)
+(* val git : *)
+end
View
@@ -46,6 +46,7 @@ module Dirname: sig
val mkdir: t -> unit
val exec: t -> string list -> int
val chdir: t -> unit
+ val exists: t -> bool
end = struct
include Base
@@ -65,6 +66,9 @@ end = struct
let chdir dirname =
Unix.chdir (to_string dirname)
+ let exists dirname =
+ Sys.file_exists (to_string dirname)
+
end
type dirname = Dirname.t
View
@@ -54,6 +54,9 @@ module Dirname: sig
(** Change the current directory *)
val chdir: t -> unit
+
+ (** see [Sys.file_exists] *)
+ val exists: t -> bool
end
(** Shortcut to directory type *)
@@ -76,6 +79,7 @@ type raw = Raw.t
(** Stdlib [Filename] module *)
module Stdlib_filename: sig
+ val check_suffix: string -> string -> bool
val concat: string -> string -> string
end
View
@@ -19,7 +19,7 @@ ARCHIVES = $(PACKAGES:%=packages/%.tar.gz)
.PHONY: all upload
-all: fresh init upload list install upload-new upgrade downgrade remove
+all: fresh init upload list install upload-new upgrade downgrade remove switch
@
$(BINARIES_): $(BUILDS)
@@ -77,6 +77,12 @@ downgrade: upgrade
$(OPAM) install P4.2
$(OPAM) list
+switch: downgrade
+ mkdir -p /tmp/opam-archives && wget -P /tmp/opam-archives -qN http://caml.inria.fr/pub/distrib/ocaml-3.11/ocaml-3.11.2.tar.gz
+ mkdir -p $(OPAM_ROOT)/compilers
+ cp packages/3.11.2.comp $(OPAM_ROOT)/compilers
+ $(OPAM) switch 3.11.2
+
packages/%.tar.gz: packages/% packages/%/*
cd packages && tar cz $* > $*.tar.gz
@@ -0,0 +1,3 @@
+opam-version: "1"
+src: "/tmp/opam-archives/ocaml-3.11.2.tar.gz"
+make: ["world.opt"]

0 comments on commit 7892d49

Please sign in to comment.