Skip to content

Commit

Permalink
implementation of an automatic gpr file with (#458)
Browse files Browse the repository at this point in the history
* First prototype implementation of an automatic gpr file with

* Add user query and config option for Auto-gpr-with

* Introduce Boolean properties

* Alire.Properties.Labeled: check TOML_Kind for labels

* auto-gpr-with: add crate entry to disable auto-gpr-with feature

* testsuite: allow custom indexes to reference fixtures/crates/

This removes duplication of several sources and archives.

* Bump index version to 0.3 for auto-gpr-with feature

* auto-gpr-with: do not add default project file for extern crates

* Bump alire-index in CI scripts

* tests/workflows/auto-gpr-with: rename test crate to avoid conflicts with scripts

* Review fixes

* tests/get/external-tool-dependency: make the test more robust

On Windows when using msys2, the make seen by alr can be different than
the one seen from the testsuite scripts. The means that the current way
to identify make's version will fail in some cases.

This patch introduces a different way to workaround the different
version numbers of make.
  • Loading branch information
Fabien-Chouteau committed Jul 2, 2020
1 parent ffe95df commit 8b908a6
Show file tree
Hide file tree
Showing 83 changed files with 575 additions and 129 deletions.
7 changes: 7 additions & 0 deletions doc/catalog-format-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,13 @@ entries:
# An explicit empty case alternative, which is not mandatory
```

- `auto-gpr-with`: Boolean value that specifies if the project files of a
crate can be automatically 'withed' by the root project file (default is
true). This feature is meant to simplify the process of using dependencies
in Alire. However, not all project files are supposed to be withed, some can
be extended for instance, in that case a crate can disable the feature by
setting `auto-gpr-with=false`.

## Release-specific information

Each release is materialized as an entry in the top-level object. The key is a
Expand Down
29 changes: 29 additions & 0 deletions doc/user-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,35 @@ This document is a development diary summarizing changes in `alr` that notably
affect the user experience. It is intended as a one-stop point for users to
stay on top of `alr` new features.

### Automatically 'with' GPR project files from dependencies

PR [#458](https://github.com/alire-project/alire/pull/458).

When adding or removing dependency with `alr with`, a list of `with` statement
for each project files of the dependencies can be automatically added to the
root project file:
```
-- begin auto-gpr-with --
-- This section was automatically added by Alire
with "libhello.gpr";
-- end auto-gpr-with --
project Test is
...
```

This feature can be permanently enabled or disabled with a local or global
configuration option:
```bash
alr config --global --set auto-gpr-with false
```

Crates with project files not compatible with this feature can disable it using
the `auto-gpr-with` entry:
```toml
auto-gpr-with=false
```

### Show release-specific dependency sets in solutions

PR [#453](https://github.com/alire-project/alire/pull/453).
Expand Down
9 changes: 8 additions & 1 deletion src/alire/alire-config.ads
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,14 @@ private
(+"msys2.install_dir",
Cfg_Absolute_Path,
+("Directory where Alire will detect and/or install" &
" msys2 system package manager. (Windows only) "))
" msys2 system package manager. (Windows only)")),

(+"auto-gpr-with",
Cfg_Bool,
+("If true, Alire will automatically add/edit a list of 'with' " &
"statements in the root GPR project file based on the " &
"dependencies of the crate."))

);

end Alire.Config;
2 changes: 1 addition & 1 deletion src/alire/alire-index.ads
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ package Alire.Index is
and then Branch_String (Branch_String'Last) /= '-'
and then (for some C of Branch_String => C = '-');

Community_Branch : constant String := "devel-0.2";
Community_Branch : constant String := "devel-0.3";
-- The branch used for the community index

Version : constant Semantic_Versioning.Version :=
Expand Down
65 changes: 65 additions & 0 deletions src/alire/alire-properties-bool.adb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package body Alire.Properties.Bool is

---------------
-- From_TOML --
---------------

function From_TOML (From : TOML_Adapters.Key_Queue)
return Conditional.Properties
is
Value : TOML.TOML_Value;
Key : constant String := From.Pop (Value);

------------------
-- Key_To_Label --
------------------

function Key_To_Label (K : String) return Labels is
begin
-- TODO: instead of this inefficient O(n) lookup, have a map.
for L in Labels loop
if Bool.Key (L) = K then
return L;
end if;
end loop;
From.Checked_Error ("Key is not a valid boolean property: " & K);
end Key_To_Label;

-- For conditional loading, we use specific conditional loaders that
-- only recognize the property being loaded:

begin
return Props : Conditional.Properties do
declare
Val : constant TOML.TOML_Value := TOML_Adapters.To_Array (Value);
-- We process the same way single values and arrays of values
-- (since they get converted into individual properties).
begin
if Val.Length > 1 then
raise Checked_Error with
"Expected single value for " & Key;
end if;

if Val.Item (1).Kind /= TOML_Boolean then
raise Checked_Error with "Expected boolean value for " & Key;
end if;

declare
L : constant Property := New_Property
(Key_To_Label (Key),
Val.Item (1).As_Boolean);
use all type Conditional.Properties;
begin
-- Labeled property is valid and added to the release props.
Props := Props and
Conditional.For_Properties.New_Value (L);
end;
end;
end return;
exception
when E : others =>
Log_Exception (E);
raise Checked_Error with "Cannot read valid property from " & Key;
end From_TOML;

end Alire.Properties.Bool;
72 changes: 72 additions & 0 deletions src/alire/alire-properties-bool.ads
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
with Alire.Conditional;
with Alire.GPR;
with Alire.TOML_Adapters;
with Alire.TOML_Keys;
with Alire.Utils;

package Alire.Properties.Bool with Preelaborate is

type Labels is
(Auto_GPR_With
-- Boolean to specify if a crate is compatible with the auto-gpr-with
-- feature.
);

type Property is new Properties.Property with private;

function New_Property (Name : Labels;
V : Boolean)
return Property;

overriding
function Image (V : Property) return String;

overriding
function To_YAML (V : Property) return String;

overriding
function Key (V : Property) return String;

function Value (V : Property) return Boolean;

function From_TOML (From : TOML_Adapters.Key_Queue)
return Conditional.Properties;
private

function Key (L : Labels) return String
is (case L is
when Auto_GPR_With => TOML_Keys.Auto_GPR_With);

type Property is new Properties.Property with record
Name : Labels;
Value : Boolean;
end record;

overriding
function To_TOML (V : Property) return TOML.TOML_Value;

function New_Property (Name : Labels;
V : Boolean)
return Property
is (Name => Name, Value => V);

overriding
function Image (V : Property) return String
is (Utils.To_Mixed_Case (V.Name'Img) & ": " & V.To_YAML);

overriding
function To_YAML (V : Property) return String
is (Key (V.Name) & "=" & (if V.Value then "true" else "false"));

overriding
function To_TOML (V : Property) return TOML.TOML_Value
is (TOML.Create_Boolean (V.Value));

overriding
function Key (V : Property) return String
is (Key (V.Name));

function Value (V : Property) return Boolean
is (V.Value);

end Alire.Properties.Bool;
4 changes: 4 additions & 0 deletions src/alire/alire-properties-from_toml.ads
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ with Alire.Properties.Environment;
with Alire.Properties.Labeled;
with Alire.Properties.Licenses;
with Alire.Properties.Scenarios;
with Alire.Properties.Bool;
with Alire.TOML_Adapters;

package Alire.Properties.From_TOML with Preelaborate is
Expand All @@ -13,6 +14,7 @@ package Alire.Properties.From_TOML with Preelaborate is

type Property_Keys is (Actions,
Authors,
Auto_GPR_With,
Description,
Environment,
Executables,
Expand Down Expand Up @@ -49,6 +51,7 @@ package Alire.Properties.From_TOML with Preelaborate is
=> Scenarios.From_TOML'Access,
Hint => null, -- Only apply to externals
Licenses => Properties.Licenses.From_TOML'Access,
Auto_GPR_With => Bool.From_TOML'Access,
others => Labeled.From_TOML'Access);
-- This loader is used in the [general] crate section

Expand All @@ -62,6 +65,7 @@ package Alire.Properties.From_TOML with Preelaborate is
=> Scenarios.From_TOML'Access,
Notes => Labeled.From_TOML'Access,
Project_Files => Labeled.From_TOML'Access,
Auto_GPR_With => Bool.From_TOML'Access,
others => null);
-- This loader applies to release sections

Expand Down
5 changes: 5 additions & 0 deletions src/alire/alire-properties-labeled.adb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ package body Alire.Properties.Labeled is
-- (since they get converted into individual properties).
begin
for I in 1 .. Val.Length loop

if Val.Item (I).Kind /= TOML_String then
raise Checked_Error with "Expected String value for " & Key;
end if;

declare
L : constant Label := New_Label
(Key_To_Label (Key),
Expand Down
29 changes: 28 additions & 1 deletion src/alire/alire-releases.adb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ with Alire.Defaults;
with Alire.Requisites.Booleans;
with Alire.TOML_Load;
with Alire.Utils.YAML;
with Alire.Properties.Bool;

with GNAT.IO; -- To keep preelaborable

Expand Down Expand Up @@ -258,6 +259,10 @@ package body Alire.Releases is
else Properties),
Available => Requisites.Booleans.Always_True);

-------------------------
-- On_Platform_Actions --
-------------------------

function On_Platform_Actions (R : Release;
P : Alire.Properties.Vector;
Moments : Moment_Array := (others => True))
Expand Down Expand Up @@ -380,7 +385,12 @@ package body Alire.Releases is
Props_To_Strings (R.All_Properties (P), Project_File);
Without : Utils.String_Vector;
begin
if With_Paths.Is_Empty then
if With_Paths.Is_Empty
and then
R.Origin.Kind not in Origins.External | Origins.System
then
-- Default project file if no one is specified by the crate. Only if
-- the create is not external nor system.
With_Paths.Append (String'((+R.Name) & ".gpr"));
end if;

Expand Down Expand Up @@ -423,6 +433,23 @@ package body Alire.Releases is
end return;
end Project_Paths;

-------------------
-- Auto_GPR_With --
-------------------

function Auto_GPR_With (R : Release) return Boolean is
Vect : constant Alire.Properties.Vector :=
Conditional.Enumerate (R.Properties).Filter
(Alire.TOML_Keys.Auto_GPR_With);
begin
if not Vect.Is_Empty then
return Alire.Properties.Bool.Property (Vect.First_Element).Value;
else
-- The default is to enable auto-gpr-with
return True;
end if;
end Auto_GPR_With;

------------------------
-- Labeled_Properties --
------------------------
Expand Down
2 changes: 2 additions & 0 deletions src/alire/alire-releases.ads
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ package Alire.Releases with Preelaborate is

function Tag (R : Release) return Alire.Properties.Vector;

function Auto_GPR_With (R : Release) return Boolean;

procedure Print (R : Release);
-- Dump info to console

Expand Down
29 changes: 29 additions & 0 deletions src/alire/alire-roots.adb
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,33 @@ package body Alire.Roots is
return Paths;
end Project_Paths;

-----------------------
-- GPR_Project_Files --
-----------------------

function GPR_Project_Files (This : Root;
Exclude_Root : Boolean)
return Utils.String_Set
is
Files : Utils.String_Set;
begin

-- Add files from every release in the solution

for Rel of This.Solution.Releases.Including (Release (This)) loop

if (not Exclude_Root or else Rel.Name /= Release (This).Name)
and then
Rel.Auto_GPR_With
then
for File of Rel.Project_Files
(This.Environment, With_Path => False)
loop
Files.Include (File);
end loop;
end if;
end loop;
return Files;
end GPR_Project_Files;

end Alire.Roots;
15 changes: 15 additions & 0 deletions src/alire/alire-roots.ads
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,25 @@ package Alire.Roots is
-- solution in this root. This includes al releases' paths and any linked
-- directories.

function GPR_Project_Files (This : Root;
Exclude_Root : Boolean)
return Utils.String_Set with
Pre => This.Is_Valid;
-- Return all the gprbuild project files defined for the solution in this
-- root. If Exclude_Root is True, the project files of the root crate are
-- excluded from the result.

function Release (This : Root) return Releases.Release with
Pre => This.Is_Valid;

function Solution (This : Root) return Solutions.Solution with
Pre => This.Is_Valid;
-- Returns the solution stored in the lockfile

function Environment (This : Root) return Properties.Vector with
Pre => This.Is_Valid;
-- Properties of the Root

-- files and folders derived from the root path (this obsoletes Alr.Paths)

function Working_Folder (This : Root) return Absolute_Path with
Expand Down Expand Up @@ -155,4 +167,7 @@ private
function Working_Folder (This : Root) return Absolute_Path is
((+This.Path) / "alire");

function Environment (This : Root) return Properties.Vector
is (This.Environment);

end Alire.Roots;
1 change: 1 addition & 0 deletions src/alire/alire-toml_keys.ads
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package Alire.TOML_Keys with Preelaborate is
Action_Folder : constant String := "directory";
Archive_Name : constant String := "archive-name";
Author : constant String := "authors";
Auto_GPR_With : constant String := "auto-gpr-with";
Available : constant String := "available";
Compiler : constant String := "compiler";
Depends_On : constant String := "depends-on";
Expand Down
Loading

0 comments on commit 8b908a6

Please sign in to comment.