diff options
author | Bob Summerwill <bob@summerwill.net> | 2016-08-01 13:25:37 +0800 |
---|---|---|
committer | Bob Summerwill <bob@summerwill.net> | 2016-08-01 16:45:11 +0800 |
commit | 4ee2114127f87b08b76b3ca94cde80a49cdc056a (patch) | |
tree | b680926d0da4aadfddae0db9567557802f2c2929 /cmake | |
parent | 56727d61a61e1485c8360f00700d766632ec7163 (diff) | |
download | dexon-solidity-4ee2114127f87b08b76b3ca94cde80a49cdc056a.tar.gz dexon-solidity-4ee2114127f87b08b76b3ca94cde80a49cdc056a.tar.zst dexon-solidity-4ee2114127f87b08b76b3ca94cde80a49cdc056a.zip |
Make the Solidity repository standalone.
This commit is the culmination of several months of work to decouple Solidity from the webthree-umbrella so that it can be developed in parallel with cpp-ethereum (the Ethereum C++ runtime) and so that even for the Solidity unit-tests there is no hard-dependency onto the C++ runtime.
The Tests-over-IPC refactoring was a major step in the same process which was already committed.
This commit contains the following changes:
- A subset of the CMake functionality in webthree-helpers was extracted and tailored for Solidity into ./cmake. Further cleanup is certainly possible.
- A subset of the libdevcore functionality in libweb3core was extracted and tailored for Solidity into ./libdevcore. Further cleanup is certainly possible
- The gas price constants in EVMSchedule were orphaned into libevmasm.
- Some other refactorings and cleanups were made to sever unnecessary EVM dependencies in the Solidity unit-tests.
- TravisCI and Appveyor support was added, covering builds and running of the unit-tests (Linux and macOS only for now)
- A bug-fix was made to get the Tests-over-IPC running on macOS.
- There are still reliability issues in the unit-tests, which need immediate attention. The Travis build has been flipped to run the unit-tests 5 times, to try to flush these out.
- The Emscripten automation which was previously in webthree-umbrella was merged into the TravisCI automation here.
- The development ZIP deployment step has been commented out, but we will want to read that ONLY for release branch.
Further iteration on these changes will definitely be needed, but I feel these have got to sufficient maturity than holding them back further isn't winning us anything. It is go time :-)
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/CMakeParseArguments.cmake | 161 | ||||
-rw-r--r-- | cmake/EthBuildInfo.cmake | 45 | ||||
-rw-r--r-- | cmake/EthCompilerSettings.cmake | 247 | ||||
-rw-r--r-- | cmake/EthDependencies.cmake | 136 | ||||
-rw-r--r-- | cmake/EthExecutableHelper.cmake | 185 | ||||
-rw-r--r-- | cmake/EthOptions.cmake | 40 | ||||
-rw-r--r-- | cmake/EthPolicy.cmake | 35 | ||||
-rw-r--r-- | cmake/EthUtils.cmake | 114 | ||||
-rw-r--r-- | cmake/FindJsoncpp.cmake | 50 | ||||
-rw-r--r-- | cmake/FindPackageHandleStandardArgs.cmake | 382 | ||||
-rw-r--r-- | cmake/FindPackageMessage.cmake | 57 | ||||
-rw-r--r-- | cmake/FindSolidity.cmake | 47 | ||||
-rw-r--r-- | cmake/UseDev.cmake | 30 | ||||
-rw-r--r-- | cmake/UseJsoncpp.cmake | 10 | ||||
-rw-r--r-- | cmake/UseSolidity.cmake | 33 | ||||
-rw-r--r-- | cmake/scripts/buildinfo.cmake | 49 | ||||
-rw-r--r-- | cmake/templates/BuildInfo.h.in | 11 |
17 files changed, 1632 insertions, 0 deletions
diff --git a/cmake/CMakeParseArguments.cmake b/cmake/CMakeParseArguments.cmake new file mode 100644 index 00000000..8553f38f --- /dev/null +++ b/cmake/CMakeParseArguments.cmake @@ -0,0 +1,161 @@ +#.rst: +# CMakeParseArguments +# ------------------- +# +# +# +# CMAKE_PARSE_ARGUMENTS(<prefix> <options> <one_value_keywords> +# <multi_value_keywords> args...) +# +# CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions +# for parsing the arguments given to that macro or function. It +# processes the arguments and defines a set of variables which hold the +# values of the respective options. +# +# The <options> argument contains all options for the respective macro, +# i.e. keywords which can be used when calling the macro without any +# value following, like e.g. the OPTIONAL keyword of the install() +# command. +# +# The <one_value_keywords> argument contains all keywords for this macro +# which are followed by one value, like e.g. DESTINATION keyword of the +# install() command. +# +# The <multi_value_keywords> argument contains all keywords for this +# macro which can be followed by more than one value, like e.g. the +# TARGETS or FILES keywords of the install() command. +# +# When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the +# keywords listed in <options>, <one_value_keywords> and +# <multi_value_keywords> a variable composed of the given <prefix> +# followed by "_" and the name of the respective keyword. These +# variables will then hold the respective value from the argument list. +# For the <options> keywords this will be TRUE or FALSE. +# +# All remaining arguments are collected in a variable +# <prefix>_UNPARSED_ARGUMENTS, this can be checked afterwards to see +# whether your macro was called with unrecognized parameters. +# +# As an example here a my_install() macro, which takes similar arguments +# as the real install() command: +# +# :: +# +# function(MY_INSTALL) +# set(options OPTIONAL FAST) +# set(oneValueArgs DESTINATION RENAME) +# set(multiValueArgs TARGETS CONFIGURATIONS) +# cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" +# "${multiValueArgs}" ${ARGN} ) +# ... +# +# +# +# Assume my_install() has been called like this: +# +# :: +# +# my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub) +# +# +# +# After the cmake_parse_arguments() call the macro will have set the +# following variables: +# +# :: +# +# MY_INSTALL_OPTIONAL = TRUE +# MY_INSTALL_FAST = FALSE (this option was not used when calling my_install() +# MY_INSTALL_DESTINATION = "bin" +# MY_INSTALL_RENAME = "" (was not used) +# MY_INSTALL_TARGETS = "foo;bar" +# MY_INSTALL_CONFIGURATIONS = "" (was not used) +# MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL" +# +# +# +# You can then continue and process these variables. +# +# Keywords terminate lists of values, e.g. if directly after a +# one_value_keyword another recognized keyword follows, this is +# interpreted as the beginning of the new option. E.g. +# my_install(TARGETS foo DESTINATION OPTIONAL) would result in +# MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION +# would be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor. + +#============================================================================= +# Copyright 2010 Alexander Neundorf <neundorf@kde.org> +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + + +if(__CMAKE_PARSE_ARGUMENTS_INCLUDED) + return() +endif() +set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE) + + +function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames) + # first set all result variables to empty/FALSE + foreach(arg_name ${_singleArgNames} ${_multiArgNames}) + set(${prefix}_${arg_name}) + endforeach() + + foreach(option ${_optionNames}) + set(${prefix}_${option} FALSE) + endforeach() + + set(${prefix}_UNPARSED_ARGUMENTS) + + set(insideValues FALSE) + set(currentArgName) + + # now iterate over all arguments and fill the result variables + foreach(currentArg ${ARGN}) + list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword + list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword + list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword + + if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1) + if(insideValues) + if("${insideValues}" STREQUAL "SINGLE") + set(${prefix}_${currentArgName} ${currentArg}) + set(insideValues FALSE) + elseif("${insideValues}" STREQUAL "MULTI") + list(APPEND ${prefix}_${currentArgName} ${currentArg}) + endif() + else() + list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg}) + endif() + else() + if(NOT ${optionIndex} EQUAL -1) + set(${prefix}_${currentArg} TRUE) + set(insideValues FALSE) + elseif(NOT ${singleArgIndex} EQUAL -1) + set(currentArgName ${currentArg}) + set(${prefix}_${currentArgName}) + set(insideValues "SINGLE") + elseif(NOT ${multiArgIndex} EQUAL -1) + set(currentArgName ${currentArg}) + set(${prefix}_${currentArgName}) + set(insideValues "MULTI") + endif() + endif() + + endforeach() + + # propagate the result variables to the caller: + foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames}) + set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE) + endforeach() + set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE) + +endfunction() diff --git a/cmake/EthBuildInfo.cmake b/cmake/EthBuildInfo.cmake new file mode 100644 index 00000000..cbb9dd24 --- /dev/null +++ b/cmake/EthBuildInfo.cmake @@ -0,0 +1,45 @@ +function(create_build_info NAME) + + # Set build platform; to be written to BuildInfo.h + set(ETH_BUILD_OS "${CMAKE_SYSTEM_NAME}") + + if (CMAKE_COMPILER_IS_MINGW) + set(ETH_BUILD_COMPILER "mingw") + elseif (CMAKE_COMPILER_IS_MSYS) + set(ETH_BUILD_COMPILER "msys") + elseif (CMAKE_COMPILER_IS_GNUCXX) + set(ETH_BUILD_COMPILER "g++") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(ETH_BUILD_COMPILER "msvc") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set(ETH_BUILD_COMPILER "clang") + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") + set(ETH_BUILD_COMPILER "appleclang") + else () + set(ETH_BUILD_COMPILER "unknown") + endif () + + set(ETH_BUILD_PLATFORM "${ETH_BUILD_OS}/${ETH_BUILD_COMPILER}") + + #cmake build type may be not speCified when using msvc + if (CMAKE_BUILD_TYPE) + set(_cmake_build_type ${CMAKE_BUILD_TYPE}) + else() + set(_cmake_build_type "${CMAKE_CFG_INTDIR}") + endif() + + # Generate header file containing useful build information + add_custom_target(${NAME}_BuildInfo.h ALL + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -DETH_SOURCE_DIR="${PROJECT_SOURCE_DIR}" -DETH_BUILDINFO_IN="${ETH_CMAKE_DIR}/templates/BuildInfo.h.in" -DETH_DST_DIR="${PROJECT_BINARY_DIR}/include/${PROJECT_NAME}" -DETH_CMAKE_DIR="${ETH_CMAKE_DIR}" + -DETH_BUILD_TYPE="${_cmake_build_type}" + -DETH_BUILD_OS="${ETH_BUILD_OS}" + -DETH_BUILD_COMPILER="${ETH_BUILD_COMPILER}" + -DETH_BUILD_PLATFORM="${ETH_BUILD_PLATFORM}" + -DETH_BUILD_NUMBER="${BUILD_NUMBER}" + -DETH_VERSION_SUFFIX="${VERSION_SUFFIX}" + -DPROJECT_VERSION="${PROJECT_VERSION}" + -P "${ETH_SCRIPTS_DIR}/buildinfo.cmake" + ) + include_directories(BEFORE ${PROJECT_BINARY_DIR}) +endfunction() diff --git a/cmake/EthCompilerSettings.cmake b/cmake/EthCompilerSettings.cmake new file mode 100644 index 00000000..066be4c1 --- /dev/null +++ b/cmake/EthCompilerSettings.cmake @@ -0,0 +1,247 @@ +#------------------------------------------------------------------------------ +# EthCompilerSettings.cmake +# +# CMake file for cpp-ethereum project which specifies our compiler settings +# for each supported platform and build configuration. +# +# See http://www.ethdocs.org/en/latest/ethereum-clients/cpp-ethereum/. +# +# Copyright (c) 2014-2016 cpp-ethereum contributors. +#------------------------------------------------------------------------------ + +# Clang seeks to be command-line compatible with GCC as much as possible, so +# most of our compiler settings are common between GCC and Clang. +# +# These settings then end up spanning all POSIX platforms (Linux, OS X, BSD, etc) + +# Use ccache if available +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + message("Using ccache") +endif(CCACHE_FOUND) + +if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) + + # Use ISO C++11 standard language. + set(CMAKE_CXX_FLAGS -std=c++11) + + # Enables all the warnings about constructions that some users consider questionable, + # and that are easy to avoid. Also enable some extra warning flags that are not + # enabled by -Wall. Finally, treat at warnings-as-errors, which forces developers + # to fix warnings as they arise, so they don't accumulate "to be fixed later". + add_compile_options(-Wall) + add_compile_options(-Wextra) + add_compile_options(-Werror) + + # Disable warnings about unknown pragmas (which is enabled by -Wall). I assume we have external + # dependencies (probably Boost) which have some of these. Whatever the case, we shouldn't be + # disabling these globally. Instead, we should pragma around just the problem #includes. + # + # TODO - Track down what breaks if we do NOT do this. + add_compile_options(-Wno-unknown-pragmas) + + # To get the code building on FreeBSD and Arch Linux we seem to need the following + # warning suppression to work around some issues in Boost headers. + # + # See the following reports: + # https://github.com/ethereum/webthree-umbrella/issues/384 + # https://github.com/ethereum/webthree-helpers/pull/170 + # + # The issue manifest as warnings-as-errors like the following: + # + # /usr/local/include/boost/multiprecision/cpp_int.hpp:181:4: error: + # right operand of shift expression '(1u << 63u)' is >= than the precision of the left operand + # + # -fpermissive is a pretty nasty way to address this. It is described as follows: + # + # Downgrade some diagnostics about nonconformant code from errors to warnings. + # Thus, using -fpermissive will allow some nonconforming code to compile. + # + # NB: Have to use this form for the setting, so that it only applies to C++ builds. + # Applying -fpermissive to a C command-line (ie. secp256k1) gives a build error. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive") + + # Build everything as shared libraries (.so files) + add_definitions(-DSHAREDLIB) + + # If supported for the target machine, emit position-independent code, suitable for dynamic + # linking and avoiding any limit on the size of the global offset table. + add_compile_options(-fPIC) + + # Configuration-specific compiler settings. + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DETH_DEBUG") + set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") + set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") + + # Additional GCC-specific compiler settings. + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + + # Check that we've got GCC 4.7 or newer. + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) + if (NOT (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7)) + message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.7 or greater.") + endif () + + # Strong stack protection was only added in GCC 4.9. + # Use it if we have the option to do so. + # See https://lwn.net/Articles/584225/ + if (GCC_VERSION VERSION_GREATER 4.9 OR GCC_VERSION VERSION_EQUAL 4.9) + add_compile_options(-fstack-protector-strong) + add_compile_options(-fstack-protector) + endif() + + # Additional Clang-specific compiler settings. + elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + + add_compile_options(-fstack-protector) + + # Enable strong stack protection only on Mac and only for OS X Yosemite + # or newer (AppleClang 7.0+). We should be able to re-enable this setting + # on non-Apple Clang as well, if we can work out what expression to use for + # the version detection. + + # The fact that the version-reporting for AppleClang loses the original + # Clang versioning is rather annoying. Ideally we could just have + # a single cross-platform "if version >= 3.4.1" check. + # + # There is debug text in the else clause below, to help us work out what + # such an expression should be, if we can get this running on a Trusty box + # with Clang. Greg Colvin previously replicated the issue there too. + # + # See https://github.com/ethereum/webthree-umbrella/issues/594 + + if (APPLE) + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0) + add_compile_options(-fstack-protector-strong) + endif() + else() + message(WARNING "CMAKE_CXX_COMPILER_VERSION = ${CMAKE_CXX_COMPILER_VERSION}") + endif() + + # A couple of extra warnings suppressions which we seemingly + # need when building with Clang. + # + # TODO - Nail down exactly where these warnings are manifesting and + # try to suppress them in a more localized way. Notes in this file + # indicate that the first is needed for sepc256k1 and that the + # second is needed for the (clog, cwarn) macros. These will need + # testing on at least OS X and Ubuntu. + add_compile_options(-Wno-unused-function) + add_compile_options(-Wno-dangling-else) + + # Some Linux-specific Clang settings. We don't want these for OS X. + if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + + # TODO - Is this even necessary? Why? + # See http://stackoverflow.com/questions/19774778/when-is-it-necessary-to-use-use-the-flag-stdlib-libstdc. + add_compile_options(-stdlib=libstdc++) + + # Tell Boost that we're using Clang's libc++. Not sure exactly why we need to do. + add_definitions(-DBOOST_ASIO_HAS_CLANG_LIBCXX) + + # Use fancy colors in the compiler diagnostics + add_compile_options(-fcolor-diagnostics) + + # See "How to silence unused command line argument error with clang without disabling it?" + # When using -Werror with clang, it transforms "warning: argument unused during compilation" messages + # into errors, which makes sense. + # http://stackoverflow.com/questions/21617158/how-to-silence-unused-command-line-argument-error-with-clang-without-disabling-i + add_compile_options(-Qunused-arguments) + endif() + + if (EMSCRIPTEN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --memory-init-file 0 -O3 -s LINKABLE=1 -s DISABLE_EXCEPTION_CATCHING=0 -s NO_EXIT_RUNTIME=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_DYNAMIC_EXECUTION=1") + add_definitions(-DETH_EMSCRIPTEN=1) + endif() + endif() + +# The major alternative compiler to GCC/Clang is Microsoft's Visual C++ compiler, only available on Windows. +elseif (DEFINED MSVC) + + add_compile_options(/MP) # enable parallel compilation + add_compile_options(/EHsc) # specify Exception Handling Model in msvc + add_compile_options(/WX) # enable warnings-as-errors + add_compile_options(/wd4068) # disable unknown pragma warning (4068) + add_compile_options(/wd4996) # disable unsafe function warning (4996) + add_compile_options(/wd4503) # disable decorated name length exceeded, name was truncated (4503) + add_compile_options(/wd4267) # disable conversion from 'size_t' to 'type', possible loss of data (4267) + add_compile_options(/wd4180) # disable qualifier applied to function type has no meaning; ignored (4180) + add_compile_options(/wd4290) # disable C++ exception specification ignored except to indicate a function is not __declspec(nothrow) (4290) + add_compile_options(/wd4244) # disable conversion from 'type1' to 'type2', possible loss of data (4244) + add_compile_options(/wd4800) # disable forcing value to bool 'true' or 'false' (performance warning) (4800) + add_compile_options(-D_WIN32_WINNT=0x0600) # declare Windows Vista API requirement + add_compile_options(-DNOMINMAX) # undefine windows.h MAX && MIN macros cause it cause conflicts with std::min && std::max functions + add_compile_options(-DMINIUPNP_STATICLIB) # define miniupnp static library + + # Always use Release variant of C++ runtime. + # We don't want to provide Debug variants of all dependencies. Some default + # flags set by CMake must be tweaked. + string(REPLACE "/MDd" "/MD" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) + string(REPLACE "/D_DEBUG" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) + string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) + string(REPLACE "/MDd" "/MD" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) + string(REPLACE "/D_DEBUG" "" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) + string(REPLACE "/RTC1" "" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG}) + set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS OFF) + + # disable empty object file warning + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") + # warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification + # warning LNK4099: pdb was not found with lib + # stack size 16MB + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ignore:4099,4075 /STACK:16777216") + + # windows likes static + if (NOT ETH_STATIC) + message("Forcing static linkage for MSVC.") + set(ETH_STATIC 1) + endif () + +# If you don't have GCC, Clang or VC++ then you are on your own. Good luck! +else () + message(WARNING "Your compiler is not tested, if you run into any issues, we'd welcome any patches.") +endif () + +if (SANITIZE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=${SANITIZE}") + if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/sanitizer-blacklist.txt") + endif() +endif() + +if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))) + set(CMAKE_CXX_FLAGS "-g ${CMAKE_CXX_FLAGS}") + set(CMAKE_C_FLAGS "-g ${CMAKE_C_FLAGS}") + add_definitions(-DETH_PROFILING_GPERF) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lprofiler") +# set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -lprofiler") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lprofiler") +endif () + +if (PROFILING AND (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU"))) + set(CMAKE_CXX_FLAGS "-g --coverage ${CMAKE_CXX_FLAGS}") + set(CMAKE_C_FLAGS "-g --coverage ${CMAKE_C_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "--coverage ${CMAKE_SHARED_LINKER_FLAGS} -lprofiler") + set(CMAKE_EXE_LINKER_FLAGS "--coverage ${CMAKE_EXE_LINKER_FLAGS} -lprofiler") +endif () + +if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")) + option(USE_LD_GOLD "Use GNU gold linker" ON) + if (USE_LD_GOLD) + execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) + if ("${LD_VERSION}" MATCHES "GNU gold") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fuse-ld=gold") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") + endif () + endif () +endif () + +if(ETH_STATIC) + set(BUILD_SHARED_LIBS OFF) +else() + set(BUILD_SHARED_LIBS ON) +endif(ETH_STATIC) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake new file mode 100644 index 00000000..72585d11 --- /dev/null +++ b/cmake/EthDependencies.cmake @@ -0,0 +1,136 @@ +# all dependencies that are not directly included in the cpp-ethereum distribution are defined here +# for this to work, download the dependency via the cmake script in extdep or install them manually! + +function(eth_show_dependency DEP NAME) + get_property(DISPLAYED GLOBAL PROPERTY ETH_${DEP}_DISPLAYED) + if (NOT DISPLAYED) + set_property(GLOBAL PROPERTY ETH_${DEP}_DISPLAYED TRUE) + message(STATUS "${NAME} headers: ${${DEP}_INCLUDE_DIRS}") + message(STATUS "${NAME} lib : ${${DEP}_LIBRARIES}") + if (NOT("${${DEP}_DLLS}" STREQUAL "")) + message(STATUS "${NAME} dll : ${${DEP}_DLLS}") + endif() + endif() +endfunction() + +if (DEFINED MSVC) + # by defining CMAKE_PREFIX_PATH variable, cmake will look for dependencies first in our own repository before looking in system paths like /usr/local/ ... + # this must be set to point to the same directory as $ETH_DEPENDENCY_INSTALL_DIR in /extdep directory + + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.0) + set (ETH_DEPENDENCY_INSTALL_DIR "${CMAKE_CURRENT_LIST_DIR}/../extdep/install/windows/x64") + else() + get_filename_component(DEPS_DIR "${CMAKE_CURRENT_LIST_DIR}/../deps/install" ABSOLUTE) + set(ETH_DEPENDENCY_INSTALL_DIR + "${DEPS_DIR}/x64" # Old location for deps. + "${DEPS_DIR}/win64" # New location for deps. + "${DEPS_DIR}/win64/Release/share" # LLVM shared cmake files. + ) + endif() + set (CMAKE_PREFIX_PATH ${ETH_DEPENDENCY_INSTALL_DIR} ${CMAKE_PREFIX_PATH}) +endif() + +# custom cmake scripts +set(ETH_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR}) +set(ETH_SCRIPTS_DIR ${ETH_CMAKE_DIR}/scripts) + +find_program(CTEST_COMMAND ctest) + +#message(STATUS "CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH}") +#message(STATUS "CMake Helper Path: ${ETH_CMAKE_DIR}") +#message(STATUS "CMake Script Path: ${ETH_SCRIPTS_DIR}") +#message(STATUS "ctest path: ${CTEST_COMMAND}") + +## use multithreaded boost libraries, with -mt suffix +set(Boost_USE_MULTITHREADED ON) + +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + +# use static boost libraries *.lib + set(Boost_USE_STATIC_LIBS ON) + +elseif (APPLE) + +# use static boost libraries *.a + set(Boost_USE_STATIC_LIBS ON) + +elseif (UNIX) +# use dynamic boost libraries *.dll + set(Boost_USE_STATIC_LIBS OFF) + +endif() + +set(STATIC_LINKING FALSE CACHE BOOL "Build static binaries") + +if (STATIC_LINKING) + + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_STATIC_RUNTIME ON) + + set(OpenSSL_USE_STATIC_LIBS ON) + + if (MSVC) + # TODO - Why would we need .a on Windows? Maybe some Cygwin-ism. + # When I work through Windows static linkage, I will remove this, + # if that is possible. + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + elseif (APPLE) + # At the time of writing, we are still only PARTIALLY statically linked + # on OS X, with a mixture of statically linked external libraries where + # those are available, and dynamically linked where that is the only + # option we have. Ultimately, the aim would be for everything except + # the runtime libraries to be statically linked. + # + # Still TODO: + # - jsoncpp + # - json-rpc-cpp + # - leveldb (which pulls in snappy, for the dylib at ;east) + # - miniupnp + # - gmp + # + # Two further libraries (curl and zlib) ship as dylibs with the platform + # but again we could build from source and statically link these too. + set(CMAKE_FIND_LIBRARY_SUFFIXES .a .dylib) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) + endif() + + set(ETH_STATIC ON) +endif() + +find_package(Boost 1.54.0 QUIET REQUIRED COMPONENTS thread date_time system regex chrono filesystem unit_test_framework program_options random) + +eth_show_dependency(Boost boost) + +if (APPLE) + link_directories(/usr/local/lib) + include_directories(/usr/local/include) +endif() + +include_directories(BEFORE "${PROJECT_BINARY_DIR}/include") + +function(eth_use TARGET REQUIRED) + if (NOT TARGET ${TARGET}) + message(FATAL_ERROR "eth_use called for non existing target ${TARGET}") + endif() + + if (TARGET ${PROJECT_NAME}_BuildInfo.h) + add_dependencies(${TARGET} ${PROJECT_NAME}_BuildInfo.h) + endif() + + foreach(MODULE ${ARGN}) + string(REPLACE "::" ";" MODULE_PARTS ${MODULE}) + list(GET MODULE_PARTS 0 MODULE_MAIN) + list(LENGTH MODULE_PARTS MODULE_LENGTH) + if (MODULE_LENGTH GREATER 1) + list(GET MODULE_PARTS 1 MODULE_SUB) + endif() + # TODO: check if file exists if not, throws FATAL_ERROR with detailed description + get_target_property(TARGET_APPLIED ${TARGET} TARGET_APPLIED_${MODULE_MAIN}_${MODULE_SUB}) + if (NOT TARGET_APPLIED) + include(Use${MODULE_MAIN}) + set_target_properties(${TARGET} PROPERTIES TARGET_APPLIED_${MODULE_MAIN}_${MODULE_SUB} TRUE) + eth_apply(${TARGET} ${REQUIRED} ${MODULE_SUB}) + endif() + endforeach() +endfunction() diff --git a/cmake/EthExecutableHelper.cmake b/cmake/EthExecutableHelper.cmake new file mode 100644 index 00000000..921b37e7 --- /dev/null +++ b/cmake/EthExecutableHelper.cmake @@ -0,0 +1,185 @@ +# +# this function requires the following variables to be specified: +# ETH_VERSION +# PROJECT_NAME +# PROJECT_VERSION +# PROJECT_COPYRIGHT_YEAR +# PROJECT_VENDOR +# PROJECT_DOMAIN_SECOND +# PROJECT_DOMAIN_FIRST +# SRC_LIST +# HEADERS +# +# params: +# ICON +# + +macro(eth_add_executable EXECUTABLE) + set (extra_macro_args ${ARGN}) + set (options) + set (one_value_args ICON) + set (multi_value_args UI_RESOURCES WIN_RESOURCES) + cmake_parse_arguments (ETH_ADD_EXECUTABLE "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") + + if (APPLE) + + add_executable(${EXECUTABLE} MACOSX_BUNDLE ${SRC_LIST} ${HEADERS} ${ETH_ADD_EXECUTABLE_UI_RESOURCES}) + set(PROJECT_VERSION "${ETH_VERSION}") + set(MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") + set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_NAME} ${PROJECT_VERSION}") + set(MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_NAME} ${PROJECT_VERSION}") + set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}") + set(MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT_YEAR} ${PROJECT_VENDOR}") + set(MACOSX_BUNDLE_GUI_IDENTIFIER "${PROJECT_DOMAIN_SECOND}.${PROJECT_DOMAIN_FIRST}") + set(MACOSX_BUNDLE_BUNDLE_NAME ${EXECUTABLE}) + set(MACOSX_BUNDLE_ICON_FILE ${ETH_ADD_EXECUTABLE_ICON}) + set_target_properties(${EXECUTABLE} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/EthereumMacOSXBundleInfo.plist.in") + set_source_files_properties(${EXECUTABLE} PROPERTIES MACOSX_PACKAGE_LOCATION MacOS) + set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/${MACOSX_BUNDLE_ICON_FILE}.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + + else () + add_executable(${EXECUTABLE} ${ETH_ADD_EXECUTABLE_UI_RESOURCES} ${ETH_ADD_EXECUTABLE_WIN_RESOURCES} ${SRC_LIST} ${HEADERS}) + endif() + +endmacro() + +macro(eth_simple_add_executable EXECUTABLE) + add_executable(${EXECUTABLE} ${SRC_LIST} ${HEADERS}) + + # Apple does not support statically linked binaries on OS X. That means + # that we can only statically link against our external libraries, but + # we cannot statically link against the C++ runtime libraries and other + # platform libraries (as is possible on Windows and Alpine Linux) to produce + # an entirely transportable binary. + # + # See https://developer.apple.com/library/mac/qa/qa1118/_index.html for more info. + # + # GLIBC also appears not to support static linkage too, which probably means that + # Debian and Ubuntu will only be able to do partially-statically linked + # executables too, just like OS X. + # + # For OS X, at the time of writing, we are left with the following dynamically + # linked dependencies, of which curl and libz might still be fixable: + # + # /usr/lib/libc++.1.dylib + # /usr/lib/libSystem.B.dylib + # /usr/lib/libcurl.4.dylib + # /usr/lib/libz.1.dylib + # + if (STATIC_LINKING AND NOT APPLE) + set(CMAKE_EXE_LINKER_FLAGS "-static ${CMAKE_EXE_LINKER_FLAGS}") + set_target_properties(${EXECUTABLE} PROPERTIES LINK_SEARCH_START_STATIC 1) + set_target_properties(${EXECUTABLE} PROPERTIES LINK_SEARCH_END_STATIC 1) + endif() +endmacro() + +macro(eth_copy_dll EXECUTABLE DLL) + # dlls must be unsubstitud list variable (without ${}) in format + # optimized;path_to_dll.dll;debug;path_to_dlld.dll + if(DEFINED MSVC) + list(GET ${DLL} 1 DLL_RELEASE) + list(GET ${DLL} 3 DLL_DEBUG) + add_custom_command(TARGET ${EXECUTABLE} + PRE_BUILD + COMMAND ${CMAKE_COMMAND} ARGS + -DDLL_RELEASE="${DLL_RELEASE}" + -DDLL_DEBUG="${DLL_DEBUG}" + -DCONF="$<CONFIGURATION>" + -DDESTINATION="${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" + -P "${ETH_SCRIPTS_DIR}/copydlls.cmake" + ) + endif() +endmacro() + +macro(eth_copy_dlls EXECUTABLE) + foreach(dll ${ARGN}) + eth_copy_dll(${EXECUTABLE} ${dll}) + endforeach(dll) +endmacro() + + +macro(eth_install_executable EXECUTABLE) + + if (APPLE) + + # TODO - Why is this different than the branch Linux below, which has the RUNTIME keyword too? + install(TARGETS ${EXECUTABLE} DESTINATION bin) + + elseif (DEFINED MSVC) + + set(COMPONENT ${EXECUTABLE}) + + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Debug/" + DESTINATION . + CONFIGURATIONS Debug + COMPONENT ${COMPONENT} + ) + + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Release/" + DESTINATION . + CONFIGURATIONS Release + COMPONENT ${COMPONENT} + ) + + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/" + DESTINATION . + CONFIGURATIONS RelWithDebInfo + COMPONENT ${COMPONENT} + ) + + else() + install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin) + endif () + +endmacro() + +macro (eth_name KEY VALUE) + if (NOT (APPLE OR WIN32)) + string(TOLOWER ${VALUE} LVALUE ) + set(${KEY} ${LVALUE}) + else() + set(${KEY} ${VALUE}) + endif() +endmacro() + +macro(jsonrpcstub_client_create SPEC CLIENTNAME CLIENTDIR CLIENTFILENAME) + if (ETH_JSON_RPC_STUB) + add_custom_target(${SPEC}stub) + add_custom_command( + TARGET ${SPEC}stub + POST_BUILD + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${SPEC}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -DETH_SPEC_PATH="${CMAKE_CURRENT_SOURCE_DIR}/${SPEC}" -DETH_SOURCE_DIR="${CMAKE_SOURCE_DIR}" -DETH_CMAKE_DIR="${ETH_CMAKE_DIR}" + -DETH_CLIENT_DIR="${CLIENTDIR}" + -DETH_CLIENT_NAME=${CLIENTNAME} + -DETH_CLIENT_FILENAME=${CLIENTFILENAME} + -DETH_JSON_RPC_STUB="${ETH_JSON_RPC_STUB}" + -P "${ETH_SCRIPTS_DIR}/jsonrpcstub.cmake" + ) + add_dependencies(${EXECUTABLE} ${SPEC}stub) + endif () +endmacro() + +macro(jsonrpcstub_create SPEC SERVERNAME SERVERDIR SERVERFILENAME CLIENTNAME CLIENTDIR CLIENTFILENAME) + if (ETH_JSON_RPC_STUB) + add_custom_target(${SPEC}stub) + add_custom_command( + TARGET ${SPEC}stub + POST_BUILD + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${SPEC}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -DETH_SPEC_PATH="${CMAKE_CURRENT_SOURCE_DIR}/${SPEC}" -DETH_SOURCE_DIR="${CMAKE_SOURCE_DIR}" -DETH_CMAKE_DIR="${ETH_CMAKE_DIR}" + -DETH_CLIENT_DIR="${CLIENTDIR}" + -DETH_CLIENT_NAME=${CLIENTNAME} + -DETH_CLIENT_FILENAME=${CLIENTFILENAME} + -DETH_SERVER_DIR="${SERVERDIR}" + -DETH_SERVER_NAME=${SERVERNAME} + -DETH_SERVER_FILENAME=${SERVERFILENAME} + -DETH_JSON_RPC_STUB="${ETH_JSON_RPC_STUB}" + -P "${ETH_SCRIPTS_DIR}/jsonrpcstub.cmake" + ) + add_dependencies(${EXECUTABLE} ${SPEC}stub) + endif () +endmacro() + diff --git a/cmake/EthOptions.cmake b/cmake/EthOptions.cmake new file mode 100644 index 00000000..b4efd6c9 --- /dev/null +++ b/cmake/EthOptions.cmake @@ -0,0 +1,40 @@ +macro(configure_project) + set(NAME ${PROJECT_NAME}) + + # features + eth_default_option(PROFILING OFF) + + # components + eth_default_option(TESTS ON) + eth_default_option(TOOLS ON) + + # Define a matching property name of each of the "features". + foreach(FEATURE ${ARGN}) + set(SUPPORT_${FEATURE} TRUE) + endforeach() + + include(EthBuildInfo) + create_build_info(${NAME}) + print_config(${NAME}) +endmacro() + +macro(print_config NAME) + message("") + message("------------------------------------------------------------------------") + message("-- Configuring ${NAME}") + message("------------------------------------------------------------------------") + message("-- CMake Version ${CMAKE_VERSION}") + message("-- CMAKE_BUILD_TYPE Build type ${CMAKE_BUILD_TYPE}") + message("-- TARGET_PLATFORM Target platform ${CMAKE_SYSTEM_NAME}") + message("--------------------------------------------------------------- features") + message("-- PROFILING Profiling support ${PROFILING}") + message("------------------------------------------------------------- components") +if (SUPPORT_TESTS) + message("-- TESTS Build tests ${TESTS}") +endif() +if (SUPPORT_TOOLS) + message("-- TOOLS Build tools ${TOOLS}") +endif() + message("------------------------------------------------------------------------") + message("") +endmacro() diff --git a/cmake/EthPolicy.cmake b/cmake/EthPolicy.cmake new file mode 100644 index 00000000..31b09f15 --- /dev/null +++ b/cmake/EthPolicy.cmake @@ -0,0 +1,35 @@ +# it must be a macro cause policies have scopes +# http://www.cmake.org/cmake/help/v3.0/command/cmake_policy.html +macro (eth_policy) + # link_directories() treats paths relative to the source dir. + cmake_policy(SET CMP0015 NEW) + + # let cmake autolink dependencies on windows + cmake_policy(SET CMP0020 NEW) + + # CMake 2.8.12 and lower allowed the use of targets and files with double + # colons in target_link_libraries, + cmake_policy(SET CMP0028 OLD) + + if (${CMAKE_VERSION} VERSION_GREATER 3.0) + + # fix MACOSX_RPATH + cmake_policy(SET CMP0042 OLD) + + # ignore COMPILE_DEFINITIONS_<Config> properties + cmake_policy(SET CMP0043 OLD) + + # allow VERSION argument in project() + cmake_policy(SET CMP0048 NEW) + + endif() + + if (${CMAKE_VERSION} VERSION_GREATER 3.1) + + # do not interpret if() arguments as variables! + cmake_policy(SET CMP0054 NEW) + + endif() + +endmacro() + diff --git a/cmake/EthUtils.cmake b/cmake/EthUtils.cmake new file mode 100644 index 00000000..68fd35d1 --- /dev/null +++ b/cmake/EthUtils.cmake @@ -0,0 +1,114 @@ +# +# renames the file if it is different from its destination +include(CMakeParseArguments) +# +macro(replace_if_different SOURCE DST) + set(extra_macro_args ${ARGN}) + set(options CREATE) + set(one_value_args) + set(multi_value_args) + cmake_parse_arguments(REPLACE_IF_DIFFERENT "${options}" "${one_value_args}" "${multi_value_args}" "${extra_macro_args}") + + if (REPLACE_IF_DIFFERENT_CREATE AND (NOT (EXISTS "${DST}"))) + file(WRITE "${DST}" "") + endif() + + execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files "${SOURCE}" "${DST}" RESULT_VARIABLE DIFFERENT OUTPUT_QUIET ERROR_QUIET) + + if (DIFFERENT) + execute_process(COMMAND ${CMAKE_COMMAND} -E rename "${SOURCE}" "${DST}") + else() + execute_process(COMMAND ${CMAKE_COMMAND} -E remove "${SOURCE}") + endif() +endmacro() + +macro(eth_add_test NAME) + + # parse arguments here + set(commands) + set(current_command "") + foreach (arg ${ARGN}) + if (arg STREQUAL "ARGS") + if (current_command) + list(APPEND commands ${current_command}) + endif() + set(current_command "") + else () + set(current_command "${current_command} ${arg}") + endif() + endforeach(arg) + list(APPEND commands ${current_command}) + + message(STATUS "test: ${NAME} | ${commands}") + + # create tests + set(index 0) + list(LENGTH commands count) + while (index LESS count) + list(GET commands ${index} test_arguments) + + set(run_test "--run_test=${NAME}") + add_test(NAME "${NAME}.${index}" COMMAND testeth ${run_test} ${test_arguments}) + + math(EXPR index "${index} + 1") + endwhile(index LESS count) + + # add target to run them + add_custom_target("test.${NAME}" + DEPENDS testeth + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -DETH_TEST_NAME="${NAME}" -DCTEST_COMMAND="${CTEST_COMMAND}" -P "${ETH_SCRIPTS_DIR}/runtest.cmake" + ) + +endmacro() + +# Creates C resources file from files +function(eth_add_resources RESOURCE_FILE OUT_FILE ETH_RES_DIR) + include("${RESOURCE_FILE}") + set(OUTPUT "${ETH_RESOURCE_LOCATION}/${ETH_RESOURCE_NAME}.hpp") + #message(FATAL_ERROR "res:! ${ETH_RESOURCE_LOCATION}") + include_directories("${ETH_RESOURCE_LOCATION}") + set(${OUT_FILE} "${OUTPUT}" PARENT_SCOPE) + + set(filenames "${RESOURCE_FILE}") + list(APPEND filenames "${ETH_SCRIPTS_DIR}/resources.cmake") + foreach(resource ${ETH_RESOURCES}) + list(APPEND filenames "${${resource}}") + endforeach(resource) + + add_custom_command(OUTPUT ${OUTPUT} + COMMAND ${CMAKE_COMMAND} -DETH_RES_FILE="${RESOURCE_FILE}" -DETH_RES_DIR="${ETH_RES_DIR}" -P "${ETH_SCRIPTS_DIR}/resources.cmake" + DEPENDS ${filenames} + ) +endfunction() + +macro(eth_default_option O DEF) + if (DEFINED ${O}) + if (${${O}}) + set(${O} ON) + else () + set(${O} OFF) + endif() + else () + set(${O} ${DEF}) + endif() +endmacro() + +# In Windows split repositories build we need to be checking whether or not +# Debug/Release or both versions were built for the config phase to run smoothly +macro(eth_check_library_link L) + if (${${L}_LIBRARY} AND ${${L}_LIBRARY} EQUAL "${L}_LIBRARY-NOTFOUND") + unset(${${L}_LIBRARY}) + endif() + if (${${L}_LIBRARY_DEBUG} AND ${${L}_LIBRARY_DEBUG} EQUAL "${L}_LIBRARY_DEBUG-NOTFOUND") + unset(${${L}_LIBRARY_DEBUG}) + endif() + if (${${L}_LIBRARY} AND ${${L}_LIBRARY_DEBUG}) + set(${L}_LIBRARIES optimized ${${L}_LIBRARY} debug ${${L}_LIBRARY_DEBUG}) + elseif (${${L}_LIBRARY}) + set(${L}_LIBRARIES ${${L}_LIBRARY}) + elseif (${${L}_LIBRARY_DEBUG}) + set(${L}_LIBRARIES ${${L}_LIBRARY_DEBUG}) + endif() +endmacro() + diff --git a/cmake/FindJsoncpp.cmake b/cmake/FindJsoncpp.cmake new file mode 100644 index 00000000..e8258b71 --- /dev/null +++ b/cmake/FindJsoncpp.cmake @@ -0,0 +1,50 @@ +# Find jsoncpp +# +# Find the jsoncpp includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH +# +# This module defines +# JSONCPP_INCLUDE_DIRS, where to find header, etc. +# JSONCPP_LIBRARIES, the libraries needed to use jsoncpp. +# JSONCPP_FOUND, If false, do not try to use jsoncpp. + +# only look in default directories +find_path( + JSONCPP_INCLUDE_DIR + NAMES json/json.h + PATH_SUFFIXES jsoncpp + DOC "jsoncpp include dir" +) + +find_library( + JSONCPP_LIBRARY + NAMES jsoncpp + DOC "jsoncpp library" +) + +set(JSONCPP_INCLUDE_DIRS ${JSONCPP_INCLUDE_DIR}) +set(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY}) + +# debug library on windows +# same naming convention as in qt (appending debug library with d) +# boost is using the same "hack" as us with "optimized" and "debug" +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + + find_library( + JSONCPP_LIBRARY_DEBUG + NAMES jsoncppd + DOC "jsoncpp debug library" + ) + + set(JSONCPP_LIBRARIES optimized ${JSONCPP_LIBRARIES} debug ${JSONCPP_LIBRARY_DEBUG}) + +endif() + +# handle the QUIETLY and REQUIRED arguments and set JSONCPP_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(jsoncpp DEFAULT_MSG + JSONCPP_LIBRARY JSONCPP_INCLUDE_DIR) +mark_as_advanced (JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) + diff --git a/cmake/FindPackageHandleStandardArgs.cmake b/cmake/FindPackageHandleStandardArgs.cmake new file mode 100644 index 00000000..6bcf1e78 --- /dev/null +++ b/cmake/FindPackageHandleStandardArgs.cmake @@ -0,0 +1,382 @@ +#.rst: +# FindPackageHandleStandardArgs +# ----------------------------- +# +# +# +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> ... ) +# +# This function is intended to be used in FindXXX.cmake modules files. +# It handles the REQUIRED, QUIET and version-related arguments to +# find_package(). It also sets the <packagename>_FOUND variable. The +# package is considered found if all variables <var1>... listed contain +# valid results, e.g. valid filepaths. +# +# There are two modes of this function. The first argument in both +# modes is the name of the Find-module where it is called (in original +# casing). +# +# The first simple mode looks like this: +# +# :: +# +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(<name> +# (DEFAULT_MSG|"Custom failure message") <var1>...<varN> ) +# +# If the variables <var1> to <varN> are all valid, then +# <UPPERCASED_NAME>_FOUND will be set to TRUE. If DEFAULT_MSG is given +# as second argument, then the function will generate itself useful +# success and error messages. You can also supply a custom error +# message for the failure case. This is not recommended. +# +# The second mode is more powerful and also supports version checking: +# +# :: +# +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME +# [FOUND_VAR <resultVar>] +# [REQUIRED_VARS <var1>...<varN>] +# [VERSION_VAR <versionvar>] +# [HANDLE_COMPONENTS] +# [CONFIG_MODE] +# [FAIL_MESSAGE "Custom failure message"] ) +# +# In this mode, the name of the result-variable can be set either to +# either <UPPERCASED_NAME>_FOUND or <OriginalCase_Name>_FOUND using the +# FOUND_VAR option. Other names for the result-variable are not +# allowed. So for a Find-module named FindFooBar.cmake, the two +# possible names are FooBar_FOUND and FOOBAR_FOUND. It is recommended +# to use the original case version. If the FOUND_VAR option is not +# used, the default is <UPPERCASED_NAME>_FOUND. +# +# As in the simple mode, if <var1> through <varN> are all valid, +# <packagename>_FOUND will be set to TRUE. After REQUIRED_VARS the +# variables which are required for this package are listed. Following +# VERSION_VAR the name of the variable can be specified which holds the +# version of the package which has been found. If this is done, this +# version will be checked against the (potentially) specified required +# version used in the find_package() call. The EXACT keyword is also +# handled. The default messages include information about the required +# version and the version which has been actually found, both if the +# version is ok or not. If the package supports components, use the +# HANDLE_COMPONENTS option to enable handling them. In this case, +# find_package_handle_standard_args() will report which components have +# been found and which are missing, and the <packagename>_FOUND variable +# will be set to FALSE if any of the required components (i.e. not the +# ones listed after OPTIONAL_COMPONENTS) are missing. Use the option +# CONFIG_MODE if your FindXXX.cmake module is a wrapper for a +# find_package(... NO_MODULE) call. In this case VERSION_VAR will be +# set to <NAME>_VERSION and the macro will automatically check whether +# the Config module was found. Via FAIL_MESSAGE a custom failure +# message can be specified, if this is not used, the default message +# will be displayed. +# +# Example for mode 1: +# +# :: +# +# find_package_handle_standard_args(LibXml2 DEFAULT_MSG +# LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) +# +# +# +# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and +# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to +# TRUE. If it is not found and REQUIRED was used, it fails with +# FATAL_ERROR, independent whether QUIET was used or not. If it is +# found, success will be reported, including the content of <var1>. On +# repeated Cmake runs, the same message won't be printed again. +# +# Example for mode 2: +# +# :: +# +# find_package_handle_standard_args(LibXslt +# FOUND_VAR LibXslt_FOUND +# REQUIRED_VARS LibXslt_LIBRARIES LibXslt_INCLUDE_DIRS +# VERSION_VAR LibXslt_VERSION_STRING) +# +# In this case, LibXslt is considered to be found if the variable(s) +# listed after REQUIRED_VAR are all valid, i.e. LibXslt_LIBRARIES and +# LibXslt_INCLUDE_DIRS in this case. The result will then be stored in +# LibXslt_FOUND . Also the version of LibXslt will be checked by using +# the version contained in LibXslt_VERSION_STRING. Since no +# FAIL_MESSAGE is given, the default messages will be printed. +# +# Another example for mode 2: +# +# :: +# +# find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) +# find_package_handle_standard_args(Automoc4 CONFIG_MODE) +# +# In this case, FindAutmoc4.cmake wraps a call to find_package(Automoc4 +# NO_MODULE) and adds an additional search directory for automoc4. Here +# the result will be stored in AUTOMOC4_FOUND. The following +# FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper +# success/error message. + +#============================================================================= +# Copyright 2007-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake) + +# internal helper macro +macro(_FPHSA_FAILURE_MESSAGE _msg) + if (${_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "${_msg}") + else () + if (NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "${_msg}") + endif () + endif () +endmacro() + + +# internal helper macro to generate the failure message when used in CONFIG_MODE: +macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + # <name>_CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: + if(${_NAME}_CONFIG) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + else() + # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. + # List them all in the error message: + if(${_NAME}_CONSIDERED_CONFIGS) + set(configsText "") + list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) + math(EXPR configsCount "${configsCount} - 1") + foreach(currentConfigIndex RANGE ${configsCount}) + list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) + list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) + set(configsText "${configsText} ${filename} (version ${version})\n") + endforeach() + if (${_NAME}_NOT_FOUND_MESSAGE) + set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n") + endif() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") + + else() + # Simple case: No Config-file was found at all: + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + endif() + endif() +endmacro() + + +function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) + +# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in +# new extended or in the "old" mode: + set(options CONFIG_MODE HANDLE_COMPONENTS) + set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR) + set(multiValueArgs REQUIRED_VARS) + set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) + list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + + if(${INDEX} EQUAL -1) + set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) + set(FPHSA_REQUIRED_VARS ${ARGN}) + set(FPHSA_VERSION_VAR) + else() + + CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) + + if(FPHSA_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") + endif() + + if(NOT FPHSA_FAIL_MESSAGE) + set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") + endif() + endif() + +# now that we collected all arguments, process them + + if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG") + set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + endif() + + # In config-mode, we rely on the variable <package>_CONFIG, which is set by find_package() + # when it successfully found the config-file, including version checking: + if(FPHSA_CONFIG_MODE) + list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) + list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) + set(FPHSA_VERSION_VAR ${_NAME}_VERSION) + endif() + + if(NOT FPHSA_REQUIRED_VARS) + message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") + endif() + + list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) + + string(TOUPPER ${_NAME} _NAME_UPPER) + string(TOLOWER ${_NAME} _NAME_LOWER) + + if(FPHSA_FOUND_VAR) + if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$") + set(_FOUND_VAR ${FPHSA_FOUND_VAR}) + else() + message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.") + endif() + else() + set(_FOUND_VAR ${_NAME_UPPER}_FOUND) + endif() + + # collect all variables which were not found, so they can be printed, so the + # user knows better what went wrong (#6375) + set(MISSING_VARS "") + set(DETAILS "") + # check if all passed variables are valid + unset(${_FOUND_VAR}) + foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) + if(NOT ${_CURRENT_VAR}) + set(${_FOUND_VAR} FALSE) + set(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}") + else() + set(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]") + endif() + endforeach() + if(NOT "${${_FOUND_VAR}}" STREQUAL "FALSE") + set(${_FOUND_VAR} TRUE) + endif() + + # component handling + unset(FOUND_COMPONENTS_MSG) + unset(MISSING_COMPONENTS_MSG) + + if(FPHSA_HANDLE_COMPONENTS) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(${_NAME}_${comp}_FOUND) + + if(NOT DEFINED FOUND_COMPONENTS_MSG) + set(FOUND_COMPONENTS_MSG "found components: ") + endif() + set(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}") + + else() + + if(NOT DEFINED MISSING_COMPONENTS_MSG) + set(MISSING_COMPONENTS_MSG "missing components: ") + endif() + set(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}") + + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_FOUND_VAR} FALSE) + set(MISSING_VARS "${MISSING_VARS} ${comp}") + endif() + + endif() + endforeach() + set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}") + set(DETAILS "${DETAILS}[c${COMPONENT_MSG}]") + endif() + + # version handling: + set(VERSION_MSG "") + set(VERSION_OK TRUE) + set(VERSION ${${FPHSA_VERSION_VAR}}) + + # check with DEFINED here as the requested or found version may be "0" + if (DEFINED ${_NAME}_FIND_VERSION) + if(DEFINED ${FPHSA_VERSION_VAR}) + + if(${_NAME}_FIND_VERSION_EXACT) # exact version required + # count the dots in the version string + string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${VERSION}") + # add one dot because there is one dot more than there are components + string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS) + if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT) + # Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT + # is at most 4 here. Therefore a simple lookup table is used. + if (${_NAME}_FIND_VERSION_COUNT EQUAL 1) + set(_VERSION_REGEX "[^.]*") + elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2) + set(_VERSION_REGEX "[^.]*\\.[^.]*") + elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3) + set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*") + else () + set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*") + endif () + string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${VERSION}") + unset(_VERSION_REGEX) + if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD) + set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable exact version \"${VERSION}\")") + endif () + unset(_VERSION_HEAD) + else () + if (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable exact version \"${VERSION}\")") + endif () + endif () + unset(_VERSION_DOTS) + + else() # minimum version specified: + if ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + set(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable version \"${VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")") + endif () + endif() + + else() + + # if the package was not found, but a version was given, add that to the output: + if(${_NAME}_FIND_VERSION_EXACT) + set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") + else() + set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") + endif() + + endif() + else () + if(VERSION) + set(VERSION_MSG "(found version \"${VERSION}\")") + endif() + endif () + + if(VERSION_OK) + set(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]") + else() + set(${_FOUND_VAR} FALSE) + endif() + + + # print the result: + if (${_FOUND_VAR}) + FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}") + else () + + if(FPHSA_CONFIG_MODE) + _FPHSA_HANDLE_FAILURE_CONFIG_MODE() + else() + if(NOT VERSION_OK) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") + else() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}") + endif() + endif() + + endif () + + set(${_FOUND_VAR} ${${_FOUND_VAR}} PARENT_SCOPE) + +endfunction() diff --git a/cmake/FindPackageMessage.cmake b/cmake/FindPackageMessage.cmake new file mode 100644 index 00000000..a0349d3d --- /dev/null +++ b/cmake/FindPackageMessage.cmake @@ -0,0 +1,57 @@ +#.rst: +# FindPackageMessage +# ------------------ +# +# +# +# FIND_PACKAGE_MESSAGE(<name> "message for user" "find result details") +# +# This macro is intended to be used in FindXXX.cmake modules files. It +# will print a message once for each unique find result. This is useful +# for telling the user where a package was found. The first argument +# specifies the name (XXX) of the package. The second argument +# specifies the message to display. The third argument lists details +# about the find result so that if they change the message will be +# displayed again. The macro also obeys the QUIET argument to the +# find_package command. +# +# Example: +# +# :: +# +# if(X11_FOUND) +# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}" +# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]") +# else() +# ... +# endif() + +#============================================================================= +# Copyright 2008-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +function(FIND_PACKAGE_MESSAGE pkg msg details) + # Avoid printing a message repeatedly for the same find result. + if(NOT ${pkg}_FIND_QUIETLY) + string(REPLACE "\n" "" details "${details}") + set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg}) + if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}") + # The message has not yet been printed. + message(STATUS "${msg}") + + # Save the find details in the cache to avoid printing the same + # message again. + set("${DETAILS_VAR}" "${details}" + CACHE INTERNAL "Details about finding ${pkg}") + endif() + endif() +endfunction() diff --git a/cmake/FindSolidity.cmake b/cmake/FindSolidity.cmake new file mode 100644 index 00000000..f2086b65 --- /dev/null +++ b/cmake/FindSolidity.cmake @@ -0,0 +1,47 @@ +# Find Solidity +# +# Find the solidity includes and library +# +# This module defines +# Solidity_XXX_LIBRARIES, the libraries needed to use solidity. +# SOLIDITY_INCLUDE_DIRS + +include(EthUtils) +set(LIBS solidity;lll;evmasm) + +set(Solidity_INCLUDE_DIRS "${SOL_DIR}") + +# if the project is a subset of main cpp-ethereum project +# use same pattern for variables as Boost uses +if ((DEFINED solidity_VERSION) OR (DEFINED cpp-ethereum_VERSION)) + + foreach (l ${LIBS}) + string(TOUPPER ${l} L) + set ("Solidity_${L}_LIBRARIES" ${l}) + endforeach() + +else() + + foreach (l ${LIBS}) + string(TOUPPER ${l} L) + find_library(Solidity_${L}_LIBRARY + NAMES ${l} + PATHS ${CMAKE_LIBRARY_PATH} + PATH_SUFFIXES "lib${l}" "${l}" "lib${l}/Debug" "lib${l}/Release" + NO_DEFAULT_PATH + ) + + set(Solidity_${L}_LIBRARIES ${Solidity_${L}_LIBRARY}) + + if (DEFINED MSVC) + find_library(Solidity_${L}_LIBRARY_DEBUG + NAMES ${l} + PATHS ${CMAKE_LIBRARY_PATH} + PATH_SUFFIXES "lib${l}/Debug" + NO_DEFAULT_PATH + ) + eth_check_library_link(Solidity_${L}) + endif() + endforeach() + +endif() diff --git a/cmake/UseDev.cmake b/cmake/UseDev.cmake new file mode 100644 index 00000000..1f4c9a2d --- /dev/null +++ b/cmake/UseDev.cmake @@ -0,0 +1,30 @@ +function(eth_apply TARGET REQUIRED SUBMODULE) + + # Base is where all dependencies for devcore are + if (${SUBMODULE} STREQUAL "base") + # if it's ethereum source dir, always build BuildInfo.h before + eth_use(${TARGET} ${REQUIRED} Dev::buildinfo) + + target_include_directories(${TARGET} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) + target_link_libraries(${TARGET} ${Boost_THREAD_LIBRARIES}) + target_link_libraries(${TARGET} ${Boost_RANDOM_LIBRARIES}) + target_link_libraries(${TARGET} ${Boost_FILESYSTEM_LIBRARIES}) + target_link_libraries(${TARGET} ${Boost_SYSTEM_LIBRARIES}) + + if (DEFINED MSVC) + target_link_libraries(${TARGET} ${Boost_CHRONO_LIBRARIES}) + target_link_libraries(${TARGET} ${Boost_DATE_TIME_LIBRARIES}) + endif() + + if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + target_link_libraries(${TARGET} pthread) + endif() + + endif() + + if (${SUBMODULE} STREQUAL "devcore") + eth_use(${TARGET} ${REQUIRED} Dev::base) + target_link_libraries(${TARGET} devcore) + endif() + +endfunction() diff --git a/cmake/UseJsoncpp.cmake b/cmake/UseJsoncpp.cmake new file mode 100644 index 00000000..6f605283 --- /dev/null +++ b/cmake/UseJsoncpp.cmake @@ -0,0 +1,10 @@ +function(eth_apply TARGET REQUIRED) + find_package (Jsoncpp 0.60) + eth_show_dependency(JSONCPP JsonCpp) + if (JSONCPP_FOUND) + target_include_directories(${TARGET} SYSTEM BEFORE PUBLIC ${JSONCPP_INCLUDE_DIRS}) + target_link_libraries(${TARGET} ${JSONCPP_LIBRARIES}) + elseif (NOT ${REQUIRED} STREQUAL "OPTIONAL") + message(FATAL_ERROR "Jsoncpp library not found") + endif() +endfunction() diff --git a/cmake/UseSolidity.cmake b/cmake/UseSolidity.cmake new file mode 100644 index 00000000..46e2cac9 --- /dev/null +++ b/cmake/UseSolidity.cmake @@ -0,0 +1,33 @@ +function(eth_apply TARGET REQUIRED SUBMODULE) + + set(SOL_DIR "${ETH_CMAKE_DIR}/.." CACHE PATH "The path to the solidity directory") + set(SOL_BUILD_DIR_NAME "build" CACHE STRING "The name of the build directory in solidity repo") + set(SOL_BUILD_DIR "${SOL_DIR}/${SOL_BUILD_DIR_NAME}") + set(CMAKE_LIBRARY_PATH ${SOL_BUILD_DIR};${CMAKE_LIBRARY_PATH}) + + find_package(Solidity) + + # Hide confusing blank dependency information when using FindSolidity on itself. + if (NOT(${MODULE_MAIN} STREQUAL Solidity)) + eth_show_dependency(SOLIDITY solidity) + endif() + + target_include_directories(${TARGET} PUBLIC ${Solidity_INCLUDE_DIRS}) + + if (${SUBMODULE} STREQUAL "evmasm") + eth_use(${TARGET} ${REQUIRED} ) + target_link_libraries(${TARGET} ${Solidity_EVMASM_LIBRARIES}) + endif() + + if (${SUBMODULE} STREQUAL "lll") + eth_use(${TARGET} ${REQUIRED} Solidity::evmasm) + target_link_libraries(${TARGET} ${Solidity_LLL_LIBRARIES}) + endif() + + if (${SUBMODULE} STREQUAL "solidity" OR ${SUBMODULE} STREQUAL "") + eth_use(${TARGET} ${REQUIRED} Dev::devcore Solidity::evmasm) + target_link_libraries(${TARGET} ${Solidity_SOLIDITY_LIBRARIES}) + endif() + + target_compile_definitions(${TARGET} PUBLIC ETH_SOLIDITY) +endfunction() diff --git a/cmake/scripts/buildinfo.cmake b/cmake/scripts/buildinfo.cmake new file mode 100644 index 00000000..39359486 --- /dev/null +++ b/cmake/scripts/buildinfo.cmake @@ -0,0 +1,49 @@ +# generates BuildInfo.h +# +# this module expects +# ETH_SOURCE_DIR - main CMAKE_SOURCE_DIR +# ETH_DST_DIR - main CMAKE_BINARY_DIR +# ETH_BUILD_TYPE +# ETH_BUILD_PLATFORM +# ETH_BUILD_NUMBER +# ETH_VERSION_SUFFIX +# +# example usage: +# cmake -DETH_SOURCE_DIR=. -DETH_DST_DIR=build -DETH_BUILD_TYPE=Debug -DETH_BUILD_PLATFORM=Darwin/appleclang -P scripts/buildinfo.cmake + +if (NOT ETH_BUILD_TYPE) + set(ETH_BUILD_TYPE "unknown") +endif() + +if (NOT ETH_BUILD_PLATFORM) + set(ETH_BUILD_PLATFORM "unknown") +endif() + +execute_process( + COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} rev-parse HEAD + OUTPUT_VARIABLE ETH_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET +) + +if (NOT ETH_COMMIT_HASH) + set(ETH_COMMIT_HASH 0) +endif() + +execute_process( + COMMAND git --git-dir=${ETH_SOURCE_DIR}/.git --work-tree=${ETH_SOURCE_DIR} diff HEAD --shortstat + OUTPUT_VARIABLE ETH_LOCAL_CHANGES OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET +) + +if (ETH_LOCAL_CHANGES) + set(ETH_CLEAN_REPO 0) +else() + set(ETH_CLEAN_REPO 1) +endif() + +set(TMPFILE "${ETH_DST_DIR}/BuildInfo.h.tmp") +set(OUTFILE "${ETH_DST_DIR}/BuildInfo.h") + +configure_file("${ETH_BUILDINFO_IN}" "${TMPFILE}") + +include("${ETH_CMAKE_DIR}/EthUtils.cmake") +replace_if_different("${TMPFILE}" "${OUTFILE}" CREATE) + diff --git a/cmake/templates/BuildInfo.h.in b/cmake/templates/BuildInfo.h.in new file mode 100644 index 00000000..6f9baf50 --- /dev/null +++ b/cmake/templates/BuildInfo.h.in @@ -0,0 +1,11 @@ +#pragma once + +#define ETH_PROJECT_VERSION "@PROJECT_VERSION@" +#define ETH_COMMIT_HASH @ETH_COMMIT_HASH@ +#define ETH_CLEAN_REPO @ETH_CLEAN_REPO@ +#define ETH_BUILD_TYPE @ETH_BUILD_TYPE@ +#define ETH_BUILD_OS @ETH_BUILD_OS@ +#define ETH_BUILD_COMPILER @ETH_BUILD_COMPILER@ +#define ETH_BUILD_PLATFORM @ETH_BUILD_PLATFORM@ +#define ETH_BUILD_NUMBER @ETH_BUILD_NUMBER@ +#define ETH_VERSION_SUFFIX "@ETH_VERSION_SUFFIX@" |