[CMake] One project, one platform, 2 compilers

Michael Hertling mhertling at online.de
Fri Nov 18 08:26:58 EST 2011


On 11/17/2011 05:18 PM, Paul Hansen wrote:
> Hi
> 
> I have a project that has to be compiled with two different compilers on
> the same computer.
> 
> Can I do that from the same CMakeLists.txt file?

What do you mean exactly?

(1) Compile the project twice, each time completely with a different
compiler? If so, use two different build trees, as already outlined
in the meantime.

(2) A part of your project must be compiled with a different compiler
than the remaining parts? Difficult - besides a custom-command-based
approach, you might outsource the concerned part and reintegrate it
as an external project which can be configured independently with a
different toolchain. Look at the following example:

# CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(MAIN C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(SUBCC ${CMAKE_C_COMPILER} CACHE FILEPATH "Subproject C compiler")
INCLUDE(ExternalProject)
ExternalProject_Add(sub
    SOURCE_DIR ${CMAKE_SOURCE_DIR}/sub
    CMAKE_CACHE_ARGS
        -DCMAKE_C_COMPILER:FILEPATH=${SUBCC}
        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/sub)
ADD_LIBRARY(f SHARED IMPORTED)
SET_TARGET_PROPERTIES(f PROPERTIES
    IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/sub/lib/libf.so)
ADD_DEPENDENCIES(f sub)
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return 0;}\n")
ADD_EXECUTABLE(main main.c)
TARGET_LINK_LIBRARIES(main f)
ADD_DEPENDENCIES(main f)

sub/CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(SUB C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
FILE(WRITE ${CMAKE_BINARY_DIR}/f.c "void f(void){}\n")
ADD_LIBRARY(f SHARED f.c)
INSTALL(TARGETS f LIBRARY DESTINATION lib)

Configure with the desired SUBCC to see the subproject being built with
that instead of the overall project's C compiler. The downside is that
you can't use FIND_*() on the subproject's targets since they're built
after the overall project is already configured, so you must predict
their locations. Additionally, there may be issues w.r.t. the correct
handling of dependencies. Moreover, if the subproject is to share the
overall project's cache, you need to pass the concerned variables to
ExternalProject_Add() individually, or do some trickery with LOAD_
CACHE(). Alternatively, you might use the so-called super-build
approach, but be prepared for other issues then, cf. [1].

> Specifically I am wondering:
> - CMake finds a compiler and makes a test. A colleague has tried to change
> the compiler variables but CMake made the test and overwrote his settings
> (from the CMakeLists.txt file) in CMakeCache.txt

The toolchain can't be changed without a complete reconfiguration, and
during the latter, CMake even forgets the cache settings specified on
the command line, cf. [2].

> - With target_link_directories I can point out specifically which libraries
> should be used with each executable. But what about header files?
> include_directories() is not specified for each executable. Is there anyway
> to control what is in the include path at different points in the
> CMakeLists.txt. I have tried to use set_directory_properties(PROPERTIES
> INCLUDE_DIRECTORIES "") to reset include path at one point. The deletion
> works but just not at that specific point on CMakeLists.txt.

The INCLUDE_DIRECTORIES directory property is read-only.

> - If split up into compiler1.cmake and compiler2.cmake I still get the
> include_directories() problem since values are "inherited"

In general, I'd recommend to invoke INCLUDE_DIRECTORIES() sufficiently
deep within the CMakeLists.txt files' hierarchy to limit the scope of
its impact. Possibly, you even need to reorganize your project a bit,
i.e. split one CMakeLists.txt in two and have INCLUDE_DIRECTORIES()
called for the latters with the correct directories separately.

Regards,

Michael

[1] http://www.mail-archive.com/cmake@cmake.org/msg36170.html
[2] http://www.mail-archive.com/cmake@cmake.org/msg37060.html


More information about the CMake mailing list