Just a few guidelines I think are helpful if your codebase targets multiple platforms:
Build your code using a cross-platform external build system rather than relying on a specific IDE. Or at least generate the IDE-specific data if you’re OK with a lower degree of quality in your build. Many IDEs don’t track dependencies correctly and don’t clean up stale output files when they are no longer produced by a build, leading to lost productivity and programmers needlessly cleaning everything as a cure-all at the first sight of problems.
Avoid checking in and maintaining IDE-specific files. Instead generate them as needed from your build system metadata. There are plenty of options for generating Visual Studio and Xcode project files. This way you keep your build data in one place for all platforms where it can be maintained more easily.
Use the file system for configuration. Instead of excluding and including files manually, put platform-specific files in their own subdirectories. If you do this, a single recursive glob of the source directory together with a few filters will give you want you want without hundreds of exceptions. This also makes it trivial to add or remove files from the build, and you’ll avoid having stale files lying around that can confuse things later. Don’t feel bad about deleting source files, you can always get them back from version control later if you change your mind.
Avoid tool-specific settings if you can. Instead define higher-level concepts that you can map to IDE settings across platforms more easily. For example, don’t define your warning levels in terms of Visual Studio’s /W0-4, but instead say “This project uses our strict warning settings”. You can define elsewhere for each toolset what that means (preferably in one place.)
Avoid per-file options in configuration. If you need to disable a MSVC-specific warning, do so with a pragma in the file. If you’re making your own code generators, design them so that options controlling their operation go in the source files themselves rather than in command line options. That means files can be globbed up to a simple list from the file system without relying on lots of tedious settings that must be kept in sync between various build files and platforms. It also means the settings are in one place and will be correctly integrated with the file during maintenance.
Build your custom tools from source instead of relying on prebuilt binaries. This is friendlier to version control systems that don’t like binaries (git) and also helps you with cross-platform bootstrapping. The tools are also always in sync with the source files and you’ll see immediately if you broke something while changing what you thought was an unrelated file.