【问题标题】:how to write a cmake Module for jsoncpp?如何为 jsoncpp 编写一个 cmake 模块?
【发布时间】:2013-08-03 01:46:36
【问题描述】:

我想使用 jsoncpp 编写 C++ 代码以解析 JSON 文件。让我解释一下我做了什么。我创建了一个 CMakeLists.txt 并创建了一个 FindJsoncpp.cmake 以及一个简单的 c++ 文件来测试jsoncpp。当我使用 -I/usr/include/jsoncpp/ -ljsoncpp 编译没有 cmake 的 C++ 源代码时,它工作正常。但是当我尝试使用 cmake 构建它时,它找不到我包含在我的 c++ 源代码中的 json.h 头文件。

这是我的CMakeLists.txt

cmake_minimum_required (VERSION 2.6)
project (Parser)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

include(LibFindMacros)

message("----------- trying to find Jsoncpp-------------")
find_package(Jsoncpp)

if(Jsoncpp_FOUND)
    message("INFO: we found LibJsoncpp on your pc.")
    message(Jsoncpp_FOUND = ${Jsoncpp_FOUND})
    message(Jsoncpp_INCLUDE_DIR = ${Jsoncpp_INCLUDE_DIR}) 
    message(Jsoncpp_LIBRARY = ${Jsoncpp_LIBRARY})
else(Jsoncpp_FOUND)
    message("WARNING: we couldn't find LibJsoncpp on your pc. DLC is disabled.")
endif(Jsoncpp_FOUND)

#set(LIBS ${Jsoncpp_LIBRARY})

# Set the include dir variables and the libraries and let libfind_process do the rest.
# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
set(Jsoncpp_PROCESS_INCLUDES Jsoncpp_INCLUDE_DIR)
set(Jsoncpp_PROCESS_LIBS Jsoncpp_LIBRARY)

# add the executable
add_executable(jsonparser jsonparser.cpp)

这是我写的FindJsoncpp.cmake

# - Try to find Jsoncpp
# Once done, this will define
#
#  Jsoncpp_FOUND - system has Jsoncpp
#  Jsoncpp_INCLUDE_DIRS - the Jsoncpp include directories
#  Jsoncpp_LIBRARIES - link these to use Jsoncpp

include(LibFindMacros)

# Use pkg-config to get hints about paths
libfind_pkg_check_modules(Jsoncpp_PKGCONF jsoncpp)

# Include dir
find_path(Jsoncpp_INCLUDE_DIR
  NAMES json/json.h
#  PATHS ./jsoncpp/
  PATHS ${Jsoncpp_PKGCONF_INCLUDE_DIRS} # /usr/include/jsoncpp/json
)

# Finally the library itself
find_library(Jsoncpp_LIBRARY
  NAMES jsoncpp
  PATHS ${Jsoncpp_PKGCONF_LIBRARY_DIRS}
#  PATH ./jsoncpp/
)

set(Jsoncpp_PROCESS_INCLUDES Jsoncpp_INCLUDE_DIR)
set(Jsoncpp_PROCESS_LIBS Jsoncpp_LIBRARY)
libfind_process(Jsoncpp)

最后是一个名为 jsonparser.cpp 的简单 C++ 代码来测试它:

#include <iostream>
#include <fstream>
#include <json/json.h>
using namespace std;

void printSongInfo(Json::Value song){
    std::clog<<"\n-----------printing a song-------------\n";
    std::clog<<"Name="<<song["name"];
    std::clog<<"Artist="<<song["artist"];
}

int main(){

    std::ifstream catalogFile("catalog.json");

    Json::Value root;   // will contains the root value after parsing.
    Json::Reader reader;
    bool parsingSuccessful = reader.parse( catalogFile, root );
    if ( !parsingSuccessful ){
        // report to the user the failure and their locations in the document.
        std::cout  << "Failed to parse configuration\n"
                   << reader.getFormattedErrorMessages();
        return 1;
    }

    //parsing songs
    const Json::Value songs = root["songs"];
    for ( int index = 0; index < songs.size(); ++index ){  // Iterates over the sequence elements.
       printSongInfo(songs[index] );
    }
    return 0;
}

当我使用以下命令运行jsonparser.cpp 时,它工作得很好。

g++ -I/usr/include/jsoncpp/ -ljsoncpp jsonparser.cpp

但是当我尝试使用cmake 来制作它时,我收到了这个错误:

$~/jsoncppTest/build$ cmake ..
-- The C compiler identification is GNU 4.7.3
-- The CXX compiler identification is GNU 4.7.3
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
----------- trying to find Jsoncpp-------------
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.26") 
-- checking for module 'jsoncpp'
--   found jsoncpp, version 0.6.0
-- Found Jsoncpp 
INFO: we found LibJsoncpp on your pc.
Jsoncpp_FOUND=TRUE
Jsoncpp_INCLUDE_DIR=/usr/include/jsoncpp
Jsoncpp_LIBRARY=/usr/lib/libjsoncpp.so
-- Configuring done
-- Generating done
-- Build files have been written to: ~/jsoncppTest/build
$~/jsoncppTest/build$ make
Scanning dependencies of target jsonparser
[100%] Building CXX object CMakeFiles/jsonparser.dir/jsonparser.cpp.o
~/jsoncppTest/jsonparser.cpp:3:23: fatal error: json/json.h: No such file or directory
compilation terminated.
make[2]: *** [CMakeFiles/jsonparser.dir/jsonparser.cpp.o] Error 1
make[1]: *** [CMakeFiles/jsonparser.dir/all] Error 2
make: *** [all] Error 2

找不到json/json.h头文件,但之前在cmake中已经建立了jsoncpp库。我检查了jsoncpp.pc 文件,发现 ti OK。我不知道我做错了什么!任何帮助将不胜感激。

我正在使用支持多架构的 ubuntu 13.04。听说64位编译器出现jsoncpp问题,不知道是不是这样。

【问题讨论】:

  • @bennofs 错误已更改但仍无法正常工作。它给出了这个错误jsonparser.cpp:(.text+0x29): undefined reference to Json::Value::operator[](char const*) jsonparser.cpp:(.text+0x46): undefined reference to Json::operator&lt;&lt;(std::ostream&amp;, Json::Value const&amp;) j
  • 试试target_link_libraries(json_parser $(Jsoncpp_LIBRARIES)),这行得通吗? (我删除了我之前的评论,因为我认为它很愚蠢,似乎没有那么愚蠢)
  • @bennofs 它说:Cannot specify link libraries for target "jsonparser" which is not built by this project.
  • @sajjadG 看起来像是错字。它应该是“json_parser”,而不是“jsonparser”。另外,我认为@bennofs 的意思是target_link_libraries(json_parser ${Jsoncpp_LIBRARIES})(注意花括号环绕Jsoncpp_LIBRARIES
  • 我猜删除的评论是添加include_directories(${Jsoncpp_INCLUDE_DIRS})

标签: c++ json g++ cmake jsoncpp


【解决方案1】:

好的,我有一个可以在我的系统上正常编译的解决方案。查找 jsoncpp 很棘手,因为 json-c 安装了一个同名的标头,而在我的系统上,该标头位于 /usr/include/json/json.h 下。要使其正常工作,您必须进行以下更改:


在 FindJsoncpp.cmake 中

# Include dir
find_path(Jsoncpp_INCLUDE_DIR
  NAMES json/features.h
  PATH_SUFFIXES jsoncpp
  PATHS ${Jsoncpp_PKGCONF_INCLUDE_DIRS} # /usr/include/jsoncpp/json
)

搜索 json/features.h 而不是 json/json.h 可以避免在我的系统上找到不兼容的 json-c 的 json.h 文件。


在 CMakeLists.txt 中

include_directories(${Jsoncpp_INCLUDE_DIR})
add_executable(jsonparser jsonparser.cpp)
target_link_libraries(jsonparser ${Jsoncpp_LIBRARY})

这里找到的目录已经设置好了,所以 CMake 实际使用了它们。


在 jsonparser.cpp 中

const Json::Value songs = root["songs"];
for ( int index = 0; index < songs.size(); ++index ){  // Iterates over the sequence elements.
   std::clog<<"Name="<<songs[index]["name"];
   std::clog<<"Artist="<<songs[index]["artist"];
}

你的原始代码没有编译,所以我用上面的代码替换了有问题的部分。您忘记声明歌曲变量了吗?


我还删除了 getFormattedErrorMessages() 调用,因为我只有 jsoncpp 0.5.0,其中该功能不可用。不过这应该没什么区别。

让我知道这是否适合你。

【讨论】:

  • 好答案... +1。我更多地考虑了您对 2 个不同 json.h 文件的评论,我想知道最强大的解决方案是否是执行 find_path(... jsoncpp/json/json.h ...),然后在源文件中您必须执行 #include "jsoncpp/json/json.h"。那就没有机会不小心捡错 json.h 了。
  • @Fraser 我也想过,但是很遗憾,默认安装(源代码中的 make install)不会创建 jsoncpp 目录,而是会安装到 /usr /包括/json/。所以可能会有 jsoncpp 的 json.h 在那个目录中的系统。
  • 啊,对。很遗憾,因为我想/usr/include 很有可能也会通过其他一些依赖项包含在内?
  • @Fraser 是的,此代码取决于用户定义的包含路径在系统搜索路径之前被搜索的事实。 GCC does this,对于其他编译器,我不知道。
  • @bennofs 成功了 :) 非常感谢。我花了 2 天时间解决它,但你在一小时内帮助我。我不知道该怎么感谢你。关于源代码。我已经更新了。我必须在复制后对其进行严重更改。无论如何,来源现在还可以。如果您能讨论更多关于CMakeLists.txt 部分的信息,我将不胜感激。我想我稍后会在其他库中遇到这种问题。那么更好地学习cmake概念会很好。
【解决方案2】:

jsoncpp 现在是builds with cmake

cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -G "Unix Makefiles" ../..
  • 支持pkg-config
  • 构建静态库和/或动态库
  • 可以包含在其他项目中

如果您有任何建议,请open an issue at GitHub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 2018-06-02
    • 2016-04-25
    • 2018-11-22
    • 1970-01-01
    相关资源
    最近更新 更多