CMake install can't find library and points to wrong compiler version - linux

linux noob here- will appreciate any kind of help.
Some background:
I'm trying to build a program from source on RHEL 6.5, the dependencies for this program are specifically:
GCC 4.7 and above (for C++ 11 support)
CMake 2.8.9+
we already had GCC 4.4.7 installed in /usr/libexec/gcc, so our linux person built and installed the new version in /usr/local/libexec/gcc (version 4.9)
We didn't have CMake so I installed in from scratch by unizipping the source in /usr/local and following the directions from here:
http://www.cmake.org/install/
./bootstrap
make
make install
so far so good and in the CMakeOutput.log of the CMake it is correctly pointing to the new GCC's path, [COMPILER PATH=/usr/local/libexec/gcc/.../4.9.2/
and I did have to copy a .so file from /usr/lib64 to /usr/local/lib64 in order to successfully bootstrap/make it but I don't think that's the source of my problem.
The Problem:
Now here's what i'm having trouble with: so when I finally try to build this program using "cmake ."
I get the following issues:
-- The C compiler identification is GNU 4.4.7
-- Performing Test COMPILER_SUPPORTS_CXX11 - Failed
The compiler identification should be version 4.9 and the Test should've succeeded but it did not...
-- Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR)
-- Could NOT find PNG (missing: PNG_LIBRARY PNG_PNG INCLUDE_ DIR)
Cmake has the FindPNG cmake module file in /usr/local/cmake-3.0.2/Modules but it doesn't seem to know where it is, I tried copying just the FindPNG.cmake file into the local cmake directory of the program and I just kept getting missing module files one after another...
Now- I think all these errors could just be a result of something not pointing to something correctly, maybe not setting environment variables for something, missing or wrong CMake commands / variables in the CMakeList file or whatever but I have spent a quite amount of time trying to fix it trying different approaches but just couldn't figure it out...any help will be greatly appreciated!!!
Here's the top level CMakeLists.txt of the program I'm trying to build:
cmake_minimum_required(VERSION 2.8)
project(COLLADA2GLTF)
if (NOT WIN32)
#http://www.guyrutenberg.com/2014/01/05/enabling-c11-c0x-in-cmake/
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
message("-- C++11 Enabled")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
message("-- C++0x Enabled")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
endif()
set(USE_OPEN3DGC "ON")
set(WITH_IN_SOURCE_BUILD "ON")
set(COLLADA2GLTF_BINARY_DIR, COLLADA2GLTF_SOURCE_DIR)
set(BUILD_SHARED_LIBS "OFF")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(GetGitRevisionDescription)
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/GitSHA1.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp" #ONLY)
set(TARGET_LIBS GeneratedSaxParser_static OpenCOLLADABaseUtils_static UTF_static ftoa_static MathMLSolver_static OpenCOLLADASaxFrameworkLoader_static OpenCOLLADAFramework_static buffer_static)
if (NOT WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES .so .a .dylib)
endif()
# Lets libxml2 work in a shared library
add_definitions(-DLIBXML_STATIC_FOR_DLL)
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
ADD_DEFINITIONS(-fPIC)
ENDIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
include_directories(${COLLADA2GLTF_SOURCE_DIR})
.......
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/OpenCOLLADA/COLLADABaseUtils/include)
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/OpenCOLLADA/COLLADASaxFrameworkLoader/include)
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/OpenCOLLADA/GeneratedSaxParser/include)
if (WIN32)
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/misc)
endif()
if (USE_OPEN3DGC)
add_definitions( -DUSE_OPEN3DGC )
include_directories(${COLLADA2GLTF_SOURCE_DIR}/extensions/o3dgc-compression)
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/o3dgc/src)
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/o3dgc/src/o3dgc_common_lib/inc)
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/o3dgc/src/o3dgc_encode_lib/inc)
include_directories(${COLLADA2GLTF_SOURCE_DIR}/dependencies/o3dgc/src/o3dgc_decode_lib/inc)
endif()
find_package(PNG)
if (PNG_FOUND)
include_directories(${PNG_INCLUDE_DIR})
include_directories(${ZLIB_INCLUDE_DIR})
add_definitions(-DUSE_LIBPNG)
else()
message(WARNING "libpng or one of its dependencies couldn't be found. Transparency may not be correctly detected.")
endif()
link_directories(${COLLADA2GLTF_BINARY_DIR}/lib)
if (WIN32)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-DWIN32)
add_definitions(-EHsc)
endif()
add_subdirectory(dependencies/OpenCOLLADA)
if (USE_OPEN3DGC)
add_subdirectory(dependencies/o3dgc/src)
endif()
set(GLTF_SOURCES
COLLADA2GLTFWriter.h
COLLADA2GLTFWriter.cpp
......
assetModifiers/GLTFFlipUVModifier.cpp
${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp
GitSHA1.h)
if (USE_OPEN3DGC)
LIST(APPEND GLTF_SOURCES
extensions/o3dgc-compression/GLTF-Open3DGC.cpp
extensions/o3dgc-compression/GLTF-Open3DGC.h)
endif()
option(CONVERT_SHARED "CONVERT_SHARED" OFF)
if (CONVERT_SHARED)
add_library(collada2gltfConvert SHARED ${GLTF_SOURCES})
#Make sure the dll is in the same directory as the executable
if (WIN32)
set_target_properties(collada2gltfConvert PROPERTIES RUNTIME_OUTPUT_DIRECTORY "bin")
endif()
else()
add_library(collada2gltfConvert STATIC ${GLTF_SOURCES})
add_definitions(-DSTATIC_COLLADA2GLTF)
endif()
if (PNG_FOUND)
LIST(APPEND TARGET_LIBS ${PNG_LIBRARY} ${ZLIB_LIBRARY})
endif()
if (USE_OPEN3DGC)
LIST(APPEND TARGET_LIBS o3dgc_common_lib o3dgc_enc_lib o3dgc_dec_lib)
endif()
IF("${CMAKE_SYSTEM}" MATCHES "Linux")
LIST(APPEND TARGET_LIBS rt)
endif("${CMAKE_SYSTEM}" MATCHES "Linux")
target_link_libraries (collada2gltfConvert ${TARGET_LIBS})
set(GLTF_EXE_SOURCES main.cpp
${CMAKE_CURRENT_BINARY_DIR}/GitSHA1.cpp
GitSHA1.h)
if (WIN32)
LIST(APPEND GLTF_EXE_SOURCES ${COLLADA2GLTF_SOURCE_DIR}/dependencies/misc/getopt_long.c ${COLLADA2GLTF_SOURCE_DIR}/dependencies/misc/getopt.c ${COLLADA2GLTF_SOURCE_DIR}/dependencies/misc/getopt.h)
endif()
add_executable(collada2gltf ${GLTF_EXE_SOURCES})
target_link_libraries (collada2gltf collada2gltfConvert)

I guess that you're just facing the problem of unsatisfied dependencies. RHEL/CentOS 6 is pretty old distribution with an old kernel and applications; its recent releases are distributed with deprecated packages (like in your case) due to the needs of the backward compatibility. So is there any significant reason for you to use the one?
I spend one year in the project where we were developing software under RHEL 6.4 and I would suggest that you set yourself an impossible goal: you need to install to your OS not just a compiler, but also all of its libraries (for instance, actual C++ standard library .so etc.) and headers. Since these versions are not provided in you distro, you'll face difficulties due to the presence of same but differing libraries. Since all system software relies on to the old libraries, your manipulation can crash your system.
However, in case if you want to continue, you can try to install missing dependencies ZLIB and PNG with these commands (just a suggestion):
yum install zlib-devel libpng-devel
But definitly I would suggest you to save your time and deploy some fresh distro: CentOS 7 (if you want server) or Fedora 21 (will be released tommorow).

Related

CMake - Compile in Linux, Execute in Windows

I have a large codebase with Linux dependencies, and I would like to use CMake to compile my code into an executable that can be run on Windows, i.e. I want CMake to produce an ".exe" file or something of that nature.
I have tried using the solution provided on the CMake website: https://cmake.org/cmake/help/v3.4/manual/cmake-toolchains.7.html#cross-compiling
however it has not worked...
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(myProject VERSION 1.0 LANGUAGES C CXX)
set(CMAKE_CROSSCOMPILING true)
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 10.0)
set(CMAKE_SYSTEM_PROCESSOR arm)
find_package(... *all my required packages* REQUIRED)
include(... *required include files*)
add_executable(${PROJECT_NAME} ...)
target_link_libraries(${PROJECT_NAME} ...)
It compiles and will execute on Linux, however I want it to produce a Windows compatible executable.
You need a mingw-w64 toolchain in Linux to do this, for example on Arch Linux you can get all the necessary mingw-w64-... packages through AUR, including mingw-w64-cmake. These packets should get you going:
mingw-w64-binutils-symlinks
mingw-w64-gcc
mingw-w64-cmake
Install others to fulfill any dependencies of your software.
Then you can just run mingw-w64-cmake instead of cmake using your regular CMakeLists.txt. E.g.:
mkdir build-mingw; cd build-mingw
x86_64-w64-mingw32-cmake ../
make
However typically it is a good idea to use a static build so your executable will work standalone. Here is how I do it:
# STATIC stuff (Windows)
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(BUILD_FOR_WIN TRUE)
endif()
option(STATIC_BUILD "Build a static binary." ${BUILD_FOR_WIN})
if (STATIC_BUILD)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" CONFIG)
set(BUILD_SHARED_LIBS OFF)
endif()
Which creates a variable, STATIC_BUILD, that the user can set, and is defaulted to ON if compiling for Windows.
There is not much more you need to adapt in your CMake files. For example I need to include extra Qt platform plugins when building Qt:
if (STATIC_BUILD AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows")
# include plugins into static build on windows
# (we lack support for static on other platforms right now)
set(QT_PLUGINS SvgIcon WindowsIntegration WindowsVistaStyle)
endif()
The key takeaway here for you is first to get the proper environment on your system.

How to get standard library c++ using clang for cross compiling

First of all: I have read all similar posts and have been looking for over a Week. The Question is not repeated and I searched a lot.
Basically i m trying to compile a simple helloWorld c++ program with docker using clang as cross compiler for raspberry pi 3.
I am using VM Ubuntu 18.04
compiler clang 8
when i cross compile the code in docker using clang:
fatal error: 'bits/c++config.h' no such file or directory ...
here is CMakeLists.txt file
cmake_minimum_required(VERSION 3.7.2)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(triple arm-linux-gnueabihf)
set(CMAKE_C_COMPILER clang)
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_COMPILER_TARGET ${triple})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
set(DCMAKE_CROSSCOMPILING=True)
set(DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabihf)
set(DLLVM_TARGET_ARCH=ARM)
set(DLLVM_TARGETS_TO_BUILD=ARM)
#executing...
project (arm_cross)
add_executable(hello hello.cpp )
i expected after invoke make to get executable file for arm
I have never dealt with docker. But half a year ago, I also had an issue of cross compiling code for raspberry, under mac os though. Anyways, I used clang as a toolchain, and finally I have succeed.
Key point is to provide clang with good target rootfs. I just mounted real raspberry through sshfs.
Another thing is that I didn't put compiler settings into CMakeLists.txt but provided cmake with toolchain file.
My cmake toolchain file:
SET(CMAKE_SYSTEM_VERSION 1)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# Custom toolchain-specific definitions for your project
set(PLATFORM_ARM "1")
set(PLATFORM_COMPILE_DEFS "COMPILE_GLES")
# There we go!
# Below, we specify toolchain itself!
SET(TARGET_TRIPLE arm-linux-gnueabihf)
# Specify your target rootfs mount point on your compiler host machine
SET(TARGET_ROOTFS /Volumes/rootfs-${TARGET_TRIPLE})
# Specify clang paths
SET(LLVM_DIR /Users/stepan/projects/shared/toolchains/llvm-7.0.darwin-release-x86_64/install)
SET(CLANG ${LLVM_DIR}/bin/clang)
SET(CLANGXX ${LLVM_DIR}/bin/clang++)
# Specify compiler (which is clang)
SET(CMAKE_C_COMPILER ${CLANG})
SET(CMAKE_CXX_COMPILER ${CLANGXX})
# Specify binutils
SET (CMAKE_AR "${LLVM_DIR}/bin/llvm-ar" CACHE FILEPATH "Archiver")
SET (CMAKE_LINKER "${LLVM_DIR}/bin/llvm-ld" CACHE FILEPATH "Linker")
SET (CMAKE_NM "${LLVM_DIR}/bin/llvm-nm" CACHE FILEPATH "NM")
SET (CMAKE_OBJDUMP "${LLVM_DIR}/bin/llvm-objdump" CACHE FILEPATH "Objdump")
SET (CMAKE_RANLIB "${LLVM_DIR}/bin/llvm-ranlib" CACHE FILEPATH "ranlib")
# You may use legacy binutils though.
#SET(BINUTILS /usr/local/Cellar/arm-linux-gnueabihf-binutils/2.31.1)
#SET (CMAKE_AR "${BINUTILS}/bin/${TARGET_TRIPLE}-ar" CACHE FILEPATH "Archiver")
#SET (CMAKE_LINKER "${BINUTILS}/bin/${TARGET_TRIPLE}-ld" CACHE FILEPATH "Linker")
#SET (CMAKE_NM "${BINUTILS}/bin/${TARGET_TRIPLE}-nm" CACHE FILEPATH "NM")
#SET (CMAKE_OBJDUMP "${BINUTILS}/bin/${TARGET_TRIPLE}-objdump" CACHE FILEPATH "Objdump")
#SET (CMAKE_RANLIB "${BINUTILS}/bin/${TARGET_TRIPLE}-ranlib" CACHE FILEPATH "ranlib")
# Specify sysroot (almost same as rootfs)
SET(CMAKE_SYSROOT ${TARGET_ROOTFS})
SET(CMAKE_FIND_ROOT_PATH ${TARGET_ROOTFS})
# Specify lookup methods for cmake
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# Sometimes you also need this:
# set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Specify raspberry triple
set(CROSS_FLAGS "--target=${TARGET_TRIPLE}")
# Specify other raspberry related flags
set(RASP_FLAGS "-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS")
# Gather and distribute flags specified at prev steps.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CROSS_FLAGS} ${RASP_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CROSS_FLAGS} ${RASP_FLAGS}")
# Use clang linker. Why?
# Well, you may install custom arm-linux-gnueabihf binutils,
# but then, you also need to recompile clang, with customized triple;
# otherwise clang will try to use host 'ld' for linking,
# so... use clang linker.
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld)
My article with detailed description is here.
Hopefully it will help.
I also would separate this problem on two steps:
1. Get it compiled by clang.
2. Integrate compilation settings into docker.
Good luck!
Solution as follow what i did
Firstly backup /usr/include then move /usr/arm/include file to up. Finally run your 32 bit arm application.
This step can be automated by simple shell script.

How to idiomatically package dependencies for a QT application using CPack?

I have a simple QT project. I'm developing on Linux. But it's meant to be deployed to Linux, Mac and Windows ultimately.
I'm attempting to package it for distribution. I'm running into problems locating the dependencies and packaging them up and doing this in an idiomatic way (IOW: No hardcoded paths to DLLs or including the DLLs in my source repo)
For the Windows port, I'm using MinGW and compiling like this:
mingw64-cmake -G "Unix Makefiles" .. -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=/usr/share/mingw/toolchain-mingw64.cmake
make && ctest && make install && cpack -G "TGZ" && cpack -G "NSIS64"
I've set it to product a tar.gz file and an NSIS installer. There's no particular reason for NSIS and not Wix at the moment. This is just to figure things out.
It compiles a Windows executable, but it does not include the DLLs necessary to run the program. It's these:
Libgcc_s_seh-1.dll
Qt5Core.dll
Qt5Gui.dll
A quick find on my computer shows me that those DLLs are present here:
/usr/x86_64-w64-mingw32/sys-root/mingw/bin/Qt5Widgets.dll
/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgcc_s_seh-1.dll
...
Is there a way to automatically get CPack to dig up the DLLs and include them in the installer?
Here is my CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8.11)
project(myapp)
enable_testing()
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
find_package(Qt5Core REQUIRED)
find_package(Qt5Gui REQUIRED)
find_package(Qt5Widgets REQUIRED)
add_executable(myapp WIN32 main.cpp mainwindow.cpp resources.qrc)
target_link_libraries(myapp Qt5::Widgets)
target_link_libraries(myapp Qt5::Core)
target_link_libraries(myapp Qt5::Gui)
INSTALL(TARGETS myapp
BUNDLE DESTINATION .
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
INSTALL(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION bin COMPONENT Libraries)
IF(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
INSTALL(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION bin COMPONENT System)
ENDIF(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS)
INCLUDE(CPack)
I've looked around for some help on this. The best thing I came across was
this link
But it's not looking so idiomatic. If we look closer at the CMakeLists.txt file, it's got machine-specific hard coded paths that are certain to change in the future:
IF( WIN32 AND ${ARCH_32BIT})
SET(QT_INSTALLED_PATH "C:/QtMSVCX86/Qt5.5.0/5.5/msvc2013" )
ELSEIF(WIN32 AND ${ARCH_64BIT})
SET(QT_INSTALLED_PATH "C:/QtMSVCX64/Qt5.5.0/5.5/msvc2013_64" )
ELSEIF(UNIX AND NOT MINGW AND ${ARCH_32BIT})
SET(QT_INSTALLED_PATH "/opt/Qt5.5.0/5.5/gcc/" )
ELSEIF(UNIX AND NOT MINGW AND ${ARCH_64BIT})
SET(QT_INSTALLED_PATH "/opt/Qt5.5.0/5.5/gcc_64/" )
ENDIF()
SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
SET(CMAKE_AUTORCC ON)
FIND_PACKAGE(Qt5Widgets PATHS ${QT_INSTALLED_PATH} NO_DEFAULT_PATH)
FIND_PACKAGE(Qt5Qml PATHS ${QT_INSTALLED_PATH} NO_DEFAULT_PATH)
FIND_PACKAGE(Qt5Quick PATHS ${QT_INSTALLED_PATH} NO_DEFAULT_PATH)
Have a look at CMake's Bundle Utilities It contains a FIXUP_BUNDLE macro which collects all the necessary dependencies of an executable, including Qt. It works basically the same way on Windows, Linux and Mac. You could start by adding FIXUP_BUNDLE(myapp) to your CMake file. the actual dependency resolving and copying happens during the CPack run. Depending on project size and complexity, some tweaks are necessary, but in general I have seen it used successfully in larger cross-platform Qt projects with a CMake based build system

Cross compile stunnel

I am having difficulties with cross compiling stunnel for an ARM device.
Cross compiling OpenSSL was done via this CMake project: http://www.valvers.com/open-software/projects/openssl-cmake/ and it runs successfully on the target device.
The CMake toolchain file I use when compiling OpenSSL:
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_C_COMPILER /home/elias/toolchains/axotec/3.4.1/bin/arm-linux-gcc)
SET(CMAKE_CXX_COMPILER /home/elias/toolchains/axotec/3.4.1/bin/arm-linux-g++)
SET(CMAKE_FIND_ROOT_PATH /home/elias/toolchains/axotec/3.4.1/arm-linux /home/elias/toolchains/axotec/3.4.1/library-for-ramdisk )
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
My question is how do I cross compile stunnel in a similar fashion? I'm struggling with passing stunnel makefile the whole sysroot dir just like in the cmake toolchain file SET(CMAKE_FIND_ROOT_PATH /home/elias/toolchains/axotec/3.4.1/arm-linux /home/elias/toolchains/axotec/3.4.1/library-for-ramdisk )
My atempts include, after running the configure, rewriting the makefile CFLAGS with --sysroot= but where to put the second folder?(library-for-arm)
General idea:
The openssl-cmake project uses CMake build infrastructure. Hence just specifying the toolchain worked for you. I looked at stunnel source code and they use the traditional GNU Autotools for the build infrastructure which means you cannot use cmake directly on that project. (./configure && make && make install)
You would have to use ExternalProject_Add to compile stunnel using cmake.
Take a look at the following links for more information.
http://www.kitware.com/media/html/BuildingExternalProjectsWithCMake2.8.html
http://www.cmake.org/cmake/help/v3.2/module/ExternalProject.html
Also this:
Pass parameter with spaces to CMake ExternalProject_Add BUILD_COMMAND
CMakeLists.txt
cmake_minimum_required (VERSION 3.2)
include(ExternalProject)
set(CROSS_INFO CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} AR=${CMAKE_AR})
ExternalProject_Add(
stunnel
URL http://www.stunnel.org/downloads/stunnel-5.17.tar.gz
CONFIGURE_COMMAND <SOURCE_DIR>/configure --host=powerpc --with-sysroot=${CMAKE_FIND_ROOT_PATH} ${CROSS_INFO}
)
Additional info:
I tried to run the above project locally on my system and I ended up spending an hour debugging it with the powerpc toolchain file I have. There is some problem with the configure script of stunnel. The way sysroot and with-ssl dir are being calculated is kind of not correct. You might have to mess with the configure file to get the cross compile to work. But the general idea is specified above.

How to cross compile for linux x86 with linux amd64, cmake and g++?

+1 for each piece of information that helps to complete the whole picture. You don't need to know the whole answer. I'll appreciate individual pieces of the puzzle just as much. Thanks.
I am about to attempt my first cross-compilation. I have searched both SO and the web and found many pieces of information, but I don't always know how to put those pieces together because there are still some missing pieces.
My host: linux Kubuntu amd64.
Target: linux kubuntu x86 (32bit) (should be easy, no?)
Tools: g++ and cmake.
Here is the information I found:
How to compile a 32-bit binary on a 64-bit linux machine with gcc/cmake
mentions export CFLAGS=-m32. That's one piece.
Cross-platform: selecting data types to use 32/64 bit
mentions data types. I may have to pay attention to that within my code.
#ifdef for 32-bit platform
#ifdef for 32-bit platform
links to the following, although I am not too sure yet how to use it:
http://predef.sourceforge.net/prearch.html
http://ww.ubuntuforums.org/showthread.php?t=1377396
I did: sudo apt-get install g++-multilib
missing pieces:
Ideally, when I do 'make' (with cmake), it should spit out both a amd64 binary and a x86 one.
Part of my CMakeLists.txt looks like this:
add_definitions(-Wall -pthread)
add_executable (../run.amd64 user.cpp time.cpp init.cpp utils.cpp main.cpp)
target_link_libraries(../run.amd64 cppcms dbixx config++ ctemplate)
How do I introduce the flag -m32 to create a second executable?
Should I want to make only one executable (e.g. for testing and debugging), how do I tell cmake to make either one or both binaries?
Also, you can see that I use some third party libraries, some of which I had to compile myself. Does this mean that I need to compile each of those binaries for the target host as well? Some use cmake and some use: ./configure; make;
How would I do about compiling those libraries for the target host (flags to use, etc.)?
Note: the dynamically linked libraries are already compiled and installed on the target computer, so maybe I don't need to worry about this step... I am not sure: this is one of my missing pieces...
What I need is a kind of tutorial, or at least some of the missing pieces. I'll update this post with more details on what I achieved and how.
Thanks.
P.S.
Is it possible at all?
Searching more, I found this:
http://www.mail-archive.com/cmake#cmake.org/msg26265.html
"The original design doesn't seem to be designed for anything more than windows-linux or linux-windows cross compiles."
cmake is NOT tested for linux amd64 to linux x86.
http://www.cmake.org/Wiki/CMake_Cross_Compiling#FAQ.2FPotential_Problems
"On mixed 32/64 bit Linux installations cross compilation cannot be used to build for 32/64 bit only."
??
If you want to use a toolchain file there is an easier solution (IMHO) than what is proposed by #auledoom. You do not need to write the shell wrapper scripts at all, simply put this in the toolchain file:
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)
# Which compilers to use for C and C++
set(CMAKE_C_COMPILER gcc -m32)
set(CMAKE_CXX_COMPILER g++ -m32)
This will make it a "list variable" in cmake. This solution works for me. Benefit of the toolchain file is that you can there also define paths for 32bit libraries etc, which is usually different from standard paths.
This solution will allow you cross-compile your cmake project on a linux64 host targeting 32bits, on systems with multi-arch support.
It's uses a "fake" cmake toolchain so CMAKE somehow "believes" it's on 32bit system, so no additional modifications are needed inside your cmake project files, no special configurations, no special settings (well almost).
Install multilib support:
$sudo apt-get install gcc-multilib
Create a "fake" linux32 toolchain
First, we create a "fake" i686 compiler. Go where your CMakeLists.txt resides and create a bin directory. Open your preferred editor and create this simple bash script for gcc compiler.
#!/bin/sh
/usr/bin/gcc -m32 "$#"
As you see, it's just make a call to the system compiler adding the -m flag. Save this as i686-linux-gnu-gcc. Do the same for the g++ compiler
#!/bin/sh
/usr/bin/g++ -m32 "$#"
Save it as i686-linux-gnu-g++. Remember to set the executable flags on this scrips
Create also a symlink to the system ar binary in this form
$ln /usr/bin/ar i686-linux-gnu-ar
At last create the toolchain-linux32.cmake file
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)
# Which compilers to use for C and C++
set(CMAKE_C_COMPILER ${CMAKE_SOURCE_DIR}/bin/i686-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${CMAKE_SOURCE_DIR}/bin/i686-linux-gnu-g++)
and create the build directory and call cmake with the toolchain file as argument
$mkdir build && cd build
$cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain-linux32.cmake ..
and your done!!!!!
I'll write a more complete guide here, which covers some problems i have with libraries not multi-lib compliant
this is a simplified version of what I use, and it does create x86 binaries:
set( TargetName myExe )
set( SOURCES a.cpp b.cpp )
add_executable( ${TargetName} ${SOURCES} )
target_link_libraries( ${TargetName} m pthread stdc++ )
set_target_properties( ${TargetName} PROPERTIES COMPILE_FLAGS -m32 LINK_FLAGS -m32 )
furthermore you'll use add_definitions to set compiler flags like -W -Ox -Dxxx etc.
All the lines above are actually split in seperate cmake files, and to get one file to build a number of executables, I generate a master cmake file containing all different configurations I want to build:
project( myProject )
set( SOURCES a.cpp b.cpp )
if( ${ConfigurationType} strequal "Debugx86" )
include( debugopts.cmake )
include( x86.cmake )
include( executable.cmake )
...
elseif( ${ConfigurationType} strequal "Releasex64" )
include( debugopts.cmake )
include( x86.cmake )
include( executable.cmake )
...
etc
Then there's a driver shell script to build it all. It takes commandline options to set some extra options and select to build everything or just one configuration. Here's a piece of it:
if [ "$myConfig" = "all" -o "$myConfig" = "Debugx86" ]; then
mkdir -p project_Debugx86
cd project_Debugx86
cmkake "$sourceDir" "$cmakeOpts" -DConfigurationType="Debugx86"
make clean
make "$makeopts"
fi
if [ "$myConfig" = "all" -o "$myConfig" = "Releasex64" ]; then
mkdir -p project_Releasex64
cd project_Releasex64
cmkake "$sourceDir" "$cmakeOpts" -DConfigurationType="Releasex64
make clean
make "$makeopts"
fi
While this is not exactly what you ask for, it works flawlessly and does the same. (Not sure if it is possible in cmake to define any number of targets in cmake itself, and have them built all together by one file.) It just takes some time to write the generator for this files, but once that is done all I have to do is point the generator to a directory with sources, let ir run, then invoke the build script to make everything.
All you need is to add -m32 to CFLAGS and CXXFLAGS when running CMake. This can be done via environment variables:
$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .
or by setting corresponding CMake variables:
$ cmake -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 .
This can easily tested with a simple CMake project:
$ uname -m
x86_64
$ CFLAGS=-m32 CXXFLAGS=-m32 cmake .
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
....
$ make
Scanning dependencies of target foo
[100%] Building CXX object CMakeFiles/foo.dir/foo.cc.o
Linking CXX executable foo
[100%] Built target foo
$ file foo
foo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x5b1871446c92cbdcbf905583e16189f68f3bf5f2, not stripped
where CMakeLists.txt is a trivial CMake file:
project(TEST)
add_executable(foo foo.cc)
and foo.cc is as follows:
int main () {}
Here is the basic recipe I use all the time for cmake projects..
OPTION(FORCE32 "Force a 32bit compile on 64bit" OFF)
IF(FORCE32)
if(APPLE)
SET(CMAKE_OSX_ARCHITECTURES "i386")
else()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
endif()
ENDIF()
IF(APPLE)
set(BIN_LIBROOT "macosx")
ELSE()
if(CMAKE_SIZEOF_VOID_P MATCHES "8" AND NOT(FORCE32) )
set(BIN_LIBROOT "linux64")
set(CMAKE_EXECUTABLE_SUFFIX ".bin.x86_64")
set(BIN_RPATH "\$ORIGIN/lib64")
else()
set(BIN_LIBROOT "linux")
set(CMAKE_EXECUTABLE_SUFFIX ".bin.x86")
set(BIN_RPATH "\$ORIGIN/lib")
endif()
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH ${BIN_RPATH})
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
ENDIF()
Then every target automatically has the .bin.${arch} extension and I never have to think about this for any targets I add. the ${BIN_LIBROOT} is useful if you have a bunch of precompiled libraries as you as you can use that to dynamically search for libs in your private lib dirs based on the target platform/arch.

Resources