Add support for command line in gnatbdd, in particular -P

Add 'make install', and reorganize projects so that the generate project
now depends on gnatbdd.gpr.
This commit is contained in:
Emmanuel Briot 2014-06-05 15:42:52 +02:00
parent 6268f45432
commit de179bcbdd
36 changed files with 481 additions and 75 deletions

View File

@ -1,18 +1,39 @@
DESTDIR=
prefix=install
exec_prefix=${prefix}
datarootdir=${prefix}/share
datadir=${DESTDIR}${datarootdir}
bindir=${DESTDIR}${exec_prefix}/bin
libdir=${DESTDIR}${exec_prefix}/lib
includedir=${DESTDIR}${prefix}/include
projectsubdir=lib/gnat
projectdir=${DESTDIR}${prefix}/${projectsubdir}
MKDIR=mkdir -p
CP=cp -p
all: build
build:
gprbuild -Pgnatbdd.gpr
build: force
gprbuild -Pgnatbdd_main.gpr -j0 -p
clean: force
gprclean -Pgnatbdd_main -r
install: force
gprinstall --prefix=${prefix} -q -p -f --install-name=gnatbdd --project-subdir=${projectsubdir} src/gnatbdd.gpr
${MKDIR} ${bindir}
${CP} obj/gnatbdd ${bindir}/
# Adding new scenarios does not erquire recompiling the driver
test: build_driver
#-./obj/driver --output=hide_passed
#-./obj/driver --output=quiet
#-./obj/driver --output=dots
-./obj/driver --output=full
-./obj/driver --output=full -o test.html
test: build install build_driver
-./example/obj/driver --output=full --features=example/features
-./example/obj/driver --output=full -o test.html --features=example/features
# Driver only needs to be recompiled when the step definitions change
build_driver: features/step_definitions/*
obj/gnatbdd
gprbuild -P obj/driver.gpr
build_driver:
${bindir}/gnatbdd -Pexample/calc.gpr
GPR_PROJECT_PATH=${projectdir} gprbuild -P example/obj/driver.gpr
force:

8
example/calc.gpr Normal file
View File

@ -0,0 +1,8 @@
project Calc is
for Source_Dirs use ("src");
for Object_Dir use "obj";
package GnatBDD is
for Switches use ("--steps=features/step_definitions");
end GnatBDD;
end Calc;

View File

@ -4,11 +4,6 @@ with Calculator; use Calculator;
package body MySteps1 is
procedure Given_An_Empty_Calculator is
begin
Reset;
end Given_An_Empty_Calculator;
procedure When_I_Enter (Value : String) is
begin
Enter (Value);

View File

@ -2,9 +2,6 @@ with BDD.Tables;
package MySteps1 is
-- @given ^an empty calculator$
procedure Given_An_Empty_Calculator;
-- @when ^I enter "(.*)"$
procedure When_I_Enter (Value : String)
with Pre => Value /= "";
@ -12,7 +9,7 @@ package MySteps1 is
-- @then ^I should read (\d+)$
procedure Then_I_Should_Read (Result : Integer);
-- @then the stack should contain
-- @then ^the stack should contain$
procedure Then_The_Stack_Should_Contain (Expected : BDD.Tables.Table);
end MySteps1;

View File

@ -2,7 +2,10 @@ package Calculator is
type Integer_Array is array (Natural range <>) of Integer;
-- @given ^an empty calculator$
procedure Reset;
-- An actual subprogram, that can be used directly from a step.
procedure Enter (Value : String);
function Peek return Integer;
function Peek_Stack return Integer_Array;

View File

@ -1,9 +1,10 @@
with "gnatcoll";
with "src/gnatbdd.gpr";
project GNATBDD is
for Main use ("gnatbdd.adb");
project GNATBDD_Main is
for Main use ("gnatbdd-main.adb");
for Languages use ("Ada");
for Source_Dirs use ("src");
for Source_Dirs use ("src/gnatbdd/");
for Object_Dir use "obj";
package Compiler is
@ -12,7 +13,11 @@ project GNATBDD is
"-gnateE");
end Compiler;
package Builder is
for Executable ("gnatbdd-main.adb") use "gnatbdd";
end Builder;
package Binder is
for Switches ("Ada") use ("-E");
end Binder;
end GNATBDD;
end GNATBDD_Main;

View File

@ -1,5 +1,5 @@
-----------------------------------------------------------------------------
-- g N A T C O L L --
------------------------------------------------------------------------------
-- G N A T C O L L --
-- --
-- Copyright (C) 2005-2014, AdaCore --
-- --
@ -75,8 +75,8 @@ package body BDD is
begin
Set_Usage
(Config,
Usage => "[switches] [file:line1:line2] [file#num1#num2]",
Help =>
Usage => "[switches] [file:line1:line2] [file#num1#num2]",
Help =>
"Run each of the scenario defined in features files.");
Define_Switch

View File

@ -1,18 +0,0 @@
-- This subprogram generates the test driver by including all the
-- step definitions provided by the user, as well as the predefined
-- steps, regular expressions and mockups.
with BDD.Codegen; use BDD.Codegen;
with GNATCOLL.Traces; use GNATCOLL.Traces;
with GNATCOLL.VFS; use GNATCOLL.VFS;
procedure Gnatbdd is
Finder : Steps_Finder;
begin
GNATCOLL.Traces.Parse_Config_File;
Discover_Steps
(Finder,
Extension => ".ads",
Directory => Create_From_Base ("features/step_definitions"));
end Gnatbdd;

12
src/gnatbdd.gpr Normal file
View File

@ -0,0 +1,12 @@
with "gnatcoll";
library project Gnatbdd is
for Source_Dirs use ("bdd/");
for Object_Dir use "../obj";
for Library_Name use "gnatbdd";
for Library_Kind use "static";
for Library_Dir use "../obj/lib";
for Library_Version use "lib" & Project'Library_Name & ".so.1.0";
end Gnatbdd;

View File

@ -26,10 +26,11 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Unchecked_Deallocation;
with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Regpat; use GNAT.Regpat;
with GNAT.Strings; use GNAT.Strings;
with GNATCOLL.Traces; use GNATCOLL.Traces;
with GNATCOLL.Utils; use GNATCOLL.Utils;
package body BDD.Codegen is
package body Gnatbdd.Codegen is
Me : constant Trace_Handle := Create ("BDD.CODEGEN");
Cst_Procedure : constant String := "procedure ";
@ -476,24 +477,50 @@ package body BDD.Codegen is
--------------------
procedure Discover_Steps
(Self : in out Steps_Finder;
Extension : Filesystem_String := ".ads";
Directory : GNATCOLL.VFS.Virtual_File)
(Self : in out Steps_Finder;
Extension : Filesystem_String := ".ads";
Object_Dir : GNATCOLL.VFS.Virtual_File;
Tree : GNATCOLL.Projects.Project_Tree;
Extra_Steps_Dirs : GNATCOLL.VFS.File_Array_Access)
is
Files : File_Array_Access := Directory.Read_Dir_Recursive
(Extension => Extension, Filter => Files_Only);
Data : Generated_Data;
F : File_Type;
begin
if Files /= null then
for F in Files'Range loop
Check_Steps (Self, File => Files (F), Data => Data);
end loop;
Files : File_Array_Access;
Data : Generated_Data;
F : File_Type;
Sources : File_And_Project_Array_Access :=
Tree.Root_Project.Source_Files (Recursive => True);
Set : File_Info_Set;
Unchecked_Free (Files);
begin
-- Parse project source files
if Sources /= null then
for F in Sources'Range loop
Set := Tree.Info_Set (Sources (F).File);
for S of Set loop
if File_Info (S).Project = Sources (F).Project
and then File_Info (S).Unit_Part = Unit_Spec
then
Check_Steps (Self, File => Sources (F).File, Data => Data);
end if;
end loop;
end loop;
Free (Sources);
end if;
Create (F, Out_File, "obj/driver.adb");
if Extra_Steps_Dirs /= null then
for D in Extra_Steps_Dirs'Range loop
Files := Extra_Steps_Dirs (D).Read_Dir_Recursive
(Extension => Extension, Filter => Files_Only);
if Files /= null then
for F in Files'Range loop
Check_Steps (Self, File => Files (F), Data => Data);
end loop;
Unchecked_Free (Files);
end if;
end loop;
end if;
Create (F, Out_File,
Create_From_Dir (Object_Dir, "driver.adb").Display_Full_Name);
Put_Line (F, "-- Automatically generated");
Put_Line (F, "with BDD; use BDD;");
Put_Line (F, "with BDD.Main; use BDD.Main;");
@ -516,9 +543,15 @@ package body BDD.Codegen is
& ");");
Put_Line (F, " begin");
Put (F, To_String (Data.Matchers));
Put_Line (F, " else");
Put_Line (F, " Step.Set_Status (Status_Undefined);");
Put_Line (F, " end if;");
if Data.Matchers /= "" then
Put_Line (F, " else");
Put_Line (F, " Step.Set_Status (Status_Undefined);");
Put_Line (F, " end if;");
else
Put_Line (F, " Step.Set_Status (Status_Undefined);");
end if;
Put_Line (F, " end Run_Steps;");
New_Line (F);
Put_Line (F, " Runner : Feature_Runner;");
@ -529,13 +562,27 @@ package body BDD.Codegen is
Put_Line (F, "end Driver;");
Close (F);
Create (F, Out_File, "obj/driver.gpr");
Create (F, Out_File,
Create_From_Dir (Object_Dir, "driver.gpr").Display_Full_Name);
Put_Line (F, "with ""gnatcoll"";");
Put_Line (F, "with ""gnatbdd"";");
Put_Line (F, "with """
& Tree.Root_Project.Project_Path.Display_Full_Name
& """;");
Put_Line (F, "project Driver is");
Put_Line (F, " for Main use (""driver.adb"");");
Put_Line (F, " for Source_Dirs use (""."",");
Put_Line (F, " ""../src/"",");
Put_Line (F, " """ & Directory.Display_Full_Name & "/**"");");
Put (F, " for Source_Dirs use ("".""");
if Extra_Steps_Dirs /= null then
for D in Extra_Steps_Dirs'Range loop
Put (F, ", """
& Extra_Steps_Dirs (D).Display_Full_Name & "**""");
end loop;
end if;
Put_Line (F, ");");
Put_Line (F, " package Binder is");
Put_Line (F, " for Switches (""Ada"") use (""-E"", ""-g"");");
Put_Line (F, " end Binder;");
@ -546,4 +593,4 @@ package body BDD.Codegen is
Close (F);
end Discover_Steps;
end BDD.Codegen;
end Gnatbdd.Codegen;

View File

@ -23,7 +23,10 @@
-- Support for code generation (detecting user-defined steps,...)
package BDD.Codegen is
with GNATCOLL.Projects; use GNATCOLL.Projects;
with GNATCOLL.VFS; use GNATCOLL.VFS;
package Gnatbdd.Codegen is
type Steps_Finder is tagged private;
@ -31,13 +34,16 @@ package BDD.Codegen is
-- Free memory used by Self
procedure Discover_Steps
(Self : in out Steps_Finder;
Extension : Filesystem_String := ".ads";
Directory : GNATCOLL.VFS.Virtual_File);
-- Find all Ada files that contain step definitions
(Self : in out Steps_Finder;
Extension : Filesystem_String := ".ads";
Object_Dir : GNATCOLL.VFS.Virtual_File;
Tree : GNATCOLL.Projects.Project_Tree;
Extra_Steps_Dirs : GNATCOLL.VFS.File_Array_Access);
-- Parse all specs in the project's source directories or in
-- Extra_Steps_Dirs, to find the definition of steps.
private
type Steps_Finder is tagged record
Files : GNATCOLL.VFS.File_Array_Access;
end record;
end BDD.Codegen;
end Gnatbdd.Codegen;

View File

@ -0,0 +1,91 @@
------------------------------------------------------------------------------
-- G N A T C O L L --
-- --
-- Copyright (C) 2014, AdaCore --
-- --
-- This library is free software; you can redistribute it and/or modify it --
-- under terms of the GNU General Public License as published by the Free --
-- Software Foundation; either version 3, or (at your option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
-- This subprogram generates the test driver by including all the
-- step definitions provided by the user, as well as the predefined
-- steps, regular expressions and mockups.
with Ada.Command_Line; use Ada.Command_Line;
with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Command_Line; use GNAT.Command_Line;
with GNAT.Strings; use GNAT.Strings;
with Gnatbdd.Codegen; use Gnatbdd.Codegen;
with Gnatbdd.Support; use Gnatbdd.Support;
with GNATCOLL.Projects; use GNATCOLL.Projects;
with GNATCOLL.Traces; use GNATCOLL.Traces;
with GNATCOLL.VFS; use GNATCOLL.VFS;
procedure Gnatbdd.Main is
Me : constant Trace_Handle := Create ("BDD");
Finder : Steps_Finder;
Config : Command_Line_Configuration;
Tree : Project_Tree;
Setup : Configuration;
begin
GNATCOLL.Traces.Parse_Config_File;
Setup_Command_Line_Switches (Config);
Parse_Command_Line (Setup, Config);
if Setup.Project_Name = No_File then
Put_Line (Standard_Error, "No project specified");
Set_Exit_Status (Failure);
return;
end if;
Parse_Project (Tree, Setup);
declare
Ads_Extension : constant String :=
Tree.Root_Project.Attribute_Value
(Attribute => Specification_Suffix_Attribute,
Index => "ada",
Default => ".ads",
Use_Extended => True);
Switches_From_Project : String_List_Access :=
Tree.Root_Project.Attribute_Value
(Attribute => Gnatbdd_Switches_Attr,
Use_Extended => True);
begin
if Switches_From_Project /= null then
Trace (Me, "Parsing switches found in project");
Parse_Command_Line (Setup, Config, Switches_From_Project);
Switches_From_Project := null; -- freed above
end if;
Discover_Steps
(Finder,
Extension => +Ads_Extension,
Object_Dir => Tree.Root_Project.Object_Dir,
Tree => Tree,
Extra_Steps_Dirs => Setup.Steps_Dirs);
end;
exception
when GNAT.Command_Line.Exit_From_Command_Line
| GNAT.Command_Line.Invalid_Switch
| GNAT.Command_Line.Invalid_Parameter
=>
null;
end Gnatbdd.Main;

View File

@ -0,0 +1,147 @@
------------------------------------------------------------------------------
-- Copyright (C) 2014, AdaCore --
-- --
-- This library is free software; you can redistribute it and/or modify it --
-- under terms of the GNU General Public License as published by the Free --
-- Software Foundation; either version 3, or (at your option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
with Ada.Command_Line; use Ada.Command_Line;
with Ada.Text_IO; use Ada.Text_IO;
with GNATCOLL.Traces; use GNATCOLL.Traces;
package body Gnatbdd.Support is
Me : constant Trace_Handle := Create ("BDD.SUPPORT");
procedure Error (Msg : String);
pragma No_Return (Error);
-- Report an error to the main
-----------
-- Error --
-----------
procedure Error (Msg : String) is
begin
if Msg /= "" then
Put_Line (Standard_Error, Msg);
end if;
Set_Exit_Status (Failure);
raise GNAT.Command_Line.Invalid_Parameter;
end Error;
---------------------------------
-- Setup_Command_Line_Switches --
---------------------------------
procedure Setup_Command_Line_Switches
(Config : in out Command_Line_Configuration)
is
begin
Set_Usage
(Config,
Usage => "-Pproject [switches]",
Help => "Generate and compile the test driver");
Define_Switch
(Config,
Switch => "-P:",
Argument => "PROJECT",
Help => "Project to load to find the sources of your application");
Define_Switch
(Config,
Long_Switch => "--steps=",
Argument => "DIR",
Help => "Specify a directory to search for step definitions");
end Setup_Command_Line_Switches;
------------------------
-- Parse_Command_Line --
------------------------
procedure Parse_Command_Line
(Result : in out Configuration;
Config : Command_Line_Configuration;
Switches : GNAT.Strings.String_List_Access := null)
is
procedure On_Switch (Switch, Parameter, Section : String);
procedure On_Switch (Switch, Parameter, Section : String) is
pragma Unreferenced (Section);
begin
Trace (Me, "Seen switch " & Switch & " '" & Parameter & "'");
if Switch = "--steps" then
if Switches = null then
Append (Result.Steps_Dirs, Create_From_Base (+Parameter));
else
Append (Result.Steps_Dirs,
Create_From_Dir
(Create (Result.Project_Name.Dir_Name), +Parameter));
end if;
elsif Switch = "-P" then
if Switches /= null then
Error ("-P cannot be specified in gnatbdd'switches");
end if;
Result.Project_Name := Create_From_Base (+Parameter);
if not Result.Project_Name.Is_Regular_File then
Result.Project_Name := Create_From_Base (+Parameter & ".gpr");
if not Result.Project_Name.Is_Regular_File then
Error ("Project file not found");
end if;
end if;
end if;
end On_Switch;
Parser : Opt_Parser;
begin
if Switches /= null then
Initialize_Option_Scan (Parser, Command_Line => Switches);
Getopt (Config, On_Switch'Unrestricted_Access, Parser);
Free (Parser);
else
Getopt (Config, On_Switch'Unrestricted_Access);
end if;
end Parse_Command_Line;
-------------------
-- Parse_Project --
-------------------
procedure Parse_Project
(Tree : out Project_Tree;
Config : Configuration)
is
Err : constant String := Register_New_Attribute
(Name => "switches",
Pkg => "gnatbdd",
Is_List => True);
begin
if Err /= "" then
Error (Err);
end if;
Tree.Load (Root_Project_Path => Config.Project_Name,
Errors => Ada.Text_IO.Put_Line'Access);
exception
when Invalid_Project =>
Error ("");
end Parse_Project;
end Gnatbdd.Support;

View File

@ -0,0 +1,68 @@
------------------------------------------------------------------------------
-- Copyright (C) 2014, AdaCore --
-- --
-- This library is free software; you can redistribute it and/or modify it --
-- under terms of the GNU General Public License as published by the Free --
-- Software Foundation; either version 3, or (at your option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
-- Support utilities for gnatbdd
with GNAT.Command_Line; use GNAT.Command_Line;
with GNAT.Strings; use GNAT.Strings;
with GNATCOLL.Projects; use GNATCOLL.Projects;
with GNATCOLL.VFS; use GNATCOLL.VFS;
package Gnatbdd.Support is
------------------
-- Command line --
------------------
type Configuration is record
Project_Name : GNATCOLL.VFS.Virtual_File;
Steps_Dirs : GNATCOLL.VFS.File_Array_Access;
end record;
-- Various configurations from the command line
procedure Setup_Command_Line_Switches
(Config : in out Command_Line_Configuration);
-- Register the supported command line switches
procedure Parse_Command_Line
(Result : in out Configuration;
Config : Command_Line_Configuration;
Switches : GNAT.Strings.String_List_Access := null);
-- Parse command line switches.
-- If Switches is null, the actual command line is parsed, otherwise the
-- switches are extracted from Switches. Switches supports a limited
-- subset of all switches (for instance it cannot contain -P, since we
-- assume Switches already comes from the project
-- This procedure will free Switches.
-------------
-- Project --
-------------
Gnatbdd_Switches_Attr : constant Attribute_Pkg_List :=
Build ("gnatbdd", "switches");
procedure Parse_Project
(Tree : out Project_Tree;
Config : Configuration);
-- Parse the project
end Gnatbdd.Support;

24
src/gnatbdd/gnatbdd.ads Normal file
View File

@ -0,0 +1,24 @@
------------------------------------------------------------------------------
-- Copyright (C) 2014, AdaCore --
-- --
-- This library is free software; you can redistribute it and/or modify it --
-- under terms of the GNU General Public License as published by the Free --
-- Software Foundation; either version 3, or (at your option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
package Gnatbdd is
pragma Pure;
end Gnatbdd;