06 August 2013

Xojo's Build Automation: Beware of CopyFiles

If you use the Xojo IDE's CopyFiles build step to add files to your built application, beware of this long-existing bug.

Maybe you've had this happen yourself: You're pretty sure you had added some entries to a CopyFiles step, but they're not there any more. And you can't remember that you've removed them, either.

Here's what happens:

If you open a Xojo project, the IDE checks if the files referenced in the CopyFiles step do actually exist. And if they don't exist, the IDE deletes these entries - without a warning. Then, if you save your project, the entries are gone forever, even if you make the missing files available again.

And it's not just missing files (something that could happen if you copied your project to another computer, e.g. using a version control system, and forgot to also copy these files along)!

The same happens if you just move your project file without also moving the referenced files relatively to it, or if you move or rename the referenced file temporarily. This is surprising because doing this is not an issue with regular external items added to the IDE!

I plan to soon add a check to Arbed so that it will warn me when it notices that a file that's referenced in a CopyFiles step is not available. Since I do use Arbed with git, it's likely to notice this issue as soon as I verify the changes on a computer that's missing the CopyFiles step files.

I've filed the issue as Feedback #28676. Though, this only describes the issue that the IDE drops the entries if the files are not found. The other issue is that the IDE doesn't find the files if the project has been moved to another folder: Feedback #28678.

Until these issues are fixed, I recomment using a IDE Script instead, issuing a shell command to copy the files. That way, you can check if the shell command fails and report the issue, e.g. like this (Mac and Linux only, for Windows you'll need different code):

  dim cmds(), s, dst as String

  // The path to the built app's Resources folder (Mac):
  dst = CurrentBuildLocation+"/"""+CurrentBuildAppName+""".app"
  dst = dst+"/Contents/Resources/"

  // prepare the commands
  cmds.Append "cd  ""$PROJECT_PATH""" // Move to the project folder
  cmds.Append "cp myfile "+dst // Copy "myfile" to app's Resources folder

  s = DoShellCommand (Join (cmds, ";"))
  if s <> "" then
    print "Copy failed: "+s

BTW, this issue wouldn't be one if the IDE would handle these CopyFiles references the same way as it does for general external files and classes added to a project. Because, if such files are temporarily missing, the project doesn't simply drop them. If you look into the project file, e.g. by saving it in XML format, you'll see that external files added to the project are referenced in three ways: With an absolute path, with a path relative to the project files, and with a "SaveInfo", which uses the special Finder Alias format, allowing it to locate files even if they've been renamed or moved, as long as they're still on the same volume. On the other hand, CopyFiles uses only use a relative path (which is, unfortunately, titled "FileAlias", misleadingly suggesting it being a powerful Finder Alias).

In my opinion, the implementation of CopyFiles was done quite badly (it's not the only bug with this seemingly simple feature), where the programmer clearly did not understand how the IDE usually references external files, instead making up its own solution, which isn't only inferior but even leads to data loss.


  1. I've had this happen fairly often Thomas. As you say "The other issue is that the IDE doesn't find the files if the project has been moved to another folder: Feedback #28678."

    This is, of course, exactly what happens when one relies on the Xojo auto-recovery process on re-launch after a crash of the IDE. The recovered project is not yet associated with a file/directory path, and thus has often, though not always, I think, had the copyFiles references removed.

    So, when Xojo crashes, the choice is to lose the CopyFiles references or to lose other work that may have been done between the last save and the IDE crash.

  2. Actually, I realized that what I wrote is not quite true. The recovered project IS associated with a file(s), but they are in Xojo's temporary recovery location, not where the original project is/was. But the effect is the same with relative path references to the CopyFiles steps being un-resolveable...