You have two separate issues:
How to code a C or C++ program which can easily be ported to several operating systems. The easiest way is to use some cross-platform framework library like Qt or POCO (or perhaps libsdl or GTK) which has been ported to several platforms and provides a common set of abstractions. You could also restrict yourself to purely C99 or C++11 standard conforming code -without any external non-standardized library (but then, there are many applications that you won't be able to write, see e.g. this). Notice that the POSIX specification exists (but has nothing for GUI applications!), if you follow it, your code should be able to be compiled and run on all POSIX compliant (a.k.a. Unix standard) operating systems (e.g. Linux & MacOSX & AIX, etc..., but not Windows). Otherwise, you would use conditional compilation (
#if preprocessor directive) and hopefully wrap all operating-system specific services in a few translation units (to be used by the rest of your code).
How to package & deploy a program (produced by compiling your C or C++ source code) on different operating systems. This is very OS specific, and even on Linux various distributions have different package managers: you'll have to do different things for Debian and for Redhat (and perhaps even different things for various versions of Linux distributions), since Debian has
*.deb packages installed with
dpkg but Redhat has
*.rpm packages installed with
rpm! However on Linux the FHS (filesystem hierarchy standard) is helpful since it defines where files of your software should go (but how they are installed is still distribution or package manager specific).
It might be actually simpler & wiser to develop and distribute your program as a free software in source form (e.g. on github), and to expect (advanced) users and sysadmins to install it by compiling its source code (then running some installation script which would copy the binary at specific places, e.g. under
/usr/local/bin/ and the configuration files at other specific places, e.g. under
/etc/, etc...). Eventually your free software might become packaged in most Linux distributions, and some external contributors would provide patches to enhance your code (or port it to some other operating system).
The dependency hell may always become an issue (because you might need some specific versions of specific external libraries) - and it does not depend much on the language, you could have it in Java too! -, but package managers are more or less dealing with it.
Portability (which is relative to some specification) is mostly a mindset or an ideal: A well known quote (I forgot the attributions) is "there is no portable program, there are only some programs which have been ported to some target systems" (and that is true for many programming languages, including Java).
BTW, some programs get compiled to a plain executable binary (only), other are requiring configuration files, external resources (e.g. fonts, graphic images, web or text templates, data files, script files) or dependencies. So the complexity of their deployment may vary a lot. For example, installing and deploying GNU emacs (or firefox browser) is very different -and much more complex- than installing a command line "hello world" program (which is nearly always a single executable). A graphical Qt-based "hello world" program is probably simple to install, if you assume that the target system already has the right version of Qt appropriately installed (in a usual place & configuration).
NB: notice that the C or C++ standards does not require that the implementation runs on a computer (in principle, you could unethically use a bunch of human slaves for a standard conforming C99 or C++11 implementation), and does not require a compiler. But most implementations are compiled (some few C interpreters exist however).