[CMake] Proposal for full CMake cross compiler support

Trevor Kellaway tkellaway at asl-electronics.co.uk
Sun Mar 4 12:08:13 EST 2007


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.

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

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

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
*	CrossCompiler-cl6x.cmake
*	CrossCompiler-Generic-cl6x.cmake
*	Linux-cl6x.cmake
*	Windows-cl6x.cmake

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).

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)


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})

	#
	# 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)


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)


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)


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?

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.

- TrevK




-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://public.kitware.com/pipermail/cmake/attachments/20070304/9816e3d6/attachment.html


More information about the CMake mailing list