The job of the linker is to give the program OS specific information so that it can execute within the framework of that OS. This is a subtle difference between the object code (raw compiled source) and the executable file. The executable contains information that the given OS needs to load and run the program. Given portable source code, you can compile a program to object code and cross OS platforms by linking to each OS separately if each OS you are linking to runs on the same hardware (specifically, the same CPU). In many of the modern compilers, the linking is done automatically within the development environment when you select "Make Executable" or equivalent option. However, it is important to understand that linking is a separate step from compiling and is necessary to make executable programs.
Modern operating systems generally provide a mechanism for dynamic linking. This is a powerful technique that is designed to both save memory and streamline the upgrade process. In dynamic linking, library code is actually executable, and main programs link to them at run-time. The means numerous programs can use the same dynamic library in memory at the same time; there need only be one copy of the library code in memory. This is in direct contrast to static linking in which the library code becomes part of each program linked to it. Further, if critical functions are placed in a dynamic library, and many programs use that library, upgrading one library will upgrade all programs that use it. However, programming to use dynamic libaries (as well as creating the libraries themselves) is bit more complicated than using static libraries; like many engineering problems, software development is series of trade-offs.