0
\$\begingroup\$

The question's description will evolve depending on requested information or evolution of answers.

I made this C++ server for a game, which works on Windows, and would like to make it cross-platform, so it at least works on Linux (Ubuntu), macOS would be a plus i'd really appreciate, but not indispensably necessary (specially if single "cross-platform executable" isn't a possibility).

The server was programmed using VisualStudio IDE. These are all my source files I copied to another directory, including a custom static library (this one is in the same directory, the rest are all in C:/libraries):

enter image description here

Project dependencies are the following as configured in VisualStudio:

enter image description here

enter image description here

enter image description here

enter image description here

All libraries are to be linked statically. These are the ones my server uses:

  • GLM: Header only, cross platform.
  • Cereal: Header only, cross platform.
  • SFML modules: Can be linked statically. Cross platform according to them, even though this surprises me, since, for example, sfml_network module depends on winsock, which is a windows library...
  • MORPH_Shared_functions, My own library: Is static. It's own dependencies are the same as already listed for server, so I'm asuming that would make it cross-platform.

The entire server fits in a single executable without dynamic library dependencies. I tried moving the exe to another computer, and it works fine without the libraries installed in the system since they're merged into the executable.

According to the first answer I got, Every platform should be considered separately. So I'm focusing on Linux/Ubuntu first:

- Progress 1:

Begining with Ubuntu, I tried the g++ compiler for windows. I installed it on windows by installing MinGW, and now I can use it from windows's cmd. I tried following this nice and simple guide: https://courses.cs.washington.edu/courses/cse373/99au/unix/g++.html

From what I read, I understand a propper approach would be first compiling each .cpp individually, so I made myself a list of commands:

g++ -c -o Game.o Game.cpp
g++ -c -o CommandManager.o CommandManager.cpp
g++ -c -o ServerPlayer.o ServerPlayer.cpp
g++ -c -o ServerProp.o ServerProp.cpp
g++ -c -o ServerWorldState.o ServerWorldState.cpp
g++ -c -o UDP_Server_CS.o UDP_Server_CS.cpp

then I would do something like:

g++ 
-Wall 
-o MORPH_Server 
-Xpreprocessor SFML_STATIC 
-I MORPH_Shared_Functions 
-I C:\libraries\SFML\SFML-2.5.1\include 
-I C:\libraries\GLM\glm 
-I C:\libraries\CEREAL 
-L C:\libraries\SFML\SFML-2.5.1\extlibs\libs-msvc\x64 
-L C:\libraries\SFML\SFMLx64SourceAndCompile\lib\Debug 
-l MORPH_Shared_Functions.lib 
-l winmm.lib 
-l ws2_32.lib 
-l sfml-system-s-d.lib 
-l sfml-network-s-d.lib 
Main.o Game.o CommandManager.o ServerPlayer.o ServerProp.o ServerWorldState.o 
UDP_Server_CS.o

In order to link them all together

However, the first individual module compilation attempt (Game.cpp) results in a header from my custom shared library not being found with error:

In file included from Game.h:2:0,
                 from Game.cpp:1:
UDP_Server_CS.h:1:33: fatal error: udp_network_manager.h: No such file or 
directory
 #include "udp_network_manager.h"

I really don't know if I should link all libraries for each compiled module, so for now I at least tried:

g++ -c -o Game.o -lMORPH_Shared_Functions.lib Game.cpp

In order to point to my shared library, hopefully helping with pointing to it's header, but this returns the same error.

I imagine if I continued with this approach (which works for ubuntu, and no other OS's I know of), I'd first try to get the commands right for compiling, and then I could try making visual studio compile with CMake using that same commands, or something like that. I don't know too much about cmake, I only used it for compiling some libraries like sfml a few times.

Note: I already did a similar question some weeks ago (How to remotely host my c++ game server on Ubuntu?). This one is based on the same objective, but with more specifics on the case, and some actual strategies already developed. In general I'm still looking for advice, ideas, and even specific guides.

\$\endgroup\$
  • 3
    \$\begingroup\$ There's no such thing as a single cross-platform executable, unless you use something like WINE or WSL. You need to build on each of your target platforms, and - more importantly - you need to test on each of your target platforms. \$\endgroup\$ – Maximus Minimus Aug 2 at 11:14
  • \$\begingroup\$ Good to know. I guess I can focus on treating this per-platform. \$\endgroup\$ – Mithrandir Aug 2 at 12:11
  • \$\begingroup\$ One important thing to note is that .lib files are Windows static libraries. They won't run on Ubuntu (or any other OS that is not Windows). Since Ubuntu is a Linux distro, you'll need the static libraries for SFML for Linux (typically ending in .a), either by downloading them from the SFML source or building them yourself. \$\endgroup\$ – Rish Aug 3 at 22:32
  • \$\begingroup\$ Ah yes, nearly forgot I saw there where platform specific sfml versions. So that also means my own .lib won't work there either, I'll need to figure out how to compile it as a static library with g++? \$\endgroup\$ – Mithrandir Aug 4 at 1:08
  • \$\begingroup\$ Although you are developing a game, the core infrastructure of how to build a software for multiple platforms is not gamedev specific, and is considered off-topic here. If you have questions specific to using these libraries, those question could be on topic here. \$\endgroup\$ – Vaillancourt Aug 5 at 13:38
0
\$\begingroup\$

As someone with some cross-platform experience, my advice would be to put everything aside for 1 or 2 days and start learning the basics of CMake. CMake is a cross-platform build system generator that performs a lot of tedious tasks for you like finding your libraries, sorting out dependencies (to some degree) and setting up the compiler and linker. Once you have wrapped your program into a CMake structure, you can generate Visual Studio project files or Linux Makefiles automatically and all that remains is to call the corresponding build command (make, ninja, etc.) - assuming all dependencies are found.

You can also include other CMake projects into your own project so that they get built together. Don't know if there is a general description for that, but in the Google Test documentation they describe several ways to include their library to other CMake projects. Guess that does work for other libraries like SFML too. Of course, you can also build SFML separately, install it and then let CMake find it.

According to the first answer I got, Every platform should be considered separately.

The advantage of using CMake would be that most of the platform-specific setup is done by it. As long as all your libraries are cross-platform and can be found by CMake (if not, you have to point it to the directory), there is not much else to do for you.

So here is how I think you should approach this:

  • learn (modern) CMake
  • wrap your project into a CMake structure
  • get it running on Windows first! Generate the projects build files with CMake and compile them from the command line, not from VisualStudio
  • Once it runs, try to do the same with Linux and/or Mac

The reason why you should start with Windows is that you got everything already set up and know that it can be built in the current environment. The reason why I suggest avoiding Visual Studio with CMake is that this adds another layer where something can go wrong. Focus on getting a working CMake build on Windows. Once that is achieved you can try to integrate it into VS.

As soon as is runs on Windows, getting it to run on Linux/Ubuntu should be a lot easier. Just install all your dependencies (sudo apt-get install INSERT_DEPENDENCIES, build and install SFML) and CMake will usually find them automatically.

Some further remarks

Take your time with CMake and especially look for tutorials on modern "target-based" CMake approaches. This link should give you an overview of what modern CMake is about. You probably need to read some material before if you want to understand what he is talking about. However, if you follow these guidelines writing cross-platform code gets as easy as it can be.

If you are using GitHub and once you get everything running, you might also think about adding some GitHub actions to your repository that build your library on all supported systems with all supported compilers every time you make a commit. This will give you early feedback if the new code does break cross-platform compatibility. Gitlab has something similar, but I don't know how it is called there. ;)

SFML modules: Can be linked statically. Cross platform according to them, even though this surprises me, since, for example, sfml_network module depends on winsock, which is a windows library...

It only depends on Winsock in windows. They most certainly have written platform-specific code with its own dependencies for every supported operating system. So on Ubuntu, you will have a Linux specific dependency instead.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you! This certainly looks like good guidelines to follow. \$\endgroup\$ – Mithrandir Aug 4 at 11:35

Not the answer you're looking for? Browse other questions tagged or ask your own question.