I am trying to build Trilinos on my OS X 10.11.6 laptop and keep encountering the following problem: CMake uses Apple's Clang instead of GCC
...
Probing the environment ...
-- USE_XSDK_DEFAULTS='FALSE'
-- CMAKE_BUILD_TYPE='RELEASE'
-- BUILD_SHARED_LIBS='FALSE'
-- CMAKE_C_COMPILER_ID='AppleClang'
-- CMAKE_C_COMPILER_VERSION='7.3.0.7030031'
-- CMAKE_CXX_COMPILER_ID='AppleClang'
-- CMAKE_CXX_COMPILER_VERSION='7.3.0.7030031'
...
Despite the fact that I passed gcc/g++ address as an argument in call:
cmake -D CMAKE_C_COMPILER=/usr/bin/gcc -D CMAKE_CXX_COMPILER=/usr/bin/g++ ..
I installed GCC and G++ separately:
$ gcc --version
gcc (GCC) 4.9.2 20141029 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
UPD If anybody's interested, I've given up and moved development to ubuntu. If you find a way to do this, please comment below
When compiler is set explicitely, CMake doesn't try to guess its identification (variables *_COMPILER_ID and *_COMPILER_VERSION.
If you want (and usually you do want) this identification to correctly reflect your compiler, you need to set these variables explicitely too.
For setup several variables describing building environment you may use toolchain files.
Related
I made a test CMakeLists.txt. I set system name and version before reading variables (although I didn't set the compiler):
cmake_minimum_required(VERSION 3.10)
project(test)
include_directories(.)
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 10.0.10240.0)
add_executable(test test.c)
target_link_libraries(test)
message("cmake system name = ${CMAKE_SYSTEM_NAME}")
message("cmake host name = ${CMAKE_HOST_SYSTEM_NAME}")
message("cmake system version = ${CMAKE_SYSTEM_VERSION}")
message("unix = ${UNIX}")
message("win32 = ${WIN32}")
Here is the output from "cmake ." on the terminal:
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
cmake system name = Windows
cmake host name = Linux
cmake system version = 10.0.10240.0
unix = 1
win32 =
-- Configuring done
-- Generating done
-- Build files have been written to: /home/francisco/Documents
The CMake documentation says UNIX and WIN32 are set to the target OS. Here I set the target OS and yet they remain set to the host OS. Why?
You're not supposed to write CMAKE_SYSTEM_NAME after the first project() command is encountered by CMake. At the first project command the choices of compiler and target system are made and you cannot change the effects of this later. As you have seen you can overwrite the value of CMAKE_SYSTEM_NAME, but the only effect of doing this are that you and any external cmake logic that may be invoked (e.g. scripts executed when using find_package) see a value that is wrong (i.e. not matching the choice of compiler).
For setting this kind of information your CMakeLists.txt files are the wrong place. This kind of info belongs into a toolchain file alongside your choice of compiler that actually produces binaries for the target platform:
toolchain-windows.cmake
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 10.0.10240.0)
set(CMAKE_C_COMPILER <command/absolute path to executable to use as C compiler goes here>)
set(CMAKE_CXX_COMPILER <command/absolute path to executable to use as C++ compiler goes here>)
...
Configure the project using something like
cmake --toolchain path/to/toolchain-windows.cmake -S path/to/source -B path/to/build/dir
Note: The default compiler on your linux almost certainly won't be able cross compile for windows targets.
I have a very large project that I'm trying to migrate from GNU make to cmake. As such, I think having intermediary files containing various variables is a good way to go.
Since I'm just starting out, this is what I have for top_directory/vars/CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
set(VARIABLE "value")
This way, in another folder, I can add this line to that CMakeLists.txt:
add_subdirectory(top_directory/vars)
However, when trying to run cmake on top_directory/vars/CMakeLists.txt, I receive the following error:
me#host:/tmp>cmake .
-- The C compiler identification is unknown
-- The CXX compiler identification is GNU 7.3.1
-- Check for working C compiler: /usr/bin/g++
-- Check for working C compiler: /usr/bin/g++ -- broken
CMake Error at /usr/share/cmake/Modules/CMakeTestCCompiler.cmake:52 (message):
The C compiler
"/usr/bin/g++"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: /tmp/CMakeFiles/CMakeTmp
Run Build Command:"/usr/bin/gmake" "cmTC_607e9/fast"
/usr/bin/gmake -f CMakeFiles/cmTC_607e9.dir/build.make CMakeFiles/cmTC_607e9.dir/build
gmake[1]: Entering directory '/tmp/CMakeFiles/CMakeTmp'
Building C object CMakeFiles/cmTC_607e9.dir/testCCompiler.c.o
/usr/bin/g++ -o CMakeFiles/cmTC_607e9.dir/testCCompiler.c.o -c /tmp/CMakeFiles/CMakeTmp/testCCompiler.c
/tmp/CMakeFiles/CMakeTmp/testCCompiler.c:2:3: error: #error "The CMAKE_C_COMPILER is set to a C++ compiler"
# error "The CMAKE_C_COMPILER is set to a C++ compiler"
^~~~~
gmake[1]: *** [CMakeFiles/cmTC_607e9.dir/build.make:66: CMakeFiles/cmTC_607e9.dir/testCCompiler.c.o] Error 1
gmake[1]: Leaving directory '/tmp/CMakeFiles/CMakeTmp'
gmake: *** [Makefile:126: cmTC_607e9/fast] Error 2
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt
-- Configuring incomplete, errors occurred!
See also "/tmp/CMakeFiles/CMakeOutput.log".
See also "/tmp/CMakeFiles/CMakeError.log".
Now I can force it by adding -DCMAKE_C_COMPILER=gcc, but that really defeats the portability aspect.
So my question is: is this the right way to be making "variable" CMake files and why does CMake incorrectly detect my C compiler?
Helpful Information:
cmake --version
cmake version 3.11.1
CMake suite maintained and supported by Kitware (kitware.com/cmake).
gcc --version
gcc (SUSE Linux) 7.3.1 20180323 [gcc-7-branch revision 258812]
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
If there is any additional information I can provide, then please let me know.
I am having trouble cross-compiling a library for my arm board using autconf.
I am using this line:
./configure --target=arm-linux --host=arm-linux --prefix=/bla/bla/bla/linux_arm_tool CFLAGS='-m32'
make
make install
When I do file to check it I get:
libjpeg.so.8.4.0: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
That doesn't seem right at all, but I tried using it anyway... and I get:
/usr/lib/gcc/arm-linux-gnueabi/4.5.3/../../../../arm-linux-gnueabi/bin/ld: skipping incompatible /bla/bla/bla/bla/../linux_arm_tool/lib/libjpeg.so when searching for -ljpeg
I'm at a loss, I've been googling for an hour now...
So I knew I've cross compiled before using really basic method calls and I figured out why I've gotten away with this before after examining the output:
checking for arm-linux-gnueabi-gcc... no
checking for gcc... gcc
...
...
checking for arm-linux-gnueabi-gcc... gcc
In my /usr/bin there was no arm-linux-gnueabi-gcc, I had to:
ln -s /usr/bin/arm-linux-gnueabi-gcc-4.5 /usr/bin/arm-linux-gnueabi-gcc
I successfully cross-compiled using:
./configure --host=arm-linux-gnueabi -prefix=${CSTOOL_DIR}/linux_arm_tool
as for linking ... I still have to check some things, but I am going to assume I might need to throw some -rpath-link flags in more advanced compiles.
I think the problem could be restated more generally as: "How do I use Autoconf to cross compile for ARM?"
According to ./configure -h:
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
The official GNU documentation is helpful for answering this question:
http://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Hosts-and-Cross_002dCompilation.html
Note when they defining the usage of --host and and --build:
Therefore, whenever you specify --host, be sure to specify --build too.
And here is an example that I just used to configure iperf for my embedded ARM platform:
First of all the "./configure" script is actually called "Autoconf" which really helps for google-ing.
The idea here is to:
Have your cross compilers in your current $PATH
Set the CC and CXX environment variables to point to the cross compilers
Give the right --host and --build
buildpath <--- my little script to setup my $PATH
export CC=arm_v5t_le-gcc
export CXX=arm_v5t_le-g++
./configure --host=armv5tl-montavista-linux-gnueabi --build=x86_64-linux-gnu
You need to override the environment variables CC, LD, and other pertinent ones. Setting those switches doesn't tell configure where your cross tool chain is (it could be anywhere)
Check out some guides for various projects, for instance:
http://wiki.wxwidgets.org/Cross-Compiling_Under_Linux
Also, here is a script I made to setup cross compile for node.js - same idea:
https://gist.github.com/edhemphill/5094239
The libjpeg is not going to work b/c it's a x86 binary, you need it to say:
ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, not stripped
or similar.
This is the reason you are getting a skipping incompatible
# Install arm-linux-gnueabi packages
apt-get install libc6-armel-cross libc6-dev-armel-cross \
binutils-arm-linux-gnueabi arm-linux-gnueabi-gcc libncurses5-dev
./configure --target=arm-linux-gnueabi --host=arm-linux-gnueabi
...
checking for arm-linux-gnueabi-gcc... arm-linux-gnueabi-gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... yes
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether arm-linux-gnueabi-gcc accepts -g... yes
checking for arm-linux-gnueabi-gcc option to accept ISO C89... none needed
checking whether arm-linux-gnueabi-gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of arm-linux-gnueabi-gcc... gcc3
...
make
arm-linux-gnueabi-gcc -DPACKAGE_NAME=\"Tutorial\ Program\" -DPACKAGE_TARNAME=\"tutorial-program\" -DPACKAGE_VERSION=\"1.0\" -DPACKAGE_STRING=\"Tutorial\ Program\ 1.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"tutorial-program\" -DVERSION=\"1.0\" -I. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
I have two gcc compilers installed on my system, one is gcc 4.1.2 (default) and the other is gcc 4.4.4. How can I check the libc version used by gcc 4.4.4, because /lib/libc.so.6 shows the glibc used by gcc 4.1.2, since it is the default compiler.
even easier
use ldd --version
This should return the glibc version being used i.e.
$ ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
...
which is the same result as running my libc library
$ /lib/libc.so.6
GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
...
Write a test program (name it for example glibc-version.c):
#include <stdio.h>
#include <stdlib.h>
#include <gnu/libc-version.h>
int main(int argc, char *argv[]) {
printf("GNU libc version: %s\n", gnu_get_libc_version());
exit(EXIT_SUCCESS);
}
and compile it with the gcc-4.4 compiler:
gcc-4.4 glibc-version.c -o glibc-version
When you execute ./glibc-version the used glibc version is shown.
Use -print-file-name gcc option:
$ gcc -print-file-name=libc.so
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
That gives the path. Let's examine the file:
$ file $(gcc -print-file-name=libc.so)
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so: ASCII text
$ cat $(gcc -print-file-name=libc.so)
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) )
The file is a linker script, which links the libraries in GROUP list.
On ELF platforms /lib/x86_64-linux-gnu/libc.so.6 is a position-independent executable with a dynamic symbol table (like that of a shared library):
$ file /lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc.so.6: symbolic link to libc-2.31.so
$ file $(readlink -f /lib/x86_64-linux-gnu/libc.so.6)
/usr/lib/x86_64-linux-gnu/libc-2.31.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=1878e6b475720c7c51969e69ab2d276fae6d1dee, for GNU/Linux 3.2.0, stripped
$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.9) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 9.4.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
gnu_get_libc_version identifies the runtime version of the GNU C Library.
If what you care about is the compile-time version (that is, the version that provided the headers in /usr/include), you should look at the macros __GLIBC__ and __GLIBC_MINOR__. These expand to positive integers, and will be defined as a side-effect of including any header file provided by the GNU C Library; this means you can include a standard header, and then use #ifdef __GLIBC__ to decide whether you can include a nonstandard header like gnu/libc-version.h.
Expanding the test program from the accepted answer:
#include <stdio.h>
#ifdef __GLIBC__
#include <gnu/libc-version.h>
#endif
int
main(void)
{
#ifdef __GLIBC__
printf("GNU libc compile-time version: %u.%u\n", __GLIBC__, __GLIBC_MINOR__);
printf("GNU libc runtime version: %s\n", gnu_get_libc_version());
return 0;
#else
puts("Not the GNU C Library");
return 1;
#endif
}
When I compile and run this program on the computer I'm typing this answer on (which is a Mac) it prints
Not the GNU C Library
but when compiled and run on a nearby Linux box it prints
GNU libc compile-time version: 2.24
GNU libc runtime version: 2.24
Under normal circumstances, the "runtime" version could be bigger than the "compile-time" version, but never smaller. The major version number is unlikely ever to change again (the last time it changed was the "libc6 transition" in 1997).
If you would prefer a shell 'one-liner' to dump these macros, use:
echo '#include <errno.h>' | gcc -xc - -E -dM |
grep -E '^#define __GLIBC(|_MINOR)__ ' | sort
The grep pattern is chosen to match only the two macros that are relevant, because there are dozens of internal macros named __GLIBC_somethingorother that you don't want to have to read through.
I doubt if you have more than one glibc installed in your system.But ldd -v <path/to/gcc-4.x> should give you the glibc used.
The easiest way is to use ldd which comes with glibc
Just run this command ldd --version :
dina#dina-X450LA:~$ ldd --version
ldd (Ubuntu GLIBC 2.23-0ubuntu9) 2.23
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
Their is two additional ways to find out the glibc version:
Check the version of the installed glibc rpm package : this by runing this command
rpm -q glibc
Check the version of the used libc.so file. This way is a little bit more difficult. You can check it in this link: Linux: Check the glibc version
You can use strings command to check GLIBC version of compiler. Highest version is applicable.
ubuntu1604:extra$ strings ./arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gcc | grep GLIBC
GLIBC_2.3
GLIBC_2.8
GLIBC_2.14
GLIBC_2.4
GLIBC_2.11
GLIBC_2.2.5
GLIBC_2.3.4
Also, check the higher versioning symbol of the libc:
readelf -V /lib64/libc.so.6
Fedora 15
cmake version 2.8.4
I am using the following CMakeLists.txt. However the status message doesn't display when I run cmake .
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(proj2 C)
IF(CMAKE_COMPILER_IS_GNUCXX)
MESSAGE(STATUS "==== GCC detected - Adding compiler flags")
SET(CMAKE_C_FLAGS "-pthread -ggdb -Wextra -Wall")
ENDIF(CMAKE_COMPILER_IS_GNUCXX)
ADD_EXECUTABLE(crypto_app main.c)
TARGET_LINK_LIBRARIES(crypto_app crypt)
All I get is the following:
-- The C compiler identification is GNU
-- Check for working C compiler: /usr/lib64/ccache/gcc
-- Check for working C compiler: /usr/lib64/ccache/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/projects/proj1/
Many thanks for any suggestions about this.
You're telling cmake that it's a C project, and then checking for a CXX (i.e. C++) compiler. CMAKE_COMPILER_IS_GNUCXX will never be true in this case. That's why.