草庐IT

c++ - 如何为 jsoncpp 编写 cmake 模块?

coder 2024-02-08 原文

我想使用 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 问题,但不知道是不是这样。

最佳答案

好的,我有一个可以在我的系统上正常编译的解决方案。查找 jsoncpp 很棘手,因为 json-c 安装了一个同名的 header ,而在我的系统上,该 header 位于/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,其中该函数不可用。不过,这应该没什么区别。

让我知道这是否适合您。

关于c++ - 如何为 jsoncpp 编写 cmake 模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18005880/

有关c++ - 如何为 jsoncpp 编写 cmake 模块?的更多相关文章

  1. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. ruby - 如何为 emacs 安装 ruby​​-mode - 2

    我刚刚为fedora安装了emacs。我想用emacs编写ruby。为ruby​​提供代码提示、代码完成类型功能所需的工具、扩展是什么? 最佳答案 ruby-mode已经包含在Emacs23之后的版本中。不过,它也可以通过ELPA获得。您可能感兴趣的其他一些事情是集成RVM、feature-mode(Cucumber)、rspec-mode、ruby-electric、inf-ruby、rinari(用于Rails)等。这是我当前用于Ruby开发的Emacs配置:https://github.com/citizen428/emacs

  6. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  7. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  8. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  9. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  10. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

随机推荐