diff --git a/doc/project-layout-specification.rst b/doc/project-layout-specification.rst index 20b71efb..d541fb71 100644 --- a/doc/project-layout-specification.rst +++ b/doc/project-layout-specification.rst @@ -131,6 +131,15 @@ Sets the name of the project: (name ) +version +------- + +Sets the version of the project: + +.. code:: scheme + + (version ) + .opam files ==================== @@ -185,25 +194,21 @@ defined in the workspace. While Jbuilder itself makes no use of version numbers, it can be use by external tools such as `ocamlfind `__. -Jbuilder determines the version of a package by first looking in the -``.opam`` for a ``version`` variable. If not found, it will try -to read the first line of a version file in the same directory as the -``.opam`` file. The version file is any file whose name is, in -order in which they are looked for: +Jbuilder determines the version of a package by trying the following +methods in order: -- ``.version`` -- ``version`` -- ``VERSION`` +- it looks in the ``.opam`` file for a ``version`` variable +- it looks for a ``.version`` file in the same directory and + reads the first line +- it looks for the version specified in the ``dune-project`` if present +- it looks for a ``version`` file and reads the first line +- it looks for a ``VERSION`` file and reads the first line -The version file can be generated by a user rule. +``.version``, ``version`` and ``VERSION`` files may be +generated. If the version can't be determined, Jbuilder just won't assign one. -Note that if you are using `Topkg `__ -as well in your project, you shouldn't manually set a version in your -``.opam`` file or write/generate on of the file listed above. -See the section about :ref:`using-topkg` for more details. - Odig conventions ---------------- diff --git a/src/dune_project.ml b/src/dune_project.ml index 30cc2579..2fc34596 100644 --- a/src/dune_project.ml +++ b/src/dune_project.ml @@ -2,7 +2,8 @@ open Import open Sexp.Of_sexp type t = - { name : string + { name : string + ; version : string option } let filename = "dune-project" @@ -32,7 +33,8 @@ let parse ~dir = record (lang >>= fun Dune_0_1 -> name ~dir >>= fun name -> - return { name }) + field_o "version" string >>= fun version -> + return { name; version }) let load ~dir = let fname = Path.relative dir filename in diff --git a/src/dune_project.mli b/src/dune_project.mli index 07dbf30a..e7e6e853 100644 --- a/src/dune_project.mli +++ b/src/dune_project.mli @@ -3,7 +3,8 @@ open Import type t = - { name : string + { name : string + ; version : string option } val load : dir:Path.t -> t diff --git a/src/install_rules.ml b/src/install_rules.ml index c96a18c3..d03e4f26 100644 --- a/src/install_rules.ml +++ b/src/install_rules.ml @@ -44,6 +44,15 @@ module Gen(P : Install_params) = struct >>> Build.write_file_dyn (lib_dune_file ~dir:(Lib.src_dir lib) ~name:(Lib.name lib))) + let version_from_dune_project (pkg : Package.t) = + let dir = Path.append (SC.build_dir sctx) pkg.path in + let scope = Scope.info (SC.find_scope_by_dir sctx dir) in + scope.version + + type version_method = + | File of string + | From_dune_project + let init_meta () = SC.libs_by_package sctx |> Package.Name.Map.iter ~f:(fun ((pkg : Package.t), libs) -> @@ -63,18 +72,25 @@ module Gen(P : Install_params) = struct let rec loop = function | [] -> Build.return None | candidate :: rest -> - let p = Path.relative path candidate in - Build.if_file_exists p - ~then_:(Build.lines_of p - >>^ function - | ver :: _ -> Some ver - | _ -> Some "") - ~else_:(loop rest) + match candidate with + | File fn -> + let p = Path.relative path fn in + Build.if_file_exists p + ~then_:(Build.lines_of p + >>^ function + | ver :: _ -> Some ver + | _ -> Some "") + ~else_:(loop rest) + | From_dune_project -> + match version_from_dune_project pkg with + | None -> loop rest + | Some _ as x -> Build.return x in loop - [ (Package.Name.to_string pkg.name) ^ ".version" - ; "version" - ; "VERSION" + [ File ((Package.Name.to_string pkg.name) ^ ".version") + ; From_dune_project + ; File "version" + ; File "VERSION" ] in Super_context.Pkg_version.set sctx pkg get diff --git a/src/jbuild.ml b/src/jbuild.ml index e599b34e..98266c6a 100644 --- a/src/jbuild.ml +++ b/src/jbuild.ml @@ -92,15 +92,17 @@ module Scope_info = struct { name : Name.t ; packages : Package.t Package.Name.Map.t ; root : Path.t + ; version : string option } let anonymous = { name = None ; packages = Package.Name.Map.empty ; root = Path.root + ; version = None } - let make = function + let make ?version = function | [] -> anonymous | pkg :: rest as pkgs -> let name = @@ -114,6 +116,7 @@ module Scope_info = struct Package.Name.Map.of_list_exn (List.map pkgs ~f:(fun pkg -> pkg.Package.name, pkg)) ; root + ; version } let package_listing packages = diff --git a/src/jbuild.mli b/src/jbuild.mli index 36a1cbea..c1f8ec53 100644 --- a/src/jbuild.mli +++ b/src/jbuild.mli @@ -28,9 +28,10 @@ module Scope_info : sig scope. *) ; packages : Package.t Package.Name.Map.t ; root : Path.t + ; version : string option } - val make : Package.t list -> t + val make : ?version:string -> Package.t list -> t (** The anonymous represent the scope at the root of the workspace when the root of the workspace contains no [.opam] diff --git a/src/jbuild_load.ml b/src/jbuild_load.ml index 1fb42c07..caf1e240 100644 --- a/src/jbuild_load.ml +++ b/src/jbuild_load.ml @@ -275,12 +275,17 @@ let load ?extra_ignored_subtrees ?(ignore_promoted_rules=false) () = match scope, project with | None, None -> assert false | Some _, None -> scope - | None, Some { name } -> + | None, Some { name; version } -> Some { name = Some name ; packages = Package.Name.Map.empty ; root = path + ; version } - | Some scope, Some { name } -> Some { scope with name = Some name }) + | Some scope, Some { name; version } -> + Some { scope with + name = Some name + ; version + }) in let scopes =