Build a boost project using cmake in msvc - c++

I have written a code to read a compressed file directly. I have to build it using Cmake. This is my only source file, uncompress.cpp
#include <iostream>
#include <vector>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
// cl /EHsc uncompress.cpp
std::vector<char> & readline(std::istream & stream, std::vector<char> & container) {
char c;
container.clear();
while (stream && stream.get(c)) {
container.push_back(c);
if (c == '\n') break;
}
return container;
}
int main () {
boost::iostreams::filtering_istream in;
boost::iostreams::filtering_istream cinn(std::cin);
in.push(boost::iostreams::bzip2_decompressor());
in.push(cinn);
std::vector<char> line;
while (readline(in, line).size() != 0) {
std::string str(line.begin(), line.end());
std::cout << "--" << str ;
}
}
My CMakeLists.txt includes
cmake_minimum_required (VERSION 2.8.9)
project (reader-demo CXX C)
find_package (Boost COMPONENTS iostreams zlib REQUIRED)
include_directories (${Boost_INCLUDE_DIR} )
add_executable(reader uncompress.cpp)
target_link_libraries(reader ${Boost_LIBRARIES})
my cmake command is:
cmake -G "NMake Makefiles" .
This throws the error boost_zlib not found during cmake
Could not find the following Boost libraries:
boost_zlib
I have the following zlib library built into all paths are set properly:
NOTE if I change the CMakeLists.txt to this. it works fine. But I can't understand how :/
cmake_minimum_required (VERSION 2.8.9)
project (reader-demo CXX C)
add_executable(reader uncompress.cpp)
it works fine as expected. reader.exe is make and that works fine.
My question is: why is it not able to find boost_zlib the time I mention it in cmake and why is it working fine when I remove the target_link_libraries().

Expanding my comments to an answer:
zlib is not a registered Boost component although the Boost build process for boost_iostreams lib generates a boost_zlib and boost_bzip2 library. Both are internally generated and linked to. The CMake module FindBoost.cmake that is called when you add find_package(Boost COMPONENTS iostreams zlib REQUIRED) to your CMakeLists.txt file does not know about these libraries.
To answer the first part of the question:
remove zlib from your find_package call.
After doing so delete the CMakeCache.txt file because the values of a Boost search are cached in CMake.
To answer the second part of the question:
You removed the Boost stuff from the CMakeLists.txt but presumably did not delete the CMakeCache.txt. It might still contain the necessary Boost entries for the compiler/linker and that may be the reason why it works in the second call.
The libraries you showed in the image are the (multithreaded) static libraries and the import libraries for the DLLs.
To use the static libraries
you need to add set(Boost_USE_STATIC_LIBS ON) to your CMakeLists.txt file before calling find_package(Boost ...).
To use the Shared Objects (SO)/Dynamic Link Libraries (DLL)
you don't need to add anything to your CMakeLists.txt file before calling find_package(Boost ...), as dynamic link libraries are chosen by default. But to run the executable the directory that contains the DLLs must be added to the PATH environment variable.
NB:
Please remove the call to include_directories(${Boost_INCLUDE_DIR}) and add after the definition of your target
add_executable(reader uncompress)
target_include_directories(reader PRIVATE ${Boost_INCLUDE_DIRS})
Note the trailing S in the variable name. This variable is assigned a value in the find_package(Boost ..) call, the other variable is used to look up the include directory of Boost and is an input to the FindBoost module. Doing so you add the include directories to the target only but not to the global environment.
Finally you should add -DBOOST_ROOT=<path_to_your_Boost_installation> to your CMake command line call to make sure Boost is found regardless of a non standard installation directory.
For extended information about find_package(Boost ...) please see the documentation

Related

Facing problems in my first time handling CMake, Third party(header only) libraries

I want to use the following library
https://github.com/gmeuli/caterpillar
It's documentation says that it's a header-only library, and that I should "directly integrate it into my source files with #include <caterpillar/caterpillar.h>." It also depends on a few other libraries, one of which I need to use directly as well.
So far I have done the following:
create cmake project to make an 'executable' (with the vscode extension)
created a 'lib' folder, inside which I did
git clone https://github.com/gmeuli/caterpillar
Then, I did include_directories(lib) in my cmake file.
But #include <caterpillar/caterpillar.h> doesn't quite work in my singular main.cpp file.
I played around with various CMake functions, and it either gave the error "No such file or directory" regarding caterpillar/caterpillar.h itself, or it gave "cannot open source file... dependent of caterpillar/caterpillar.h" depending on how I messed with the cmake file.
For reference:
cat ~/project/main.cpp
#include <caterpillar/caterpillar.hpp>
#include <lorina/lorina.hpp> //how do I include this ? it's in the lib folder of caterpillar itself, or do I need to have a copy of it in my lib folder too
int main()
{
// stuff in lorina:: namespace
// stuff in caterpillar:: namespace
return 0;
}
cat ~/project/CMakeLists.txt
include_directories(lib)
//... rest is stuff like CXX standard, etc etc
tree ~/project
main.cpp
lib/
caterpillar/
build/
cmake generated stuff
CMakeLists.txt
Firstly, modern cmake recommends target_include_directories() instead of old include_directories() for better scope management.
Actually <caterpillar/caterpillar.hpp> is not in $PROJECT_SOURCE_DIR/lib directory. That's why your code not works.
CMakeLists example:
cmake_minimum_required(VERSION 3.22)
project(myproject)
set(CMAKE_CXX_STANDARD 17)
add_executable(my_project main.cpp)
target_include_directories(my_project PRIVATE ${PROJECT_SOURCE_DIR}/lib/caterpillar/include)
# project_src_dir/lib/catepillar/include/ is the directory where you find the headers like <catepillar/catepillar.hpp>
target_include_directories(my_project PRIVATE ${PROJECT_SOURCE_DIR}/lib/caterpillar/lib/lorina)
caterpillar's document describes how to include their headers in a traditional style, assuming the readers could understand this and decide where to put the headers themselves. (which means you don't need the whole git repo but only the "include" dir.)
For this specific problem, the library has provided a detailed CMakeLists.txt for users to include:
cmake_minimum_required(VERSION 3.22)
project(my_project)
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(lib/caterpillar)
# this works because "project_src_dir/lib/catepillar/CMakeLists.txt" exists.
add_executable(my_project main.cpp)
target_link_libraries(my_project PRIVATE caterpillar)
# you need to tell cmake to add all catepillar settings into your project

CMake project in Visual Studio: How to add additional include and library directories?

I am developing C++ code using VisualStudio 2019.
I am using CMake to configure the project.
I need to use boost library which is compiled on my remote machine.
In console application, I can put the path of the include files I need when I go to the Properties of the project under Additional Include Directories field.
And under Additional Include Directories I can put the path of boost library.
Now I can not find Properties when I right-click on my project to add what I need.
My boost include directory is under /home/ubuntu/boost_1_70_0
My boost libraries directory is under /home/ubuntu/boost_1_70_0/stage
How can add them in my CMake project?
Thank you!
EDIT:
This is my CMakelists.txt file:
# CMakeList.txt : CMake project for CMakeProject1, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
# Add source to this project's executable.
add_executable (CMakeProject1 "CMakeProject1.cpp" "CMakeProject1.h")
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.70.0 REQUIRED COMPONENTS lambda)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(CMakeProject1 CMakeProject1.cpp)
target_link_libraries(CMakeProject1 ${Boost_LIBRARIES})
endif()
# TODO: Add tests and install targets if needed.
And this is my .cpp file:
#include "CMakeProject1.h"
#include <iostream>
#include <iterator>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
using namespace std;
int main()
{
typedef std::istream_iterator<int> in;
std::cout << "Type in any number: ";
std::for_each(
in(std::cin), in(), std::cout
<< (boost::lambda::_1 * 10)
<< "\nType in another number: ");
}
The path of my boost directory is: /home/ubuntu/boost_1_70_0
The path of my boost libraries is: /home/ubuntu/boost_1_70_0/stage
When I run the .cpp file this CMake error occurs:
Error CMake Error at CMakeProject1/CMakeLists.txt:13 (find_package):
Could not find a package configuration file provided by "Boost"
(requested version 1.70.0) with any of the following names:
BoostConfig.cmake
boost-config.cmake
Add the installation prefix of "Boost" to CMAKE_PREFIX_PATH or set
"Boost_DIR" to a directory containing one of the above files. If
"Boost" provides a separate development package or SDK, be sure it
has been installed.
CMake's find_package command has two modes: Module and Config mode. Many related questions on this site feature answers that are using Module mode. However, Boost 1.70 and greater provides a BoostConfig.cmake or boost-config.cmake package configuration file to easily use with find_package() Config mode. The package configuration file should be generated when you build Boost. For example, if you build Boost 1.72 into the stage directory, the BoostConfig.cmake file is located here:
boost_1_72_0/stage/lib/cmake/Boost-1.72.0/BoostConfig.cmake
Your error indicates that you are using Config mode, so you have two options:
Option 1
Do the steps recommended in the error message to help the Config mode package search complete successfully. Append the path to your Boost installation to the prefix path by adding this line to your CMake file before find_package():
list(APPEND CMAKE_PREFIX_PATH /home/ubuntu/boost_1_70_0)
Option 2
Force Module mode by setting the Boost_NO_BOOST_CMAKE variable before the call to find_package():
set(Boost_NO_BOOST_CMAKE ON)

Setup Boost in Clion

How to use Boost library in Clion with MinGW ? I have downloaded and unzipped boost_1_60_0.zip to C:\boost_1_60_0. What am I supposed to do now ? Do I have to install something ? Here is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.3)
project(server_client)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s -O3")
set(CMAKE_EXE_LINKER_FLAGS -static)
set(BOOST_ROOT "C:/boost_1_60_0")
set(BOOSTROOT "C:/boost_1_60_0")
find_package(Boost 1.60.0)
if(NOT Boost_FOUND)
message(FATAL_ERROR "Could not find boost!")
endif()
set(SOURCE_FILES chat_server.cpp)
add_executable(server_client ${SOURCE_FILES})
Can not find Boost:
I use MinGW distro by Stephan T. Lavavej with Boost libraries prebuilt.
In my cmaklist.txt I added this
set(Boost_INCLUDE_DIR c:/mingw/include/)
set(Boost_LIBRARY_DIR c:/mingw/lib/)
find_package(Boost COMPONENTS system filesystem REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
This post help me get it going. How to include external library (boost) into CLion C++ project with CMake?
Here's example project for CLion that uses Boost's regex library. It references to this tutorial.
Goal: with CLion create .exe that process jayne.txt as shown in Boost's tutorial.
My example revolves around building Boost Library Binary with GCC, configuring project in CLion and using CMake. It's quite expressive, maybe even an overkill, but I believe you can adapt. On the other hand I'll try to make project itself as system independent as its possible.
Configuration:
OS: Windows 8.1
CLion: 2018.2.4
Boost: 1.68.0
compiler: GCC-6.3.0 (provided by MinGW)
MinGW was configured according to its instructions and JetBrains's suggestions. (I downloaded setup for MinGW 14/10/2018 if that matters.)
A word about tools structure
I decided to create following structure for Boost and things aroung it:
D:\
SDK\
boost\
boost_1_68_0\ # untouched Boost root
boost\
rst.css
...other directories and files...
1_68_0\
build\ # dir for Boost.Build, b2.exe
buildDir\ # intermediate dir for creating libraries
stageDir\ # dir for libraries
lib\
MinGW\
bin\
...other directories...
I left Boost root untouched -- I didn't create any additional directories. This separates Boost sources from created tools and libraries so I can show how to specify these directories explicitly.
Obtain Boost Library Binary
I decided to build libraries from source with GCC.
Download and unpack Boost ("D:\SDK\boost\boost_1_68_0");
Build libraries (5.2):
Open command prompt at \tools\build of Boost root ("D:\SDK\boost\boost_1_68_0\tools\build")
Run bootstrap.bat
Run b2 install --prefix="D:\SDK\boost\1_68_0\build" --toolset=gcc-6.3.0. This creates b2.exe under "D:\SDK\boost\1_68_0\build\bin"
Move command prompt to Boost root (cd "D:\SDK\boost\boost_1_68_0")
(You can consider using "D:\SDK\boost\1_68_0\build\bin\b2.exe --show-directories". It's worth to specify libraries to build (--with-library-name) in the following command, because this step can take a while.) Run "D:\SDK\boost\1_68_0\build\bin\b2" --build-dir="D:\SDK\boost\1_68_0\buildDir" toolset=gcc-6.3.0 --build-type=complete stage --stagedir="D:\SDK\boost\1_68_0\stageDir" --with-regex. It creates following files under D:\SDK\boost\1_68_0\stageDir\lib directory:
libboost_regex-mgw63-mt-d-x32-1_68.a
libboost_regex-mgw63-mt-d-x32-1_68.dll
libboost_regex-mgw63-mt-d-x32-1_68.dll.a
libboost_regex-mgw63-mt-sd-x32-1_68.a
libboost_regex-mgw63-mt-s-x32-1_68.a
libboost_regex-mgw63-mt-x32-1_68.a
libboost_regex-mgw63-mt-x32-1_68.dll
libboost_regex-mgw63-mt-x32-1_68.dll.a
CMake looks for files with specific names in library folder, so be sure to (copy and) change name for one of .a files there. For this example, I changed libboost_regex-mgw63-mt-x32-1_68.a to boost_regex.a.
Create CLion project
Create a new project (for this example its name is CLionBoostRegex) and put content to main.cpp (6):
#include <boost/regex.hpp>
#include <iostream>
#include <string>
int main()
{
std::string line;
boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );
while (std::cin)
{
std::getline(std::cin, line);
boost::smatch matches;
if (boost::regex_match(line, matches, pat))
std::cout << matches[2] << std::endl;
}
}
Configure CLion
Go to (on Windows) File -> Settings -> Build, Execution, Deployment -> CMake, and in CMake options add path to Boost root directory with -DBOOST_ROOT=, i.e.: -DBOOST_ROOT="D:\SDK\boost\boost_1_68_0". If directory with built libraries is placed outside Boost root, add it with -DBOOST_LIBRARYDIR=, i.e.: -DBOOST_LIBRARYDIR="D:\SDK\boost\1_68_0\stageDir\lib". Commands are space separated.
Decide if you want static or dynamic linking.
Option 1: Static linking
For static linking your CMakeLists.txt should look like this:
cmake_minimum_required(VERSION 3.12)
project(CLionBoostRegex)
set(CMAKE_CXX_STANDARD 98)
find_package(Boost REQUIRED COMPONENTS regex)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(CLionBoostRegex main.cpp)
target_link_libraries(CLionBoostRegex -static)
target_link_libraries(CLionBoostRegex ${Boost_LIBRARIES})
Option 2: Dynamic linking
CMakeLists.txt should look like for static linking, but remove target_link_libraries(CLionBoostRegex -static) line.
After building your project make sure to copy .dll library to directory with executable (libboost_regex-mgw63-mt-x32-1_68.dll) along with libstdc++-6.dll from MinGW\bin directory (D:\SDK\MinGW\bin) (or consider including target_link_libraries(CLionBoostRegex -static-libstdc++) line in CMakeLists.txt or add -DCMAKE_CXX_FLAGS="-static-libstdc++" to CMake options in settings).
Run your program (6.4)
Build your target (it creates cmake-build-debug\ directory with default config) (if you picked dynamic linking make sure to add necessary .dlls)
In directory with your executable create jayne.txt file with following content:
To: George Shmidlap
From: Rita Marlowe
Subject: Will Success Spoil Rock Hunter?
---
See subject.
Open command prompt there
Run CLionBoostRegex.exe < jayne.txt
Program should output Will Success Spoil Rock Hunter? as shown in tutorial.
Notes
Changing name for an .a library and choosing -static linking causes the least effort afterwards - you won't have to copy any additional libraries at the price of bigger executable size. When executable size is more important, you can change name for .dll library in Boost libraries directory instead and then copy missing .dlls for your .exe (i.e.: libboost_regex-mgw63-mt-x32-1_68.dll and libstdc++-6.dll).
You can include set(Boost_DEBUG ON) line in your CMakeLists.txt or -DBoost_DEBUG=1 to CMake options to get some precious info.
I used other questions to write this post, most notably: 1, 2, 3, 4.

How to tell CMake to use during compilation specific version of Qt?

There are two versions of Qt installed on my Ubuntu - 5.2 (default) and 5.4 (in /opt/Qt/5.4/gcc_64):
CMakeLists.txt:
project(testproject)
find_package(Qt5Core HINTS /opt/Qt/5.4/gcc_64 REQUIRED)
add_executable(main main.cpp)
target_link_libraries(main Qt5::Core)
main.cpp:
#include <QDebug>
int main()
{
qDebug() << "runtime version: " << qVersion() << " compiled with: " << QT_VERSION_STR << endl;
return 0;
}
Running the program:
cmake . && make clean && make && LD_LIBRARY_PATH=/opt/Qt/5.4/gcc_64/lib ./main
Output:
runtime version: 5.4.0 compiled with: 5.2.1
How to tell inside CMake to use Qt 5.4 instead of default Qt 5.2? I've tried several options for HINTS in find_package but none of them looks to work.
I took a look through the CMake files generated by an installation of Qt5, and no where in those files are hints being ingested from the caller. These CMake files all use relative paths once one of them is picked up.
That is, if you're looking for the core library, then all of the dependencies that version of the core library will be the correct version. So the goal is to get it to pick the right CMake module when you call find_package, and there are a couple of ways to do that using CMake level hints.
Export CMAKE_PREFIX_PATH
You can set the prefix path to the base directory your Qt is installed to. The base directory is the directory containing lib/ and bin/. In your case, this might be something like this:
export CMAKE_PREFIX_PATH=/opt/Qt/5.4/gcc_64:$CMAKE_PREFIX_PATH
and then from the same shell session run your cmake commands.
Set Qt5Core_DIR in your CMakeLists.txt
This requires setting a variable that points to the right CMake root module you want your Qt to be found from:
set(Qt5Core_DIR /opt/Qt/5.4/gcc_64/lib/cmake/Qt5Core)
find_package(Qt5Core REQUIRED)
Of course, the issue with this is that if you wanted to find another module, you'd have to set the specific Qt5<MODULE>_DIR variable before your find_package call.

Methods to combine one project into another

I have a library that depends on jsoncpp, which is a json parser written in C++. At the moment, jsoncpp is stable and not updated very often. It also has been released into the public domain. Now, in order to build the library, there's a dependency on SCons and Python, which works, but is an annoyance to some of my users. Rather than have them download jsoncpp, SCons, Python, and then build the library themselves, I could include the code into my project directly and build everything together. However, this causes some problems.
Primarily, if I include the jsoncpp code into my library, then my library contains the jsoncpp symbols. If a user tries to embed my library into one that already depends on jsoncpp, there's a symbol conflict. What's the correct way to deal with this issue? For example, I could compile my library and jsoncpp separately and distribute both libraries. If the user already has jsoncpp, they could link their own version. Alternatively, I could modify the jsoncpp code and push everything into a new namespace, but this seems cumbersome.
If it helps, I build everything in CMake, so if there's a CMake trick for dealing with this, that's best.
EDIT
Based on Fraser's suggestion, I have the following.
$ find .
.
./build
./build/jsoncpp-src-0.6.0-rc2.tar.gz
./src
./src/cpp
./src/cpp/hello.cpp
./src/cpp/CMakeLists.txt
./src/thirdparty
./src/thirdparty/jsoncpp
./src/thirdparty/jsoncpp/CMakeLists.txt
./src/thirdparty/CMakeLists.txt
./src/CMakeLists.txt
$ cat ./src/cpp/hello.cpp
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <iomanip>
#include "json/json.h"
// Parses a JSON file and returns the root
void parse(const std::string& fname,Json::Value& root) {
// Read in the input file
Json::Reader reader;
std::ifstream file(fname.c_str(),std::ifstream::in);
bool parsingSuccessful = reader.parse( file, root, true );
if (!parsingSuccessful) {
std::cerr << "Failed to parse the optimization parameter "
"file: " << reader.getFormattedErrorMessages() << std::endl;
exit(EXIT_FAILURE);
}
// Close everything out
file.close();
}
int main(int argc,char* argv[]) {
// Make sure we have the correct number of arguments
if(argc!=2) {
std::cout << "hello <json>" << std::endl;
return EXIT_FAILURE;
}
// Parse the JSON files
Json::Value root;
parse(argv[1],root);
// Get the hello string
std::string hello = root["Hello"].get("Message","Hello World!").asString();
// Tell everyone
std::cout << hello << std::endl;
return EXIT_SUCCESS;
}
$ cat ./src/cpp/CMakeLists.txt
project(hello)
cmake_minimum_required(VERSION 2.8.9)
enable_language(CXX)
# Set the location of jsoncpp
find_library(JSONCPP_LIBRARY
NAMES json libjson
PATHS ${CMAKE_BINARY_DIR}/installed/lib)
set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY} )
set(JSONCPP_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/installed/include)
# Locate the headers
include_directories(${JSONCPP_INCLUDE_DIRS})
# Build the executable
add_executable(hello hello.cpp)
# Link jsoncpp
target_link_libraries(hello ${JSONCPP_LIBRARIES})
$ cat ./src/thirdparty/jsoncpp/CMakeLists.txt
project(jsoncpp)
cmake_minimum_required(VERSION 2.8.9)
enable_language(CXX)
# Set the source file prefix
set(source_prefix ${CMAKE_CURRENT_SOURCE_DIR}/src/lib_json/)
# Save the include directory
set(JSONCPP_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIRI}/include)
# Grab all the sources for the library
set(jsoncpp_srcs
"${source_prefix}/json_reader.cpp"
"${source_prefix}/json_value.cpp"
"${source_prefix}/json_writer.cpp"
)
# Locate the headers
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Compile everything
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_library(jsoncpp_object OBJECT ${jsoncpp_srcs})
add_library(jsoncpp_static STATIC $<TARGET_OBJECTS:jsoncpp_object> )
add_library(jsoncpp_shared SHARED $<TARGET_OBJECTS:jsoncpp_object> )
set_target_properties(jsoncpp_shared jsoncpp_static
PROPERTIES OUTPUT_NAME json)
# Install the libraries and headers
install(TARGETS jsoncpp_static jsoncpp_shared DESTINATION lib)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/json DESTINATION include)
$ cat ./src/thirdparty/CMakeLists.txt
project(third_party_libraries)
cmake_minimum_required(VERSION 2.8.9)
# Build jsoncpp
include(ExternalProject)
ExternalProject_Add(
JsonCpp
URL ${CMAKE_BINARY_DIR}/jsoncpp-src-0.6.0-rc2.tar.gz
URL_MD5 363e2f4cbd3aeb63bf4e571f377400fb
PATCH_COMMAND ${CMAKE_COMMAND} -E copy
"${CMAKE_CURRENT_SOURCE_DIR}/jsoncpp/CMakeLists.txt"
CMakeLists.txt
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/installed
)
$ cat ./src/CMakeLists.txt
project(hello_example)
cmake_minimum_required(VERSION 2.8.9)
# First, build our TPLs
add_subdirectory(thirdparty)
# Then, build our target
add_subdirectory(cpp)
Basically, we use CMake's ExternalProject script in order to compile and install jsoncpp locally to the build directory. Once the library has been installed, we can link our executables to it. Since jsoncpp doesn't contain a CMakeLists.txt, we use the patch procedure to insert an appropriate CMake script into the jsoncpp source structure. In a fancier build script, we could choose whether or not to use this build procedure or have he user specify the library directly.
In any case, perhaps someone else will find this useful. It simplifies the build setup for some users, but doesn't bundle all of the symbols into some mega library.
If you want to try and keep all the users happy (I know - not possible!), you could add an option for each dependency, e.g. option(BuildJsonCpp).
If the option is ON, you build the dependency, otherwise you include it using find_library and find_path or find_package.
For building the dependencies, rather than including the sources, you could consider the ExternalProject CMake module. This module is used to download, configure, build and install external projects, and allows the external project to be contained entirely in your build tree - not your source tree.
This would allow you to keep just your own source files in your project, making it smaller and more relevant - especially for users not wishing to build the dependencies.
It will make your CMake files a bit more complex and harder to maintain, but I guess that's the price you have to pay if you want to make the build system more flexible.