' Gambas module file

Public Dir As String
Private Path As String
Public ChangeLog As String
Public Signature As String

Public Const ALL_TARGETS As String = "*"
'Public Const DEFAULT_GAMBAS_REPOSITORY As String = "http://ppa.launchpad.net/gambas-team/gambas3/ubuntu/"
Public Const DEFAULT_GAMBAS_REPOSITORY As String = "http://download.opensuse.org/repositories/home:/gambas:/stable/xUbuntu_${VERSION}/ /"

Private RPMBUILD_PROG As String
Private FAKEROOT_PROG As String
Private DPKG_PROG As String
Private TAR_1_13_PROG As String
Private AUTOCONF_PROG As String
Private AUTOMAKE_PROG As String
Private MAKEPKG_PROG As String
Private APPIMAGE_PROG As String

Private $sOutput As String
Private $bEnd As Boolean

Private $sName As String                ' Project name
Private $sVendor As String              ' Vendor
Private $sVendorPrefix As String        ' Vendor prefix
Private $sComponentName As String       ' Project name with a vendor prefix
Private $sLibraryName As String         ' Library name, with the version
Private $sUnsafePackageName As String   ' Package name, i.e project name with prefix, but with possible forbidden characters inside
Private $sCategories As String          ' Categories list
Private $sHome As String                ' Home user directory
Private $sVersion As String             ' Package version
Private $sVersionWithRelease As String  ' Package version with release number
Private $sDescription As String
Private $bDescription As Boolean

Private $sSupportPackage As String

Private MIN_VERSION As String
Private Const MAX_VERSION As String = "3.99.0"

Private $sFormatSingle As String
Private $sFormatMin As String
Private $sFormatMax As String
Private $sFormatMinMax As String
Private $sFormatEqual As String

Private Const QT4_SUPPORT As String = "qt4"
Private QT4_SUPPORT_PACKAGES As String[] = ["gb.qt4:gb.gui", "gb.qt4:gb.gui.qt", "gb.qt4.opengl:gb.gui.opengl", "gb.qt4.webkit:gb.gui.qt.webkit", "gb.qt4.webview:gb.gui.webview"]
Private Const QT5_SUPPORT As String = "qt5"
Private QT5_SUPPORT_PACKAGES As String[] = ["gb.qt5:gb.gui", "gb.qt5:gb.gui.qt", "gb.qt5.opengl:gb.gui.opengl", "gb.qt5.webkit:gb.gui.qt.webkit", "gb.qt5.webview:gb.gui.webview"]
Private Const QT6_SUPPORT As String = "qt6"
Private QT6_SUPPORT_PACKAGES As String[] = ["gb.qt6:gb.gui", "gb.qt6:gb.gui.qt", "gb.qt6.opengl:gb.gui.opengl", "gb.qt6.webkit:gb.gui.qt.webkit", "gb.qt6.webview:gb.gui.webview"]
Private Const GTK_SUPPORT As String = "gtk"
Private GTK_SUPPORT_PACKAGES As String[] = ["gb.gtk:gb.gui", "gb.gtk.opengl:gb.gui.opengl"]
Private Const GTK3_SUPPORT As String = "gtk3"
Private GTK3_SUPPORT_PACKAGES As String[] = ["gb.gtk3:gb.gui", "gb.gtk3.opengl:gb.gui.opengl", "gb.gtk3.webview:gb.gui.webview"] ', "gb.gtk.opengl:gb.gui.opengl"]

Private Const DEBIAN_STANDARD As String = "3.9.6"
Private Const DEBIAN_DEBHELPER_VERSION As String = "10"
Private DEBIAN_ICON_SIZES As Integer[] = [16, 22, 32, 48, 64, 128, 256, 512, 1024]

Private RUNTIME_COMPONENTS As String[] = ["gb.debug", "gb.draw", "gb.eval", "gb.geom", "gb.gui", "gb.gui.base", "gb.gui.opengl", "gb.gui.qt", "gb.gui.qt.opengl", "gb.gui.qt.webkit", "gb.gui.trayicon", "gb.gui.webview", "gb.hash", "gb.test"]

Private DATABASE_DRIVERS As String[] = [".sqlite3", ".mysql", ".odbc", ".postgresql"]

Private GUI_COMPONENTS_USING_WAYLAND As String[] = ["gb.qt5", "gb.qt6", "gb.gtk3", "gb.gui"]

Private GENERIC_GUI_COMPONENT As String[] = ["gb.gui", "gb.gui.opengl", "gb.gui.webview", "gb.gui.qt", "gb.gui.qt.ext", "gb.gui.qt.opengl", "gb.gui.qt.webkit"]
Private $sPassword As String

Private Sub CheckProgram(sProg As String) As String
  
  If Not Project.CheckProgram(sProg) Then Return sProg
  
End

Public Sub CheckPrograms()
  
  DPKG_PROG = CheckProgram("dh_install")
  RPMBUILD_PROG = CheckProgram("rpmbuild")
  FAKEROOT_PROG = CheckProgram("fakeroot")
  TAR_1_13_PROG = CheckProgram("tar-1.13")
  If Not TAR_1_13_PROG Then TAR_1_13_PROG = CheckProgram("tar")
  AUTOCONF_PROG = CheckProgram("autoconf")
  AUTOMAKE_PROG = CheckProgram("automake")
  MAKEPKG_PROG = CheckProgram("makepkg")
  'If Not Project.CheckProgram("makeself") Then MAKESELF_PROG = "makeself"
  APPIMAGE_PROG = CheckProgram("appimage-builder-x86_64.AppImage")
  If Not APPIMAGE_PROG Then APPIMAGE_PROG = CheckProgram("appimage-builder-x86_64")
  If Not APPIMAGE_PROG Then APPIMAGE_PROG = CheckProgram("appimage-builder")
  
End

Public Sub CheckSystem(sSys As String) As String
  
  Select Case sSys
  
    Case "mageia", "fedora", "suse"
      If Not RPMBUILD_PROG Then Return ("Cannot create Fedora, Mageia or SuSE packages.") & " " & Subst(("'&1' is missing."), "rpmbuild")
      
    Case "debian", "ubuntu"
      If Not DPKG_PROG Then Return ("Cannot create Debian or Ubuntu packages.") & " " & Subst(("'&1' is missing."), "debhelper")
      If Not FAKEROOT_PROG Then Return ("Cannot create Debian or Ubuntu packages.") & " " & Subst(("'&1' is missing."), "fakeroot")

    Case "slackware"
      If Not TAR_1_13_PROG Then Return ("Cannot create Slackware packages.") & " " & Subst(("'&1' is missing."), "tar-1.13")

    Case "autotools"
      If Not AUTOCONF_PROG And If Not AUTOMAKE_PROG Then Return ("Cannot create Autotools packages.") & " " & Subst(("'&1' and '&2' are missing."), "autoconf", "automake")
      If Not AUTOCONF_PROG Then Return ("Cannot create Autotools packages.") & " " & Subst(("'&1' is missing."), "autoconf")
      If Not AUTOMAKE_PROG Then Return ("Cannot create Autotools packages.") & " " & Subst(("'&1' is missing."), "automake")
      
    Case "archlinux"
      If Not MAKEPKG_PROG Then Return ("Cannot create ArchLinux packages.") & " " & Subst(("'&1' is missing."), "makepkg")
      If Not FAKEROOT_PROG Then Return ("Cannot create ArchLinux packages.") & " " & Subst(("'&1' is missing."), "fakeroot")
      
    'Case "self"
    '  If Not MAKESELF_PROG Then Return Subst(("'&1' is missing."), "makeself")
    
    Case "appimage"
      If Not APPIMAGE_PROG Then Return ("Cannot create AppImage.") & " " & Subst(("'&1' is missing."), "appimage-builder")
      If Not GetAppImageSystem() Then Return ("Cannot create AppImage.") & " " & (("'apt' or 'pacman' are missing."))
      If Project.Type <> Project.TYPE_NORMAL Then Return ("Cannot create an AppImage of a library or a component.")
      'If Project.Components.Exist("*.opengl*", gb.Like) Then Return ("AppImage does not support OpenGL.")

    Case Else
      Return
      
  End Select
  
End

Private Sub ClearLog()
  
  FMakeInstall.ClearLog
  
End

Private Sub AddLog(sText As String)

  FMakeInstall.AddLog(sText)

End

Private Sub RemoveEmptyLines(sText As String) As String
  
  Return Split(sText, "\n", "", True).Join("\n")
  
End

Private Sub GetShortDesc(sText As String, Optional iMax As Integer) As String

  Dim iPos As Integer
  
  iPos = InStr(sText, ". ")
  If iPos = 0 Then iPos = Len(sText) + 1
  sText = Trim(Replace(Left(sText, iPos), "\n", " "))
  
  If iMax And If Len(sText) > iMax Then
    sText = Left(sText, iMax - 3) & "..."
  Endif
  
  Return sText
  
End

Private Sub FormatDesc(sText As String, Optional iMax As Integer) As String[]

  Dim aLine As New String[]
  Dim iPos As Integer
  Dim I As Integer
  Dim sLine As String
  Dim sCar As String

  If iMax = 0 Then Return Split(sText, "\n")

  aLine.Add("")

  While sText
    
    sCar = String.Left(sText)
    sText = String.Mid$(sText, 2)
    
    If sCar = "\n" Then
      aLine.Add("")
      Continue
    Endif
    
    aLine[aLine.Max] &= sCar
    
    sLine = aLine[aLine.Max]
    If String.Len(sLine) > iMax Then
      For I = Len(sLine) - 1 DownTo 1
        iPos = InStr(" .,;", Mid$(sLine, I, 1))
        If iPos Then
          aLine[aLine.Max] = Left(sLine, I)
          aLine.Add(Mid$(sLine, I + 1))
          Break
        Endif
      Next
      If I = 0 Then
        aLine[aLine.Max] = String.Left(sLine, iMax)
        aLine.Add(String.Mid$(sLine, iMax + 1))
      Endif
    Endif
    
  Wend
  
  Return aLine
  
End



Private Sub GetVersion() As String

  Return Project.FormatVersion()
        
End  

Private Sub InitMake(sSys As String)
  
  Dim sCompatibleUntil As String
  
  If Project.CreateEachDirectory Then
    Path = Dir &/ sSys
    Try Mkdir Dir
    Try Mkdir Path
  Else 
    Path = Dir
    Try Mkdir Path
  Endif

  $sName = Project.Name
  $sComponentName = $sName
  $sVendor = Project.Vendor
  $sVendorPrefix = Project.VendorPrefix
  If Not $sVendorPrefix Then $sVendorPrefix = $sVendor

  If Project.Type = Project.TYPE_COMPONENT Then
    If $sVendorPrefix Then
      If $sName Not Begins $sVendorPrefix & "." Then $sComponentName = $sVendorPrefix & "." & $sName
    Endif
    $sComponentName = String.LCase($sComponentName)
  Else If Project.Type = Project.TYPE_LIBRARY Then
    $sLibraryName = $sName & ":" & Project.MajorVersion & "." & Project.MinorVersion
    sCompatibleUntil = Project.ReadComponentFile()["CompatibleUntil"]
    If sCompatibleUntil Then $sLibraryName &= "-" & sCompatibleUntil
  Endif

  '$sPrefix = GetPackagePrefix(Project.Vendor, Project.Prefix)
  $sUnsafePackageName = GetPackageFullName($sVendor, $sVendorPrefix, Project.Prefix, Project.PackageNameWithMajor, False)

  $sHome = System.User.Home

  $sCategories = Project.Categories[sSys]
  If $sCategories Then $sCategories &= ";"

  $sVersion = GetVersion()
  If sSys = "ubuntu" Then
    $sVersionWithRelease = $sVersion & "-0ubuntu" & CStr(Project.PackageVersion)
  Else
    $sVersionWithRelease = $sVersion & "-" & CStr(Project.PackageVersion)
  Endif
  
  $sDescription = RemoveEmptyLines(Project.Description)
  If $sDescription Then
    $bDescription = True
  Else
    $sDescription = "Missing description."
    $bDescription = False
  Endif

  With Project.Components
    If .Exist("gb.gui") Then
      $sSupportPackage = "gb.gui"
    Else If .Exist("gb.gui.qt") Then
      $sSupportPackage = "gb.gui.qt"
    Endif
  End With
  
  If sSys = "archlinux" Then MakeArchPackageInit()
  
End

Private Sub ExitMake(sSys As String)
  
  If sSys = "archlinux" Then MakeArchPackageExit()
  
End

Public Function Make() As Boolean

  Dim sSys As String
  Dim sMacro As String
  Dim bAdd As Boolean
  Dim sPath As String
  Dim aVer As String[]
  
  If Project.RuntimeVersion Then
    MIN_VERSION = Project.RuntimeVersion
  Else
    aVer = Split(System.FullVersion, ".")
    MIN_VERSION = aVer[0] & "." & aVer[1]
  Endif

  If Project.Systems.Exist("slackware") Or If Project.Systems.Exist("appimage") Then 
    If Project.MakeExecutable(True, True, False) Then Return True
  Endif  
  
  ' Save old rpm macro file
  sMacro = User.Home &/ ".rpmmacros"
  Try Move sMacro To sMacro & ".save"
  Try Kill sMacro

  ClearLog
  AddLog(("Saving CHANGELOG file."))
  sPath = Project.Dir &/ ".hidden" &/ "CHANGELOG"
  bAdd = Not Exist(sPath)
  'Try Mkdir Project.Dir &/ ".hidden"
  File.Save(sPath, ChangeLog)
  Project.RefreshKey(sPath)
  If bAdd Then VersionControl.AddFile(sPath)
  
  For Each sSys In Project.Systems
    If MakePackage(sSys) Then Return True
  Next

  ' Restore old rpm macro file
  Try Kill sMacro
  Try Move sMacro & ".save" To sMacro

  ' sPath = Project.Dir &/ ".extratest"
  ' bAdd = Not Exist(sPath)
  ' If Len(ExtraTest) > 0 Then
  '   AddLog(("Saving extra tests settings."))
  '   File.Save(sPath, ExtraTest)
  '   If bAdd Then VersionControl.AddFile(sPath)
  ' Else
  '   If Not bAdd Then VersionControl.RemoveFile(sPath)
  ' Endif
  
  AddLog("\n" & String(40, "=") & "\n")
  AddLog(("The packages have been successfully created.") & "\n")

End

Public Function GetChangeDate() As String

  Dim sLang As String
  Dim sDate As String

  sLang = System.Language
  System.Language = "C"
  sDate = Format$(Now, "ddd mmm dd yyyy") & " " & Project.Maintainer & " "
  If Project.Address Then sDate = sDate & "<" & Project.Address & "> "
  sDate &= GetVersion()
  System.Language = sLang
  Return sDate

End

Private Function IsConsoleProject() As Boolean

  Dim sLib As String
  Dim hComp As CComponent

  For Each sLib In Project.Components
    hComp = Project.Documentation[sLib]
    If hComp.IsForm() Then Return False
  Next

  Return True

End

Private Sub ComponentToPackageName(sComp As String) As String
      
  Return "gambas" & System.Version & "-" & Replace(sComp, ".", "-")

End

Private Sub IsRuntimeComponent(sComp As String) As Boolean
  
  Return RUNTIME_COMPONENTS.Exist(sComp)
  
End

Private Function GetDependencies(Optional aComp As String[]) As String
  
  Dim sRes As String
  Dim sComp As String
  Dim iPos As Integer
  Dim sTest As String
  
  If Not aComp Then 
    If Project.Type = Project.TYPE_COMPONENT Then
      aComp = Project.ReadComponentFile()["Require"]
    Else
      aComp = Project.Components
    Endif
  Endif
  
  If aComp Then
    For Each sComp In aComp
      
      iPos = InStr(sComp, ":")
      If iPos Then
        sTest = Mid$(sComp, iPos + 1)
        If Not Project.Components.Exist(sTest) Then Continue
        sComp = Left(sComp, iPos - 1)
      Endif
      
      If IsRuntimeComponent(sComp) Then Continue
      
      sRes &= GetDependency(sComp)
      'If sComp = "gb.form" Then sRes &= GetDependency("gb.form.stock")
    Next
  Endif
  
  For Each sComp In Project.Libraries
    sRes &= GetDependency(sComp)
  Next
  
  Return sRes
  
End

Private Function GetExtraDependencies(sSys As String) As String
  
  Dim sDep As String
  Dim aDep As String[]
  Dim sRes As String
  Dim sFormat As String
  
  If Project.SameDependencies Then sSys = ALL_TARGETS 'Project.Systems[0]
  
  'If Not sFormatMinMax Then sFormatMinMax = sFormatMin & sFormatMax
  
  For Each sDep In Split(Project.ExtraDependencies[sSys], "\n")
    
    aDep = Split(sDep, "\t")
    aDep.Resize(3)
    
    If aDep[1] And If aDep[2] Then
      If aDep[1] = aDep[2] Then
        sFormat = $sFormatEqual
      Else
        sFormat = $sFormatMinMax
      Endif
    Else If aDep[1] Then
      sFormat = $sFormatMin
    Else If aDep[2] Then
      sFormat = $sFormatMax
    Else
      sFormat = $sFormatSingle
    Endif
    
    sRes &= Subst(sFormat, aDep[0], aDep[1], aDep[2])
    
  Next
  
  Return sRes
  
End

Private Function GetExtraFiles(sSys As String, sFormat As String, Optional sFormatDir As String) As String
  
  Dim sFile As String
  Dim aFile As String[]
  Dim sRes As String
  Dim sFmt As String
  
  If Project.SameFiles Then sSys = ALL_TARGETS 'Project.Systems[0]
  
  For Each sFile In Split(Project.ExtraFiles[sSys], "\n")
    aFile = Split(sFile, "\t")
    aFile.Resize(2)
    
    sFmt = If(IsDir(Project.Dir &/ ".hidden" &/ aFile[0]), sFormatDir, sFormat)
    sRes &= Subst(sFmt, Shell$(aFile[0]), Shell$(aFile[1]), Shell$(Mid$(aFile[0], RInStr(aFile[0], "/") + 1))) & "\n"
    
  Next
  
  Return sRes
  
End

Private Sub FormatFileInList(sFile As String, Optional bDebian As Boolean) As String
  
  If InStr(sFile, " ") Then
    If bDebian Then
      sFile = Replace(sFile, " ", "[!#-~.\"!]")
    Else
      sFile = Chr$(34) & Replace(sFile, Chr$(34), "\\\"") & Chr$(34)
    Endif 
  Endif
  Return sFile
  
End


Private Function GetExtraFilesList(sSys As String, sPrefix As String, sFormat As String, Optional bDebian As Boolean) As String
  
  Dim sFile As String
  Dim aFile As String[]
  Dim sRes As String
  Dim sSrc, sDest, sDestDir As String
  
  If Project.SameFiles Then sSys = ALL_TARGETS 'Project.Systems[0]
  
  For Each sFile In Split(Project.ExtraFiles[sSys], "\n")
    aFile = Split(sFile, "\t")
    aFile.Resize(2)
    
    sSrc = FormatFileInList(sPrefix &/ aFile[0], bDebian)
    sDest = FormatFileInList(aFile[1] &/ File.Name(aFile[0]), bDebian)
    sDestDir = FormatFileInList(aFile[1], bDebian)
    sRes &= Subst(sFormat, sSrc, sDest, sDestDir) & "\n"
    
  Next
  
  Return sRes
  
End


Private Function CopyExtraFiles(sSys As String, sBuildDir As String)
  
  Dim sFile As String
  Dim aFile As String[]
  Dim sSrc As String
  Dim sDst As String
  
  If Project.SameFiles Then sSys = ALL_TARGETS 'Project.Systems[0]
  
  For Each sFile In Split(Project.ExtraFiles[sSys], "\n")
    aFile = Split(sFile, "\t")
    'aFile.Resize(2)
    sSrc = Project.Dir &/ ".hidden" &/ aFile[0]
    sDst = File.Dir(sBuildDir &/ aFile[1] &/ File.Name(aFile[0]))

    Project.MakeDir(sDst)
    If IsDir(sSrc) Then
      RunCommand("cp -R --preserve=timestamp " & Shell$(sSrc) & " " & Shell$(sDst))
    Else
      RunCommand("cp --preserve=timestamp " & Shell$(sSrc) & " " & Shell$(sDst))
    Endif
  Next
  
End

Private Function GetExtraFilesDir(sSys As String, sFormat As String, Optional bDebian As Boolean) As String
  
  Dim sFile As String
  Dim aFile As String[]
  Dim sRes As String
  
  If Project.SameFiles Then sSys = ALL_TARGETS 'Project.Systems[0]
  
  For Each sFile In Split(Project.ExtraFiles[sSys], "\n")
    
    aFile = Split(sFile, "\t")
    aFile.Resize(2)
    
    If bDebian Then
      sRes &= Subst(sFormat, aFile[1]) & "\n"
    Else
      sRes &= Subst(sFormat, Shell$(aFile[1])) & "\n"
    Endif
    
  Next
  
  Return sRes
  
End

Private Function GetDependency(sLib As String) As String
        
  Dim hLibrary As CLibraryInfo
  Dim sVersion As String
  Dim aMinVersion As String[]
  Dim aMaxVersion As String[]
  Dim sPackageName As String
  
  If Left(sLib) = "/" Or If Left(sLib) = ":" Then
    
    ' The package name dependency must not include the version!
    
    hLibrary = CLibraryInfo[sLib]
    sPackageName = hLibrary.GetDependencyName()
    sVersion = hLibrary.Version
    
    aMinVersion = Split(sVersion, ".")
    If aMinVersion[1] = "0" Then
      If aMinVersion[0] <> "0" Then
        aMinVersion[0] = CStr(CInt(aMinVersion[0]) - 1)
        aMinVersion[1] = "90"
      Endif
    Else
      aMinVersion[1] = CStr(CInt(aMinVersion[1]) - 1)
    Endif
    aMinVersion.Resize(3)
    aMinVersion[2] = "0"
    
    If hLibrary.CompatibleUntil Then
      aMaxVersion = Split(hLibrary.CompatibleUntil, ".")
    Else
      aMaxVersion = Split(sVersion, ".")
      aMaxVersion.Resize(3)
      aMaxVersion[2] = "90"
    Endif
    
  ' Else If Left(sLib) = ":" Then
  '     
  '   sLib = File.Name(sLib)
  '   iPos = RInStr(sLib, ":")
  '   sVersion = Mid$(sLib, iPos + 1)
  '   sLib = Left(sLib, iPos - 1)
  '     
  '   sPackageName = ComponentToPackageName(sLib)
  '   
  '   aMinVersion = Split(sVersion, ".")
  '   aMaxVersion = Split(sVersion, ".")
    
  Else
    
    sPackageName = ComponentToPackageName(sLib)
    
    aMinVersion = Split(MIN_VERSION, ".")
    aMaxVersion = Split(MAX_VERSION, ".")
    
  Endif
       
  Return Subst($sFormatMinMax, sPackageName, aMinVersion.Join("."), aMaxVersion.Join("."))

End

Private Sub PrintOnlyShowIn(cLine As Collection, sCategories As String)
  
  Dim aCat As String[] = Split(sCategories, ";", "", True)
  Dim sCat As String
  Dim aOnly As New String[]
  
  If aCat.Exist("Screensaver") Or If aCat.Exist("TrayIcon") Or If aCat.Exist("Applet") Or If aCat.Exist("Shell") Then
  
    For Each sCat In aCat
      If sCat = "KDE" Or If sCat = "GNOME" Or If sCat = "ROX" Or If sCat = "XFCE" Then
        aOnly.Add(sCat)
      Endif
    Next
    
    If aOnly.Count Then cLine["ShowOnlyIn"] = aOnly.Join(";") & ";"
    
  Endif
  
End

Private Sub MakeOneLine(sStr As String) As String

  Dim iLen As Integer
  
  sStr = Replace(sStr, "\r", "")
  sStr = Replace(sStr, "\n", " ")
  sStr = Replace(sStr, "\t", " ")
  
  Repeat
    iLen = Len(sStr)
    sStr = Replace(sStr, "  ", " ")
  Until Len(sStr) = iLen
  
  Return Trim(sStr)

End

Private Sub PrintTranslatedDesktopEntry(cLine As Collection, sEntry As String, sText As String)

  Dim sLang As String
  Dim sTrans As String
  
  cLine[sEntry] = MakeOneLine(sText)
  
  For Each sLang In Project.GetTranslations()
    sTrans = CTranslation.FindTranslation(MyLanguage.GetPath(sLang, "po"), sText)
    If sTrans Then cLine[sEntry & "[" & sLang & "]"] = MakeOneLine(sTrans)
  Next

End

Private Sub PrintDesktopFile(hFile As File, sExec As String, sIcon As String, Optional sExtraCat As String)

  Dim cLine As New Collection
  Dim sExtra As String
  Dim iPos As Integer
    
  Print #hFile, "[Desktop Entry]"
  Print #hFile, "Version=1.0"

  If Project.Title Then
    PrintTranslatedDesktopEntry(cLine, "Name", Project.Title)
  Else
    PrintTranslatedDesktopEntry(cLine, "Name", Project.Name)
  Endif

  If $bDescription Then PrintTranslatedDesktopEntry(cLine, "Comment", Project.Description)
  
  cLine["Exec"] = sExec
  cLine["Icon"] = sIcon
  cLine["Terminal"] = IIf(IsConsoleProject(), "true", "false")
  cLine["Type"] = "Application"
  cLine["StartupNotify"] = "true"
  cLine["Categories"] = sExtraCat & $sCategories
  If Project.MimeTypes.Count Then cLine["MimeType"] = Project.MimeTypes.Join(";")
  PrintOnlyShowIn(cLine, $sCategories)
  
  If Trim(Project.ExtraDesktop) Then
    For Each sExtra In Split(Project.ExtraDesktop, "\n")
      sExtra = Trim(sExtra)
      If Not sExtra Then Continue
      If InStr("#;=", Left(sExtra)) Then Continue
      iPos = InStr(sExtra, "=")
      cLine[RTrim(Left(sExtra, iPos - 1))] = LTrim(Mid$(sExtra, iPos + 1))
    Next
  Endif
  
  For Each sExtra In ["Name", "Comment", "Exec", "Icon", "Terminal", "Type", "StartupNotify", "Categories", "MimeType", "ShowOnlyIn"]
    If cLine[sExtra] Then
      Print #hFile, sExtra; "="; cLine[sExtra]
      cLine.Remove(sExtra)
    Endif
  Next
  
  For Each sExtra In cLine
    Print #hFile, cLine.Key; "="; sExtra
  Next
  
End


Private Sub RunCommand(sCmd As String, Optional sDir As String, Optional bIgnoreStderr As Boolean)

  Dim aCmd As New String[]
  Dim hProcess As Process
  
  $sOutput = ""
  $bEnd = False
  If sDir Then
    AddLog("cd " & Shell$(sDir))
    aCmd.Push("cd " & SConv(Shell$(sDir)))
  Endif
  AddLog(sCmd)
  aCmd.Push(sCmd)
  If bIgnoreStderr = False Then aCmd.Last &= " 2>&1"
  hProcess = Shell aCmd.Join(" && ") With VersionControl.LANG_ENV For Input Output As "Process"
  If sCmd Begins "sudo " Then hProcess.Expect("password*:")
  Repeat
    Sleep 0.05
    Wait
  Until $bEnd
  
End

Private Sub MakeSupportPackage(sSys As String)

  Dim sSupport As String
  Dim aPackage As String[]
  Dim sMsg As String
  
  'slackware doesn't use support packages
  If sSys = "slackware" Then Return
  If sSys = "appimage" Then Return
  
  If $sSupportPackage = "gb.gui" Then
  
    sSupport = GTK_SUPPORT
    aPackage = GTK_SUPPORT_PACKAGES
    sMsg = Subst(("Making &1 support package..."), "GTK+")
    AddLog("\n============ " & sMsg)
    FMakeInstall.ShowMessage(sMsg)
    GoSub MAKE_PACKAGE
  
    If Not Project.Components.Exist("gb.gui.opengl") Then
      sSupport = GTK3_SUPPORT
      aPackage = GTK3_SUPPORT_PACKAGES
      sMsg = Subst(("Making &1 support package..."), "GTK+3")
      AddLog("\n============ " & sMsg)
      FMakeInstall.ShowMessage(sMsg)
      GoSub MAKE_PACKAGE
    Endif
    
  Endif

  sSupport = QT4_SUPPORT
  aPackage = QT4_SUPPORT_PACKAGES
  sMsg = Subst(("Making &1 support package..."), "QT4")
  AddLog("\n============ " & sMsg)
  FMakeInstall.ShowMessage(sMsg)
  GoSub MAKE_PACKAGE

  sSupport = QT5_SUPPORT
  aPackage = QT5_SUPPORT_PACKAGES
  sMsg = Subst(("Making &1 support package..."), "QT5")
  AddLog("\n============ " & sMsg)
  FMakeInstall.ShowMessage(sMsg)
  GoSub MAKE_PACKAGE
  
  sSupport = QT6_SUPPORT
  aPackage = QT6_SUPPORT_PACKAGES
  sMsg = Subst(("Making &1 support package..."), "QT5")
  AddLog("\n============ " & sMsg)
  FMakeInstall.ShowMessage(sMsg)
  GoSub MAKE_PACKAGE
  
  Return
  
MAKE_PACKAGE:
  
  Select Case sSys
  
    Case "mageia", "fedora", "suse"
      MakeRpmSupportPackage(sSys, sSupport, aPackage)
  
    Case "debian", "ubuntu"
      MakeDebSupportPackage(sSys, sSupport, aPackage)
      
    Case "slackware"
      'we shouldn't get here, but if we do, do nothing as not needed for slackware
      'MakeTgzSupportPackage(sSys, sSupport, aPackage)
   
    Case "archlinux"
      MakeArchSupportPackage(sSys, sSupport, aPackage)
      
    Default
      
  End Select
  
  Return
  
End


Private Function MakePackage(sSys As String) As Boolean

  Dim sErr As String
  Dim sMsg As String
  
  Inc Application.Busy
  
  AddLog("\n" & String(78, "=") & "\n")
  sMsg = Subst(("Creating package for &1."), FMakeInstall.GetSystemName(sSys))
  AddLog(String.UCase(sMsg))
  FMakeInstall.ShowMessage(sMsg)
  AddLog("\n")

  InitMake(sSys)
  
  Select Case sSys
  
    Case "mageia", "fedora", "suse"
      MakeRpmPackage(sSys)
  
    Case "debian", "ubuntu"
      MakeDebPackage(sSys)
      
    Case "slackware"
      MakeSlackwarePackage(sSys)
   
    Case "autotools"
      MakeAutotoolsPackage(sSys)
       
    Case "archlinux"
      MakeArchPackage(sSys)
      
    Case "appimage"
      MakeAppImagePackage(sSys)

    Default
      Return True
    
  End Select
  
  If $sSupportPackage Then MakeSupportPackage(sSys)
  
  ExitMake(sSys)
  
  Dec Application.Busy
  
Catch

  sErr = Error.Text
  AddLog("\n" & ("The package build has failed.") & "\n" & Error.Where & ": " & sErr)
  FMakeInstall.ShowError("<b>" & ("The package build has failed.") & "</b><br>" & sErr)
  Application.Busy = 0
  Return True

End

Private Sub GetDebianBuildPackageCommand() As String

  Dim sCmd As String

  sCmd = "dpkg-buildpackage -d -rfakeroot"
  If Project.PackageSignature Then
    sCmd &= " -k" & Shell(Project.Address)
  Else
    sCmd &= " -uc -us"
  Endif
  Return sCmd

End

' From Debian Policy Manual:
' Package names (both source and binary, see Package, Section 5.6.7) must consist only of lower case letters (a-z), digits (0-9), plus (+) and minus (-) signs, and periods (.). 
' They must be at least two characters long And must start With an alphanumeric character.


Private Sub FormatDebPackageName(sName As String) As String

  Dim I As Integer
  Dim sCar As String
  Dim sRes As String

  For I = 1 To Len(sName)
    sCar = Mid$(sName, I, 1)
    If Not IsLetter(sCar) And If Not IsDigit(sCar) And If InStr("+-", sCar) = 0 Then sCar = "-"
    sRes &= sCar
  Next
  
  Return sRes

End

Private Function MakeDebPackage(sSys As String)

  Dim hFile As File
  Dim sCmd As String
  Dim sIcon As String
  Dim sIconDir As String
  Dim sArch As String
  Dim sPackageName As String
  Dim sPackagePath As String
  Dim sLine As String
  Dim hImageStat As ImageStat
  Dim iSize As Integer
  Dim sPath As String
  Dim W As Integer
  Dim H As Integer
  Dim sExec As String
      
  $sFormatSingle = ", &1"
  $sFormatMin = ", &1 (>= &2)"
  $sFormatMax = ", &1 (<< &3)"
  $sFormatMinMax = $sFormatMin & $sFormatMax
  $sFormatEqual = $sFormatMinMax
  
  sPackageName = FormatDebPackageName($sUnsafePackageName)
  
  '$sName = Replace$($sName, "_", "-")

  ' Step 1. Create the build directory

  AddLog(("Making build directory.")) 

  RunCommand("rm -f " & Shell(Path &/ Subst("&1_&2", sPackageName, $sVersion)) & "*")

  sPackagePath = Path &/ Subst("&1-&2", sPackageName, $sVersion)
  RunCommand("rm -Rf " & Shell$(sPackagePath))
  RunCommand("rm -Rf " & Shell$(sPackagePath & ".orig"))

  Mkdir sPackagePath
  Mkdir sPackagePath &/ "src"
  Mkdir sPackagePath &/ "debian"
  
  Mkdir sPackagePath &/ "debian/source"
  File.Save(sPackagePath &/ "debian/source/format", "1.0")

  sArch = sPackagePath &/ "src/raw.tar.gz"
  
  ' Create icons
    
  sIconDir = Project.Dir &/ ".hidden/.icons"
  Try Shell.RmDir(sIconDir)
  Shell.MkDir(sIconDir)
  
  sIcon = sPackageName
  
  Project.StretchIcon(Project.Dir &/ Project.Icon, 32).Save(sIconDir &/ sIcon & ".png")
  
  Try hImageStat = ImageStat(Project.Dir &/ Project.Icon)
  If Error Then
    W = 32
    H = 32
  Else
    W = hImageStat.Width
    H = hImageStat.Height
  Endif
  
  For Each iSize In DEBIAN_ICON_SIZES
    If W >= iSize And If H >= iSize Then
      Mkdir sIconDir &/ CStr(iSize)
      Project.StretchIcon(Project.Dir &/ Project.Icon, iSize).Save(sIconDir &/ CStr(iSize) &/ sIcon & ".png")
    Endif
  Next
  
  Project.MakeSourcePackageTo(sArch)
  
  ' Remove the icon dir from the project now it has been archived
  Shell.RmDir(sIconDir)
  
  sCmd = "cd " & Shell$(sPackagePath &/ "src") & "; tar xzf raw.tar.gz >/dev/null" 
  Shell sCmd Wait 
  
  ' Rename the source archive project directory to the package name
  'TRY MOVE Path &/ (sPrefix & Subst("&1", Project.Name)) TO sPackagePath
  Try Kill sArch
  Try Shell "cp -Rf " & Shell(sPackagePath) & " " & Shell(sPackagePath & ".orig") Wait


  ' Step 2. Make the desktop file
  If Project.Type = Project.TYPE_NORMAL Then
    AddLog(("Creating desktop file..."))
    hFile = Open sPackagePath &/ "debian/" & sPackageName & ".desktop" For Create
    PrintDesktopFile(hFile, $sName, sIcon)
    Close #hFile
  Endif 
  
  'Step 3. Create debianization needed files: control, rules
  'debian/copyright
  AddLog(("Sources are being debianizated."))
  hFile = Open sPackagePath &/ "debian/copyright" For Create 
  Print #hFile, "This package was debianized by " & Project.Maintainer & " <" & Project.Address & "> on"
  Print #hFile, Format$(Date, "ddd, dd mmm yyyy hh:nn:ss") & "+0000"
  Print #hFile
  Print #hFile, "Copyright Holder: " & Project.Maintainer & " <" & Project.Address & ">"
  Print #hFile
  Print #hFile, "License:"
  Print #hFile
  Print #hFile, If(Project.License, Project.License, "GNU General Public License") 
  Print #hFile
  Print #hFile, "Created by: "; Project.Authors
  Close #hFile
  
  'debian/changelog
  hFile = Open sPackagePath &/ "debian/changelog" For Create 
  Print #hFile, ChangelogToDebChangelog(sPackageName)
  Close #hFile

  'debian/compat
  hFile = Open sPackagePath &/ "debian/compat" For Create 
  Print #hFile, DEBIAN_DEBHELPER_VERSION
  Close #hFile
    
  'debian/menu
  If Project.Type = Project.TYPE_NORMAL Then
    hFile = Open sPackagePath &/ "debian/menu" For Create 
    Print #hFile, "?package("; sPackageName; "):needs=\""; IIf(IsConsoleProject(), "text", "X11"); "\" section=\""; Project.Menus[sSys]; "\"\\"
    Print #hFile, "title=\""; IIf(Project.Title, Project.Title, Project.Name); "\"\\" 
    Print #hFile, "command=\"/usr/bin/"; $sName; "\"\\"
    Print #hFile, "icon=\"/usr/share/pixmaps/"; sIcon; ".png\""
    Close #hFile
  Endif 
  
  'debian/dirs
  hFile = Open sPackagePath &/ "debian/dirs" For Create
  Select Case Project.Type
    Case Project.TYPE_COMPONENT 
      Print #hFile, "usr/share/gambas"; System.Version; "/info"
      Print #hFile, "usr/lib/gambas"; System.Version 
      If Exist(Project.Dir &/ ".hidden/control") Then Print #hFile, "usr/share/gambas" & System.Version & "/control/" & $sComponentName
    Case Project.TYPE_LIBRARY
      Print #hFile, "usr/lib/gambas"; System.Version; "/"; LCase($sVendor)
    Case Project.TYPE_NORMAL
      Print #hFile, "usr/bin"
      Print #hFile, "usr/share/applications"
      Print #hFile, "usr/share/pixmaps"
      For Each iSize In DEBIAN_ICON_SIZES
        Print #hFile, "usr/share/icons/hicolor/"; iSize; "x"; iSize; "/apps"
      Next
  End Select
  Print #hFile, GetExtraFilesDir(sSys, "&1", True)
  Close #hFile
  
  'debian/install
  hFile = Open sPackagePath &/ "debian/install" For Create
  
  Select Case Project.Type
    
    Case Project.TYPE_COMPONENT
      
      Print #hFile, "src/"; $sName; "/"; $sComponentName; ".gambas usr/lib/gambas" & System.Version
      If Exist(Project.Dir &/ ".hidden/control") Then Print #hFile, "src/"; $sName; "/.hidden/control/*.png usr/share/gambas" & System.Version &/ "control" &/ $sComponentName
      
    Case Project.TYPE_LIBRARY
      
      Print #hFile, "src/"; $sName; "/"; $sLibraryName; ".gambas usr/lib/gambas" & System.Version; "/"; LCase($sVendor)
      
    Case Project.TYPE_NORMAL
    
      Print #hFile, "src/"; $sName; "/"; $sName; " usr/bin"
      Print #hFile, "debian/"; sPackageName; ".desktop usr/share/applications"

      Print #hFile, "src/"; $sName; "/.hidden/.icons/"; sIcon; ".png usr/share/pixmaps"
      For Each iSize In DEBIAN_ICON_SIZES
        sPath = "src" &/ $sName &/ ".hidden/.icons" &/ CStr(iSize) &/ sIcon & ".png"
        If Exist(sPackagePath &/ sPath) Then Print #hFile, sPath; " /usr/share/icons/hicolor/"; iSize; "x"; iSize; "/apps"
      Next

  End Select
  
  Print #hFile, GetExtraFilesList(sSys, "src/" & $sName & "/.hidden", "&1 &3", True)
  
  Close #hFile  
 
  'debian/control
  hFile = Open sPackagePath &/ "debian/control" For Create
  Print #hFile, "Source: "; sPackageName
  Print #hFile, "Section: contrib/"; Project.Groups[sSys]
  Print #hFile, "Priority: optional"
  Print #hFile, "Maintainer: "; Project.Maintainer; " <"; Project.Address; ">"
  Print #hFile, "Build-Depends: debhelper (>= "; DEBIAN_DEBHELPER_VERSION; "), gambas"; System.Version; "-dev (>= "; MIN_VERSION; "), gambas"; System.Version; "-dev (<< "; MAX_VERSION; ")";
  Print #hFile, GetDependencies();
  Print #hFile, GetExtraDependencies(sSys);
  Print #hFile

  Print #hFile, "Standards-Version: "; DEBIAN_STANDARD
  Print #hFile
  Print #hFile, "Package: "; sPackageName
  Print #hFile, "Architecture: all"
  Print #hFile, "Depends: gambas"; System.Version; "-runtime (>= "; MIN_VERSION; "), gambas"; System.Version; "-runtime (<< "; MAX_VERSION; ")";
  
  Print #hFile, GetDependencies();
  Print #hFile, GetExtraDependencies(sSys);
  Print #hFile

  Print #hFile, GetShortDesc("Description: " & $sDescription, 80)
  ' If Project.Title Then 
  '   Print #hFile, Project.Title
  ' Else 
  '   Print #hFile, Project.Name
  ' Endif 
  
  For Each sLine In FormatDesc($sDescription, 80)
    Print #hFile, " "; sLine
  Next

  Select Case Project.Type
    Case Project.TYPE_NORMAL
      Print #hFile, " This program is written in Gambas."
    Case Project.TYPE_LIBRARY
      Print #hFile, " This is a Gambas library."
    Case Project.TYPE_COMPONENT
      Print #hFile, " This is a Gambas component written in Gambas."
  End Select
  
  Close #hFile
  
  'debian/rules
  hFile = Open sPackagePath &/ "debian/rules" For Create
  Output To #hFile
  Print "#!/usr/bin/make -f"
  Print "build: build-stamp"
  Print "build-stamp:"
  Print "\tdh_testdir"
  Print "\ttouch build-stamp"
  Print "\t"; Project.GetCompileCommand(True, Not Project.KeepDebugInfo, True, False) & " src" &/ $sName
  Print "\tgba"; System.Version; " -o ";
  
  Select Case Project.Type
    Case Project.TYPE_COMPONENT
      sExec = "src" &/ $sName &/ $sComponentName & ".gambas"
    Case Project.TYPE_LIBRARY
      sExec = "src" &/ $sName &/ $sLibraryName & ".gambas"
    Case Project.TYPE_NORMAL
      sExec = "src" &/ $sName &/ $sName
  End Select
  Print Shell(sExec); " src" &/ $sName
  
  ' If Project.Type = Project.TYPE_COMPONENT 
  '   If $sName <> $sComponentName Then
  '     Print "\tmv "; Shell$("src" &/ $sName &/ $sName & ".gambas"); " "; Shell$("src" &/ $sName &/ $sComponentName & ".gambas")
  '   Endif
  ' Else If Project.Type = Project.TYPE_LIBRARY Then
  '   Print "\tmv "; Shell$("src" &/ $sName &/ $sName & ".gambas"); " "; Shell$("src" &/ $sName &/ $sLibraryName & ".gambas")
  ' Endif
  
  Print 
  Print "clean:"
  Print "\tdh_testdir"
  Print "\tdh_testroot"
  Print "\trm -Rf "; Shell("src" &/ $sName &/ ".gambas")  
  Print "\trm -f "; Shell(sExec)
  Print "\trm -f build-stamp install-stamp"
  Print "\tdh_clean"
  Print
  Print "install: build"
  Print "\tdh_testdir"
  Print "\tdh_testroot"
  Print "\tdh_prep"
  Print "\tdh_installdirs" 
  If Project.Type = Project.TYPE_NORMAL Then
    If $sName <> sPackageName Then Print "\tln -s " & Shell$($sName) & " \"$(CURDIR)\"/debian" &/ sPackageName &/ "/usr/bin" &/ Shell$(sPackageName)
  Else If Project.Type = Project.TYPE_COMPONENT Then 
    Print "\tcp src" &/ $sName & "/.component \"$(CURDIR)\"/debian/" & sPackageName & "/usr/lib/gambas" & System.Version & "/" & Shell$($sComponentName) & ".component"
    Print "\tcp src" &/ $sName & "/.info \"$(CURDIR)\"/debian/" & sPackageName & "/usr/share/gambas" & System.Version & "/info/" & Shell$($sComponentName) & ".info " ""
    Print "\tcp src" &/ $sName & "/.list \"$(CURDIR)\"/debian/" & sPackageName & "/usr/share/gambas" & System.Version & "/info/" & Shell$($sComponentName) & ".list"
  Endif 
  Print "\ttouch install-stamp"
  Print 
  Print "binary-arch: build install"
  Print "\tdh_testdir"
  Print 
  Print "binary-indep: build install"
  Print "\tdh_testdir -i"
  Print "\tdh_testroot -i"
  Print "\tdh_installdocs -i"
  Print "\tdh_installchangelogs -i"
  Print "\tdh_install -i"
  Print "\tdh_installmenu"
  Print "\tdh_compress -i"
  Print "\tdh_fixperms -i"
  Print "\tdh_installdeb -i"
  Print "\tdh_gencontrol -i"
  Print "\tdh_md5sums -i"
  Print "\tdh_builddeb -i"
  Print 
  Print "binary: binary-indep binary-arch"
  Print ".PHONY: build clean binary-indep binary-arch binary install"
  Output To Default
  Close #hFile
  Try Shell "chmod +x " & Shell(sPackagePath &/ "debian/rules") Wait

  ' Step 4. Build package

  AddLog(("Creating package..."))
  'sCmd = "cd " & Shell$(sPackagePath) & "; fakeroot dpkg-buildpackage -d"
  'sCmd = "fakeroot dpkg-buildpackage -d"
  
  RunCommand(GetDebianBuildPackageCommand(), sPackagePath)
  
  If Process.LastValue > 2 Then Error.Raise(("'dpkg-buildpackage' has failed."))

  'Try Shell "rm -rf " & Shell$(sPackagePath) Wait
  Shell.RmDir(sPackagePath)
  Try Shell "rm -f " & Shell$(Path) &/ "*.dsc.asc" Wait 

End

Private Function MakeDebSupportPackage(sSys As String, sSupport As String, aComp As String[])

  Dim hFile As File
  Dim sPackageName As String
  Dim sPackagePath As String
  Dim sDesc As String
  Dim sLine As String
  Dim sRelease As String
      
  $sFormatSingle = ", &1"
  $sFormatMin = ", &1 (>= &2)"
  $sFormatMax = ", &1 (<< &3)"
  $sFormatMinMax = $sFormatMin & $sFormatMax
  $sFormatEqual = $sFormatMin & Replace($sFormatMax, "<<", "<=")
  
  sPackageName = FormatDebPackageName($sUnsafePackageName) & "-" & sSupport
  
  sRelease = CStr(Project.PackageVersion)
  
  ' Step 1. Create the build directory

  AddLog(("Making build directory.")) 
  sPackagePath = Path &/ Subst("&1-&2", sPackageName, $sVersion)
  
  'Try Shell "rm -Rf " & Shell$(sPackagePath) Wait
  Shell.RmDir(sPackagePath)
  Mkdir sPackagePath
  Mkdir sPackagePath &/ "debian"

  'Step 3. Create debianization needed files: control, rules
  'debian/copyright
  AddLog(("Sources are being debianizated."))
  hFile = Open sPackagePath &/ "debian/copyright" For Create 
  Print #hFile, "This package was debianized by " & Project.Maintainer & " <" & Project.Address & "> on"
  Print #hFile, Format$(Date, "ddd, dd mmm yyyy hh:nn:ss") & "+0000"
  Print #hFile
  Print #hFile, "Copyright Holder: " & Project.Maintainer & " <" & Project.Address & ">"
  Print #hFile
  Print #hFile, "License:"
  Print #hFile
  Print #hFile, If(Project.License, Project.License, "GNU General Public License") 
  Close #hFile
  
  'debian/changelog
  hFile = Open sPackagePath &/ "debian/changelog" For Create 
  Print #hFile, ChangelogToDebChangelog(sPackageName)
  Close #hFile

  'debian/compat
  hFile = Open sPackagePath &/ "debian/compat" For Create 
  Print #hFile, DEBIAN_DEBHELPER_VERSION
  Close #hFile
    
  'debian/control
  hFile = Open sPackagePath &/ "debian/control" For Create
  Print #hFile, "Source: "; sPackageName
  Print #hFile, "Section: contrib/"; Project.Groups[sSys]
  Print #hFile, "Priority: optional"
  Print #hFile, "Maintainer: "; Project.Maintainer; " <"; Project.Address; ">"
  Print #hFile, "Build-Depends: debhelper (>= "; DEBIAN_DEBHELPER_VERSION; ")"
  Print #hFile, "Standards-Version: "; DEBIAN_STANDARD
  Print #hFile
  Print #hFile, "Package: "; sPackageName
  Print #hFile, "Architecture: all"
  Print #hFile, "Depends: "; FormatDebPackageName($sUnsafePackageName);; "(>=";; $sVersionWithRelease;; "), "; FormatDebPackageName($sUnsafePackageName);; "(<=";; $sVersionWithRelease; ")"; GetDependencies(aComp)
  
  sDesc = sSupport & " package for " & If(Project.Title, Project.Title, Project.Name)
  
  Print #hFile, GetShortDesc("Description: " & sDesc, 80)
  
  sDesc = "This is the dummy " & sDesc
  
  For Each sLine In FormatDesc(sDesc)
    Print #hFile, " "; sLine
  Next
  
  
  ' debian/rules
  hFile = Open sPackagePath &/ "debian/rules" For Create
  Output To #hFile
  Print "#!/usr/bin/make -f"
  Print
  Print "build build-arch build-indep:"
  Print
  Print "clean:"
  Print "\tdh_testdir"
  Print "\tdh_clean"
  Print
  Print "install: build"
  Print "\tdh_testdir"
  Print "\tdh_testroot"
  Print "\tdh_prep"
  Print
  Print "binary-arch: install"
  Print
  Print "binary-indep: install"
  Print "\tdh_testdir"
  Print "\tdh_testroot"
  Print "\tdh_install"
  Print "\tdh_installdocs"
  Print "\tdh_installchangelogs"
  Print "\tdh_compress"
  Print "\tdh_fixperms"
  Print "\tdh_installdeb"
  Print "\tdh_gencontrol"
  Print "\tdh_md5sums"
  Print "\tdh_builddeb"
  Print
  Print "binary: binary-indep binary-arch"
  Print ".PHONY: build clean binary-indep binary-arch binary install"
  Print
  Output To Default
  Close #hFile
  Try Shell "chmod +x " & Shell(sPackagePath &/ "debian/rules") Wait

  ' Step 4. Build package

  AddLog(("Creating package..."))
  RunCommand(GetDebianBuildPackageCommand(), sPackagePath)
  
  If Process.LastValue > 2 Then Error.Raise(("'dpkg-buildpackage' has failed."))

  'Try Shell "rm -Rf " & Shell$(sPackagePath) Wait
  Shell.RmDir(sPackagePath)
  Try Shell "rm -f " & Shell$(Path) &/ "*.dsc.asc" Wait 

End

Private Sub ChangelogToDebChangelog(sPackageName As String) As String
 
  Dim aLine As String[]
  Dim sLine As String
  Dim sDebChangeLog As String
  Dim sDate As String
  Dim sPreviousLine As String
  Dim sWord As String
  Dim sNextWord As String
  Dim aWord As String[]
  Dim aDate As String[]
  
  aLine = Split(ChangeLog, "\n")  
  
  For Each sLine In aLine
    
    If sLine Begins "*" Then 
      
      If sDate <> "" Then
        'Debian packages don't accept an empty changelog line for the release:
        If sPreviousLine = sPackageName & " (" & $sVersionWithRelease & ") unstable; urgency=low" & "\n\n" Then 
          sDebChangeLog = sDebChangeLog & "  * New release version\n"
        Endif   
        sDebChangeLog = sDebChangeLog & "\n -- " & Project.Maintainer & " <" & Project.Address & ">  " & sDate & "\n\n"
      Endif
      
      sLine = Trim(Mid$(sLine, 2))
      aDate = Split(sLine, " ")
      
      If aDate.Count < 4 Then Goto BAD_DATE
      If Len(aDate[0]) < 3 Or If Not IsLetter(aDate[0]) Then Goto BAD_DATE
      If Len(aDate[1]) < 3 Or If Not IsLetter(aDate[1]) Then Goto BAD_DATE
      If Not IsDigit(aDate[2]) Or If CInt(aDate[2]) < 1 Or If CInt(aDate[2]) > 31 Then Goto BAD_DATE
      If Not IsDigit(aDate[3]) Or If CInt(aDate[3]) < 1970 Or If CInt(aDate[3]) > 9999 Then Goto BAD_DATE
      
      sDate = aDate[0] & ", " & aDate[2] & " " & aDate[1] & " " & aDate[3] & " 12:00:00 +0000"
      
      'sVersion = GetDebVersion()
      sPreviousLine = sPackageName & " (" & $sVersionWithRelease & ") unstable; urgency=low" & "\n\n"
      sDebChangeLog &= sPreviousLine
    
    Else 
      
      If Trim$(sLine) <> "" Then
        
        aWord = Split(Right$(sLine, -2), " ")
        sPreviousLine = "  * "
        sLine = ""
        For Each sWord In aWord
          Repeat
            If String.Len(sWord) > 76 Then
              sNextWord = String.Mid$(sWord, 77)
              sWord = String.Left(sWord, 76)
            Else
              sNextWord = ""
            Endif
            If String.Len(sLine & sWord) > 76 Then
              sPreviousLine &= sLine & "\n    "
              sLine = sWord
            Else
              sLine = LTrim(sLine & " " & sWord)
            Endif
            sWord = sNextWord
          Until Not sWord
        Next
        If sLine Then sPreviousLine &= sLine & "\n"
        
        sDebChangeLog &= sPreviousLine
        
      Endif
      
    Endif   
    
  Next 
  
  sDebChangeLog &= "\n -- " & Project.Maintainer & " <" & Project.Address & ">  " & sDate & "\n"
  
  Return sDebChangeLog 
  
BAD_DATE:

  Error.Raise(Subst(("Incorrect date in ChangeLog: &1"), sLine))

End

Private Sub FormatRpmPackageName(sName As String) As String

  Dim I As Integer
  Dim sCar As String
  Dim sRes As String
  Dim iLen As Integer

  For I = 1 To Len(sName)
    sCar = Mid$(sName, I, 1)
    If Not IsLetter(sCar) And If Not IsDigit(sCar) Then sCar = "-"
    sRes &= sCar
  Next
  
  Do
    iLen = Len(sRes)
    sRes = Replace(sRes, "--", "-")
    If Len(sRes) = iLen Then Break
  Loop
  
  Return sRes

End

Private Function MakeRpmPackage(sSys As String)

  Dim sSrc As String
  Dim sDir As String
  Dim sCmd As String
  Dim hFile As File
  Dim sArch As String
  Dim sOutput As String
  Dim sLang As String
  Dim sPackage As String
  Dim sIcon As String
  Dim sDistribution As String
  Dim sVendor As String
  Dim sRelease As String
  Dim sPackageName As String

  $sFormatSingle = ",&1"
  $sFormatMin = ",&1 >= &2"
  $sFormatMax = ",&1 < &3"
  $sFormatMinMax = $sFormatMin & $sFormatMax
  $sFormatEqual = $sFormatMin & Replace($sFormatMax, "<", "<=")
  
  sPackageName = FormatRpmPackageName($sUnsafePackageName)

  sRelease = CStr(Project.PackageVersion)
  
  Select Case sSys

    Case "mageia"
      sDistribution = "Mageia"
      sVendor = "Mageia"
      sRelease &= ".mga"

    Case "fedora"
      sDistribution = "Fedora"
      sVendor = "Fedora"
      sRelease &= ".fdr"

    Case "suse"
      sDistribution = "openSUSE"
      sVendor = "SUSE"
      sRelease &= ".suse"

  End Select
  
    ' step 1, set up RPM dirs and macros if they're not there already

  AddLog(("Initializing ~/RPM directory."))

  For Each sCmd In ["RPM/", "RPM/BUILD/", "RPM/RPMS/", "RPM/SOURCES/", "RPM/SPECS/", "RPM/SRPMS/", "RPM/tmp/"]
    Try Mkdir $sHome &/ sCmd
  Next

  hFile = Open $sHome &/ ".rpmmacros" For Create
  Print #hFile, "%_topdir " & $sHome &/ "RPM"
  Print #hFile, "%_tmppath " & $sHome &/ "RPM/tmp"
    'PRINT #hFile, "%_signature gpg"
    'PRINT #hFile, "%_gpg_name Mandrivalinux"
    'PRINT #hFile, "%_gpg_path ~/.gnupg"
  Print #hFile, "%packager "; Project.Maintainer & "<" & SConv(Project.Address) & ">"
  Print #hFile, "%buildhost "; System.Host
  Print #hFile, "%distribution "; sDistribution
  Print #hFile, "%vendor "; If($sVendor, $sVendor, sVendor)
  Close #hFile

    ' step 2, write source tarball (with bzip) to SOURCES dir

  AddLog(("Creating source package."))

  sSrc = $sHome &/ "RPM/SOURCES"

  sDir = Project.Dir &/ ".icon"
  'Shell "rm -rf " & Shell$(sDir) Wait
  Shell.RmDir(sDir)
  Try Mkdir sDir

    ' IF Project.Icon THEN
    '   hIcon = Image.Load(Project.Dir &/ Project.Icon)
    ' ELSE
    '   hIcon = Image.Load("img/32/gambas.png")
    ' ENDIF

  Project.StretchIcon(Project.Dir &/ Project.Icon, 16).Save(sDir &/ "16.png")
  Project.StretchIcon(Project.Dir &/ Project.Icon, 32).Save(sDir &/ "32.png")
  Project.StretchIcon(Project.Dir &/ Project.Icon, 48).Save(sDir &/ "48.png")
  Project.StretchIcon(Project.Dir &/ Project.Icon, 64).Save(sDir &/ "64.png")

  sArch = sSrc &/ Subst("&1-&2.tar.bz2", sPackageName, $sVersion)
  Project.MakeSourcePackageTo(sArch)

  'Shell "rm -rf " & Shell$(sDir) Wait
  Shell.RmDir(sDir)

  AddLog(("Creating .spec file."))

  hFile = Open $sHome &/ "RPM/SPECS" &/ sPackageName & ".spec" For Create

  Print #hFile, "%define name " & sPackageName
  Print #hFile, "%define version " & $sVersion
  Print #hFile, "%define release "; sRelease

  Print #hFile
  Print #hFile, "Summary: " & IIf(Project.Title, Project.Title, Project.Name)
  Print #hFile, "Name: %{name}"
  Print #hFile, "Version: %{version}"
  Print #hFile, "Release: %{release}"
  Print #hFile, "Source0: %{name}-%{version}.tar.bz2"
  Print #hFile, "License: "; If(Project.License, Project.License, "GPL")
  Print #hFile, "Group: " & Project.Groups[sSys]
  Print #hFile, "BuildRoot: %{_tmppath}/%{name}-%{version}-${release}-buildroot"
  If sSys <> "mageia" Then
    Print #hFile, "Prefix: %{_prefix}"
  Endif
    'PRINT #hFile, "BuildRequires: gambas2-ide"
  Print #hFile, "BuildArch: noarch"

  Print #hFile, "Requires: gambas"; System.Version; "-runtime >= "; MIN_VERSION; ",gambas"; System.Version; "-runtime < "; MAX_VERSION;

  Print #hFile, GetDependencies();
  Print #hFile, GetExtraDependencies(sSys);

  Print #hFile

  Print #hFile, "AutoReqProv: no"

  Print #hFile, "\n%description\n" & $sDescription & "\nThis program is written in Gambas, so you will need Gambas to be installed."

    Print #hFile, "\n%prep"
  If sSys <> "mageia" Then
    Print #hFile, "rm -rf %{buildroot}"
  Endif

  Print #hFile, "%setup -q -n " & Shell$($sName)

  If Project.Type = Project.TYPE_COMPONENT Then

    ' Components must be installed in Gambas prefix, which is not known at package creation time.
    ' How can we do that? Hardcode installation path according to the distribution?

    Print #hFile, "\n%build"
    Print #hFile, Project.GetCompileCommand(True, Not Project.KeepDebugInfo, True, False) & "\ngba"; System.Version
     
    Print #hFile, "\n%install"
    Print #hFile, GetExtraFilesDir(sSys, "install -d %{buildroot}/&1")
    Print #hFile, GetExtraFiles(sSys, "install -p .hidden/&1 %{buildroot}/&2/&1", "cp -R --preserve=timestamp .hidden/&1 %{buildroot}/&2/&1")
    Print #hFile, "install -d %{buildroot}/%{_libdir}/gambas"; System.Version
    Print #hFile, "install -p "; Shell$($sName); ".gambas %{buildroot}/%{_libdir}/gambas" & System.Version; "/"; Shell$($sComponentName); ".gambas"
    Print #hFile, "install -p .component %{buildroot}/%{_libdir}/gambas"; System.Version; "/"; Shell$($sComponentName); ".component"

    Print #hFile, "install -d %{buildroot}/%{_datadir}/gambas"; System.Version; "/info"
    Print #hFile, "install -p .info %{buildroot}/%{_datadir}/gambas"; System.Version; "/info/"; Shell$($sComponentName); ".info"
    Print #hFile, "install -p .list %{buildroot}/%{_datadir}/gambas"; System.Version; "/info/"; Shell$($sComponentName); ".list"

    If Exist(Project.Dir &/ ".hidden/control") Then 
      Print #hFile, "install -d %{buildroot}/%{_datadir}/gambas"; System.Version; "/control/"; Shell$($sComponentName)
      Print #hFile, "install -p "; ".hidden/control/*.png %{buildroot}/%{_datadir}/gambas" & System.Version &/ "control" &/ Shell$($sComponentName)
    Endif

  Else 
  
    Print #hFile, "\n%build"
    Print #hFile, Project.GetCompileCommand(True, Not Project.KeepDebugInfo, True, False) & "\ngba"; System.Version
  
    Print #hFile, "\n%install"
  
    If Project.Type = Project.TYPE_NORMAL Then
      Print #hFile, "install -Dp "; Shell$($sName); ".gambas %{buildroot}/%{_bindir}" &/ Shell$($sName)
    Else If Project.Type = Project.TYPE_LIBRARY Then
      Print #hFile, "install -d %{buildroot}/%{_libdir}/gambas"; System.Version; "/"; LCase($sVendor)
      Print #hFile, "install -p "; Shell$($sName); ".gambas %{buildroot}/%{_libdir}/gambas"; System.Version; "/"; LCase($sVendor); "/"; Shell$($sLibraryName & ".gambas")
    Endif
    
    Print #hFile, GetExtraFilesDir(sSys, "install -d %{buildroot}/&1")
    Print #hFile, GetExtraFiles(sSys, "install -p .hidden/&1 %{buildroot}/&2/&1", "cp -R --preserve=timestamp .hidden/&1 %{buildroot}/&2/&1")
    
    If Project.Type = Project.TYPE_NORMAL
    
      sIcon = $sName & ".png"
    
      ' NOTE: There are explicit references to /usr/share.
      '       I must find a way to use the rpm macros instead.
    
      Select Case sSys
    
        Case "mageia"
    
          Print #hFile, "install -Dp .icon/16.png %{buildroot}/%{_datadir}/icons/hicolor/16x16/apps" &/ Shell$(sIcon)
          Print #hFile, "install -Dp .icon/32.png %{buildroot}/%{_datadir}/icons/hicolor/32x32/apps" &/ Shell$(sIcon)
          Print #hFile, "install -Dp .icon/48.png %{buildroot}/%{_datadir}/icons/hicolor/48x48/apps" &/ Shell$(sIcon)
          Print #hFile, "install -Dp .icon/64.png %{buildroot}/%{_datadir}/icons/hicolor/64x64/apps" &/ Shell$(sIcon)
          
          If $sName <> sPackageName Then Print #hFile, "ln -s " & Shell$($sName) & " \"%{buildroot}/%{_bindir}\"/" & Shell$(sPackageName)
  
          Print #hFile, "install -d %{buildroot}/%{_datadir}/applications"
          Print #hFile, "cat << EOF > %{buildroot}/%{_datadir}/applications/%{name}.desktop"
        
          PrintDesktopFile(hFile, $sName, $sName) ', "X-MandrivaLinux-" & Replace(Replace(Project.Menus[sSys], " ", ""), "/", "-") & ";")
        
          Print #hFile, "EOF"
    
        Case "fedora"
    
          Print #hFile, "install -d %{buildroot}/%{_datadir}/pixmaps"
          Print #hFile, "install -d %{buildroot}/%{_datadir}/applications"
          Print #hFile, "install -p .icon/48.png %{buildroot}/%{_datadir}/pixmaps" &/ Shell$(sIcon)
          
          If $sName <> sPackageName Then Print #hFile, "ln -s " & Shell$($sName) & " \"%{buildroot}/%{_bindir}\"/" & Shell$(sPackageName)
    
          Print #hFile, "cat << EOF > %{buildroot}%{_datadir}/applications/%{name}.desktop"
          
          PrintDesktopFile(hFile, $sName, sIcon, "X-RedHat-Extra;")
          
          Print #hFile, "EOF"
    
        Case "suse"
    
          Print #hFile, "install -d %{buildroot}/%{_datadir}/pixmaps"
          Print #hFile, "install -d %{buildroot}/%{_datadir}/applications"
          Print #hFile, "install -p .icon/48.png %{buildroot}/%{_datadir}/pixmaps" &/ Shell$(sIcon)
          
          If $sName <> sPackageName Then Print #hFile, "ln -s " & Shell$($sName) & " \"%{buildroot}/%{_bindir}\"/" & Shell$(sPackageName)
    
          Print #hFile, "cat << EOF > %{buildroot}%{_datadir}/applications/%{name}.desktop"
          
          PrintDesktopFile(hFile, $sName, sIcon)
          
          Print #hFile, "EOF"
          
      End Select
      
    Endif
    
  Endif

  If sSys <> "mageia" Then

    Print #hFile, "\n%clean"
    Print #hFile, "rm -rf %{buildroot}"
    
  Endif
  
    Print #hFile, "\n%files"
    
  If sSys <> "mageia" Then
    
    Print #hFile, "%defattr(-,root,root)"

  Endif
  
  If Project.Type = Project.TYPE_COMPONENT Then
  
    Print #hFile, FormatFileInList("%{_libdir}/gambas" & System.Version & "/" & $sComponentName & ".gambas")
    Print #hfile, FormatFileInList("%{_libdir}/gambas" & System.Version & "/" & $sComponentName & ".component")
    
    Print #hFile, FormatFileInList("%{_datadir}/gambas" & System.Version & "/info/" & $sComponentName & ".info")
    Print #hFile, FormatFileInList("%{_datadir}/gambas" & System.Version & "/info/" & $sComponentName & ".list")

    If Exist(Project.Dir &/ ".hidden/control") Then 
      Print #hFile, FormatFileInList("%{_datadir}/gambas" & System.Version & "/control/" & $sComponentName & "/*.png")
    Endif
    Print #hFile, GetExtraFilesList(sSys, "", "&2");

  Else
  
    If Project.Type = Project.TYPE_NORMAL Then
      Print #hFile, FormatFileInList("%{_bindir}" &/ $sName)
      Print #hFile, FormatFileInList("%{_bindir}" &/ sPackageName)
    Else If Project.Type = Project.TYPE_LIBRARY Then
      Print #hFile, FormatFileInList("%{_libdir}/gambas" & System.Version &/ LCase($sVendor) &/ $sLibraryName & ".gambas")
    Endif
    
    Print #hFile, GetExtraFilesList(sSys, "", "&2");
  
    If Project.Type = Project.TYPE_NORMAL Then
      
      Select Case sSys
    
        Case "mageia"
    
          Print #hFile, FormatFileInList("%{_datadir}/icons/hicolor/*/apps" &/ sIcon)
                'PRINT #hFile, "/%{_menudir}" &/ sName
          Print #hFile, "%{_datadir}/applications/%{name}.desktop"
        
        Case "fedora"
    
          Print #hFile, FormatFileInList("%{_datadir}/pixmaps" &/ sIcon)
          Print #hFile, "%{_datadir}/applications/%{name}.desktop"
    
        Case "suse"
    
          Print #hFile, FormatFileInList("%{_datadir}/pixmaps" &/ sIcon)
          Print #hFile, "%{_datadir}/applications/%{name}.desktop"
    
      End Select
      
    Endif
    
  Endif

  Print #hFile, "\n%changelog\n"
  Print #hFile, ChangeLog

  Close #hFile

    ' and step 4.... build that sucker.

  AddLog(("Creating package...") & "\n")

  sLang = System.Language
  System.Language = "C"

  sCmd = RPMBUILD_PROG & " -ba " & Shell$($sHome &/ "RPM/SPECS" &/ sPackageName & ".spec")
  AddLog(sCmd)

    'sTemp = Temp$
  $sOutput = ""
  $bEnd = False
  Shell sCmd & " 2>&1" Wait For Read As "Process" 'TO sOutput
    ' REPEAT
    '   SLEEP 0.01
    '   WAIT
    ' UNTIL $bEnd
  
  AddLog("")
  
  sOutput = Replace($sOutput, "\r", "")
  Try sOutput = DConv(sOutput)

  Try Kill $sHome &/ ".rpmmacros"

  System.Language = sLang

  If Process.LastValue Then Error.Raise(("'rpmbuild' has returned the following error code:") & " " & Process.LastValue)

  For Each sCmd In Split(sOutput, "\n")
    If Left(sCmd, 6) = "Wrote:" And Right$(sCmd, 10) = "noarch.rpm" Then

      sPackage = Subst("&1-&2-&3.noarch.rpm", sPackageName, $sVersion, sRelease)
            ' IF sSys = "debian" THEN
            '   SHELL "cd " & Shell$(sHome &/ "RPM/RPMS/noarch") & "; fakeroot " & ALIEN_PROG & " --to-deb -k " & Shell$(sPackage) WAIT
            '   sPackage = sPrefix & Subst("&1_&2.&3-&4_all.deb", LCase(Project.Name), Project.MajorVersion, Project.MinorVersion, sRelease)
            '   IF NOT Exist(sHome &/ "RPM/RPMS/noarch" &/ sPackage) THEN Error.Raise("alien command has failed")
            ' ENDIF
      MoveFile($sHome &/ "RPM/RPMS/noarch" &/ sPackage, Path &/ sPackage)
      AddLog(sPackage)

      sPackage = Subst("&1-&2-&3.src.rpm", sPackageName, $sVersion, sRelease)
            ' IF sSys = "debian" THEN
            '   SHELL "cd " & Shell$(sHome &/ "RPM/SRPMS") & "; fakeroot alien --to-deb -k " & Shell$(sPackage) WAIT
            '   sPackage = sPrefix & Subst("&1_&2.&3-&4_all.deb", LCase(Project.Name), Project.MajorVersion, Project.MinorVersion, sRelease)
            '   IF NOT Exist(sHome &/ "RPM/SRPMS" &/ sPackage) THEN Error.Raise("alien command has failed")
            '   MoveFile(sHome &/ "RPM/SRPMS" &/ sPackage, Path &/ File.BaseName(sPackage) & ".src.deb")
            ' ELSE
      MoveFile($sHome &/ "RPM/SRPMS" &/ sPackage, Path &/ sPackage)
      AddLog(sPackage)
            ' ENDIF

    End If
  Next

End

Private Function MakeRpmSupportPackage(sSys As String, sSupport As String, aComp As String[])

  Dim sCmd As String
  Dim hFile As File
  Dim sOutput As String
  Dim sLang As String
  Dim sPackage As String
  Dim sDistribution As String
  Dim sVendor As String
  Dim sRelease As String
  Dim sPackageName As String
  Dim sDependency As String

  $sFormatSingle = ",&1"
  $sFormatMin = ",&1 >= &2"
  $sFormatMax = ",&1 < &3"
  $sFormatMinMax = $sFormatMin & $sFormatMax
  $sFormatEqual = $sFormatMinMax
  
  sPackageName = FormatRpmPackageName($sUnsafePackageName) & "-" & sSupport
  
  sRelease = CStr(Project.PackageVersion)

  Select Case sSys

    Case "mageia"
      sDistribution = "Mageia"
      sVendor = "Mageia"
      sRelease &= ".mga"

    Case "fedora"
      sDistribution = "Fedora"
      sVendor = "Fedora"
      sRelease &= ".fdr"

    Case "suse"
      sDistribution = "openSUSE"
      sVendor = "SUSE"
      sRelease &= ".suse"

  End Select
  
    ' step 1, set up RPM dirs and macros if they're not there already

  AddLog(("Initializing ~/RPM directory."))

  For Each sCmd In ["RPM/", "RPM/BUILD/", "RPM/RPMS/", "RPM/SOURCES/", "RPM/SPECS/", "RPM/SRPMS/", "RPM/tmp/"]
    Try Mkdir $sHome &/ sCmd
  Next

  hFile = Open $sHome &/ ".rpmmacros" For Create
  Print #hFile, "%_topdir " & $sHome &/ "RPM"
  Print #hFile, "%_tmppath " & $sHome &/ "RPM/tmp"
    'PRINT #hFile, "%_signature gpg"
    'PRINT #hFile, "%_gpg_name Mandrivalinux"
    'PRINT #hFile, "%_gpg_path ~/.gnupg"
  Print #hFile, "%packager "; Project.Maintainer & "<" & SConv(Project.Address) & ">"
  Print #hFile, "%buildhost "; System.Host
  Print #hFile, "%distribution "; sDistribution
  Print #hFile, "%vendor "; If($sVendor, $sVendor, sVendor)
  Close #hFile

    ' step 2, write source tarball (with bzip) to SOURCES dir

  AddLog(("Creating .spec file."))

  hFile = Open $sHome &/ "RPM/SPECS" &/ sPackageName & ".spec" For Create

  Print #hFile, "%define name " & sPackageName
  Print #hFile, "%define version " & $sVersion
  Print #hFile, "%define release "; sRelease
  
  Print #hFile
  Print #hFile, "Summary: "; sSupport; " support for "; IIf(Project.Title, Project.Title, Project.Name)
  Print #hFile, "Name: %{name}"
  Print #hFile, "Version: %{version}"
  Print #hFile, "Release: %{release}"
  'Print #hFile, "Source0: " '"%{name}-%{version}.tar.bz2"
  Print #hFile, "License: "; If(Project.License, Project.License, "GPL")
  Print #hFile, "Group: " & Project.Groups[sSys]
  'Print #hFile, "BuildRoot: %{_tmppath}/%{name}-%{version}-${release}-buildroot"
  If sSys <> "mageia" Then
    Print #hFile, "Prefix: %{_prefix}"
  Endif
    'PRINT #hFile, "BuildRequires: gambas2-ide"
  Print #hFile, "BuildArch: noarch"

  sDependency = $sVersion & "-" & sRelease

  Print #hFile, "Requires: "; FormatRpmPackageName($sUnsafePackageName);; ">=";; sDependency;; ","; FormatRpmPackageName($sUnsafePackageName);; "<=";; sDependency; GetDependencies(aComp)

  Print #hFile

  Print #hFile, "AutoReqProv: no"

  Print #hFile, "\n%description\n"; "This is the "; sSupport; " support for "; Project.Name

  Print #hFile, "\n%files"
  If sSys <> "mageia" Then
    Print #hFile, "%defattr(-,root,root)"
  Endif

  Print #hFile, "\n%changelog\n"
  Print #hFile, ChangeLog

  Close #hFile

    ' and step 4.... build that sucker.

  AddLog(("Creating package...") & "\n")

  sLang = System.Language
  System.Language = "C"

  sCmd = RPMBUILD_PROG & " -ba " & Shell$($sHome &/ "RPM/SPECS" &/ sPackageName & ".spec")
  AddLog(sCmd)

    'sTemp = Temp$
  $sOutput = ""
  $bEnd = False
  Shell sCmd & " 2>&1" Wait For Read As "Process" 'TO sOutput
    ' REPEAT
    '   SLEEP 0.01
    '   WAIT
    ' UNTIL $bEnd
  
  AddLog("")
  
  sOutput = Replace($sOutput, "\r", "")
  Try sOutput = DConv(sOutput)

  Try Kill $sHome &/ ".rpmmacros"

  System.Language = sLang

  If Process.LastValue Then Error.Raise(("'rpmbuild' has returned the following error code:") & " " & Process.LastValue)

  For Each sCmd In Split(sOutput, "\n")
    If Left(sCmd, 6) = "Wrote:" And Right$(sCmd, 10) = "noarch.rpm" Then

      sPackage = Subst("&1-&2-&3.noarch.rpm", sPackageName, $sVersion, sRelease)
            ' IF sSys = "debian" THEN
            '   SHELL "cd " & Shell$(sHome &/ "RPM/RPMS/noarch") & "; fakeroot " & ALIEN_PROG & " --to-deb -k " & Shell$(sPackage) WAIT
            '   sPackage = sPrefix & Subst("&1_&2.&3-&4_all.deb", LCase(Project.Name), Project.MajorVersion, Project.MinorVersion, sRelease)
            '   IF NOT Exist(sHome &/ "RPM/RPMS/noarch" &/ sPackage) THEN Error.Raise("alien command has failed")
            ' ENDIF
      MoveFile($sHome &/ "RPM/RPMS/noarch" &/ sPackage, Path &/ sPackage)
      AddLog(sPackage)

      sPackage = Subst("&1-&2-&3.src.rpm", sPackageName, $sVersion, sRelease)
            ' IF sSys = "debian" THEN
            '   SHELL "cd " & Shell$(sHome &/ "RPM/SRPMS") & "; fakeroot alien --to-deb -k " & Shell$(sPackage) WAIT
            '   sPackage = sPrefix & Subst("&1_&2.&3-&4_all.deb", LCase(Project.Name), Project.MajorVersion, Project.MinorVersion, sRelease)
            '   IF NOT Exist(sHome &/ "RPM/SRPMS" &/ sPackage) THEN Error.Raise("alien command has failed")
            '   MoveFile(sHome &/ "RPM/SRPMS" &/ sPackage, Path &/ File.BaseName(sPackage) & ".src.deb")
            ' ELSE
      MoveFile($sHome &/ "RPM/SRPMS" &/ sPackage, Path &/ sPackage)
      AddLog(sPackage)
            ' ENDIF

    End If
  Next

End

Private Sub PrintSlackDescRuler(hFile As File, sPackageName As String)
  
  Dim sLine As String
  
  sLine = Space(Len(sPackageName)) & "|-----handy-ruler" & String$(76, "-")
  sLine = Left(sLine, 75) & "|"
  Print #hFile, sLine
  
End

Private Sub PrintSlackDesc(hFile As File, sLine As String, sPackageName As String)
  
  sLine = sPackageName & ": " & sLine
  sLine = Left(sLine, 76)
  Print #hFile, sLine
  
End


Private Sub PrintSlackDescContents(hFile As File, sData As String, nLine As Integer, sPackageName As String)

  Dim sLine As String
  Dim iPos As Integer
    
  While nLine
    If sData Then
      If Len(sData) > (76 - Len(sPackageName) - 2) Then
        sLine = Left(sData, 76 - Len(sPackageName) - 2)
        iPos = RInStr(sLine, " ")
        If iPos Then sLine = RTrim(Left(sLine, iPos - 1))
        sData = LTrim(Mid$(sData, Len(sLine) + 1))
      Else
        sLine = sData
        sData = ""
      Endif
    Else
      sLine = ""
    Endif
    PrintSlackDesc(hFile, sLine, sPackageName)
    Dec nLine
  Wend
  
End

Private Sub FormatTgzPackageName(sName As String) As String

 ' Use the same format as RPM at the moment
  Return FormatRpmPackageName(sName)

End

Private Sub MakeSlackwarePackage(sSys As String)

  Dim sDistribution As String
  Dim sVendor As String
  Dim sBuildDir As String
  Dim hFile As File
  'Dim sPrefix As String
  Dim sCmd As String
  Dim sIcon As String
  Dim sData As String
  Dim sTempPackage As String
  Dim sPackage As String
  Dim sFile As String 
  Dim sPackageName As String
      
  $sFormatSingle = "&1\n"
  $sFormatMin = "&1 >= &2\n"
  $sFormatMax = "&1 < &3\n"
  $sFormatMinMax = $sFormatMin & $sFormatMax
  $sFormatEqual = $sFormatMinMax

  sPackageName = FormatTgzPackageName($sUnsafePackageName)
  sDistribution = "Slackware"
  sVendor = "Slackware"
  
  ' 1. Create the temporary build directory

  AddLog(("Making build directory."))

  sBuildDir = File.SetExt(Temp$("slackware"), "")
  'Shell "rm -rf " & Shell(sBuildDir) Wait
  Shell.RmDir(sBuildDir)
  Mkdir sBuildDir

  Select Case Project.Type

    Case Project.TYPE_COMPONENT 
  
      For Each sCmd In ["/usr", "/usr/lib", "/usr/lib/gambas" & System.Version, "/usr/share", "/usr/share/gambas" & System.Version, "/usr/share/gambas" & System.Version & "/info", "/install"]
        Try Mkdir sBuildDir &/ sCmd
      Next
      
    Case Project.TYPE_LIBRARY
      
      For Each sCmd In ["/usr", "/usr/lib", "/usr/lib/gambas" & System.Version, "/usr/lib/gambas" & System.Version &/ LCase($sVendor), "/install"]
        Try Mkdir sBuildDir &/ sCmd
      Next
      
    Case Project.TYPE_NORMAL

      For Each sCmd In ["/usr", "/usr/bin", "/usr/share", "/usr/share/applications", "/usr/share/pixmaps", "/install"]
        Try Mkdir sBuildDir &/ sCmd
      Next
  
  End Select
  
  CopyExtraFiles(sSys, sBuildDir)
  
  If Project.Type = Project.TYPE_COMPONENT Then 
  
    ' 2. Copy the library, the information files and the controls
  
    Copy Project.GetExecPath() To sBuildDir &/ "/usr/lib/gambas" & System.Version &/ $sComponentName & ".gambas"
    Copy Project.Dir &/ ".component" To sBuildDir &/ "/usr/lib/gambas" & System.Version &/ $sComponentName & ".component"
    Copy Project.Dir &/ ".info" To sBuildDir &/ "/usr/share/gambas" & System.Version &/ "info/" & $sComponentName & ".info"
    Copy Project.Dir &/ ".list" To sBuildDir &/ "/usr/share/gambas" & System.Version &/ "info/" & $sComponentName & ".list"
  
    If Exist(Project.Dir &/ ".hidden/control") Then 
      Try Mkdir sBuildDir &/ "/usr/share/gambas" & System.Version & "/control"
      Try Mkdir sBuildDir &/ "/usr/share/gambas" & System.Version & "/control/" & $sComponentName
      For Each sFile In Dir(Project.Dir &/ ".hidden/control", "*.png") 
        Copy Project.Dir &/ ".hidden/control" &/ sFile To sBuildDir &/ "/usr/share/gambas" & System.Version & "/control/" & $sComponentName &/ sFile
      Next
    Endif
  
  Else

    ' 2. Copy the executable
  
    'COPY Project.Dir &/ Project.Name & ".gambas" TO sBuildDir &/ "/usr/bin" &/ Project.Name
    
    If Project.Type = Project.TYPE_NORMAL Then
      Copy Project.GetExecPath() To sBuildDir &/ "/usr/bin" &/ $sName
      Chmod sBuildDir &/ "/usr/bin" &/ $sName To "..x..x..x"
      If $sName <> sPackageName Then Link $sName To sBuildDir &/ "/usr/bin" &/ sPackageName
    Else If Project.Type = Project.TYPE_LIBRARY Then
      Copy Project.GetExecPath() To sBuildDir &/ "/usr/lib/gambas" & System.Version &/ LCase($sVendor) &/ $sLibraryName & ".gambas"
      Chmod sBuildDir &/ "/usr/lib/gambas" & System.Version &/ LCase($sVendor) &/ $sLibraryName & ".gambas" To "..x..x..x"
    Endif
      
    If Project.Type = Project.TYPE_NORMAL Then
      
      ' 3. Copy the icon
    
      ' IF Project.Icon THEN
      '   hIcon = Image.Load(Project.Dir &/ Project.Icon)
      ' ELSE
      '   hIcon = Image.Load("img/gambas.png")
      ' ENDIF
    
      Project.StretchIcon(Project.Dir &/ Project.Icon, 48).Save(sBuildDir &/ "/usr/share/pixmaps" &/ Project.Name & ".png")
    
      ' 4. Make the desktop file
      
      sIcon = Shell$($sName) & ".png"
    
      hFile = Open sBuildDir &/ "/usr/share/applications/" & sPackageName & ".desktop" For Create
    
      PrintDesktopFile(hFile, $sName, "/usr/share/pixmaps/" & $sName & ".png")
    
      Close #hFile
      ' if we are creating a project with desktop icon/menu we need to run a doinst.sh in the package
      ' to make sure the menu item appears without needing a restart of xwindows.
      hFile = Open sBuildDir &/ "install" &/ "doinst.sh" For Create
      Print #hFile, "if [ -x /usr/bin/update-desktop-database ]; then"
      Print #hfile, "  /usr/bin/update-desktop-database -q usr/share/applications >/dev/null 2>&1"
      Print #hFile, "fi"
      Close #hFile
       
            
    Endif
  
  Endif
  
  ' 5. Description file

  hFile = Open sBuildDir &/ "/install/slack-desc" For Create
  
  Print #hFile, File.Load("install/slack-desc-header");    
  PrintSlackDescRuler(hFile, sPackageName)
  PrintSlackDesc(hFile, Subst("&1 &2: &3", sPackageName, $sVersion, If(Project.Title, Project.Title, Project.Name)), sPackageName)
  PrintSlackDesc(hFile, "", sPackageName)
  sData = Replace($sDescription, "\n", " ")
  PrintSlackDescContents(hFile, sData, 7, sPackageName)
  PrintSlackDesc(hFile, "Package created by: " & Project.Maintainer, sPackageName)
  PrintSlackDesc(hFile, "EMail address: " & Project.Address, sPackageName)

  Close #hFile
  
  ' 6. Dependencies. only used by slapt-get. other tools, like installpkg don't use it.
  ' gambas is packaged a a single package - gambas3 including everything.
  
  hFile = Open sBuildDir &/ "/install/slack-required" For Create
  
  Print #hFile, "gambas"; System.Version; " >= "; MIN_VERSION
  Print #hFile, "gambas"; System.Version; " < "; MAX_VERSION

  Print #hFile, GetDependencies();
  Print #hFile, GetExtraDependencies(sSys);
  
  Close #hFile
  
  ' 7. Create package
  
  AddLog(("Creating package...") & "\n")

  sTempPackage = File.SetExt(Temp$("slackware"), "tgz")
  sCmd = TAR_1_13_PROG & " --exclude=slackware.tgz --owner=root --group=root -c -z -f " & Shell$(sTempPackage) & " ."
  RunCommand(sCmd, sBuildDir)
  ' AddLog(sCmd)
  ' $sOutput = ""
  ' $bEnd = FALSE
  ' SHELL "(cd " & SConv(Shell$(sBuildDir)) & ";" & sCmd & ") 2>&1" FOR READ 'TO sOutput
  ' REPEAT
  '   SLEEP 0.01 
  '   WAIT
  ' UNTIL $bEnd
  
  If Process.LastValue Then Error.Raise(("'tar' has returned the following error code:") & " " & Process.LastValue)

  AddLog("")
  sPackage = Subst("&1-&2-noarch-&3.tgz", sPackageName, $sVersion, CStr(Project.PackageVersion))
  MoveFile(sTempPackage, Path &/ sPackage)
  AddLog(sPackage)
  
End

' Private Sub MakeTgzSupportPackage((sSys) As String, sSupport As String, aComp As String[])
' 
'   Dim sDistribution As String
'   Dim sVendor As String
'   Dim sBuildDir As String
'   Dim hFile As File
'   'Dim sPrefix As String
'   Dim sCmd As String
'   Dim sData As String
'   Dim sTempPackage As String
'   Dim sPackage As String
'   Dim sPackageName As String
'   
'   $sFormatSingle = "&1\n"
'   $sFormatMin = "&1 >= &2\n"
'   $sFormatMax = "&1 < &3\n"
'   $sFormatMinMax = $sFormatMin & $sFormatMax
'   $sFormatEqual = $sFormatMinMax
' 
'   sPackageName = FormatTgzPackageName($sUnsafePackageName) & "-" & sSupport
'   sDistribution = "Slackware"
'   sVendor = "Slackware"
'   
'   ' 1. Create the temporary build directory
' 
'   AddLog(("Making build directory."))
' 
'   sBuildDir = File.SetExt(Temp$("slackware"), "")
'   Shell "rm -rf " & Shell(sBuildDir) Wait
'   Mkdir sBuildDir
'   Try Mkdir sBuildDir &/ "install"
'   
'   ' 5. Description file
' 
'   hFile = Open sBuildDir &/ "/install/slack-desc" For Create
'   
'   Print #hFile, File.Load("install/slack-desc-header");    
'   PrintSlackDescRuler(hFile, sPackageName)
'   PrintSlackDesc(hFile, Subst("&1 &2: &3", sPackageName, $sVersion, sSupport & " support for " & IIf(Project.Title, Project.Title, Project.Name)), sPackageName)
'   PrintSlackDesc(hFile, "", sPackageName)
'   sData = sSupport & " support for " & IIf(Project.Title, Project.Title, Project.Name)
'   PrintSlackDescContents(hFile, sData, 7, sPackageName)
'   PrintSlackDesc(hFile, "Package created by: " & Project.Maintainer, sPackageName)
'   PrintSlackDesc(hFile, "EMail address: " & Project.Address, sPackageName)
' 
'   Close #hFile
'   
'   ' 6. Dependencies
'   
'   hFile = Open sBuildDir &/ "/install/slack-required" For Create
'   
'   Print #hFile, FormatTgzPackageName($sUnsafePackageName); " >= "; $sVersion
'   Print #hFile, FormatTgzPackageName($sUnsafePackageName); " <= "; $sVersion
'   Print #hFile, GetDependencies(aComp);
'   
'   Close #hFile
'   
'   ' 7. Create package
'   
'   AddLog(("Creating package...") & "\n")
' 
'   sTempPackage = File.SetExt(Temp$("slackware"), "tgz")
'   sCmd = TAR_1_13_PROG & " --exclude=slackware.tgz --owner=root --group=root -c -z -f " & Shell$(sTempPackage) & " ."
'   RunCommand(sCmd, sBuildDir)
'   ' AddLog(sCmd)
'   ' $sOutput = ""
'   ' $bEnd = FALSE
'   ' SHELL "(cd " & SConv(Shell$(sBuildDir)) & ";" & sCmd & ") 2>&1" FOR READ 'TO sOutput
'   ' REPEAT
'   '   SLEEP 0.01 
'   '   WAIT
'   ' UNTIL $bEnd
'   
'   If Process.LastValue Then Error.Raise(("'tar' has returned the following error code:") & " " & Process.LastValue)
' 
'   AddLog("")
'   sPackage = Subst("&1-&2-noarch-&3.tgz", sPackageName, $sVersion, CStr(Project.PackageVersion))
'   MoveFile(sTempPackage, Path &/ sPackage)
'   AddLog(sPackage)
'   
' End
' 
Private Sub MakeAutotoolsPackage((sSys) As String)

  Dim sBuildDir As String
  Dim sFile As String
  Dim hFile As File
  Dim sCmd As String
  Dim sPackage As String
  
  sPackage = GetPackageName($sName)
  
  ' 1. Create the temporary build directory

  AddLog(("Making build directory."))

  sBuildDir = File.SetExt(Temp$("autotools"), "")
  'Shell "rm -rf " & Shell(sBuildDir) Wait
  Shell.RmDir(sBuildDir)
  Mkdir sBuildDir
  
  ' 2. Copy needed files 

  Try sCmd = Scan(Project.GetCompileCommand(True, Not Project.KeepDebugInfo, True, False), "*/bin/gbc" & System.Version & " *")[1]

  'Mkdir sBuildDir &/ Project.Name
  Shell "cp -rL " & Shell$(Project.Dir) & " " & Shell$(sBuildDir &/ $sName) Wait 
  sFile = Replace(File.Load("install/acinclude.m4"), "$(VERSION)", CStr(System.Version))
  sFile = Replace(sFile, "$(PACKAGE_VERSION)", $sVersion)
  sFile = Replace(sFile, "$(EXTRA_TEST)", Project.ExtraAutoconfTest)
  File.Save(sBuildDir &/ "acinclude.m4", sFile)
  sFile = Replace(File.Load("install/Makefile.am"), "$(VERSION)", CStr(System.Version))  
  sFile = Replace(sFile, "$(COMPILE_FLAGS)", sCmd)
  File.Save(sBuildDir &/ "Makefile.am", sFile)
  
  ' 3. Create needed files (AUTHORS, README, COPYING, NEWS, ChangeLog, configure.ac)
  
  If Exist(sBuildDir &/ $sName &/ "CHANGELOG") Then 
    Move sBuildDir &/ $sName &/ "CHANGELOG" To sBuildDir &/ "ChangeLog"
  Endif  

  File.Save(sBuildDir &/ "ChangeLog", ChangeLog)
  File.Save(sBuildDir &/ "AUTHORS", Project.Maintainer & " <" & Project.Address & ">")
  File.Save(sBuildDir &/ "README", Project.Description)
  File.Save(sBuilddir &/ "COPYING", "This program is under: " & Project.License)
  File.Save(sBuilddir &/ "NEWS", "")
  
  hFile = Open sBuildDir &/ "configure.ac" For Create
    Print #hFile, "dnl -- package generated with gambas3 ide --"
    Print #hFile, ""
    Print #hFile, "AC_INIT([" & $sName & "],[" & $sVersion & "],[],[" & $sName & "])"
    Print #hFile, "AC_CONFIG_SRCDIR([configure.ac])"
    If Project.Type = Project.TYPE_COMPONENT Then
      Print #hFile, "GB_INIT_PROJECT([" & $sName & "],[" & sPackage & "],[" & $sComponentName & "])"
    Else
      Print #hFile, "GB_INIT_PROJECT([" & $sName & "],[" & sPackage & "])"
    Endif
    Print #hFile, ""
    Print #hFile, "dnl -- create makefile --"
    Print #hFile, ""
    Print #hFile, "AC_OUTPUT(Makefile)"
  Close #hFile

  ' 4. create the package
  
  AddLog(("Creating package...") & "\n")

  For Each sCmd In ["aclocal", AUTOCONF_PROG, AUTOMAKE_PROG & " -a", "./configure", "make dist"]
    RunCommand(sCmd, sBuildDir)
  Next 
  
  AddLog("")

  sPackage = Dir(sBuildDir, $sName & "*" & $sVersion & "*")[0]
  MoveFile(sBuildDir &/ sPackage, Path &/ GetPackagePrefix(Project.Type, $sVendor, $sVendorPrefix, Project.Prefix) & sPackage)
  AddLog(sPackage)
  
  ' Remove build dir
  Shell.RmDir(sBuildDir)
  
End

Private Sub FormatArchPackageName(sName As String) As String
  
  Dim I As Integer
  Dim sCar As String
  Dim sRes As String

  For I = 1 To Len(sName)
    sCar = Mid$(sName, I, 1)
    If Not IsLetter(sCar) And If Not IsDigit(sCar) Then sCar = "-"
    sRes &= sCar
  Next
  
  Return sRes
  
End

Private Sub MakeArchPackageInit()

  Dim aLines As New String[]

  Try aLines = Split(File.Load("~/.makepkg.conf"), "\n")
  Try Move "~/.makepkg.conf" Kill "~/.makepkg.conf.save"
  aLines.Add("PACKAGER=" & Quote(Project.Maintainer & " <" & Project.Address & ">"))
  File.Save("~/.makepkg.conf", aLines.Join("\n") & "\n")

End

Private Sub MakeArchPackageExit()
  
  Try Kill "~/.makepkg.conf"
  Try Move "~/.makepkg.conf.save" Kill "~/.makepkg.conf"
  
End


Private Function MakeArchPackage(sSys As String)

  Dim sBuildDir As String
  Dim sPkgTgz As String
  Dim hFile As File
  Dim sCmd As String
  Dim sDependencies As String
  Dim sPkgDesc As String
  Dim sPackageName As String
  
  sPackageName = FormatArchPackageName($sUnsafePackageName)

  sPkgDesc = Replace($sDescription, "\n", " ")
  If sPkgDesc = "" Then sPkgDesc = "A software done with Gambas3"
  
  $sFormatMinMax = "'&1>=&2' '&1<=&3' "
  $sFormatMin = "'&1>=&2' "
  $sFormatMax = "'&1<=&3' "
  $sFormatSingle = "'&1' "
  $sFormatEqual = "'&1=&2' "
  sDependencies = GetDependencies() & GetExtraDependencies(sSys)
  
  ' 1. Create the temporary build directory

  AddLog(("Making build directory."))

  sBuildDir = File.SetExt(Temp$("archlinux"), "")
  Shell.RmDir(sBuildDir)
  Mkdir sBuildDir

  ' 2. Copy needed files 
  
  sPkgTgz = $sName & "-" & $sVersion & ".tar.bz2"
  Project.MakeSourcePackageTo(sBuildDir &/ sPkgTgz)

  File.Save(sBuilddir &/ "license.txt", "This program is under: " & Project.License)
  
  If Project.Type = Project.TYPE_NORMAL Then

    Project.StretchIcon(Project.Dir &/ Project.Icon, 48).Save(sBuildDir &/ Project.Name & ".png")

    hFile = Open sBuildDir &/ sPackageName & ".desktop" For Create
    PrintDesktopFile(hFile, $sName, "/usr/share/pixmaps/" & $sName & ".png")
    Close #hFile
    
  Endif 
   
  hFile = Open sBuildDir &/ "PKGBUILD" For Create
    Print #hFile, "# generated by the gambas3 ide"
    Print #hFile, "# Maintainer: " & Project.Maintainer & " <" & Project.Address & ">"
    Print #hFile, ""
    Print #hFile, "pkgname="; sPackageName
    Print #hFile, "_realname="; $sName
    Print #hFile, "pkgdesc="; Shell$(sPkgDesc)
    Print #hFile, "pkgver="; $sVersion
    Print #hFile, "pkgrel="; Project.PackageVersion
    Print #hFile, "arch=('any')"
    Print #hFile, "url="; Shell(Project.Url)
    If Me.ChangeLog Then 
      File.Save(sBuildDir &/ "ChangeLog", Me.ChangeLog)
      Print #hFile, "changelog=ChangeLog"
    Endif  
    
    ' General Public License
    ' Public Domain
    ' Lesser General Public License
    ' Other License(s)
    ' Non-free License
    
    Print #hFile, "license=('custom:" & Project.License & "')"
    If Len(sDependencies) > 0 Then
      Print #hFile, "depends=(" & Left$(sDependencies, -1) & ")"
    Endif
    Print #hFile, "makedepend=('gambas3-devel')"
    Print #hFile, "source=(${_realname}-$pkgver.tar.bz2 license.txt";
    If Project.Type = Project.TYPE_NORMAL Then
      Print #hFile, "\\\n        '" & sPackageName & ".desktop'";
      Print #hFile, " '" & Project.Name & ".png'";
    Endif 
    Print #hFile, ")"
  Close #hFile

  RunCommand(MAKEPKG_PROG & " -m -g >> PKGBUILD", sBuildDir, True)
  If Process.LastValue > 0 Then Error.Raise(("'makepkg' has failed."))

  hFile = Open sBuildDir &/ "PKGBUILD" For Append
  
    Print #hFile, ""
    Print #hFile, "build() {"
    Print #hFile, "  cd ${srcdir}/${_realname}"
    Print #hFile, ""
    Print #hFile, "  "; Project.GetCompileCommand(True, Not Project.KeepDebugInfo, True, False); " && gba"; System.Version
    Print #hFile, "}"
    Print #hFile, ""
    Print #hFile, "package() {"
    Print #hFile, "  cd ${srcdir}/${_realname}"
    Print #hFile, ""
    
    Select Case Project.Type
    
      Case Project.TYPE_COMPONENT
        
        Print #hFile, "  install -d ${pkgdir}/usr/lib/gambas" & System.Version
        Print #hFile, "  install -d ${pkgdir}/usr/share/gambas" & System.Version &/ "info"
        Print #hFile, "  install -m755 " & $sName & ".gambas ${pkgdir}/usr/lib/gambas" & System.Version &/ $sComponentName & ".gambas"
        Print #hFile, "  install .component ${pkgdir}/usr/lib/gambas" & System.Version &/ $sComponentName & ".component"
        Print #hFile, "  chmod a-x ${pkgdir}/usr/lib/gambas" & System.Version &/ $sComponentName & ".component" 
        Print #hFile, "  install .info ${pkgdir}/usr/share/gambas" & System.Version &/ "info" &/ $sComponentName & ".info"
        Print #hFile, "  chmod a-x ${pkgdir}/usr/share/gambas" & System.Version &/ "info" &/ $sComponentName & ".info" 
        Print #hFile, "  install .list ${pkgdir}/usr/share/gambas" & System.Version &/ "info" &/ $sComponentName & ".list"
        Print #hFile, "  chmod a-x ${pkgdir}/usr/share/gambas" & System.Version &/ "info" &/ $sComponentName & ".list" 
        Print #hFile, "  if test -d control; then"
        Print #hFile, "    install -d ${pkgdir}/usr/share/gambas" & System.Version &/ "control" &/ $sComponentName
        Print #hFile, "    install .hidden/control/*.png ${pkgdir}/usr/share/gambas" & System.Version &/ "control" &/ $sComponentName
        Print #hFile, "    chmod a-x ${pkgdir}/usr/share/gambas" & System.Version &/ "control" &/ $sComponentName &/ "*.png"
        Print #hFile, "  fi"
        
      Case Project.TYPE_LIBRARY
        
        Print #hFile, "  install -d ${pkgdir}/usr/lib/gambas" & System.Version &/ LCase($sVendor)
        Print #hFile, "  install -m755 " & $sName & ".gambas ${pkgdir}/usr/lib/gambas" & System.Version &/ LCase($sVendor) &/ $sLibraryName & ".gambas"

      Case Project.TYPE_NORMAL
  
        Print #hFile, "  install -d ${pkgdir}/usr/bin"
        Print #hFile, "  install -m755 " & $sName & ".gambas ${pkgdir}/usr/bin" &/ $sName
        If $sName <> sPackageName Then Print #hFile, "  ln -s " & Shell$($sName) & " \"${pkgdir}\"/usr/bin" &/ Shell$(sPackageName)
        Print #hFile, "  install -D .." &/ Project.Name & ".png \\"
        Print #hFile, "    ${pkgdir}/usr/share/pixmaps" &/ Project.Name & ".png"
        Print #hFile, "  install -D .." &/ sPackageName & ".desktop \\"
        Print #hFile, "    ${pkgdir}/usr/share/applications" &/ sPackageName & ".desktop"

    End Select

    Print #hFile, GetExtraFilesDir(sSys, "  install -d ${pkgdir}&1");
    Print #hFile, GetExtraFiles(sSys, "  install -p ${srcdir}/${_realname}/.hidden/&1 ${pkgdir}&2/&1", "  cp -R --preserve=timestamp ${srcdir}/${_realname}/.hidden/&1 ${pkgdir}&2/&1");
    Print #hFile, "  install -Dm644 ${srcdir}/license.txt ${pkgdir}/usr/share/licenses" &/ sPackageName &/ "LICENSE"
    Print #hFile, "}"
    
  Close #hFile
  
  ' 4. create the packages
  
  AddLog(("Creating package...") & "\n")
  
  For Each sCmd In [MAKEPKG_PROG & " -m --allsource", "makepkg -m -d"]
    RunCommand(sCmd, sBuildDir)
    If Process.LastValue > 0
      Error.Raise(("'makepkg' has failed."))
    Endif
  Next 

  RunCommand("cp " & sPackageName & "-" & $sVersion & "-" & CStr(Project.PackageVersion) & "*.tar.* " & Shell$(Path) &/ "", sBuildDir)

  ' Remove build dir
  Shell.RmDir(sBuildDir)

End 

Private Function MakeArchSupportPackage((sSys) As String, sSupport As String, aComp As String[])

  Dim sBuildDir As String
  Dim hFile As File
  Dim sCmd As String
  Dim sDependencies As String
  Dim sPkgDesc As String
  Dim sPackageName As String
  
  sPackageName = FormatArchPackageName($sUnsafePackageName & "-" & sSupport)

  sPkgDesc = "This is the " & sSupport & " support for " & If(Project.Title, Project.Title, Project.Name)
  
  $sFormatMinMax = "'&1>=&2' '&1<=&3' "
  $sFormatMin = "'&1>=&2' "
  $sFormatMax = "'&1<=&3' "
  $sFormatSingle = "'&1' "
  $sFormatEqual = "'&1=&2' "
  
  sDependencies = GetDependencies(aComp)
  
  ' 1. Create the temporary build directory

  AddLog(("Making build directory."))

  sBuildDir = File.SetExt(Temp$("archlinux"), "")
  Shell.RmDir(sBuildDir)
  Mkdir sBuildDir

  ' 2. Copy needed files 
  
  File.Save(sBuilddir &/ "license.txt", "This program is under: " & Project.License)
  
  hFile = Open sBuildDir &/ "PKGBUILD" For Create
    Print #hFile, "# generated by the gambas3 ide"
    Print #hFile, "# Maintainer : " & Project.Maintainer & " <" & Project.Address & ">"
    Print #hFile, ""
    Print #hFile, "pkgname=" & sPackageName
    Print #hFile, "_realname="; sPackageName
    Print #hFile, "pkgdesc="; Shell$(sPkgDesc)
    Print #hFile, "pkgver="; $sVersion
    Print #hFile, "pkgrel="; Project.PackageVersion
    Print #hFile, "arch=('any')"
    Print #hFile, "url="; Shell$(Project.Url)
    If Me.ChangeLog Then 
      File.Save(sBuildDir &/ "ChangeLog", Me.ChangeLog)
      Print #hFile, "changelog=ChangeLog"
    Endif  
    Print #hFile, "license=('custom')"
    If Len(sDependencies) > 0 Then
      Print #hFile, "depends=(" & Subst($sFormatEqual, FormatArchPackageName($sUnsafePackageName), $sVersion) & Left$(sDependencies, -1) & ")"
    Endif
    'Print #hFile, "makedepend=('gambas3-devel')"
    'Print #hFile, "source=(${_realname}-$pkgver.tar.bz2 license.txt";
    'If Project.Type = Project.TYPE_NORMAL Then
    '  Print #hFile, "\\\n        '" & $sPackageName & ".desktop'";
    '  Print #hFile, " '" & Project.Name & ".png'";
    'Endif 
    'Print #hFile, ")"
  Close #hFile
  
  RunCommand(MAKEPKG_PROG & " -m -g >> PKGBUILD", sBuildDir, True)
  If Process.LastValue > 0 Then Error.Raise(("'makepkg' has failed."))
  
  ' hFile = Open sBuildDir &/ "PKGBUILD" For Append
  ' 
  '   Print #hFile, ""
  '   Print #hFile, "build() {"
  '   Print #hFile, "  cd ${srcdir}/${_realname}"
  '   Print #hFile, ""
  '   Print #hFile, "  "; Project.GetCompileCommand(True, Not Project.KeepDebugInfo, True, False); " && gba"; System.Version
  '   Print #hFile, "}"
  '   Print #hFile, ""
  '   Print #hFile, "package() {"
  '   Print #hFile, "  cd ${srcdir}/${_realname}"
  '   Print #hFile, ""
  '   
  '   Select Case Project.Type
  '   
  '     Case Project.TYPE_COMPONENT
  '       
  '       Print #hFile, "  install -d ${pkgdir}/usr/lib/gambas" & System.Version
  '       Print #hFile, "  install -d ${pkgdir}/usr/share/gambas" & System.Version &/ "info"
  '       Print #hFile, "  install -m755 " & $sName & ".gambas ${pkgdir}/usr/lib/gambas" & System.Version
  '       Print #hFile, "  install .component ${pkgdir}/usr/lib/gambas" & System.Version &/ $sName & ".component"
  '       Print #hFile, "  chmod a-x ${pkgdir}/usr/lib/gambas" & System.Version &/ $sName & ".component" 
  '       Print #hFile, "  install .info ${pkgdir}/usr/share/gambas" & System.Version &/ "info" &/ $sName & ".info"
  '       Print #hFile, "  chmod a-x ${pkgdir}/usr/share/gambas" & System.Version &/ "info" &/ $sName & ".info" 
  '       Print #hFile, "  install .list ${pkgdir}/usr/share/gambas" & System.Version &/ "info" &/ $sName & ".list"
  '       Print #hFile, "  chmod a-x ${pkgdir}/usr/share/gambas" & System.Version &/ "info" &/ $sName & ".list" 
  '       Print #hFile, "  if test -d control; then"
  '       Print #hFile, "    install -d ${pkgdir}/usr/share/gambas" & System.Version &/ "control" &/ $sName
  '       Print #hFile, "    install .hidden/control/*.png ${pkgdir}/usr/share/gambas" & System.Version &/ "control" &/ $sName
  '       Print #hFile, "    chmod a-x ${pkgdir}/usr/share/gambas" & System.Version &/ "control" &/ $sName &/ "*.png"
  '       Print #hFile, "  fi"
  '       
  '     Case Project.TYPE_LIBRARY
  '       
  '       Print #hFile, "  install -d ${pkgdir}/usr/bin"
  '       Print #hFile, "  install -m755 " & $sName & ".gambas ${pkgdir}/usr/bin" &/ $sName & ".gambas"
  ' 
  '     Case Project.TYPE_NORMAL
  ' 
  '       Print #hFile, "  install -d ${pkgdir}/usr/bin"
  '       Print #hFile, "  install -m755 " & $sName & ".gambas ${pkgdir}/usr/bin" &/ $sName
  '       Print #hFile, "  install -D .." &/ Project.Name & ".png \\"
  '       Print #hFile, "    ${pkgdir}/usr/share/pixmaps" &/ Project.Name & ".png"
  '       Print #hFile, "  install -D .." &/ $sPackageName & ".desktop \\"
  '       Print #hFile, "    ${pkgdir}/usr/share/applications" &/ $sPackageName & ".desktop"
  ' 
  '   End Select
  ' 
  '   Print #hFile, GetExtraFilesDir(sSys, "  install -d ${pkgdir}&1\n");
  '   Print #hFile, GetExtraFiles(sSys, "  install -p ${srcdir}/${_realname}/.hidden/&1 ${pkgdir}&2/&1", "  cp -R --preserve=timestamp ${srcdir}/${_realname}/.hidden/&1 ${pkgdir}&2/&1");
  '   Print #hFile, "  install -Dm644 ${srcdir}/license.txt ${pkgdir}/usr/share/licenses" &/ $sPackageName &/ "license.txt"
  '   Print #hFile, "}"
  '   
  ' Close #hFile
  
  ' 4. create the packages
  
  AddLog(("Creating package...") & "\n")
  
  For Each sCmd In [MAKEPKG_PROG & " -m --allsource", MAKEPKG_PROG & " -m -d"]
    RunCommand(sCmd, sBuildDir)
    If Process.LastValue > 0
      Error.Raise(("'makepkg' has failed."))
    Endif
  Next 

  RunCommand("cp " & sPackageName & "-" & $sVersion & "-" & CStr(Project.PackageVersion) & "*.tar.* " & Shell$(Path) &/ "", sBuildDir)

  ' Remove build dir
  Shell.RmDir(sBuildDir)

End 

Private Sub MoveFile(sSrc As String, sDst As String)

  Try Kill sDst
  Try Move sSrc To sDst
  If Error Then
    Copy sSrc To sDst
    Try Kill sSrc
  Endif
  
End

Public Sub Process_Kill()
  
  $bEnd = True
  
End

Public Sub Process_Read()
  
  Dim sData As String
  
  sData = Read #Last, -256
  $sOutput &= sData
  FMakeInstall.AddLog(sData, True)
  
End

Public Sub Process_Prompt((Prompt) As String, (Answer) As String)

  Dim hProcess As Process
  
  hProcess = Last
  
  If Not $sPassword Then

    Dialog.NoUser = True
    If Dialog.AskPassword() Then
      hProcess.Kill
      Return 
    Endif
    
    $sPassword = Dialog.Password
    
  Endif
  
  Print #hProcess, $sPassword

End

Public Sub Process_Error(sData As String)

  FMakeInstall.AddLog(sData, True)

End

Public Sub GetPackageName(sName As String) As String

  sName = LCase(String.RemoveDiacritics(sName))
  sName = Replace(sName, ".", "-")
  Return sName
  
End

Public Sub GetPackagePrefix(iProjectType As Integer, sVendor As String, sVendorPrefix As String, bPrefix As Boolean) As String

  Dim sText As String
  Dim sPackage As String
  Dim sPrefix As String
  
  If iProjectType = Project.TYPE_COMPONENT Then

    sPrefix = String.LCase(Trim(sVendorPrefix))
    If Not sPrefix Then sPrefix = "gb"
    
    sPackage = GetPackageName(Project.Name)
    If sPackage Begins sPrefix & "-" Or If sPackage = sPrefix Then 
      sPrefix = ""
    Else 
      sPrefix &= "-"
    Endif
    sText = "gambas" & System.Version & "-" & sPrefix
  
  Else

    If bPrefix Then
      
      sPrefix = sVendorPrefix
      If Not sPrefix Then sPrefix = sVendor
      sPrefix = String.LCase(Trim(sPrefix))
      sPrefix = Replace(sPrefix, "_", "-")
  
      If Not sPrefix Then sPrefix = "gambas"
      
      sText = sPrefix & "-"
      
    Endif
    
  Endif
  
  Return sText
  
End

Public Sub GetPackageFullName(sVendor As String, sVendorPrefix As String, bPrefix As Boolean, bWithMajor As Boolean, bWithVersion As Boolean) As String
  
  Dim sText As String
  
  sText = GetPackagePrefix(Project.Type, sVendor, sVendorPrefix, bPrefix) & GetPackageName(Project.Name)
  If bWithMajor Then sText &= CStr(Project.MajorVersion)
  If bWithVersion Then sText &= "-" & Project.FormatVersion()
  Return sText
  
End

Public Sub GetAppImageSystem() As String
  
  If System.Exist("apt") And If Exist("/etc/apt/sources.list") Then Return "apt"
  If System.Exist("pacman") And If Exist("/etc/pacman.d/mirrorlist") Then Return "pacman"
  
End

Private Sub MakeAppImagePackage(sSys As String)

  Dim sRoot As String
  Dim sAppDir As String
  Dim sAppImageBuilder As String
  Dim sDistrib As String
  Dim aSources As String[]
  Dim sGambasPPA As String
  Dim sComp As String
  Dim aPackages As String[]
  Dim aGenericGuiComp As String[]
  Dim I As Integer
  Dim aDir As String[]
  Dim bHasDatabaseDriver As Boolean
  Dim sDep As String
  Dim sAppId As String
  Dim bAddWayland As Boolean
  Dim sSource As String
  Dim sName As String
  Dim sSignKey As String
  Dim sAppImageType As String
  Dim sArch As String
  Dim sSudo As String
  Dim sDatabaseComponent As String
  Dim aDistrib As String[]
  Dim sDistribVer As String
  
  sAppImageType = GetAppImageSystem()
  If Settings["/Packager/AppImage/BuildAsRoot", False] Then sSudo = "sudo "
  
  AddLog(("Making build directory.")) 
  
  sName = Replace($sName, " ", "_")
  sRoot = User.Home &/ ".var/tmp/AppImage"
  sAppDir = sRoot &/ "AppDir"
  
  RunCommand(sSudo & "rm -rf " & Shell(sAppDir))
  If sSudo And If Not $sPassword Then Goto __ERROR
    
  RunCommand("mkdir -p " & Shell(sAppDir &/ "usr/bin"))
  RunCommand("mkdir -p " & Shell(sAppDir &/ "usr/share/icons/hicolor/256x256/apps"))

  ' 1. Copy the executable
  
  Copy Project.GetExecPath() To sAppDir &/ "/usr/bin" &/ sName
  Chmod sAppDir &/ "/usr/bin" &/ sName To "..x..x..x"
  
  ' 2. Copy the icon
  
  Project.StretchIcon(Project.Dir &/ Project.Icon, 256).Save(sAppDir &/ "usr/share/icons/hicolor/256x256/apps" &/ sName & ".png")

  ' TODO: 3. Copy the used libraries
  
  ' 4. Extra files
  
  CopyExtraFiles(sSys, sAppDir)
  
  ' 5. Building the 'AppImageBuilder.yml' file
  
  AddLog(("Generating 'AppImageBuilder' configuration file...")) 
  
  sAppImageBuilder = File.Load("install/AppImageBuilder-" & sAppImageType & ".yml")
  
  ' 6. Fill the application details
  
  sAppId = Project.GetAppId()
  
  sArch = System.Architecture
  Select Case sArch
    Case "x86_64"
      If sAppImageType = "apt" Then sArch = "amd64"
  End Select
  
  sAppImageBuilder = Replace(sAppImageBuilder, "$(appdir)", sAppDir)
  sAppImageBuilder = Replace(sAppImageBuilder, "$(id)", sAppId)
  sAppImageBuilder = Replace(sAppImageBuilder, "$(name)", sName)
  sAppImageBuilder = Replace(sAppImageBuilder, "$(icon)", sName & ".png")
  sAppImageBuilder = Replace(sAppImageBuilder, "$(exec)", sName)
  sAppImageBuilder = Replace(sAppImageBuilder, "$(version)", $sVersion)
  sAppImageBuilder = Replace(sAppImageBuilder, "$(package-arch)", sArch)
  sAppImageBuilder = Replace(sAppImageBuilder, "$(arch)", System.Architecture)
  
  If Settings["/Packager/AppImage/Sign", False] Then sSignKey = Trim(Settings["/Packager/AppImage/SignKey"])
  If sSignKey Then
    sAppImageBuilder = Replace(sAppImageBuilder, "$(signature)", "sign-key: " & sSignKey)
  Else
    sAppImageBuilder = Replace(sAppImageBuilder, "$(signature)", "")
  Endif
  
  If Not Project.AppImageDoNotUseEmbedProg Then
    sAppImageBuilder = Replace(sAppImageBuilder, "$(pathenv)", "PATH: '${APPDIR}/usr/bin:${APPDIR}/bin:${PATH}'")
  Else
    sAppImageBuilder = Replace(sAppImageBuilder, "$(pathenv)", "")
  Endif
  
  ' 7. Package sources
  
  aSources = New String[]
  
  Select Case sAppImageType
    
    Case "apt"
  
      sDistrib = LCase(Trim(Project.AppImageDistribution))
      If Not sDistrib Then sDistrib = "jammy (22.04)"
      aDistrib = Scan(sDistrib, "* (*)")
      If aDistrib.Count = 2 Then
        sDistrib = aDistrib[0]
        sDistribVer = aDistrib[1]
      Else If sDistrib Like "[0-9][0-9].{04;10}" Then
        sDistribVer = sDistrib
        sDistrib = ""
      Else
        Error.Raise(("Incorrect Ubuntu version"))
      Endif
  
      For Each sSource In ["&1 &2 main restricted", "&1 &2-updates main restricted", "&1 &2 universe", "&1 &2-updates universe", "&1 &2 multiverse", "&1 &2-updates multiverse", "&3 &2-security main restricted", "&3 &2-security universe", "&3 &2-security multiverse", "&4 &2 main restricted universe multiverse"]
        
        sSource = "deb " & Subst(sSource, Project.AppImageRepository, sDistrib, "http://security.ubuntu.com/ubuntu/", "http://ddebs.ubuntu.com")
        aSources.Add("    - sourceline: " & sSource)
        
      Next
      
      sGambasPPA = Project.AppImageGambasRepository
      If Not sGambasPPA Then sGambasPPA = DEFAULT_GAMBAS_REPOSITORY
      If InStr(sGambasPPA, " ") = 0 Then
        If Not sDistrib Then Error.Raise(("Incorrect Ubuntu version"))
        sSource = Subst("deb &1 &2 main", sGambasPPA, sDistrib)
      Else
        sSource = "deb " & Replace(sGambasPPA, "${VERSION}", sDistribVer)
      Endif
      aSources.Add("    - sourceline: " & sSource)
      
    Case "pacman"
      
      aSources.Add("      core:")
      aSources.Add("        - " & Project.AppImagePacmanRepository)
      aSources.Add("      extra:")
      aSources.Add("        - " & Project.AppImagePacmanRepository)
      aSources.Add("      multilib:")
      aSources.Add("        - " & Project.AppImagePacmanRepository)
      
  End Select
  
  sAppImageBuilder = Replace(sAppImageBuilder, "$(sources)", aSources.Join("\n"))
  
  ' 8. Package dependencies
  
  aPackages = New String[]
  aGenericGuiComp = New String[]
  
  For Each sComp In Project.Components
    If sComp = "gb.db" Or If sComp = "gb.db2" Then
      sDatabaseComponent = sComp
    Else If sComp Begins "gb.db." And If DATABASE_DRIVERS.Exist(Mid$(sComp, 6)) Then
      bHasDatabaseDriver = True
    Else If sComp Begins "gb.db2." And If DATABASE_DRIVERS.Exist(Mid$(sComp, 7)) Then
      bHasDatabaseDriver = True
    Else If sComp Begins "gb.gui" And If GENERIC_GUI_COMPONENT.Exist(sComp) Then
      aGenericGuiComp.Add(sComp)
    Endif
    If GUI_COMPONENTS_USING_WAYLAND.Exist(sComp) Then bAddWayland = True
    If IsRuntimeComponent(sComp) Then Continue
    aPackages.Add("gambas3-" & Replace(sComp, ".", "-"))
  Next
  
  If sDatabaseComponent And If Not bHasDatabaseDriver Then
    For Each sComp In DATABASE_DRIVERS
      aPackages.Add("gambas3-" & Replace(sDatabaseComponent & sComp, ".", "-"))
    Next
  Endif
  
  For Each sComp In aGenericGuiComp
    If sComp Begins "gb.gui.qt" Then
      aPackages.Add("gambas3-" & Replace(Replace(sComp, ".gui.qt", ".qt5"), ".", "-"))
    Else
      aPackages.Add("gambas3-" & Replace(Replace(sComp, ".gui", ".qt5"), ".", "-"))
      aPackages.Add("gambas3-" & Replace(Replace(sComp, ".gui", ".gtk3"), ".", "-"))
    Endif
  Next
  
  ' Always add Gambas stock icons, in the case they are loaded at runtime.
  If Not aPackages.Exist("gambas3-gb-form-stock") Then aPackages.Add("gambas3-gb-form-stock")
  
  Select Case sAppImageType
    
    Case "apt"
      If bAddWayland Then aPackages.Insert(["libwayland-client0", "libwayland-cursor0", "libwayland-egl1"])
      If aPackages.Exist("gambas3-gb-gtk3") Then aPackages.Insert(["librsvg2-2", "librsvg2-common"])
      
  End Select
  
  ' 9. Extra dependencies

  For Each sDep In Split(Project.ExtraDependencies[If(Project.SameDependencies, ALL_TARGETS, sSys)], "\n")
    aPackages.Add(Split(sDep, "\t")[0])
  Next

  For I = 0 To aPackages.Max
    aPackages[I] = "    - " & aPackages[I]
  Next
  
  sAppImageBuilder = Replace(sAppImageBuilder, "$(packages)", aPackages.Join("\n"))
  
  ' 10. Build that sucker
  
  File.Save(sRoot &/ "AppImageBuilder.yml", sAppImageBuilder)
  
  AddLog(("Creating AppImage..."))
  
  RunCommand(sSudo & APPIMAGE_PROG & " --skip-script --skip-tests", sRoot)
  If sSudo And If $sPassword Then RunCommand(sSudo & "chown -R " & User.Name & ":" & User.Name & " " & Shell$(sRoot))
  
__ERROR:
  
  aDir = Dir(sRoot, "*.AppImage")
  If aDir.Count = 1 Then
    MoveFile(sRoot &/ aDir[0], Path &/ aDir[0])
    'Try Shell "rm -rf " & Shell$(sRoot) Wait
  Else
    Error.Raise(("Unable to create AppImage."))
  Endif
  
End
