-9

I am working on a robotic simulation, and to control the robot (in the simulation) we have to write C++ code in a file called a Plugin.

To compile the plugin we use CMake, and we write the commands in a terminal.

Now, what I want is to compile a lot of plugins (hundreds) one after another for testing the best controller using genetic algorithms.

I can not manually do this (i.e. for each plugin, write the CMake command in a terminal), so I want to write C++ code that will compile all the plugins.

Fraser
  • 74,704
  • 20
  • 238
  • 215
user1931907
  • 41
  • 10
  • 2
    What do you mean _automatically_? Time scheduled? Or as a distributed package for update or installation? I don't get what you're actually asking for. – πάντα ῥεῖ Dec 13 '14 at 16:53
  • Is this what u are looking for http://m.wikihow.com/Compile-a-C/C%2B%2B-Program-on-Ubuntu-Linux –  Dec 13 '14 at 16:54
  • not necessary a c++ file. I want instead of typing cmake and make on the terminal, write a command in a file and while this file is executing it will compile the other c++ file at run time. – user1931907 Dec 13 '14 at 17:00
  • @user1931907 It's still not clear what you want to do actually. You want to type `make` or `cmake` in a terminal, and it should compile, install and execute your program? – πάντα ῥεῖ Dec 13 '14 at 17:11
  • I edited the question, thanks for being patient with me – user1931907 Dec 13 '14 at 17:27

1 Answers1

0

I'm not sure I fully understand your question, but I'll have a stab at an answer :)

You can create a new C++ project to be configured by CMake. CMake will write all the paths required by your C++ code into a C++ source file. Let's say the new project has the following structure:

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

Your top-level CMakeLists.txt could do:

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")

So, as part of configuring the project, this writes a C++ header which defines a collection of build and source paths to each of the plugins - e.g.

#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_

You can then have main.cpp do something like:

#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;
}

Now if you run the program "Builder", it should configure and build each of the plugins.

This is a simplified example - you may well have to pass extra args to the CMake commands, or want to use something better than std::system, but this might give you the general idea. I haven't gone into all the details of the code above since your question was pretty vague; feel free to ask further, more specific questions.

Fraser
  • 74,704
  • 20
  • 238
  • 215
  • thanks for the answer, this will help me a lot. In fact I am using ubuntu 12.04 and never used CMake before. For the plugins, I will generate them at the execution of the main.cpp so they are varaible... I am gonna try your idea, and then I will ask a more specific question – user1931907 Dec 14 '14 at 10:36
  • No worries. The docs for CMake v3.0 are [here](http://www.cmake.org/cmake/help/v3.0/index.html). – Fraser Dec 14 '14 at 13:39