diff --git a/.travis.yml b/.travis.yml index 4625dfb087..87f218e3dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,49 @@ language: cpp env: global: - /usr/local/bin:$PATH + - CONAN_USERNAME="google" + - CONAN_PACKAGE_NAME="benchmark" + +conan-linux: &conan-linux + os: linux + sudo: required + language: python + python: "3.6" + services: + - docker + before_install: + - | + CONAN_VERSION=${TRAVIS_TAG//v}; + export CONAN_REFERENCE=${CONAN_PACKAGE_NAME}/${CONAN_VERSION}; + export CONAN_CHANNEL="stable"; + install: + - ./conan/travis/install.sh + script: + - ./conan/travis/build.sh + # the following are dummies to overwrite default build steps + before_script: + - true + after_success: + - true + if: tag IS present +conan-osx: &conan-osx + os: osx + language: generic + before_install: + - | + CONAN_VERSION=${TRAVIS_TAG//v}; + export CONAN_REFERENCE=${CONAN_PACKAGE_NAME}/${CONAN_VERSION}; + export CONAN_CHANNEL="stable"; + install: + - ./conan/travis/install.sh + script: + - ./conan/travis/build.sh + # the following are dummies to overwrite default build steps + before_script: + - true + after_success: + - true + if: tag IS present matrix: include: @@ -137,6 +180,73 @@ matrix: compiler: gcc env: - COMPILER=g++-7 C_COMPILER=gcc-7 BUILD_TYPE=Debug + # Conan testing and uploading + - compiler: gcc + env: CONAN=True + language: python + python: "3.6" + before_install: + - pip install -U pip + install: + - pip install conan + before_script: + - pip --version + - conan --version + script: + - CONAN_FULL_REFERENCE=${CONAN_PACKAGE_NAME}/master@${CONAN_USERNAME}/testing + - conan create . ${CONAN_FULL_REFERENCE} --build + after_success: + # If this build is NOT triggered by a pull request; AND got triggered by either a tag OR push to master + # and the following environment variables are set: + # CONAN_UPLOAD - a reference to the Conan repository e.g. https://bintray.com/google/conan + # CONAN_LOGIN_USERNAME - user for the upload e.g. upload_bot_username + # CONAN_PASSWORD - password for the CONAN_LOGIN_USERNAME; for Bintray this is the API key + # then upload the new recipe version to the Conan repository. + # + # For the tag pushes we are using for the + # version the tag name, removing the "v" + # channel "stable" + # For master pushes we are using for the + # version simply "master" + # channel "testing" + - if [[ "${TRAVIS_PULL_REQUEST}" == "false" && "${TRAVIS_BRANCH}" == "master" && -n "${CONAN_UPLOAD}" && -n "${CONAN_LOGIN_USERNAME}" && -n "${CONAN_PASSWORD}" ]]; then + conan remote add ${CONAN_PACKAGE_NAME} ${CONAN_UPLOAD} --insert; + conan remote list; + + conan user -p "${CONAN_PASSWORD}" -r benchmark "${CONAN_LOGIN_USERNAME}"; + conan upload --force -r ${CONAN_PACKAGE_NAME} --retry 3 --retry-wait 10 --confirm "${CONAN_FULL_REFERENCE}"; + fi; + if: NOT tag IS present + - <<: *conan-linux + env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=lasote/conangcc49 + - <<: *conan-linux + env: CONAN_GCC_VERSIONS=5 CONAN_DOCKER_IMAGE=lasote/conangcc5 + - <<: *conan-linux + env: CONAN_GCC_VERSIONS=6 CONAN_DOCKER_IMAGE=lasote/conangcc6 + - <<: *conan-linux + env: CONAN_GCC_VERSIONS=7 CONAN_DOCKER_IMAGE=lasote/conangcc7 + - <<: *conan-linux + env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=lasote/conangcc8 + - <<: *conan-linux + env: CONAN_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=lasote/conanclang39 + - <<: *conan-linux + env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=lasote/conanclang40 + - <<: *conan-linux + env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=lasote/conanclang50 + - <<: *conan-linux + env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=lasote/conanclang60 + - <<: *conan-osx + osx_image: xcode7.3 + env: CONAN_APPLE_CLANG_VERSIONS=7.3 + - <<: *conan-osx + osx_image: xcode8.3 + env: CONAN_APPLE_CLANG_VERSIONS=8.1 + - <<: *conan-osx + osx_image: xcode9 + env: CONAN_APPLE_CLANG_VERSIONS=9.0 + - <<: *conan-osx + osx_image: xcode9.4 + env: CONAN_APPLE_CLANG_VERSIONS=9.1 before_script: - if [ -n "${LIBCXX_BUILD}" ]; then diff --git a/conan/CMakeLists.txt b/conan/CMakeLists.txt new file mode 100644 index 0000000000..15b92ca91a --- /dev/null +++ b/conan/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8.11) +project(cmake_wrapper) + +include(conanbuildinfo.cmake) +conan_basic_setup() + +include(${CMAKE_SOURCE_DIR}/CMakeListsOriginal.txt) diff --git a/conan/appveyor/build.py b/conan/appveyor/build.py new file mode 100644 index 0000000000..9bac46dbe7 --- /dev/null +++ b/conan/appveyor/build.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os + +if os.getenv("APPVEYOR_REPO_TAG") != "true": + print("Skip build step. It's not TAG") +else: + os.system("python conan/build.py") diff --git a/conan/appveyor/install.py b/conan/appveyor/install.py new file mode 100644 index 0000000000..962c7da6b7 --- /dev/null +++ b/conan/appveyor/install.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os + +if os.getenv("APPVEYOR_REPO_TAG") != "true": + print("Skip step. It's not TAG") +else: + os.system("pip install conan conan-package-tools") diff --git a/conan/build.py b/conan/build.py new file mode 100755 index 0000000000..47c79e7080 --- /dev/null +++ b/conan/build.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from cpt.packager import ConanMultiPackager +import os + +def set_appveyor_environment(): + if os.getenv("APPVEYOR") is not None: + compiler_version = os.getenv("CMAKE_VS_VERSION").split(" ")[0].replace('"', '') + os.environ["CONAN_VISUAL_VERSIONS"] = compiler_version + os.environ["CONAN_STABLE_BRANCH_PATTERN"] = "master" + ci_platform = os.getenv("Platform").replace('"', '') + ci_platform = "x86" if ci_platform == "x86" else "x86_64" + os.environ["CONAN_ARCHS"] = ci_platform + os.environ["CONAN_BUILD_TYPES"] = os.getenv("Configuration").replace('"', '') + +if __name__ == "__main__": + login_username = os.getenv("CONAN_LOGIN_USERNAME") + username = os.getenv("CONAN_USERNAME") + reference = os.getenv("CONAN_REFERENCE") + channel = os.getenv("CONAN_CHANNEL") + upload = os.getenv("CONAN_UPLOAD") + stable_branch_pattern = os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*") + test_folder = os.getenv("CPT_TEST_FOLDER", os.path.join("conan", "test_package")) + upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True) + set_appveyor_environment() + + builder = ConanMultiPackager(username=username, + reference=reference, + channel=channel, + login_username=login_username, + upload=upload, + stable_branch_pattern=stable_branch_pattern, + upload_only_when_stable=upload_only_when_stable, + test_folder=test_folder) + builder.add_common_builds(pure_c=False) + builder.run() diff --git a/conan/test_package/CMakeLists.txt b/conan/test_package/CMakeLists.txt new file mode 100644 index 0000000000..74a74af38d --- /dev/null +++ b/conan/test_package/CMakeLists.txt @@ -0,0 +1,10 @@ +project(test_package) +cmake_minimum_required(VERSION 2.8.11) + +set(CMAKE_VERBOSE_MAKEFILE TRUE) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +add_executable(${PROJECT_NAME} test_package.cpp) +target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS}) diff --git a/conan/test_package/conanfile.py b/conan/test_package/conanfile.py new file mode 100644 index 0000000000..f940718a40 --- /dev/null +++ b/conan/test_package/conanfile.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 + +from conans import ConanFile, CMake +import os + + +class TestPackageConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + bin_path = os.path.join("bin", "test_package") + self.run(bin_path, run_environment=True) diff --git a/conan/test_package/test_package.cpp b/conan/test_package/test_package.cpp new file mode 100644 index 0000000000..4fa7ec0bf9 --- /dev/null +++ b/conan/test_package/test_package.cpp @@ -0,0 +1,18 @@ +#include "benchmark/benchmark.h" + +void BM_StringCreation(benchmark::State& state) { + while (state.KeepRunning()) + std::string empty_string; +} + +BENCHMARK(BM_StringCreation); + +void BM_StringCopy(benchmark::State& state) { + std::string x = "hello"; + while (state.KeepRunning()) + std::string copy(x); +} + +BENCHMARK(BM_StringCopy); + +BENCHMARK_MAIN(); diff --git a/conan/travis/build.sh b/conan/travis/build.sh new file mode 100755 index 0000000000..069ced202f --- /dev/null +++ b/conan/travis/build.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e +set -x + +if [[ "$(uname -s)" == 'Darwin' ]]; then + if which pyenv > /dev/null; then + eval "$(pyenv init -)" + fi + pyenv activate conan +fi + +conan user +python conan/build.py diff --git a/conan/travis/install.sh b/conan/travis/install.sh new file mode 100755 index 0000000000..f4208d8264 --- /dev/null +++ b/conan/travis/install.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e +set -x + +if [[ "$(uname -s)" == 'Darwin' ]]; then + brew update || brew update + brew outdated pyenv || brew upgrade pyenv + brew install pyenv-virtualenv + brew install cmake || true + + if which pyenv > /dev/null; then + eval "$(pyenv init -)" + fi + + pyenv install 2.7.10 + pyenv virtualenv 2.7.10 conan + pyenv rehash + pyenv activate conan +fi + +pip install -U conan_package_tools conan diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000000..2ce1549653 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,82 @@ +from conans import ConanFile, CMake, tools +import shutil +import os + + +class GoogleBenchmarkConan(ConanFile): + name = "benchmark" + description = "A microbenchmark support library." + url = "https://github.com/google/benchmark" + homepage = "https://github.com/google/benchmark" + license = "Apache-2.0" + settings = "arch", "build_type", "compiler", "os" + options = { + "shared": [True, False], + "fPIC": [True, False], + "enable_exceptions": [True, False], + "enable_lto": [True, False], + "enable_testing": [True, False], + "enable_gtest_tests": [True, False] + } + default_options = "shared=False", "fPIC=True", "enable_exceptions=True", "enable_lto=False", "enable_testing=False", "enable_gtest_tests=False" + exports_sources = ["*"] + generators = "cmake" + + build_subfolder = "." + + def source(self): + """Wrap the original CMake file to call conan_basic_setup + """ + shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt") + shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt") + + def config_options(self): + if self.settings.os == 'Windows': + del self.options.fPIC + + def configure(self): + if self.settings.os == 'Windows' and self.options.shared: + raise Exception("Windows shared builds are not supported right now, see issue #639") + + if self.options.enable_testing == False: + self.options.enable_gtest_tests = False + + def _configure_cmake(self): + cmake = CMake(self) + cmake.definitions['BENCHMARK_ENABLE_TESTING'] = "ON" if self.options.enable_testing else "OFF" + cmake.definitions['BENCHMARK_ENABLE_GTEST_TESTS'] = "ON" if self.options.enable_gtest_tests and self.options.enable_testing else "OFF" + cmake.definitions["BENCHMARK_ENABLE_LTO"] = "ON" if self.options.enable_lto else "OFF" + cmake.definitions["BENCHMARK_ENABLE_EXCEPTIONS"] = "ON" if self.options.enable_exceptions else "OFF" + + # See https://github.com/google/benchmark/pull/638 for Windows 32 build explanation + if self.settings.os != "Windows": + cmake.definitions["BENCHMARK_BUILD_32_BITS"] = "ON" if "64" not in str(self.settings.arch) else "OFF" + cmake.definitions["BENCHMARK_USE_LIBCXX"] = "ON" if (str(self.settings.compiler.libcxx) == "libc++") else "OFF" + else: + cmake.definitions["BENCHMARK_USE_LIBCXX"] = "OFF" + + cmake.configure(build_folder=self.build_subfolder) + return cmake + + def build_requirements(self): + if self.options.enable_gtest_tests: + self.build_requires("gtest/1.8.0@bincrafters/stable") + + def build(self): + cmake = self._configure_cmake() + cmake.build() + + def package(self): + cmake = self._configure_cmake() + cmake.install() + + self.copy(pattern="LICENSE", dst="licenses") + + def package_info(self): + self.cpp_info.libs = tools.collect_libs(self) + if self.settings.os == "Linux": + self.cpp_info.libs.extend(["pthread", "rt"]) + elif self.settings.os == "Windows": + self.cpp_info.libs.append("shlwapi") + elif self.settings.os == "SunOS": + self.cpp.info.libs.append("kstat")