diff --git a/.appveyor.yml b/.appveyor.yml index 99ebac83..0ee6904f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -35,7 +35,7 @@ install: # Build and install xeus-python - mkdir build - cd build - - cmake -G "NMake Makefiles" -D CMAKE_INSTALL_PREFIX=%MINICONDA%\\Library -D XEXTRA_JUPYTER_DATA_DIR=%MINICONDA%\\share\\jupyter -D BUILD_TESTS=ON .. + - cmake -G "NMake Makefiles" -D CMAKE_INSTALL_PREFIX=%MINICONDA%\\Library -D XEXTRA_JUPYTER_DATA_DIR=%MINICONDA%\\share\\jupyter -D BUILD_TESTS=ON -D XEUS_PYTHONHOME_RELPATH=..\\ .. - nmake - nmake install # Install test dependencies diff --git a/.travis.yml b/.travis.yml index b4a619f5..b3e0f1ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,13 +64,14 @@ install: # Build and install xeus-python - mkdir build - cd build - - cmake -D CMAKE_INSTALL_PREFIX=$HOME/miniconda -D DOWNLOAD_GTEST=ON -D PYTHON_EXECUTABLE=`which python` -D XEUS_PYTHONHOME="$HOME/miniconda" -D CMAKE_INSTALL_LIBDIR=lib -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX .. + - cmake -D CMAKE_INSTALL_PREFIX=$HOME/miniconda -D DOWNLOAD_GTEST=ON -D PYTHON_EXECUTABLE=`which python` -D CMAKE_INSTALL_LIBDIR=lib -DCMAKE_C_COMPILER=$CC -DCMAKE_CXX_COMPILER=$CXX .. - make -j2 install script: # For Python 2, activate the kernel_test Python3 environment - if [[ "$PY" == "2" ]]; then source activate kernel_test; jupyter kernelspec install --sys-prefix ../share/jupyter/kernels/xpython; + source activate root; fi - cd test - ./test_xeus_python diff --git a/CMakeLists.txt b/CMakeLists.txt index e37e4ce6..acb05207 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,6 @@ set(XEUS_PYTHON_SRC src/xlinecache.hpp src/xptvsd_client.cpp src/xptvsd_client.hpp - src/xpythonhome.cpp src/xstream.cpp src/xstream.hpp src/xtraceback.cpp @@ -118,14 +117,21 @@ set(XEUS_PYTHON_HEADERS include/xeus-python/xdebugger.hpp include/xeus-python/xeus_python_config.hpp include/xeus-python/xinterpreter.hpp - include/xeus-python/xpythonhome.hpp +) + +set(XPYTHON_SRC + src/main.cpp + src/xpythonhome.hpp + src/xpythonhome.cpp + src/xpaths.hpp + src/xpaths.cpp ) # xeus-python is the target for the library add_library(xeus-python SHARED ${XEUS_PYTHON_SRC} ${XEUS_PYTHON_HEADERS}) # xpython is the target for the kernel executable -add_executable(xpython src/main.cpp) +add_executable(xpython ${XPYTHON_SRC}) set_target_properties(xpython PROPERTIES ENABLE_EXPORTS 1) target_link_libraries(xpython PRIVATE pybind11::pybind11 xeus-python INTERFACE pybind11_json) @@ -158,7 +164,11 @@ set_target_properties(xeus-python PROPERTIES SOVERSION ${XPYT_VERSION_MAJOR} OUTPUT_NAME "libxeus-python") -target_compile_definitions(xeus-python PUBLIC "XEUS_PYTHON_EXPORTS" XEUS_PYTHONHOME="${PYTHON_PREFIX}") +target_compile_definitions(xeus-python PUBLIC "XEUS_PYTHON_EXPORTS") + +if (XEUS_PYTHONHOME_RELPATH) + target_compile_definitions(xpython PRIVATE XEUS_PYTHONHOME_RELPATH=${XEUS_PYTHONHOME_RELPATH}) +endif() ######### # Tests # diff --git a/include/xeus-python/xpythonhome.hpp b/include/xeus-python/xpythonhome.hpp deleted file mode 100644 index 6a6cfa93..00000000 --- a/include/xeus-python/xpythonhome.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** -* Copyright (c) 2018, Martin Renou, Johan Mabille, Sylvain Corlay and * -* Wolf Vollprecht * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#ifndef XEUS_PYTHON_HOME_HPP -#define XEUS_PYTHON_HOME_HPP - -#include -#include - -#include "pybind11/pybind11.h" - -#include "xeus_python_config.hpp" - -namespace xpyt -{ - XEUS_PYTHON_API - const char* get_pythonhome(); - - inline void set_pythonhome() - { - static const char* ph = get_pythonhome(); -#if PY_MAJOR_VERSION == 2 - Py_SetPythonHome(const_cast(ph)); -#else - // The same could be achieved with Py_SetPythonHome(T"" XEUS_PYTHON_HOME) - // but wide string literals are not properly relocated by the conda package - // manager. - static const std::wstring wstr(ph, ph + std::strlen(ph));; - Py_SetPythonHome(const_cast(wstr.c_str())); -#endif - } -} -#endif - diff --git a/src/main.cpp b/src/main.cpp index baafcf2a..17973e00 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,9 +20,10 @@ #include "pybind11/pybind11.h" #include "xeus-python/xinterpreter.hpp" -#include "xeus-python/xpythonhome.hpp" #include "xeus-python/xdebugger.hpp" +#include "xpythonhome.hpp" + namespace py = pybind11; std::string extract_filename(int& argc, char* argv[]) diff --git a/src/xpaths.cpp b/src/xpaths.cpp new file mode 100644 index 00000000..f267c4b4 --- /dev/null +++ b/src/xpaths.cpp @@ -0,0 +1,96 @@ +/*************************************************************************** +* Copyright (c) 2018, Martin Renou, Johan Mabille, Sylvain Corlay and * +* Wolf Vollprecht * +* * +* Distributed under the terms of the BSD 3-Clause License. * +* * +* The full license is in the file LICENSE, distributed with this software. * +****************************************************************************/ + +#include "xpaths.hpp" + +#include +#include + +#if defined(__linux__) +# include +#endif +#if defined(_WIN32) +# if defined(NOMINMAX) +# include +# else +# define NOMINMAX +# include +# undef NOMINMAX +# endif +#endif +#ifdef __APPLE__ +# include +# include +#endif +#if defined(__sun) +# include +#endif + +namespace xpyt +{ + std::string executable_path() + { + std::string path; + char buffer[1024]; + std::memset(buffer, '\0', sizeof(buffer)); +#if defined(__linux__) + if (readlink("/proc/self/exe", buffer, sizeof(buffer)) != -1) + { + path = buffer; + } + else + { + // failed to determine run path + } +#elif defined (_WIN32) + if (GetModuleFileName(nullptr, buffer, sizeof(buffer)) != 0) + { + path = buffer; + } + else + { + // failed to determine run path + } +#elif defined (__APPLE__) + std::uint32_t size = sizeof(buffer); + if(_NSGetExecutablePath(buffer, &size) == 0) + { + path = buffer; + } + else + { + // failed to determine run path + } +#elif defined (__FreeBSD__) + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + if (sysctl(mib, 4, buffer, sizeof(buffer), NULL, 0) != -1) + { + path = buffer; + } + else + { + // failed to determine run path + } +#elif defined(__sun) + path = getexecname(); +#endif + return path; + } + + std::string prefix_path() + { + std::string path = executable_path(); +#if defined (_WIN32) + char separator = '\\'; +#else + char separator = '/'; +#endif + return path.substr(0, path.find_last_of("/\\")) + separator + ".." + separator; + } +} diff --git a/src/xpaths.hpp b/src/xpaths.hpp new file mode 100644 index 00000000..787415fb --- /dev/null +++ b/src/xpaths.hpp @@ -0,0 +1,29 @@ +/*************************************************************************** +* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * +* Copyright (c) QuantStack * +* * +* Distributed under the terms of the BSD 3-Clause License. * +* * +* The full license is in the file LICENSE, distributed with this software. * +****************************************************************************/ + +#ifndef XPYT_PATHS_HPP +#define XPYT_PATHS_HPP + +#include + +namespace xpyt +{ + /******************* + * executable_path * + *******************/ + + std::string executable_path(); + + /******************* + * prefix_path * + *******************/ + + std::string prefix_path(); +} +#endif diff --git a/src/xpythonhome.cpp b/src/xpythonhome.cpp index d53045cf..33f99f4d 100644 --- a/src/xpythonhome.cpp +++ b/src/xpythonhome.cpp @@ -7,22 +7,33 @@ * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ -#include "xeus-python/xpythonhome.hpp" +#include "pybind11/pybind11.h" + +#include +#include + +#include "xeus-python/xeus_python_config.hpp" + +#include "xpythonhome.hpp" +#include "xpaths.hpp" namespace xpyt { - // This functino must not be inlined in the header. - // get_pythonhome and set_pythonhome must remain - // in different compilation units to avoid compiler - // optimization in set_pythonhome that results - // in a relocation issue with conda. - const char* get_pythonhome() + void set_pythonhome() { -#ifdef XEUS_PYTHONHOME - return XEUS_PYTHONHOME; +// The XEUS_PYTHONHOME_RELPATH compile-time definition can be used. +// To specify the PYTHONHOME location as a relative path to the PREFIX. +#if defined(XEUS_PYTHONHOME_RELPATH) + static const std::string pythonhome = prefix_path() + XPYT_STRINGIFY(XEUS_PYTHONHOME_RELPATH); #else - return ""; + static const std::string pythonhome = prefix_path(); +#endif + +#if PY_MAJOR_VERSION == 2 + Py_SetPythonHome(const_cast(pythonhome.c_str())); +#else + static const std::wstring wstr(pythonhome.cbegin(), pythonhome.cend());; + Py_SetPythonHome(const_cast(wstr.c_str())); #endif } } - diff --git a/src/xpythonhome.hpp b/src/xpythonhome.hpp new file mode 100644 index 00000000..b85dfb2f --- /dev/null +++ b/src/xpythonhome.hpp @@ -0,0 +1,18 @@ +/*************************************************************************** +* Copyright (c) 2018, Martin Renou, Johan Mabille, Sylvain Corlay and * +* Wolf Vollprecht * +* * +* Distributed under the terms of the BSD 3-Clause License. * +* * +* The full license is in the file LICENSE, distributed with this software. * +****************************************************************************/ + +#ifndef XEUS_PYTHONHOME_HPP +#define XEUS_PYTHONHOME_HPP + +namespace xpyt +{ + void set_pythonhome(); +} +#endif + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 26b7fab4..3f3d732b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -77,7 +77,6 @@ find_package(Threads) include_directories(${GTEST_INCLUDE_DIRS} SYSTEM) set(XEUS_PYTHON_TESTS - ../src/xpythonhome.cpp ../src/xutils.cpp test_debugger.cpp xeus_client.hpp diff --git a/test/test_debugger.cpp b/test/test_debugger.cpp index c1e8a6ad..44794c10 100644 --- a/test/test_debugger.cpp +++ b/test/test_debugger.cpp @@ -779,11 +779,7 @@ void start_kernel() dump_connection_file(); std::thread kernel([]() { -#if WIN32 - std::string cmd = ".\\..\\xpython -f " + KERNEL_JSON + "&"; -#else - std::string cmd = "./../xpython -f " + KERNEL_JSON + "&"; -#endif + std::string cmd = "xpython -f " + KERNEL_JSON + "&"; int ret2 = std::system(cmd.c_str()); }); std::this_thread::sleep_for(2s);