I am in the process of reorganizing the physical (on disk) layout of a large cross-platform C++ project with many third party dependencies, built using CMake.
Since we need to support Windows, a platform on which there is no well-established package manager, we decided a long time ago to include the third party libraries we rely on in the source tree. However, on the other platforms we support such as Linux and Mac OS X, many of these third party libraries are available as packages or are already present in the system and are easily found by CMake.
The current project layout is as follow:
root/
src/
3rd-party-lib1/ (build system modified to output to build/)
3rd-party-lib2/ (build system modified to output to build/)
project-module1/ (our own code)
project-module2/ (our own code)
build/ (CMake is invoked from here)
3rd-party-lib1-bin/
3rd-party-lib2-bin/
The third party libraries have been tweaked so that when built, they output their binaries to root/build/<lib>/
.
The problems with this layout are multiple:
- The third party libraries are no longer 100% original. This makes updating them slightly more difficult than required.
- The
src/
directory contains a mixture of our own code and third party code, which is confusing. - The
src/
directory is very large. Becausesrc/
contains third party libraries, it is very large compared to the actual amount of original source code, making backuping our own code slightly more complicated than required (we can't just archive the wholesrc/
directory anymore). - The project repository (Git) is very large, due to the inclusion of the third party libraries (which may contains lots of non-source files such as documentation, test data etc.), and it gets larger each time we update them. Unfortunately there is no way back here, unless we decide to restart with a fresh repository (unfortunately loosing the entire commit history).
- Many of those included third party libraries (e.g. zlib, libpng) are not needed at all by users building the project on Linux or Mac OS X, although they greatly simplify things for Windows users.
An alternative layout would be as follow:
root/
3rdparty/
3rd-party-lib1/ (100% original, contains built artifacts)
3rd-party-lib2/ (100% original, contains built artifacts)
src/
project-module1/ (our own code)
project-module2/ (our own code)
build/ (CMake is invoked from here)
Our CMake files would need to be modified to look for third party header files and libraries in the right place for each library.
What are the best practices regarding the handling of third party libraries in native, cross platform projects? Which layout would lead to the most unsurprising build experience for our developers on their respective platforms? Concrete examples of successful layouts from existing projects are also welcome.