The correct CMakeLists.txt file to call a MAXON li

2020-02-15 14:57发布

问题:

I'm very new to the whole CMake. Following this and this posts, now I want to call a MAXON function inside Python, using pybind11. What I have done so far:

  • The library can be downloaded from this page (direct download link).
wget https://www.maxongroup.com/medias/sys_master/root/8837358518302/EPOS-Linux-Library-En.zip
  • unzip:
unzip EPOS-Linux-Library-En.zip
  • make the install shell script executable and run it:
chmod +x ./install.sh
sudo ./install.sh
  • Then going to the example folder:
cd /opt/EposCmdLib_6.6.1.0/examples/HelloEposCmd/
  • Now combining the CMakeLists.txt files from here:
# CMakeLists.txt

cmake_minimum_required(VERSION 2.8.12)
project (HelloEposCmd)

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall")

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

find_package(pybind11 REQUIRED)
pybind11_add_module(${PROJECT_NAME} HelloEposCmd.cpp)

add_executable(${PROJECT_NAME} HelloEposCmd.cpp)

target_link_libraries(${PROJECT_NAME} -lEposCmd)
  • and the HelloEposCmd.cpp this line is added right after other header files:
#include <pybind11/pybind11.h>

the main function is renamed to:

int run(int argc, char** argv)

and the pybind11 syntax to add the module is written at the end:

PYBIND11_MODULE(HelloEposCmd, m) {

    m.def("run", &run, "runs the HelloEposCmd");
}

However, When I run the cmake . I get the error:

CMake Error at CMakeLists.txt:13 (add_executable):

add_executable can not create target "HelloEposCmd" because another target with the same name already exists. The existing target is a module library created in source directory "/opt/EposCmdLib_6.6.1.0/examples/HelloEposCmd" See documentation for policy CMP0002 for more details.

...

I was wondering if you could be kind to help me get the right CMakeList.txt file. Ideally, I should be able to call the compiled module in python:

# HelloEposCmd.py

import HelloEposCmd

HelloEposCmd.run()

Thanks for your support in advance.

回答1:

pybind11_add_module already creates a target for you. So you don't need add_executable anymore. Just remove that line and when you will build you will get a library with the name HelloEposCmd

add_executable is needed if you are building an executable (.exe), which I believe is not what you want.

Documenation of pybind11 says.

This function behaves very much like CMake’s builtin add_library (in fact, it’s a wrapper function around that command).



回答2:

Thanks to abhilb post and his kind followup in the comments I was able to figure the problem out. well, at least find a temporary workaround:

  • According to this post, the last two lines of the CMakeLists.txt file should change to
# this line can be removed
# add_executable(${PROJECT_NAME} HelloEposCmd.cpp)

target_link_libraries(${PROJECT_NAME} PRIVATE -lEposCmd)
  • and then because according to this post pybind11 doesn't support double pointers we change the run function to:
int run() {

    int argc = 1;
    char* argv[] = {"./HelloEposCmd"};

...
}

which I suppose to be a horrible workaround (inspired by information from this page). Now running cmake ., make and python3 HelloEposCmd.py should work properly (except a small c++ warning!).

P.S.1. Maybe someone could use std::vector<std::string> as suggested here. This idea was proposed here and there are already some answers worth investigating.

P.S.2. Following this discussion, another workaround could be something like:

#include <stdio.h>
#include <stdlib.h>

void myFunc(int argc, char* argv[]) {
    for (int i = 0; i < argc; ++i) {
        printf("%s\n", argv[i]);
    }
}

int run(int argc, long* argv_) {

    char** argv = (char**)malloc(argc * sizeof(char*));

    for (int i = 0; i < argc; ++i) {
        argv[i] = (char*)(argv_[i]);
    }

    myFunc(argc, argv);

    free(argv);

    return 0;
}