8

This is my first cmake file. I have a linux system with both clang and g++. Also libc++ is installed. I develop on Mac (xcode) but deploy to linux. I am writing a cmake file in which I can pick either clang or g++ and libc++ or libstdc++. So 4 possible combinations.

I figured out how to select the compiler and force c++11 on it, but I can't figure out how to specify the standard library. Any suggestions?

This is what I have so far:

## cmake ###
cmake_minimum_required (VERSION 3.5)

#set project directories
set(ProjectDirectory ${CMAKE_SOURCE_DIR}) #.../Project/
set(BuildDirectory ${ProjectDirectory}/Build)
set(ProductDirectory ${ProjectDirectory}/Products)
set(sourceDirectory ${ProjectDirectory}/Source)

#print project directories
message(${ProjectDirectory})
message(${BuildDirectory})
message(${ProductDirectory})

#configure cmake
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ProductDirectory})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ProductDirectory})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${ProductDirectory})

set(CMAKE_VERBOSE_MAKEFILE on)

#compiler and standard library settings
set(CMAKE_CXX_COMPILER "clang++")
set(CMAKE_CXX_STANDARD 11)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v -stdlib=libc++")
        #libstdc++ #linux
        #libc++    #OS X

#compiler flags
SET( CompilerFlags  " ")
#SET( CompilerFlags  "${CompilerFlags} -stdlib=libc++" )
SET( CompilerFlags  "${CompilerFlags} -Wno-unknown-pragmas" )
SET( CompilerFlags  "${CompilerFlags} -Wall" )
SET( CompilerFlags  "${CompilerFlags} -Wextra" )

set (CMAKE_CXX_FLAGS ${CompilerFlags})

#linker flags
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")

#message(${CMAKE_CXX_FLAGS})

##################
### Libraries ###
################
### common library ###
project(common)

#message(STATUS ${CMAKE_CXX_FLAGS})

#source files
#set (commonSource ${sourceDirectory}/Object/object.cpp) #specify specific files
file(GLOB_RECURSE commonSource ${sourceDirectory}/Object/*.cpp) # recursive

#targets
add_library (common STATIC ${commonSource})

#target_compile_options (common PUBLIC ${CompilerFlags})


#####################
### Applications ###
###################
### Hello project ###
project (hello)

#source files
#set (helloSource ${sourceDirectory}/main.cpp)

#targets
#add_executable (hello ${helloSource})

#linking
#target_link_libraries (hello common)


#install(TARGETS common DESTINATION ${ProductDirectory})

I run this command on a console

../Project/Build$ rm -r *; rm -r ../Products/*; cmake ..; make VERBOSE=1;

My folder structure is:

Project
    Source
    Build
    Products
    CMakeLists.txt

I have also noticed that the compiler flags are sometimes ignored and only used when I run cmake and make a second time.

Also, I use a lot of #warning todo in my code How can I disable these warnings during compilation?

user965972
  • 2,489
  • 2
  • 23
  • 39
  • Have you checked that question: http://stackoverflow.com/questions/7031126/switching-between-gcc-and-clang-llvm-using-cmake? Among other things [its answer](http://stackoverflow.com/a/7032021/3440745) explains proper setting of compiler flags. Your last question about disabling warnings is **unrelated** to the other parts of your question post. It is better to create new question post for it. – Tsyvarev Apr 27 '17 at 19:51
  • If I understand correctly, that is about changing the compiler for the entire linux system. I just want to specify the compiler and standard library for a specific project. – user965972 Apr 27 '17 at 20:19
  • 1
    Selection of compiler is usually outside of project's `CMakeLists.txt`. And related question describes how to do that. As for libc++ library, its selection also can be viewed as separate compiler environment, so it is natural to move this selection outside of the project's `CMakeLists.txt` too. – Tsyvarev Apr 27 '17 at 20:59
  • 1
    Ok, it's unusual. But I don't care that it's unusual. I just want it to work the way I want it to work. So, if it's possible, how can it be done? – user965972 Apr 27 '17 at 21:30
  • 1
    If you are about setting variable *CMAKE_CXX_FLAGS*, before `project()` call it should be set as *CMAKE_CXX_FLAGS_INIT*. – Tsyvarev Apr 27 '17 at 21:51
  • 2
    There are better ways to specify to use C++11 and also to let CMake choose the appropriate C++ library to link with. In short, the target properties `CXX_STANDARD`, `CXX_STANDARD_REQUIRED` and `CXX_EXTENSIONS` are what you want (and/or their CMake variable counterparts). An article explaining it all in depth can be found [here](https://crascit.com/2015/03/28/enabling-cxx11-in-cmake/). Compiler selection should really be left up to the developer unless you really need one and not the other for some reason. – Craig Scott Apr 28 '17 at 11:17
  • 1
    My code compiles and runs just fine on OS X. But it's a nightmare to compile on linux. I have been told the linux c++ libraries do not yet fully implement the c++11 standard. So I want to try clang and libc++ instead of gcc and libstdc++. Frankly I don't care about compilers as long as it runs. – user965972 Apr 28 '17 at 15:12

1 Answers1

7

It's a little tricky because I don't believe CMake has a built in way to select a standard library. What I do is pass it into the linker flags. e.g.

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")

CMake does, however, support setting the compiler:

set(CMAKE_CXX_COMPILER "clang++")
Cinder Biscuits
  • 4,880
  • 31
  • 51
  • Better to use the full path. On linux I get the following error: CMake Error at tests/CMakeLists.txt:6 (project): The CMAKE_CXX_COMPILER: clang++ is not a full path and was not found in the PATH. Tell CMake where to find the compiler by setting either the environment variable "CXX" or the CMake cache entry CMAKE_CXX_COMPILER to the full path to the compiler, or to the compiler name if it is in the PATH. -- Configuring incomplete, errors occurred! – zertyz Dec 13 '18 at 22:04
  • Anyway it didn't work for me: the creation of makefiles locks in an eternal loop – zertyz Dec 13 '18 at 22:07
  • I disagree, adding the compiler to your PATH is the more accepted and better way of doing things. It makes code reuse easier and doesn't hardcode the development environment setup into source code. If you need to specify a full path, it's better just to set it using -D when you run CMake. `cmake -D CMAKE_CXX_COMPILER "/path/to/your/cpp/compiler/executable" /path/to/directory/containing/CMakeLists.txt` The generation recursion you mention wouldn't have anything to do with the compiler variable. Look for issues elsewhere. – Cinder Biscuits Dec 13 '18 at 22:55
  • The compiler is in my path. Nonetheless, I got the error message. I might be a bug with my tool's versions. – zertyz Dec 14 '18 at 00:12