[CMake] Proposal for full CMake cross compiler support

Peter Soetens peter.soetens at fmtc.be
Thu Apr 5 06:53:11 EDT 2007


On Sunday 04 March 2007 18:08:13 Trevor Kellaway wrote:
> Hi,
>
> I've been working on adding support for a TI DSP compiler to CMake.
> Initially I started off down the same route as the current UseEcos.cmake
> support, however this didn't really work out for a number of reasons,
> one main one being if you don't have a native platform compiler (e.g.
> Visual Studio under Windows) then you won't be able to build.

Although UseEcos.cmake implies that it is easy to use CMake for embedded 
development, it isn't yet. But you discovered that below...

>
> It occurs to me that what is really needed is the ability to add cross
> compilers as first class citizens, in place of the native compiler. What
> you really want to be able to do is something like this (where cl6x is
> the TI DSP compiler support):
>
> 	cmake -G "NMake Makefiles" -DCMAKE_CROSS_COMPILER:string=cl6x

The common way today is to specify for example 

CROSS_COMPILE=powerpc-603-linux-gnu- ARCH=ppc

The main reason for splitting these is that it would be too hard to specify a 
configure or cmake script for every possible cross combo. It is much easier 
to indicate: 1. I'm cross compiling (with prefix CROSS_COMPILE),  2. Its for 
target ARCH; for which universal macro's can be written.

For CMake convention, I'll name them CMAKE_CROSS_COMPILE and CMAKE_ARCH (or 
CMAKE_CROSS_COMPILE_ARCH)

>
> I've managed to get an initial attempt at this working, with minimal
> patches to CMake's Modules directory.

A patch would have been welcome.

>
> The concept is to follow a similar idea to CMake's existing modules and
> platforms, by having a hierarchy of include files, based on the proposed
> new CMAKE_CROSS_COMPILER:
>
> *	CrossCompiler.cmake

I agree with this one.

> *	CrossCompiler-cl6x.cmake
> *	CrossCompiler-Generic-cl6x.cmake
> *	Linux-cl6x.cmake
> *	Windows-cl6x.cmake

I would only provide CrossCompiler-ARCH.cmake 'target' macros here.

>
> The include hierarchy is:
>
> *	CrossCompiler.cmake
> *	CrossCompiler-cl6x.cmake
> *	Linux-cl6x.cmake
> *	CrossCompiler-Generic-cl6x.cmake
> *	Windows-cl6x.cmake
> *	CrossCompiler-Generic-cl6x.cmake
>
> The actual build flags/rules for the cross compiler are in the common
> file CrossCompiler-Generic-cl6x.cmake, this can then be included (with
> any override tweaks) for a specific platform (e.g., I run this EXE
> compiler under Windows, and using Wine on Linux).

Given ARCH, wouldn't it be possible to reduce this ?

>
> One key issue is getting in early enough in the config process, it seems
> that CMakeDetermineSystem.cmake is the first module included (anyone
> know better?), so an initial include is added to this file:
>
> CMakeDetermineSystem.cmake:
> 	IF (CMAKE_CROSS_COMPILER)
> 		INCLUDE (Platform/CrossCompiler)
> 	ENDIF (CMAKE_CROSS_COMPILER)

OK.

>
>
> The CrossCompiler.cmake then contains the commands to disable the
> testing of the native compiler.
>
> CrossCompiler.cmake:
> 	#
> 	# Set the compiler name to stop automatic searching for
> compilers.
> 	# This name is used as the CMAKE_BASE_NAME part which is used to
> include
> 	# the 'Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake'
> later.
> 	#
> 	SET (CMAKE_C_COMPILER ${CMAKE_CROSS_COMPILER})
> 	SET (CMAKE_CXX_COMPILER ${CMAKE_CROSS_COMPILER})

The problem here is that not only the compiler needs to be set, but also 
assembler, linker etc. I would propose to modify the existing .cmake files 
such that they prepend ${CMAKE_CROSS_COMPILE} to ${CMAKE_C_COMPILER} etc,
this allows to do:

cmake -DCMAKE_CROSS_COMPILE:string=powerpc-linux-gnu -DCMAKE_ARCH:string=ppc -DCMAKE_C_COMPILER:string=gcc

which remains compatible with current cmake conventions.

>
> 	#
> 	# Inhibit compiler compatibility tests.
> 	# Stop test to see if our compilers work.
> 	# Stop auto GNU test.
> 	#
> 	SET (CMAKE_SKIP_COMPATIBILITY_TESTS 1)
> 	SET (CMAKE_C_COMPILER_WORKS 1)
> 	SET (CMAKE_CXX_COMPILER_WORKS 1)
> 	SET (CMAKE_COMPILER_IS_GNUCC_RUN 1)
> 	SET (CMAKE_COMPILER_IS_GNUCXX_RUN 1)
>
> 	#
> 	# Allow optional cross compiler specific override.
> 	#
> 	INCLUDE (Platform/CrossCompiler-${CMAKE_CROSS_COMPILER}
> OPTIONAL)

Agree, but my last line would be 
INCLUDE (Platform/CrossCompiler-${CMAKE_ARCH})

>
>
> This then also pulls in a optional cross compiler target specific file
> that allows changing of the object extension (this has to be changed
> very early on in the config process, as it gets generated as a cached
> file and can't be easily changed at the platform or project
> CMakeLists.txt level later).
>
> CrossCompiler-cl6x.cmake:
> 	#
> 	# We must set the object extension type prior to the (skipped)
> compiler test,
> 	# as this gets embedded in the inference rule and attempts to
> change it later
> 	# will be ignored.
> 	#
> 	SET (CMAKE_C_OUTPUT_EXTENSION .obj)
> 	SET (CMAKE_CXX_OUTPUT_EXTENSION .obj)

This is actually a part of my CrossCompiler-ARCH.cmake file.

>
>
> CMakeCCompiler.cmake.in and CMakeCXXCompiler.cmake.in have to be patched
> as they both unconditionally set the object extension based on running
> on Linux or Windows, I've changed it to only set this if it isn't
> already set:
>
> CMakeCCompiler.cmake.in:
> 	IF (NOT CMAKE_C_OUTPUT_EXTENSION)
> 	  IF(UNIX)
> 	    SET(CMAKE_C_OUTPUT_EXTENSION .o)
> 	  ELSE(UNIX)
> 	    SET(CMAKE_C_OUTPUT_EXTENSION .obj)
> 	  ENDIF(UNIX)
> 	ENDIF (NOT CMAKE_C_OUTPUT_EXTENSION)

OK.

>
>
> CMakeTestCCompiler.cmake has to be modified to stop it from trying to
> check the size of a "void*" (it looks like this is an oversight, as all
> other size testing is turned off by CMAKE_SKIP_COMPATIBILITY_TESTS):
>
> CMakeTestCCompiler.cmake:
> 	  IF (NOT CMAKE_SKIP_COMPATIBILITY_TESTS)
> 	     CHECK_TYPE_SIZE("void*"  CMAKE_SIZEOF_VOID_P)
> 	  ENDIF (NOT CMAKE_SKIP_COMPATIBILITY_TESTS)
>
>
> Has anyone else tried to implement anything similar for cross compiler
> support?

I'm doing it right now for powerpc target (603) on a Linux host. I got already 
very far by 
specifying -DCMAKE_C_COMPILER:string=... -DCMAKE_CXX_COMPILER:string=...

at the console. The main issue is the 'Check' scripts of cmake which only 
query the build environment and find things not present on the target and 
vice versa. The FIND_X macro is better suited for 'host environment' 
detection, as it allows you to tweak paths. So you should only use that one. 
An improved version of FIND would detect that CMAKE_CROSS_COMPILE has been 
set and skip the default paths right away.

>
> What do you think of this approach? Is it suitable for thinking about as
> a generic CMake solution for any cross platform compiler?
>
> Comments welcome.

Better late than never !

Peter


-- 
Peter Soetens -- FMTC -- <http://www.fmtc.be>


More information about the CMake mailing list