質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.06%

CMakeから生成されるMakefile内のリンカーフラッグの位置変更

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,085

inoshishi

score 17

 前提・実現したいこと

現在pykepというpython用の宇宙軌道設計用ツールを導入しようとしています。
このツールはC++で書かれたものをboost pythonでpython側に公開しているためビルドが必要です。
pipを使った導入もできるのですが、C++側を弄って使う予定もあるのでソースコードからビルドする方法を確立したいのです。
作者のページのインストール手順に従っているのですが、boost pythonがうまく使えていないようでpythonでimportしようとするとエラーがでてしまいます。
makeとmake installは通ります。
ソースコードには一番上層にあるCMakeLists.txtを貼っていますがこれでいいのかもちょっとわかっていません。

 発生している問題・エラーメッセージ

import pykep
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.5/dist-packages/pykep/init.py", line 47, in <module>
from pykep.core import *
File "/usr/local/lib/python3.5/dist-packages/pykep/core/init.py", line 3, in <module>
from ._core import _get_AU, _get_JR, _get_DAY2SEC, _get_DAY2YEAR, _get_DEG2RAD, _get_EARTH_VELOCITY, _get_EARTH_J2, _get_EARTH_RADIUS, _get_MU_EARTH, _get_G0, _get_MU_SUN, _get_RAD2DEG, _get_SEC2DAY
ImportError: /usr/local/lib/python3.5/dist-packages/pykep/core/_core.so: undefined symbol: _ZN5boost7archive18text_iarchive_implINS0_13text_iarchiveEE13load_overrideERNS0_15class_name_typeEi

 該当のソースコード

# CMake version check.
cmake_minimum_required(VERSION 3.2)

# Main pykep project version.
set(PYKEP_PROJECT_VERSION 2.3)
project(pykep VERSION ${PYKEP_PROJECT_VERSION})
enable_testing()

# Module path setup.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake_modules" "${CMAKE_SOURCE_DIR}/cmake_modules/yacma")

message(STATUS "System name: ${CMAKE_SYSTEM_NAME}")

# Set default build type to "Release".
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release CACHE STRING
        "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
    FORCE)
endif()

# Writing some configuration files with version update ...
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doc/sphinx/conf.py.in" "${CMAKE_CURRENT_SOURCE_DIR}/doc/sphinx/conf.py" @ONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pykep/__init__.py.in" "${CMAKE_CURRENT_SOURCE_DIR}/pykep/__init__.py" @ONLY)

# Initial setup of compiler flags.
include(YACMACompilerLinkerSettings)

# Provides build options to CMake
# Build Option: when active the file main.cpp is built and linked to the PYKEP static library
OPTION(BUILD_MAIN "Build 'main.cpp'." ON)

# Build Option: when active builds Python bindings called pykep
OPTION(BUILD_PYKEP "Build pykep." OFF)

# Build Option: when active the examples in the folder example are compiled into executables
OPTION(BUILD_TESTS "Build tests'." ON)

# Build Option: when active the JPL SPICE toolbox is used to extend pykep. You can choose
# to build the library or use a pre-build library
OPTION(BUILD_SPICE "Interface pykep to JPL SPICE toolbox'." OFF)

# Build Option: when active headers will be installed in the CMAKE_INSTALL_PREFIX/include directory
OPTION(INSTALL_HEADERS "Installs the header files" OFF)

# Assemble the flags.
set(PYKEP_CXX_FLAGS_DEBUG ${YACMA_CXX_FLAGS} ${YACMA_CXX_FLAGS_DEBUG} ${YACMA_THREADING_CXX_FLAGS})
set(PYKEP_CXX_FLAGS_RELEASE ${YACMA_CXX_FLAGS} ${YACMA_THREADING_CXX_FLAGS})
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND YACMA_COMPILER_IS_CLANGXX)
  message(STATUS "Clang compiler on OSX detected, setting the standard library to 'libc++'.")
  list(APPEND PYKEP_CXX_FLAGS_DEBUG "-stdlib=libc++")
  list(APPEND PYKEP_CXX_FLAGS_RELEASE "-stdlib=libc++")
endif()
if(YACMA_COMPILER_IS_MSVC)
  # Disable the idiotic minmax macros on MSVC, some annoying warnings,
  # and enable the bigobj option.
  list(APPEND PYKEP_CXX_FLAGS_DEBUG "-DNOMINMAX" "/wd4459" "/wd4127" "/wd4702" "/bigobj")
  list(APPEND PYKEP_CXX_FLAGS_RELEASE "-DNOMINMAX" "/wd4459" "/wd4127" "/wd4702" "/bigobj")
endif()
if(YACMA_COMPILER_IS_INTELXX)
  # NOTE: on MSVC we use the push/pop pragmas, but they do not seem to work on Intel (the pragmas
  # in icc influence the behaviour at instantiation point, not at definition point).
  # These warnings are useful in principle, but they are generated a lot from cereal and we have no
  # way of disabling them selectively. Just rely on the other compilers to provde good diagnostic.
  list(APPEND PYKEP_CXX_FLAGS_DEBUG "-diag-disable" "2259,1682,68")
  list(APPEND PYKEP_CXX_FLAGS_RELEASE "-diag-disable" "2259,1682,68")
endif()
if(MINGW)
    # Flag needed to deal with big binaries in MinGW.
    message(STATUS "Enabling the '-Wa,-mbig-obj' flag in MinGW builds.")
    list(APPEND PYKEP_CXX_FLAGS_DEBUG "-Wa,-mbig-obj")
    list(APPEND PYKEP_CXX_FLAGS_RELEASE "-Wa,-mbig-obj")
endif()

if(BUILD_PYKEP)
    # pygmo dependencies.
    include(YACMAPythonSetup)

    # Python version check.
    if(${PYTHON_VERSION_MAJOR} LESS 2 OR (${PYTHON_VERSION_MAJOR} EQUAL 2 AND ${PYTHON_VERSION_MINOR} LESS 7))
        message(FATAL_ERROR "Minimum supported Python version is 2.7.")
    endif()

    # Internal variable that will be used to tell PYKEPFindBoost to locate Boost.Python.
    set(_PYKEP_FIND_BOOST_PYTHON TRUE)
endif()

# Boost setup. Will allow using Boost::library_name for the needed components
include(PykepFindBoost)

# We build cspice static library and link it in pykep libraries
if(BUILD_SPICE)
add_subdirectory("${CMAKE_SOURCE_DIR}/src/third_party/cspice")
    add_definitions(-DPYKEP_USING_SPICE)
endif(BUILD_SPICE)

# Here we define the file list and make the static and dynamic library
add_subdirectory("${CMAKE_SOURCE_DIR}/src")

# Build main and link it to static library.
if(BUILD_MAIN)
    add_executable(main main.cpp)
    target_link_libraries(main keplerian_toolbox_static Boost::boost Boost::serialization Boost::date_time)
    set_property(TARGET main PROPERTY CXX_STANDARD 11)
    set_property(TARGET main PROPERTY CXX_STANDARD_REQUIRED YES)
    set_property(TARGET main PROPERTY CXX_EXTENSIONS NO)
endif(BUILD_MAIN)

# Build Tests and link them to static library.
if(BUILD_TESTS)
    add_subdirectory("${CMAKE_SOURCE_DIR}/tests")
    file(COPY "${CMAKE_SOURCE_DIR}/tests/data/sgp4_test.txt" DESTINATION "${CMAKE_BINARY_DIR}/tests")
    file(COPY "${CMAKE_SOURCE_DIR}/tests/data/C_G_1000012_2012_2017.bsp" DESTINATION "${CMAKE_BINARY_DIR}/tests")
    file(COPY "${CMAKE_SOURCE_DIR}/tests/data/pck00010.tpc" DESTINATION "${CMAKE_BINARY_DIR}/tests")
    FILE(COPY "${CMAKE_SOURCE_DIR}/tests/data/gm_de431.tpc" DESTINATION "${CMAKE_BINARY_DIR}/tests")
endif(BUILD_TESTS)

# Build pykep and link it to dynamic library.
if(BUILD_PYKEP)
    add_subdirectory("${CMAKE_SOURCE_DIR}/pykep")
    if(MINGW OR ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
        message(STATUS "Creating the files for the generation of a binary wheel.")
        configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/wheel_setup.py" "${CMAKE_CURRENT_BINARY_DIR}/wheel/setup.py" @ONLY)
        if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
            # NOTE: this is necessary on linux but harmful on mingw.
            configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/wheel_setup.cfg" "${CMAKE_CURRENT_BINARY_DIR}/wheel/setup.cfg" @ONLY)
        endif()
        if(MINGW)
            configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/mingw_wheel_libs_python${PYTHON_VERSION_MAJOR}.txt" "${CMAKE_CURRENT_BINARY_DIR}/wheel/mingw_wheel_libs_python${PYTHON_VERSION_MAJOR}.txt" @ONLY)
        endif()
    endif()
endif()

 試したこと

以下のページを参考にしました。
Install pykep
調べてみたところ以下の似たような事例を見つけました。
boost.pythonでundefined symbolエラーが発生する
発生しているエラーを見るとまさにこれと同様なので-lboost_pythonの位置を変えたいのですが、Cmakeを使っているのでどこをいじればこれができるのかわかりません。
CmakeでできたMakefileを書き直すのでもいいのですが、いかんせん該当箇所も多くまたこれでうまく行く保証もないため今後試行錯誤を繰り返すことを考えるとCMake側でこれを解決したいです。

試したことその2

boost.pythonのチュートリアルを説明しているページを元に以下を試しました。
Boost.Python の機能をざっと紹介してみる

#include <boost/python.hpp>

int add(int lhs, int rhs)
{
    return lhs + rhs;
}

BOOST_PYTHON_MODULE(basic)
{
    using namespace boost::python;
    def("add", &add);
}


これを作って

takehiro@takehiro-desktop:~/ドキュメント$ g++ -DPIC -shared -fPIC -o basic.so basic.cpp -I/usr/include/python3.5m -lboost_python3
>>> import basic
>>> basic.add(1,2)
3
>>> quit()
takehiro@takehiro-desktop:~/ドキュメント$ g++ -I/usr/include/python3.5m -lboost_python3 -DPIC -shared -fPIC -o basic.so basic.cpp
takehiro@takehiro-desktop:~/ドキュメント$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import basic
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /home/takehiro/ドキュメント/basic.so: undefined symbol: _ZNK5boost6python7objects21py_function_impl_base9max_arityEv


これを試してみました。やはりリンカフラッグの位置は大事なようです。

 補足情報(FW/ツールのバージョンなど)

Ubuntu16.04LTS
CMake3.12.3
python3.5
teratailで質問をするのが初めてです。至らないことも多々あると思いますがよろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yumetodo

    2018/10/21 20:03

    まず普通のboost.pythonを使うプログラムをコンパイルして実行できるのか検証してください

    キャンセル

  • inoshishi

    2018/10/21 21:05 編集

    はじめまして。反応していただきありがとうございます。ご指摘いただいた通り検証を行いました。

    キャンセル

  • ikedas

    2018/11/04 18:12 編集

    libboost_python3.soはどこにインストールされているでしょうか。

    キャンセル

回答 1

0

Python 2 と 3 がどうも混在しているように想像しました。
Pykep が python 2 でビルドされているような気がします。

参照リンク先にて ccmake が使われているようですが、以下のように cmake を使った処理をスクリプト化した方が、開発的にもより適切かと思います。そして python3 の実行モジュールを確実に利用するために、PYTHON_EXECUTABLE の指定が必要かな、と想像しました。間違っていたらすみません。

cmake \
  -DBUILD_MAIN=ON                   \
  -DBUILD_PYKEP=ON                  \
  -DCMAKE_BUILD_TYPE=Release        \
  -DCMAKE_INSTALL_PREFIX=/usr/local \
  -DINSTALL_HEADERS=ON              \
  -DPYTHON_EXECUTABLE="/usr/bin/python3" \
  ..

PYTHON_EXECUTABLE に関しては、pykep のドキュメント doc/sphinx/installation.rst に、"Systems with both Python 2 and Python 3 installed" という節において書かれていることです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る