J'ai une bibliothèque qui dépend de jsoncpp, qui est un analyseur json écrit en C++. Pour l'instant, jsoncpp est stable et n'est pas mis à jour très souvent. Il a également été publié dans le domaine public. Maintenant, afin de construire la bibliothèque, il y a une dépendance sur SCons et Python, qui fonctionne, mais qui dérange certains de mes utilisateurs. Plutôt que de les télécharger jsoncpp, SCons, Python, puis de construire la bibliothèque eux-mêmes, je pourrais directement inclure le code dans mon projet et tout construire ensemble. Cependant, cela provoque des problèmes.Méthodes pour combiner un projet dans un autre
Principalement, si j'inclue le code jsoncpp dans ma bibliothèque, alors ma bibliothèque contient les symboles jsoncpp. Si un utilisateur essaie d'intégrer ma bibliothèque dans celle qui dépend déjà de jsoncpp, il y a un conflit de symbole. Quelle est la bonne façon de traiter ce problème? Par exemple, je pourrais compiler ma bibliothèque et jsoncpp séparément et distribuer les deux bibliothèques. Si l'utilisateur a déjà jsoncpp, ils peuvent lier leur propre version. Alternativement, je pourrais modifier le code jsoncpp et pousser tout dans un nouvel espace de nom, mais cela semble lourd.
Si ça aide, je construis tout dans CMake, donc s'il y a une astuce CMake pour gérer ça, c'est mieux.
EDIT
Basé sur la suggestion de Fraser, je donne les résultats suivants.
$ 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)
Fondamentalement, nous utilisons le script ExternalProject de CMake pour compiler et installer jsoncpp localement dans le répertoire de construction. Une fois la bibliothèque installée, nous pouvons lier nos exécutables. Puisque jsoncpp ne contient pas de CMakeLists.txt, nous utilisons la procédure de correction pour insérer un script CMake approprié dans la structure source jsoncpp. Dans un script de construction plus sophistiqué, nous pouvons choisir d'utiliser ou non cette procédure de construction ou de spécifier directement la bibliothèque à l'utilisateur.
Dans tous les cas, peut-être que quelqu'un d'autre le trouvera utile. Il simplifie la configuration de la construction pour certains utilisateurs, mais ne regroupe pas tous les symboles dans une méga bibliothèque.