Add Linux/Clang CI build using Travis CI (#63)

* Add .travis.yml configuration file for Travis CI
  This builds Linux x64 clang 6.0-dev debug/optimised variants.
* Make clang/libc++ locations configurable from cake command-line.
  Added new cake command-line args for Linux/Darwin builds:
  --clang-executable=PATH
  --clang-install-prefix=PATH
* Refactored config.cake to remove duplication between Linux/Darwin build variants.
* Added `build-clang.sh` and `build-libcxx.sh` helper scripts.
* Add Linux build status badge to README.
* Make Appveyor badge link to build status page.
* Ignore Linux CI failures for clang optimised builds.
  They are currently failing due to a compiler bug.
This commit is contained in:
Lewis Baker 2017-12-12 10:21:35 +10:30 committed by GitHub
parent 1142838144
commit 2c67b4475d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 350 additions and 107 deletions

72
.travis.yml Normal file
View File

@ -0,0 +1,72 @@
# Copyright Lewis Baker 2017
#
# Distributed under MIT license.
# See LICENSE.txt file for details.
language: cpp
os: linux
dist: trusty
git:
submodules: true
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty
packages:
- python2.7
- clang-6.0
- lld-6.0
- ninja-build
cache:
directories:
- ${TOOLS_DIR}/cmake-${CMAKE_VERSION}
compiler:
- clang
env:
global:
- TOOLS_DIR=${TRAVIS_BUILD_DIR}/tools
- LLVM_INSTALL_PREFIX=${TOOLS_DIR}/llvm
- CMAKE_VERSION="3.9.1"
matrix:
include:
- env: RELEASE=debug ARCH=x64 CLANG_VERSION=6.0
- env: RELEASE=optimised ARCH=x64 CLANG_VERSION=6.0
allow_failures:
# Clang 6.0~svn320382 has a bug that causes optimised builds to fail.
# See https://bugs.llvm.org/show_bug.cgi?id=34897
- env: RELEASE=optimised ARCH=x64 CLANG_VERSION=6.0
before_install:
- export CC="$CC-$CLANG_VERSION"
- export CXX="$CXX-$CLANG_VERSION"
- |
if [ ! -f "${TOOLS_DIR}/cmake-${CMAKE_VERSION}/cached" ]; then
CMAKE_URL="https://cmake.org/files/v3.9/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz"
mkdir -p "${TOOLS_DIR}/cmake-${CMAKE_VERSION}"
travis_retry wget --no-check-certificate --quiet -O - "${CMAKE_URL}" | tar --strip-components=1 -xz -C "${TOOLS_DIR}/cmake-${CMAKE_VERSION}"
touch "${TOOLS_DIR}/cmake-${CMAKE_VERSION}/cached"
else
echo "Using cached CMake version ${CMAKE_VERSION}"
fi
export PATH="${TOOLS_DIR}/cmake-${CMAKE_VERSION}/bin:$PATH"
install:
- ./build-libcxx.sh
- export LD_LIBRARY_PATH="${LLVM_INSTALL_PREFIX}/lib"
before_script:
- source ./init.sh
script:
- cake architecture=$ARCH release=$RELEASE --clang-executable="$CC" --libcxx-install-prefix="${LLVM_INSTALL_PREFIX}"
notifications:
email: false

View File

@ -41,8 +41,8 @@ It has been open-sourced in the hope that others will find it useful and that th
can provide feedback on it and ways to improve it.
It requires a compiler that supports the coroutines TS:
- Windows + Visual Studio 2017 ![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/lewissbaker/cppcoro?branch=master&svg=true&passingText=master%20-%20OK&failingText=master%20-%20Failing&pendingText=master%20-%20Pending)
- Linux + Clang 5.0/6.0 + libc++
- Windows + Visual Studio 2017 [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/lewissbaker/cppcoro?branch=master&svg=true&passingText=master%20-%20OK&failingText=master%20-%20Failing&pendingText=master%20-%20Pending)](https://ci.appveyor.com/project/lewissbaker/cppcoro/branch/master)
- Linux + Clang 5.0/6.0 + libc++ [![Build Status](https://travis-ci.org/lewissbaker/cppcoro.svg?branch=master)](https://travis-ci.org/lewissbaker/cppcoro)
The Linux version is functional except for the `io_context` and file I/O related classes which have not yet been implemented for Linux (see issue [#15](https://github.com/lewissbaker/cppcoro/issues/15) for more info).

View File

@ -4,6 +4,7 @@
# This file defines extra command-line args specific to the cppcoro project.
##############################################################################
from cake.script import Script
import cake.system
parser = Script.getCurrent().engine.parser
@ -16,3 +17,30 @@ parser.add_option(
help="Create projects instead of building a variant.",
default=False,
)
if cake.system.isLinux() or cake.system.isDarwin():
parser.add_option(
"--clang-install-prefix",
dest="clangInstallPrefix",
type="string",
metavar="PATH",
default=None,
help="Path where clang has been installed."
)
parser.add_option(
"--clang-executable",
dest="clangExecutable",
type="string",
metavar="FILE",
default="clang",
help="Name or full-path of clang executable to compile with")
parser.add_option(
"--libcxx-install-prefix",
dest="libcxxInstallPrefix",
type="string",
metavar="PATH",
default=None,
help="Path where libc++ has been installed.\n"
"Defaults to value of --clang-install-prefix")

104
build-clang.sh Executable file
View File

@ -0,0 +1,104 @@
#!/bin/bash
#
# Builds Clang and LLD from source.
export WORKSPACE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export LLVM_PROJECT="${WORKSPACE_ROOT}/tools/llvm-project"
: "${LLVM_REPO:=https://github.com/llvm-mirror/llvm.git}"
: "${LLVM_REF:=master}"
: "${CLANG_REPO:=https://github.com/llvm-mirror/clang.git}"
: "${CLANG_REF:=master}"
: "${LLD_REPO:=https://github.com/llvm-mirror/lld.git}"
: "${LLD_REF:=master}"
: "${LIBCXX_REPO:=https://github.com/llvm-mirror/libcxx.git}"
: "${LIBCXX_REF:=master}"
: "${LLVM_INSTALL_PREFIX:=$WORKSPACE_ROOT/build/llvm-install}"
: "${CXX:=clang++}"
: "${CC:=clang}"
if [ ! -d "${LLVM_PROJECT}" ]; then
mkdir -p "${LLVM_PROJECT}" || exit
fi
cd "${LLVM_PROJECT}" || exit
if [ ! -d llvm/.git ]; then
git clone --depth=1 -b "$LLVM_REF" -- "$LLVM_REPO" llvm || exit
else
(cd llvm &&
git remote set-url origin "$LLVM_REPO" &&
git fetch origin "$LLVM_REF" &&
git checkout FETCH_HEAD) || exit
fi
if [ ! -d llvm/tools/clang/.git ]; then
git clone --depth=1 -b "$CLANG_REF" -- "$CLANG_REPO" llvm/tools/clang || exit
ln -s llvm/tools/clang clang || exit
else
(cd llvm/tools/clang &&
git remote set-url origin "$CLANG_REPO" &&
git fetch --depth=1 origin "$CLANG_REF" &&
git checkout FETCH_HEAD) || exit
fi
if [ ! -d llvm/tools/lld/.git ]; then
git clone --depth=1 -b "$LLD_REF" -- "$LLD_REPO" llvm/tools/lld || exit
ln -s llvm/tools/lld lld || exit
else
(cd llvm/tools/lld &&
git remote set-url origin "$LLD_REPO" &&
git fetch --depth=1 origin "$LLD_REF" &&
git checkout FETCH_HEAD) || exit
fi
if [ ! -d llvm/projects/libcxx.git ]; then
git clone --depth=1 -b "$LIBCXX_REF" -- "$LIBCXX_REPO" llvm/projects/libcxx || exit
ln -s llvm/projects/libcxx libcxx || exit
else
(cd llvm/projects/libcxx &&
git remote set-url origin "$LIBCXX_REPO" &&
git fetch --depth=1 origin "$LIBCXX_REF" &&
git checkout FETCH_HEAD) || exit
fi
cd "$WORKSPACE_ROOT" || exit
if [ ! -d build/clang ]; then
mkdir -p build/clang || exit
fi
# Build clang toolchain
(mkdir -p build/clang && \
cd build/clang && \
cmake -GNinja \
-DCMAKE_CXX_COMPILER="$CXX" \
-DCMAKE_C_COMPILER="$CC" \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DCMAKE_INSTALL_PREFIX="${LLVM_INSTALL_PREFIX}" \
-DCMAKE_BUILD_WITH_INSTALL_RPATH="yes" \
-DLLVM_TARGETS_TO_BUILD=X86 \
-DLLVM_ENABLE_PROJECTS="lld;clang" \
"${LLVM_PROJECT}/llvm" && \
ninja install-clang \
install-clang-headers \
install-llvm-ar \
install-lld) || exit
# Build libcxx using clang we just built
(mkdir -p build/libcxx && \
cd build/libcxx && \
cmake -GNinja \
-DCMAKE_CXX_COMPILER="${LLVM_INSTALL_PREFIX}/bin/clang++" \
-DCMAKE_C_COMPILER="${LLVM_INSTALL_PREFIX}/bin/clang" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="${LLVM_INSTALL_PREFIX}" \
-DLLVM_PATH="${LLVM_PROJECT}/llvm" \
-DLIBCXX_CXX_ABI=libstdc++ \
"${LLVM_PROJECT}/libcxx" && \
ninja install) || exit

56
build-libcxx.sh Executable file
View File

@ -0,0 +1,56 @@
#!/bin/bash
#
# Builds libc++ from source
export WORKSPACE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export LLVM_PROJECT="${WORKSPACE_ROOT}/tools/llvm-project"
: "${LLVM_REPO:=https://github.com/llvm-mirror/llvm.git}"
: "${LLVM_REF:=master}"
: "${LIBCXX_REPO:=https://github.com/llvm-mirror/libcxx.git}"
: "${LIBCXX_REF:=master}"
: "${LLVM_INSTALL_PREFIX:=$WORKSPACE_ROOT/build/llvm-install}"
: "${CXX:=clang++}"
: "${CC:=clang}"
if [ ! -d "${LLVM_PROJECT}" ]; then
mkdir -p "${LLVM_PROJECT}" || exit
fi
cd "${LLVM_PROJECT}" || exit
if [ ! -d llvm/.git ]; then
git clone --depth=1 -b "$LLVM_REF" -- "$LLVM_REPO" llvm || exit
else
(cd llvm &&
git remote set-url origin "$LLVM_REPO" &&
git fetch origin "$LLVM_REF" &&
git checkout FETCH_HEAD) || exit
fi
if [ ! -d llvm/projects/libcxx.git ]; then
git clone --depth=1 -b "$LIBCXX_REF" -- "$LIBCXX_REPO" llvm/projects/libcxx || exit
ln -s llvm/projects/libcxx libcxx || exit
else
(cd llvm/projects/libcxx &&
git remote set-url origin "$LIBCXX_REPO" &&
git fetch --depth=1 origin "$LIBCXX_REF" &&
git checkout FETCH_HEAD) || exit
fi
cd "$WORKSPACE_ROOT" || exit
(mkdir -p build/libcxx && \
cd build/libcxx && \
cmake -GNinja \
-DCMAKE_CXX_COMPILER="${CXX}" \
-DCMAKE_C_COMPILER="${CC}" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="${LLVM_INSTALL_PREFIX}" \
-DLLVM_PATH="${LLVM_PROJECT}/llvm" \
-DLIBCXX_CXX_ABI=libstdc++ \
"${LLVM_PROJECT}/libcxx" && \
ninja install) || exit

View File

@ -176,45 +176,103 @@ if cake.system.isWindows() or cake.system.isCygwin():
except CompilerNotFoundError, e:
print str(e)
elif cake.system.isLinux():
elif cake.system.isLinux() or cake.system.isDarwin():
def firstExisting(paths, default=None):
for p in paths:
if os.path.exists(p):
return p
else:
return default
if cake.system.isLinux():
defaultInstallPaths = ["/usr"]
elif cake.system.isDarwin():
defaultInstallPaths = ["/usr/local/opt/llvm", "/usr"]
clangInstallPrefix = engine.options.clangInstallPrefix
clangExe = engine.options.clangExecutable
if clangInstallPrefix is None:
# If no clang install prefix was specified then try to deduce it
# from the --clang-executable path.
if os.path.isabs(clangExe):
clangBinPath = cake.path.dirName(clangExe)
if cake.path.baseName(clangBinPath) == 'bin':
clangInstallPrefix = cake.path.dirName(clangBinPath)
# Use sensible system defaults if neither --clang-executable or
# --clang-install-prefix command-line arguments are specified.
if clangInstallPrefix is None:
clangInstallPrefix = firstExisting(defaultInstallPaths, default="/usr")
libcxxInstallPrefix = engine.options.libcxxInstallPrefix
if libcxxInstallPrefix is None:
libcxxInstallPrefix = clangInstallPrefix
# If the user didn't specify an absolute path to clang then look for it in
# the installed clang bin directory.
if not os.path.isabs(clangExe):
clangExe = cake.path.join(clangInstallPrefix, 'bin', clangExe)
# Extract the clang version suffix from the file-name
# We'll try and use other LLVM tools with the same suffix if they exist.
clangName = cake.path.baseName(clangExe)
versionSuffix = clangName[5:] if clangName.startswith('clang-') else ""
clangExeDir = cake.path.dirName(clangExe)
clangBinPath = cake.path.join(clangInstallPrefix, 'bin')
binPaths = [clangExeDir]
if clangBinPath not in binPaths:
binPaths.append(clangBinPath)
llvmArExe = firstExisting(
cake.path.join(binPaths, ['llvm-ar' + versionSuffix, 'llvm-ar', 'ar']),
default="/usr/bin/ar")
# Prefer lld if available, otherwise fall back to system ld
lldExe = firstExisting(
cake.path.join(binPaths, ['ld.lld' + versionSuffix, 'ld.lld']),
)
engine.logger.outputInfo(
"clang: " + clangExe + "\n" +
"llvm-ar: " + llvmArExe + "\n")
from cake.library.compilers.clang import ClangCompiler
if cake.system.isLinux():
platform = 'linux'
elif cake.system.isDarwin():
platform = 'darwin'
clangVariant = baseVariant.clone(compiler='clang',
platform='linux',
platform=platform,
architecture='x64')
# If you have built your own version of Clang, you can modify
# this variable to point to the CMAKE_INSTALL_PREFIX for
# where you have installed your clang/libcxx build.
clangInstallPrefix = '/usr'
# Set this to the install-prefix of where libc++ is installed.
# You only need to set this if it is not installed at the same
# location as clangInstallPrefix.
libCxxInstallPrefix = None # '/path/to/install'
clangBinPath = cake.path.join(clangInstallPrefix, 'bin')
compiler = ClangCompiler(
configuration=configuration,
clangExe=cake.path.join(clangBinPath, 'clang'),
llvmArExe=cake.path.join(clangBinPath, 'llvm-ar'),
clangExe=clangExe,
llvmArExe=llvmArExe,
binPaths=[clangBinPath])
compiler.addCppFlag('-std=c++1z')
compiler.addCppFlag('-fcoroutines-ts')
compiler.addCppFlag('-m64')
compiler.addModuleFlag('-fuse-ld=lld')
compiler.addProgramFlag('-fuse-ld=lld')
if lldExe:
compiler.addModuleFlag('-fuse-ld=' + lldExe)
compiler.addProgramFlag('-fuse-ld=' + lldExe)
if libCxxInstallPrefix:
if libcxxInstallPrefix != clangInstallPrefix:
compiler.addCppFlag('-nostdinc++')
compiler.addIncludePath(cake.path.join(
libCxxInstallPrefix, 'include', 'c++', 'v1'))
libcxxInstallPrefix, 'include', 'c++', 'v1'))
compiler.addLibraryPath(cake.path.join(
libCxxInstallPrefix, 'lib'))
libcxxInstallPrefix, 'lib'))
else:
compiler.addCppFlag('-stdlib=libc++')
@ -229,8 +287,8 @@ elif cake.system.isLinux():
env = clangVariant.tools["env"]
env["COMPILER"] = "clang"
env["COMPILER_VERSION"] = "5.0"
env["PLATFORM"] = "linux"
env["COMPILER_VERSION"] = compiler.version
env["PLATFORM"] = platform
env["ARCHITECTURE"] = "x64"
clangDebugVariant = clangVariant.clone(release='debug')
@ -250,86 +308,11 @@ elif cake.system.isLinux():
compiler = clangOptimisedVariant.tools["compiler"]
compiler.addCppFlag('-O3')
compiler.addCppFlag('-g')
compiler.addCppFlag('-flto')
compiler.addProgramFlag('-flto')
compiler.addModuleFlag('-flto')
configuration.addVariant(clangOptimisedVariant)
elif cake.system.isDarwin():
from cake.library.compilers.clang import ClangCompiler
clangVariant = baseVariant.clone(compiler='clang',
platform='darwin',
architecture='x86_64')
# If you have built your own version of Clang, you can modify
# this variable to point to the CMAKE_INSTALL_PREFIX for
# where you have installed your clang/libcxx build.
clangInstallPrefix = '/usr/local/opt/llvm'
# Set this to the install-prefix of where libc++ is installed.
# You only need to set this if it is not installed at the same
# location as clangInstallPrefix.
libCxxInstallPrefix = None # '/path/to/install'
clangBinPath = cake.path.join(clangInstallPrefix, 'bin')
compiler = ClangCompiler(
configuration=configuration,
clangExe=cake.path.join(clangBinPath, 'clang'),
llvmArExe=cake.path.join(clangBinPath, 'llvm-ar'),
binPaths=[clangBinPath])
compiler.addCppFlag('-std=c++17')
compiler.addCppFlag('-fcoroutines-ts')
compiler.addCppFlag('-m64')
compiler.addModuleFlag('-fuse-ld=/usr/bin/ld')
compiler.addProgramFlag('-fuse-ld=/usr/bin/ld')
if libCxxInstallPrefix:
compiler.addCppFlag('-nostdinc++')
compiler.addIncludePath(cake.path.join(
libCxxInstallPrefix, 'include', 'c++', 'v1'))
compiler.addLibraryPath(cake.path.join(
libCxxInstallPrefix, 'lib'))
else:
compiler.addCppFlag('-stdlib=libc++')
compiler.addLibrary('c++')
#compiler.addProgramFlag('-Wl,--trace')
#compiler.addProgramFlag('-Wl,-v')
clangVariant.tools['compiler'] = compiler
env = clangVariant.tools["env"]
env["COMPILER"] = "clang"
env["COMPILER_VERSION"] = "5.0"
env["PLATFORM"] = "darwin"
env["ARCHITECTURE"] = "x86_64"
clangDebugVariant = clangVariant.clone(release='debug')
clangDebugVariant.tools["env"]["RELEASE"] = 'debug'
# Configure debug-specific settings here
compiler = clangDebugVariant.tools["compiler"]
compiler.addCppFlag('-O0')
compiler.addCppFlag('-g')
configuration.addVariant(clangDebugVariant)
clangOptimisedVariant = clangVariant.clone(release='optimised')
clangOptimisedVariant.tools["env"]["RELEASE"] = 'optimised'
# Configure optimised-specific settings here
compiler = clangOptimisedVariant.tools["compiler"]
compiler.addCppFlag('-O3')
compiler.addCppFlag('-g')
compiler.addCppFlag('-flto')
compiler.addProgramFlag('-flto')
compiler.addModuleFlag('-flto')
# Only use link-time optimisation if we're using LLD
if lldExe:
compiler.addCppFlag('-flto')
compiler.addProgramFlag('-flto')
compiler.addModuleFlag('-flto')
configuration.addVariant(clangOptimisedVariant)

0
init.sh Normal file → Executable file
View File

@ -1 +1 @@
Subproject commit 88d8c43e9ec2e49adc89e671c849b0b1f5814e4d
Subproject commit db43f336b95d367163b967491f4e22d252ae59b4