From 1f03becd24b60d8634d5e725b51fabdbafd28ddb Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Thu, 16 Aug 2018 16:17:52 -0300 Subject: [PATCH] Conan build packages on CI (#4590) (#4594) * Build Conan package on Travis CI (#4590) - Added multi package support on Linux, running on Travis CI - Only upload when branch is a tag and named "vX.Y.Z" - Replace Conan injection by Conan wrapper - Removed os_build os_arch -- Conan 1.0.1 hotfix Signed-off-by: Uilian Ries * Build Conan package on OSX (#4590) - Added jobs to build Flatbuffers on OSX running on Travis Signed-off-by: Uilian Ries * Build Conan package on Windows (#4590) - Added support necessary to build Flatbuffers on Windows (conan) - Added Appveyor jobs to build Conan package - Only build Conan package when release (tag) Signed-off-by: Uilian Ries * Reduce Conan CI support to simple scripts (#4590) - Removed msvc 10 x86_64 workaround - Updated conan remote address - Added Bincrafters' package tools Signed-off-by: Uilian Ries * Add fPIC option on Conan recipe (#4590) - Add fPIC as optional. It works on Linux and OSX - Update recipe metadata: author, homepage, license - Checking for flatc and flathash on Conan package Signed-off-by: Uilian Ries * Build Conan package on CI (#4590) - Add rule to run conan job only for tags - Run Conan on Linux, OSX and Windows - Update package tool to new interface Signed-off-by: Uilian Ries * Update Conan username (#4590) - Use google as default username Signed-off-by: Uilian Ries * Update OSX version on CI (#4590) - Use latest OSX 9.3 version to build Conan package Signed-off-by: Uilian Ries --- .travis.yml | 56 +++++++++++++++++++++++++++- appveyor.yml | 5 +++ conan/CMakeLists.txt | 12 ++++++ conan/appveyor/build.py | 8 ++++ conan/appveyor/install.py | 8 ++++ conan/build.py | 32 ++++++++++++++++ conan/test_package/CMakeLists.txt | 9 +++++ conan/test_package/conanfile.py | 21 +++++++++++ conan/test_package/test_package.cpp | 35 ++++++++++++++++++ conan/travis/build.sh | 14 +++++++ conan/travis/install.sh | 22 +++++++++++ conanfile.py | 57 +++++++++++++++++++---------- 12 files changed, 259 insertions(+), 20 deletions(-) create mode 100644 conan/CMakeLists.txt create mode 100644 conan/appveyor/build.py create mode 100644 conan/appveyor/install.py create mode 100644 conan/build.py create mode 100644 conan/test_package/CMakeLists.txt create mode 100644 conan/test_package/conanfile.py create mode 100644 conan/test_package/test_package.cpp create mode 100755 conan/travis/build.sh create mode 100755 conan/travis/install.sh diff --git a/.travis.yml b/.travis.yml index 3fb0abd66..a4cade39c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,29 @@ env: global: # Set at the root level as this is ignored when set under matrix.env. - GCC_VERSION="4.9" + +conan-linux: &conan-linux + os: linux + sudo: required + language: python + python: "3.6" + services: + - docker + install: + - ./conan/travis/install.sh + script: + - ./conan/travis/build.sh + if: tag IS present + +conan-osx: &conan-osx + os: osx + language: generic + install: + - ./conan/travis/install.sh + script: + - ./conan/travis/build.sh + if: tag IS present + matrix: include: #- language: python @@ -50,7 +73,7 @@ matrix: script: - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test - - if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . flatbuffers/testing -s build_type=$BUILD_TYPE; fi + - if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . google/testing -s build_type=$BUILD_TYPE -tf conan/test_package; fi - language: cpp os: osx @@ -62,6 +85,37 @@ matrix: script: - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test + - <<: *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.3 + env: CONAN_APPLE_CLANG_VERSIONS=9.1 + #- language: android # sudo: true # android: diff --git a/appveyor.yml b/appveyor.yml index d9dd5f1c5..e5be9eac6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,6 +13,7 @@ environment: matrix: - CMAKE_VS_VERSION: "10 2010" + - CMAKE_VS_VERSION: "12 2013" - CMAKE_VS_VERSION: "14 2015" platform: @@ -32,6 +33,10 @@ build: project: ALL_BUILD.vcxproj verbosity: minimal +after_build: + - python conan/appveyor/install.py + - python conan/appveyor/build.py + install: - set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%; diff --git a/conan/CMakeLists.txt b/conan/CMakeLists.txt new file mode 100644 index 000000000..d32a01327 --- /dev/null +++ b/conan/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 2.8) + +message(STATUS "Conan FlatBuffers Wrapper") + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +if (WIN32 AND MSVC AND FLATBUFFERS_BUILD_SHAREDLIB) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +endif(WIN32 AND MSVC AND FLATBUFFERS_BUILD_SHAREDLIB) + +include(${CMAKE_SOURCE_DIR}/CMakeListsOriginal.txt) diff --git a/conan/appveyor/build.py b/conan/appveyor/build.py new file mode 100644 index 000000000..9bac46dbe --- /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 000000000..962c7da6b --- /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 100644 index 000000000..6c63de8b2 --- /dev/null +++ b/conan/build.py @@ -0,0 +1,32 @@ +#!/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", "aardappel") + username = os.getenv("CONAN_USERNAME", "google") + upload = os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers") + 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, + 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 000000000..9c1c78c58 --- /dev/null +++ b/conan/test_package/CMakeLists.txt @@ -0,0 +1,9 @@ +project(test_package CXX) +cmake_minimum_required(VERSION 2.8.11) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +add_executable(${PROJECT_NAME} test_package.cpp) +target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS}) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11) diff --git a/conan/test_package/conanfile.py b/conan/test_package/conanfile.py new file mode 100644 index 000000000..735e31d27 --- /dev/null +++ b/conan/test_package/conanfile.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +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) + self.run("flatc --version", run_environment=True) + self.run("flathash fnv1_16 conan", run_environment=True) diff --git a/conan/test_package/test_package.cpp b/conan/test_package/test_package.cpp new file mode 100644 index 000000000..df7d577ae --- /dev/null +++ b/conan/test_package/test_package.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "flatbuffers/util.h" + +// Test to validate Conan package generated + +int main(int /*argc*/, const char * /*argv*/ []) { + + const std::string filename("conanbuildinfo.cmake"); + + if (flatbuffers::FileExists(filename.c_str())) { + std::cout << "File " << filename << " exists.\n"; + } else { + std::cout << "File " << filename << " does not exist.\n"; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/conan/travis/build.sh b/conan/travis/build.sh new file mode 100755 index 000000000..069ced202 --- /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 000000000..f4208d826 --- /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 index ee54bd1d2..718cf2cf7 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,52 +4,71 @@ """Conan recipe package for Google FlatBuffers """ import os +import shutil from conans import ConanFile, CMake, tools class FlatbuffersConan(ConanFile): name = "flatbuffers" version = "1.9.0" - license = "https://github.com/google/flatbuffers/blob/master/LICENSE.txt" + license = "Apache-2.0" url = "https://github.com/google/flatbuffers" + homepage = "http://google.github.io/flatbuffers/" + author = "Wouter van Oortmerssen" description = "Memory Efficient Serialization Library" - settings = "os", "compiler", "build_type", "arch", "os_build", "arch_build" - options = {"shared": [True, False]} - default_options = "shared=False" + settings = "os", "compiler", "build_type", "arch" + options = {"shared": [True, False], "fPIC": [True, False]} + default_options = "shared=False", "fPIC=True" generators = "cmake" exports = "LICENSE.txt" - exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt"] + exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt", "conan/CMakeLists.txt"] - def _inject_magic_lines(self): - """Inject Conan setup in cmake file to solve exteral dependencies. + def source(self): + """Wrap the original CMake file to call conan_basic_setup """ - conan_magic_lines = '''project(FlatBuffers) - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) - conan_basic_setup() - ''' - tools.replace_in_file("CMakeLists.txt", "project(FlatBuffers)", conan_magic_lines) + shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt") + shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt") + + def config_options(self): + """Remove fPIC option on Windows platform + """ + if self.settings.os == "Windows": + self.options.remove("fPIC") + + def configure_cmake(self): + """Create CMake instance and execute configure step + """ + cmake = CMake(self) + cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False + cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared + cmake.definitions["FLATBUFFERS_BUILD_FLATLIB"] = not self.options.shared + cmake.configure() + return cmake def build(self): """Configure, build and install FlatBuffers using CMake. """ - self._inject_magic_lines() - cmake = CMake(self) - cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False - cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared - cmake.configure() + cmake = self.configure_cmake() cmake.build() - cmake.install() def package(self): """Copy Flatbuffers' artifacts to package folder """ + cmake = self.configure_cmake() + cmake.install() self.copy(pattern="LICENSE.txt", dst="licenses") self.copy(pattern="flathash*", dst="bin", src="bin") self.copy(pattern="flatc*", dst="bin", src="bin") + if self.settings.os == "Windows" and self.options.shared: + if self.settings.compiler == "Visual Studio": + shutil.move(os.path.join(self.package_folder, "lib", "%s.dll" % self.name), + os.path.join(self.package_folder, "bin", "%s.dll" % self.name)) + elif self.settings.compiler == "gcc": + shutil.move(os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name), + os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name)) def package_info(self): """Collect built libraries names and solve flatc path. """ self.cpp_info.libs = tools.collect_libs(self) - self.env_info.PATH.append(os.path.join(self.package_folder, "bin")) self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc")