Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to batch convert bdsproj to dproj?

We recently upgraded from Delphi 2006 to Delphi 2007, and the project files changed from .bdsproj to .dproj.

My research so far indicates that in order to create the .dproj, an existing project needs to be opened in the D2007 IDE. We have over 400 .bdsproj files so doing this manually is not really practical.

The process I came up with was to open all the projects from the command line using:

find . -name *.bdsproj -exec bds.exe -pDelphi -ns -m "{}" ";"

This isn't ideal because it is quite slow (wait for BDS to load, wait for compile to happen, wait while BDS closes, ...).

Is there an efficient way to convert multiple .bdsproj to .dproj?

Note: The 'find' in the above command line is a UNIX-like find (e.g. MKS or GNU) which searches for files, not the Windows find which searches for text within files.

like image 279
WileCau Avatar asked Nov 19 '10 02:11

WileCau


3 Answers

You can open several projects at once. Even using drag and drop.

  • Select 40 projects
  • Drag them to the IDE
  • Click yes 40 times
  • Save all
  • close all
  • Repeat until finished.
like image 165
Toon Krijthe Avatar answered Nov 11 '22 02:11

Toon Krijthe


Here is a fancier version of the find solution using PowerShell. It searches for bdsproj files under a specified directory and produces a bdsgroup containing all of the projects.

After the script is run, open the bdsgroup with D2007 to convert the projects to dproj. D2007 also produces a groupproj, which seems to be the D2007 equivalent of bdsgroup.

Hints:

  • Run the script with -help to see instructions.
  • Start D2007 before opening the bdsgroup, it seems to process the projects quicker.
  • You don't need to save the projects, opening them is enough to create the dproj.

Thanks to:

  • Ulrich Gerhardt for suggesting the bdsgroup approach.
  • dangph for help with the PowerShell script.

Here's the script. It works for me :o)

Param(
    $path = ".",
    $exclude = "",
    [switch]$help
)

Set-PSDebug -Strict
$ErrorActionPreference = 'Stop'

# Ensure path is fully qualified and ends with a path delimiter
$path = Join-Path (Resolve-Path $path) ""

# Output file full name ($path\scriptname.bdsproj)
$outfile = Join-Path $path ([IO.Path]::ChangeExtension($MyInvocation.MyCommand.Name, "bdsgroup"))

# Bdsgroup template
$groupXml = [xml]@"
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
    <PersonalityInfo>
        <Option>
            <Option Name="Personality">Default.Personality</Option>
            <Option Name="ProjectType"></Option>
            <Option Name="Version">1.0</Option>
            <Option Name="GUID">{$([guid]::NewGuid().ToString())}</Option>
        </Option>
    </PersonalityInfo>
    <Default.Personality>
        <Projects>
            <Projects Name="Targets"></Projects>
        </Projects>
        <Dependencies/>
    </Default.Personality>
</BorlandProject>
"@

### Functions ###

function ShowUsage()
{
    $myName = Split-Path -Leaf $MyInvocation.ScriptName
    Write-Host "Usage:"
    Write-Host "`t$myName [-path <Path>] [-exclude <Exclude>] [-help]"
    Write-Host
    Write-Host "`t-path <Path>"
    Write-Host "`t`tSpecifies the directory to begin searching for *.bdsproj."
    Write-Host "`t`tPath:" $path
    Write-Host
    Write-Host "`t-exclude <Exclude>"
    Write-Host "`t`tSpecifies a directory to exclude from the search."
    Write-Host "`t`tExclude:" $exclude
    Write-Host
    Write-Host "`t-help"
    Write-Host "`t`tDisplays this message."
    Write-Host
    Write-Host "Output will be written to:"
    Write-Host "`t" $outfile
    Write-Host
    Write-Host "Limitations:"
    Write-Host "`tDoes not support multiple directories for Path or Exclude."
}

# Get the target name.
# e.g. "D:\dev\src\foo.bdsproj" returns "foo.exe"
function GetTarget($bdsproj)
{
    $mainSource = GetMainSource($bdsproj)
    $ext = GetTargetExt($mainSource)
    Split-Path -Leaf ([IO.Path]::ChangeExtension($mainSource, $ext))
}

# Get the relative project path.
# e.g. If path is "D:\dev" then "D:\dev\src\foo.bdsproj" returns "src\foo.bdsproj"
function GetProject($bdsproj)
{
    $prefixLen = $path.Length
    $suffixLen = $bdsproj.Length - $prefixLen
    $bdsproj.Substring($prefixLen, $suffixLen)
}

# Get the fully qualified MainSource (dpr/dpk) path.
# e.g. "D:\dev\src\foo.bdsproj" returns "D:\dev\src\foo.dpr"
function GetMainSource($bdsproj)
{
    $projXml = [xml](Get-Content $bdsproj)
    $mainSource = $projXml.BorlandProject."Delphi.Personality".Source.Source |
        Where-Object { $_.Name -eq "MainSource" }

    $result = Join-Path (Split-Path -Path $bdsproj) $mainSource.InnerText

    if (-not (Test-Path $result))
    {
        throw "No MainSource (dpr/dpk) found for $bdsproj"
    }

    $result
}

# Get the target extension depending on the source type.
function GetTargetExt($mainSource)
{
    $targets = @{"package"="pkg"; "library"="dll"; "program"="exe"}
    $targetType = GetTargetType($mainSource)
    $targets[$targetType]
}

# Read the target type out of the dpr.
function GetTargetType($mainSource)
{
    $name = [IO.Path]::GetFileNameWithoutExtension($mainSource)
    $pattern = "^\s*(package|library|program)\s+$name;$"
    $matches = (Select-String -Path $mainSource -Pattern $pattern)
    if ($matches -eq $null)
    {
        throw "Unknown target type (pkg/dll/exe) for $mainSource"
    }
    $matches.Matches[0].Groups[1].Value
}

# Add a project entry to groupXml.
# e.g. <Projects Name="foo.exe">src\foo.bdsproj</Projects>
function AddProject($target, $project)
{
    $node = $groupXml.CreateElement("Projects")
    $node.SetAttribute("Name", $target)
    $node.InnerText = $project
    $groupXml.BorlandProject."Default.Personality".Projects.AppendChild($node) | Out-Null

    $targets = $groupXml.BorlandProject."Default.Personality".Projects.Projects |
        Where-Object { $_.Name -eq "Targets" }
    $targets.InnerText = $targets.InnerText + " " + $target
}

### Main ###

if ($help)
{
    ShowUsage
}
else
{
    Get-ChildItem -Path $path -Include "*.bdsproj" -Recurse |
    Where-Object { $exclude -eq "" -or $_.FullName -notmatch $exclude } |
    ForEach-Object { AddProject (GetTarget $_.FullName) (GetProject $_.FullName) }

    $groupXml.OuterXml | Out-File -Encoding "UTF8" $outfile
}
like image 22
WileCau Avatar answered Nov 11 '22 01:11

WileCau


Maybe you could use a command line similar to your find (and maybe a little Delphi programm) to create a *.bdsgroup file with all projects and open that in D2007.

like image 2
Uli Gerhardt Avatar answered Nov 11 '22 00:11

Uli Gerhardt