Kumputer
Kumputer

Reputation: 726

How to write truly cross-platform C++ libraries for distribution

The problem:

I'm writing an SDK that is primarily C++. The source code will be licensed to developers who pay for it, and the output libraries and include headers will be free for public usage. The SDK will target a plethora of platforms including Windows, Xbox, Playstation, Android, iOS, Mac OS X, and Linux. I'm a kind of guy who mostly likes Visual Studio and usually develops software using Windows machines. In the last few years, Visual Studio has made this quite a lot easier than it used to, where I have a mostly clear path to target all the previously mentioned platforms using a Visual Studio set of project files as the source of truth that brings all my source code files together... except for Mac OS X, unfortunately. Visual Studio is able to build executable code for iOS and Linux by remotely interfacing with a Mac or Linux box respectively for compilation and debugging, which is really quite cool, but for some reason Mac OS X as a target is left out here. Additionally I'm well aware that there are plenty of other professional developers out there that don't write code on Windows machines, nor do they have any interest in buying a commercial license for Visual Studio.

The question: Since C++ still does not yet have a build system standard, and may not ever, how do I maintain a single source of truth that maintains the build configurations for all my source files targeting so many different platforms while simultaneously minimizing the barrier to entry of supporting software developer clients who need to build, run, and debug my source code?

Possible answers I'm aware of:

A) Visual Studio projects remain the source of truth from which any other C++ project types (such as Android Studio, XCode, and .make files) are derived. I'm aware of tools that can convert VS to .make and the like, but haven't actually tried them yet (my source code base is starting to get somewhat large already). Or I could just bite the bullet and write them by hand and try to keep them all in sync.

B) CMake. Sigh. So frustrating that it's very popular, and seems to exactly solve my issues, but it has its own set of problems that seem to be deal-breakers. For starters, once you go in on CMake, you pretty much can't come back. Using Visual Studio and property sheets, I've been able to tweak my build configurations with properties that are mostly inherited and rarely duplicated across projects and configurations. As far as I can see, CMake doesn't care about respecting such things, and for common properties, it just duplicates them on all vcxproj files. To make matters worse, all file paths it generates in the output projects are absolute, not relative, and to top it all off, it forces anyone else who builds your code to use CMake, disallowing distribution of the project build files it creates without it. Also, does this even work for game consoles? Last I checked I couldn't find a reasonable way of supporting them without hacking the source code.

C) Roll my own script that's similar to CMake, but allows redistribution of its output projects, and supports all the platforms I need. It goes without saying that this would consume a lot of dev time.

Any other options I'm missing here? Your input is greatly appreciated.

Upvotes: 3

Views: 1032

Answers (1)

Phil
Phil

Reputation: 6174

I agree with the comments from @Scheff and @arrowd. Use CMake. I have built and deployed software to multiple platforms and CMake is the best, though not perfect, solution I have found for building C++ code.

  • I have not had to hack the cmake code to get it to work on various platforms.
  • Do not worry about properties being duplicated in vcxproj files. With CMake the build language is in the CMakeLists.txt file(s). The vcxproj files are generated code. As long as you are do not have redundant cmake logic, you should not care about replicated properties in the generated vcxproj files. Similarly, you should not care that the generated vcxproj files have absolute paths; you do not reuse the vcxproj files you reuse the CMakeLists.txt files and regenerate vcxproj files for each new platform or build.
  • Use the top-level CMakeLists.txt to define the properties that are common to all targets. Then in individual target(s) CMakeLists.txt files use target properties to tweak builds of specific targets. In my experience the replication of properties in the generated files helps because they make the builds more consistent; I am able to minimize replication in the source CMake logic.
  • Various IDEs (VS 2017, CLion, QtCreator) can use cmake based projects directly.
  • There is nothing cmake specific about the generated artifacts. The headers, libraries (and dlls), and executables of our SDK are standalone artifacts. Yes, cmake can make it easier for your SDK users but using CMake in your SDK will not force your customers to use CMake.

Have you tried CMake and not been able to use it? Or are you looking for something better? There are certainly multiple C++ build systems, but despite its shortcomings I believe CMake is the best one available right now.

Upvotes: 1

Related Questions