【问题标题】:How to run make & CMake programmatically如何以编程方式运行 make 和 CMake
【发布时间】:2015-02-12 04:54:40
【问题描述】:

我正在研究机器人模拟,为了控制机器人(在模拟中),我们必须在名为插件的文件中编写 C++ 代码。

我们使用 CMake 编译插件,并在终端中编写命令。

现在,我想要的是一个接一个地编译很多插件(数百个),用于使用遗传算法测试最好的控制器。

我无法手动执行此操作(即,对于每个插件,在终端中编写 CMake 命令),所以我想编写将编译所有插件的 C++ 代码。

【问题讨论】:

  • 你是什么意思自动?时间安排?还是作为用于更新或安装的分布式包?我不明白你的实际要求。
  • 不需要 c++ 文件。我不想在终端上键入 cmake 和 make,而是在文件中编写命令,并且在执行该文件时,它将在运行时编译另一个 c++ 文件。
  • @user1931907 目前还不清楚你到底想做什么。您想在终端中输入makecmake,它应该编译、安装和执行您的程序?
  • 我编辑了问题,感谢您对我的耐心

标签: c++ compilation cmake programmatically-created


【解决方案1】:

我不确定我是否完全理解你的问题,但我会尽快回答:)

您可以创建一个新的 C++ 项目以由 CMake 配置。 CMake 会将您的 C++ 代码所需的所有路径写入 C++ 源文件。假设新项目具有以下结构:

/CMakeLists.txt
/PluginAlpha
  /CMakeLists.txt
  /...
/PluginBeta
  /CMakeLists.txt
  /...
/PluginGamma
  /CMakeLists.txt
  /...
/main.cpp

您的顶级 CMakeLists.txt 可以做到:

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(Builder)

set(Plugins PluginAlpha PluginBeta PluginGamma)
foreach(Plugin ${Plugins})
  set(Contents "${Contents}\n  {\"\\\"${CMAKE_BINARY_DIR}/Build${Plugin}\\\"\", \"\\\"${CMAKE_SOURCE_DIR}/${Plugin}\\\"\"},")
endforeach()
string(REGEX REPLACE ",$" "" Contents "${Contents}")

file(WRITE "${CMAKE_BINARY_DIR}/always_updated/paths.hpp" "#ifndef PATHS_HPP_
#define PATHS_HPP_

#include <array>
#include <string>
#include <vector>

const std::vector<std::array<std::string, 2>> paths = {${Contents}
};

#endif  // PATHS_HPP_
")
configure_file("${CMAKE_BINARY_DIR}/always_updated/paths.hpp" "${CMAKE_BINARY_DIR}/generated/paths.hpp" COPYONLY)

add_executable(Builder main.cpp "${CMAKE_BINARY_DIR}/generated/paths.hpp")
target_include_directories(Builder PRIVATE "${CMAKE_BINARY_DIR}/generated")

因此,作为配置项目的一部分,这会编写一个 C++ 标头,该标头定义了每个插件的构建和源路径的集合 - 例如

#ifndef PATHS_HPP_
#define PATHS_HPP_

#include <array>
#include <string>
#include <vector>

const std::vector<std::array<std::string, 2>> paths = {
  {"\"E:/build/BuildPluginAlpha\"", "\"E:/PluginAlpha\""},
  {"\"E:/build/BuildPluginBeta\"", "\"E:/PluginBeta\""},
  {"\"E:/build/BuildPluginGamma\"", "\"E:/PluginGamma\""}
};

#endif  // PATHS_HPP_

然后您可以让 main.cpp 执行以下操作:

#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>

#include "paths.hpp"  // Generated by CMake during configuration

struct Results {
  std::string plugin_id;
  int configure_result, build_result;
};

int main() {
  std::vector<Results> results;
  for (const auto& p : paths) {
    const std::string& build_folder = p[0];
    const std::string& source_folder = p[1];

    results.emplace_back();
    results.back().plugin_id = source_folder;

    std::string command = "cmake -B" + build_folder + " -H" + source_folder;
    results.back().configure_result = std::system(command.c_str());

    command = "cmake --build " + build_folder + " --config Release";
    results.back().build_result = std::system(command.c_str());
  }

  std::cout << "\n\n";
  for (const auto& r : results) {
    std::cout << "Results for " << r.plugin_id << ":\n";
    std::cout << "  configure result: " << r.configure_result << '\n';
    std::cout << "  build result:     " << r.build_result << '\n';
  }
  return 0;
}

现在,如果您运行“Builder”程序,它应该配置和构建每个插件。

这是一个简化的示例 - 您可能需要向 CMake 命令传递额外的参数,或者想要使用比 std::system 更好的东西,但这可能会给您一个大致的想法。由于您的问题非常模糊,因此我没有详细介绍上述代码的所有细节;请随时提出更多、更具体的问题。

【讨论】:

  • 感谢您的回答,这对我有很大帮助。事实上,我使用的是 ubuntu 12.04,之前从未使用过 CMake。对于插件,我将在执行 main.cpp 时生成它们,因此它们是可变的......我会尝试你的想法,然后我会问一个更具体的问题
  • 不用担心。 CMake v3.0 的文档是here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 2015-07-18
  • 2023-03-24
  • 2018-05-04
  • 1970-01-01
  • 2011-11-08
相关资源
最近更新 更多