From 61d3444f93600955ca12840b0e62503584bb8910 Mon Sep 17 00:00:00 2001 From: Alexander Neundorf Date: Thu, 17 May 2007 13:20:44 -0400 Subject: [PATCH] ENH: merge CMake-CrossCompileBasic to HEAD -add a RESULT_VARIABLE to INCLUDE() -add CMAKE_TOOLCHAIN_FILE for specifiying your (potentially crosscompiling) toolchain -have TRY_RUN() complain if you try to use it in crosscompiling mode (which were compiled but cannot run on this system) -use CMAKE_EXECUTABLE_SUFFIX in TRY_RUN(), probably TRY_RUN won't be able to run the executables if they have a different suffix because they are probably crosscompiled, but nevertheless it should be able to find them -make several cmake variables presettable by the user: CMAKE_C/CXX_COMPILER, CMAKE_C/CXX_OUTPUT_EXTENSION, CMAKE_SYSTEM_NAME, CMAKE_SYSTEM_INFO_FILE -support prefix for GNU toolchains (arm-elf-gcc, arm-elf-ar, arm-elf-strip etc.) -move ranlib on OSX from the file command to a command in executed in cmake_install.cmake -add support for stripping during install in cmake_install.cmake -split out cl.cmake from Windows-cl.cmake, first (very incomplete) step to support MS crosscompiling tools -remove stdio.h from the simple C program which checks if the compiler works, since this may not exist for some embedded platforms -create a new CMakeFindBinUtils.cmake which collects the search fro ar, ranlib, strip, ld, link, install_name_tool and other tools like these -add support for CMAKE_FIND_ROOT_PATH for all FIND_XXX commands, which is a list of directories which will be prepended to all search directories, right now as a cmake variable, turning it into a global cmake property may need some more work -remove cmTestTestHandler::TryExecutable(), it's unused -split cmFileCommand::HandleInstall() into slightly smaller functions Alex --- Modules/CMakeCCompiler.cmake.in | 7 +- Modules/CMakeCInformation.cmake | 27 +- Modules/CMakeCXXCompiler.cmake.in | 7 +- Modules/CMakeCXXInformation.cmake | 30 +- Modules/CMakeDetermineCCompiler.cmake | 86 +- Modules/CMakeDetermineCXXCompiler.cmake | 73 +- Modules/CMakeDetermineFortranCompiler.cmake | 11 +- Modules/CMakeDetermineSystem.cmake | 79 +- Modules/CMakeFindBinUtils.cmake | 52 + Modules/CMakeLists.txt | 2 + Modules/CMakeSystem.cmake.in | 24 +- Modules/CMakeSystemSpecificInformation.cmake | 13 +- Modules/CMakeTestCCompiler.cmake | 3 +- Modules/CTest.cmake | 1 + Modules/CheckTypeSize.cmake | 2 + Modules/Platform/Windows-cl.cmake | 51 +- Modules/Platform/cl.cmake | 53 + Source/CTest/cmCTestTestHandler.cxx | 45 - Source/CTest/cmCTestTestHandler.h | 5 - Source/cmFileCommand.cxx | 1032 +++++++++-------- Source/cmFileCommand.h | 38 +- Source/cmFindBase.cxx | 89 +- Source/cmFindBase.h | 11 +- Source/cmIncludeCommand.cxx | 61 +- Source/cmIncludeCommand.h | 8 +- Source/cmInstallTargetGenerator.cxx | 69 +- Source/cmInstallTargetGenerator.h | 7 +- Source/cmMakefile.cxx | 12 +- Source/cmMakefile.h | 4 +- Source/cmTryRunCommand.cxx | 18 +- Source/cmUtilitySourceCommand.cxx | 2 +- Source/cmUtilitySourceCommand.h | 9 +- Tests/CMakeTests/CMakeLists.txt | 3 + Tests/CMakeTests/DummyToolchain.cmake | 8 + Tests/CMakeTests/FindBaseTest.cmake.in | 44 + Tests/CMakeTests/IncludeTest.cmake.in | 22 + Tests/CMakeTests/ToolchainTest.cmake.in | 83 ++ .../cmake_i_do_not_exist_in_the_system.h | 1 + 38 files changed, 1352 insertions(+), 740 deletions(-) create mode 100644 Modules/CMakeFindBinUtils.cmake create mode 100644 Modules/Platform/cl.cmake create mode 100644 Tests/CMakeTests/DummyToolchain.cmake create mode 100644 Tests/CMakeTests/FindBaseTest.cmake.in create mode 100644 Tests/CMakeTests/IncludeTest.cmake.in create mode 100644 Tests/CMakeTests/ToolchainTest.cmake.in create mode 100644 Tests/CMakeTests/include/cmake_i_do_not_exist_in_the_system.h diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index 16c7d69a8..abd506783 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/Modules/CMakeCCompiler.cmake.in @@ -22,11 +22,8 @@ SET(CMAKE_C_COMPILER_ID_RUN 1) SET(CMAKE_C_SOURCE_FILE_EXTENSIONS c) SET(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) SET(CMAKE_C_LINKER_PREFERENCE None) -IF(UNIX) - SET(CMAKE_C_OUTPUT_EXTENSION .o) -ELSE(UNIX) - SET(CMAKE_C_OUTPUT_EXTENSION .obj) -ENDIF(UNIX) +SET(CMAKE_C_OUTPUT_EXTENSION @CMAKE_C_OUTPUT_EXTENSION@) + # save the size of void* in case where cache is removed # and the this file is still around SET(CMAKE_SIZEOF_VOID_P @CMAKE_SIZEOF_VOID_P@) diff --git a/Modules/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake index 10ec1e7b4..5f73e6f46 100644 --- a/Modules/CMakeCInformation.cmake +++ b/Modules/CMakeCInformation.cmake @@ -3,18 +3,21 @@ # It also loads the available platform file for the system-compiler # if it exists. -GET_FILENAME_COMPONENT(CMAKE_BASE_NAME ${CMAKE_C_COMPILER} NAME_WE) -IF(CMAKE_COMPILER_IS_GNUCC) - SET(CMAKE_BASE_NAME gcc) -ENDIF(CMAKE_COMPILER_IS_GNUCC) -IF(CMAKE_C_COMPILER_ID) - IF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C.cmake) - SET(CMAKE_BASE_NAME ${CMAKE_C_COMPILER_ID}-C) - ENDIF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C.cmake) -ENDIF(CMAKE_C_COMPILER_ID) -SET(CMAKE_SYSTEM_AND_C_COMPILER_INFO_FILE - ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake) -INCLUDE(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL) +IF(NOT CMAKE_SYSTEM_AND_C_COMPILER_INFO_FILE) + GET_FILENAME_COMPONENT(CMAKE_BASE_NAME ${CMAKE_C_COMPILER} NAME_WE) + IF(CMAKE_COMPILER_IS_GNUCC) + SET(CMAKE_BASE_NAME gcc) + ENDIF(CMAKE_COMPILER_IS_GNUCC) + IF(CMAKE_C_COMPILER_ID) + IF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C.cmake) + SET(CMAKE_BASE_NAME ${CMAKE_C_COMPILER_ID}-C) + ENDIF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_C_COMPILER_ID}-C.cmake) + ENDIF(CMAKE_C_COMPILER_ID) + SET(CMAKE_SYSTEM_AND_C_COMPILER_INFO_FILE + ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake) +ENDIF(NOT CMAKE_SYSTEM_AND_C_COMPILER_INFO_FILE) + +INCLUDE(${CMAKE_SYSTEM_AND_C_COMPILER_INFO_FILE} OPTIONAL) # This should be included before the _INIT variables are # used to initialize the cache. Since the rule variables diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index 5fafd663e..c6f474082 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -22,11 +22,8 @@ SET(CMAKE_CXX_COMPILER_ID_RUN 1) SET(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;H;o;O;obj;OBJ;def;DEF;rc;RC) SET(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm) SET(CMAKE_CXX_LINKER_PREFERENCE Prefered) -IF(UNIX) - SET(CMAKE_CXX_OUTPUT_EXTENSION .o) -ELSE(UNIX) - SET(CMAKE_CXX_OUTPUT_EXTENSION .obj) -ENDIF(UNIX) +SET(CMAKE_CXX_OUTPUT_EXTENSION @CMAKE_CXX_OUTPUT_EXTENSION@) + # save the size of void* in case where cache is removed # and the this file is still around SET(CMAKE_SIZEOF_VOID_P @CMAKE_SIZEOF_VOID_P@) diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake index ef1b07eaf..d966f1224 100644 --- a/Modules/CMakeCXXInformation.cmake +++ b/Modules/CMakeCXXInformation.cmake @@ -3,19 +3,23 @@ # It also loads the available platform file for the system-compiler # if it exists. -GET_FILENAME_COMPONENT(CMAKE_BASE_NAME ${CMAKE_CXX_COMPILER} NAME_WE) -# since the gnu compiler has several names force g++ -IF(CMAKE_COMPILER_IS_GNUCXX) - SET(CMAKE_BASE_NAME g++) -ENDIF(CMAKE_COMPILER_IS_GNUCXX) -IF(CMAKE_CXX_COMPILER_ID) - IF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX.cmake) - SET(CMAKE_BASE_NAME ${CMAKE_CXX_COMPILER_ID}-CXX) - ENDIF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX.cmake) -ENDIF(CMAKE_CXX_COMPILER_ID) -SET(CMAKE_SYSTEM_AND_CXX_COMPILER_INFO_FILE - ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake) -INCLUDE(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL) +IF(NOT CMAKE_SYSTEM_AND_CXX_COMPILER_INFO_FILE) + GET_FILENAME_COMPONENT(CMAKE_BASE_NAME ${CMAKE_CXX_COMPILER} NAME_WE) + # since the gnu compiler has several names force g++ + IF(CMAKE_COMPILER_IS_GNUCXX) + SET(CMAKE_BASE_NAME g++) + ENDIF(CMAKE_COMPILER_IS_GNUCXX) + IF(CMAKE_CXX_COMPILER_ID) + IF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX.cmake) + SET(CMAKE_BASE_NAME ${CMAKE_CXX_COMPILER_ID}-CXX) + ENDIF(EXISTS ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_CXX_COMPILER_ID}-CXX.cmake) + ENDIF(CMAKE_CXX_COMPILER_ID) + SET(CMAKE_SYSTEM_AND_CXX_COMPILER_INFO_FILE + ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}.cmake) +ENDIF(NOT CMAKE_SYSTEM_AND_CXX_COMPILER_INFO_FILE) + +INCLUDE(${CMAKE_SYSTEM_AND_CXX_COMPILER_INFO_FILE} OPTIONAL) + # This should be included before the _INIT variables are # used to initialize the cache. Since the rule variables # have if blocks on them, users can still define them here. diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index d80452f55..0ee390bbf 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/Modules/CMakeDetermineCCompiler.cmake @@ -2,9 +2,26 @@ # determine the compiler to use for C programs # NOTE, a generator may set CMAKE_C_COMPILER before # loading this file to force a compiler. -# use environment variable CCC first if defined by user, next use +# use environment variable CC first if defined by user, next use # the cmake variable CMAKE_GENERATOR_CC which can be defined by a generator # as a default compiler +# If the internal cmake variable _CMAKE_TOOLCHAIN_PREFIX is set, this is used +# as prefix for the tools (e.g. arm-elf-gcc, arm-elf-ar etc.). This works +# currently with the GNU crosscompilers. +# It also tries to detect a MS crosscompiler and find out its +# suffix (clarm.exe), which will be stored in _CMAKE_TOOLCHAIN_SUFFIX and +# reused for the CXX compiler. +# +# +# Sets the following variables: +# CMAKE_C_COMPILER +# CMAKE_AR +# CMAKE_RANLIB +# CMAKE_COMPILER_IS_GNUCC +# +# If not already set before, it also sets +# _CMAKE_TOOLCHAIN_PREFIX +# _CMAKE_TOOLCHAIN_SUFFIX IF(NOT CMAKE_C_COMPILER) SET(CMAKE_CXX_COMPILER_INIT NOTFOUND) @@ -15,10 +32,9 @@ IF(NOT CMAKE_C_COMPILER) IF(CMAKE_C_FLAGS_ENV_INIT) SET(CMAKE_C_COMPILER_ARG1 "${CMAKE_C_FLAGS_ENV_INIT}" CACHE STRING "First argument to C compiler") ENDIF(CMAKE_C_FLAGS_ENV_INIT) - IF(EXISTS ${CMAKE_C_COMPILER_INIT}) - ELSE(EXISTS ${CMAKE_C_COMPILER_INIT}) + IF(NOT EXISTS ${CMAKE_C_COMPILER_INIT}) MESSAGE(FATAL_ERROR "Could not find compiler set in environment variable CC:\n$ENV{CC}.") - ENDIF(EXISTS ${CMAKE_C_COMPILER_INIT}) + ENDIF(NOT EXISTS ${CMAKE_C_COMPILER_INIT}) ENDIF($ENV{CC} MATCHES ".+") # next try prefer the compiler specified by the generator @@ -32,26 +48,64 @@ IF(NOT CMAKE_C_COMPILER) IF(CMAKE_C_COMPILER_INIT) SET(CMAKE_C_COMPILER_LIST ${CMAKE_C_COMPILER_INIT}) ELSE(CMAKE_C_COMPILER_INIT) - SET(CMAKE_C_COMPILER_LIST gcc cc cl bcc xlc) + SET(CMAKE_C_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}gcc ${_CMAKE_TOOLCHAIN_PREFIX}cc cl${_CMAKE_TOOLCHAIN_SUFFIX} bcc xlc) ENDIF(CMAKE_C_COMPILER_INIT) # Find the compiler. + IF (_CMAKE_USER_CXX_COMPILER_PATH) + FIND_PROGRAM(CMAKE_C_COMPILER NAMES ${CMAKE_C_COMPILER_LIST} PATHS ${_CMAKE_USER_CXX_COMPILER_PATH} DOC "C compiler" NO_DEFAULT_PATH) + ENDIF (_CMAKE_USER_CXX_COMPILER_PATH) FIND_PROGRAM(CMAKE_C_COMPILER NAMES ${CMAKE_C_COMPILER_LIST} DOC "C compiler") + IF(CMAKE_C_COMPILER_INIT AND NOT CMAKE_C_COMPILER) SET(CMAKE_C_COMPILER "${CMAKE_C_COMPILER_INIT}" CACHE FILEPATH "C compiler" FORCE) ENDIF(CMAKE_C_COMPILER_INIT AND NOT CMAKE_C_COMPILER) +ELSE(NOT CMAKE_C_COMPILER) + + # if a compiler was specified by the user but without path, + # now try to find it with the full path and force it into the cache + GET_FILENAME_COMPONENT(_CMAKE_USER_C_COMPILER_PATH "${CMAKE_C_COMPILER}" PATH) + IF(NOT _CMAKE_USER_C_COMPILER_PATH) + FIND_PROGRAM(CMAKE_C_COMPILER_WITH_PATH NAMES ${CMAKE_C_COMPILER}) + MARK_AS_ADVANCED(CMAKE_C_COMPILER_WITH_PATH) + SET(CMAKE_C_COMPILER ${CMAKE_C_COMPILER_WITH_PATH} CACHE FILEPATH "C compiler" FORCE) + ENDIF(NOT _CMAKE_USER_C_COMPILER_PATH) ENDIF(NOT CMAKE_C_COMPILER) -MARK_AS_ADVANCED(CMAKE_C_COMPILER) -GET_FILENAME_COMPONENT(COMPILER_LOCATION "${CMAKE_C_COMPILER}" - PATH) +MARK_AS_ADVANCED(CMAKE_C_COMPILER) -FIND_PROGRAM(CMAKE_AR NAMES ar PATHS ${COMPILER_LOCATION} ) +IF (NOT _CMAKE_TOOLCHAIN_LOCATION) + GET_FILENAME_COMPONENT(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_C_COMPILER}" PATH) +ENDIF (NOT _CMAKE_TOOLCHAIN_LOCATION) + +# if we have a gcc cross compiler, they have usually some prefix, like +# e.g. powerpc-linux-gcc, arm-elf-gcc or i586-mingw32msvc-gcc +# the other tools of the toolchain usually have the same prefix +IF (NOT _CMAKE_TOOLCHAIN_PREFIX) + GET_FILENAME_COMPONENT(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME_WE) + IF (COMPILER_BASENAME MATCHES "^(.+-)g?cc") + STRING(REGEX REPLACE "^(.+-)g?cc" "\\1" _CMAKE_TOOLCHAIN_PREFIX "${COMPILER_BASENAME}") + ENDIF (COMPILER_BASENAME MATCHES "^(.+-)g?cc") +ENDIF (NOT _CMAKE_TOOLCHAIN_PREFIX) + +# if we have a MS cross compiler, it usually has a suffix, like +# e.g. clarm.exe or clmips.exe. Use this suffix for the CXX compiler too. +IF (NOT _CMAKE_TOOLCHAIN_SUFFIX) + GET_FILENAME_COMPONENT(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME) + IF (COMPILER_BASENAME MATCHES "^cl(.+)\\.exe$") + STRING(REGEX REPLACE "^cl(.+)\\.exe$" "\\1" _CMAKE_TOOLCHAIN_SUFFIX "${COMPILER_BASENAME}") + ENDIF (COMPILER_BASENAME MATCHES "^cl(.+)\\.exe$") +ENDIF (NOT _CMAKE_TOOLCHAIN_SUFFIX) + +# some exotic compilers have different extensions (e.g. sdcc uses .rel) +# so don't overwrite it if it has been already defined by the user +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) -FIND_PROGRAM(CMAKE_RANLIB NAMES ranlib) -IF(NOT CMAKE_RANLIB) - SET(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib") -ENDIF(NOT CMAKE_RANLIB) -MARK_AS_ADVANCED(CMAKE_RANLIB) # Build a small source file to identify the compiler. IF(${CMAKE_GENERATOR} MATCHES "Visual Studio") @@ -62,6 +116,7 @@ IF(${CMAKE_GENERATOR} MATCHES "Visual Studio") # the user may be using an integrated Intel compiler. # SET(CMAKE_C_COMPILER_ID "MSVC") ENDIF(${CMAKE_GENERATOR} MATCHES "Visual Studio") + IF(NOT CMAKE_C_COMPILER_ID_RUN) SET(CMAKE_C_COMPILER_ID_RUN 1) @@ -81,9 +136,10 @@ IF(NOT CMAKE_C_COMPILER_ID_RUN) ENDIF("${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW") ENDIF(NOT CMAKE_C_COMPILER_ID_RUN) +INCLUDE(CMakeFindBinUtils) + # configure variables set in this file for fast reload later on CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCCompiler.cmake.in "${CMAKE_PLATFORM_ROOT_BIN}/CMakeCCompiler.cmake" IMMEDIATE) -MARK_AS_ADVANCED(CMAKE_AR) SET(CMAKE_C_COMPILER_ENV_VAR "CC") diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index 4ba152a7e..41b5e475d 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/Modules/CMakeDetermineCXXCompiler.cmake @@ -5,13 +5,21 @@ # use environment variable CXX first if defined by user, next use # the cmake variable CMAKE_GENERATOR_CXX which can be defined by a generator # as a default compiler +# If the internal cmake variable _CMAKE_TOOLCHAIN_PREFIX is set, this is used +# as prefix for the tools (e.g. arm-elf-g++, arm-elf-ar etc.) +# It also tries to detect a MS crosscompiler and find out its +# suffix (clarm.exe), which will be stored in _CMAKE_TOOLCHAIN_SUFFIX and +# reused for the C compiler. # # Sets the following variables: # CMAKE_CXX_COMPILER # CMAKE_COMPILER_IS_GNUCXX # CMAKE_AR # CMAKE_RANLIB - +# +# If not already set before, it also sets +# _CMAKE_TOOLCHAIN_PREFIX +# _CMAKE_TOOLCHAIN_SUFFIX IF(NOT CMAKE_CXX_COMPILER) SET(CMAKE_CXX_COMPILER_INIT NOTFOUND) @@ -22,10 +30,9 @@ IF(NOT CMAKE_CXX_COMPILER) IF(CMAKE_CXX_FLAGS_ENV_INIT) SET(CMAKE_CXX_COMPILER_ARG1 "${CMAKE_CXX_FLAGS_ENV_INIT}" CACHE STRING "First argument to CXX compiler") ENDIF(CMAKE_CXX_FLAGS_ENV_INIT) - IF(EXISTS ${CMAKE_CXX_COMPILER_INIT}) - ELSE(EXISTS ${CMAKE_CXX_COMPILER_INIT}) + IF(NOT EXISTS ${CMAKE_CXX_COMPILER_INIT}) MESSAGE(FATAL_ERROR "Could not find compiler set in environment variable CXX:\n$ENV{CXX}.\n${CMAKE_CXX_COMPILER_INIT}") - ENDIF(EXISTS ${CMAKE_CXX_COMPILER_INIT}) + ENDIF(NOT EXISTS ${CMAKE_CXX_COMPILER_INIT}) ENDIF($ENV{CXX} MATCHES ".+") # next prefer the generator specified compiler @@ -39,27 +46,65 @@ IF(NOT CMAKE_CXX_COMPILER) IF(CMAKE_CXX_COMPILER_INIT) SET(CMAKE_CXX_COMPILER_LIST ${CMAKE_CXX_COMPILER_INIT}) ELSE(CMAKE_CXX_COMPILER_INIT) - SET(CMAKE_CXX_COMPILER_LIST c++ g++ CC aCC cl bcc xlC) + SET(CMAKE_CXX_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ CC aCC cl${_CMAKE_TOOLCHAIN_SUFFIX} bcc xlC) ENDIF(CMAKE_CXX_COMPILER_INIT) # Find the compiler. + IF (_CMAKE_USER_C_COMPILER_PATH) + FIND_PROGRAM(CMAKE_CXX_COMPILER NAMES ${CMAKE_CXX_COMPILER_LIST} PATHS ${_CMAKE_USER_C_COMPILER_PATH} DOC "C++ compiler" NO_DEFAULT_PATH) + ENDIF (_CMAKE_USER_C_COMPILER_PATH) FIND_PROGRAM(CMAKE_CXX_COMPILER NAMES ${CMAKE_CXX_COMPILER_LIST} DOC "C++ compiler") + IF(CMAKE_CXX_COMPILER_INIT AND NOT CMAKE_CXX_COMPILER) SET(CMAKE_CXX_COMPILER "${CMAKE_CXX_COMPILER_INIT}" CACHE FILEPATH "C++ compiler" FORCE) ENDIF(CMAKE_CXX_COMPILER_INIT AND NOT CMAKE_CXX_COMPILER) +ELSE(NOT CMAKE_CXX_COMPILER) + +# if a compiler was specified by the user but without path, +# now try to find it with the full path and force it into the cache + GET_FILENAME_COMPONENT(_CMAKE_USER_CXX_COMPILER_PATH "${CMAKE_CXX_COMPILER}" PATH) + IF(NOT _CMAKE_USER_CXX_COMPILER_PATH) + FIND_PROGRAM(CMAKE_CXX_COMPILER_WITH_PATH NAMES ${CMAKE_CXX_COMPILER}) + MARK_AS_ADVANCED(CMAKE_CXX_COMPILER_WITH_PATH) + SET(CMAKE_CXX_COMPILER ${CMAKE_CXX_COMPILER_WITH_PATH} CACHE FILEPATH "CXX compiler" FORCE) + ENDIF(NOT _CMAKE_USER_CXX_COMPILER_PATH) ENDIF(NOT CMAKE_CXX_COMPILER) MARK_AS_ADVANCED(CMAKE_CXX_COMPILER) -GET_FILENAME_COMPONENT(COMPILER_LOCATION "${CMAKE_CXX_COMPILER}" PATH) +IF (NOT _CMAKE_TOOLCHAIN_LOCATION) + GET_FILENAME_COMPONENT(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_CXX_COMPILER}" PATH) +ENDIF (NOT _CMAKE_TOOLCHAIN_LOCATION) -FIND_PROGRAM(CMAKE_AR NAMES ar PATHS ${COMPILER_LOCATION}) -MARK_AS_ADVANCED(CMAKE_AR) +# if we have a g++ cross compiler, they have usually some prefix, like +# e.g. powerpc-linux-g++, arm-elf-g++ or i586-mingw32msvc-g++ +# the other tools of the toolchain usually have the same prefix +IF (NOT _CMAKE_TOOLCHAIN_PREFIX) + GET_FILENAME_COMPONENT(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME_WE) + IF (COMPILER_BASENAME MATCHES "^(.+-)[gc]\\+\\+") + STRING(REGEX REPLACE "^(.+-)[gc]\\+\\+" "\\1" _CMAKE_TOOLCHAIN_PREFIX "${COMPILER_BASENAME}") + ENDIF (COMPILER_BASENAME MATCHES "^(.+-)[gc]\\+\\+") +ENDIF (NOT _CMAKE_TOOLCHAIN_PREFIX) + +# if we have a MS cross compiler, it usually has a suffix, like +# e.g. clarm.exe or clmips.exe. Use this suffix for the CXX compiler too. +IF (NOT _CMAKE_TOOLCHAIN_SUFFIX) + GET_FILENAME_COMPONENT(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME) + IF (COMPILER_BASENAME MATCHES "^cl(.+)\\.exe$") + STRING(REGEX REPLACE "^cl(.+)\\.exe$" "\\1" _CMAKE_TOOLCHAIN_SUFFIX "${COMPILER_BASENAME}") + ENDIF (COMPILER_BASENAME MATCHES "^cl(.+)\\.exe$") +ENDIF (NOT _CMAKE_TOOLCHAIN_SUFFIX) + + +# some exotic compilers have different extensions (e.g. sdcc uses .rel) +# so don't overwrite it if it has been already defined by the user +IF(NOT CMAKE_CXX_OUTPUT_EXTENSION) + IF(UNIX) + SET(CMAKE_CXX_OUTPUT_EXTENSION .o) + ELSE(UNIX) + SET(CMAKE_CXX_OUTPUT_EXTENSION .obj) + ENDIF(UNIX) +ENDIF(NOT CMAKE_CXX_OUTPUT_EXTENSION) -FIND_PROGRAM(CMAKE_RANLIB NAMES ranlib) -IF(NOT CMAKE_RANLIB) - SET(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib") -ENDIF(NOT CMAKE_RANLIB) -MARK_AS_ADVANCED(CMAKE_RANLIB) # This block was used before the compiler was identified by building a # source file. Unless g++ crashes when building a small C++ @@ -101,6 +146,8 @@ IF(NOT CMAKE_CXX_COMPILER_ID_RUN) ENDIF("${CMAKE_CXX_PLATFORM_ID}" MATCHES "MinGW") ENDIF(NOT CMAKE_CXX_COMPILER_ID_RUN) +INCLUDE(CMakeFindBinUtils) + # configure all variables set in this file CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCXXCompiler.cmake.in ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCXXCompiler.cmake IMMEDIATE) diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index 15f66f95c..687bb8d18 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -66,14 +66,6 @@ ENDIF(NOT CMAKE_Fortran_COMPILER) MARK_AS_ADVANCED(CMAKE_Fortran_COMPILER) -FIND_PROGRAM(CMAKE_AR NAMES ar ) - -FIND_PROGRAM(CMAKE_RANLIB NAMES ranlib) -IF(NOT CMAKE_RANLIB) - SET(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib") -ENDIF(NOT CMAKE_RANLIB) -MARK_AS_ADVANCED(CMAKE_RANLIB) - # Build a small source file to identify the compiler. IF(${CMAKE_GENERATOR} MATCHES "Visual Studio") SET(CMAKE_Fortran_COMPILER_ID_RUN 1) @@ -130,8 +122,9 @@ IF(NOT CMAKE_Fortran_COMPILER_ID_RUN) ENDIF("${CMAKE_Fortran_PLATFORM_ID}" MATCHES "MinGW") ENDIF(NOT CMAKE_Fortran_COMPILER_ID_RUN) +INCLUDE(CMakeFindBinUtils) + # configure variables set in this file for fast reload later on CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeFortranCompiler.cmake.in ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeFortranCompiler.cmake IMMEDIATE) -MARK_AS_ADVANCED(CMAKE_AR) SET(CMAKE_Fortran_COMPILER_ENV_VAR "FC") diff --git a/Modules/CMakeDetermineSystem.cmake b/Modules/CMakeDetermineSystem.cmake index e7559e21a..3ad4a602a 100644 --- a/Modules/CMakeDetermineSystem.cmake +++ b/Modules/CMakeDetermineSystem.cmake @@ -25,37 +25,60 @@ # Ultrix ULTRIX # cygwin CYGWIN_NT-5.1 # MacOSX Darwin -IF(UNIX) - FIND_PROGRAM(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin ) - IF(CMAKE_UNAME) - EXEC_PROGRAM(uname ARGS -s OUTPUT_VARIABLE CMAKE_SYSTEM_NAME) - EXEC_PROGRAM(uname ARGS -r OUTPUT_VARIABLE CMAKE_SYSTEM_VERSION) - IF(CMAKE_SYSTEM_NAME MATCHES "Linux") - EXEC_PROGRAM(uname ARGS -m OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR - RETURN_VALUE val) - ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux") - EXEC_PROGRAM(uname ARGS -p OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR - RETURN_VALUE val) - IF("${val}" GREATER 0) + +IF(CMAKE_TOOLCHAIN_FILE) + # at first try to load it as path relative to the directory from which cmake has been run + INCLUDE("${CMAKE_BINARY_DIR}/${CMAKE_TOOLCHAIN_FILE}" OPTIONAL RESULT_VARIABLE _INCLUDED_TOOLCHAIN_FILE) + IF(NOT _INCLUDED_TOOLCHAIN_FILE) + # if the file isn't found there, check the default locations + INCLUDE("${CMAKE_TOOLCHAIN_FILE}" OPTIONAL RESULT_VARIABLE _INCLUDED_TOOLCHAIN_FILE) + ENDIF(NOT _INCLUDED_TOOLCHAIN_FILE) + + IF(_INCLUDED_TOOLCHAIN_FILE) + SET(CMAKE_TOOLCHAIN_FILE "${_INCLUDED_TOOLCHAIN_FILE}") + ELSE(_INCLUDED_TOOLCHAIN_FILE) + MESSAGE(FATAL_ERROR "Could not find toolchain file: ${CMAKE_TOOLCHAIN_FILE}") + ENDIF(_INCLUDED_TOOLCHAIN_FILE) + + IF(NOT DEFINED CMAKE_CROSSCOMPILING) + SET(CMAKE_CROSSCOMPILING TRUE) + ENDIF(NOT DEFINED CMAKE_CROSSCOMPILING) +ENDIF(CMAKE_TOOLCHAIN_FILE) + +IF(NOT CMAKE_SYSTEM_NAME) + IF(UNIX) + FIND_PROGRAM(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin ) + IF(CMAKE_UNAME) + EXEC_PROGRAM(uname ARGS -s OUTPUT_VARIABLE CMAKE_SYSTEM_NAME) + EXEC_PROGRAM(uname ARGS -r OUTPUT_VARIABLE CMAKE_SYSTEM_VERSION) + IF(CMAKE_SYSTEM_NAME MATCHES "Linux") EXEC_PROGRAM(uname ARGS -m OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR RETURN_VALUE val) + ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux") + EXEC_PROGRAM(uname ARGS -p OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR + RETURN_VALUE val) + IF("${val}" GREATER 0) + EXEC_PROGRAM(uname ARGS -m OUTPUT_VARIABLE CMAKE_SYSTEM_PROCESSOR + RETURN_VALUE val) + ENDIF("${val}" GREATER 0) + ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") + # check the return of the last uname -m or -p + IF("${val}" GREATER 0) + SET(CMAKE_SYSTEM_PROCESSOR "unknown") ENDIF("${val}" GREATER 0) - ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") - # check the return of the last uname -m or -p - IF("${val}" GREATER 0) - SET(CMAKE_SYSTEM_PROCESSOR "unknown") - ENDIF("${val}" GREATER 0) - SET(CMAKE_UNAME ${CMAKE_UNAME} CACHE INTERNAL "uname command") - # processor may have double quote in the name, and that needs to be removed - STRING(REGEX REPLACE "\"" "" CMAKE_SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}") - STRING(REGEX REPLACE "/" "_" CMAKE_SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}") - ENDIF(CMAKE_UNAME) -ELSE(UNIX) - IF(WIN32) - SET (CMAKE_SYSTEM_NAME "Windows") - SET (CMAKE_SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITECTURE}") - ENDIF(WIN32) -ENDIF(UNIX) + SET(CMAKE_UNAME ${CMAKE_UNAME} CACHE INTERNAL "uname command") + # processor may have double quote in the name, and that needs to be removed + STRING(REGEX REPLACE "\"" "" CMAKE_SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}") + STRING(REGEX REPLACE "/" "_" CMAKE_SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}") + ENDIF(CMAKE_UNAME) + ELSE(UNIX) + IF(WIN32) + SET (CMAKE_SYSTEM_NAME "Windows") + SET (CMAKE_SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITECTURE}") + ENDIF(WIN32) + ENDIF(UNIX) +ENDIF(NOT CMAKE_SYSTEM_NAME) + IF(NOT CMAKE_SYSTEM_NAME) SET(CMAKE_SYSTEM_NAME "UnknownOS") diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake new file mode 100644 index 000000000..48925bc12 --- /dev/null +++ b/Modules/CMakeFindBinUtils.cmake @@ -0,0 +1,52 @@ + +# search for additional tools required for C/C++ (and other languages ?) +# +# If the internal cmake variable _CMAKE_TOOLCHAIN_PREFIX is set, this is used +# as prefix for the tools (e.g. arm-elf-gcc etc.) +# If the cmake variable _CMAKE_TOOLCHAIN_LOCATION is set, the compiler is +# searched only there. The other tools are at first searched there, then +# also in the default locations. +# +# Sets the following variables: +# CMAKE_AR +# CMAKE_RANLIB +# CMAKE_LINKER +# CMAKE_STRIP +# CMAKE_INSTALL_NAME_TOOL + +# on UNIX, cygwin and mingw +IF(UNIX OR CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + FIND_PROGRAM(CMAKE_AR NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ar PATHS ${_CMAKE_TOOLCHAIN_LOCATION} NO_DEFAULT_PATH) + FIND_PROGRAM(CMAKE_AR NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ar) + + FIND_PROGRAM(CMAKE_RANLIB NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ranlib ${_CMAKE_TOOLCHAIN_LOCATION} NO_DEFAULT_PATH) + FIND_PROGRAM(CMAKE_RANLIB NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ranlib) + IF(NOT CMAKE_RANLIB) + SET(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib") + ENDIF(NOT CMAKE_RANLIB) + + FIND_PROGRAM(CMAKE_STRIP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}strip PATHS ${_CMAKE_TOOLCHAIN_LOCATION} NO_DEFAULT_PATH) + FIND_PROGRAM(CMAKE_STRIP NAMES ${_CMAKE_TOOLCHAIN_PREFIX}strip) + + FIND_PROGRAM(CMAKE_LINKER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ld PATHS ${_CMAKE_TOOLCHAIN_LOCATION} NO_DEFAULT_PATH) + FIND_PROGRAM(CMAKE_LINKER NAMES ${_CMAKE_TOOLCHAIN_PREFIX}ld) + + MARK_AS_ADVANCED(CMAKE_AR CMAKE_RANLIB CMAKE_STRIP CMAKE_LINKER) + +ENDIF(UNIX OR CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + +IF(APPLE) + FIND_PROGRAM(CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool PATHS ${_CMAKE_TOOLCHAIN_LOCATION} NO_DEFAULT_PATH) + FIND_PROGRAM(CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool) + + MARK_AS_ADVANCED(CMAKE_INSTALL_NAME_TOOL) +ENDIF(APPLE) + +IF("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC" OR "${CMAKE_C_COMPILER_ID}" MATCHES "MSVC") + FIND_PROGRAM(CMAKE_LINKER NAMES link PATHS ${_CMAKE_TOOLCHAIN_LOCATION} NO_DEFAULT_PATH) + FIND_PROGRAM(CMAKE_LINKER NAMES link) + + MARK_AS_ADVANCED(CMAKE_LINKER) +ENDIF("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC" OR "${CMAKE_C_COMPILER_ID}" MATCHES "MSVC") + +# maybe check for more tools ? diff --git a/Modules/CMakeLists.txt b/Modules/CMakeLists.txt index be80179a5..c3b5903e9 100644 --- a/Modules/CMakeLists.txt +++ b/Modules/CMakeLists.txt @@ -1,4 +1,6 @@ # just install the modules +# new file added, force rerunning cmake + SUBDIRS(Platform) INSTALL_FILES(${CMAKE_DATA_DIR}/Modules .*\\.cmake$) INSTALL_FILES(${CMAKE_DATA_DIR}/Modules .*\\.cpp$) diff --git a/Modules/CMakeSystem.cmake.in b/Modules/CMakeSystem.cmake.in index ad921f6be..0fbf387e4 100644 --- a/Modules/CMakeSystem.cmake.in +++ b/Modules/CMakeSystem.cmake.in @@ -1,5 +1,21 @@ -SET(CMAKE_SYSTEM "@CMAKE_SYSTEM@") -SET(CMAKE_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@") -SET(CMAKE_SYSTEM_VERSION "@CMAKE_SYSTEM_VERSION@") -SET(CMAKE_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@") +IF("@CMAKE_TOOLCHAIN_FILE@" STREQUAL "") + + SET(CMAKE_SYSTEM "@CMAKE_SYSTEM@") + SET(CMAKE_SYSTEM_NAME "@CMAKE_SYSTEM_NAME@") + SET(CMAKE_SYSTEM_VERSION "@CMAKE_SYSTEM_VERSION@") + SET(CMAKE_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@") + +ELSE("@CMAKE_TOOLCHAIN_FILE@" STREQUAL "") + + INCLUDE("@CMAKE_TOOLCHAIN_FILE@") + +# set CMAKE_SYSTEM to the CMAKE_SYSTEM_NAME + SET(CMAKE_SYSTEM ${CMAKE_SYSTEM_NAME}) +# if there is a CMAKE_SYSTEM_VERSION then add a -${CMAKE_SYSTEM_VERSION} + IF(CMAKE_SYSTEM_VERSION) + SET(CMAKE_SYSTEM ${CMAKE_SYSTEM}-${CMAKE_SYSTEM_VERSION}) + ENDIF(CMAKE_SYSTEM_VERSION) + +ENDIF("@CMAKE_TOOLCHAIN_FILE@" STREQUAL "") + SET(CMAKE_SYSTEM_LOADED 1) diff --git a/Modules/CMakeSystemSpecificInformation.cmake b/Modules/CMakeSystemSpecificInformation.cmake index 53905eb89..b2c5671dc 100644 --- a/Modules/CMakeSystemSpecificInformation.cmake +++ b/Modules/CMakeSystemSpecificInformation.cmake @@ -7,10 +7,13 @@ INCLUDE(CMakeGenericSystem) # 2. now include SystemName.cmake file to set the system specific information -SET(CMAKE_SYSTEM_INFO_FILE ${CMAKE_ROOT}/Modules/Platform/${CMAKE_SYSTEM_NAME}.cmake) -IF(EXISTS ${CMAKE_SYSTEM_INFO_FILE}) - INCLUDE(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) -ELSE(EXISTS ${CMAKE_SYSTEM_INFO_FILE}) +IF(NOT CMAKE_SYSTEM_INFO_FILE) + SET(CMAKE_SYSTEM_INFO_FILE Platform/${CMAKE_SYSTEM_NAME}) +ENDIF(NOT CMAKE_SYSTEM_INFO_FILE) + +INCLUDE(${CMAKE_SYSTEM_INFO_FILE} OPTIONAL RESULT_VARIABLE _INCLUDED_SYSTEM_INFO_FILE) + +IF(NOT _INCLUDED_SYSTEM_INFO_FILE) MESSAGE("System is unknown to cmake, create:\n${CMAKE_SYSTEM_INFO_FILE}" " to use this system, please send your config file to " "cmake@www.cmake.org so it can be added to cmake") @@ -20,7 +23,7 @@ ELSE(EXISTS ${CMAKE_SYSTEM_INFO_FILE}) MESSAGE("You CMakeCache.txt file was copied to CopyOfCMakeCache.txt. " "Please send that file to cmake@www.cmake.org.") ENDIF(EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt) -ENDIF(EXISTS ${CMAKE_SYSTEM_INFO_FILE}) +ENDIF(NOT _INCLUDED_SYSTEM_INFO_FILE) # for most systems a module is the same as a shared library diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake index 639baeec9..68c164048 100644 --- a/Modules/CMakeTestCCompiler.cmake +++ b/Modules/CMakeTestCCompiler.cmake @@ -10,7 +10,6 @@ IF(NOT CMAKE_C_COMPILER_WORKS) "#ifdef __cplusplus\n" "# error \"The CMAKE_C_COMPILER is set to a C++ compiler\"\n" "#endif\n" - "#include \n" "#if defined(__CLASSIC_C__)\n" "int main(argc, argv)\n" " int argc;\n" @@ -18,7 +17,7 @@ IF(NOT CMAKE_C_COMPILER_WORKS) "#else\n" "int main(int argc, char* argv[])\n" "#endif\n" - "{ printf(\"%s\\n\", argv[0]); return argc-1;}\n") + "{ return argc-1;}\n") TRY_COMPILE(CMAKE_C_COMPILER_WORKS ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c OUTPUT_VARIABLE OUTPUT) diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake index 8663f4159..9838bae50 100644 --- a/Modules/CTest.cmake +++ b/Modules/CTest.cmake @@ -46,6 +46,7 @@ IF(BUILD_TESTING) SET_IF_SET_AND_NOT_SET(DROP_SITE_MODE "${CTEST_DROP_SITE_MODE}") SET_IF_SET_AND_NOT_SET(DROP_LOCATION "${CTEST_DROP_LOCATION}") SET_IF_SET_AND_NOT_SET(TRIGGER_SITE "${CTEST_TRIGGER_SITE}") + SET_IF_SET_AND_NOT_SET(UPDATE_TYPE "${CTEST_UPDATE_TYPE}") ENDIF(EXISTS "${PROJECT_SOURCE_DIR}/CTestConfig.cmake") # the project can have a DartConfig.cmake file diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake index 2eb1224a1..9f4324935 100644 --- a/Modules/CheckTypeSize.cmake +++ b/Modules/CheckTypeSize.cmake @@ -13,6 +13,7 @@ # CMAKE_REQUIRED_LIBRARIES = list of libraries to link MACRO(CHECK_TYPE_SIZE TYPE VARIABLE) + IF(NOT DEFINED ${VARIABLE}) SET(CMAKE_ALLOW_UNKNOWN_VARIABLE_READ_ACCESS 1) IF("HAVE_${VARIABLE}" MATCHES "^HAVE_${VARIABLE}$") SET(CHECK_TYPE_SIZE_TYPE "${TYPE}") @@ -65,4 +66,5 @@ MACRO(CHECK_TYPE_SIZE TYPE VARIABLE) ENDIF(HAVE_${VARIABLE}) ENDIF("HAVE_${VARIABLE}" MATCHES "^HAVE_${VARIABLE}$") SET(CMAKE_ALLOW_UNKNOWN_VARIABLE_READ_ACCESS ) + ENDIF(NOT DEFINED ${VARIABLE}) ENDMACRO(CHECK_TYPE_SIZE) diff --git a/Modules/Platform/Windows-cl.cmake b/Modules/Platform/Windows-cl.cmake index 6c6cac207..658a1e34a 100644 --- a/Modules/Platform/Windows-cl.cmake +++ b/Modules/Platform/Windows-cl.cmake @@ -3,58 +3,9 @@ INCLUDE( ${CMAKE_PLATFORM_ROOT_BIN}/CMakeCPlatform.cmake OPTIONAL) # try to load any previously computed information for CXX on this platform INCLUDE( ${CMAKE_PLATFORM_ROOT_BIN}/CMakeCXXPlatform.cmake OPTIONAL) -SET(CMAKE_LIBRARY_PATH_FLAG "-LIBPATH:") -SET(CMAKE_LINK_LIBRARY_FLAG "") SET(WIN32 1) -SET(MSVC 1) -IF(CMAKE_VERBOSE_MAKEFILE) - SET(CMAKE_CL_NOLOGO) -ELSE(CMAKE_VERBOSE_MAKEFILE) - SET(CMAKE_CL_NOLOGO "/nologo") -ENDIF(CMAKE_VERBOSE_MAKEFILE) -# create a shared C++ library -SET(CMAKE_CXX_CREATE_SHARED_LIBRARY - "link ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /dll /version:. ${CMAKE_END_TEMP_FILE}") -SET(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_LIBRARY}) -# create a C shared library -SET(CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY}") - -# create a C shared module -SET(CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE}") - -# create a C++ static library -SET(CMAKE_CXX_CREATE_STATIC_LIBRARY "link /lib ${CMAKE_CL_NOLOGO} /out: ") - -# create a C static library -SET(CMAKE_C_CREATE_STATIC_LIBRARY "${CMAKE_CXX_CREATE_STATIC_LIBRARY}") - -# compile a C++ file into an object file -SET(CMAKE_CXX_COMPILE_OBJECT - " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /TP /Fo /Fd -c ${CMAKE_END_TEMP_FILE}") - -# compile a C file into an object file -SET(CMAKE_C_COMPILE_OBJECT - " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /Fo /Fd -c ${CMAKE_END_TEMP_FILE}") - - -SET(CMAKE_C_LINK_EXECUTABLE - " ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /Fe /Fd -link /implib: /version:. ${CMAKE_END_TEMP_FILE}") - -SET(CMAKE_CXX_LINK_EXECUTABLE - " ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /Fe /Fd -link /implib: /version:. ${CMAKE_END_TEMP_FILE}") - -SET(CMAKE_C_CREATE_PREPROCESSED_SOURCE - " > ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} -E ${CMAKE_END_TEMP_FILE}") - -SET(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE - " > ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /TP -E ${CMAKE_END_TEMP_FILE}") - -SET(CMAKE_C_CREATE_ASSEMBLY_SOURCE - " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /FAs /FoNUL /Fa /c ${CMAKE_END_TEMP_FILE}") - -SET(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE - " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /TP /FAs /FoNUL /Fa /c ${CMAKE_END_TEMP_FILE}") +INCLUDE(Platform/cl) SET(CMAKE_CREATE_WIN32_EXE /subsystem:windows) SET(CMAKE_CREATE_CONSOLE_EXE /subsystem:console) diff --git a/Modules/Platform/cl.cmake b/Modules/Platform/cl.cmake new file mode 100644 index 000000000..9ab3b00b5 --- /dev/null +++ b/Modules/Platform/cl.cmake @@ -0,0 +1,53 @@ +SET(CMAKE_LIBRARY_PATH_FLAG "-LIBPATH:") +SET(CMAKE_LINK_LIBRARY_FLAG "") +SET(MSVC 1) + +IF(CMAKE_VERBOSE_MAKEFILE) + SET(CMAKE_CL_NOLOGO) +ELSE(CMAKE_VERBOSE_MAKEFILE) + SET(CMAKE_CL_NOLOGO "/nologo") +ENDIF(CMAKE_VERBOSE_MAKEFILE) +# create a shared C++ library +SET(CMAKE_CXX_CREATE_SHARED_LIBRARY + "${CMAKE_LINKER} ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /out: /implib: /pdb: /dll /version:. ${CMAKE_END_TEMP_FILE}") +SET(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_LIBRARY}) + +# create a C shared library +SET(CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY}") + +# create a C shared module +SET(CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE}") + +# create a C++ static library +SET(CMAKE_CXX_CREATE_STATIC_LIBRARY "${CMAKE_LINKER} /lib ${CMAKE_CL_NOLOGO} /out: ") + +# create a C static library +SET(CMAKE_C_CREATE_STATIC_LIBRARY "${CMAKE_CXX_CREATE_STATIC_LIBRARY}") + +# compile a C++ file into an object file +SET(CMAKE_CXX_COMPILE_OBJECT + " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /TP /Fo /Fd -c ${CMAKE_END_TEMP_FILE}") + +# compile a C file into an object file +SET(CMAKE_C_COMPILE_OBJECT + " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /Fo /Fd -c ${CMAKE_END_TEMP_FILE}") + + +SET(CMAKE_C_LINK_EXECUTABLE + " ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /Fe /Fd -link /implib: /version:. ${CMAKE_END_TEMP_FILE}") + +SET(CMAKE_CXX_LINK_EXECUTABLE + " ${CMAKE_CL_NOLOGO} ${CMAKE_START_TEMP_FILE} /Fe /Fd -link /implib: /version:. ${CMAKE_END_TEMP_FILE}") + +SET(CMAKE_C_CREATE_PREPROCESSED_SOURCE + " > ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} -E ${CMAKE_END_TEMP_FILE}") + +SET(CMAKE_CXX_CREATE_PREPROCESSED_SOURCE + " > ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /TP -E ${CMAKE_END_TEMP_FILE}") + +SET(CMAKE_C_CREATE_ASSEMBLY_SOURCE + " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /FAs /FoNUL /Fa /c ${CMAKE_END_TEMP_FILE}") + +SET(CMAKE_CXX_CREATE_ASSEMBLY_SOURCE + " ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO} /TP /FAs /FoNUL /Fa /c ${CMAKE_END_TEMP_FILE}") + diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 7552f7522..e33d62bc4 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -213,51 +213,6 @@ bool cmCTestSetTestsPropertiesCommand::InitialPass( return this->TestHandler->SetTestsProperties(args); } -//---------------------------------------------------------------------- -// Try to find an executable, if found fullPath will be set to the full path -// of where it was found. The directory and filename to search for are passed -// in as well an a subdir (typically used for configuraitons such as -// Release/Debug/etc) -bool cmCTestTestHandler::TryExecutable(const char *dir, - const char *file, - std::string *fullPath, - const char *subdir) -{ - // try current directory - std::string tryPath; - if (dir && strcmp(dir,"")) - { - tryPath = dir; - tryPath += "/"; - } - - if (subdir && strcmp(subdir,"")) - { - tryPath += subdir; - tryPath += "/"; - } - - tryPath += file; - - // find the file without an executable extension - if(cmSystemTools::FileExists(tryPath.c_str())) - { - *fullPath = cmSystemTools::CollapseFullPath(tryPath.c_str()); - return true; - } - - // if not found try it with the executable extension - tryPath += cmSystemTools::GetExecutableExtension(); - if(cmSystemTools::FileExists(tryPath.c_str())) - { - *fullPath = cmSystemTools::CollapseFullPath(tryPath.c_str()); - return true; - } - - // not found at all, return false - return false; -} - //---------------------------------------------------------------------- // get the next number in a string with numbers separated by , // pos is the start of the search and pos2 is the end of the search diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 6b81f8aa3..1bac55cbe 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -103,11 +103,6 @@ public: cmCTestTestProperties* Properties; }; - // useful function for looking for a test - static bool TryExecutable(const char *dir, const char *file, - std::string *fullPath, - const char *subdir); - // add configuraitons to a search path for an executable static void AddConfigurations(cmCTest *ctest, std::vector &attempted, diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 2cb3bf2a0..7128ca5b2 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1018,479 +1018,16 @@ bool cmFileInstaller::InstallDirectory(const char* source, } //---------------------------------------------------------------------------- -bool cmFileCommand::HandleInstallCommand( - std::vector const& args) +void cmFileCommand::HandleInstallPermissions(cmFileInstaller& installer, + mode_t& permissions_file, + mode_t& permissions_dir, + int itype, + bool use_given_permissions_file, + bool use_given_permissions_dir, + bool use_source_permissions) const { - if ( args.size() < 6 ) - { - this->SetError("called with incorrect number of arguments"); - return false; - } - - // Construct a file installer object. - cmFileInstaller installer(this, this->Makefile); - - std::string rename = ""; - std::string destination = ""; - std::string stype = "FILES"; - const char* destdir = cmSystemTools::GetEnv("DESTDIR"); - - std::set components; - std::set configurations; - std::vector files; - int itype = cmTarget::INSTALL_FILES; - - std::vector::size_type i = 0; - i++; // Get rid of subcommand - - std::map properties; - - bool doing_files = false; - bool doing_properties = false; - bool doing_permissions_file = false; - bool doing_permissions_dir = false; - bool doing_permissions_match = false; - bool doing_components = false; - bool doing_configurations = false; - bool use_given_permissions_file = false; - bool use_given_permissions_dir = false; - bool use_source_permissions = false; - mode_t permissions_file = 0; - mode_t permissions_dir = 0; - bool optional = false; - cmFileInstaller::MatchRule* current_match_rule = 0; - for ( ; i != args.size(); ++i ) - { - const std::string* cstr = &args[i]; - if ( *cstr == "DESTINATION" && i < args.size()-1 ) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - i++; - destination = args[i]; - doing_files = false; - doing_properties = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = false; - } - else if ( *cstr == "TYPE" && i < args.size()-1 ) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - i++; - stype = args[i]; - if ( args[i+1] == "OPTIONAL" ) - { - i++; - optional = true; - } - doing_properties = false; - doing_files = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = false; - } - else if ( *cstr == "RENAME" && i < args.size()-1 ) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - i++; - rename = args[i]; - doing_properties = false; - doing_files = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = false; - } - else if ( *cstr == "REGEX" && i < args.size()-1 ) - { - i++; - installer.MatchRules.push_back(cmFileInstaller::MatchRule(args[i])); - current_match_rule = &*(installer.MatchRules.end()-1); - if(!current_match_rule->Regex.is_valid()) - { - cmOStringStream e; - e << "INSTALL could not compile REGEX \"" << args[i] << "\"."; - this->SetError(e.str().c_str()); - return false; - } - doing_properties = false; - doing_files = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = false; - } - else if ( *cstr == "EXCLUDE" ) - { - // Add this property to the current match rule. - if(!current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" - << *cstr << "\" before a REGEX is given."; - this->SetError(e.str().c_str()); - return false; - } - current_match_rule->Properties.Exclude = true; - doing_permissions_match = true; - } - else if ( *cstr == "PROPERTIES" ) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - doing_properties = true; - doing_files = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = false; - } - else if ( *cstr == "PERMISSIONS" ) - { - if(current_match_rule) - { - doing_permissions_match = true; - doing_permissions_file = false; - } - else - { - doing_permissions_match = false; - doing_permissions_file = true; - use_given_permissions_file = true; - } - doing_properties = false; - doing_files = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = false; - } - else if ( *cstr == "DIR_PERMISSIONS" ) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - use_given_permissions_dir = true; - doing_properties = false; - doing_files = false; - doing_permissions_file = false; - doing_permissions_dir = true; - doing_components = false; - doing_configurations = false; - } - else if ( *cstr == "USE_SOURCE_PERMISSIONS" ) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - doing_properties = false; - doing_files = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = false; - use_source_permissions = true; - } - else if ( *cstr == "COMPONENTS" ) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - doing_properties = false; - doing_files = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = true; - doing_configurations = false; - } - else if ( *cstr == "CONFIGURATIONS" ) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - doing_properties = false; - doing_files = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = true; - } - else if ( *cstr == "FILES" && !doing_files) - { - if(current_match_rule) - { - cmOStringStream e; - e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; - this->SetError(e.str().c_str()); - return false; - } - - doing_files = true; - doing_properties = false; - doing_permissions_file = false; - doing_permissions_dir = false; - doing_components = false; - doing_configurations = false; - } - else if ( doing_properties && i < args.size()-1 ) - { - properties[args[i]] = args[i+1].c_str(); - i++; - } - else if ( doing_files ) - { - files.push_back(*cstr); - } - else if ( doing_components ) - { - components.insert(*cstr); - } - else if ( doing_configurations ) - { - configurations.insert(cmSystemTools::UpperCase(*cstr)); - } - else if(doing_permissions_file) - { - if(!installer.CheckPermissions(args[i], permissions_file)) - { - return false; - } - } - else if(doing_permissions_dir) - { - if(!installer.CheckPermissions(args[i], permissions_dir)) - { - return false; - } - } - else if(doing_permissions_match) - { - if(!installer.CheckPermissions( - args[i], current_match_rule->Properties.Permissions)) - { - return false; - } - } - else - { - this->SetError("called with inappropriate arguments"); - return false; - } - } - - if ( destination.size() < 2 ) - { - this->SetError("called with inapropriate arguments. " - "No DESTINATION provided or ."); - return false; - } - - // Check for component-specific installation. - const char* cmake_install_component = - this->Makefile->GetDefinition("CMAKE_INSTALL_COMPONENT"); - if(cmake_install_component && *cmake_install_component) - { - // This install rule applies only if it is associated with the - // current component. - if(components.find(cmake_install_component) == components.end()) - { - return true; - } - } - - // Check for configuration-specific installation. - if(!configurations.empty()) - { - std::string cmake_install_configuration = - cmSystemTools::UpperCase( - this->Makefile->GetSafeDefinition("CMAKE_INSTALL_CONFIG_NAME")); - if(cmake_install_configuration.empty()) - { - // No configuration specified for installation but this install - // rule is configuration-specific. Skip it. - return true; - } - else if(configurations.find(cmake_install_configuration) == - configurations.end()) - { - // This rule is specific to a configuration not being installed. - return true; - } - } - - if ( destdir && *destdir ) - { - std::string sdestdir = destdir; - cmSystemTools::ConvertToUnixSlashes(sdestdir); - - char ch1 = destination[0]; - char ch2 = destination[1]; - char ch3 = 0; - if ( destination.size() > 2 ) - { - ch3 = destination[2]; - } - int skip = 0; - if ( ch1 != '/' ) - { - int relative = 0; - if ( ( ch1 >= 'a' && ch1 <= 'z' || ch1 >= 'A' && ch1 <= 'Z' ) && - ch2 == ':' ) - { - // Assume windows - // let's do some destdir magic: - skip = 2; - if ( ch3 != '/' ) - { - relative = 1; - } - } - else - { - relative = 1; - } - if ( relative ) - { - // This is relative path on unix or windows. Since we are doing - // destdir, this case does not make sense. - this->SetError("called with relative DESTINATION. This " - "does not make sense when using DESTDIR. Specify " - "absolute path or remove DESTDIR environment variable."); - return false; - } - } - else - { - if ( ch2 == '/' ) - { - // looks like a network path. - this->SetError("called with network path DESTINATION. This " - "does not make sense when using DESTDIR. Specify local " - "absolute path or remove DESTDIR environment variable."); - return false; - } - } - destination = sdestdir + (destination.c_str() + skip); - installer.DestDirLength = int(sdestdir.size()); - } - - if ( files.size() == 0 ) - { - this->SetError( - "called with inapropriate arguments. No FILES provided."); - return false; - } - if ( stype == "EXECUTABLE" ) - { - itype = cmTarget::EXECUTABLE; - } - else if ( stype == "PROGRAM" ) - { - itype = cmTarget::INSTALL_PROGRAMS; - } - else if ( stype == "STATIC_LIBRARY" ) - { - itype = cmTarget::STATIC_LIBRARY; - } - else if ( stype == "SHARED_LIBRARY" ) - { - itype = cmTarget::SHARED_LIBRARY; - } - else if ( stype == "MODULE" ) - { - itype = cmTarget::MODULE_LIBRARY; - } - else if ( stype == "DIRECTORY" ) - { - itype = cmTarget::INSTALL_DIRECTORY; - } - - if ( !cmSystemTools::FileExists(destination.c_str()) ) - { - if ( !cmSystemTools::MakeDirectory(destination.c_str()) ) - { - std::string errstring = "cannot create directory: " + destination + - ". Maybe need administrative privileges."; - this->SetError(errstring.c_str()); - return false; - } - } - if ( !cmSystemTools::FileIsDirectory(destination.c_str()) ) - { - std::string errstring = "INSTALL destination: " + destination + - " is not a directory."; - this->SetError(errstring.c_str()); - return false; - } - - // Check rename form. - if(!rename.empty()) - { - if(itype != cmTarget::INSTALL_FILES && - itype != cmTarget::INSTALL_PROGRAMS) - { - this->SetError("INSTALL option RENAME may be used only with " - "FILES or PROGRAMS."); - return false; - } - if(files.size() > 1) - { - this->SetError("INSTALL option RENAME may be used only with one file."); - return false; - } - } - // Choose a default for shared library permissions. bool install_so_no_exe = this->Makefile->IsOn("CMAKE_INSTALL_SO_NO_EXE"); - // If file permissions were not specified set default permissions // for this target type. if(!use_given_permissions_file && !use_source_permissions) @@ -1545,10 +1082,543 @@ bool cmFileCommand::HandleInstallCommand( permissions_dir |= mode_world_read; permissions_dir |= mode_world_execute; } - // Set the installer permissions. installer.FilePermissions = permissions_file; installer.DirPermissions = permissions_dir; +} + +//---------------------------------------------------------------------------- +void cmFileCommand::GetTargetTypeFromString(const std::string& stype, int& itype) const +{ + if ( stype == "EXECUTABLE" ) + { + itype = cmTarget::EXECUTABLE; + } + else if ( stype == "PROGRAM" ) + { + itype = cmTarget::INSTALL_PROGRAMS; + } + else if ( stype == "STATIC_LIBRARY" ) + { + itype = cmTarget::STATIC_LIBRARY; + } + else if ( stype == "SHARED_LIBRARY" ) + { + itype = cmTarget::SHARED_LIBRARY; + } + else if ( stype == "MODULE" ) + { + itype = cmTarget::MODULE_LIBRARY; + } + else if ( stype == "DIRECTORY" ) + { + itype = cmTarget::INSTALL_DIRECTORY; + } +} + + +//---------------------------------------------------------------------------- +bool cmFileCommand::HandleInstallDestination(cmFileInstaller& installer, std::string& destination) +{ + if ( destination.size() < 2 ) + { + this->SetError("called with inapropriate arguments. " + "No DESTINATION provided or ."); + return false; + } + + const char* destdir = cmSystemTools::GetEnv("DESTDIR"); + if ( destdir && *destdir ) + { + std::string sdestdir = destdir; + cmSystemTools::ConvertToUnixSlashes(sdestdir); + + char ch1 = destination[0]; + char ch2 = destination[1]; + char ch3 = 0; + if ( destination.size() > 2 ) + { + ch3 = destination[2]; + } + int skip = 0; + if ( ch1 != '/' ) + { + int relative = 0; + if ( ( ch1 >= 'a' && ch1 <= 'z' || ch1 >= 'A' && ch1 <= 'Z' ) && + ch2 == ':' ) + { + // Assume windows + // let's do some destdir magic: + skip = 2; + if ( ch3 != '/' ) + { + relative = 1; + } + } + else + { + relative = 1; + } + if ( relative ) + { + // This is relative path on unix or windows. Since we are doing + // destdir, this case does not make sense. + this->SetError("called with relative DESTINATION. This " + "does not make sense when using DESTDIR. Specify " + "absolute path or remove DESTDIR environment variable."); + return false; + } + } + else + { + if ( ch2 == '/' ) + { + // looks like a network path. + this->SetError("called with network path DESTINATION. This " + "does not make sense when using DESTDIR. Specify local " + "absolute path or remove DESTDIR environment variable."); + return false; + } + } + destination = sdestdir + (destination.c_str() + skip); + installer.DestDirLength = int(sdestdir.size()); + } + + if ( !cmSystemTools::FileExists(destination.c_str()) ) + { + if ( !cmSystemTools::MakeDirectory(destination.c_str()) ) + { + std::string errstring = "cannot create directory: " + destination + + ". Maybe need administrative privileges."; + this->SetError(errstring.c_str()); + return false; + } + } + if ( !cmSystemTools::FileIsDirectory(destination.c_str()) ) + { + std::string errstring = "INSTALL destination: " + destination + + " is not a directory."; + this->SetError(errstring.c_str()); + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +bool cmFileCommand::HandleInstallCommand(std::vector const& args) +{ + if ( args.size() < 6 ) + { + this->SetError("called with incorrect number of arguments"); + return false; + } + + // Construct a file installer object. + cmFileInstaller installer(this, this->Makefile); + + std::string rename = ""; + std::string destination = ""; + + std::set components; + std::set configurations; + std::vector files; + int itype = cmTarget::INSTALL_FILES; + + std::map properties; + bool optional = false; + bool result = this->ParseInstallArgs(args, installer, components, + configurations, properties, + itype, rename, destination, files, + optional); + if (result == true) + { + result = this->DoInstall(installer, components, configurations, properties, + itype, rename, destination, files, optional); + } + return result; +} + +//---------------------------------------------------------------------------- +bool cmFileCommand::ParseInstallArgs(std::vector const& args, + cmFileInstaller& installer, + std::set& components, + std::set& configurations, + std::map& properties, + int& itype, + std::string& rename, + std::string& destination, + std::vector& files, + bool& optional) +{ + std::string stype = "FILES"; + bool doing_files = false; + bool doing_properties = false; + bool doing_permissions_file = false; + bool doing_permissions_dir = false; + bool doing_permissions_match = false; + bool doing_components = false; + bool doing_configurations = false; + bool use_given_permissions_file = false; + bool use_given_permissions_dir = false; + bool use_source_permissions = false; + mode_t permissions_file = 0; + mode_t permissions_dir = 0; + + cmFileInstaller::MatchRule* current_match_rule = 0; + std::vector::size_type i = 0; + i++; // Get rid of subcommand + for ( ; i != args.size(); ++i ) + { + const std::string* cstr = &args[i]; + if ( *cstr == "DESTINATION" && i < args.size()-1 ) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + i++; + destination = args[i]; + doing_files = false; + doing_properties = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = false; + } + else if ( *cstr == "TYPE" && i < args.size()-1 ) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + i++; + stype = args[i]; + if ( args[i+1] == "OPTIONAL" ) + { + i++; + optional = true; + } + doing_properties = false; + doing_files = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = false; + } + else if ( *cstr == "RENAME" && i < args.size()-1 ) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + i++; + rename = args[i]; + doing_properties = false; + doing_files = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = false; + } + else if ( *cstr == "REGEX" && i < args.size()-1 ) + { + i++; + installer.MatchRules.push_back(cmFileInstaller::MatchRule(args[i])); + current_match_rule = &*(installer.MatchRules.end()-1); + if(!current_match_rule->Regex.is_valid()) + { + cmOStringStream e; + e << "INSTALL could not compile REGEX \"" << args[i] << "\"."; + this->SetError(e.str().c_str()); + return false; + } + doing_properties = false; + doing_files = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = false; + } + else if ( *cstr == "EXCLUDE" ) + { + // Add this property to the current match rule. + if(!current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" + << *cstr << "\" before a REGEX is given."; + this->SetError(e.str().c_str()); + return false; + } + current_match_rule->Properties.Exclude = true; + doing_permissions_match = true; + } + else if ( *cstr == "PROPERTIES" ) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + doing_properties = true; + doing_files = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = false; + } + else if ( *cstr == "PERMISSIONS" ) + { + if(current_match_rule) + { + doing_permissions_match = true; + doing_permissions_file = false; + } + else + { + doing_permissions_match = false; + doing_permissions_file = true; + use_given_permissions_file = true; + } + doing_properties = false; + doing_files = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = false; + } + else if ( *cstr == "DIR_PERMISSIONS" ) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + use_given_permissions_dir = true; + doing_properties = false; + doing_files = false; + doing_permissions_file = false; + doing_permissions_dir = true; + doing_components = false; + doing_configurations = false; + } + else if ( *cstr == "USE_SOURCE_PERMISSIONS" ) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + doing_properties = false; + doing_files = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = false; + use_source_permissions = true; + } + else if ( *cstr == "COMPONENTS" ) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + doing_properties = false; + doing_files = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = true; + doing_configurations = false; + } + else if ( *cstr == "CONFIGURATIONS" ) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + doing_properties = false; + doing_files = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = true; + } + else if ( *cstr == "FILES" && !doing_files) + { + if(current_match_rule) + { + cmOStringStream e; + e << "INSTALL does not allow \"" << *cstr << "\" after REGEX."; + this->SetError(e.str().c_str()); + return false; + } + + doing_files = true; + doing_properties = false; + doing_permissions_file = false; + doing_permissions_dir = false; + doing_components = false; + doing_configurations = false; + } + else if ( doing_properties && i < args.size()-1 ) + { + properties[args[i]] = args[i+1].c_str(); + i++; + } + else if ( doing_files ) + { + files.push_back(*cstr); + } + else if ( doing_components ) + { + components.insert(*cstr); + } + else if ( doing_configurations ) + { + configurations.insert(cmSystemTools::UpperCase(*cstr)); + } + else if(doing_permissions_file) + { + if(!installer.CheckPermissions(args[i], permissions_file)) + { + return false; + } + } + else if(doing_permissions_dir) + { + if(!installer.CheckPermissions(args[i], permissions_dir)) + { + return false; + } + } + else if(doing_permissions_match) + { + if(!installer.CheckPermissions( + args[i], current_match_rule->Properties.Permissions)) + { + return false; + } + } + else + { + this->SetError("called with inappropriate arguments"); + return false; + } + } + + // now check and postprocess what has been parsed + if ( files.size() == 0 ) + { + this->SetError( + "called with inapropriate arguments. No FILES provided."); + return false; + } + + // Check rename form. + if(!rename.empty()) + { + if(itype != cmTarget::INSTALL_FILES && + itype != cmTarget::INSTALL_PROGRAMS) + { + this->SetError("INSTALL option RENAME may be used only with " + "FILES or PROGRAMS."); + return false; + } + if(files.size() > 1) + { + this->SetError("INSTALL option RENAME may be used only with one file."); + return false; + } + } + + if (this->HandleInstallDestination(installer, destination) == false) + { + return false; + } + + this->GetTargetTypeFromString(stype, itype); + + this->HandleInstallPermissions(installer, + permissions_file, + permissions_dir, + itype, + use_given_permissions_file, + use_given_permissions_dir, + use_source_permissions); + + return true; +} + +//---------------------------------------------------------------------------- +bool cmFileCommand::DoInstall( cmFileInstaller& installer, + const std::set& components, + const std::set& configurations, + std::map& properties, + const int itype, + const std::string& rename, + const std::string& destination, + const std::vector& files, + const bool optional) +{ + // Check for component-specific installation. + const char* cmake_install_component = + this->Makefile->GetDefinition("CMAKE_INSTALL_COMPONENT"); + if(cmake_install_component && *cmake_install_component) + { + // This install rule applies only if it is associated with the + // current component. + if(components.find(cmake_install_component) == components.end()) + { + return true; + } + } + + // Check for configuration-specific installation. + if(!configurations.empty()) + { + std::string cmake_install_configuration = cmSystemTools::UpperCase( + this->Makefile->GetSafeDefinition("CMAKE_INSTALL_CONFIG_NAME")); + if(cmake_install_configuration.empty()) + { + // No configuration specified for installation but this install + // rule is configuration-specific. Skip it. + return true; + } + else if(configurations.find(cmake_install_configuration) == + configurations.end()) + { + // This rule is specific to a configuration not being installed. + return true; + } + } // Check whether files should be copied always or only if they have // changed. @@ -1556,7 +1626,7 @@ bool cmFileCommand::HandleInstallCommand( cmSystemTools::IsOn(cmSystemTools::GetEnv("CMAKE_INSTALL_ALWAYS")); // Handle each file listed. - for ( i = 0; i < files.size(); i ++ ) + for (std::vector::size_type i = 0; i < files.size(); i ++ ) { // Split the input file into its directory and name components. std::vector fromPathComponents; @@ -1704,24 +1774,6 @@ bool cmFileCommand::HandleInstallCommand( { return false; } - - // Perform post-installation processing on the file depending - // on its type. -#if defined(__APPLE_CC__) - // Static libraries need ranlib on this platform. - if(itype == cmTarget::STATIC_LIBRARY) - { - std::string ranlib = "ranlib "; - ranlib += cmSystemTools::ConvertToOutputPath(toFile.c_str()); - if(!cmSystemTools::RunSingleCommand(ranlib.c_str())) - { - std::string err = "ranlib failed: "; - err += ranlib; - this->SetError(err.c_str()); - return false; - } - } -#endif } else if(!optional) { diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h index d6327b140..f758151d6 100644 --- a/Source/cmFileCommand.h +++ b/Source/cmFileCommand.h @@ -19,6 +19,8 @@ #include "cmCommand.h" +struct cmFileInstaller; + /** \class cmFileCommand * \brief Command for manipulation of files * @@ -146,11 +148,45 @@ protected: bool HandleStringsCommand(std::vector const& args); bool HandleGlobCommand(std::vector const& args, bool recurse); bool HandleMakeDirectoryCommand(std::vector const& args); - bool HandleInstallCommand(std::vector const& args); + bool HandleRelativePathCommand(std::vector const& args); bool HandleCMakePathCommand(std::vector const& args, bool nativePath); void ComputeVersionedName(std::string& name, const char* version); + + // FILE(INSTALL ...) related functions + bool HandleInstallCommand(std::vector const& args); + bool ParseInstallArgs(std::vector const& args, + cmFileInstaller& installer, + std::set& components, + std::set& configurations, + std::map& properties, + int& itype, + std::string& destination, + std::string& rename, + std::vector& files, + bool& optional + ); + bool DoInstall(cmFileInstaller& installer, + const std::set& components, + const std::set& configurations, + std::map& properties, + const int itype, + const std::string& rename, + const std::string& destination, + const std::vector& files, + const bool optional + ); + void GetTargetTypeFromString(const std::string& stype, int& itype) const; + bool HandleInstallDestination(cmFileInstaller& installer, + std::string& destination); + void HandleInstallPermissions(cmFileInstaller& installer, + mode_t& permissions_file, + mode_t& permissions_dir, + int itype, + bool use_given_permissions_file, + bool use_given_permissions_dir, + bool use_source_permissions) const; }; diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index d2ac606c1..0c3ad8664 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -25,6 +25,7 @@ cmFindBase::cmFindBase() this->NoCMakeEnvironmentPath = false; this->NoSystemEnvironmentPath = false; this->NoCMakeSystemPath = false; + this->FindRootPathMode = RootPathModeBoth; // default is to search frameworks first on apple #if defined(__APPLE__) this->SearchFrameworkFirst = true; @@ -250,6 +251,24 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) return true; } this->AlreadyInCache = false; + + + std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_"; + findRootPathVar += this->CMakePathName; + std::string rootPathMode = this->Makefile->GetSafeDefinition(findRootPathVar.c_str()); + if (rootPathMode=="NEVER") + { + this->FindRootPathMode = RootPathModeNoRootPath; + } + else if (rootPathMode=="ONLY") + { + this->FindRootPathMode = RootPathModeOnlyRootPath; + } + else if (rootPathMode=="BOTH") + { + this->FindRootPathMode = RootPathModeBoth; + } + std::vector userPaths; std::string doc; bool doingNames = true; // assume it starts with a name @@ -328,6 +347,21 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) doingNames = false; this->NoCMakeSystemPath = true; } + else if (args[j] == "NO_CMAKE_FIND_ROOT_PATH") + { + compatibility = false; + this->FindRootPathMode = RootPathModeNoRootPath; + } + else if (args[j] == "ONLY_CMAKE_FIND_ROOT_PATH") + { + compatibility = false; + this->FindRootPathMode = RootPathModeOnlyRootPath; + } + else if (args[j] == "CMAKE_FIND_ROOT_PATH_BOTH") + { + compatibility = false; + this->FindRootPathMode = RootPathModeBoth; + } else { if(doingNames) @@ -358,7 +392,7 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) if(this->VariableDocumentation.size() == 0) { - this->VariableDocumentation = "Whare can "; + this->VariableDocumentation = "Where can "; if(this->Names.size() == 0) { this->VariableDocumentation += "the (unknown) library be found"; @@ -392,6 +426,8 @@ bool cmFindBase::ParseArguments(std::vector const& argsIn) } } this->ExpandPaths(userPaths); + + this->HandleCMakeFindRootPath(); return true; } @@ -413,7 +449,7 @@ void cmFindBase::ExpandPaths(std::vector userPaths) !(this->SearchFrameworkOnly || this->SearchAppBundleOnly)) { // Add CMAKE_*_PATH environment variables - this->AddEnvironmentVairables(); + this->AddEnvironmentVariables(); } if(!this->NoCMakePath && !(this->SearchFrameworkOnly || this->SearchAppBundleOnly)) @@ -421,13 +457,13 @@ void cmFindBase::ExpandPaths(std::vector userPaths) // Add CMake varibles of the same name as the previous environment // varibles CMAKE_*_PATH to be used most of the time with -D // command line options - this->AddCMakeVairables(); + this->AddCMakeVariables(); } if(!this->NoSystemEnvironmentPath && !(this->SearchFrameworkOnly || this->SearchAppBundleOnly)) { // add System environment PATH and (LIB or INCLUDE) - this->AddSystemEnvironmentVairables(); + this->AddSystemEnvironmentVariables(); } if(!this->NoCMakeSystemPath && !(this->SearchFrameworkOnly || this->SearchAppBundleOnly)) @@ -453,7 +489,46 @@ void cmFindBase::ExpandPaths(std::vector userPaths) this->AddPaths(paths); } -void cmFindBase::AddEnvironmentVairables() +void cmFindBase::HandleCMakeFindRootPath() +{ + if (this->FindRootPathMode == RootPathModeNoRootPath) + { + return; + } + + const char* rootPath = this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH"); + if ((rootPath == 0) || (strlen(rootPath) == 0)) + { + return; + } + + std::vector prefixes; + cmSystemTools::ExpandListArgument(rootPath, prefixes); + + std::vector unprefixedPaths=this->SearchPaths; + this->SearchPaths.clear(); + + for (std::vector::const_iterator prefixIt = prefixes.begin(); + prefixIt != prefixes.end(); + ++prefixIt ) + { + for (std::vector::const_iterator it = unprefixedPaths.begin(); + it != unprefixedPaths.end(); + ++it ) + { + std::string prefixedDir=*prefixIt; + prefixedDir+=*it; + this->SearchPaths.push_back(prefixedDir); + } + } + + if (this->FindRootPathMode == RootPathModeBoth) + { + this->AddPaths(unprefixedPaths); + } +} + +void cmFindBase::AddEnvironmentVariables() { std::string var = "CMAKE_"; var += this->CMakePathName; @@ -547,7 +622,7 @@ void cmFindBase::AddAppBundlePaths() this->AddPaths(paths); } -void cmFindBase::AddCMakeVairables() +void cmFindBase::AddCMakeVariables() { std::string var = "CMAKE_"; var += this->CMakePathName; @@ -576,7 +651,7 @@ void cmFindBase::AddCMakeVairables() this->AddPaths(paths); } -void cmFindBase::AddSystemEnvironmentVairables() +void cmFindBase::AddSystemEnvironmentVariables() { // Add LIB or INCLUDE std::vector paths; diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index e9fae389a..95fc25895 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -39,16 +39,20 @@ public: virtual const char* GetFullDocumentation() {return this->GenericDocumentation.c_str();} + enum RootPathMode { RootPathModeBoth, RootPathModeOnlyRootPath, RootPathModeNoRootPath }; + protected: void PrintFindStuff(); void ExpandPaths(std::vector userPaths); + void HandleCMakeFindRootPath(); + // add to the SearchPaths void AddPaths(std::vector& paths); void AddFrameWorkPaths(); void AddAppBundlePaths(); - void AddEnvironmentVairables(); - void AddCMakeVairables(); - void AddSystemEnvironmentVairables(); + void AddEnvironmentVariables(); + void AddCMakeVariables(); + void AddSystemEnvironmentVariables(); void AddCMakeSystemVariables(); void ExpandRegistryAndCleanPath(std::vector& paths); // see if the VariableName is already set in the cache, @@ -75,6 +79,7 @@ protected: bool NoCMakeEnvironmentPath; bool NoSystemEnvironmentPath; bool NoCMakeSystemPath; + RootPathMode FindRootPathMode; bool SearchFrameworkFirst; bool SearchFrameworkOnly; diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index 5cab7d394..8b63fe970 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -20,21 +20,55 @@ // cmIncludeCommand bool cmIncludeCommand::InitialPass(std::vector const& args) { - if (args.size()< 1 || args.size() > 2) + if (args.size()< 1 || args.size() > 4) { this->SetError("called with wrong number of arguments. " "Include only takes one file."); return false; } bool optional = false; - - std::string fname = args[0].c_str(); - - if(args.size() == 2) - { - optional = args[1] == "OPTIONAL"; - } + std::string fname = args[0]; + std::string resultVarName; + for (unsigned int i=1; iSetError("called with invalid arguments: OPTIONAL used twice"); + return false; + } + optional = true; + } + else if(args[i] == "RESULT_VARIABLE") + { + if (resultVarName.size() > 0) + { + this->SetError("called with invalid arguments: " + "only one result variable allowed"); + return false; + } + if(++i < args.size()) + { + resultVarName = args[i]; + } + else + { + this->SetError("called with no value for RESULT_VARIABLE."); + return false; + } + } + else if(i > 1) // compat.: in previous cmake versions the second + // parameter was ignore if it wasn't "OPTIONAL" + { + std::string errorText = "called with invalid argument: "; + errorText += args[i]; + this->SetError(errorText.c_str()); + return false; + } + } + if(!cmSystemTools::FileIsFullPath(fname.c_str())) { // Not a path. Maybe module. @@ -46,9 +80,18 @@ bool cmIncludeCommand::InitialPass(std::vector const& args) fname = mfile.c_str(); } } + std::string fullFilePath; bool readit = this->Makefile->ReadListFile( this->Makefile->GetCurrentListFile(), - fname.c_str() ); + fname.c_str(), &fullFilePath ); + + // add the location of the included file if a result variable was given + if (resultVarName.size()) + { + this->Makefile->AddDefinition(resultVarName.c_str(), + readit?fullFilePath.c_str():"NOTFOUND"); + } + if(!optional && !readit && !cmSystemTools::GetFatalErrorOccured()) { std::string m = "Could not find include file: "; diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h index 8fc9833bd..428df0caf 100644 --- a/Source/cmIncludeCommand.h +++ b/Source/cmIncludeCommand.h @@ -68,12 +68,14 @@ public: virtual const char* GetFullDocumentation() { return - " INCLUDE(file1 [OPTIONAL])\n" - " INCLUDE(module [OPTIONAL])\n" + " INCLUDE(file1 [OPTIONAL] [RESULT_VARIABLE ])\n" + " INCLUDE(module [OPTIONAL] [RESULT_VARIABLE ])\n" "Reads CMake listfile code from the given file. Commands in the file " "are processed immediately as if they were written in place of the " "INCLUDE command. If OPTIONAL is present, then no error " - "is raised if the file does not exist.\n" + "is raised if the file does not exist. If RESULT_VARIABLE is given " + "the variable will be set to the full filename which " + "has been included or NOTFOUND if it failed.\n" "If a module is specified instead of a file, the file with name " ".cmake is searched in the CMAKE_MODULE_PATH."; } diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index fd92eab22..bd3f86432 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -19,7 +19,6 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmTarget.h" #include "cmake.h" //---------------------------------------------------------------------------- @@ -171,12 +170,21 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os) no_rename, literal_args.c_str()); // Fix the install_name settings in installed binaries. - if(type == cmTarget::SHARED_LIBRARY || + if((type == cmTarget::SHARED_LIBRARY || type == cmTarget::MODULE_LIBRARY || - type == cmTarget::EXECUTABLE) + type == cmTarget::EXECUTABLE) && + this->Target->GetMakefile()->IsSet("CMAKE_INSTALL_NAME_TOOL")) { this->AddInstallNamePatchRule(os, destination.c_str()); } + + std::string destinationFilename = destination; + destinationFilename += "/"; + destinationFilename += cmSystemTools::GetFilenameName(fromFile); + + this->AddRanlibRule(os, type, destinationFilename); + + this->AddStripRule(os, destinationFilename); } //---------------------------------------------------------------------------- @@ -417,7 +425,9 @@ void cmInstallTargetGenerator component_test += this->Component; component_test += ")$\""; os << "IF(" << component_test << ")\n"; - os << " EXECUTE_PROCESS(COMMAND install_name_tool"; + os << " EXECUTE_PROCESS(COMMAND \""; + os <Target->GetMakefile()->GetDefinition("CMAKE_INSTALL_NAME_TOOL"); + os << "\""; if(!new_id.empty()) { os << "\n -id \"" << new_id << "\""; @@ -433,3 +443,54 @@ void cmInstallTargetGenerator os << "ENDIF(" << component_test << ")\n"; } } + +void cmInstallTargetGenerator::AddStripRule(std::ostream& os, + const std::string& destinationFilename) +{ + + // Don't handle OSX Bundles. + if(this->Target->GetMakefile()->IsOn("APPLE") && + this->Target->GetPropertyAsBool("MACOSX_BUNDLE")) + { + return; + } + + if(! this->Target->GetMakefile()->IsSet("CMAKE_STRIP")) + { + return; + } + + os << "IF(CMAKE_INSTALL_DO_STRIP)\n"; + os << " EXECUTE_PROCESS(COMMAND \""; + os << this->Target->GetMakefile()->GetDefinition("CMAKE_STRIP"); + os << "\" \"$ENV{DESTDIR}" << destinationFilename << "\" )\n"; + os << "ENDIF(CMAKE_INSTALL_DO_STRIP)\n"; +} + +void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, + cmTarget::TargetType type, + const std::string& destinationFilename) +{ + // Static libraries need ranlib on this platform. + if(type != cmTarget::STATIC_LIBRARY) + { + return; + } + + // Perform post-installation processing on the file depending + // on its type. + if(!this->Target->GetMakefile()->IsOn("APPLE")) + { + return; + } + + std::string ranlib = this->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB"); + if (!ranlib.size()) + { + return; + } + + os << "EXECUTE_PROCESS(COMMAND \""; + os << ranlib; + os << "\" \"$ENV{DESTDIR}" << destinationFilename << "\" )\n"; +} diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 77f9fec46..c7dcec573 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -18,8 +18,7 @@ #define cmInstallTargetGenerator_h #include "cmInstallGenerator.h" - -class cmTarget; +#include "cmTarget.h" /** \class cmInstallTargetGenerator * \brief Generate target installation rules. @@ -45,6 +44,10 @@ protected: std::string GetScriptReference(cmTarget* target, const char* place, bool useSOName); void AddInstallNamePatchRule(std::ostream& os, const char* destination); + void AddStripRule(std::ostream& os, const std::string& destinationFilename); + void AddRanlibRule(std::ostream& os, cmTarget::TargetType type, + const std::string& destinationFilename); + cmTarget* Target; std::string Destination; bool ImportLibrary; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 4cc265f21..2d345df70 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -370,7 +370,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff) // Parse the given CMakeLists.txt file executing all commands // bool cmMakefile::ReadListFile(const char* filename_in, - const char *external_in) + const char *external_in, + std::string* fullPath) { std::string currentParentFile = this->GetSafeDefinition("CMAKE_PARENT_LIST_FILE"); @@ -446,12 +447,19 @@ bool cmMakefile::ReadListFile(const char* filename_in, // push the listfile onto the stack this->ListFileStack.push_back(filenametoread); - + if(fullPath!=0) + { + *fullPath=filenametoread; + } cmListFile cacheFile; if( !cacheFile.ParseFile(filenametoread, requireProjectCommand) ) { // pop the listfile off the stack this->ListFileStack.pop_back(); + if(fullPath!=0) + { + fullPath->clear(); + } this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str()); this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str()); return false; diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 5d18ead45..68780cfae 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -72,7 +72,9 @@ public: /** * Read and parse a CMakeLists.txt file. */ - bool ReadListFile(const char* listfile, const char* external= 0); + bool ReadListFile(const char* listfile, + const char* external= 0, + std::string* fullPath= 0); /** * Add a function blocker to this makefile diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index ce991cb3f..127f8ac2e 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -18,13 +18,20 @@ #include "cmCacheManager.h" #include "cmTryCompileCommand.h" -// cmExecutableCommand +// cmTryRunCommand bool cmTryRunCommand::InitialPass(std::vector const& argv) { if(argv.size() < 4) { return false; } + + if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING")) + { + this->SetError("doesn't work when crosscompiling."); + cmSystemTools::SetFatalErrorOccured(); + return false; + } // build an arg list for TryCompile and extract the runArgs std::vector tryCompile; @@ -75,10 +82,11 @@ bool cmTryRunCommand::InitialPass(std::vector const& argv) { int retVal = -1; std::string output; + std::string executableSuffix=this->Makefile->GetDefinition("CMAKE_EXECUTABLE_SUFFIX"); std::string command1 = binaryDirectory; std::vector attemptedPaths; command1 += "/cmTryCompileExec"; - command1 += cmSystemTools::GetExecutableExtension(); + command1 += executableSuffix; std::string fullPath; if(cmSystemTools::FileExists(command1.c_str())) { @@ -97,7 +105,7 @@ bool cmTryRunCommand::InitialPass(std::vector const& argv) command1 += "/"; command1 += config; command1 += "/cmTryCompileExec"; - command1 += cmSystemTools::GetExecutableExtension(); + command1 += executableSuffix; if(cmSystemTools::FileExists(command1.c_str())) { fullPath = cmSystemTools::CollapseFullPath(command1.c_str()); @@ -110,7 +118,7 @@ bool cmTryRunCommand::InitialPass(std::vector const& argv) { command1 = binaryDirectory; command1 += "/Debug/cmTryCompileExec"; - command1 += cmSystemTools::GetExecutableExtension(); + command1 += executableSuffix; if(cmSystemTools::FileExists(command1.c_str())) { fullPath = cmSystemTools::CollapseFullPath(command1.c_str()); @@ -122,7 +130,7 @@ bool cmTryRunCommand::InitialPass(std::vector const& argv) { command1 = binaryDirectory; command1 += "/Development/cmTryCompileExec"; - command1 += cmSystemTools::GetExecutableExtension(); + command1 += executableSuffix; if(cmSystemTools::FileExists(command1.c_str())) { fullPath = cmSystemTools::CollapseFullPath(command1.c_str()); diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx index 5160189b4..8b7a3e22b 100644 --- a/Source/cmUtilitySourceCommand.cxx +++ b/Source/cmUtilitySourceCommand.cxx @@ -88,7 +88,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector const& args) // Construct the cache entry for the executable's location. std::string utilityExecutable = utilityDirectory+"/"+cmakeCFGout+"/" - +utilityName+cmSystemTools::GetExecutableExtension(); + +utilityName+this->Makefile->GetDefinition("CMAKE_EXECUTABLE_SUFFIX"); // make sure we remove any /./ in the name cmSystemTools::ReplaceString(utilityExecutable, "/./", "/"); diff --git a/Source/cmUtilitySourceCommand.h b/Source/cmUtilitySourceCommand.h index 3dd58c8df..e1866efc8 100644 --- a/Source/cmUtilitySourceCommand.h +++ b/Source/cmUtilitySourceCommand.h @@ -72,7 +72,14 @@ public: "is assumed that the source tree of the utility will have been built " "before it is needed."; } - + + /** This command is kept for compatibility with older CMake versions. */ + virtual bool IsDiscouraged() + { + return true; + } + + cmTypeMacro(cmUtilitySourceCommand, cmCommand); }; diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index 6f5167f83..411855f92 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -9,3 +9,6 @@ ENDMACRO(AddCMakeTest) AddCMakeTest(List "") AddCMakeTest(VariableWatch "") +AddCMakeTest(Include "") +AddCMakeTest(FindBase "") +AddCMakeTest(Toolchain "") diff --git a/Tests/CMakeTests/DummyToolchain.cmake b/Tests/CMakeTests/DummyToolchain.cmake new file mode 100644 index 000000000..0cd0dfbb0 --- /dev/null +++ b/Tests/CMakeTests/DummyToolchain.cmake @@ -0,0 +1,8 @@ +set(CMAKE_SYSTEM_NAME Dumdidum) +set(CMAKE_SYSTEM_VERSION "1.0") + +set(CMAKE_C_COMPILER /opt/foo/bin/arm-elf-gcc) +set(CMAKE_C_OUTPUT_EXTENSION ".foo") + +set(CMAKE_CXX_COMPILER /opt/bar/bin/clarm.exe) +set(CMAKE_CXX_OUTPUT_EXTENSION ".bar") diff --git a/Tests/CMakeTests/FindBaseTest.cmake.in b/Tests/CMakeTests/FindBaseTest.cmake.in new file mode 100644 index 000000000..703084711 --- /dev/null +++ b/Tests/CMakeTests/FindBaseTest.cmake.in @@ -0,0 +1,44 @@ +set(MY_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@") + +set(_HEADER cmake_i_do_not_exist_in_the_system.h) +set(_HEADER_FULL "${MY_SOURCE_DIR}/include/${_HEADER}") + +# at first check that the header isn't found without special measures +find_file(FOO_H_1 ${_HEADER}) +if(FOO_H_1) + message(FATAL_ERROR "${_HEADER} found: ${FOO_H_1}, it should not exist !") +endif(FOO_H_1) + +# with this it still should not be found, since the include/ subdir is still missing +set(CMAKE_INCLUDE_PATH "${MY_SOURCE_DIR}") +find_file(FOO_H_2 ${_HEADER}) +if(FOO_H_2) + message(FATAL_ERROR "${_HEADER} found: ${FOO_H_2}, it should not exist !") +endif(FOO_H_2) + +# now with the PATH_SUFFIX it should be found +find_file(FOO_H_3 NAMES ${_HEADER} PATH_SUFFIXES include ) +if(NOT "${FOO_H_3}" STREQUAL "${_HEADER_FULL}") + message(FATAL_ERROR "Did not find \"${_HEADER_FULL}\"\ngot ${FOO_H_3} instead !") +endif(NOT "${FOO_H_3}" STREQUAL "${_HEADER_FULL}") + +# without PATH_SUFFIX, but with a CMAKE_INCLUDE_PATH it should not be found +set(CMAKE_INCLUDE_PATH /include) +find_file(FOO_H_4 ${_HEADER}) +if(FOO_H_4) + message(FATAL_ERROR "${_HEADER} found: ${FOO_H_4}, it should not exist !") +endif(FOO_H_4) + +# when setting CMAKE_FIND_ROOT_PATH to the current source dir, +# together with the CMAKE_INCLUDE_PATH it should be found +set(CMAKE_FIND_ROOT_PATH blub "${MY_SOURCE_DIR}") +find_file(FOO_H_5 ${_HEADER}) +if(NOT "${FOO_H_5}" STREQUAL "${_HEADER_FULL}") + message(FATAL_ERROR "Did not find \"${_HEADER_FULL}\"\ngot ${FOO_H_5} instead !") +endif(NOT "${FOO_H_5}" STREQUAL "${_HEADER_FULL}") + +# by explicitely disabling CMAKE_FIND_ROOT_PATH again it shouldn't be found +find_file(FOO_H_6 ${_HEADER} NO_CMAKE_FIND_ROOT_PATH) +if(FOO_H_6) + message(FATAL_ERROR "${_HEADER} found: ${FOO_H_6}, it should not exist !") +endif(FOO_H_6) diff --git a/Tests/CMakeTests/IncludeTest.cmake.in b/Tests/CMakeTests/IncludeTest.cmake.in new file mode 100644 index 000000000..c8e9e386d --- /dev/null +++ b/Tests/CMakeTests/IncludeTest.cmake.in @@ -0,0 +1,22 @@ +# this one must silently fail +include(I_am_not_here OPTIONAL) + +# this one must be found and the result must be put into _includedFile +include(CMake RESULT_VARIABLE _includedFile) +if(NOT "${_includedFile}" STREQUAL "${CMAKE_ROOT}/Modules/CMake.cmake") + message(FATAL_ERROR "Wrong CMake.cmake was included: \"${_includedFile}\"") +endif(NOT "${_includedFile}" STREQUAL "${CMAKE_ROOT}/Modules/CMake.cmake") + +# this one must return NOTFOUND in _includedFile +include(I_do_not_exist OPTIONAL RESULT_VARIABLE _includedFile) + +if(_includedFile) + message(FATAL_ERROR "File \"I_do_not_exist\" was included, although it shouldn't exist,\nIncluded file is \"${_includedFile}\"") +endif(_includedFile) + +# and this one must succeed too +include(CMake OPTIONAL RESULT_VARIABLE _includedFile) + +if(NOT "${_includedFile}" STREQUAL "${CMAKE_ROOT}/Modules/CMake.cmake") + message(FATAL_ERROR "Wrong CMake.cmake was included: \"${_includedFile}\"") +endif(NOT "${_includedFile}" STREQUAL "${CMAKE_ROOT}/Modules/CMake.cmake") diff --git a/Tests/CMakeTests/ToolchainTest.cmake.in b/Tests/CMakeTests/ToolchainTest.cmake.in new file mode 100644 index 000000000..7d59118b5 --- /dev/null +++ b/Tests/CMakeTests/ToolchainTest.cmake.in @@ -0,0 +1,83 @@ +############################################################ +# some preparations so that the CMakeDetermineXXX.cmake files will work in scripted mode + +# overwrite MARK_AS_ADVANCED(), since this is used in CMakeDetermineCCompiler.cmake +# which will complain that it can"t be used in script mode +macro(MARK_AS_ADVANCED) +endmacro(MARK_AS_ADVANCED) + +# set this to a place where we are allowed to write +set(CMAKE_PLATFORM_ROOT_BIN "${CMAKE_CURRENT_BINARY_DIR}") + +# don't run the compiler detection +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_CXX_COMPILER_ID_RUN 1) + +set(MY_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@") + +############################################################ + +# now define a toolchain file and check that everything is +# detected correctly and nothing predefined is overwritten + +set(CMAKE_TOOLCHAIN_FILE "${MY_SOURCE_DIR}/DummyToolchain.cmake") + +include(CMakeDetermineSystem) +include(CMakeDetermineCCompiler) +include(CMakeDetermineCXXCompiler) + +############################################################# + +# check the results from DetermineSystem + +if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Dumdidum") + message(FATAL_ERROR "CMAKE_SYSTEM_NAME overwritten: \"${CMAKE_SYSTEM_NAME}\", was: \"Dumdidum\"") +endif(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Dumdidum") + +if(NOT "${CMAKE_SYSTEM}" STREQUAL "Dumdidum-1.0") + message(FATAL_ERROR "CMAKE_SYSTEM wrong: \"${CMAKE_SYSTEM}\", expected: \"Dumdidum-1.0\"") +endif(NOT "${CMAKE_SYSTEM}" STREQUAL "Dumdidum-1.0") + +if(NOT "${_INCLUDED_TOOLCHAIN_FILE}" STREQUAL "${MY_SOURCE_DIR}/DummyToolchain.cmake") + message(FATAL_ERROR "wrong toolchain file loaded: \"${_INCLUDED_TOOLCHAIN_FILE}\", expected: \"${MY_SOURCE_DIR}/DummyToolchain.cmake\"") +endif(NOT "${_INCLUDED_TOOLCHAIN_FILE}" STREQUAL "${MY_SOURCE_DIR}/DummyToolchain.cmake") + +############################################################# + +# check the results from DetermineCCompiler + +if(NOT "${_CMAKE_TOOLCHAIN_PREFIX}" STREQUAL "arm-elf-") + message(FATAL_ERROR "wrong toolchain prefix detected: \"${_CMAKE_TOOLCHAIN_PREFIX}\", expected: \"arm-elf-\"") +endif(NOT "${_CMAKE_TOOLCHAIN_PREFIX}" STREQUAL "arm-elf-") + +if(NOT "${_CMAKE_USER_C_COMPILER_PATH}" STREQUAL "/opt/foo/bin") + message(FATAL_ERROR "wrong C compiler location detected: \"${_CMAKE_USER_C_COMPILER_PATH}\", expected: \"/opt/foo/bin\"") +endif(NOT "${_CMAKE_USER_C_COMPILER_PATH}" STREQUAL "/opt/foo/bin") + +if(NOT "${CMAKE_C_OUTPUT_EXTENSION}" STREQUAL ".foo") + message(FATAL_ERROR "C output extension overwritten: \"${CMAKE_C_OUTPUT_EXTENSION}\", was: \".foo\"") +endif(NOT "${CMAKE_C_OUTPUT_EXTENSION}" STREQUAL ".foo") + +############################################################# + +# check the results from DetermineCXXCompiler + +if(NOT "${_CMAKE_TOOLCHAIN_SUFFIX}" STREQUAL "arm") + message(FATAL_ERROR "wrong toolchain suffix detected: \"${_CMAKE_TOOLCHAIN_SUFFIX}\", expected: \"arm\"") +endif(NOT "${_CMAKE_TOOLCHAIN_SUFFIX}" STREQUAL "arm") + +if(NOT "${_CMAKE_USER_CXX_COMPILER_PATH}" STREQUAL "/opt/bar/bin") + message(FATAL_ERROR "wrong CXX compiler location detected: \"${_CMAKE_USER_CXX_COMPILER_PATH}\", expected: \"/opt/bar/bin\"") +endif(NOT "${_CMAKE_USER_CXX_COMPILER_PATH}" STREQUAL "/opt/bar/bin") + +if(NOT "${CMAKE_CXX_OUTPUT_EXTENSION}" STREQUAL ".bar") + message(FATAL_ERROR "C output extension overwritten: \"${CMAKE_CXX_OUTPUT_EXTENSION}\", was: \".bar\"") +endif(NOT "${CMAKE_CXX_OUTPUT_EXTENSION}" STREQUAL ".bar") + +message(STATUS "CMAKE_SYSTEM: \"${CMAKE_SYSTEM}\"") +message(STATUS "_CMAKE_TOOLCHAIN_SUFFIX: \"${_CMAKE_TOOLCHAIN_SUFFIX}\"") +message(STATUS "_CMAKE_TOOLCHAIN_PREFIX: \"${_CMAKE_TOOLCHAIN_PREFIX}\"") +message(STATUS "_CMAKE_USER_C_COMPILER_PATH: \"${_CMAKE_USER_C_COMPILER_PATH}\"") +message(STATUS "_CMAKE_USER_CXX_COMPILER_PATH: \"${_CMAKE_USER_CXX_COMPILER_PATH}\"") +message(STATUS "CMAKE_C_OUTPUT_EXTENSION: \"${CMAKE_C_OUTPUT_EXTENSION}\"") +message(STATUS "CMAKE_CXX_OUTPUT_EXTENSION: \"${CMAKE_CXX_OUTPUT_EXTENSION}\"") diff --git a/Tests/CMakeTests/include/cmake_i_do_not_exist_in_the_system.h b/Tests/CMakeTests/include/cmake_i_do_not_exist_in_the_system.h new file mode 100644 index 000000000..2392aee71 --- /dev/null +++ b/Tests/CMakeTests/include/cmake_i_do_not_exist_in_the_system.h @@ -0,0 +1 @@ +/* empty header file */