[iOS] Add documentation for working with iOS files.
Change-Id: I24aead570e61d9451372f9b4a0a792c12bbe2ae3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2149455
Commit-Queue: Mark Cogan <[email protected]>
Reviewed-by: Sylvain Defresne <[email protected]>
Reviewed-by: Tina Wang <[email protected]>
Cr-Commit-Position: refs/heads/master@{#759207}
diff --git a/docs/ios/build_instructions.md b/docs/ios/build_instructions.md
index 4fb5b123..734f62d 100644
--- a/docs/ios/build_instructions.md
+++ b/docs/ios/build_instructions.md
@@ -206,7 +206,7 @@
display an error stating that "The application was signed with invalid
entitlements").
-## Running apps from the commandline
+## Running apps from the command line
Any target that is built and runs on the bots (see [below](#Troubleshooting))
should run successfully in a local build. To run in the simulator from the
@@ -285,6 +285,11 @@
## Tips, tricks, and troubleshooting
+Remember that the XCode project you interact with while working on Chromium is a
+build artifact, generated from the `BUILD.gn` files. Do not use it to add new
+files; instead see the procedures for [working with
+files](working_with_files.md).
+
If you have problems building, join us in `#chromium` on `irc.freenode.net` and
ask there. As mentioned above, be sure that the
[waterfall](https://build.chromium.org/buildbot/waterfall/) is green and the tree
diff --git a/docs/ios/working_with_files.md b/docs/ios/working_with_files.md
new file mode 100644
index 0000000..37a74a8
--- /dev/null
+++ b/docs/ios/working_with_files.md
@@ -0,0 +1,223 @@
+# Working With Files
+
+Adding, removing, and renaming files in iOS Chromium needs to follow a specific
+procedure that will be unfamiliar to engineers coming from other iOS projects.
+Conceptually, every file is recorded in _four_ locations: the local filesystem,
+git, the `BUILD.gn` files, and the XCode projects. Of these, the XCode project
+is wholly generated from the others.
+
+[TOC]
+
+## Overview
+
+**Do not use XCode to manipulate files.** The XCode project used for iOS
+Chromium is _generated_; it's functionally a build artifact. The various
+`BUILD.gn` files in Chromium define structure of the XCode project file. Running
+`gclient runhooks` causes the project files to be regenerated.
+
+Individual files can have their contents edited within XCode, and all of the
+regular testing and debugging activities can be done within XCode. It just can't
+be used to create files, rename files, delete files, or manipulate the project
+group structure in any way. To do these things, follow the procedures below.
+
+## Adding files
+
+To add any files (new headers, `.mm` or `.cc` implementation files, asset files
+of any kind), the following general steps need to happen:
+
+1. The file needs to exist in the correct directory of the file system for your
+ Chromium checkout. New files need to be created, or assets need to be
+ copied to the right location.
+
+1. The new files need to be added to git.
+
+1. The new files need to be added to a target in a `BUILD.gn` file (usually in
+ the same directory as the newly added file).
+
+1. The XCode project needs to be regenerated.
+
+For adding new header or implementation files, the following procedure is
+recommended:
+
+1. Generate the new files using `tools/boilerplate.py`. This will generate the
+ correct header guard macros and include the copyright boilerplate.
+
+2. Add the newly created files using `git add`.
+
+3. Edit the `BUILD.gn` file for the directory where the files were added. For
+ each file, add it to the `sources` list for the correct `source_set` in the
+ `BUILD.gn` file. Note that `gn format` (which is run as part of `git cl
+ format`) will take care of alphabetizing the lists along with other
+ formatting, so there's no need to manually do these things. (`BUILD.gn`
+ files cand be edited directly in XCode, or in another editor such as `vi`).
+
+4. Once all of the files have been created, `add`ed and all `BUILD.gn` files
+ have been updated, run `gclient runhooks` to regenerate all XCode projects.
+
+5. If XCode is open, it may prompt to "Autocreate Schemes". If so, click on the
+ highlighted "Automatically Create Schemes" button.
+
+In the shell, this procedure would look like this:
+```bash
+// Step 1 -- generate new files.
+$ tools/boilerplate.py ios/chrome/browser/some_feature/feature_class.h
+$ tools/boilerplate.py ios/chrome/browser/some_feature/feature_class.mm
+$ tools/boilerplate.py ios/chrome/browser/some_feature/feature_class_unittest.mm
+// Step 2 -- add the new files.
+$ git add ios/chrome/browser/some_feature/feature_class*
+// Step 3 -- edit the BUILD.gn file in the editor of your choice
+$ vi ios/chrome/browser/some_feature/BUILD.gn
+// Step 4 -- regenerate the XCode Projects
+$ gclient runhooks
+```
+
+To add asset files, follow this procedure:
+
+1. Copy the asset files to the correct directory, with the correct names
+ (including `@2x` and `@3x` suffixes) Note that images are stored in
+ `.imageset` directories, conventionally inside `resources` directories for a
+ given UI feature. New directories, if needed, are created in the usual way
+ (`mkdir`). Note that there is no equivalent of `boilerplate.py` for images
+ or other asset files.
+
+1. Create or copy `Contents.json` files for each new `.imageset` directory,
+ with the appropriate contents.
+
+1. Add all image and `Contents.json` files using `git add`.
+
+1. Edit the `BUILD.gn` file in the containing `resources` directory, adding
+ `imageset` entries for each added `.imageset` directory, and then grouping
+ all assets into a new or existing `group()` declaration with a `public_deps`
+ list containing all of the `imageset` targets.
+
+1. Regenerate the XCode project with `gclient runhooks`.
+
+To add Markdown documentation files, the procedure is much simpler. These files
+are automatically added to the XCode project without `BUILD.gn` entries, and
+they have no required boilerplate. So adding new docs is as simple as:
+
+1. Create a new `.md` file in the appropriate directory (`docs/ios`, for
+ example).
+
+1. `git add` the file.
+
+The newly added file will be visible in XCode after the next `gclient runhooks`.
+
+## Moving and renaming files.
+
+Renaming a file involves updating the filename in all of the places where it
+exists: the file names in the filesystem, the file names in git, header guards
+in files, import declarations in files, listings in BUILD.gn files, and
+internally in the XCode project. As with adding a file, different tools are used
+for each of these. Unlike creating a file, which starts with actually adding a
+file to the filesystem, a rename starts with updating git (via `git mv`), then
+using the `mass_rename` tool to update file contents.
+
+`tools/git/mass_rename.py` works by looking at _uncommitted_ file moves in git,
+and then updating all includes, header guards, and BUILD.gn entries to use the
+new name. It doesn't update some other files, such as `Contents.json` files for
+image assets. It also doesn't change any symbols in code, so class and variable
+names won't be changed.
+
+For many file moves, it will be simpler to use another tool,
+`tools/git/move_source_file.py`, which combines `git mv` and `mass_rename` in a
+single action. For example, renaming `feature_class` to `renamed_class` would be
+done like this:
+```bash
+ $ tools/git/move_source_file.py ios/chrome/browser/some_feature/feature_class.h \
+ ios/chrome/browser/some_feature/renamed_class.h
+ $ tools/git/move_source_file.py ios/chrome/browser/some_feature/feature_class.mm \
+ ios/chrome/browser/some_feature/renamed_class.mm
+```
+
+The step-by-step procedure for a rename is:
+
+1. If there are other uncommitted changes before the move, it's usually
+ cleanest to commit before starting the move.
+
+1. `move_source_file` each file that needs to be renamed. This renames the file
+ in both the file system and in git, and in most places where it's used in
+ code.
+
+1. Run `gclient runhooks` to update the XCode project. Check that all of the
+ needed name changes have been made (for example, by building all targets).
+ Make any other needed fixes.
+
+1. If any classes or other symbols need to be renamed (remember that the name
+ of the primary interface in each file must match the file name), make those
+ changes. Find-and-replace tools like `tools/git/mffr.py` or XCode's
+ Find/Replace can help here, but there are no compiler-aware tools that can
+ do a "smart" rename.
+
+1. Commit all changes (`git commit -a -m <your comment>`).
+
+A move—where a file is moved to a different directory—is in most respects
+performed using the same steps as a rename. However, while `mass_rename.py` (and
+thus `move_source_file.py`) will update existing file names in `BUILD.gn` files,
+it won't move entries from one `BUILD.gn` file to another. To move files to a
+different directory, the preceding procedure is used, but between steps 2 and 3
+(after moving the files, but before regenerating the XCode project), the old
+filenames will need to be removed from the `BUILD.gn` files in the old
+directories and added to the `BUILD.gn` files in the new directories.
+
+Also note that while `move_source_file` must be used separately for each file
+being renamed within a directory, it (just like `git mv`) can move multiple
+files without renaming to a new directory in a single command:
+
+```bash
+$ tools/git/mass_rename.py ios/chrome/browser/some_feature/feature_class.* \
+ ios/chrome/browser/some_feature/feature_class_unittest.mm \
+ ios/chrome/browser/other_feature/
+```
+
+## Deleting files.
+
+Deleting files follows the same patterns as adding and moving files. As with a
+file move, it's best to begin with deleting the files from git.
+
+Typically, before actually removing a file, first all usage of the interface(s)
+in the file(s) will be removed, and the file will no longer be `#imported`
+anywhere.
+
+Step-by step:
+
+1. `git rm` the files you want to remove. This will also remove the files
+ from the filesystem.
+
+1. Manually remove the `BUILD.gn` entries for the files.
+
+1. Regenerate the XCode project (with `gclient runhooks`) to remove the files
+ from XCode.
+
+## Finally.
+
+It's easy to miss some uses of a file that was renamed or deleted, and fixing
+compilation errors discovered in the commit queue means another
+commit-upload-dry run cycle (at least). To minimize this, after any change that
+adds, renames, moves, or deletes files, be sure to take the following steps:
+
+1. `git cl format` to update the formatting of all files.
+
+1. `gn check` to make sure that any new or moved files follow the dependency
+ rules (for example: `gn check -C out/Debug-iphonesimulator/`).
+
+1. Build all targets, to make sure that everything has been added, changed, or
+ removed correctly. This can be done by selecting the "All" target in XCode
+ and building (`⌘-B`), or from the command line (for example, `autoninja -C
+ out/Debug-iphonesimulator/`).
+
+Changes that involve adding or deleting more than a few files, and most renames
+of any size, should be in a single CL with no other changes, for ease of
+reviewing and (if necessary) reverting or cherry-picking.
+
+## Recovering from accidental XCode Project usage.
+
+If files are accidentally added, renamed, or moved through XCode, other settings
+in the XCode project may be changed that will introduce strange local build
+failures. In this case, take the following steps to recover.
+
+1. Quit XCode.
+
+1. Delete all generated XCode projects and associated files: `rm -rf out/build`.
+
+1. Regenerate all XCode projects: `gclient runhooks`.