使用 CMake 和 pkg-config 正确配置、生成和构建一个包含系统库的简单项目的步骤?

问题描述 投票:0回答:1

我在编写 C/C++ 代码方面有一些旧的经验,但现在我想学习如何在现代环境中构建应用程序,并链接一些系统库。

我仅使用终端和 CMake(即不使用 IDE)构建代码。 我在 Linux Mint,但我认为这个问题的主要答案适用于任何系统。

就我而言,我想要的库是 GTK,有一个 GUI,我正在开发一个简单的“hello world”应用程序示例,可以在此处找到:

https://gnome.pages.gitlab.gnome.org/gtkmm-documentation/sec-helloworld.html.

但是我在写这个问题时考虑的是一般情况。

所以,我的问题是:从我意识到代码“包含”某个库中的某些头文件开始,要遵循哪些步骤,继续安装所述库(的“dev”包),可能包括检查给定库(标头)的正确路径(以检查 pkg-config 是否完成其工作),最后是编写 CMakeLists.txt 的正确方法,以便可以正确“配置”代码和“建造”?

到目前为止我所遵循的步骤如下。

  1. 使用

    main.cpp
    helloworld.h
    文件创建项目文件夹。

  2. 注意头文件中有

    #include <gtkmm/button.h>
    行,需要GTK库。

  3. 确保系统中存在所需库的“dev”包(及其头文件),如果需要,请使用系统包管理器安装它。记下安装位置。

  4. 编写 CMakeLists.txt 文件,包括

    find_package(PkgConfig REQUIRED)
    行以使用 pkg-config,然后
    pkg_check_modules(GTK REQUIRED gtkmm-3.0)
    读取有关库路径和依赖项的信息。

  5. 运行

    cmake ..
    在项目的build文件夹中配置并生成CMake文件

  6. 检查 CMakeCache.txt 以检查是否已从 pkg-config 读取到库的正确路径,并可能修改 CMakeLists.txt 文件。

  7. 使用“cmake - - build”构建可执行文件。在 CMake 中。

我使用了在这里找到的 CMakeLists.txt 文件作为起点: https://gist.github.com/fracek/3323924?permalink_comment_id=4047507。 使用它,我成功配置和生成,终端上有以下输出:

$ cmake ..
-- The C compiler identification is GNU 11.4.0
-- The CXX compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2")
-- Checking for module 'gtkmm-3.0'
--   Found gtkmm-3.0, version 3.24.5
-- Configuring done
-- Generating done
-- Build files have been written to: /home/fabio/Documents/GTK_experiment/build


但是我无法构建,收到以下错误:

$ cmake --build .
[ 50%] Building CXX object CMakeFiles/hello.dir/main.cpp.o
In file included from /home/fabio/Documents/GTK_experiment/main.cpp:14:
/home/fabio/Documents/GTK_experiment/helloworld.h:17:10: fatal error: gtkmm/button.h: No such file or directory
   17 | #include <gtkmm/button.h>
      |          ^~~~~~~~~~~~~~~~
compilation terminated.
gmake[2]: *** [CMakeFiles/hello.dir/build.make:76: CMakeFiles/hello.dir/main.cpp.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/hello.dir/all] Error 2
gmake: *** [Makefile:91: all] Error 2

由于错误是

gtkmm/button.h: no such file or directory
,虽然我确信该文件已正确安装,但我知道问题出在 CMakeLists.txt 文件中,未能将链接器指向库头文件夹的正确路径。 那么,问题又来了:如何正确学习库的路径,并检查 CMakeLists.txt 是否指向它?

我将项目中的三个文件复制到此处:

main.cpp


#include "helloworld.h"
#include <iostream>

HelloWorld::HelloWorld()
: m_button("Hello World")   // creates a new button with label "Hello World".
{
  // Sets the border width of the window.
  set_border_width(10);

  // When the button receives the "clicked" signal, it will call the
  // on_button_clicked() method defined below.
  m_button.signal_clicked().connect(sigc::mem_fun(*this,
              &HelloWorld::on_button_clicked));

  // This packs the button into the Window (a container).
  add(m_button);

  // The final step is to display this newly created widget...
  m_button.show();
}

HelloWorld::~HelloWorld()
{
}

void HelloWorld::on_button_clicked()
{
  std::cout << "Hello World" << std::endl;
}
helloworld.h

#ifndef GTKMM_EXAMPLE_HELLOWORLD_H
#define GTKMM_EXAMPLE_HELLOWORLD_H

#include <gtkmm/button.h>
#include <gtkmm/window.h>

class HelloWorld : public Gtk::Window
{

public:
  HelloWorld();
  virtual ~HelloWorld();

protected:
  //Signal handlers:
  void on_button_clicked();

  //Member widgets:
  Gtk::Button m_button;
};

#endif
CMakeLists.txt
# Set the name and the supported language of the project
project(hello-world C CXX)

# Set the minimum version of cmake required to build this project
cmake_minimum_required(VERSION 3.10)

# Use the package PkgConfig to detect GTK+ headers/library files
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED gtkmm-3.0)


add_executable(hello main.cpp)
target_link_libraries(hello PRIVATE ${GTKMM_LIBRARIES})


# Add other flags to the compiler
target_compile_definitions(hello PRIVATE ${GTKMM_CFLAGS_OTHER})


# Setup CMake to use GTK+, tell the compiler where to look for headers
# and to the linker where to look for libraries
target_include_directories(hello PRIVATE ${GTKMM_INCLUDE_DIRS})
target_link_directories(hello PRIVATE ${GTKMM_LIBRARY_DIRS})

我在网上找到并用作初学者的 CMakeLists.txt 文件有几个变量,例如

GTKMM_LIBRARIES
GTKMM_INCLUDE_DIRS
GTKMM_LIBRARY_DIRS
,我认为应该从上面的步骤 4、5 和 6 中学习。 但是是哪一个,以及将它们放在 CMakeLists.txt 文件中的什么位置?

我知道在我的系统中,库位于路径中

/usr/include/gtkmm-3.0

/usr/lib/x86_64-linux-gnu/gtkmm-3.0

确实在

CMakeCache.txt
文件中我发现:

GTK_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include/gtkmm-3.0;/usr/lib/x86_64-linux-gnu/gtkmm-3.0
GTK_INCLUDE_DIRS:INTERNAL=/usr/include/gtkmm-3.0;/usr/lib/x86_64-linux-gnu/gtkmm-3.0/include
GTK_STATIC_CFLAGS:INTERNAL=-pthread;-I/usr/include/gtkmm-3.0;-I/usr/lib/x86_64-linux-gnu/gtkmm-3.0/include

所以我编辑了

CMakeLists.txt
,并更改了例如

GTKMM_INCLUDE_DIRS   ->   GTK_STATIC_INCLUDE_DIRS:INTERNAL
GTKMM_LIBRARY_DIRS   ->   GTK_INCLUDE_DIRS:INTERNAL

和类似的组合,但我仍然遇到相同的错误。

c++ cmake gtk3 pkg-config
1个回答
1
投票

你让事情变得比他们需要的更复杂。

FindPkgConfig
模块现在已经支持导入目标很长一段时间了,所以你可以这样做:

pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtkmm-3.0)
target_link_libraries(hello PUBLIC PkgConfig::GTK)

导入的目标将处理所有标头和链接标志。

© www.soinside.com 2019 - 2024. All rights reserved.