From cfc9da55b13ac0dcefefe6f4e120f15a023e6305 Mon Sep 17 00:00:00 2001 From: Nadavbh Date: Sat, 21 Jan 2017 16:33:17 +0200 Subject: [PATCH] updates setup.py to use cmake --- CMakeLists.txt | 38 +++++++----- rle_python_interface/rle_python_interface.py | 14 ++++- setup.py | 64 +++++++++++++++----- src/environment/RetroAgent.cpp | 3 +- 4 files changed, 87 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb64dce..07cbfd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ project(rle) option(USE_SDL "Use SDL" OFF) option(BUILD_EXAMPLES "Build Example Agents" ON) +option(BUILD_PYTHON "Usef when building Python with distutils" OFF) option(DEBUG "Suspend optimization & enable debugging" OFF) option(UNIT_TESTING "Build unit tests using Google Test" OFF) option(INSTALL_CORES "Install the core libs. Install may require sudo" OFF) @@ -49,6 +50,7 @@ set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) set(SNES9X_DIR ${CMAKE_CURRENT_SOURCE_DIR}/snes9x2010) set(STELLA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/stella-libretro) set(GENESIS_PLUS_GX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Genesis-Plus-GX) +set(PYTHON_RLE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/rle_python_interface) set(MODULES common controllers environment games games/supported external external/TinyMT) foreach(module ${MODULES}) @@ -92,16 +94,27 @@ set(LIBDIR "${CMAKE_INSTALL_PREFIX}/lib") MESSAGE(STATUS "INCLUDE_DIR ${INCDIR}") MESSAGE(STATUS "LIBRARY_DIR ${LIBDIR}") + IF(INSTALL_CORES) set(SNES9X_INSTALL_COMMAND - cp snes9x2010_libretro.so - ${LIBDIR}) + mv snes9x2010_libretro.so + ${LIBDIR}/snes9x2010_libretro.so) + set(STELLA_INSTALL_COMMAND + mv stella_libretro.so + ${LIBDIR}/stella_libretro.so) + set(GENESIS_INSTALL_COMMAND + mv genesis_plus_gx_libretro.so + ${LIBDIR}/genesis_plus_gx_libretro.so) +ELSEIF(BUILD_PYTHON) + set(SNES9X_INSTALL_COMMAND + mv `${FIND_SNES9X}` + ${PYTHON_RLE_DIR}/snes9x2010_libretro.so) set(STELLA_INSTALL_COMMAND - cp stella_libretro.so - ${LIBDIR}) + mv stella_libretro.so + ${PYTHON_RLE_DIR}/stella_libretro.so) set(GENESIS_INSTALL_COMMAND - cp genesis_plus_gx_libretro.so - ${LIBDIR}) + mv genesis_plus_gx_libretro.so + ${PYTHON_RLE_DIR}/genesis_plus_gx_libretro.so) ELSE() set(SNES9X_INSTALL_COMMAND "") set(STELLA_INSTALL_COMMAND "") @@ -115,7 +128,7 @@ ExternalProject_add(snes9x2010_libretro SOURCE_DIR ${SNES9X_DIR} BINARY_DIR ${SNES9X_DIR} CONFIGURE_COMMAND "" - BUILD_COMMAND make + BUILD_COMMAND ${MAKE} INSTALL_DIR ${LIBDIR} INSTALL_COMMAND "${SNES9X_INSTALL_COMMAND}" ) @@ -125,7 +138,7 @@ ExternalProject_add(stella_libretro SOURCE_DIR ${STELLA_DIR} BINARY_DIR ${STELLA_DIR} CONFIGURE_COMMAND "" - BUILD_COMMAND "make" + BUILD_COMMAND ${MAKE} INSTALL_DIR ${LIBDIR} INSTALL_COMMAND "${STELLA_INSTALL_COMMAND}" ) @@ -135,7 +148,7 @@ ExternalProject_add(genesis_plus_gx_libretro SOURCE_DIR ${GENESIS_PLUS_GX_DIR} BINARY_DIR ${GENESIS_PLUS_GX_DIR} CONFIGURE_COMMAND "" - BUILD_COMMAND "make" + BUILD_COMMAND ${MAKE} INSTALL_DIR ${LIBDIR} INSTALL_COMMAND "${GENESIS_INSTALL_COMMAND}" ) @@ -143,10 +156,7 @@ ExternalProject_add(genesis_plus_gx_libretro add_library(rle-lib SHARED ${SOURCE_DIR}/rle_interface.cpp ${SOURCES}) set_target_properties(rle-lib PROPERTIES OUTPUT_NAME rle) set_target_properties(rle-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -add_dependencies(rle-lib snes9x2010_libretro) -add_dependencies(rle-lib stella_libretro) -add_dependencies(rle-lib genesis_plus_gx_libretro) -add_library(rle-c-lib SHARED ${CMAKE_CURRENT_SOURCE_DIR}/rle_python_interface/rle_c_wrapper.cpp ${SOURCE_DIR}/rle_interface.cpp ${SOURCES}) +add_library(rle-c-lib SHARED ${PYTHON_RLE_DIR}/rle_c_wrapper.cpp ${SOURCE_DIR}/rle_interface.cpp ${SOURCES}) set_target_properties(rle-c-lib PROPERTIES OUTPUT_NAME rle_c) set_target_properties(rle-c-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rle_python_interface) @@ -213,7 +223,7 @@ if(UNIT_TESTING) add_definitions(-D__UNIT_TESTING) add_subdirectory(googletest) enable_testing() - include_directories(${GTEST_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/rle_python_interface) + include_directories(${GTEST_INCLUDE_DIRS} ${PYTHON_RLE_DIR}) file(GLOB test_sources test/*.cpp) list(APPEND TEST_SOURCES ${test_sources}) diff --git a/rle_python_interface/rle_python_interface.py b/rle_python_interface/rle_python_interface.py index b72c975..45c12d8 100644 --- a/rle_python_interface/rle_python_interface.py +++ b/rle_python_interface/rle_python_interface.py @@ -106,8 +106,18 @@ def setBool(self, key, value): def setFloat(self, key, value): rle_lib.setFloat(self.obj, key, value) - def loadROM(self, rom_file, core_file): - rle_lib.loadROM(self.obj, rom_file, core_file) + def loadROM(self, rom_file, core): + _ROOT = os.path.abspath(os.path.dirname(__file__)) + if 'snes' == core: + core_path = _ROOT + '/snes9x2010_libretro.so' + elif 'atari' == core: + core_path = _ROOT + '/stella_libretro.so' + elif 'genesis' == core or 'game_gear' == core or 'sg1000' == core: + core_path = _ROOT + '/genesis_plus_gx_libretro.so' + else: + raise ValueError('core must be atari|snes|genesis|game_gear|sg1000') + + rle_lib.loadROM(self.obj, rom_file, core_path) def act(self, actionA, actionB = 0): return rle_lib.act(self.obj, int(actionA), int(actionB)) diff --git a/setup.py b/setup.py index 4b8cf73..1fa0f09 100644 --- a/setup.py +++ b/setup.py @@ -1,26 +1,60 @@ -from distutils.core import setup, Extension -import os.path, sys +import sys +import os +import multiprocessing +from setuptools import setup +import os.path as op +import distutils.command.build as _build +import distutils.dir_util as dd +import distutils.spawn as ds -rle_c_lib = 'rle_python_interface/librle_c.so' -if not os.path.isfile(rle_c_lib): - print 'ERROR: Unable to find required library: %s. Please ensure you\'ve '\ - 'built RLE using CMake.'%(rle_c_lib) - sys.exit() +# script based on: +# https://github.com/mgbellemare/Arcade-Learning-Environment/blob/master/setup.py +# https://github.com/sim-x/simx/blob/master/setup.py +# https://github.com/openai/atari-py/blob/master/setup.py + +def run_cmake(): + if ds.find_executable('cmake') is None: + print "CMake is required to build RLE" + print "Please install cmake version >= 3.02 and re-run setup" + sys.exit(-1) + + new_dir = op.join(op.split(__file__)[0], 'build') + dd.mkpath(new_dir) + os.chdir(new_dir) + cmake_args = ' -DBUILD_EXAMPLES=OFF -DBUILD_PYTHON=ON' + cores_to_use = max(1, multiprocessing.cpu_count() - 1) + + try: + ds.spawn(['cmake', '../'] + cmake_args.split()) + ds.spawn(['make', '-j', str(cores_to_use)]) + except ds.DistutilsExecError: + print "Error while running cmake" + print "run 'setup.py build --help' for build options" + print "You may also try editing the settings in CMakeLists.txt file and re-running setup" + sys.exit(-1) + +########################### +# Custom 'build' command +########################### +class Build(_build.build): + def run(self): + cwd = os.getcwd() + run_cmake() + os.chdir(cwd) -module1 = Extension('rle_python_interface.rle_c_wrapper', - libraries = ['rle_c'], - include_dirs = ['src'], - library_dirs = ['rle_python_interface'], - extra_compile_args=['-D__STDC_CONSTANT_MACROS', '-std=c++11'], - sources=['rle_python_interface/rle_c_wrapper.cpp']) setup(name = 'rle_python_interface', version='0.1.0', description = 'Retro Learning Environment Python Interface based on Ben Goodrich\'s work', url='https://github.com/nadavbh12/Retro-Learning-Environment', + download_url='https://github.com/nadavbh12/Retro-Learning-Environment/tarball/1.0.1', author='Nadav Bhonker, Shai Rozenberg', author_email='nadavbh@gmail.com;shai.roz1989@gmail.com', license = 'GPL', - ext_modules = [module1], packages=['rle_python_interface'], package_dir={'rle_python_interface': 'rle_python_interface'}, - package_data={'rle_python_interface': ['librle_c.so']}) + package_data={'rle_python_interface': ['librle_c.so', + 'stella_libretro.so', + 'snes9x2010_libretrolinux-x86_64.so', + 'genesis_plus_gx_libretro.so']}, + cmdclass={'build': Build } + ) diff --git a/src/environment/RetroAgent.cpp b/src/environment/RetroAgent.cpp index b74cc08..b8f3f31 100644 --- a/src/environment/RetroAgent.cpp +++ b/src/environment/RetroAgent.cpp @@ -457,7 +457,8 @@ void RetroAgent::loadCore(const string& coreName){ string suffix = ".so"; size_t start_pos = coreName.find(suffix); if(start_pos == std::string::npos){ - throw invalid_argument("Invalid core file path. File name must end with .so"); + throw invalid_argument("Invalid core file path: " + coreName + + +"\n File name must end with .so"); } if(agentNum > 0){ string newCoreName = coreName;