2009-06-09 9 views
6

Para las herramientas de análisis de código estático, es necesario conocer todas las rutas de origen efectivas para un proyecto Delphi determinado, que se definen en el nivel de proyecto y en la configuración IDE global.¿Hay una biblioteca Delphi que devuelva todas las rutas de origen efectivas para un proyecto?

¿Hay una biblioteca Delphi que pueda recopilar este tipo de información del proyecto?

Hasta donde yo sé, la configuración del registro para Delphi IDE puede estar en diferentes lugares, para admitir configuraciones múltiples. Pero para una combinación dada de la ubicación del registro IDE y un archivo de proyecto, debería ser posible recopilar las rutas de origen.

Editar: Otra solución es usar el modificador --depends. Esto hará que dcc32.exe escriba un archivo ".d" con todos los nombres de archivos dcu del proyecto (y todas las dependencias), incluidos los nombres de las rutas. Sin embargo, la lista de archivos incluye unidades que ya están compiladas, por lo que no es una solución correcta para el problema original.

+0

¿Alguna versión específica de Delphi que desee conocer? –

+0

Delphi 2009 - porque es mucho más complicado con configuraciones de compilación que incluso pueden heredarse, y puede contener macros como '$ (DCC_UnitSearchPath)' - esto parece ser más difícil de lo esperado ... – mjn

Respuesta

8

Sólo encontró otra solución:

si pongo en marcha el símbolo del sistema RAD Studio y corro

msbuild /t:Rebuild 

en el directorio del proyecto, msbuild mostrará la línea de comando completa para invocar a dcc32, incluidas todas las configuraciones de ruta. Redirigir el registro de compilación a un archivo (o reemplazar dcc32.exe con una versión propia que solo captura los parámetros) y analizar el resultado parece ser mucho más fácil que analizar archivos dproj.

Otra ventaja es que se puede usar en construcciones automatizadas/integración continua.

10

Puede utilizar la API de OpenTools para obtener la ruta de búsqueda del proyecto activo (fusionada de la configuración activa y el conjunto de opciones) y la ruta de la biblioteca global del IDE. Aquí es una unidad de mi paquete de diseño de la prueba rápida:

unit Unit1; 

interface 

uses 
    Windows, SysUtils, Classes, 
    ToolsAPI; 

type 
    TTestWizard = class(TNotifierObject, IOTAWizard, IOTAMenuWizard) 
    private 
    { IOTAWizard } 
    function GetIDString: string; 
    function GetName: string; 
    function GetState: TWizardState; 
    procedure Execute; 
    { IOTAMenuWizard } 
    function GetMenuText: string; 
    private 
    function AddLibraryPaths(Strings: TStrings): Integer; 
    function AddProjectSearchPaths(Strings: TStrings): Integer; 
    end; 

procedure Register; 

implementation 

uses 
    Dialogs, 
    DCCStrs, TypInfo; 

var 
    WizardIndex: Integer = -1; 

procedure GetEnvironmentVariables(Strings: TStrings); 
var 
    P: PChar; 
begin 
    P := nil; 
    Strings.BeginUpdate; 
    try 
    Strings.Clear; 
    P := GetEnvironmentStrings; 
    repeat 
     Strings.Add(P); 
     P := StrEnd(P); 
     Inc(P); 
    until P^ = #0; 
    finally 
    if Assigned(P) then 
     FreeEnvironmentStrings(P); 
    Strings.EndUpdate; 
    end; 
end; 

function EvaluateEnvironmentVariables(const S: string): string; 
var 
    Strings: TStringList; 
    I: Integer; 
begin 
    Result := S; 

    Strings := TStringList.Create; 
    try 
    GetEnvironmentVariables(Strings); 
    for I := 0 to Strings.Count - 1 do 
     Result := StringReplace(Result, Format('$(%s)', [Strings.Names[I]]), Strings.ValueFromIndex[I], 
     [rfReplaceAll, rfIgnoreCase]); 
    finally 
    Strings.Free; 
    end; 
end; 

procedure Register; 
begin 
    WizardIndex := (BorlandIDEServices as IOTAWizardServices).AddWizard(TTestWizard.Create); 
end; 

{ TTestWizard private: IOTAWizard } 

function TTestWizard.GetIDString: string; 
begin 
    Result := 'TOndrej.TestWizard'; 
end; 

function TTestWizard.GetName: string; 
begin 
    Result := 'TestWizard'; 
end; 

function TTestWizard.GetState: TWizardState; 
begin 
    Result := [wsEnabled]; 
end; 

procedure TTestWizard.Execute; 
var 
    Paths: TStrings; 
begin 
    Paths := TStringList.Create; 
    try 
    AddProjectSearchPaths(Paths); 
    AddLibraryPaths(Paths); 
    ShowMessage(EvaluateEnvironmentVariables(Paths.Text)); 
    finally 
    Paths.Free; 
    end; 
end; 

{ TTestWizard private: IOTAMenuWizard } 

function TTestWizard.GetMenuText: string; 
begin 
    Result := GetIDString; 
end; 

function TTestWizard.AddLibraryPaths(Strings: TStrings): Integer; 
var 
    Paths: TStringList; 
    EnvironmentOptions: IOTAEnvironmentOptions; 
begin 
    Paths := TStringList.Create; 
    try 
    Paths.Delimiter := ';'; 
    Paths.StrictDelimiter := True; 
    EnvironmentOptions := (BorlandIDEServices as IOTAServices).GetEnvironmentOptions; 
    Paths.DelimitedText := EnvironmentOptions.Values['LibraryPath']; 
    Strings.AddStrings(Paths); 
    Result := Paths.Count; 
    finally 
    Paths.Free; 
    end; 
end; 

function TTestWizard.AddProjectSearchPaths(Strings: TStrings): Integer; 
var 
    ActiveProject: IOTAProject; 
    Configurations: IOTAProjectOptionsConfigurations; 
    Configuration: IOTABuildConfiguration; 
    Paths: TStringList; 
begin 
    Result := -1; 
    ActiveProject := GetActiveProject; 
    if not Assigned(ActiveProject) then 
    Exit; 
    Configurations := ActiveProject.ProjectOptions as IOTAProjectOptionsConfigurations; 
    Configuration := Configurations.ActiveConfiguration; 
    if not Assigned(Configuration) then 
    Exit; 

    Paths := TStringList.Create; 
    try 
    Configuration.GetValues(sUnitSearchPath, Paths, True); 
    Strings.AddStrings(Paths); 
    Result := Paths.Count; 
    finally 
    Paths.Free; 
    end; 
end; 

initialization 

finalization 
    if WizardIndex <> -1 then 
    (BorlandIDEServices as IOTAWizardServices).RemoveWizard(WizardIndex); 

end. 
+0

Esto se ve muy prometedor, muchas gracias ¡mucho! Voy a echar un vistazo más de cerca a la OTA. Es fácil obtener una lista de los archivos fuente del proyecto (¿todos los archivos que se han agregado explícitamente al DPR)? También echaré un vistazo a las fuentes de GExpert/cnWizard. – mjn

+0

Sí, con OTA puede enumerar módulos de un proyecto. Eche un vistazo a la interfaz IOTAProject. Específicamente, los métodos de IOTAProject40 GetModuleCount, GetModule. –

Cuestiones relacionadas