From 13f47585ef28196d5c0ec0afe0dec513fb732c4e Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Tue, 4 Jun 2019 17:14:12 +0000 Subject: [PATCH] add cmake support for linux/mac/windows This is a complete reproduction of the autotools code in cmake, with improvements where cmake has an advantage. The options are documented in README.md Dependencies on Windows with Visual Studio are handled with vcpkg, and the `VCPKG_TARGET_TRIPLET` variable can activate vcpkg support on other platforms as well. Include the FindPython2 cmake modules as they are not in the base cmake package on Ubuntu. Make some minor fixes to the autotools code as well, for things broken by adding the cmake support and some other fixes. Signed-off-by: Rafael Kitover --- .gitignore | 8 +- CMakeLists.txt | 51 + CMakeSettings.json | 53 + README.md | 61 +- cmake/ArmorySupport.cmake | 91 ++ cmake/FindPython/Support.cmake | 1267 +++++++++++++++++ cmake/FindPython2.cmake | 171 +++ cmake/PrettyCompilerColors.cmake | 21 + cmake/Set-Toolchain-vcpkg.cmake | 56 + cmake/scripts/RewriteArmoryScriptPrefix.cmake | 15 + configure.ac | 5 +- cppForSwig/BlockUtils.h | 4 - cppForSwig/CMakeLists.txt | 578 ++++++++ cppForSwig/Makefile.am | 13 +- cppForSwig/chacha20poly1305/CMakeLists.txt | 13 + cppForSwig/cryptopp/CMakeLists.txt | 239 ++++ cppForSwig/gtest/CMakeLists.txt | 81 ++ cppForSwig/libbtc/CMakeLists.txt | 242 ++++ cppForSwig/libbtc/Makefile.am | 2 +- cppForSwig/libbtc/libbtc.pc.cmakein | 12 + cppForSwig/libbtc/src/libbtc-config.h.cmakein | 59 + .../libbtc/src/secp256k1/CMakeLists.txt | 213 +++ cppForSwig/libbtc/src/secp256k1/Makefile.am | 2 +- .../libbtc/src/secp256k1/include/secp256k1.h | 4 + .../src/secp256k1/libsecp256k1.pc.cmakein | 13 + .../src/libsecp256k1-config.h.cmakein | 106 ++ .../lmdb/libraries/liblmdb/CMakeLists.txt | 37 + 27 files changed, 3381 insertions(+), 36 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 CMakeSettings.json create mode 100644 cmake/ArmorySupport.cmake create mode 100644 cmake/FindPython/Support.cmake create mode 100644 cmake/FindPython2.cmake create mode 100644 cmake/PrettyCompilerColors.cmake create mode 100644 cmake/Set-Toolchain-vcpkg.cmake create mode 100644 cmake/scripts/RewriteArmoryScriptPrefix.cmake create mode 100644 cppForSwig/CMakeLists.txt create mode 100644 cppForSwig/chacha20poly1305/CMakeLists.txt create mode 100644 cppForSwig/cryptopp/CMakeLists.txt create mode 100644 cppForSwig/gtest/CMakeLists.txt create mode 100644 cppForSwig/libbtc/CMakeLists.txt create mode 100644 cppForSwig/libbtc/libbtc.pc.cmakein create mode 100644 cppForSwig/libbtc/src/libbtc-config.h.cmakein create mode 100644 cppForSwig/libbtc/src/secp256k1/CMakeLists.txt create mode 100644 cppForSwig/libbtc/src/secp256k1/libsecp256k1.pc.cmakein create mode 100644 cppForSwig/libbtc/src/secp256k1/src/libsecp256k1-config.h.cmakein create mode 100644 cppForSwig/lmdb/libraries/liblmdb/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 5e220ba02..635c1947c 100755 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,10 @@ *.idb *.pdb +build/* +build32/* +vsbuild/* + *libtool.m4 *ltoptions.m4 *ltsugar.m4 @@ -125,8 +129,10 @@ _CppBlockUtils.* /.settings /*.wallet -/findpass.py /*.txt +!CMakeLists.txt + +/findpass.py /sandbox.py /lang/*.qm diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..7a51a5283 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 2.8.12) # ubuntu 14 version + +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +set(VCPKG_DEPS protobuf openssl libwebsockets) + +include(Set-Toolchain-vcpkg) + +project(BitcoinArmory C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "release build with debug info" FORCE) +endif() + +if(POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) +endif() + +include(ArmorySupport) +include(PrettyCompilerColors) + +use_cxx11() + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# use ccache if available, and not already enabled on the command line +# but not with ninja and msys ccache on msys2 +if(NOT (WIN32 AND (NOT $ENV{MSYSTEM} STREQUAL "") AND CMAKE_GENERATOR STREQUAL Ninja)) + if(NOT CMAKE_CXX_COMPILER_LAUNCHER AND NOT CMAKE_C_COMPILER_LAUNCHER) + find_program(CCACHE_FOUND ccache) + if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + endif(CCACHE_FOUND) + endif() +endif() + +# build for host CPU if desired (default yes) +option(WITH_HOST_CPU_FEATURES "support the CPU features of the build host, gcc only" ON) + +if(WITH_HOST_CPU_FEATURES AND CMAKE_CXX_COMPILER_ID STREQUAL GNU) + check_x86_cpu_features() + + add_compile_options(-march=native ${X86_CPU_FEATURES_COMPILER_FLAGS}) +endif() + +if(MSVC) + add_compile_definitions(NOMINMAX _WINSOCKAPI_) +endif() + +add_subdirectory(cppForSwig) diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 000000000..28ca9987c --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,53 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "msvc_x64" + ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "-DVCPKG_TRIPLET=x64-windows", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "Release", + "inheritEnvironments": [ + "msvc_x64" + ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "-DVCPKG_TRIPLET=x64-windows", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, { + "name": "x86-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "msvc_x86" + ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "-DVCPKG_TRIPLET=x86-windows", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + }, { + "name": "x86-Release", + "generator": "Ninja", + "configurationType": "Release", + "inheritEnvironments": [ + "msvc_x86" + ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "-DVCPKG_TRIPLET=x86-windows", + "buildCommandArgs": "-v", + "ctestCommandArgs": "" + } + ] +} diff --git a/README.md b/README.md index b306f53c2..02453722a 100644 --- a/README.md +++ b/README.md @@ -16,32 +16,20 @@ Multi-signature transactions are accommodated under-the-hood about 80%, and will ## Building Armory From Source -[Instructions for Windows](windowsbuild/Windows_build_notes.md) -[Instructions for macOS](osxbuild/macOS_build_notes.md) -[Instructions for Ubuntu and Arch Linux](linuxbuild/Linux_build_notes.md) - ### Dependencies * GNU Compiler Collection Linux: Install package `g++` -* Crypto++ - Linux: Install package `libcrypto++-dev` - Windows: [Download](https://www.cryptopp.com/#download) - * SWIG Linux: Install package `swig` - Windows: [Download](http://www.swig.org/download.html) + Windows: [Download](http://www.swig.org/download.html) MSVS: Copy swigwin-2.x directory next to cryptopp as `swigwin` * Python 2.6/2.7 Linux: Install package `python-dev` Windows: [Download](https://www.python.org/getit/) -* Python Twisted -- asynchronous networking - Linux: Install package `python-twisted` - Windows: [Download](https://twistedmatrix.com/trac/wiki/Downloads) - * PyQt 4 (for Python 2.X) Linux: Install packages `libqtcore4`, `libqt4-dev`, `python-qt4`, and `pyqt4-dev-tools` Windows: [Download](https://riverbankcomputing.com/software/pyqt/download) @@ -50,19 +38,48 @@ Multi-signature transactions are accommodated under-the-hood about 80%, and will (OPTIONAL - if you want to make a standalone executable in Windows) Windows: [Download](http://www.py2exe.org/) -* LMDB - database engine, modified to suit Armory's use cases -[LMDB page](http://symas.com/mdb/) - No need for external installs by Armory users - * libwebsockets - Linux: Final instructions TBA. - Windows: Follow the "Windows binary build" directions [here](https://github.com/warmcat/libwebsockets/blob/master/README.md). + Linux: install latest version from source + Windows: handled automatically with vcpkg, see below * Google Protocol Buffers (protobuf) Linux: Install the `protobuf` package. - Windows: Follow the "C++ Installation - Windows" directions [here](https://github.com/google/protobuf/blob/master/src/README.md), downloading only the `protoc` binary. - -* macOS - [Instructions for downloading, verifying, and running Armory on macOS](README_macOS.md). + Windows: handled automatically with vcpkg, see below + +### CMake options + +| **Option** | **Description** | **Default** | +|-----------------------------|------------------------------------------------------------------------------------------|--------------------------------| +| WITH_HOST_CPU_FEATURES | use -march=native and supported cpu feature flags, gcc only | ON | +| WITH_CRYPTOPP | use Crypto++ library for cryptography functions | OFF | +| WITH_CLIENT | build Python client | AUTO | +| WITH_GUI | build GUI support using Qt4 for the Python client | AUTO | +| ENABLE_TESTS | build the test binaries | OFF | +| LIBBTC_WITH_WALLET | enable libbtc wallet | OFF | +| LIBBTC_WITH_TESTS | enable libbtc tests | OFF | +| LIBBTC_WITH_TOOLS | build libbtc tools binaries | OFF | +| LIBBTC_RANDOM_DEVICE | device to use for random numbers | /dev/urandom | +| SECP256K1_ENABLE_ASM | enable asm routines in the secp256k1 library | ON | +| SECP256K1_USE_LIBGMP | use libgmp for numeric routines in the secp256k1 library | AUTO | +| SECP256K1_MODULE_ECDH | enable the ecdh module in the secp256k1 library | OFF | +| SECP256K1_MODULE_SCHNORR | enable the schnorr module in the secp256k1 library | OFF | +| SECP256K1_ECMULT_STATIC_PRECOMPUTATION | use a statically generated ecmult table for the secp256k1 library | OFF | +| SECP256K1_ENDOMORPHISM | use endomorphism optiomization for the secp256k1 library | OFF | +| SECP256K1_WITH_FIELD | field for the secp256k1 library, can be '32bit', '64bit' or 'AUTO' | AUTO | +| SECP256K1_WITH_SCALAR | scalar for the secp256k1 library, can be '32bit', '64bit' or 'AUTO' | AUTO | +| VCPKG_TARGET_TRIPLET | see below | not set | + +### CMake Windows/vcpkg Build Type + +When building on windows, set the cmake variable `VCPKG_TARGET_TRIPLET` to +`x64-windows` or `x86-windows` depending on whether the build is for 64 bit or +32 bit. You must be in the appropriate Visual Studio environment as well. + +All vcpkg supported triplets should work, and this variable can be used to +activate vcpkg support on other platforms. + +When building with the Visual Studio IDE, the build products will be located +under `C:\Users\\CMakeBuilds`. ## Sample Code diff --git a/cmake/ArmorySupport.cmake b/cmake/ArmorySupport.cmake new file mode 100644 index 000000000..16cef97a2 --- /dev/null +++ b/cmake/ArmorySupport.cmake @@ -0,0 +1,91 @@ +# random utility functions/macros + +# make sure architecture is set +if(NOT CMAKE_SYSTEM_PROCESSOR) + if(NOT CMAKE_TOOLCHAIN_FILE AND CMAKE_HOST_SYSTEM_PROCESSOR) + set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR}) + elseif(CMAKE_TOOLCHAIN_FILE MATCHES mxe) + if(CMAKE_TOOLCHAIN_FILE MATCHES "i[3-9]86") + set(CMAKE_SYSTEM_PROCESSOR i686) + else() + set(CMAKE_SYSTEM_PROCESSOR x86_64) + endif() + endif() +endif() + +macro(string_option opt doc_string initial_value) + if(NOT DEFINED ${${opt}}) + set(${opt} ${initial_value}) + endif() + + set(${opt} ${${opt}} CACHE STRING ${doc_string}) +endmacro() + +# This is from: +# https://stackoverflow.com/a/31010221 +macro(use_cxx11) + if (CMAKE_VERSION VERSION_LESS 3.1) + if(CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") + endif() + else() + # Fix behavior of CMAKE_CXX_STANDARD when targeting macOS. + if(POLICY CMP0025) + cmake_policy(SET CMP0025 NEW) + endif() + + set(CMAKE_CXX_STANDARD 11) + endif() +endmacro(use_cxx11) + +unset(X86_CPU_FEATURES_COMPILER_FLAGS) + +# check for x86 cpu features and sets X86_CPU_FEATURES_COMPILER_FLAGS for gcc/clang +function(check_x86_cpu_features) + if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "i.86|x86_64") + return() + endif() + + if(DEFINED X86_CPU_FEATURES_COMPILER_FLAGS) # already computed, do nothing + return() + endif() + + include(CheckCXXSourceCompiles) + + check_cxx_source_compiles(" + #include + + int main(int argc, char** argv) + { + __builtin_cpu_init(); + } + " HAVE_CPU_INIT) + + if(HAVE_CPU_INIT) + include(CheckCXXSourceRuns) + + foreach(cpu_feature mmx popcnt sse sse2 sse3 sse4.1 sse4.2 sse4a avx avx2 avx512f fma fma4 bmi bmi2) + string(REPLACE . _ cpu_feature_var ${cpu_feature}) + + check_cxx_source_runs(" + #include + + int main(int argc, char** argv) + { + __builtin_cpu_init(); + + if (__builtin_cpu_supports(\"${cpu_feature}\")) + return 0; + + return 1; + } + " HAVE_${cpu_feature_var}) + + if(HAVE_${cpu_feature_var}) + list(APPEND X86_CPU_FEATURES_COMPILER_FLAGS -m${cpu_feature}) + endif() + endforeach() + + set(X86_CPU_FEATURES_COMPILER_FLAGS ${X86_CPU_FEATURES_COMPILER_FLAGS} CACHE STRING "gcc/clang cpu feature flags for the build host" FORCE) + endif() +endfunction() diff --git a/cmake/FindPython/Support.cmake b/cmake/FindPython/Support.cmake new file mode 100644 index 000000000..f1ee341a9 --- /dev/null +++ b/cmake/FindPython/Support.cmake @@ -0,0 +1,1267 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# +# This file is a "template" file used by various FindPython modules. +# + +cmake_policy (VERSION 3.7) + +# +# Initial configuration +# +if (NOT DEFINED _PYTHON_PREFIX) + message (FATAL_ERROR "FindPython: INTERNAL ERROR") +endif() +if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) + message (FATAL_ERROR "FindPython: INTERNAL ERROR") +endif() +if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 3) + set(_${_PYTHON_PREFIX}_VERSIONS 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 2) + set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) +else() + message (FATAL_ERROR "FindPython: INTERNAL ERROR") +endif() + + +# +# helper commands +# +macro (_PYTHON_DISPLAY_FAILURE _PYTHON_MSG) + if (${_PYTHON_PREFIX}_FIND_REQUIRED) + message (FATAL_ERROR "${_PYTHON_MSG}") + else() + if (NOT ${_PYTHON_PREFIX}_FIND_QUIETLY) + message(STATUS "${_PYTHON_MSG}") + endif () + endif() + + set (${_PYTHON_PREFIX}_FOUND FALSE) + string (TOUPPER "${_PYTHON_PREFIX}" _${_PYTHON_PREFIX}_UPPER_PREFIX) + set (${_PYTHON_UPPER_PREFIX}_FOUND FALSE) + return() +endmacro() + + +macro (_PYTHON_FIND_FRAMEWORKS) + set (${_PYTHON_PREFIX}_FRAMEWORKS) + if (APPLE) + set (_pff_frameworks ${CMAKE_FRAMEWORK_PATH} + $ENV{CMAKE_FRAMEWORK_PATH} + ~/Library/Frameworks + /usr/local/Frameworks + ${CMAKE_SYSTEM_FRAMEWORK_PATH}) + list (REMOVE_DUPLICATES _pff_frameworks) + foreach (_pff_framework IN LISTS _pff_frameworks) + if (EXISTS ${_pff_framework}/Python.framework) + list (APPEND ${_PYTHON_PREFIX}_FRAMEWORKS ${_pff_framework}/Python.framework) + endif() + endforeach() + unset (_pff_frameworks) + unset (_pff_framework) + endif() +endmacro() + +function (_PYTHON_GET_FRAMEWORKS _PYTHON_PGF_FRAMEWORK_PATHS _PYTHON_VERSION) + set (_PYTHON_FRAMEWORK_PATHS) + foreach (_PYTHON_FRAMEWORK IN LISTS ${_PYTHON_PREFIX}_FRAMEWORKS) + list (APPEND _PYTHON_FRAMEWORK_PATHS + "${_PYTHON_FRAMEWORK}/Versions/${_PYTHON_VERSION}") + endforeach() + set (${_PYTHON_PGF_FRAMEWORK_PATHS} ${_PYTHON_FRAMEWORK_PATHS} PARENT_SCOPE) +endfunction() + + +function (_PYTHON_VALIDATE_INTERPRETER) + if (NOT ${_PYTHON_PREFIX}_EXECUTABLE) + return() + endif() + + if (ARGC EQUAL 1) + set (expected_version ${ARGV0}) + else() + unset (expected_version) + endif() + + get_filename_component (python_name "${${_PYTHON_PREFIX}_EXECUTABLE}" NAME) + + if (expected_version AND NOT python_name STREQUAL "python${expected_version}${CMAKE_EXECUTABLE_SUFFIX}") + # executable found must have a specific version + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))" + RESULT_VARIABLE result + OUTPUT_VARIABLE version + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (result OR NOT version EQUAL expected_version) + # interpreter not usable or has wrong major version + set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE) + return() + endif() + else() + if (NOT python_name STREQUAL "python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}${CMAKE_EXECUTABLE_SUFFIX}") + # executable found do not have version in name + # ensure major version is OK + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys; sys.stdout.write(str(sys.version_info[0]))" + RESULT_VARIABLE result + OUTPUT_VARIABLE version + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) + # interpreter not usable or has wrong major version + set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE) + return() + endif() + endif() + endif() + + if (CMAKE_SIZEOF_VOID_P AND "Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS + AND NOT CMAKE_CROSSCOMPILING) + # In this case, interpreter must have same architecture as environment + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys, struct; sys.stdout.write(str(struct.calcsize(\"P\")))" + RESULT_VARIABLE result + OUTPUT_VARIABLE size + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P) + # interpreter not usable or has wrong architecture + set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE) + return() + endif() + endif() +endfunction() + + +function (_PYTHON_VALIDATE_COMPILER expected_version) + if (NOT ${_PYTHON_PREFIX}_COMPILER) + return() + endif() + + # retrieve python environment version from compiler + set (working_dir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir") + file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))\n") + execute_process (COMMAND "${${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${working_dir}/version.py" + WORKING_DIRECTORY "${working_dir}" + OUTPUT_QUIET + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process (COMMAND "${working_dir}/version" + WORKING_DIRECTORY "${working_dir}" + RESULT_VARIABLE result + OUTPUT_VARIABLE version + ERROR_QUIET) + file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}") + + if (result OR NOT version EQUAL expected_version) + # Compiler not usable or has wrong major version + set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE) + endif() +endfunction() + + +function (_PYTHON_FIND_RUNTIME_LIBRARY _PYTHON_LIB) + string (REPLACE "_RUNTIME" "" _PYTHON_LIB "${_PYTHON_LIB}") + # look at runtime part on systems supporting it + if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR + (CMAKE_SYSTEM_NAME MATCHES "MSYS|CYGWIN" + AND ${_PYTHON_LIB} MATCHES "${CMAKE_IMPORT_LIBRARY_SUFFIX}$")) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + # MSYS has a special syntax for runtime libraries + if (CMAKE_SYSTEM_NAME MATCHES "MSYS") + list (APPEND CMAKE_FIND_LIBRARY_PREFIXES "msys-") + endif() + find_library (${ARGV}) + endif() +endfunction() + + +function (_PYTHON_SET_LIBRARY_DIRS _PYTHON_SLD_RESULT) + unset (_PYTHON_DIRS) + set (_PYTHON_LIBS ${ARGV}) + list (REMOVE_AT _PYTHON_LIBS 0) + foreach (_PYTHON_LIB IN LISTS _PYTHON_LIBS) + if (${_PYTHON_LIB}) + get_filename_component (_PYTHON_DIR "${${_PYTHON_LIB}}" DIRECTORY) + list (APPEND _PYTHON_DIRS "${_PYTHON_DIR}") + endif() + endforeach() + if (_PYTHON_DIRS) + list (REMOVE_DUPLICATES _PYTHON_DIRS) + endif() + set (${_PYTHON_SLD_RESULT} ${_PYTHON_DIRS} PARENT_SCOPE) +endfunction() + + +# If major version is specified, it must be the same as internal major version +if (DEFINED ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR + AND NOT ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) + _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Wrong major version specified is \"${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}\", but expected major version is \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"") +endif() + + +# handle components +if (NOT ${_PYTHON_PREFIX}_FIND_COMPONENTS) + set (${_PYTHON_PREFIX}_FIND_COMPONENTS Interpreter) + set (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter TRUE) +endif() +foreach (_${_PYTHON_PREFIX}_COMPONENT IN LISTS ${_PYTHON_PREFIX}_FIND_COMPONENTS) + set (${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_FOUND FALSE) +endforeach() +unset (_${_PYTHON_PREFIX}_FIND_VERSIONS) + +# Set versions to search +## default: search any version +set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSIONS}) + +if (${_PYTHON_PREFIX}_FIND_VERSION_COUNT GREATER 1) + if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT) + set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}.${${_PYTHON_PREFIX}_FIND_VERSION_MINOR}) + else() + unset (_${_PYTHON_PREFIX}_FIND_VERSIONS) + # add all compatible versions + foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_VERSIONS) + if (_${_PYTHON_PREFIX}_VERSION VERSION_GREATER_EQUAL ${_PYTHON_PREFIX}_FIND_VERSION) + list (APPEND _${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSION}) + endif() + endforeach() + endif() +endif() + +# Python and Anaconda distributions: define which architectures can be used +if (CMAKE_SIZEOF_VOID_P) + # In this case, search only for 64bit or 32bit + math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8") + set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH}) +else() + # architecture unknown, search for both 64bit and 32bit + set (_${_PYTHON_PREFIX}_ARCH 64) + set (_${_PYTHON_PREFIX}_ARCH2 32) +endif() + +# IronPython support +if (CMAKE_SIZEOF_VOID_P) + # In this case, search only for 64bit or 32bit + math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8") + set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy${_${_PYTHON_PREFIX}_ARCH} ipy) +else() + # architecture unknown, search for natural interpreter + set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy) +endif() +set (_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES net45 net40) + +# Apple frameworks handling +_python_find_frameworks () + +# Save CMAKE_FIND_APPBUNDLE +if (DEFINED CMAKE_FIND_APPBUNDLE) + set (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE}) +else() + unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE) +endif() +# To avoid app bundle lookup +set (CMAKE_FIND_APPBUNDLE "NEVER") + +# Save CMAKE_FIND_FRAMEWORK +if (DEFINED CMAKE_FIND_FRAMEWORK) + set (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK}) + if (CMAKE_FIND_FRAMEWORK STREQUAL "ONLY") + message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: CMAKE_FIND_FRAMEWORK: 'ONLY' value is not supported. 'FIRST' will be used instead.") + set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK "FIRST") + else() + set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK}) + endif() +else() + unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK) + set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK "FIRST") +endif() +# To avoid framework lookup +set (CMAKE_FIND_FRAMEWORK "NEVER") + +# Windows Registry handling +if (DEFINED ${_PYTHON_PREFIX}_FIND_REGISTRY) + if (NOT ${_PYTHON_PREFIX}_FIND_REGISTRY MATCHES "^(FIRST|LAST|NEVER)$") + message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_REGISTRY}: invalid value for '${_PYTHON_PREFIX}_FIND_REGISTRY'. 'FIRST', 'LAST' or 'NEVER' expected.") + set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST") + else() + set (_${_PYTHON_PREFIX}_FIND_REGISTRY ${${_PYTHON_PREFIX}_FIND_REGISTRY}) + endif() +else() + set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST") +endif() + + +unset (_${_PYTHON_PREFIX}_REQUIRED_VARS) +unset (_${_PYTHON_PREFIX}_CACHED_VARS) + + +# first step, search for the interpreter +if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) + if (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter) + list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_EXECUTABLE) + list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_EXECUTABLE) + endif() + + set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) + + # look-up for various versions and locations + foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) + string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION}) + + _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) + + # Apple frameworks handling + if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_VERSION} + python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + NAMES_PER_DIR + PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATH_SUFFIXES bin + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + # Windows registry + if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_VERSION} + python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + python + ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + # try using HINTS + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_VERSION} + python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + python + ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + # try using standard paths. + if (WIN32) + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_VERSION} + python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + python + ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} + NAMES_PER_DIR) + else() + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_VERSION} + python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + NAMES_PER_DIR) + endif() + + # Apple frameworks handling + if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_VERSION} + python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + NAMES_PER_DIR + PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATH_SUFFIXES bin + NO_DEFAULT_PATH) + endif() + + # Windows registry + if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_VERSION} + python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + python + ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} + NAMES_PER_DIR + PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} + NO_DEFAULT_PATH) + endif() + + _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION}) + if (${_PYTHON_PREFIX}_EXECUTABLE) + break() + endif() + endforeach() + + if (NOT ${_PYTHON_PREFIX}_EXECUTABLE) + # No specific version found. Retry with generic names + # try using HINTS + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + python + ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + # try using standard paths. + # NAMES_PER_DIR is not defined on purpose to have a chance to find + # expected version. + # For example, typical systems have 'python' for version 2.* and 'python3' + # for version 3.*. So looking for names per dir will find, potentially, + # systematically 'python' (i.e. version 2) even if version 3 is searched. + find_program (${_PYTHON_PREFIX}_EXECUTABLE + NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} + python + ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}) + + _python_validate_interpreter () + endif() + + # retrieve exact version of executable found + if (${_PYTHON_PREFIX}_EXECUTABLE) + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))" + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE ${_PYTHON_PREFIX}_VERSION + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT _${_PYTHON_PREFIX}_RESULT) + string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${${_PYTHON_PREFIX}_VERSION}") + list (GET _${_PYTHON_PREFIX}_VERSIONS 0 ${_PYTHON_PREFIX}_VERSION_MAJOR) + list (GET _${_PYTHON_PREFIX}_VERSIONS 1 ${_PYTHON_PREFIX}_VERSION_MINOR) + list (GET _${_PYTHON_PREFIX}_VERSIONS 2 ${_PYTHON_PREFIX}_VERSION_PATCH) + else() + # Interpreter is not usable + set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE) + unset (${_PYTHON_PREFIX}_VERSION) + endif() + endif() + + if (${_PYTHON_PREFIX}_EXECUTABLE + AND ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) + set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE) + # Use interpreter version for future searches to ensure consistency + set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) + endif() + + if (${_PYTHON_PREFIX}_Interpreter_FOUND) + if (NOT CMAKE_SIZEOF_VOID_P) + # determine interpreter architecture + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.maxsize > 2**32)" + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE ${_PYTHON_PREFIX}_IS64BIT + ERROR_VARIABLE ${_PYTHON_PREFIX}_IS64BIT) + if (NOT _${_PYTHON_PREFIX}_RESULT) + if (${_PYTHON_PREFIX}_IS64BIT) + set (_${_PYTHON_PREFIX}_ARCH 64) + set (_${_PYTHON_PREFIX}_ARCH2 64) + else() + set (_${_PYTHON_PREFIX}_ARCH 32) + set (_${_PYTHON_PREFIX}_ARCH2 32) + endif() + endif() + endif() + + # retrieve interpreter identity + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -V + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID + ERROR_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID) + if (NOT _${_PYTHON_PREFIX}_RESULT) + if (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Anaconda") + set (${_PYTHON_PREFIX}_INTERPRETER_ID "Anaconda") + elseif (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Enthought") + set (${_PYTHON_PREFIX}_INTERPRETER_ID "Canopy") + else() + string (REGEX REPLACE "^([^ ]+).*" "\\1" ${_PYTHON_PREFIX}_INTERPRETER_ID "${${_PYTHON_PREFIX}_INTERPRETER_ID}") + if (${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "Python") + # try to get a more precise ID + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.copyright)" + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE ${_PYTHON_PREFIX}_COPYRIGHT + ERROR_QUIET) + if (${_PYTHON_PREFIX}_COPYRIGHT MATCHES "ActiveState") + set (${_PYTHON_PREFIX}_INTERPRETER_ID "ActivePython") + endif() + endif() + endif() + else() + set (${_PYTHON_PREFIX}_INTERPRETER_ID Python) + endif() + else() + unset (${_PYTHON_PREFIX}_INTERPRETER_ID) + endif() + + # retrieve various package installation directories + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig;sys.stdout.write(';'.join([sysconfig.get_python_lib(plat_specific=False,standard_lib=True),sysconfig.get_python_lib(plat_specific=True,standard_lib=True),sysconfig.get_python_lib(plat_specific=False,standard_lib=False),sysconfig.get_python_lib(plat_specific=True,standard_lib=False)]))" + + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_LIBPATHS + ERROR_QUIET) + if (NOT _${_PYTHON_PREFIX}_RESULT) + list (GET _${_PYTHON_PREFIX}_LIBPATHS 0 ${_PYTHON_PREFIX}_STDLIB) + list (GET _${_PYTHON_PREFIX}_LIBPATHS 1 ${_PYTHON_PREFIX}_STDARCH) + list (GET _${_PYTHON_PREFIX}_LIBPATHS 2 ${_PYTHON_PREFIX}_SITELIB) + list (GET _${_PYTHON_PREFIX}_LIBPATHS 3 ${_PYTHON_PREFIX}_SITEARCH) + else() + unset (${_PYTHON_PREFIX}_STDLIB) + unset (${_PYTHON_PREFIX}_STDARCH) + unset (${_PYTHON_PREFIX}_SITELIB) + unset (${_PYTHON_PREFIX}_SITEARCH) + endif() + + mark_as_advanced (${_PYTHON_PREFIX}_EXECUTABLE) +endif() + + +# second step, search for compiler (IronPython) +if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) + if (${_PYTHON_PREFIX}_FIND_REQUIRED_Compiler) + list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_COMPILER) + list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_COMPILER) + endif() + + # IronPython specific artifacts + # If IronPython interpreter is found, use its path + unset (_${_PYTHON_PREFIX}_IRON_ROOT) + if (${_PYTHON_PREFIX}_Interpreter_FOUND AND ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython") + get_filename_component (_${_PYTHON_PREFIX}_IRON_ROOT "${${_PYTHON_PREFIX}_EXECUTABLE}" DIRECTORY) + endif() + + # try using root dir and registry + foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) + if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") + find_program (${_PYTHON_PREFIX}_COMPILER + NAMES ipyc + HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} + PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + find_program (${_PYTHON_PREFIX}_COMPILER + NAMES ipyc + HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + + if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") + find_program (${_PYTHON_PREFIX}_COMPILER + NAMES ipyc + PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} + NO_DEFAULT_PATH) + endif() + + _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION}) + if (${_PYTHON_PREFIX}_COMPILER) + break() + endif() + endforeach() + + # no specific version found, re-try in standard paths + find_program (${_PYTHON_PREFIX}_COMPILER + NAMES ipyc + HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}) + + if (${_PYTHON_PREFIX}_COMPILER) + # retrieve python environment version from compiler + set (_${_PYTHON_PREFIX}_VERSION_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir") + file (WRITE "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))\n") + execute_process (COMMAND "${${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" + WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}" + OUTPUT_QUIET + ERROR_QUIET) + execute_process (COMMAND "${_${_PYTHON_PREFIX}_VERSION_DIR}/version" + WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}" + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_VERSION + ERROR_QUIET) + if (NOT _${_PYTHON_PREFIX}_RESULT) + string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${_${_PYTHON_PREFIX}_VERSION}") + list (GET _${_PYTHON_PREFIX}_VERSIONS 0 _${_PYTHON_PREFIX}_VERSION_MAJOR) + list (GET _${_PYTHON_PREFIX}_VERSIONS 1 _${_PYTHON_PREFIX}_VERSION_MINOR) + list (GET _${_PYTHON_PREFIX}_VERSIONS 2 _${_PYTHON_PREFIX}_VERSION_PATCH) + + if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND) + # set public version information + set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION}) + set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR}) + set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR}) + set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH}) + endif() + else() + # compiler not usable + set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE) + endif() + file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}") + endif() + + if (${_PYTHON_PREFIX}_COMPILER) + if (${_PYTHON_PREFIX}_Interpreter_FOUND) + # Compiler must be compatible with interpreter + if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) + set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE) + endif() + elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) + set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE) + # Use compiler version for future searches to ensure consistency + set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) + endif() + endif() + + if (${_PYTHON_PREFIX}_Compiler_FOUND) + set (${_PYTHON_PREFIX}_COMPILER_ID IronPython) + else() + unset (${_PYTHON_PREFIX}_COMPILER_ID) + endif() + + mark_as_advanced (${_PYTHON_PREFIX}_COMPILER) +endif() + + +# third step, search for the development artifacts +## Development environment is not compatible with IronPython interpreter +if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS + AND NOT ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython") + if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development) + list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_LIBRARY + ${_PYTHON_PREFIX}_INCLUDE_DIR) + list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_LIBRARY + ${_PYTHON_PREFIX}_LIBRARY_RELEASE + ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE + ${_PYTHON_PREFIX}_LIBRARY_DEBUG + ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG + ${_PYTHON_PREFIX}_INCLUDE_DIR) + endif() + + # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES + unset (_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES) + if (DEFINED ${_PYTHON_PREFIX}_USE_STATIC_LIBS AND NOT WIN32) + set(_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + if(${_PYTHON_PREFIX}_USE_STATIC_LIBS) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + else() + list (REMOVE_ITEM CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + endif() + else() + endif() + + # if python interpreter is found, use its location and version to ensure consistency + # between interpreter and development environment + unset (_${_PYTHON_PREFIX}_PREFIX) + if (${_PYTHON_PREFIX}_Interpreter_FOUND) + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.PREFIX)" + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PREFIX + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + unset (_${_PYTHON_PREFIX}_PREFIX) + endif() + endif() + set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) + + foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) + string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION}) + + # try to use pythonX.Y-config tool + set (_${_PYTHON_PREFIX}_CONFIG_NAMES) + if (DEFINED CMAKE_LIBRARY_ARCHITECTURE) + set (_${_PYTHON_PREFIX}_CONFIG_NAMES "${CMAKE_LIBRARY_ARCHITECTURE}-python${_${_PYTHON_PREFIX}_VERSION}-config") + endif() + list (APPEND _${_PYTHON_PREFIX}_CONFIG_NAMES "python${_${_PYTHON_PREFIX}_VERSION}-config") + find_program (_${_PYTHON_PREFIX}_CONFIG + NAMES ${_${_PYTHON_PREFIX}_CONFIG_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES bin) + unset (_${_PYTHON_PREFIX}_CONFIG_NAMES) + + if (NOT _${_PYTHON_PREFIX}_CONFIG) + continue() + endif() + if (DEFINED CMAKE_LIBRARY_ARCHITECTURE) + # check that config tool match library architecture + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + continue() + endif() + string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) + if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + continue() + endif() + endif() + + # retrieve root install directory + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --prefix + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PREFIX + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_${_PYTHON_PREFIX}_RESULT) + # python-config is not usable + unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + continue() + endif() + set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) + + # retrieve library + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT _${_PYTHON_PREFIX}_RESULT) + # retrieve library directory + string (REGEX MATCHALL "-L[^ ]+" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_FLAGS}") + string (REPLACE "-L" "" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_LIB_DIRS}") + list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_DIRS) + # retrieve library name + string (REGEX MATCHALL "-lpython[^ ]+" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_FLAGS}") + string (REPLACE "-l" "" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_LIB_NAMES}") + list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_NAMES) + + find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} ${_${_PYTHON_PREFIX}_LIB_DIRS} + PATH_SUFFIXES lib + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + # retrieve runtime library + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE) + get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) + _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE + NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_PATH} ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES bin + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + endif() + + # retrieve include directory + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --includes + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT _${_PYTHON_PREFIX}_RESULT) + # retrieve include directory + string (REGEX MATCHALL "-I[^ ]+" _${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_FLAGS}") + string (REPLACE "-I" "" _${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIRS}") + list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_INCLUDE_DIRS) + + find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + NAMES Python.h + HINTS ${_${_PYTHON_PREFIX}_INCLUDE_DIRS} + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_INCLUDE_DIR) + break() + endif() + endforeach() + + # Rely on HINTS and standard paths if config tool failed to locate artifacts + if (NOT (${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) OR NOT ${_PYTHON_PREFIX}_INCLUDE_DIR) + foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) + string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION}) + + _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION}) + + set (_${_PYTHON_PREFIX}_REGISTRY_PATHS + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] + [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]) + + if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") + find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS} + python${_${_PYTHON_PREFIX}_VERSION}mu + python${_${_PYTHON_PREFIX}_VERSION}m + python${_${_PYTHON_PREFIX}_VERSION}u + python${_${_PYTHON_PREFIX}_VERSION} + NAMES_PER_DIR + PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION} + lib/python${_${_PYTHON_PREFIX}_VERSION}/config + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") + find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS} + python${_${_PYTHON_PREFIX}_VERSION}mu + python${_${_PYTHON_PREFIX}_VERSION}m + python${_${_PYTHON_PREFIX}_VERSION}u + python${_${_PYTHON_PREFIX}_VERSION} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION} + lib/python${_${_PYTHON_PREFIX}_VERSION}/config + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + # search in HINTS locations + find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS} + python${_${_PYTHON_PREFIX}_VERSION}mu + python${_${_PYTHON_PREFIX}_VERSION}m + python${_${_PYTHON_PREFIX}_VERSION}u + python${_${_PYTHON_PREFIX}_VERSION} + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION} + lib/python${_${_PYTHON_PREFIX}_VERSION}/config + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + + if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") + set (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}) + else() + unset (__${_PYTHON_PREFIX}_FRAMEWORK_PATHS) + endif() + + if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") + set (__${_PYTHON_PREFIX}_REGISTRY_PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}) + else() + unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS) + endif() + + # search in all default paths + find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS} + python${_${_PYTHON_PREFIX}_VERSION}mu + python${_${_PYTHON_PREFIX}_VERSION}m + python${_${_PYTHON_PREFIX}_VERSION}u + python${_${_PYTHON_PREFIX}_VERSION} + NAMES_PER_DIR + PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATH_SUFFIXES lib/${CMAKE_LIBRARY_ARCHITECTURE} lib libs + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u + lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION} + lib/python${_${_PYTHON_PREFIX}_VERSION}/config) + # retrieve runtime library + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE) + get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) + _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS} + python${_${_PYTHON_PREFIX}_VERSION}mu + python${_${_PYTHON_PREFIX}_VERSION}m + python${_${_PYTHON_PREFIX}_VERSION}u + python${_${_PYTHON_PREFIX}_VERSION} + NAMES_PER_DIR + HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES bin) + endif() + + if (WIN32) + # search for debug library + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE) + # use library location as a hint + get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) + find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d + NAMES_PER_DIR + HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS} + NO_DEFAULT_PATH) + else() + # search first in known locations + if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") + find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATH_SUFFIXES lib libs + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + # search in all default paths + find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d + NAMES_PER_DIR + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATH_SUFFIXES lib libs) + endif() + if (${_PYTHON_PREFIX}_LIBRARY_DEBUG) + get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY) + _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG + NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d + NAMES_PER_DIR + HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS} + PATH_SUFFIXES bin) + endif() + endif() + + # Don't search for include dir until library location is known + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) + unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS) + + if (${_PYTHON_PREFIX}_EXECUTABLE) + # pick up include directory from configuration + execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys; import sysconfig; sys.stdout.write(sysconfig.get_path('include'))" + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PATH + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT _${_PYTHON_PREFIX}_RESULT) + file (TO_CMAKE_PATH "${_${_PYTHON_PREFIX}_PATH}" _${_PYTHON_PREFIX}_PATH) + list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PATH}") + endif() + endif() + + foreach (_${_PYTHON_PREFIX}_LIB IN ITEMS ${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_LIBRARY_DEBUG) + if (${_${_PYTHON_PREFIX}_LIB}) + # Use the library's install prefix as a hint + if (${_${_PYTHON_PREFIX}_LIB} MATCHES "^(.+/Frameworks/Python.framework/Versions/[0-9.]+)") + list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") + elseif (${_${_PYTHON_PREFIX}_LIB} MATCHES "^(.+)/lib(64|32)?/python[0-9.]+/config") + list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") + elseif (DEFINED CMAKE_LIBRARY_ARCHITECTURE AND ${_${_PYTHON_PREFIX}_LIB} MATCHES "^(.+)/lib/${CMAKE_LIBRARY_ARCHITECTURE}") + list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") + else() + # assume library is in a directory under root + get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${${_${_PYTHON_PREFIX}_LIB}}" DIRECTORY) + get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_PREFIX}" DIRECTORY) + list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PREFIX}") + endif() + endif() + endforeach() + list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_INCLUDE_HINTS) + + if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") + find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + NAMES Python.h + HINTS ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + PATH_SUFFIXES include/python${_${_PYTHON_PREFIX}_VERSION}mu + include/python${_${_PYTHON_PREFIX}_VERSION}m + include/python${_${_PYTHON_PREFIX}_VERSION}u + include/python${_${_PYTHON_PREFIX}_VERSION} + include + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") + find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + NAMES Python.h + HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATH_SUFFIXES include/python${_${_PYTHON_PREFIX}_VERSION}mu + include/python${_${_PYTHON_PREFIX}_VERSION}m + include/python${_${_PYTHON_PREFIX}_VERSION}u + include/python${_${_PYTHON_PREFIX}_VERSION} + include + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + NAMES Python.h + HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} + PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} + ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} + PATH_SUFFIXES include/python${_${_PYTHON_PREFIX}_VERSION}mu + include/python${_${_PYTHON_PREFIX}_VERSION}m + include/python${_${_PYTHON_PREFIX}_VERSION}u + include/python${_${_PYTHON_PREFIX}_VERSION} + include + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + + if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) AND ${_PYTHON_PREFIX}_INCLUDE_DIR) + break() + endif() + endforeach() + + # search header file in standard locations + find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + NAMES Python.h) + endif() + + if (${_PYTHON_PREFIX}_INCLUDE_DIR) + # retrieve version from header file + file (STRINGS "${${_PYTHON_PREFIX}_INCLUDE_DIR}/patchlevel.h" _${_PYTHON_PREFIX}_VERSION + REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"") + string (REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1" + _${_PYTHON_PREFIX}_VERSION "${_${_PYTHON_PREFIX}_VERSION}") + string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${_${_PYTHON_PREFIX}_VERSION}") + list (GET _${_PYTHON_PREFIX}_VERSIONS 0 _${_PYTHON_PREFIX}_VERSION_MAJOR) + list (GET _${_PYTHON_PREFIX}_VERSIONS 1 _${_PYTHON_PREFIX}_VERSION_MINOR) + list (GET _${_PYTHON_PREFIX}_VERSIONS 2 _${_PYTHON_PREFIX}_VERSION_PATCH) + + if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT ${_PYTHON_PREFIX}_Compiler_FOUND) + # set public version information + set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION}) + set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR}) + set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR}) + set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH}) + endif() + endif() + + # define public variables + include (SelectLibraryConfigurations) + select_library_configurations (${_PYTHON_PREFIX}) + if (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE) + set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}") + elseif (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) + set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}") + else() + set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "$${_PYTHON_PREFIX}_RUNTIME_LIBRARY-NOTFOUND") + endif() + + _python_set_library_dirs (${_PYTHON_PREFIX}_LIBRARY_DIRS + ${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_LIBRARY_DEBUG) + if (UNIX) + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$" + OR ${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$") + set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS ${${_PYTHON_PREFIX}_LIBRARY_DIRS}) + endif() + else() + _python_set_library_dirs (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS + ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) + endif() + + set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${${_PYTHON_PREFIX}_INCLUDE_DIR}") + + mark_as_advanced (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE + ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG + ${_PYTHON_PREFIX}_INCLUDE_DIR) + + if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) + AND ${_PYTHON_PREFIX}_INCLUDE_DIR) + if (${_PYTHON_PREFIX}_Interpreter_FOUND OR ${_PYTHON_PREFIX}_Compiler_FOUND) + # development environment must be compatible with interpreter/compiler + if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) + set (${_PYTHON_PREFIX}_Development_FOUND TRUE) + endif() + elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) + set (${_PYTHON_PREFIX}_Development_FOUND TRUE) + endif() + endif() + + # Restore the original find library ordering + if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES) + set (CMAKE_FIND_LIBRARY_SUFFIXES ${_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES}) + endif() +endif() + +# final validation +if (${_PYTHON_PREFIX}_VERSION_MAJOR AND + NOT ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) + _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Found unsuitable major version \"${${_PYTHON_PREFIX}_VERSION_MAJOR}\", but required major version is exact version \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"") +endif() + +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (${_PYTHON_PREFIX} + REQUIRED_VARS ${_${_PYTHON_PREFIX}_REQUIRED_VARS} + VERSION_VAR ${_PYTHON_PREFIX}_VERSION + HANDLE_COMPONENTS) + +# Create imported targets and helper functions +if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS + AND ${_PYTHON_PREFIX}_Interpreter_FOUND + AND NOT TARGET ${_PYTHON_PREFIX}::Interpreter) + add_executable (${_PYTHON_PREFIX}::Interpreter IMPORTED) + set_property (TARGET ${_PYTHON_PREFIX}::Interpreter + PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_EXECUTABLE}") +endif() + +if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS + AND ${_PYTHON_PREFIX}_Compiler_FOUND + AND NOT TARGET ${_PYTHON_PREFIX}::Compiler) + add_executable (${_PYTHON_PREFIX}::Compiler IMPORTED) + set_property (TARGET ${_PYTHON_PREFIX}::Compiler + PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_COMPILER}") +endif() + +if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS + AND ${_PYTHON_PREFIX}_Development_FOUND AND NOT TARGET ${_PYTHON_PREFIX}::Python) + + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$" + OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$" + OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) + set (_${_PYTHON_PREFIX}_LIBRARY_TYPE SHARED) + else() + set (_${_PYTHON_PREFIX}_LIBRARY_TYPE STATIC) + endif() + + add_library (${_PYTHON_PREFIX}::Python ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED) + + set_property (TARGET ${_PYTHON_PREFIX}::Python + PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIR}") + + if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE) + OR (${_PYTHON_PREFIX}_LIBRARY_DEBUG AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)) + # System manage shared libraries in two parts: import and runtime + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG) + set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG) + set_target_properties (${_PYTHON_PREFIX}::Python + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_IMPLIB_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" + IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}") + set_target_properties (${_PYTHON_PREFIX}::Python + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" + IMPORTED_IMPLIB_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}" + IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}") + else() + set_target_properties (${_PYTHON_PREFIX}::Python + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_IMPLIB "${${_PYTHON_PREFIX}_LIBRARY}" + IMPORTED_LOCATION "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY}") + endif() + else() + if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG) + set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG) + set_target_properties (${_PYTHON_PREFIX}::Python + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}") + set_target_properties (${_PYTHON_PREFIX}::Python + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" + IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}") + else() + set_target_properties (${_PYTHON_PREFIX}::Python + PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${${_PYTHON_PREFIX}_LIBRARY}") + endif() + endif() + + if (_${_PYTHON_PREFIX}_CONFIG AND _${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC") + # extend link information with dependent libraries + execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT _${_PYTHON_PREFIX}_RESULT) + string (REGEX MATCHALL "-[Ll][^ ]+" _${_PYTHON_PREFIX}_LINK_LIBRARIES "${_${_PYTHON_PREFIX}_FLAGS}") + # remove elements relative to python library itself + list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-lpython") + foreach (_${_PYTHON_PREFIX}_DIR IN LISTS ${_PYTHON_PREFIX}_LIBRARY_DIRS) + list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-L${${_PYTHON_PREFIX}_DIR}") + endforeach() + set_property (TARGET ${_PYTHON_PREFIX}::Python + PROPERTY INTERFACE_LINK_LIBRARIES ${_${_PYTHON_PREFIX}_LINK_LIBRARIES}) + endif() + endif() + + # + # PYTHON_ADD_LIBRARY ( [STATIC|SHARED|MODULE] src1 src2 ... srcN) + # It is used to build modules for python. + # + function (__${_PYTHON_PREFIX}_ADD_LIBRARY prefix name) + cmake_parse_arguments (PARSE_ARGV 2 PYTHON_ADD_LIBRARY + "STATIC;SHARED;MODULE" "" "") + + unset (type) + if (NOT (PYTHON_ADD_LIBRARY_STATIC + OR PYTHON_ADD_LIBRARY_SHARED + OR PYTHON_ADD_LIBRARY_MODULE)) + set (type MODULE) + endif() + add_library (${name} ${type} ${ARGN}) + target_link_libraries (${name} PRIVATE ${prefix}::Python) + + # customize library name to follow module name rules + get_property (type TARGET ${name} PROPERTY TYPE) + if (type STREQUAL "MODULE_LIBRARY") + set_property (TARGET ${name} PROPERTY PREFIX "") + if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set_property (TARGET ${name} PROPERTY SUFFIX ".pyd") + endif() + endif() + endfunction() +endif() + +# final clean-up + +# Restore CMAKE_FIND_APPBUNDLE +if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE) + set (CMAKE_FIND_APPBUNDLE ${_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE}) + unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE) +else() + unset (CMAKE_FIND_APPBUNDLE) +endif() +# Restore CMAKE_FIND_FRAMEWORK +if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK) + set (CMAKE_FIND_FRAMEWORK ${_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK}) + unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK) +else() + unset (CMAKE_FIND_FRAMEWORK) +endif() + +unset (_${_PYTHON_PREFIX}_CONFIG CACHE) diff --git a/cmake/FindPython2.cmake b/cmake/FindPython2.cmake new file mode 100644 index 000000000..998e99223 --- /dev/null +++ b/cmake/FindPython2.cmake @@ -0,0 +1,171 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindPython2 +----------- + +Find Python 2 interpreter, compiler and development environment (include +directories and libraries). + +Three components are supported: + +* ``Interpreter``: search for Python 2 interpreter +* ``Compiler``: search for Python 2 compiler. Only offered by IronPython. +* ``Development``: search for development artifacts (include directories and + libraries) + +If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed. + +To ensure consistent versions between components ``Interpreter``, ``Compiler`` +and ``Development``, specify all components at the same time:: + + find_package (Python2 COMPONENTS Interpreter Development) + +This module looks only for version 2 of Python. This module can be used +concurrently with :module:`FindPython3` module to use both Python versions. + +The :module:`FindPython` module can be used if Python version does not matter +for you. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module defines the following :ref:`Imported Targets `: + +``Python2::Interpreter`` + Python 2 interpreter. Target defined if component ``Interpreter`` is found. +``Python2::Compiler`` + Python 2 compiler. Target defined if component ``Compiler`` is found. +``Python2::Python`` + Python 2 library. Target defined if component ``Development`` is found. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module will set the following variables in your project +(see :ref:`Standard Variable Names `): + +``Python2_FOUND`` + System has the Python 2 requested components. +``Python2_Interpreter_FOUND`` + System has the Python 2 interpreter. +``Python2_EXECUTABLE`` + Path to the Python 2 interpreter. +``Python2_INTERPRETER_ID`` + A short string unique to the interpreter. Possible values include: + * Python + * ActivePython + * Anaconda + * Canopy + * IronPython +``Python2_STDLIB`` + Standard platform independent installation directory. + + Information returned by + ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)``. +``Python2_STDARCH`` + Standard platform dependent installation directory. + + Information returned by + ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)``. +``Python2_SITELIB`` + Third-party platform independent installation directory. + + Information returned by + ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)``. +``Python2_SITEARCH`` + Third-party platform dependent installation directory. + + Information returned by + ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``. +``Python2_Compiler_FOUND`` + System has the Python 2 compiler. +``Python2_COMPILER`` + Path to the Python 2 compiler. Only offered by IronPython. +``Python2_COMPILER_ID`` + A short string unique to the compiler. Possible values include: + * IronPython +``Python2_Development_FOUND`` + System has the Python 2 development artifacts. +``Python2_INCLUDE_DIRS`` + The Python 2 include directories. +``Python2_LIBRARIES`` + The Python 2 libraries. +``Python2_LIBRARY_DIRS`` + The Python 2 library directories. +``Python2_RUNTIME_LIBRARY_DIRS`` + The Python 2 runtime library directories. +``Python2_VERSION`` + Python 2 version. +``Python2_VERSION_MAJOR`` + Python 2 major version. +``Python2_VERSION_MINOR`` + Python 2 minor version. +``Python2_VERSION_PATCH`` + Python 2 patch version. + +Hints +^^^^^ + +``Python2_ROOT_DIR`` + Define the root directory of a Python 2 installation. + +``Python2_USE_STATIC_LIBS`` + * If not defined, search for shared libraries and static libraries in that + order. + * If set to TRUE, search **only** for static libraries. + * If set to FALSE, search **only** for shared libraries. + +``Python2_FIND_REGISTRY`` + On Windows the ``Python2_FIND_REGISTRY`` variable determine the order + of preference between registry and environment variables. + the ``Python2_FIND_REGISTRY`` variable can be set to empty or one of the + following: + + * ``FIRST``: Try to use registry before environment variables. + This is the default. + * ``LAST``: Try to use registry after environment variables. + * ``NEVER``: Never try to use registry. + +``CMAKE_FIND_FRAMEWORK`` + On macOS the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of + preference between Apple-style and unix-style package components. + + .. note:: + + Value ``ONLY`` is not supported so ``FIRST`` will be used instead. + +.. note:: + + If a Python virtual environment is configured, set variable + ``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with + value ``LAST`` or ``NEVER`` to select it preferably. + +Commands +^^^^^^^^ + +This module defines the command ``Python2_add_library`` which have the same +semantic as :command:`add_library` but take care of Python module naming rules +(only applied if library is of type ``MODULE``) and add dependency to target +``Python2::Python``:: + + Python2_add_library (my_module MODULE src1.cpp) + +If library type is not specified, ``MODULE`` is assumed. +#]=======================================================================] + + +set (_PYTHON_PREFIX Python2) + +set (_Python2_REQUIRED_VERSION_MAJOR 2) + +include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake) + +if (COMMAND __Python2_add_library) + macro (Python2_add_library) + __Python2_add_library (Python2 ${ARGV}) + endmacro() +endif() + +unset (_PYTHON_PREFIX) diff --git a/cmake/PrettyCompilerColors.cmake b/cmake/PrettyCompilerColors.cmake new file mode 100644 index 000000000..42f0aeb9b --- /dev/null +++ b/cmake/PrettyCompilerColors.cmake @@ -0,0 +1,21 @@ +include(CheckCCompilerFlag) + +if(CMAKE_C_COMPILER_ID STREQUAL GNU) + unset(COMPILER_COLOR_DIAGNOSTICS) + check_c_compiler_flag(-fdiagnostics-color=always COMPILER_COLOR_DIAGNOSTICS) + if(COMPILER_COLOR_DIAGNOSTICS) + add_compile_options(-fdiagnostics-color=always) + else() + unset(COMPILER_COLOR_DIAGNOSTICS) + check_c_compiler_flag(-fdiagnostics-color COMPILER_COLOR_DIAGNOSTICS) + if(COMPILER_COLOR_DIAGNOSTICS) + add_compile_options(-fdiagnostics-color) + endif() + endif() +elseif(CMAKE_C_COMPILER_ID STREQUAL Clang) + unset(COMPILER_COLOR_DIAGNOSTICS) + check_c_compiler_flag(-fcolor-diagnostics COMPILER_COLOR_DIAGNOSTICS) + if(COMPILER_COLOR_DIAGNOSTICS) + add_compile_options(-fcolor-diagnostics) + endif() +endif() diff --git a/cmake/Set-Toolchain-vcpkg.cmake b/cmake/Set-Toolchain-vcpkg.cmake new file mode 100644 index 000000000..b3abef6b5 --- /dev/null +++ b/cmake/Set-Toolchain-vcpkg.cmake @@ -0,0 +1,56 @@ +if(VCPKG_TARGET_TRIPLET) + if(NOT DEFINED ENV{VCPKG_ROOT}) + get_filename_component(VCPKG_ROOT ${CMAKE_SOURCE_DIR}/../vcpkg ABSOLUTE) + set(ENV{VCPKG_ROOT} ${VCPKG_ROOT}) + else() + set(VCPKG_ROOT $ENV{VCPKG_ROOT}) + endif() + + if(NOT EXISTS ${VCPKG_ROOT}) + get_filename_component(vcpkg_root_parent ${VCPKG_ROOT}/.. ABSOLUTE) + + execute_process( + COMMAND git clone https://github.com/microsoft/vcpkg.git + RESULT_VARIABLE git_status + WORKING_DIRECTORY ${vcpkg_root_parent} + ) + + if(NOT git_status EQUAL 0) + message(FATAL_ERROR "Error cloning vcpkg, please make sure git for windows is installed correctly, it can be installed from Visual Studio components") + endif() + endif() + + # build vcpkg if not built + if(WIN32) + if(NOT EXISTS ${VCPKG_ROOT}/vcpkg.exe) + execute_process( + COMMAND bootstrap-vcpkg.bat + WORKING_DIRECTORY ${VCPKG_ROOT} + ) + endif() + else() + if(NOT EXISTS ${VCPKG_ROOT}/vcpkg) + execute_process( + COMMAND bootstrap-vcpkg.sh + WORKING_DIRECTORY ${VCPKG_ROOT} + ) + endif() + endif() + + foreach(pkg ${VCPKG_DEPS}) + list(APPEND VCPKG_DEPS_QUALIFIED ${pkg}:${VCPKG_TARGET_TRIPLET}) + endforeach() + + # build our deps + execute_process( + COMMAND vcpkg install ${VCPKG_DEPS_QUALIFIED} + WORKING_DIRECTORY ${VCPKG_ROOT} + ) + + if(WIN32 AND VCPKG_TARGET_TRIPLET MATCHES x64) + set(CMAKE_GENERATOR_PLATFORM x64 CACHE STRING "visual studio build architecture" FORCE) + endif() + + set(CMAKE_TOOLCHAIN_FILE ${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake CACHE FILEPATH "vcpkg toolchain" FORCE) + include(${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake) +endif() diff --git a/cmake/scripts/RewriteArmoryScriptPrefix.cmake b/cmake/scripts/RewriteArmoryScriptPrefix.cmake new file mode 100644 index 000000000..ca4e33630 --- /dev/null +++ b/cmake/scripts/RewriteArmoryScriptPrefix.cmake @@ -0,0 +1,15 @@ +file(READ ${script_file} script_contents) + +string(REGEX REPLACE " /usr" " ${prefix}" script_edited ${script_contents}) + +file(MAKE_DIRECTORY ${script_dir}/script_tmp) + +file(WRITE ${script_dir}/script_tmp/${script_output_file} ${script_edited}) + +file( + COPY ${script_dir}/script_tmp/${script_output_file} + DESTINATION ${script_dir} + FILE_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) + +file(REMOVE ${script_dir}/script_tmp) diff --git a/configure.ac b/configure.ac index 853b2ea7f..2681c1ed2 100644 --- a/configure.ac +++ b/configure.ac @@ -89,7 +89,7 @@ AM_CONDITIONAL([BUILD_GUI], [test x$build_gui = xyes]) AC_PROG_CC AC_PROG_CXX -AM_CONDITIONAL([HAVE_GCC], [test $CXX = g++]) +AM_CONDITIONAL([HAVE_GCC], [$CXX -v 2>&1 | grep -q 'g++']) AC_CHECK_SIZEOF([long unsigned int]) AM_CONDITIONAL([HAVE_64BIT], [test $ac_cv_sizeof_long_unsigned_int = 8]) @@ -279,6 +279,8 @@ if test x$LWS_WITH_TLS_FOUND = xyes; then ]) AC_MSG_RESULT($CRYPTO_LIBDIR) AC_SUBST([CRYPTO_LIBDIR]) + CRYPTO_LDFLAGS=$(pkg-config --libs --static libcrypto 2>/dev/null) + AC_SUBST([CRYPTO_LDFLAGS]) fi AC_MSG_CHECKING(for LWS_WITH_LIBUV) @@ -385,6 +387,7 @@ export LDFLAGS AM_CONDITIONAL([HAVE_CLANG], [test x$CLANG = xyes]) AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin]) +AM_CONDITIONAL([BUILD_LINUX], [test x$BUILD_OS = xlinux]) AC_CONFIG_FILES(Makefile cppForSwig/Makefile diff --git a/cppForSwig/BlockUtils.h b/cppForSwig/BlockUtils.h index aabf78b06..da77e367c 100644 --- a/cppForSwig/BlockUtils.h +++ b/cppForSwig/BlockUtils.h @@ -48,11 +48,7 @@ #endif #ifdef _MSC_VER - #include "mman.h" - //#include "leveldb_windows_port\win32_posix\win32_posix.h" - #else #include - #include #endif diff --git a/cppForSwig/CMakeLists.txt b/cppForSwig/CMakeLists.txt new file mode 100644 index 000000000..dd180e593 --- /dev/null +++ b/cppForSwig/CMakeLists.txt @@ -0,0 +1,578 @@ +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +add_subdirectory(chacha20poly1305) +add_subdirectory(lmdb/libraries/liblmdb) + +# this is the right way to set options for sub-projects +# we allow these to be overridden by the user +if(NOT DEFINED LIBBTC_WITH_WALLET) + set(LIBBTC_WITH_WALLET OFF CACHE BOOL "disable libbtc wallet" FORCE) +endif() + +if(NOT DEFINED LIBBTC_WITH_NET) + set(LIBBTC_WITH_NET OFF CACHE BOOL "disable libbtc networking" FORCE) +endif() + +if(NOT DEFINED LIBBTC_WITH_TOOLS) + set(LIBBTC_WITH_TOOLS OFF CACHE BOOL "disable libbtc tools" FORCE) +endif() + +if(NOT DEFINED LIBBTC_WITH_TESTS) + set(LIBBTC_WITH_TESTS OFF CACHE BOOL "do not build libbtc tests" FORCE) +endif() + +add_subdirectory(libbtc) + +set(LIBARMORYCOMMON_INCLUDE_DIRECTORIES + PUBLIC lmdb/libraries/liblmdb + PUBLIC . + PRIVATE bech32/ref/c++ + PRIVATE chacha20poly1305 + PRIVATE libbtc/src/secp256k1/include + PRIVATE libbtc/include + PRIVATE ${PROJECT_BINARY_DIR} # for protobuf protoc genned .h files +) + +set(LIBARMORYCOMMON_LINK_LIBRARIES + chacha20poly1305 + btc + lmdb +) + +if(NOT MSVC) + list(APPEND LIBARMORYCOMMON_LINK_LIBRARIES + pthread + ) +endif() + +option(WITH_CRYPTOPP "use Crypto++ crypto functions" OFF) + +unset(LIBARMORYCOMMON_SOURCES) +unset(LIBARMORYCOMMON_COMPILE_DEFINITIONS) + +if(WITH_CRYPTOPP) + add_subdirectory(cryptopp) + + list(APPEND LIBARMORYCOMMON_SOURCES EncryptionUtils.cpp) + + list(APPEND LIBARMORYCOMMON_LINK_LIBRARIES + cryptopp + ) +else() + list(APPEND LIBARMORYCOMMON_COMPILE_DEFINITIONS + PRIVATE LIBBTC_ONLY + ) + + list(APPEND LIBARMORYCOMMON_SOURCES EncryptionUtils_libbtc.cpp) +endif() + +if(CMAKE_TOOLCHAIN_FILE MATCHES vcpkg) + find_package(Libwebsockets CONFIG REQUIRED) + set(LIBWEBSOCKETS_LIBRARIES websockets_shared) +else() + find_package(PkgConfig REQUIRED) + + pkg_check_modules(LIBWEBSOCKETS REQUIRED libwebsockets>=3.0.1) +endif() + +list(APPEND LIBARMORYCOMMON_INCLUDE_DIRECTORIES + PRIVATE ${LIBWEBSOCKETS_INCLUDE_DIRS} +) + +list(APPEND LIBARMORYCOMMON_LINK_LIBRARIES + ${LIBWEBSOCKETS_LIBRARIES} +) + +include(CheckCXXSymbolExists) + +check_cxx_symbol_exists(LWS_WITH_TLS lws_config.h LIBWEBSOCKETS_WITH_TLS) + +if(LIBWEBSOCKETS_WITH_TLS) + if(APPLE) + set(OPENSSL_ROOT_DIR /usr/local/opt/openssl) + endif() + + find_package(OpenSSL REQUIRED) + + list(APPEND LIBARMORYCOMMON_INCLUDE_DIRECTORIES + PUBLIC ${OPENSSL_INCLUDE_DIR} + ) + + list(APPEND LIBARMORYCOMMON_LINK_LIBRARIES + ${OPENSSL_LIBRARIES} + ) +endif() + +check_cxx_symbol_exists(LWS_WITH_LIBUV lws_config.h LIBWEBSOCKETS_WITH_LIBUV) + +if(LIBWEBSOCKETS_WITH_LIBUV) + pkg_check_modules(LIBUV REQUIRED libuv) + + list(APPEND LIBARMORYCOMMON_LINK_LIBRARIES + ${LIBUV_LIBRARIES} + ) +endif() + +check_cxx_symbol_exists(LWS_WITH_LIBEVENT lws_config.h LIBWEBSOCKETS_WITH_LIBEVENT) + +if(LIBWEBSOCKETS_WITH_LIBEVENT) + pkg_check_modules(LIBEVENT REQUIRED libevent) + + list(APPEND LIBARMORYCOMMON_LINK_LIBRARIES + ${LIBEVENT_LIBRARIES} + ) +endif() + +check_cxx_symbol_exists(LWS_WITH_LIBCAP lws_config.h LIBWEBSOCKETS_WITH_LIBCAP) + +if(LIBWEBSOCKETS_WITH_LIBCAP) + pkg_check_modules(LIBCAP REQUIRED libcap) + + list(APPEND LIBARMORYCOMMON_LINK_LIBRARIES + ${LIBCAP_LIBRARIES} + ) +endif() + +if(CMAKE_TOOLCHAIN_FILE MATCHES vcpkg) + find_package(protobuf CONFIG REQUIRED) + set(PROTOBUF_LIBRARIES protobuf::libprotoc protobuf::libprotobuf) +else() + pkg_check_modules(PROTOBUF REQUIRED protobuf>=2.0.0) +endif() + +list(APPEND LIBARMORYCOMMON_INCLUDE_DIRECTORIES + PRIVATE ${PROTOBUF_INCLUDE_DIRS} +) + +list(APPEND LIBARMORYCOMMON_LINK_LIBRARIES + ${PROTOBUF_LIBRARIES} +) + +list(APPEND LIBARMORYCOMMON_SOURCES + Accounts.cpp + Addresses.cpp + AssetEncryption.cpp + Assets.cpp + AsyncClient.cpp + AuthorizedPeers.cpp + BinaryData.cpp + BIP32_Node.cpp + BlockDataManagerConfig.cpp + BtcUtils.cpp + ClientClasses.cpp + CoinSelection.cpp + DecryptedDataContainer.cpp + DerivationScheme.cpp + hkdf.cpp + KDF.cpp + log.cpp + NetworkConfig.cpp + ReentrantLock.cpp + Script.cpp + SecureBinaryData.cpp + ScriptRecipient.cpp + Signer.cpp + SocketObject.cpp + StoredBlockObj.cpp + SwigClient.cpp + Transactions.cpp + TxClasses.cpp + TxEvalState.cpp + txio.cpp + UniversalTimer.cpp + WalletManager.cpp + Wallets.cpp + WebSocketClient.cpp + WebSocketMessage.cpp + DBUtils.cpp + bech32/ref/c++/bech32.cpp + bech32/ref/c++/segwit_addr.cpp +) + +set(PROTOBUF_FILES + AddressBook.proto + AddressData.proto + BDVCommand.proto + CommonTypes.proto + FeeEstimate.proto + LedgerEntry.proto + NodeStatus.proto + Utxo.proto +) + +find_program(PROTOC_EXECUTABLE protoc) + +if(NOT PROTOC_EXECUTABLE) + message(FATAL_ERROR "protocol buffers compiler 'protoc' not found") +endif() + +file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/protobuf) + +foreach(proto ${PROTOBUF_FILES}) + string(REGEX REPLACE "\\.proto$" ".pb.cc" proto_cc ${proto}) + + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/protobuf/${proto_cc} + COMMAND ${PROTOC_EXECUTABLE} --cpp_out=${PROJECT_BINARY_DIR}/protobuf --proto_path=${CMAKE_CURRENT_SOURCE_DIR}/protobuf ${CMAKE_CURRENT_SOURCE_DIR}/protobuf/${proto} + DEPENDS protobuf/${proto} + ) + + list(APPEND LIBARMORYCOMMON_SOURCES ${PROJECT_BINARY_DIR}/protobuf/${proto_cc}) +endforeach() + +add_library(ArmoryCommon + STATIC + ${LIBARMORYCOMMON_SOURCES} +) + +target_compile_definitions(ArmoryCommon + PUBLIC __STDC_LIMIT_MACROS + ${LIBARMORYCOMMON_COMPILE_DEFINITIONS} +) + +target_include_directories(ArmoryCommon + ${LIBARMORYCOMMON_INCLUDE_DIRECTORIES} +) + +target_link_libraries(ArmoryCommon + ${LIBARMORYCOMMON_LINK_LIBRARIES} +) + +set(LIBARMORYCLI_SOURCES + BDM_mainthread.cpp + BDM_Server.cpp + BIP150_151.cpp + BitcoinP2P.cpp + Blockchain.cpp + BlockchainScanner.cpp + BlockchainScanner_Super.cpp + BlockDataMap.cpp + BlockDataViewer.cpp + BlockObj.cpp + BlockUtils.cpp + BtcWallet.cpp + DatabaseBuilder.cpp + HistoryPager.cpp + HttpMessage.cpp + JSON_codec.cpp + LedgerEntry.cpp + lmdb_wrapper.cpp + nodeRPC.cpp + Progress.cpp + ScrAddrFilter.cpp + ScrAddrObj.cpp + Server.cpp + SshParser.cpp + StringSockets.cpp + txio.cpp + ZeroConf.cpp +) + +if(MSVC) + list(APPEND LIBARMORYCLI_SOURCES + SocketService_win32.cpp + ) +else() + list(APPEND LIBARMORYCLI_SOURCES + SocketService_unix.cpp + ) +endif() + +add_library(ArmoryCLI + STATIC + ${LIBARMORYCLI_SOURCES} +) + +target_link_libraries(ArmoryCLI + ArmoryCommon +) + +target_compile_definitions(ArmoryCLI + PUBLIC -D__STDC_LIMIT_MACROS +) + +string_option(WITH_GUI "with GUI" AUTO) + +find_package(Qt4 COMPONENTS QtGui QUIET) + +find_program(PYRCC4_EXECUTABLE pyrcc4) +find_program(LRELEASE_EXECUTABLE lrelease) + +if(WITH_GUI STREQUAL AUTO) + if(Qt4_FOUND AND PYRCC4_EXECUTABLE AND LRELEASE_EXECUTABLE) + set(WITH_GUI ON) + else() + set(WITH_GUI OFF) + endif() +endif() + +if(WITH_GUI) + if(NOT PYRCC4_EXECUTABLE) + message(FATAL_ERROR "pyrcc4 not found, install python2-qt4-devel") + endif() + + if(NOT LRELEASE_EXECUTABLE) + message(FATAL_ERROR "lrelease not found, install qt4-linguist") + endif() + + add_library(ArmoryGUI + TransactionBatch.cpp + ) + + target_link_libraries(ArmoryGUI + ArmoryCommon + Qt4::QtGui + ) + + target_compile_definitions(ArmoryGUI + PUBLIC -D__STDC_LIMIT_MACROS + ) +endif() + +add_executable(ArmoryDB + main.cpp +) + +set_target_properties(ArmoryDB + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR} +) + +target_link_libraries(ArmoryDB + ArmoryCLI +) + +include(GNUInstallDirs) + +install(TARGETS ArmoryDB DESTINATION ${CMAKE_INSTALL_BINDIR}) + +add_executable(BIP150KeyManager + KeyManager.cpp +) + +set_target_properties(BIP150KeyManager + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR} +) + +target_link_libraries(BIP150KeyManager + ArmoryCLI +) + +install(TARGETS BIP150KeyManager DESTINATION ${CMAKE_INSTALL_BINDIR}) + +string_option(WITH_CLIENT "build python client" AUTO) + +find_package(Python2 COMPONENTS Development QUIET) + +find_program(SWIG_EXECUTABLE swig) + +if(WITH_CLIENT STREQUAL AUTO) + if(Python2_Development_FOUND AND SWIG_EXECUTABLE) + set(WITH_CLIENT ON) + else() + set(WITH_CLIENT OFF) + endif() +endif() + +if(WITH_CLIENT) + if(NOT Python2_Development_FOUND) + message(FATAL_ERROR "python 2 development files not found, install python-dev") + endif() + + if(NOT SWIG_EXECUTABLE) + message(FATAL_ERROR "swig not found") + endif() + + set(CPPBLOCKUTILS_SOURCES + ${PROJECT_BINARY_DIR}/CppBlockUtils_wrap.cxx + ) + + unset(SWIG_OPTS) + + if(CMAKE_COMPILER_IS_GNUCXX) + set(SWIG_OPTS -D__GNUC__) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL Clang) + set(SWIG_OPTS -D__CLANG__) + endif() + + if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 8) # 64 bit + set(SWIG_OPTS ${SWIG_OPTS} -D__LP64__) + endif() + + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/CppBlockUtils_wrap.cxx + COMMAND ${SWIG_EXECUTABLE} -c++ -python -threads ${SWIG_OPTS} -o ${PROJECT_BINARY_DIR}/CppBlockUtils_wrap.cxx ${CMAKE_CURRENT_SOURCE_DIR}/CppBlockUtils.i + DEPENDS CppBlockUtils.i + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ) + + set(CPPBLOCKUTILS_LINK_LIBRARIES + ArmoryCommon + Python2::Python + ) + + add_library(CppBlockUtils + SHARED + ${CPPBLOCKUTILS_SOURCES} + ) + + set_target_properties(CppBlockUtils + PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR} + ) + + # remove "lib" prefix + set_target_properties(CppBlockUtils + PROPERTIES PREFIX "" + ) + + target_include_directories(CppBlockUtils + PUBLIC Python2::Python + ) + + # copy CppBlockUtils.so to _CppBlockUtils.so as well, why I don't know + add_custom_command( + TARGET CppBlockUtils POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${PROJECT_BINARY_DIR}/CppBlockUtils${CMAKE_SHARED_LIBRARY_SUFFIX} + ${PROJECT_BINARY_DIR}/_CppBlockUtils${CMAKE_SHARED_LIBRARY_SUFFIX} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ) + + if(WITH_GUI) + list(APPEND CPPBLOCKUTILS_LINK_LIBRARIES + ArmoryGUI + ) + + # this mechanism for dependent custom targets I found here: + # https://cmake.org/pipermail/cmake/2010-March/035621.html + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/qrc_img_resources.py + COMMAND ${PYRCC4_EXECUTABLE} -o ${PROJECT_BINARY_DIR}/qrc_img_resources.py ${PROJECT_SOURCE_DIR}/imgList.xml + DEPENDS ${PROJECT_SOURCE_DIR}/imgList.xml + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ) + + add_custom_target(qrc_img_resources_py DEPENDS ${PROJECT_BINARY_DIR}/qrc_img_resources.py) + + file(COPY ${PROJECT_SOURCE_DIR}/lang DESTINATION ${PROJECT_BINARY_DIR}) + + set(LANG_SOURCES + armory_da.ts + armory_de.ts + armory_el.ts + armory_en.ts + armory_es.ts + armory_fr.ts + armory_he.ts + armory_hr.ts + armory_id.ts + armory_ru.ts + armory_sv.ts + ) + + unset(LANG_QM_FILES) + + foreach(lang_file ${LANG_SOURCES}) + string(REGEX REPLACE "\\.ts$" ".qm" lang_qm_file ${lang_file}) + + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/lang/${lang_qm_file} + COMMAND ${LRELEASE_EXECUTABLE} ${PROJECT_BINARY_DIR}/lang/${lang_file} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/lang + ) + + list(APPEND LANG_QM_FILES + ${PROJECT_BINARY_DIR}/lang/${lang_qm_file} + ) + endforeach() + + add_custom_target(lang_lrelease DEPENDS ${LANG_QM_FILES}) + + add_dependencies(CppBlockUtils + qrc_img_resources_py + lang_lrelease + ) + + install(CODE "file(MAKE_DIRECTORY ${CMAKE_INSTALL_LIBDIR}/armory/ui)") + + install(CODE "file(MAKE_DIRECTORY ${CMAKE_INSTALL_LIBDIR}/armory/lang)") + + install(DIRECTORY ../ui DESTINATION ${CMAKE_INSTALL_LIBDIR}/armory) + + install(DIRECTORY ${PROJECT_BINARY_DIR}/lang + DESTINATION ${CMAKE_INSTALL_LIBDIR}/armory + FILES_MATCHING PATTERN "*.qm" + ) + endif() + + target_link_libraries(CppBlockUtils + ${CPPBLOCKUTILS_LINK_LIBRARIES} + ) + + # rewrite prefix for armory script + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/armory + COMMAND ${CMAKE_COMMAND} -Dscript_file=${PROJECT_SOURCE_DIR}/dpkgfiles/armory + -Dscript_output_file=${PROJECT_BINARY_DIR}/armory + -Dscript_dir=${PROJECT_BINARY_DIR} + -Dprefix=${CMAKE_INSTALL_PREFIX} + -P ${PROJECT_SOURCE_DIR}/cmake/scripts/RewriteArmoryScriptPrefix.cmake + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ) + + add_custom_target(armory_script DEPENDS ${PROJECT_BINARY_DIR}/armory) + + add_dependencies(CppBlockUtils armory_script) + + install(PROGRAMS ${PROJECT_BINARY_DIR}/armory DESTINATION ${CMAKE_INSTALL_BINDIR}) + + install(CODE "file(MAKE_DIRECTORY ${CMAKE_INSTALL_LIBDIR}/armory/armoryengine)") + + install(CODE "file(MAKE_DIRECTORY ${CMAKE_INSTALL_DATAROOTDIR}/applications)") # share/applications + + install( + TARGETS CppBlockUtils + DESTINATION ${CMAKE_INSTALL_LIBDIR}/armory + ) + + # copy the underscore prefixed version too + install( + FILES ${PROJECT_BINARY_DIR}/_CppBlockUtils${CMAKE_SHARED_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}/armory + ) + + install(FILES + ../armorycolors.py + ../armorymodels.py + ../ArmoryQt.py + ../dynamicImport.py + ../guardian.py + ../jasvet.py + ../LICENSE.py + ../qrcodenative.py + ../qtdefines.py + ../qtdialogs.py + ../SDM.py + ../setup.py + ../subprocess_win.py + ../update_version.py + ../writeNSISCompilerArgs.py + ${PROJECT_BINARY_DIR}/CppBlockUtils.py + ${PROJECT_BINARY_DIR}/qrc_img_resources.py + + DESTINATION ${CMAKE_INSTALL_LIBDIR}/armory + ) + + install(DIRECTORY ../armoryengine DESTINATION ${CMAKE_INSTALL_LIBDIR}/armory) + + install(DIRECTORY ../img + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/armory + PATTERN ".DS_Store" EXCLUDE + ) +endif() + +option(ENABLE_TESTS "build tests binaries" OFF) + +if(ENABLE_TESTS) + add_subdirectory(gtest) +endif() diff --git a/cppForSwig/Makefile.am b/cppForSwig/Makefile.am index e7cf4443b..158a50b67 100644 --- a/cppForSwig/Makefile.am +++ b/cppForSwig/Makefile.am @@ -103,7 +103,6 @@ ARMORYCLI_SOURCE_FILES = BDM_mainthread.cpp \ BlockUtils.cpp \ BtcWallet.cpp \ DatabaseBuilder.cpp \ - DBUtils.cpp \ HistoryPager.cpp \ HttpMessage.cpp \ JSON_codec.cpp \ @@ -131,6 +130,7 @@ ARMORYCOMMON_SOURCE_FILES = Accounts.cpp \ BtcUtils.cpp \ ClientClasses.cpp \ CoinSelection.cpp \ + DBUtils.cpp \ DecryptedDataContainer.cpp \ DerivationScheme.cpp \ hkdf.cpp \ @@ -250,7 +250,8 @@ ArmoryDB_LDADD = $(LIBARMORYCOMMON) \ $(LIBWEBSOCKETS_STATIC) if BUILD_OPENSSL_SUPPORT ArmoryDB_LDADD += $(LIBSSL_STATIC) \ - $(LIBCRYPTO_STATIC) + $(LIBCRYPTO_STATIC) \ + $(CRYPTO_LDFLAGS) endif if BUILD_LIBUV_SUPPORT ArmoryDB_LDADD += $(LIBUV_STATIC) @@ -299,17 +300,17 @@ libCppBlockUtils_la_CPPFLAGS = $(AM_CPPFLAGS) $(INCLUDE_FILES) \ $(PYTHON_CFLAGS) libCppBlockUtils_la_CXXFLAGS = $(AM_CXXFLAGS) -Ilmdb/libraries/liblmdb \ $(UNIT_TEST_CXXFLAGS) -D__STDC_LIMIT_MACROS -libCppBlockUtils_la_LIBADD = $(LIBARMORYCOMMON) $(LIBCRYPTOPP) \ - -lpthread if BUILD_GUI -libCppBlockUtils_la_LIBADD += $(LIBARMORYGUI) +libCppBlockUtils_la_LIBADD = $(LIBARMORYGUI) $(LIBCRYPTOPP) -lpthread +else +libCppBlockUtils_la_LIBADD = $(LIBARMORYCOMMON) $(LIBCRYPTOPP) -lpthread endif libCppBlockUtils_la_LDFLAGS = $(LDFLAGS) $(LWSLDFLAGS) $(PYTHON_LDFLAGS) -shared BUILT_SOURCES += CppBlockUtils_wrap.cxx #custom rules - always force SWIG to run and compile the resultant C++ file CppBlockUtils_wrap.cxx: CppBlockUtils.i - swig $(SWIG_FLAGS) CppBlockUtils.i + swig $(SWIG_FLAGS) -o CppBlockUtils_wrap.cxx CppBlockUtils.i endif MOSTLYCLEANFILES = $(PROTOBUF_CC) $(PROTOBUF_H) diff --git a/cppForSwig/chacha20poly1305/CMakeLists.txt b/cppForSwig/chacha20poly1305/CMakeLists.txt new file mode 100644 index 000000000..da6178f7c --- /dev/null +++ b/cppForSwig/chacha20poly1305/CMakeLists.txt @@ -0,0 +1,13 @@ +set(CHACHA20POLY1305_SOURCES + poly1305.c + chacha.c + chachapoly_aead.c +) + +add_library(chacha20poly1305 + ${CHACHA20POLY1305_SOURCES} +) + +target_include_directories(chacha20poly1305 + PUBLIC . +) diff --git a/cppForSwig/cryptopp/CMakeLists.txt b/cppForSwig/cryptopp/CMakeLists.txt new file mode 100644 index 000000000..e68ae673d --- /dev/null +++ b/cppForSwig/cryptopp/CMakeLists.txt @@ -0,0 +1,239 @@ +include(ArmorySupport) + +use_cxx11() + +include(CheckIncludeFileCXX) + +set(REQUIRED_HEADERS + arpa/inet.h fcntl.h limits.h netdb.h netinet/in.h stddef.h stdlib.h + string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h +) + +foreach(header ${REQUIRED_HEADERS}) + check_include_file_cxx(${header} ${header}_exists) + + if(NOT ${header}_exists) + message(FATAL_ERROR "required header ${header} not found") + endif() +endforeach() + +include(CheckTypeSize) + +foreach(type size_t ssize_t ptrdiff_t) + check_type_size(${type} ${type}_exists LANGUAGE CXX) + + if(NOT ${type}_exists) + message(FATAL_ERROR "your C++ compiler is missing the required type ${type}") + endif() +endforeach() + +include(CheckFunctionExists) + +set(save_libs ${CMAKE_REQUIRED_LIBRARIES}) + +if(NOT WIN32) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} m) # math library +endif() + +foreach(func gethostbyname gettimeofday memmove memset pow select setlocale socket) + check_function_exists(${func} ${func}_exists) + + if(NOT ${func}_exists) + message(FATAL_ERROR "your system is missing the required C library function ${func}") + endif() +endforeach() + +set(CMAKE_REQUIRED_LIBRARIES ${save_libs}) + +set(LIBCRYPTOPP_SOURCES + 3way.cpp + gf2n.cpp + pssr.cpp + socketft.cpp + adler32.cpp + default.cpp + gfpcrypt.cpp + pubkey.cpp + sosemanuk.cpp + algebra.cpp + des.cpp + gost.cpp + queue.cpp + square.cpp + algparam.cpp + dessp.cpp + gzip.cpp + rabin.cpp + squaretb.cpp + arc4.cpp + DetSign.cpp + hex.cpp + randpool.cpp + strciphr.cpp + asn.cpp + dh2.cpp + hmac.cpp + rc2.cpp + tea.cpp + authenc.cpp + dh.cpp + hrtimer.cpp + rc5.cpp + base32.cpp + dll.cpp + ida.cpp + rc6.cpp + tftables.cpp + base64.cpp + idea.cpp + rdtables.cpp + tiger.cpp + basecode.cpp + dsa.cpp + integer.cpp + tigertab.cpp + eax.cpp + iterhash.cpp + rijndael.cpp + trdlocal.cpp + ec2n.cpp + luc.cpp + ripemd.cpp + ttmac.cpp + bfinit.cpp + eccrypto.cpp + md2.cpp + rng.cpp + twofish.cpp + blowfish.cpp + ecp.cpp + md4.cpp + rsa.cpp + blumshub.cpp + elgamal.cpp + md5.cpp + rw.cpp + camellia.cpp + emsa2.cpp + misc.cpp + safer.cpp + cast.cpp + eprecomp.cpp + modes.cpp + salsa.cpp + vmac.cpp + casts.cpp + esign.cpp + mqueue.cpp + seal.cpp + wait.cpp + cbcmac.cpp + files.cpp + mqv.cpp + seed.cpp + wake.cpp + ccm.cpp + filters.cpp + nbtheory.cpp + serpent.cpp + whrlpool.cpp + channels.cpp + fips140.cpp + network.cpp + shacal2.cpp + winpipes.cpp + cmac.cpp + oaep.cpp + sha.cpp + xtr.cpp + cpu.cpp + osrng.cpp + sharkbox.cpp + xtrcrypt.cpp + crc.cpp + gcm.cpp + pch.cpp + shark.cpp + zdeflate.cpp + cryptlib_bds.cpp + gf2_32.cpp + pkcspad.cpp + simple.cpp + zinflate.cpp + cryptlib.cpp + gf256.cpp + polynomi.cpp + skipjack.cpp + zlib.cpp +) + +unset(LIBCRYPTOPP_DEFINITIONS) +unset(LIBCRYPTOPP_COMPILE_OPTIONS) + +option(WITH_HOST_CPU_FEATURES "support the CPU features of the build host" ON) + +if(WITH_HOST_CPU_FEATURES AND CMAKE_CXX_COMPILER_ID STREQUAL GNU) + list(APPEND LIBCRYPTOPP_COMPILE_OPTIONS -march=native) +endif() + +# enable asm on x86, gcc only +if(CMAKE_SYSTEM_PROCESSOR MATCHES "i.86|x86_64" AND CMAKE_CXX_COMPILER_ID STREQUAL GNU) + enable_language(ASM) + + # cmake needs to be patched to support this + execute_process( + COMMAND as --version + COMMAND head -1 + COMMAND awk "{print $NF}" + ERROR_QUIET + OUTPUT_VARIABLE CMAKE_ASM_COMPILER_VERSION + ) + + if(CMAKE_ASM_COMPILER_VERSION VERSION_LESS 2.10) + list(APPEND LIBCRYPTOPP_DEFINITIONS CRYPTOPP_DISABLE_ASM) + elseif(CMAKE_ASM_COMPILER_VERSION VERSION_LESS 2.17) + list(APPEND LIBCRYPTOPP_DEFINITIONS CRYPTOPP_DISABLE_SSE3) + endif() + + if(WITH_HOST_CPU_FEATURES AND CMAKE_SYSTEM_NAME STREQUAL Linux) + execute_process(COMMAND grep -o -m 1 aes /proc/cpuinfo OUTPUT_VARIABLE HAVE_AES) + execute_process(COMMAND grep -o -m 1 pclmul /proc/cpuinfo OUTPUT_VARIABLE HAVE_PCLMUL) + + if(HAVE_AES) + list(APPEND LIBCRYPTOPP_COMPILE_OPTIONS -maes) + list(APPEND LIBCRYPTOPP_DEFINITIONS CRYPTOPP_ENABLE_AESNI) + endif() + + if(HAVE_PCLMUL) + list(APPEND LIBCRYPTOPP_COMPILE_OPTIONS -mpclmul) + endif() + endif() + + check_x86_cpu_features() + + list(APPEND LIBCRYPTOPP_COMPILE_OPTIONS ${X86_CPU_FEATURES_COMPILER_FLAGS}) +else() + list(APPEND LIBCRYPTOPP_DEFINITIONS CRYPTOPP_DISABLE_ASM) +endif() + +add_library(cryptopp + ${LIBCRYPTOPP_SOURCES} +) + +if(LIBCRYPTOPP_DEFINITIONS) + target_compile_definitions(cryptopp + PRIVATE ${LIBCRYPTOPP_DEFINITIONS} + ) +endif() + +if(LIBCRYPTOPP_COMPILE_OPTIONS) + target_compile_options(cryptopp + PRIVATE ${LIBCRYPTOPP_COMPILE_OPTIONS} + ) +endif() + +if(NOT WIN32) + target_link_libraries(cryptopp + m # math + ) +endif() diff --git a/cppForSwig/gtest/CMakeLists.txt b/cppForSwig/gtest/CMakeLists.txt new file mode 100644 index 000000000..3c5d7541f --- /dev/null +++ b/cppForSwig/gtest/CMakeLists.txt @@ -0,0 +1,81 @@ +set(GTEST_COMPILE_DEFINITIONS + PUBLIC -DUNIT_TESTS +) + +if(APPLE) + list(APPEND GTEST_COMPILE_DEFINITIONS + PRIVATE -DGTEST_USE_OWN_TR1_TUPLE=1 + ) +endif() + +file(COPY input_files DESTINATION ${PROJECT_BINARY_DIR}) + +add_library(gtest + TestUtils.cpp + NodeUnitTest.cpp + gtest-all.cc +) + +target_link_libraries(gtest + ArmoryCLI +) + +add_executable(ContainerTests + ContainerTests.cpp +) + +target_link_libraries(ContainerTests + gtest +) + +set_target_properties(ContainerTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + +add_executable(BIP151RekeyTest + BIP151RekeyTest.cpp +) + +target_link_libraries(BIP151RekeyTest + gtest +) + +set_target_properties(BIP151RekeyTest PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + +add_executable(SupernodeTests + SupernodeTests.cpp +) + +target_link_libraries(SupernodeTests + gtest +) + +set_target_properties(SupernodeTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + +add_executable(CppBlockUtilsTests + CppBlockUtilsTests.cpp +) + +target_link_libraries(CppBlockUtilsTests + gtest +) + +set_target_properties(CppBlockUtilsTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + +add_executable(WalletTests + WalletTests.cpp +) + +target_link_libraries(WalletTests + gtest +) + +set_target_properties(WalletTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + +add_executable(SignerTests + SignerTests.cpp +) + +target_link_libraries(SignerTests + gtest +) + +set_target_properties(SignerTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) diff --git a/cppForSwig/libbtc/CMakeLists.txt b/cppForSwig/libbtc/CMakeLists.txt new file mode 100644 index 000000000..742320401 --- /dev/null +++ b/cppForSwig/libbtc/CMakeLists.txt @@ -0,0 +1,242 @@ +# this is the right way to set options for sub-projects +set(SECP256K1_MODULE_RECOVERY ON CACHE BOOL "enable sec256k1 recovery module" FORCE) + +add_subdirectory(src/secp256k1) + +set(LIBBTC_SOURCES + src/aes256_cbc.c + src/base58.c + src/bip32.c + src/block.c + src/buffer.c + src/chainparams.c + src/commontools.c + src/cstr.c + src/ctaes.c + src/ecc_key.c + src/ecc_libsecp256k1.c + src/memory.c + src/random.c + src/ripemd160.c + src/script.c + src/segwit_addr.c + src/serialize.c + src/sha2.c + src/tx.c + src/utils.c + src/vector.c +) + +include(CheckIncludeFile) + +check_include_file("dlfcn.h" HAVE_DLFCN_H) +check_include_file("inttypes.h" HAVE_INTTYPES_H) +check_include_file("memory.h" HAVE_MEMORY_H) +check_include_file("stdbool.h" HAVE_STDBOOL_H) +check_include_file("stdint.h" HAVE_STDINT_H) +check_include_file("stdlib.h" HAVE_STDLIB_H) +check_include_file("strings.h" HAVE_STRINGS_H) +check_include_file("string.h" HAVE_STRING_H) +check_include_file("sys/stat.h" HAVE_SYS_STAT_H) +check_include_file("sys/types.h" HAVE_SYS_TYPES_H) +check_include_file("unistd.h" HAVE_UNISTD_H) + +option(LIBBTC_WITH_WALLET "with libbtc wallet/database functions" ON) + +set(WITH_WALLET ${LIBBTC_WITH_WALLET}) + +if(LIBBTC_WITH_WALLET) + list(APPEND LIBBTC_SOURCES + src/logdb/logdb_core.c + src/logdb/logdb_memdb_llist.c + src/logdb/logdb_memdb_rbtree.c + src/logdb/logdb_rec.c + src/logdb/red_black_tree.c + src/wallet.c + ) +endif() + +option(LIBBTC_WITH_NET "with libbtc networking" ON) + +set(WITH_NET ${LIBBTC_WITH_NET}) + +set(LIBBTC_LINK_LIBRARIES + secp256k1 +) + +# these have to be PUBLIC for the tools targets +set(LIBBTC_INCLUDE_DIRECTORIES + PUBLIC include + PUBLIC src/logdb/include + PUBLIC ${PROJECT_BINARY_DIR} # for config.h +) + +if(LIBBTC_WITH_NET) + find_package(PkgConfig REQUIRED) + + pkg_check_modules(LIBEVENT REQUIRED libevent) + pkg_check_modules(LIBEVENT_PTHREADS REQUIRED libevent_pthreads) + + list(APPEND LIBBTC_LINK_LIBRARIES + ${LIBEVENT_LIBRARIES} + ${LIBEVENT_PTHREADS_LIBRARIES} + ) + + list(APPEND LIBBTC_INCLUDE_DIRECTORIES + PRIVATE ${LIBEVENT_INCLUDE_DIRS} + PRIVATE ${LIBEVENT_PTHREADS_INCLUDE_DIRS} + ) + + list(APPEND LIBBTC_SOURCES + src/headersdb_file.c + src/net.c + src/netspv.c + src/protocol.c + ) +endif() + +option(LIBBTC_WITH_TESTS "with libbtc tests" ON) + +option(LIBBTC_WITH_TOOLS "with libbtc tool cli applications" ON) + +include(CheckCXXSourceCompiles) + +check_cxx_source_compiles(" + void myfunc() + { + __builtin_expect(0,0); + } +" HAVE_BUILTIN_EXPECT) + +string_option(LIBBTC_RANDOM_DEVICE "device to use for random numbers, generally /dev/urandom on linux" /dev/urandom) + +set(RANDOM_DEVICE ${LIBBTC_RANDOM_DEVICE}) + +if(RANDOM_DEVICE STREQUAL /dev/urandom OR RANDOM_DEVICE STREQUAL /dev/random) + set(FILE_RANDOM TRUE) +endif() + +set(PACKAGE_NAME libbtc) + +set(LIBBTC_VERSION 0.1) + +set(PACKAGE_VERSION ${LIBBTC_VERSION}) + +configure_file( + src/libbtc-config.h.cmakein + ${PROJECT_BINARY_DIR}/libbtc-config.h +) + +add_library(btc + ${LIBBTC_SOURCES} +) + +target_include_directories(btc + ${LIBBTC_INCLUDE_DIRECTORIES} +) + +target_link_libraries(btc + ${LIBBTC_LINK_LIBRARIES} +) + +target_compile_definitions(btc + PUBLIC HAVE_CONFIG_H +) + +if(LIBBTC_WITH_TOOLS) + add_executable(bitcointool + src/tools/bitcointool.c + ) + + set_target_properties(bitcointool PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + + target_link_libraries(bitcointool btc) + + if(LIBBTC_WITH_NET) + add_executable(bitcoin-send-tx + src/tools/bitcoin-send-tx.c + ) + + set_target_properties(bitcoin-send-tx PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + + target_link_libraries(bitcoin-send-tx btc) + + add_executable(bitcoin-spv + src/tools/bitcoin-spv.c + ) + + set_target_properties(bitcoin-spv PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + + target_link_libraries(bitcoin-spv btc) + endif() +endif() + +# we don't need this but upstream might +if(FALSE) + configure_file( + libbtc.pc.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/libbtc.pc @ONLY + ) + + include(GNUInstallDirs) + + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/libbtc.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig + ) +endif() + +if(LIBBTC_WITH_TESTS) + set(TESTS_SOURCES + test/aes_tests.c + test/base58check_tests.c + test/bip32_tests.c + test/block_tests.c + test/buffer_tests.c + test/cstr_tests.c + test/ecc_tests.c + test/eckey_tests.c + test/hash_tests.c + test/memory_tests.c + test/random_tests.c + test/serialize_tests.c + test/sha2_tests.c + test/utest.h + test/unittester.c + test/tx_tests.c + test/utils_tests.c + test/vector_tests.c + ) + + if(LIBBTC_WITH_WALLET) + list(APPEND TESTS_SOURCES + test/wallet_tests.c + src/logdb/test/logdb_tests.c + src/logdb/test/tests_red_black_tree.c + ) + endif() + + if(LIBBTC_WITH_NET) + list(APPEND TESTS_SOURCES + test/net_tests.c + test/netspv_tests.c + test/protocol_tests.c + ) + endif() + + if(LIBBTC_WITH_TOOLS) + list(APPEND TESTS_SOURCES + test/tool_tests.c + ) + endif() + + add_executable(libbtc-tests + ${TESTS_SOURCES} + ) + + target_link_libraries(libbtc-tests + btc + ) + + set_target_properties(libbtc-tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) +endif() diff --git a/cppForSwig/libbtc/Makefile.am b/cppForSwig/libbtc/Makefile.am index 6e22fc834..a550ba4a0 100644 --- a/cppForSwig/libbtc/Makefile.am +++ b/cppForSwig/libbtc/Makefile.am @@ -62,7 +62,7 @@ libbtc_la_SOURCES = \ src/utils.c \ src/vector.c -libbtc_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/logdb/include +libbtc_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/logdb/include -I$(top_srcdir)/src/secp256k1/src libbtc_la_LIBADD = $(LIBSECP256K1) if USE_TESTS diff --git a/cppForSwig/libbtc/libbtc.pc.cmakein b/cppForSwig/libbtc/libbtc.pc.cmakein new file mode 100644 index 000000000..d74760c6f --- /dev/null +++ b/cppForSwig/libbtc/libbtc.pc.cmakein @@ -0,0 +1,12 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_LIBDIR@ +includedir=@CMAKE_INSTALL_INCLUDEDIR@ + +Name: libbtc +Description: C library for manipulating bitcoin data structures +URL: https://github.com/jonasschnelli/libbtc +Version: @LIBBTC_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lbtc + diff --git a/cppForSwig/libbtc/src/libbtc-config.h.cmakein b/cppForSwig/libbtc/src/libbtc-config.h.cmakein new file mode 100644 index 000000000..ae4e6c32e --- /dev/null +++ b/cppForSwig/libbtc/src/libbtc-config.h.cmakein @@ -0,0 +1,59 @@ +#ifndef LIBBTC_CONFIG_H + +#define LIBBTC_CONFIG_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H + +/* Define to 1 if stdbool.h conforms to C99. */ +#cmakedefine HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H + +/* Define this symbol if __builtin_expect is available */ +#cmakedefine HAVE_BUILTIN_EXPECT + +/* Define to set random file handle */ +#define RANDOM_DEVICE "@RANDOM_DEVICE@" + +/* Define to 1 to enable /dev/random or /dev/urandom as random device */ +#cmakedefine FILE_RANDOM + +/* Define to 1 to enable net compilation */ +#cmakedefine WITH_NET + +/* Define to 1 to enable wallet compilation */ +#cmakedefine WITH_WALLET + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PACKAGE_VERSION@" + +#endif /*LIBBTC_CONFIG_H*/ diff --git a/cppForSwig/libbtc/src/secp256k1/CMakeLists.txt b/cppForSwig/libbtc/src/secp256k1/CMakeLists.txt new file mode 100644 index 000000000..e7a3ada79 --- /dev/null +++ b/cppForSwig/libbtc/src/secp256k1/CMakeLists.txt @@ -0,0 +1,213 @@ +set(SECP256K1_VERSION 0.1) # I have no idea actually, this is not used + +set(SECP256K1_SOURCES + src/secp256k1.c +) + +option(SECP256K1_ENABLE_ASM "enable asm for secp256k1" ON) + +unset(USE_ASM_X86_64) +unset(USE_EXTERNAL_ASM) + +if(SECP256K1_ENABLE_ASM) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) + set(USE_ASM_X86_64 ON) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES arm) + set(USE_EXTERNAL_ASM ON) + list(APPEND SECP256K1_SOURCES src/asm/field_10x26_arm.s) + endif() +endif() + +add_library(secp256k1 + ${SECP256K1_SOURCES} +) + +target_compile_definitions(secp256k1 + PRIVATE SECP256K1_BUILD HAVE_CONFIG_H +) + +# make the config file + +include(CheckIncludeFile) + +check_include_file("inttypes.h" HAVE_INTTYPES_H) +check_include_file("memory.h" HAVE_MEMORY_H) +check_include_file("stdint.h" HAVE_STDINT_H) +check_include_file("stdlib.h" HAVE_STDLIB_H) +check_include_file("strings.h" HAVE_STRINGS_H) +check_include_file("string.h" HAVE_STRING_H) +check_include_file("sys/stat.h" HAVE_SYS_STAT_H) +check_include_file("sys/types.h" HAVE_SYS_TYPES_H) +check_include_file("unistd.h" HAVE_UNISTD_H) + +include(TestBigEndian) + +test_big_endian(WORDS_BIGENDIAN) + +include(CheckTypeSize) + +check_type_size(__int128 HAVE___INT128) + +check_type_size(uint128_t HAVE_UINT128_T) + +string_option(SECP256K1_USE_LIBGMP "use libgmp for secp256k1" AUTO) + +unset(LIBGMP_REQUIRED) +unset(HAVE_LIBGMP) + +if(SECP256K1_USE_LIBGMP AND (NOT SECP256K1_USE_LIBGMP STREQUAL AUTO)) + set(LIBGMP_REQUIRED REQUIRED) +elseif(NOT SECP256K1_USE_LIBGMP) + set(HAVE_LIBGMP NO) +endif() + +unset(USE_NUM_NONE) +unset(USE_NUM_GMP) +unset(USE_FIELD_INV_BUILTIN) +unset(USE_FIELD_INV_NUM) +unset(USE_SCALAR_INV_BUILTIN) +unset(USE_SCALAR_INV_NUM) + +if(NOT DEFINED HAVE_LIBGMP) + find_library(GMP_LIBRARIES NAMES gmp ${LIBGMP_REQUIRED}) + + if(GMP_LIBRARIES) + set(HAVE_LIBGMP ON) + + target_link_libraries(secp256k1 + ${GMP_LIBRARIES} + ) + + set(USE_NUM_GMP ON) + set(USE_FIELD_INV_NUM ON) + set(USE_SCALAR_INV_NUM ON) + else() + set(HAVE_LIBGMP OFF) + endif() +endif() + +if(NOT HAVE_LIBGMP) + set(USE_NUM_NONE ON) + set(USE_FIELD_INV_BUILTIN ON) + set(USE_SCALAR_INV_BUILTIN ON) +endif() + +option(SECP256K1_MODULE_ECDH "enable ecdh module for secp256k1" OFF) + +unset(ENABLE_MODULE_ECDH) + +if(SECP256K1_MODULE_ECDH) + set(ENABLE_MODULE_ECDH ON) +endif() + +option(SECP256K1_MODULE_RECOVERY "enable recovery module for secp256k1" OFF) + +unset(ENABLE_MODULE_RECOVERY) + +if(SECP256K1_MODULE_RECOVERY) + set(ENABLE_MODULE_RECOVERY ON) +endif() + +option(SECP256K1_MODULE_SCHNORR "enable schnorr module for secp256k1" OFF) + +unset(ENABLE_MODULE_SCHNORR) + +if(SECP256K1_MODULE_SCHNORR) + set(ENABLE_MODULE_SCHNORR ON) +endif() + +option(SECP256K1_ECMULT_STATIC_PRECOMPUTATION "use a statically generated ecmult table for secp256k1" OFF) + +unset(USE_ECMULT_STATIC_PRECOMPUTATION) + +if(SECP256K1_ECMULT_STATIC_PRECOMPUTATION) + set(USE_ECMULT_STATIC_PRECOMPUTATION ON) +endif() + +option(SECP256K1_ENDOMORPHISM "use endomorphism optimization for secp256k1" OFF) + +unset(USE_ENDOMORPHISM) + +if(SECP256K1_ENDOMORPHISM) + set(USE_ENDOMORPHISM ON) +endif() + +string_option(SECP256K1_WITH_FIELD "use '32bit', '64bit' or 'AUTO' field with secp256k1" AUTO) + +string_option(SECP256K1_WITH_SCALAR "use '32bit', '64bit' or 'AUTO' scalar with secp256k1" AUTO) + +if(SECP256K1_WITH_FIELD STREQUAL AUTO) + set(SECP256K1_WITH_FIELD 32bit) + + # 64 bit + if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 8 AND (HAVE_LIBGMP OR HAVE_UINT128_T)) + set(SECP256K1_WITH_FIELD 64bit) + endif() +endif() + +if(SECP256K1_WITH_FIELD STREQUAL 64bit AND (NOT (HAVE_LIBGMP OR HAVE_UINT128_T))) + message(FATAL_ERROR "64bit field support requires your compiler to have the 'uint128_t' type when not using libgmp") +endif() + +if(SECP256K1_WITH_SCALAR STREQUAL AUTO) + set(SECP256K1_WITH_SCALAR 32bit) + + # 64 bit + if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 8 AND (HAVE_LIBGMP OR HAVE_UINT128_T)) + set(SECP256K1_WITH_SCALAR 64bit) + endif() +endif() + +if(SECP256K1_WITH_SCALAR STREQUAL 64bit AND (NOT (HAVE_LIBGMP OR HAVE_UINT128_T))) + message(FATAL_ERROR "64bit scalar support requires your compiler to have the 'uint128_t' type when not using libgmp") +endif() + +unset(USE_FIELD_5X52) +unset(USE_FIELD_10X26) + +if(SECP256K1_WITH_FIELD STREQUAL 64bit) + set(USE_FIELD_5X52 ON) +elseif(SECP256K1_WITH_FIELD STREQUAL 32bit) + set(USE_FIELD_10X26 ON) +else() + message(FATAL_ERROR "invalid value for SECP256K1_WITH_FIELD, must be '64bit', '32bit' or 'AUTO'") +endif() + +unset(USE_SCALAR_4X64) +unset(USE_SCALAR_8X32) + +if(SECP256K1_WITH_SCALAR STREQUAL 64bit) + set(USE_SCALAR_4X64 ON) +elseif(SECP256K1_WITH_SCALAR STREQUAL 32bit) + set(USE_SCALAR_8X32 ON) +else() + message(FATAL_ERROR "invalid value for SECP256K1_WITH_SCALAR, must be '64bit', '32bit' or 'AUTO'") +endif() + +configure_file( + src/libsecp256k1-config.h.cmakein + ${PROJECT_BINARY_DIR}/libsecp256k1-config.h +) + +# we don't need this but upstream might +if(FALSE) + configure_file( + libsecp256k1.pc.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/libsecp256k1.pc @ONLY + ) + + include(GNUInstallDirs) + + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/libsecp256k1.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig + ) +endif() + +target_include_directories(secp256k1 + PUBLIC include + PRIVATE . + PRIVATE ../../include + PRIVATE ../../src + PRIVATE ${PROJECT_BINARY_DIR} +) diff --git a/cppForSwig/libbtc/src/secp256k1/Makefile.am b/cppForSwig/libbtc/src/secp256k1/Makefile.am index 3d130bdcb..aa1b38935 100644 --- a/cppForSwig/libbtc/src/secp256k1/Makefile.am +++ b/cppForSwig/libbtc/src/secp256k1/Makefile.am @@ -69,7 +69,7 @@ endif endif libsecp256k1_la_SOURCES = src/secp256k1.c -libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) +libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(abs_builddir)/include -I$(abs_builddir)/src $(SECP_INCLUDES) libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c diff --git a/cppForSwig/libbtc/src/secp256k1/include/secp256k1.h b/cppForSwig/libbtc/src/secp256k1/include/secp256k1.h index 7145dbcc5..eb2a52c64 100644 --- a/cppForSwig/libbtc/src/secp256k1/include/secp256k1.h +++ b/cppForSwig/libbtc/src/secp256k1/include/secp256k1.h @@ -7,6 +7,10 @@ extern "C" { #include +#ifdef HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + /* These rules specify the order of arguments in API calls: * * 1. Context pointers go first, followed by output arguments, combined diff --git a/cppForSwig/libbtc/src/secp256k1/libsecp256k1.pc.cmakein b/cppForSwig/libbtc/src/secp256k1/libsecp256k1.pc.cmakein new file mode 100644 index 000000000..828bc2584 --- /dev/null +++ b/cppForSwig/libbtc/src/secp256k1/libsecp256k1.pc.cmakein @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_LIBDIR@ +includedir=@CMAKE_INSTALL_INCLUDEDIR@ + +Name: libsecp256k1 +Description: Optimized C library for EC operations on curve secp256k1 +URL: https://github.com/bitcoin-core/secp256k1 +Version: @SECP256K1_VERSION@ +Cflags: -I${includedir} +Libs.private: @LIBSECP256K1_LIBS@ +Libs: -L${libdir} -lsecp256k1 + diff --git a/cppForSwig/libbtc/src/secp256k1/src/libsecp256k1-config.h.cmakein b/cppForSwig/libbtc/src/secp256k1/src/libsecp256k1-config.h.cmakein new file mode 100644 index 000000000..015e204d2 --- /dev/null +++ b/cppForSwig/libbtc/src/secp256k1/src/libsecp256k1-config.h.cmakein @@ -0,0 +1,106 @@ +#ifndef LIBSECP256K1_CONFIG_H + +#define LIBSECP256K1_CONFIG_H + +/* Define this symbol to enable the ECDH module */ +#cmakedefine ENABLE_MODULE_ECDH + +/* Define this symbol to enable the ECDSA pubkey recovery module */ +#cmakedefine ENABLE_MODULE_RECOVERY + +/* Define this symbol to enable the Schnorr signature module */ +#cmakedefine ENABLE_MODULE_SCHNORR + +/* Define this symbol if OpenSSL EC functions are available */ +#cmakedefine ENABLE_OPENSSL_TESTS + +/* Define this symbol if __builtin_expect is available */ +#cmakedefine HAVE_BUILTIN_EXPECT + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H + +/* Define this symbol if libcrypto is installed */ +#cmakedefine HAVE_LIBCRYPTO + +/* Define this symbol if libgmp is installed */ +#cmakedefine HAVE_LIBGMP + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H + +/* Define to 1 if the system has the type `__int128'. */ +#cmakedefine HAVE___INT128 + +/* Define this symbol to enable x86_64 assembly optimizations */ +#cmakedefine USE_ASM_X86_64 + +/* Define this symbol to use a statically generated ecmult table */ +#cmakedefine USE_ECMULT_STATIC_PRECOMPUTATION + +/* Define this symbol to use endomorphism optimization */ +#cmakedefine USE_ENDOMORPHISM + +/* Define this symbol if an external (non-inline) assembly implementation is + used */ +#cmakedefine USE_EXTERNAL_ASM + +/* Define this symbol to use the FIELD_10X26 implementation */ +#cmakedefine USE_FIELD_10X26 + +/* Define this symbol to use the FIELD_5X52 implementation */ +#cmakedefine USE_FIELD_5X52 + +/* Define this symbol to use the native field inverse implementation */ +#cmakedefine USE_FIELD_INV_BUILTIN + +/* Define this symbol to use the num-based field inverse implementation */ +#cmakedefine USE_FIELD_INV_NUM + +/* Define this symbol to use the gmp implementation for num */ +#cmakedefine USE_NUM_GMP + +/* Define this symbol to use no num implementation */ +#cmakedefine USE_NUM_NONE + +/* Define this symbol to use the 4x64 scalar implementation */ +#cmakedefine USE_SCALAR_4X64 + +/* Define this symbol to use the 8x32 scalar implementation */ +#cmakedefine USE_SCALAR_8X32 + +/* Define this symbol to use the native scalar inverse implementation */ +#cmakedefine USE_SCALAR_INV_BUILTIN + +/* Define this symbol to use the num-based scalar inverse implementation */ +#cmakedefine USE_SCALAR_INV_NUM + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#cmakedefine WORDS_BIGENDIAN + +#endif /*LIBSECP256K1_CONFIG_H*/ diff --git a/cppForSwig/lmdb/libraries/liblmdb/CMakeLists.txt b/cppForSwig/lmdb/libraries/liblmdb/CMakeLists.txt new file mode 100644 index 000000000..a30c8f662 --- /dev/null +++ b/cppForSwig/lmdb/libraries/liblmdb/CMakeLists.txt @@ -0,0 +1,37 @@ +set(LMDB_SOURCES + lmdbpp.cpp + mdb.c + midl.c +) + +set(LMDB_INCLUDE_DIRECTORIES + PRIVATE lmdb/libraries/liblmdb +) + +if(MSVC) + list(APPEND LMDB_SOURCES + ../../../leveldb_windows_port/win32_posix/dirent_win32.cpp + ../../../leveldb_windows_port/win32_posix/mman.cpp + ../../../leveldb_windows_port/win32_posix/pthread_win32port.cpp + ../../../leveldb_windows_port/win32_posix/Win_TranslatePath.cpp + ../../../leveldb_windows_port/win32_posix/win32_posix.cc + ) + + list(APPEND LMDB_INCLUDE_DIRECTORIES + PUBLIC ../../../leveldb_windows_port/win32_posix + ) +endif() + +add_library(lmdb + ${LMDB_SOURCES} +) + +target_include_directories(lmdb + ${LMDB_INCLUDE_DIRECTORIES} +) + +if(APPLE) + target_compile_definitions(lmdb + PRIVATE MDB_USE_POSIX_SEM=1 + ) +endif()