troubles linking boost statically to shared objet on linux - c++

I am using Boost 1.57.0
I compiled it with the following command
sudo ./b2 install --prefix=/home/sumkin/boost_build cxxflags='-fPIC' link=static
When I compile shared library to where I want to link boost statically I got the following error
/usr/bin/ld: /home/sumkin/boost_build/lib/libboost_filesystem.a(operations.o):
relocation R_X86_64_32 against `.rodata.str1.1' can not
be used when making a shared object; recompile with -fPIC
/home/sumkin/boost_build/lib/libboost_filesystem.a: error adding
symbols: Bad value
collect2: error: ld returned 1 exit status
make[2]: *** [libhtkernel.so] Error 1
make[1]: *** [CMakeFiles/htkernel.dir/all] Error 2
make: *** [all] Error 2
What I am doing wrong? I am on x86_64-linux-gnu.

We use this script to build boost statically and do build shared libs from it afterwards:
#! /bin/bash
set -eux
. ${VOLUMEDRIVER_BUILD_CONFIGURATION?"You need to set the path to the build configuration file"}
BOOST_VERSION=boost_1_57_0
BOOST_DIR=$BOOST_VERSION
BOOST_PACKAGE=$BOOST_VERSION.tar.bz2
BOOST_URL=http://downloads.sourceforge.net/project/boost/boost/1.57.0/$BOOST_PACKAGE
BOOST_BUILD_DIR=boost_build
. ../definitions.sh
. ../../helper-functions.sh
get_package_or_die $BOOST_PACKAGE $BOOST_URL
echo ">+>+> Cleaning up from previous build"
rm -rf $BOOST_DIR $BOOST_BUILD_DIR
echo "<+<+< Done cleaning up from previous build"
echo ">+>+> Unpacking $BOOST_PACKAGE"
tar -xjf $SOURCES_DIR/$BOOST_PACKAGE
echo "<+<+< Done unpacking $BOOST_PACKAGE"
echo ">+>+> Patching $BOOST_VERSION"
# patch -p0 < boost.patch0 # a more descriptive name would be nice
pushd $BOOST_DIR
patch -p1 < ../boost-make-valgrind-happy.patch
popd
echo "<+<+< Done patching $BOOST_VERSION"
# Add the correct flags for boost compilation .. another build system..lovely
BOOST_COMPILER_FLAGS=""
for i in ${CXX_COMPILER_FLAGS}
do
BOOST_COMPILER_FLAGS="$BOOST_COMPILER_FLAGS <cxxflags>$i"
done
# Specifying which boost to use can be done here by checking:
# http://www.boost.org/doc/libs/1_53_0/libs/python/doc/building.html
# and specifying the correct using python line beneath. For now we just
# support the system python and trust that that is the one the boost
# build system will find.
cat > project-config.jam <<EOF
# Boost.Build Configuration
# Automatically generated by bootstrap.sh
import option ;
import feature ;
# Compiler configuration. This definition will be used unless
# you already have defined some toolsets in your user-config.jam
# file.
# if ! gcc in [ feature.values <toolset> ]
{
using gcc : vd : $PREFIX/bin/vd-g++ : $BOOST_COMPILER_FLAGS ;
}
project : default-build <toolset>gcc ;
# Python configuration
using python : 2.7 : /usr ;
# List of --with-<library> and --without-<library>
# options. If left empty, all libraries will be built.
# Options specified on the command line completely
# override this variable.
libraries = --without-math --without-wave --without-graph --without-graph_parallel --without-mpi ;
# These settings are equivivalent to corresponding command-line
# options.
option.set prefix : $PREFIX ;
option.set exec-prefix : $PREFIX ;
option.set libdir : $PREFIX/lib ;
option.set includedir : $PREFIX/include ;
# Stop on first error
option.set keep-going : false ;
EOF
echo ">+>+> Configuring $BOOST_VERSION"
pushd $BOOST_DIR
./bootstrap.sh --without-icu --without-libraries=math,wave,graph,graph_parallel,mpi --prefix=$PREFIX
echo "<+<+< Done configuring $BOOST_VERSION"
mv ../project-config.jam .
echo ">+>+> Building $BOOST_VERSION"
./b2 -a -d2 -q -j ${BUILD_NUM_PROCESSES-2} --build-dir=$BOOST_BUILD_DIR --disable-icu toolset=gcc-vd link=static variant=debug threading=multi
echo "<+<+< Done building $BOOST_VERSION"
echo ">+>+> Removing previous installation (if any)"
rm -rf ${PREFIX}/include/boost
rm -rf ${PREFIX}/lib/libboost*
echo "<+<+< Done removing previous installation"
echo ">+>+> Installing $BOOST_VERSION"
./b2 -a -d2 -q -j ${BUILD_NUM_PROCESSES-2} --build-dir=$BOOST_BUILD_DIR --disable-icu toolset=gcc-vd link=static variant=debug threading=multi install
echo "<+<+< Done installing $BOOST_VERSION"
BUILD_SIZE=`du -sh`
echo "Build used $BUILD_SIZE disk space"
echo ">+>+>+ Cleaning up"
popd
rm -rf $BOOST_DIR $BOOST_BUILD_DIR project-config.jam
echo "<+<+< Done cleaning up"
set -eux
. ${VOLUMEDRIVER_BUILD_CONFIGURATION?"You need to set the path to the build configuration file"}
BOOST_VERSION=boost_1_57_0
BOOST_DIR=$BOOST_VERSION
BOOST_PACKAGE=$BOOST_VERSION.tar.bz2
BOOST_URL=http://downloads.sourceforge.net/project/boost/boost/1.57.0/$BOOST_PACKAGE
BOOST_BUILD_DIR=boost_build
. ../definitions.sh
. ../../helper-functions.sh
get_package_or_die $BOOST_PACKAGE $BOOST_URL
echo ">+>+> Cleaning up from previous build"
rm -rf $BOOST_DIR $BOOST_BUILD_DIR
echo "<+<+< Done cleaning up from previous build"
echo ">+>+> Unpacking $BOOST_PACKAGE"
tar -xjf $SOURCES_DIR/$BOOST_PACKAGE
echo "<+<+< Done unpacking $BOOST_PACKAGE"
echo ">+>+> Patching $BOOST_VERSION"
# patch -p0 < boost.patch0 # a more descriptive name would be nice
pushd $BOOST_DIR
patch -p1 < ../boost-make-valgrind-happy.patch
popd
echo "<+<+< Done patching $BOOST_VERSION"
# Add the correct flags for boost compilation .. another build system..lovely
BOOST_COMPILER_FLAGS=""
for i in ${CXX_COMPILER_FLAGS}
do
BOOST_COMPILER_FLAGS="$BOOST_COMPILER_FLAGS <cxxflags>$i"
done
# Specifying which boost to use can be done here by checking:
# http://www.boost.org/doc/libs/1_53_0/libs/python/doc/building.html
# and specifying the correct using python line beneath. For now we just
# support the system python and trust that that is the one the boost
# build system will find.
cat > project-config.jam <<EOF
# Boost.Build Configuration
# Automatically generated by bootstrap.sh
import option ;
import feature ;
# Compiler configuration. This definition will be used unless
# you already have defined some toolsets in your user-config.jam
# file.
# if ! gcc in [ feature.values <toolset> ]
{
using gcc : vd : $PREFIX/bin/vd-g++ : $BOOST_COMPILER_FLAGS ;
}
project : default-build <toolset>gcc ;
# Python configuration
using python : 2.7 : /usr ;
# List of --with-<library> and --without-<library>
# options. If left empty, all libraries will be built.
# Options specified on the command line completely
# override this variable.
libraries = --without-math --without-wave --without-graph --without-graph_parallel --without-mpi ;
# These settings are equivivalent to corresponding command-line
# options.
option.set prefix : $PREFIX ;
option.set exec-prefix : $PREFIX ;
option.set libdir : $PREFIX/lib ;
option.set includedir : $PREFIX/include ;
# Stop on first error
option.set keep-going : false ;
EOF
echo ">+>+> Configuring $BOOST_VERSION"
pushd $BOOST_DIR
./bootstrap.sh --without-icu --without-libraries=math,wave,graph,graph_parallel,mpi --prefix=$PREFIX
echo "<+<+< Done configuring $BOOST_VERSION"
mv ../project-config.jam .
echo ">+>+> Building $BOOST_VERSION"
./b2 -a -d2 -q -j ${BUILD_NUM_PROCESSES-2} --build-dir=$BOOST_BUILD_DIR --disable-icu toolset=gcc-vd link=static variant=debug threading=multi
echo "<+<+< Done building $BOOST_VERSION"
echo ">+>+> Removing previous installation (if any)"
rm -rf ${PREFIX}/include/boost
rm -rf ${PREFIX}/lib/libboost*
echo "<+<+< Done removing previous installation"
echo ">+>+> Installing $BOOST_VERSION"
./b2 -a -d2 -q -j ${BUILD_NUM_PROCESSES-2} --build-dir=$BOOST_BUILD_DIR --disable-icu toolset=gcc-vd link=static variant=debug threading=multi install
echo "<+<+< Done installing $BOOST_VERSION"
BUILD_SIZE=`du -sh`
echo "Build used $BUILD_SIZE disk space"
echo ">+>+>+ Cleaning up"
popd
rm -rf $BOOST_DIR $BOOST_BUILD_DIR project-config.jam
echo "<+<+< Done cleaning up"
The compiler flags we set are:
CXX_COMPILER_FLAGS=-std=gnu++14 -fPIC -g-ggdb3 -O0 -gdwarf-3
That seems to work.

Related

Duplicate symbols when linking libwebrtc.a on Android

Building WebRTC directly is somewhat painful (& rather time consuming so not ideal in paid for CI environments) so I've opted to use some excellent precompiled static libraries released on GitHub to speed things up. This has worked perfectly for all platforms I'm targetting (Windows, MacOS, iOS, Apple TVOS, linux...) except for Android.
When linking the binary on Android I encounter several duplicate symbol errors related to the std libary:
ld: error: duplicate symbol: std::logic_error::logic_error(char const*)
>>> defined at stdexcept_default.ipp:24 (../../../../../_source/android/webrtc/src/buildtools/third_party/libc++/trunk/src/support/runtime/stdexcept_default.ipp:24)
>>> stdexcept.o:(std::logic_error::logic_error(char const*)) in archive /root/webrtc/lib/armeabi-v7a/libwebrtc.a
>>> defined at stdexcept_default.ipp:24 (/buildbot/src/android/ndk-release-r23/toolchain/llvm-project/libcxx/src/support/runtime/stdexcept_default.ipp:24)
>>> stdexcept.o:(.text._ZNSt11logic_errorC2EPKc+0x1) in archive /app/android-sdk-linux/ndk/23.1.7779620/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_static.a
...
ld: error: duplicate symbol: std::runtime_error::runtime_error(char const*)
>>> defined at stdexcept_default.ipp:35 (../../../../../_source/android/webrtc/src/buildtools/third_party/libc++/trunk/src/support/runtime/stdexcept_default.ipp:35)
>>> stdexcept.o:(std::runtime_error::runtime_error(char const*)) in archive /root/webrtc/lib/armeabi-v7a/libwebrtc.a
>>> defined at stdexcept_default.ipp:35 (/buildbot/src/android/ndk-release-r23/toolchain/llvm-project/libcxx/src/support/runtime/stdexcept_default.ipp:35)
>>> stdexcept.o:(.text._ZNSt13runtime_errorC2EPKc+0x1) in archive /app/android-sdk-linux/ndk/23.1.7779620/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_static.a
It appears that libwebrtc.a for Android includes some libc++ object files and I'm not entirely sure how to successfully link with this library here.
This might be coming down to the libwebrtc.a being compiled with Google's own patched libc++ (Based on what I've read online I believe Google contributes patches to upstream libc++ but they don't wait for the patches to go in - rather they use their fully patched version of libc++ for building WebRTC, Chrome, etc).
When compiling for Linux I actually use the exact versions of clang & libc++ that were downloaded & used in building the static library & I suspect I might need to be doing something similar here - I'm just not entirely sure how given the need to use the Android CMake toolchain.
I've put together a minimal example project on GitHub with Dockerfile that can be used to easily reproduce the above issue.
Does anyone have an idea how I can successfully link the library on Android?
For completeness the source files of interest are:
CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(AndroidWebRTC)
set(CMAKE_CXX_STANDARD 17)
add_executable(AndroidWebRTC src/main.cpp)
target_link_libraries(AndroidWebRTC PRIVATE ${WEBRTC_LIBRARY})
add_compile_definitions(WEBRTC_POSIX WEBRTC_ANDROID WEBRTC_LINUX)
include_directories(
${WEBRTC_INCLUDE_DIR}
${WEBRTC_INCLUDE_DIR}/third_party/abseil-cpp
${WEBRTC_INCLUDE_DIR}/third_party/boringssl/src/include
${WEBRTC_INCLUDE_DIR}/third_party/libyuv/include
${WEBRTC_INCLUDE_DIR}/third_party/zlib
)
Dockerfile
# I explicitly specify an amd64 platform as I often build on Apple Silicon
# machines where the default of arm64 breaks things. I believe the alternative
# (and possibly better option) is to use NDK 24 and above, see:
# https://stackoverflow.com/a/69541958
FROM --platform=linux/amd64 ubuntu:20.04 AS build
ENV ANDROID_SDK_ROOT /app/android-sdk-linux
WORKDIR /app
# Install dependencies to build the project
# include apt-get --no-install-recommends
RUN apt-get update && \
apt-get -y upgrade && \
apt-get --no-install-recommends -y install tzdata && \
echo 'Europe/London' > /etc/timezone && \
dpkg-reconfigure -f noninteractive tzdata
RUN apt-get --no-install-recommends -y install git lsb-release python rsync \
emacs wget build-essential sudo pkg-config clang unzip openjdk-8-jdk ant \
android-sdk-platform-tools-common libncurses5 curl
RUN mkdir ${ANDROID_SDK_ROOT}
# ------------------------------------------------------
# --- Android SDK
RUN wget https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip && \
unzip commandlinetools-linux-7583922_latest.zip && \
mkdir ${ANDROID_SDK_ROOT}/cmdline-tools/ &&\
mv cmdline-tools ${ANDROID_SDK_ROOT}/cmdline-tools/latest && \
rm commandlinetools-linux-7583922_latest.zip
ENV PATH ${PATH}:${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin
RUN yes | sdkmanager --licenses
RUN touch /root/.android/repositories.cfg
# Platform tools
RUN yes | sdkmanager "platform-tools"
RUN yes | sdkmanager --update --channel=0
# Keep all sections in descending order!
RUN yes | sdkmanager \
"platforms;android-30" \
"build-tools;31.0.0" \
"ndk;23.1.7779620" \
"extras;android;m2repository" \
"extras;google;m2repository" \
"extras;google;google_play_services" \
"add-ons;addon-google_apis-google-24"
ENV ANDROID_HOME ${ANDROID_SDK_ROOT}
ENV ANDROID_NDK_HOME=${ANDROID_SDK_ROOT}/ndk/23.1.7779620
ENV PATH ${PATH}:${ANDROID_NDK_HOME}:${ANDROID_HOME}/build-tools/31.0.0/
# Get CMake
COPY scripts/get_cmake.sh scripts/get_cmake.sh
RUN ./scripts/get_cmake.sh "3.25.1" linux /root
ENV PATH "/root/cmake/bin:$PATH"
# Get WebRTC
COPY scripts/get_webrtc.sh scripts/get_webrtc.sh
RUN ./scripts/get_webrtc.sh 108.5359.5.0 android /root /root
## Copy resources
COPY src src
COPY CMakeLists.txt ./
RUN cmake -B build \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI=armeabi-v7a \
-DANDROID_NATIVE_API_LEVEL=16 \
-DBUILD_SHARED_LIBS=OFF \
-DWEBRTC_INCLUDE_DIR=/root/webrtc/include \
-DWEBRTC_LIBRARY=/root/webrtc/lib/armeabi-v7a/libwebrtc.a \
-DCMAKE_BUILD_TYPE=Release
RUN cmake --build build --config Release --parallel $(nproc) --target AndroidWebRTC
src/main.cpp
#include <iostream>
#include <api/create_peerconnection_factory.h>
int main() {
auto googleSessionDescription = webrtc::CreateSessionDescription(
webrtc::SdpType::kOffer, "sdp");
std::cout << "Hello, World!" << std::endl;
return 0;
}
scripts/get_webrtc.sh
#!/bin/bash
if [ $# -lt 4 ]; then
echo "$0 <webrtc_build_version> <package_name> <output_dir> <source_dir>"
exit 1
fi
WEBRTC_BUILD_VERSION=$1
PACKAGE_NAME=$2
OUTPUT_DIR=$3
SOURCE_DIR=$4
set -ex
if [ ! -e $SOURCE_DIR/webrtc.${PACKAGE_NAME}.${WEBRTC_BUILD_VERSION}.tar.gz ]; then
curl -Lo $SOURCE_DIR/webrtc.${PACKAGE_NAME}.${WEBRTC_BUILD_VERSION}.tar.gz https://github.com/shiguredo-webrtc-build/webrtc-build/releases/download/m${WEBRTC_BUILD_VERSION}/webrtc.${PACKAGE_NAME}.tar.gz
fi
pushd $OUTPUT_DIR
tar xf $SOURCE_DIR/webrtc.${PACKAGE_NAME}.${WEBRTC_BUILD_VERSION}.tar.gz
popd
scripts/get_cmake.sh
#!/bin/bash
# <platform> には Linux か Darwin を指定する
# <output_dir>/cmake に CMake が配置される
if [ $# -lt 3 ]; then
echo "$0 <cmake_version> <platform> <output_dir>"
exit 1
fi
CMAKE_VERSION=$1
PLATFORM=$2
OUTPUT_DIR=$3
set -ex
pushd $OUTPUT_DIR
curl -LO https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-${PLATFORM}-x86_64.tar.gz
tar xf cmake-${CMAKE_VERSION}-${PLATFORM}-x86_64.tar.gz
rm cmake-${CMAKE_VERSION}-${PLATFORM}-x86_64.tar.gz
rm -rf cmake
mv cmake-${CMAKE_VERSION}-${PLATFORM}-x86_64 cmake
popd

How to take user input at installation time.... during sudo dpkg -i <package_name>.deb?

My requirement is to install sample binaries as per user's yes/no to question
Do you want to install to sample binaries?
If user give input yes/y then mypackage.deb will install sample binaries to location otherwise won't.
I have created a config file, postinst file and template file but not able to achieve this yet during installation time. It is asking me "Do you want to install to sample binaries?" during deb package creation time.
following are the files.
I have googled some possible thing, some suggest to use debconf set selection but was not able to fit it in my requirement.
Any suggestion to achieve this??
"mypackage.config"
#!/bin/bash
# Source debconf library.
. /usr/share/debconf/confmodule
echo "My package repo path: $1"
echo "Creating My package dir"
mkdir my_package
cd my_package
echo "Copy debian control file"
mkdir DEBIAN
cp $1/debian/control DEBIAN/
cp $1/debian/mypackage.postinst DEBIAN/
cp $1/debian/mypackage.templates DEBIAN/
echo "Copy include files"
mkdir -p usr/include/local
cp $1/MyLib.h usr/include/local/
echo "Copy lib"
mkdir -p usr/local/lib
cp $1/build/src/mylib.so usr/local/lib/
mkdir usr/local/sample
cp $1/build/examples/sample_all usr/local/sample/
#Do you want to install sample binaries?
db_unregister mypackage/sample
db_input high mypackage/sample
# Check their answer.
db_get mypackage/sample
if [ "$RET" = "true" ];
then
echo "Copy Sample Binaries"
mkdir -p home/$USER/My_Package/examples/bin
mv usr/local/sample/sample_all home/$USER/My_Package/examples/bin/
sudo rm -rf /usr/local/sample
db_go
else
echo "Installing deb package without sample binaries"
sudo rm -rf /usr/local/sample
db_go
fi
echo "Create debian package"
cd $1/debian
dpkg-deb --build --root-owner-group mypackage
"my_package.templates"
Template: my_package/sample
Type: boolean
Description: Do you want to install sample binaries as well [true/false] ..?
"my_package.postinst"
#!/bin/sh
# Make sure this script fails if any unexpected errors happen
set -e
# Load debconf library
. /usr/share/debconf/confmodule
db_purge
"control"
Package: my_package
Version: 1.0
Section: custom
Priority: optional
Architecture: all
Pre-Depends: debconf
Essential: no
Installed-Size: 1024
Maintainer: package
Description: My package framework

How to print a ; symbol using CMake command?

I am building Boost as an ExternalProject under CMake. I want to cross compile for arm. To do this, I am trying to write using gcc : arm : arm-linux-gnueabi ; to user-config.jam before the build step.
However, it seems to refuse to print a ; symbol. I can only assume that this is due to some sort of mangling by CMake passing the command to the shell. I tried to edit project-config.jam inline using sed, but had the same result. Now I'm trying to echo the line to user-config.jam.
Here is my ExternalProject command in CMakeLists.txt:
ExternalProject_Add(Boost
URL https://downloads.sourceforge.net/project/boost/boost/1.59.0/boost_1_59_0.tar.gz
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/downloads/boost_1_59_0
BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/downloads/boost_1_59_0
UPDATE_COMMAND ""
PATCH_COMMAND ""
CONFIGURE_COMMAND ./bootstrap.sh --prefix="${CMAKE_BINARY_DIR}/boost_1_59_0" --without-icu
COMMAND echo using gcc : arm : arm-linux-gnueabi > ./user-config.jam
COMMAND echo ; >> ./user-config.jam
BUILD_COMMAND "./b2"
INSTALL_COMMAND ./b2 install toolset=gcc-arm --prefix=${CMAKE_CURRENT_SOURCE_DIR}/deps/boost
INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/boost
)
The verbose CMake prints:
cd /home/matthew/Desktop/arm/downloads/boost_1_59_0 && echo using gcc : arm : arm-linux-gnueabi > ./user-config.jam
cd /home/matthew/Desktop/arm/downloads/boost_1_59_0 && echo >> ./user-config.jam
You can see that it prints the using ... gnueabi line fine to user-config.jam. However, it seems to treat ; as an null character. It does the same thing when I use single and double quotes around the ; character as well.
The semicolon is the list delimiter for cmake. CMake 2.8.11 and greater have a special $ token:
COMMAND echo $<SEMICOLON> >> ./user-config.jam
As a side-note, you can make your cmake configuration more platform independent by using the cmake -E <command>:
COMMAND ${CMAKE_COMMAND} -E echo ...
It probably doesn't matter for echo, for other functionallity (creating/removing directories) it's something to keep in mind.

Travis CI: "Unable to locate package python-opencv" Python 2.7

On a normal non-virtualenv Ubuntu machine I can run:
sudo apt-get install python-opencv
And then from Python 2.7 I can run import cv2. Success!
But when I try to do the very same thing in my .travis.yml file for automated testing, I get the error:
E: Unable to locate package python-opencv
How can I get apt-get to locate python-opencv in my Travis-CI build?
I've tried the following; all were unsuccessful:
From https://askubuntu.com/questions/339217/, I tried appending these lines to /etc/apt/sources.list:
echo "deb http://de.archive.ubuntu.com/ubuntu precise main restricted universe" | sudo tee -a /etc/apt/sources.list
echo "deb-src http://de.archive.ubuntu.com/ubuntu precise restricted main multiverse universe" | sudo tee -a /etc/apt/sources.list
echo "deb http://de.archive.ubuntu.com/ubuntu precise-updates main restricted universe" | sudo tee -a /etc/apt/sources.list
echo "deb-src http://de.archive.ubuntu.com/ubuntu precise-updates restricted main multiverse universe" | sudo tee -a /etc/apt/sources.list
From here I tried adding these lines right before:
sudo apt-get install python-software-properties
sudo add-apt-repository python-opencv
Following this, with updated method from here, I tried using this instead of 2.7:
python:
- "2.7_with_system_site_packages"
(My full .travis.yml file is here.)
Update
Burhan Khalid's answer did get OpenCV installed, so the error went away. However, then when I tried find the package using import cv2 it still couldn't find it, because the Travis-CI build machine is wrapped in a virtualenv. So we can't access packages outside of our hermetically-sealed build environment.
So I build from source. (References: here, here and here)
Here's how to do it in the .travis.yml file:
env:
global:
# Dependencies
- DEPS_DIR="`readlink -f $TRAVIS_BUILD_DIR/..`"
- OPENCV_BUILD_DIR=$DEPS_DIR/opencv/build
And then, in the before_install section:
- travis_retry git clone --depth 1 https://github.com/Itseez/opencv.git $DEPS_DIR/opencv
- mkdir $OPENCV_BUILD_DIR && cd $OPENCV_BUILD_DIR
- |
if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then
cmake -DBUILD_TIFF=ON -DBUILD_opencv_java=OFF -DWITH_CUDA=OFF -DENABLE_AVX=ON -DWITH_OPENGL=ON -DWITH_OPENCL=ON -DWITH_IPP=ON -DWITH_TBB=ON -DWITH_EIGEN=ON -DWITH_V4L=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=$(python -c "import sys; print(sys.prefix)") -DPYTHON_EXECUTABLE=$(which python) -DPYTHON_INCLUDE_DIR=$(python -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") -DPYTHON_PACKAGES_PATH=$(python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") ..
else
cmake -DBUILD_TIFF=ON -DBUILD_opencv_java=OFF -DWITH_CUDA=OFF -DENABLE_AVX=ON -DWITH_OPENGL=ON -DWITH_OPENCL=ON -DWITH_IPP=ON -DWITH_TBB=ON -DWITH_EIGEN=ON -DWITH_V4L=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=$(python3 -c "import sys; print(sys.prefix)") -DPYTHON_EXECUTABLE=$(which python3) -DPYTHON_INCLUDE_DIR=$(python3 -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())") -DPYTHON_PACKAGES_PATH=$(python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") ..
fi
- make -j4
- sudo make install
- echo "/usr/local/lib" | sudo tee -a /etc/ld.so.conf.d/opencv.conf
- sudo ldconfig
- echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig" | sudo tee -a /etc/bash.bashrc
- echo "export PKG_CONFIG_PATH" | sudo tee -a /etc/bash.bashrc
- export PYTHONPATH=$OPENCV_BUILD_DIR/lib/python3.3/site-packages:$PYTHONPATH
After:
sudo add-apt-repository python-opencv
You need
sudo apt-get update
So that the new repository information is correctly updated; before you can add packages from that repository.

Unknown package libcxx and libcxxabi when building Clang?

I'm trying to build Clang with libc++ from sources. And I'm trying to drop libc++ in-tree while building it out-of-tree with the other components. The recipe I use is below.
If I simply place libcxx and libcxxabi in-tree, then configure does not pick them up, and they are not built automatically. I placed them in llvm/projects per LLVM's libc++ Standard Library.
Additionally, adding make cxx to the recipe does not work as advertised on the LLVM's libc++ Standard Library page. It results in:
llvm[0]: Constructing LLVMBuild project information.
make: *** No rule to make target `cxx'. Stop.
When I configure LLVM/Clang with --with-libcxx and --with-libcxxabi:
# Issued from a scratch 'build' directory, which is next to the 'llvm' directory.
../llvm/configure --enable-optimized --enable-cxx11 --with-libcxx --with-libcxxabi \
$OTHER_OPTIONS --prefix=/usr/local
then I receive the following:
configure: WARNING: Unknown project (libcxx) won't be configured automatically
configure: WARNING: Unknown project (libcxxabi) won't be configured automatically
libcxx and libcxxabi are literally what LLVM calls them, so I'm not sure what names to use if they are not correct.
I tried to examine configure for what the package names should be, but its not very helpful. See below for the logic.
How do I configure and build Clang with libc++ (when libc++ and libc++ ABI are in-tree)?
Configure logic for --with-XXX is shown below.
this is all I can find (its not very helpful):
-with-* | --with-*)
ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
{ echo "$as_me: error: invalid package name: $ac_package" >&2
{ (exit 1); exit 1; }; }
ac_package=`echo $ac_package| sed 's/-/_/g'`
eval with_$ac_package=\$ac_optarg ;;
Related links:
LLVM/Clang download page
LLVM's libc++ Standard Library page
And this Stack Overflow question is related: When is libc++ sources needed when building Clang from sources?
And this discussion of CFE-Dev mailing list: Questions about libc++ for linux and its git repository (if any). The thread says unpacking libcxx into llcm/projects ensures the headers are copied where Clang expects them during make install. But it does not address the --with-XXX question, it does not discuss why libc++ was not built, and it does not discuss how to get make install to actually install the libraries.
Recipe to fetch and build Clang. It works fine when not including libcxx and libcxxabi.
#! /bin/sh
# Clang 3.5 recipe.
# The script should be run from a scratch directory.
# Fetch
if [ ! -e llvm-3.5.0.src.tar.xz ]; then
wget http://llvm.org/releases/3.5.0/llvm-3.5.0.src.tar.xz
fi
if [ ! -e cfe-3.5.0.src.tar.xz ]; then
wget http://llvm.org/releases/3.5.0/cfe-3.5.0.src.tar.xz
fi
if [ ! -e compiler-rt-3.5.0.src.tar.xz ]; then
wget http://llvm.org/releases/3.5.0/compiler-rt-3.5.0.src.tar.xz
fi
if [ ! -e libcxx-3.5.0.src.tar.xz ]; then
wget http://llvm.org/releases/3.5.0/libcxx-3.5.0.src.tar.xz
fi
if [ ! -e libcxxabi-3.5.0.src.tar.xz ]; then
wget http://llvm.org/releases/3.5.0/libcxxabi-3.5.0.src.tar.xz
fi
if [ ! -e clang-tools-extra-3.5.0.src.tar.xz ]; then
wget http://llvm.org/releases/3.5.0/clang-tools-extra-3.5.0.src.tar.xz
fi
# Cleanup
echo "Cleaning up artifacts"
rm -rf llvm build llvm-3.5.0.src
# LLVM
echo "Unpacking LLVM"
tar xf llvm-3.5.0.src.tar.xz
mv llvm-3.5.0.src/ llvm
# Clang Front End
echo "Unpacking Clang Front End"
cd llvm/tools
tar xf ../../cfe-3.5.0.src.tar.xz
mv cfe-3.5.0.src clang
cd ../../
# Compiler RT
echo "Unpacking Compiler RT"
cd llvm/projects
tar xf ../../compiler-rt-3.5.0.src.tar.xz
mv compiler-rt-3.5.0.src/ compiler-rt
cd ../../
# Extra Tools
echo "Unpacking Extra Tools"
cd llvm/tools/clang/tools/
tar xf ../../../../clang-tools-extra-3.5.0.src.tar.xz
mv clang-tools-extra-3.5.0.src extra
cd ../../../../
# libc++
echo "Unpacking libc++"
cd llvm/projects
tar xf ../../libcxx-3.5.0.src.tar.xz
mv libcxx-3.5.0.src/ libcxx
cd ../../
# libc++ ABI
echo "Unpacking libc++ ABI"
cd llvm/projects
tar xf ../../libcxxabi-3.5.0.src.tar.xz
mv libcxxabi-3.5.0.src/ libcxxabi
cd ../../
# Determine if Apple
IS_DARWIN=`uname -s | egrep -i -c "Darwin"`
if [ $IS_DARWIN -ne 0 ]; then
OTHER_OPTIONS=" --enable-libcpp"
fi
# Configure
echo "Configuring build"
mkdir -p build
cd build
../llvm/configure --enable-optimized --enable-cxx11 --with-libcxx --with-libcxxabi $OTHER_OPTIONS --prefix=/usr/local
# Build
# 'make cxx' for libc++ is from http://libcxx.llvm.org/
echo "Running make"
make cxx
make -j2
RET=$?
if [ $RET -eq 0 ];then
echo "****************************************"
read -p "Press [ENTER] to install, or [CTRL]+C to quit"
sudo make install
fi
# ****************************************
# ****************************************
# Install does not install scan-build and scan-view
# Perform the copy, and/or put them on-path
#sudo cp llvm/projects/compiler-rt/lib/asan/scripts/asan_symbolize.py /usr/local/bin
#sudo 2to3 -w /usr/local/bin/asan_symbolize.py
#sudo mkdir /usr/local/bin/scan-build
#sudo cp -r llvm/tools/clang/tools/scan-build /usr/local/bin
#sudo mkdir /usr/local/bin/scan-view
#sudo cp -r llvm/tools/clang/tools/scan-view /usr/local/bin
This is script which I used to build libcxxabi and libcxx. It use previously built Clang (with GCC (4.8.3 in my case) and GCC STL):
if ( $#argv != 2 ) then
echo "Usage: [32|64] <directory>"
exit
endif
set echo on
set CMake=<CMake executable>
set GCCDir=<recent GCC directory>
set LLVMSourceDir=${PWD}/llvm-${LLVM_VERSION}.src
set LLVMOutOfTreeSourceDir=${PWD}
set LLVMPass1Dir=${PWD}/pass1
set PythonDir=<Python directory>
set InstallDir=${PWD}/$argv[2]
if ( $argv[1] == 32 ) then
set GCC_EHDir=${GCCDir}/lib/gcc/x86_64-redhat-linux/4.8.3/32
set BuildMode="-m32"
set LibDirSuffix=""
else
set GCC_EHDir=${GCCDir}/lib/gcc/x86_64-redhat-linux/4.8.3
set BuildMode="-m64"
set LibDirSuffix="64"
endif
set BuildDir=libcxxabi.build
if ( -d ${BuildDir} ) then
rm -rf ${BuildDir}
endif
mkdir ${BuildDir}
cd ${BuildDir}
${CMake} \
-DCMAKE_BUILD_TYPE="Release" \
-DCMAKE_INSTALL_PREFIX:PATH=${InstallDir} \
-DCMAKE_C_COMPILER=${LLVMPass1Dir}/bin/clang \
-DCMAKE_C_FLAGS=${BuildMode} \
-DCMAKE_CXX_COMPILER=${LLVMPass1Dir}/bin/clang++ \
-DCMAKE_CXX_FLAGS=${BuildMode} \
-DCMAKE_SHARED_LINKER_FLAGS="-L ${GCC_EHDir}" \
-DCMAKE_STATIC_LINKER_FLAGS="${GCC_EHDir}/libgcc_eh.a" \
-DLLVM_FORCE_USE_OLD_TOOLCHAIN=YES \
-DLLVM_PATH=${LLVMSourceDir} \
-DLIBCXXABI_LIBCXX_INCLUDES=${LLVMOutOfTreeSourceDir}/libcxx-${LLVM_VERSION}.src/include \
-DLIBCXXABI_LIBCXX_PATH=${LLVMOutOfTreeSourceDir}/libcxx-${LLVM_VERSION}.src \
-DLIBCXXABI_LIBDIR_SUFFIX=${LibDirSuffix} \
${LLVMOutOfTreeSourceDir}/libcxxabi-${LLVM_VERSION}.src
make
make install
cd ..
set BuildDir=libcxx.build
if ( -d ${BuildDir} ) then
rm -rf ${BuildDir}
endif
mkdir ${BuildDir}
cd ${BuildDir}
${CMake} \
-DCMAKE_BUILD_TYPE="Release" \
-DCMAKE_INSTALL_PREFIX:PATH=${InstallDir} \
-DCMAKE_C_COMPILER=${LLVMPass1Dir}/bin/clang \
-DCMAKE_C_FLAGS=${BuildMode} \
-DCMAKE_CXX_COMPILER=${LLVMPass1Dir}/bin/clang++ \
-DCMAKE_CXX_FLAGS=${BuildMode} \
-DCMAKE_SHARED_LINKER_FLAGS="-L ${GCCDir}/lib${LibDirSuffix}" \
-DLLVM_PATH=${LLVMSourceDir} \
-DLIBCXX_CXX_ABI=libcxxabi \
-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${LLVMOutOfTreeSourceDir}/libcxxabi-${LLVM_VERSION}.src/include \
-DLIBCXX_CXX_ABI_LIBRARY_PATH=${InstallDir}/lib \
-DLIBCXX_LIBDIR_SUFFIX=${LibDirSuffix} \
-DLIT_EXECUTABLE=${LLVMSourceDir}/utils/lit/lit.py \
${LLVMOutOfTreeSourceDir}/libcxx-${LLVM_VERSION}.src
make
make install
cd ..
libc++ and libc++abi aren't maintained to work with configure. I think libc++ might work if you invoke it correctly, but there isn't even a configure script for libc++abi.
See our docs for using cmake with these projects:
# In-tree build:
# Check out libcxx and libcxxabi into llvm/projects
cd llvm
mkdir build && cd build
cmake .. # Linux may require -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
make cxx