diff --git a/CMakeLists.txt b/CMakeLists.txt index e4c12ab5..913e3c1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,35 @@ -# --- L-Py Project +# --- CMake Modules cmake_minimum_required(VERSION 3.12) +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +include("Anaconda") +include("pywrapper") + +# --- L-Py Project + project(lpy_project CXX) -# --- CMake Modules +# --- Build setup -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +set(CMAKE_SKIP_BUILD_RPATH FALSE) +set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -include("Anaconda") +list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir) + +if("${isSystemDir}" STREQUAL "-1") + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") +endif("${isSystemDir}" STREQUAL "-1") + + + +# --- CXX11 Compilation + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") # --- (Win32) Multithreaded Compilation @@ -15,25 +37,33 @@ if (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") endif() + +## ################################################################### +## Dependencies +## ################################################################### + +# --- Python + +find_package (Python3 COMPONENTS Interpreter Development) +include_directories(${Python3_INCLUDE_DIRS}) + # --- Libraries find_package(Threads REQUIRED) -find_package(Python REQUIRED) find_package(Qt5Core CONFIG REQUIRED) find_package(Qt5Concurrent CONFIG REQUIRED) find_package(PlantGL REQUIRED) -# Boost -if (DEFINED CONDA_ENV) +if (USE_CONDA) set(BOOST_ROOT ${CONDA_ENV}) - set(BOOST_LIBRARYDIR "${BOOST_ROOT}/lib") endif() set(Boost_NO_SYSTEM_PATHS ON) set(Boost_USE_MULTITHREAD ON) set(Boost_USE_STATIC_LIBS OFF) +set(BUILD_SHARED_LIBS ON) -find_package(Boost COMPONENTS system ${BOOST_PYTHON_LIB} REQUIRED) +find_package(Boost COMPONENTS system python REQUIRED) # --- Include Directories @@ -43,7 +73,9 @@ include_directories(${Boost_INCLUDE_DIR}) # --- Library Directory -link_directories("${CONDA_ENV}/lib") +if (DEFINED CONDA_ENV) + link_directories("${CONDA_ENV}/lib") +endif() # --- Source Directories diff --git a/appveyor.yml b/appveyor.yml index 7ad3d65b..4a05c293 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,6 +12,8 @@ install: - git clone https://github.com/OpenAlea/appveyor-ci.git appveyor-ci - cd appveyor-ci - call install.bat + - conda config --prepend channels conda-forge + - conda config --prepend channels fredboudon before_build: - call before_build.bat diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..727a0bfe --- /dev/null +++ b/build.sh @@ -0,0 +1 @@ +conda build . -c conda-forge -c fredboudon -c defaults --python=3.7 diff --git a/cmake/Anaconda.cmake b/cmake/Anaconda.cmake index 8b93c778..f364d36a 100644 --- a/cmake/Anaconda.cmake +++ b/cmake/Anaconda.cmake @@ -1,9 +1,14 @@ # Anaconda Check if (DEFINED ENV{CONDA_PREFIX}) # Anaconda Environment - message(STATUS "Anaconda environment detected.") + message(STATUS "Anaconda environment detected: " $ENV{CONDA_PREFIX}) - file(TO_CMAKE_PATH $ENV{CONDA_PREFIX} TMP_CONDA_ENV) + + if (DEFINED ENV{BUILD_PREFIX}) + file(TO_CMAKE_PATH $ENV{BUILD_PREFIX} TMP_CONDA_ENV) + else() + file(TO_CMAKE_PATH $ENV{CONDA_PREFIX} TMP_CONDA_ENV) + endif() if (WIN32) set(CONDA_ENV "${TMP_CONDA_ENV}/Library/") @@ -12,4 +17,52 @@ if (DEFINED ENV{CONDA_PREFIX}) endif() set(CONDA_PYTHON_ENV "${TMP_CONDA_ENV}/") + + set(USE_CONDA ON) + +else() + message(STATUS "Compilation outside an anaconda environment.") + set(USE_CONDA OFF) +endif() + + +if (DEFINED ENV{CONDA_BUILD}) + message(STATUS "Conda build detected. " $ENV{CONDA_BUILD}) + + # specify the cross compiler + set(CMAKE_C_COMPILER $ENV{CC}) + set(CMAKE_LINKER $ENV{LD}) + set(CMAKE_AR $ENV{AR}) + set(CMAKE_NM $ENV{NM}) + set(CMAKE_RANLIB $ENV{RANLIB}) + set(CMAKE_STRIP $ENV{STRIP}) + set(CMAKE_INSTALL_NAME_TOOL $ENV{INSTALL_NAME_TOOL}) + #CMAKE_MAKE_PROGRAM + #CMAKE_OBJCOPY + #CMAKE_OBJDUMP + + if (APPLE) + set(CMAKE_OSX_ARCHITECTURES $ENV{OSX_ARCH}) + endif() + + set(CMAKE_CXX_COMPILER $ENV{CXX}) + set(CMAKE_CXX_COMPILER_RANLIB $ENV{RANLIB}) + set(CMAKE_CXX_COMPILER_AR $ENV{AR}) + + # where is the target environment + set(CMAKE_FIND_ROOT_PATH $ENV{PREFIX} $ENV{BUILD_PREFIX} $ENV{BUILD_PREFIX}/$ENV{HOST}/sysroot $ENV{CONDA_BUILD_SYSROOT}) + + # search for programs in the build host directories + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + # for libraries and headers in the target directories + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + + + set(USE_CONDA_BUILD ON) +else() + set(USE_CONDA_BUILD OFF) endif() + + + diff --git a/cmake/CXX14.cmake b/cmake/CXX14.cmake index 268b9685..4969e6a0 100644 --- a/cmake/CXX14.cmake +++ b/cmake/CXX14.cmake @@ -20,6 +20,6 @@ else() endif() # C++14 Standard -set(CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) +#set(CMAKE_CXX_STANDARD 14) +#set(CMAKE_CXX_STANDARD_REQUIRED ON) +#set(CMAKE_CXX_EXTENSIONS OFF) diff --git a/cmake/pywrapper.cmake b/cmake/pywrapper.cmake new file mode 100644 index 00000000..c16742d5 --- /dev/null +++ b/cmake/pywrapper.cmake @@ -0,0 +1,35 @@ + + +function(pgllib_link_python libwrapname) + if(NOT APPLE OR NOT USE_CONDA) + if (Python3_FOUND) + target_link_libraries(${libwrapname} Python3::Python) + elseif (Python2_FOUND) + target_link_libraries(${libwrapname} Python2::Python) + endif() + else() + message(STATUS "Do not link with Python directly : " ${libwrapname}) + endif() + + # Disable Boost Auto-Link + #target_compile_definitions(${libwrapname} PRIVATE BOOST_ALL_NO_LIB) + + #target_link_libraries(${libwrapname} Boost::system Boost::thread Boost::python ) + +endfunction() + + + +function(pglwrapper_install libwrapname) + set_target_properties(${libwrapname} PROPERTIES PREFIX "") + + if (WIN32) + set_target_properties(${libwrapname} PROPERTIES SUFFIX ".pyd") + endif() + + if (APPLE) + set_target_properties(${libwrapname} PROPERTIES SUFFIX ".so") + endif() + + install(TARGETS ${libwrapname} DESTINATION "${CMAKE_SOURCE_DIR}/src/openalea/lpy") +endfunction() diff --git a/conda/build.sh b/conda/build.sh index c5c9546b..af75983a 100644 --- a/conda/build.sh +++ b/conda/build.sh @@ -1,14 +1,73 @@ #!/bin/bash -# Working Dir +if [[ -d build ]]; then + rm -rf build +fi mkdir build cd build -# Build -cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} -DCMAKE_PREFIX_PATH=${PREFIX} -DCMAKE_BUILD_TYPE=Release .. -make -j${CPU_COUNT} +if [ `uname` = "Darwin" ]; then + SYSTEM_DEPENDENT_ARGS=( + "-DCMAKE_OSX_SYSROOT=${CONDA_BUILD_SYSROOT}" + ) + export LDFLAGS="-undefined dynamic_lookup ${LDFLAGS}" +else + SYSTEM_DEPENDENT_ARGS=( + "-DOPENGL_opengl_LIBRARY=${BUILD_PREFIX}/${HOST}/sysroot/usr/lib64/libGL.so" + "-DOPENGL_glx_LIBRARY=${BUILD_PREFIX}/${HOST}/sysroot/usr/lib64/libGL.so" + ) +fi + +export SYSTEM_DEPENDENT_ARGS + +echo +echo "****** CMAKE" +which cmake +echo 'CONDA_BUILD_SYSROOT:' $CONDA_BUILD_SYSROOT +echo +echo "****** ENV" +env + +echo +echo "****** CMAKE CONFIG" + +cmake -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + -DCMAKE_PREFIX_PATH=${PREFIX} \ + -DCMAKE_BUILD_TYPE=Release \ + ${SYSTEM_DEPENDENT_ARGS[@]} \ + -LAH .. + +echo +echo "****** LPY CONFIG" +cat $SRC_DIR/src/openalea/lpy/__version__.py + +echo +echo "****** COMPILE" +export VERBOSE=1 +make -j${CPU_COUNT} +echo "****** INSTALL CXX LIB" make install -# Install Python Files +echo +echo "****** INSTALL PYTHON LIB" cd .. -$PYTHON setup.py install --prefix=${PREFIX} +echo "PYTHON:" ${PYTHON} + +#echo "** PYTHON CALL" +#export PYTHONPATH=${PREFIX}/lib/python${PY_VER}/site-packages/ +${PYTHON} setup.py install --prefix=${PREFIX} + +echo +echo "****** CHECK PYTHON LIB" + +# To check if Python lib is not in the dependencies with conda-forge distribution. +# See https://github.com/conda-forge/boost-feedstock/issues/81 +if [ `uname` = "Darwin" ]; then + export LDD='otool -L' +else + export LDD='ldd' +fi + +${LDD} `${PYTHON} -c "import openalea.lpy.__lpy_kernel__ as lpy ; print(lpy.__file__)"` + +echo "****** END OF BUILD PROCESS" diff --git a/conda/meta.yaml b/conda/meta.yaml index c079874d..b74fda79 100644 --- a/conda/meta.yaml +++ b/conda/meta.yaml @@ -1,58 +1,57 @@ -# do not edit the following line. It will be updated automatically -{% set version = "2.7.2" %} - -package: - name: openalea.lpy - version: {{ version }} - -source: - path: .. - -about: - home: https://github.com/openalea/lpy - license: Cecill-C - summary: L-Py is a simulation software that mixes L-systems construction with the Python high-level modeling language. - -build: - preserve_egg_dir: True - number: 1 - features: - - vc9 [win and py27] - - vc14 [win and py37] - track_features: - - vc9 [win and py27] - - vc14 [win and py37] - -requirements: - build: - - python - - openalea.plantgl - - boost - - qt =5 - - pyqt - - openalea.deploy - - setuptools - run: - - python - - openalea.plantgl - - boost - - qt =5 - - pyqt - - ipython - - qtconsole - - pyopengl - - pyqglviewer - - vs2008_runtime [win and py27] - - vs2015_runtime [win and py37] - -test: - requires: - - nose - imports: - - openalea.lpy - source_files: - - test/ - - share/ - commands: - - nosetests -v -I test_predecessor_at_scale.py -I test_ui.py [unix] - - nosetests -v -I test_predecessor_at_scale.py -I test_ui.py -I test_axialtree.py -I test_successor_at_scale.py [win] +#{% set version = "2.7.2" %} +{% set data = load_setup_py_data() %} + +package: + name: openalea.lpy + version: {{ data.get('version') }} + +source: + path: .. + +about: + home: https://github.com/openalea/lpy + license: Cecill-C + summary: L-Py is a simulation software that mixes L-systems construction with the Python high-level modeling language. + +build: + preserve_egg_dir: True + number: 3 +requirements: + build: + - binutils_impl_linux-64<2.31.0 # [linux] + - {{ compiler('cxx') }} + - python {{PY_VER}} + - cmake >=3.12.0 + - pkg-config # [linux] + - make # [unix] + - menuinst # [win] + host: + - python {{PY_VER}} + - setuptools + - openalea.plantgl + - boost + - pyqt + run: + - python {{PY_VER}} + - setuptools + - openalea.plantgl + - boost + - pyqt + - ipython + - pyopengl + - qtconsole + - pyqglviewer + # - scipy + # - matplotlib + # - openalea.mtg +# test: +# requires: +# - nose +# imports: +# - openalea.lpy +# source_files: +# - test/ +# - share/ +# commands: +# - nosetests -v -I test_predecessor_at_scale.py -I test_ui.py [unix] +# - nosetests -v -I test_predecessor_at_scale.py -I test_ui.py -I test_axialtree.py -I test_successor_at_scale.py [win] diff --git a/options_conda_build.py b/options_conda_build.py deleted file mode 100644 index f9ca0502..00000000 --- a/options_conda_build.py +++ /dev/null @@ -1,12 +0,0 @@ -import os -pj=os.path.join - -PREFIX = os.path.abspath(os.environ.get('PREFIX')) -SRC_DIR = os.environ.get('SRC_DIR') - -vplants_plantgl_include = pj(PREFIX,'include') -vplants_plantgl_lib = pj(PREFIX,'lib') - -if 'CPU_COUNT' in os.environ: - num_jobs = os.environ['CPU_COUNT'] - diff --git a/setup.py b/setup.py index 4c5e6af6..f37fdce9 100644 --- a/setup.py +++ b/setup.py @@ -5,13 +5,6 @@ import os, sys pj = os.path.join -# from openalea.deploy.metainfo import read_metainfo -# metadata = read_metainfo('metainfo.ini', verbose=True) -# for key,value in metadata.items(): -# exec("%s = '%s'" % (key, value)) - -version = '2.7.1' -release = '2.7' project = 'openalea' package = 'lpy' name = 'OpenAlea.Lpy' @@ -19,7 +12,7 @@ pkg_name = 'openalea.lpy' description = 'Lindenmayer Systems in Python package for OpenAlea.' long_description= 'L-Py is a simulation software that mixes L-systems construction with the Python high-level modeling language. ' -authors = 'Frederic Boudon' +authors = 'Frédéric Boudon' authors_email = 'frederic.boudon@cirad.fr' url= 'https://github.com/openalea/lpy' # LGPL compatible INRIA license @@ -31,32 +24,37 @@ # Package name pkg_name= namespace + '.' + package -meta_version = version # check that meta version is updated -f = pj(os.path.dirname(__file__),'src', 'openalea', 'lpy','__version__.py') -d = {} -exec(compile(open(f, "rb").read(), f, 'exec'),d,d) -version= d['LPY_VERSION_STR'] -if meta_version != version: - print ('Warning:: Update the version in metainfo.ini !!') -print (pkg_name+': version ='+version) +lpydir = pj(os.path.dirname(__file__),'src', 'openalea', 'lpy') +versionfile = pj(lpydir,'__version__.py') +versioninfo = {} +with open(versionfile) as fp: + exec(fp.read(), versioninfo) -# Scons build directory -build_prefix = "build-cmake" +version= versioninfo['LPY_VERSION_STR'] +print (pkg_name+': version = '+version) -from setuptools import setup -# from openalea.deploy.binary_deps import binary_deps + +# cmake build directory +build_prefix = "build-cmake" def compile_interface(): cwd = os.getcwd() - os.chdir(pj('src','openalea','lpy','gui')) + os.chdir(pj(lpydir,'gui')) sys.path = ['']+sys.path import generate_ui os.chdir(cwd) -compile_interface() -install_requires = [] + py2exe_file = pj(lpydir,'gui','py2exe_release.py') + if not os.path.exists(py2exe_file): + open(py2exe_file,'w').close() + +if 'install' in sys.argv: + compile_interface() + + +from setuptools import setup setup( name=name, @@ -73,8 +71,8 @@ def compile_interface(): # pure python packages packages = [ + namespace, pkg_name, - pkg_name + '_d', pkg_name + '_wralea', pkg_name + '.gui', pkg_name + '.gui.plugins', @@ -84,9 +82,13 @@ def compile_interface(): # python packages directory package_dir = { '' : 'src',}, + package_data={ + "": ["share/*","share/*/*","share/*/*/*","share/*/*/*/*", '*.pyd', '*.so', '*.dylib', '*.lpy','*.ui','*.qrc'], + }, + # Add package platform libraries if any include_package_data = True, - package_data = {'' : ['*.pyd', '*.so', '*.dylib', '*.lpy','*.ui','*.qrc'],}, + #package_data = {'' : ['*.pyd', '*.so', '*.dylib', '*.lpy','*.ui','*.qrc'],}, zip_safe = False, # Dependencies @@ -94,12 +96,6 @@ def compile_interface(): "wralea": ["lpy = openalea.lpy_wralea",], 'gui_scripts': ['lpy = openalea.lpy.gui.lpystudio:main',], 'console_scripts': ['cpfg2lpy = openalea.lpy.cpfg_compat.cpfg2lpy:main',], - }, - - # Dependencies - setup_requires = ['openalea.deploy'], - dependency_links = ['http://openalea.gforge.inria.fr/pi'], - install_requires = install_requires, + } - pylint_packages = ['src/openalea/lpy/gui'] ) diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt index 33df4962..5cfb4734 100644 --- a/src/cpp/CMakeLists.txt +++ b/src/cpp/CMakeLists.txt @@ -8,12 +8,12 @@ add_library(lpy SHARED ${SRC_FILES}) target_link_libraries(lpy ${PLANTGL_LIBRARIES}) target_link_libraries(lpy Qt5::Core Qt5::Concurrent) -target_link_libraries(lpy Python3::Python) +pgllib_link_python(lpy) # Disable Boost Auto-Link target_compile_definitions(lpy PRIVATE BOOST_ALL_NO_LIB) -target_link_libraries(lpy Boost::${BOOST_PYTHON_LIB}) +target_link_libraries(lpy Boost::python) # --- Preprocessor @@ -28,4 +28,4 @@ install(TARGETS lpy LIBRARY DESTINATION "lib") # --- Install Headers -install(DIRECTORY "." DESTINATION "include" FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp") +install(DIRECTORY "." DESTINATION "include/lpy" FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp") diff --git a/src/openalea/__init__.py b/src/openalea/__init__.py index 64ac5e45..de40ea7c 100644 --- a/src/openalea/__init__.py +++ b/src/openalea/__init__.py @@ -1,17 +1 @@ -try: - import pkg_resources - pkg_resources.declare_namespace(__name__) -except ImportError: - import pkgutil - __path__ = pkgutil.extend_path(__path__, __name__) - - -try: - from __init_path__ import set_path - set_path() -except: - pass - -import modulefinder -for p in __path__: - modulefinder.AddPackagePath(__name__, p) +__import__('pkg_resources').declare_namespace(__name__) diff --git a/src/openalea/lpy/__version__.py b/src/openalea/lpy/__version__.py index fcf0127f..9a455e3c 100644 --- a/src/openalea/lpy/__version__.py +++ b/src/openalea/lpy/__version__.py @@ -1,4 +1,4 @@ -__version_number__ = 0x020702 +__version_number__ = 0x030000 __revision_str__="" diff --git a/src/openalea/lpy/gui/compile_ui.py b/src/openalea/lpy/gui/compile_ui.py index 9f4b577f..adc52166 100644 --- a/src/openalea/lpy/gui/compile_ui.py +++ b/src/openalea/lpy/gui/compile_ui.py @@ -1,10 +1,9 @@ -from openalea.plantgl.gui.qt import qt +from openalea.plantgl.gui.qt import QT_API, PYQT5_API, PYQT4_API, PYSIDE_API from openalea.plantgl.gui.qt.uic import compileUi, compile_args import os import sys -from openalea.plantgl.gui.qt import QT_API, PYQT5_API, PYQT4_API, PYSIDE_API def get_uifnames_from(fname): uiprefix = os.path.splitext(fname)[0] diff --git a/src/openalea/lpy/gui/generate_ui.py b/src/openalea/lpy/gui/generate_ui.py index 167bc1a0..54488968 100644 --- a/src/openalea/lpy/gui/generate_ui.py +++ b/src/openalea/lpy/gui/generate_ui.py @@ -6,7 +6,9 @@ py2exe_release = False if not py2exe_release: - import openalea.lpy.gui.compile_ui as ui + import compile_ui as ui +# from . import compile_ui as ui + print("Generate Ui - imported") import os.path ldir = os.path.dirname(__file__) print("Generate Ui") diff --git a/src/openalea/lpy_d/__init__.py b/src/openalea/lpy_d/__init__.py deleted file mode 100644 index 0a7de47b..00000000 --- a/src/openalea/lpy_d/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .__lpy_kernel__ import * \ No newline at end of file diff --git a/src/wrapper/CMakeLists.txt b/src/wrapper/CMakeLists.txt index 54b98d0a..5e21f7b9 100644 --- a/src/wrapper/CMakeLists.txt +++ b/src/wrapper/CMakeLists.txt @@ -8,12 +8,12 @@ add_library(__lpy_kernel__ SHARED ${SRC_FILES}) target_link_libraries(__lpy_kernel__ lpy) target_link_libraries(__lpy_kernel__ ${PLANTGL_LIBRARIES}) -target_link_libraries(__lpy_kernel__ Python3::Python) +pgllib_link_python(__lpy_kernel__) # Disable Boost Auto-Link target_compile_definitions(__lpy_kernel__ PRIVATE BOOST_ALL_NO_LIB) -target_link_libraries(__lpy_kernel__ Boost::system Boost::${BOOST_PYTHON_LIB}) +target_link_libraries(__lpy_kernel__ Boost::system Boost::python) # --- Dependencies @@ -21,14 +21,5 @@ add_dependencies(__lpy_kernel__ lpy) # --- Output Library -set_target_properties(__lpy_kernel__ PROPERTIES PREFIX "") +pglwrapper_install(__lpy_kernel__) -if (WIN32) - set_target_properties(__lpy_kernel__ PROPERTIES SUFFIX ".pyd") -endif() - -if (APPLE) - set_target_properties(__lpy_kernel__ PROPERTIES SUFFIX ".so") -endif() - -install(TARGETS __lpy_kernel__ DESTINATION "${CMAKE_SOURCE_DIR}/src/openalea/lpy") diff --git a/travis.yml b/travis.yml index 4857dc40..88e85d3c 100644 --- a/travis.yml +++ b/travis.yml @@ -11,12 +11,14 @@ services: env: - CONDA_RECIPE=conda - CONDA_VERSION=2 + CONDA_VERSION=3 install: - git clone https://github.com/openalea/travis-ci.git - cd travis-ci - source install.sh + - conda config --prepend channels fredboudon + - conda config --prepend channels conda-forge before_script: - source before_script.sh