Rule #2: Factor out the GUI into non-reusable code then develop a cross-platform library for the underlying logic
Some engineers think Cross-Platform means least common denominator programs or possibly bad port that doesnt embrace the beauty of my favorite platform. Not true! You should NEVER sacrifice a single bit of quality or platform specific beauty! What were shooting for is the maximum re-use of code WITHOUT sacrificing any of the end user experience. Towards that end, the least re-useable code in most software programs is the GUI. Specifically the buttons, menus, popup dialogs or slide down panes, etc. On Windows the GUI is probably in a .rc Windows specific resource file laid out by the Visual Studio dialog editor. On the Mac the GUI is typically stored in an Apple specific .xib laid out by Apples Interface Builder. Its important to embrace the local tools for editing the GUI and just admit these are going to be re-implemented completely from scratch, possibly even with some layout changes. Luckily, these are also the EASIEST part of most applications and done by dragging and dropping buttons in a GUI builder.
But other than the GUI drawing and layout step that does not share any code, much of the underlying logic CAN be shared. Take Backblaze as a concrete example. Both the Mac and PC have a button that says Pause Backup which is intended to temporarily pause any backup that is occurring. On the Mac the Pause Backup button lives in an Apple Preference Pane under System Preferences. On Windows the button lives in a dialog launched from the Microsoft System Tray. But on BOTH PLATFORMS they call the same line of code -> BzUiUtil:

auseBackup(); The BzUiUtil class and all of the functions in it are shared between the two implementations because those can be cross platform; both platforms want to stop all the same processes and functions and pause the backup.
Furthermore, if at all possible you should factor the GUI code all the way out into its own stand-alone process. In Backblazes case, the GUI process (called bzbui) reads and writes a few XML files out to the filesystem instructing the rest of the system how to behave, for example which directories to exclude from backup. There is a completely separate process called bztransmit that has no GUI (and therefore can be much more cross-platform) which reads the XML configuration files left by the bzbui GUI process and knows not to transmit the directories excluded from backup. It turns out having a process with no GUI is a really good feature for a low level service such as online backup, because it allows the backups to continue when the user is logged out (and therefore no GUI is authorized to run).
Finally, notice that this design is really EASY (and solid, and has additional benefits) but only if you think about cross platform from the very beginning of a project. It is much more difficult if we ignore the cross platform design issues at first and allow the code to be peppered randomly with platform specific GUI code.