From f2ab17d4db86af5695f70b5c49f388319e510472 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 9 Feb 2013 11:12:20 +0100 Subject: [PATCH 1/3] Keep track of all targets seen while evaluating a genex. As dependencies of the generator expression, these will re-exported in try_compile generated code. --- Source/cmGeneratorExpression.cxx | 3 ++- Source/cmGeneratorExpression.h | 8 ++++++-- Source/cmGeneratorExpressionEvaluator.cxx | 4 +++- Source/cmGeneratorExpressionEvaluator.h | 3 ++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 5d162fe03..51ebddb93 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -114,7 +114,8 @@ const char *cmCompiledGeneratorExpression::Evaluate( this->HadContextSensitiveCondition = context.HadContextSensitiveCondition; } - this->Targets = context.Targets; + this->DependTargets = context.DependTargets; + this->AllTargetsSeen = context.AllTargets; // TODO: Return a std::string from here instead? return this->Output.c_str(); } diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 489b052e9..e22303497 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -88,11 +88,14 @@ public: /** Get set of targets found during evaluations. */ std::set const& GetTargets() const - { return this->Targets; } + { return this->DependTargets; } std::set const& GetSeenTargetProperties() const { return this->SeenTargetProperties; } + std::set const& GetAllTargetsSeen() const + { return this->AllTargetsSeen; } + ~cmCompiledGeneratorExpression(); std::string GetInput() const @@ -123,7 +126,8 @@ private: const std::string Input; bool NeedsParsing; - mutable std::set Targets; + mutable std::set DependTargets; + mutable std::set AllTargetsSeen; mutable std::set SeenTargetProperties; mutable std::string Output; mutable bool HadContextSensitiveCondition; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index cd6a40b8d..97ba52408 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -392,6 +392,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode reportError(context, content->GetOriginalExpression(), e.str()); return std::string(); } + context->AllTargets.insert(target); } if (target == context->HeadTarget) @@ -852,7 +853,8 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode "Target \"" + name + "\" is not an executable or library."); return std::string(); } - context->Targets.insert(target); + context->DependTargets.insert(target); + context->AllTargets.insert(target); std::string result = TargetFilesystemArtifactResultCreator::Create( diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index 37d5c864f..ce7ad69bb 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -23,7 +23,8 @@ class cmTarget; struct cmGeneratorExpressionContext { cmListFileBacktrace Backtrace; - std::set Targets; + std::set DependTargets; + std::set AllTargets; std::set SeenTargetProperties; cmMakefile *Makefile; const char *Config; From 1c0597c25bf69a9c73e3d4f6ab68d16b5e56a271 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 17:36:29 +0100 Subject: [PATCH 2/3] Add a new Export generator for IMPORTED targets. This is to be used during try_compile using LINK_LIBRARIES in the srcfile signature and, in the future, TARGETS in the binary dir signature. --- Source/CMakeLists.txt | 2 + Source/cmExportFileGenerator.cxx | 3 + Source/cmExportTryCompileFileGenerator.cxx | 114 +++++++++++++++++++++ Source/cmExportTryCompileFileGenerator.h | 55 ++++++++++ bootstrap | 1 + 5 files changed, 175 insertions(+) create mode 100644 Source/cmExportTryCompileFileGenerator.cxx create mode 100644 Source/cmExportTryCompileFileGenerator.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 675f576f9..fde9677d1 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -176,6 +176,8 @@ set(SRCS cmExportFileGenerator.cxx cmExportInstallFileGenerator.h cmExportInstallFileGenerator.cxx + cmExportTryCompileFileGenerator.h + cmExportTryCompileFileGenerator.cxx cmExportSet.h cmExportSet.cxx cmExportSetMap.h diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index ef4ea3800..d8a705947 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -679,6 +679,9 @@ cmExportFileGenerator case cmTarget::MODULE_LIBRARY: os << "add_library(" << targetName << " MODULE IMPORTED)\n"; break; + case cmTarget::UNKNOWN_LIBRARY: + os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n"; + break; default: // should never happen break; } diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx new file mode 100644 index 000000000..75f2651ba --- /dev/null +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -0,0 +1,114 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#include "cmExportTryCompileFileGenerator.h" + +#include "cmGeneratedFileStream.h" +#include "cmGeneratorExpressionDAGChecker.h" + +//---------------------------------------------------------------------------- +bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os) +{ + std::set emitted; + std::set emittedDeps; + while(!this->Exports.empty()) + { + cmTarget* te = this->Exports.back(); + this->Exports.pop_back(); + if (emitted.insert(te).second) + { + emittedDeps.insert(te); + this->GenerateImportTargetCode(os, te); + + ImportPropertyMap properties; + + this->FindTargets("INTERFACE_INCLUDE_DIRECTORIES", te, emittedDeps); + this->FindTargets("INTERFACE_COMPILE_DEFINITIONS", te, emittedDeps); + + this->PopulateProperties(te, properties, emittedDeps); + + this->GenerateInterfaceProperties(te, os, properties); + } + } + return true; +} + +std::string cmExportTryCompileFileGenerator::FindTargets(const char *propName, + cmTarget *tgt, + std::set &emitted) +{ + const char *prop = tgt->GetProperty(propName); + if(!prop) + { + return std::string(); + } + + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + tgt->GetName(), + propName, 0, 0); + + cmsys::auto_ptr cge = ge.Parse(prop); + + cmTarget dummyHead; + dummyHead.SetType(cmTarget::EXECUTABLE, "try_compile_dummy_exe"); + dummyHead.SetMakefile(tgt->GetMakefile()); + + std::string result = cge->Evaluate(tgt->GetMakefile(), this->Config, + false, &dummyHead, tgt, &dagChecker); + + const std::set &allTargets = cge->GetAllTargetsSeen(); + for(std::set::const_iterator li = allTargets.begin(); + li != allTargets.end(); ++li) + { + if(emitted.insert(*li).second) + { + this->Exports.push_back(*li); + } + } + return result; +} + +//---------------------------------------------------------------------------- +void +cmExportTryCompileFileGenerator::PopulateProperties(cmTarget* target, + ImportPropertyMap& properties, + std::set &emitted) +{ + cmPropertyMap props = target->GetProperties(); + for(cmPropertyMap::const_iterator i = props.begin(); i != props.end(); ++i) + { + properties[i->first] = i->second.GetValue(); + + if(i->first.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0) + { + const std::string libs = i->second.GetValue(); + + std::string evalResult = this->FindTargets(i->first.c_str(), + target, emitted); + + std::vector depends; + cmSystemTools::ExpandListArgument(evalResult, depends); + for(std::vector::const_iterator li = depends.begin(); + li != depends.end(); ++li) + { + cmTarget *tgt = target->GetMakefile()->FindTargetToUse(li->c_str()); + if(tgt && emitted.insert(tgt).second) + { + this->Exports.push_back(tgt); + } + } + } + } +} diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h new file mode 100644 index 000000000..ed393abf4 --- /dev/null +++ b/Source/cmExportTryCompileFileGenerator.h @@ -0,0 +1,55 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2013 Stephen Kelly + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmExportInstallFileGenerator_h +#define cmExportInstallFileGenerator_h + +#include "cmExportFileGenerator.h" + +class cmInstallExportGenerator; +class cmInstallTargetGenerator; + +class cmExportTryCompileFileGenerator: public cmExportFileGenerator +{ +public: + /** Set the list of targets to export. */ + void SetExports(const std::vector &exports) + { this->Exports = exports; } + void SetConfig(const char *config) { this->Config = config; } +protected: + + // Implement virtual methods from the superclass. + virtual bool GenerateMainFile(std::ostream& os); + + virtual void GenerateImportTargetsConfig(std::ostream&, + const char*, + std::string const&, + std::vector&) {} + virtual void HandleMissingTarget(std::string&, + std::vector&, + cmMakefile*, + cmTarget*, + cmTarget*) {} + + void PopulateProperties(cmTarget* target, + ImportPropertyMap& properties, + std::set &emitted); + +private: + std::string FindTargets(const char *prop, cmTarget *tgt, + std::set &emitted); + + + std::vector Exports; + const char *Config; +}; + +#endif diff --git a/bootstrap b/bootstrap index 9a4f796fe..5c2addb50 100755 --- a/bootstrap +++ b/bootstrap @@ -214,6 +214,7 @@ CMAKE_CXX_SOURCES="\ cmMakefile \ cmExportFileGenerator \ cmExportInstallFileGenerator \ + cmExportTryCompileFileGenerator \ cmExportSet \ cmExportSetMap \ cmInstallDirectoryGenerator \ From 236133e79e2d047810eeba90915e38d9861e2a22 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 9 Feb 2013 10:34:37 +0100 Subject: [PATCH 3/3] Handle targets in the LINK_LIBRARIES of try_compile. Imported targets are re-exported so that they can be used by the try_compile generated code with target_link_libraries. This makes the use of the cmake_expand_imported_targets macro obsolete. The macro is not able to expand the generator expressions which may appear in the IMPORTED_LINK_INTERFACE_LIBRARIES content. Instead it just sees them as 'not a target'. --- Modules/CheckCSourceCompiles.cmake | 7 +- Modules/CheckCSourceRuns.cmake | 7 +- Modules/CheckCXXSourceCompiles.cmake | 7 +- Modules/CheckCXXSourceRuns.cmake | 7 +- Modules/CheckFortranFunctionExists.cmake | 7 +- Modules/CheckFunctionExists.cmake | 7 +- Modules/CheckLibraryExists.cmake | 7 +- Modules/CheckPrototypeDefinition.cmake | 7 +- Modules/CheckSymbolExists.cmake | 7 +- Modules/CheckTypeSize.cmake | 5 +- Modules/CheckVariableExists.cmake | 7 +- Source/cmCoreTryCompile.cxx | 108 ++++++++++++++++-- Source/cmTryCompileCommand.h | 8 +- Tests/ExportImport/Import/CMakeLists.txt | 2 + .../Import/try_compile/CMakeLists.txt | 21 ++++ 15 files changed, 150 insertions(+), 64 deletions(-) create mode 100644 Tests/ExportImport/Import/try_compile/CMakeLists.txt diff --git a/Modules/CheckCSourceCompiles.cmake b/Modules/CheckCSourceCompiles.cmake index b4577544e..86a4565ce 100644 --- a/Modules/CheckCSourceCompiles.cmake +++ b/Modules/CheckCSourceCompiles.cmake @@ -24,7 +24,6 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_C_SOURCE_COMPILES SOURCE VAR) @@ -43,10 +42,8 @@ macro(CHECK_C_SOURCE_COMPILES SOURCE VAR) set(MACRO_CHECK_FUNCTION_DEFINITIONS "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES) endif() @@ -64,8 +61,8 @@ macro(CHECK_C_SOURCE_COMPILES SOURCE VAR) ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}" "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}" OUTPUT_VARIABLE OUTPUT) diff --git a/Modules/CheckCSourceRuns.cmake b/Modules/CheckCSourceRuns.cmake index bc64acd31..e3a091fb3 100644 --- a/Modules/CheckCSourceRuns.cmake +++ b/Modules/CheckCSourceRuns.cmake @@ -24,7 +24,6 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_C_SOURCE_RUNS SOURCE VAR) @@ -32,10 +31,8 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) set(MACRO_CHECK_FUNCTION_DEFINITIONS "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES) endif() @@ -53,9 +50,9 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR) ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} - "${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}" "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}" COMPILE_OUTPUT_VARIABLE OUTPUT) # if it did not compile make the return value fail code of 1 diff --git a/Modules/CheckCXXSourceCompiles.cmake b/Modules/CheckCXXSourceCompiles.cmake index c0be1f784..734c0839b 100644 --- a/Modules/CheckCXXSourceCompiles.cmake +++ b/Modules/CheckCXXSourceCompiles.cmake @@ -24,7 +24,6 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_CXX_SOURCE_COMPILES SOURCE VAR) @@ -44,10 +43,8 @@ macro(CHECK_CXX_SOURCE_COMPILES SOURCE VAR) set(MACRO_CHECK_FUNCTION_DEFINITIONS "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES) endif() @@ -65,8 +62,8 @@ macro(CHECK_CXX_SOURCE_COMPILES SOURCE VAR) ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES}" "${CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES}" OUTPUT_VARIABLE OUTPUT) diff --git a/Modules/CheckCXXSourceRuns.cmake b/Modules/CheckCXXSourceRuns.cmake index 47ab1614b..9e401f18e 100644 --- a/Modules/CheckCXXSourceRuns.cmake +++ b/Modules/CheckCXXSourceRuns.cmake @@ -24,7 +24,6 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_CXX_SOURCE_RUNS SOURCE VAR) @@ -32,10 +31,8 @@ macro(CHECK_CXX_SOURCE_RUNS SOURCE VAR) set(MACRO_CHECK_FUNCTION_DEFINITIONS "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES) endif() @@ -53,9 +50,9 @@ macro(CHECK_CXX_SOURCE_RUNS SOURCE VAR) ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.cxx COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} - "${CHECK_CXX_SOURCE_COMPILES_ADD_LIBRARIES}" "${CHECK_CXX_SOURCE_COMPILES_ADD_INCLUDES}" COMPILE_OUTPUT_VARIABLE OUTPUT) diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake index 4b9f9b70d..45dd7bebe 100644 --- a/Modules/CheckFortranFunctionExists.cmake +++ b/Modules/CheckFortranFunctionExists.cmake @@ -22,17 +22,14 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE) if(NOT DEFINED ${VARIABLE}) message(STATUS "Looking for Fortran ${FUNCTION}") if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - cmake_expand_imported_targets(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES) endif() @@ -48,7 +45,7 @@ macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE) try_compile(${VARIABLE} ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f - CMAKE_FLAGS "${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES}" + ${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES} OUTPUT_VARIABLE OUTPUT ) # message(STATUS "${OUTPUT}") diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake index 3f952e0ec..7aa1748da 100644 --- a/Modules/CheckFunctionExists.cmake +++ b/Modules/CheckFunctionExists.cmake @@ -27,7 +27,6 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_FUNCTION_EXISTS FUNCTION VARIABLE) @@ -36,10 +35,8 @@ macro(CHECK_FUNCTION_EXISTS FUNCTION VARIABLE) "-DCHECK_FUNCTION_EXISTS=${FUNCTION} ${CMAKE_REQUIRED_FLAGS}") message(STATUS "Looking for ${FUNCTION}") if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES) endif() @@ -53,8 +50,8 @@ macro(CHECK_FUNCTION_EXISTS FUNCTION VARIABLE) ${CMAKE_BINARY_DIR} ${CMAKE_ROOT}/Modules/CheckFunctionExists.c COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} - "${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES}" "${CHECK_FUNCTION_EXISTS_ADD_INCLUDES}" OUTPUT_VARIABLE OUTPUT) if(${VARIABLE}) diff --git a/Modules/CheckLibraryExists.cmake b/Modules/CheckLibraryExists.cmake index 697f8a4dc..fb7d0ec01 100644 --- a/Modules/CheckLibraryExists.cmake +++ b/Modules/CheckLibraryExists.cmake @@ -26,7 +26,6 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_LIBRARY_EXISTS LIBRARY FUNCTION LOCATION VARIABLE) @@ -36,19 +35,17 @@ macro(CHECK_LIBRARY_EXISTS LIBRARY FUNCTION LOCATION VARIABLE) message(STATUS "Looking for ${FUNCTION} in ${LIBRARY}") set(CHECK_LIBRARY_EXISTS_LIBRARIES ${LIBRARY}) if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_LIBRARY_EXISTS_LIBRARIES - ${CHECK_LIBRARY_EXISTS_LIBRARIES} ${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}) + ${CHECK_LIBRARY_EXISTS_LIBRARIES} ${CMAKE_REQUIRED_LIBRARIES}) endif() try_compile(${VARIABLE} ${CMAKE_BINARY_DIR} ${CMAKE_ROOT}/Modules/CheckFunctionExists.c COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + LINK_LIBRARIES ${CHECK_LIBRARY_EXISTS_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_LIBRARY_EXISTS_DEFINITION} -DLINK_DIRECTORIES:STRING=${LOCATION} - "-DLINK_LIBRARIES:STRING=${CHECK_LIBRARY_EXISTS_LIBRARIES}" OUTPUT_VARIABLE OUTPUT) if(${VARIABLE}) diff --git a/Modules/CheckPrototypeDefinition.cmake b/Modules/CheckPrototypeDefinition.cmake index 74b94b86f..2342b3c4f 100644 --- a/Modules/CheckPrototypeDefinition.cmake +++ b/Modules/CheckPrototypeDefinition.cmake @@ -34,7 +34,6 @@ # License text for the above reference.) # -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") get_filename_component(__check_proto_def_dir "${CMAKE_CURRENT_LIST_FILE}" PATH) @@ -46,10 +45,8 @@ function(CHECK_PROTOTYPE_DEFINITION _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIAB set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS}) if (CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - cmake_expand_imported_targets(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_PROTOTYPE_DEFINITION_LIBS - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_PROTOTYPE_DEFINITION_LIBS) endif() @@ -78,8 +75,8 @@ function(CHECK_PROTOTYPE_DEFINITION _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIAB ${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_PROTOTYPE_DEFINITION_LIBS} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CHECK_PROTOTYPE_DEFINITION_FLAGS} - "${CHECK_PROTOTYPE_DEFINITION_LIBS}" "${CMAKE_SYMBOL_EXISTS_INCLUDES}" OUTPUT_VARIABLE OUTPUT) diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index 5a8597f23..0969bc562 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -35,7 +35,6 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE) @@ -47,10 +46,8 @@ macro(_CHECK_SYMBOL_EXISTS SOURCEFILE SYMBOL FILES VARIABLE) set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n") set(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_SYMBOL_EXISTS_LIBS - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_SYMBOL_EXISTS_LIBS) endif() @@ -75,9 +72,9 @@ macro(_CHECK_SYMBOL_EXISTS SOURCEFILE SYMBOL FILES VARIABLE) ${CMAKE_BINARY_DIR} "${SOURCEFILE}" COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_SYMBOL_EXISTS_LIBS} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS} - "${CHECK_SYMBOL_EXISTS_LIBS}" "${CMAKE_SYMBOL_EXISTS_INCLUDES}" OUTPUT_VARIABLE OUTPUT) if(${VARIABLE}) diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake index 7285b8a6d..2d0eab51c 100644 --- a/Modules/CheckTypeSize.cmake +++ b/Modules/CheckTypeSize.cmake @@ -52,7 +52,6 @@ # License text for the above reference.) include(CheckIncludeFile) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") cmake_policy(PUSH) cmake_minimum_required(VERSION 2.6 FATAL_ERROR) @@ -83,18 +82,16 @@ function(__check_type_size_impl type var map builtin) # Perform the check. - # this one translates potentially used imported library targets to their files on disk - cmake_expand_imported_targets(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.c) set(bin ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.bin) configure_file(${__check_type_size_dir}/CheckTypeSize.c.in ${src} @ONLY) try_compile(HAVE_${var} ${CMAKE_BINARY_DIR} ${src} COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${CMAKE_REQUIRED_FLAGS}" "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}" - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}" OUTPUT_VARIABLE output COPY_FILE ${bin} ) diff --git a/Modules/CheckVariableExists.cmake b/Modules/CheckVariableExists.cmake index f9155a014..a21e65f26 100644 --- a/Modules/CheckVariableExists.cmake +++ b/Modules/CheckVariableExists.cmake @@ -26,7 +26,6 @@ # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) -include("${CMAKE_CURRENT_LIST_DIR}/CMakeExpandImportedTargets.cmake") macro(CHECK_VARIABLE_EXISTS VAR VARIABLE) @@ -35,10 +34,8 @@ macro(CHECK_VARIABLE_EXISTS VAR VARIABLE) "-DCHECK_VARIABLE_EXISTS=${VAR} ${CMAKE_REQUIRED_FLAGS}") message(STATUS "Looking for ${VAR}") if(CMAKE_REQUIRED_LIBRARIES) - # this one translates potentially used imported library targets to their files on disk - CMAKE_EXPAND_IMPORTED_TARGETS(_ADJUSTED_CMAKE_REQUIRED_LIBRARIES LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CONFIGURATION "${CMAKE_TRY_COMPILE_CONFIGURATION}") set(CHECK_VARIABLE_EXISTS_ADD_LIBRARIES - "-DLINK_LIBRARIES:STRING=${_ADJUSTED_CMAKE_REQUIRED_LIBRARIES}") + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) else() set(CHECK_VARIABLE_EXISTS_ADD_LIBRARIES) endif() @@ -46,8 +43,8 @@ macro(CHECK_VARIABLE_EXISTS VAR VARIABLE) ${CMAKE_BINARY_DIR} ${CMAKE_ROOT}/Modules/CheckVariableExists.c COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_VARIABLE_EXISTS_ADD_LIBRARIES} CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_VARIABLE_DEFINITIONS} - "${CHECK_VARIABLE_EXISTS_ADD_LIBRARIES}" OUTPUT_VARIABLE OUTPUT) if(${VARIABLE}) set(${VARIABLE} 1 CACHE INTERNAL "Have variable ${VAR}") diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 1ae70350b..387f6ed5b 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -13,8 +13,11 @@ #include "cmake.h" #include "cmCacheManager.h" #include "cmGlobalGenerator.h" +#include "cmExportTryCompileFileGenerator.h" #include +#include + int cmCoreTryCompile::TryCompileCode(std::vector const& argv) { this->BinaryDirectory = argv[1].c_str(); @@ -39,7 +42,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) // is not used, so it matches regular command line parsing which has // the program name as arg 0 for (; i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" && - argv[i] != "OUTPUT_VARIABLE"; + argv[i] != "OUTPUT_VARIABLE" && + argv[i] != "LINK_LIBRARIES"; ++i) { extraArgs++; @@ -75,7 +79,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) { extraArgs++; for (i = i + 1; i < argv.size() && argv[i] != "CMAKE_FLAGS" && - argv[i] != "OUTPUT_VARIABLE"; + argv[i] != "OUTPUT_VARIABLE" && + argv[i] != "LINK_LIBRARIES"; ++i) { extraArgs++; @@ -85,6 +90,61 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) } } + std::vector targets; + std::string libsToLink = " "; + bool useOldLinkLibs = true; + for (i = 3; i < argv.size(); ++i) + { + if (argv[i] == "LINK_LIBRARIES") + { + if ( argv.size() <= (i+1) ) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "LINK_LIBRARIES specified but there is no content"); + return -1; + } + extraArgs++; + ++i; + useOldLinkLibs = false; + for ( ; i < argv.size() && argv[i] != "CMAKE_FLAGS" + && argv[i] != "COMPILE_DEFINITIONS" && argv[i] != "OUTPUT_VARIABLE"; + ++i) + { + extraArgs++; + libsToLink += argv[i] + " "; + cmTarget *tgt = this->Makefile->FindTargetToUse(argv[i].c_str()); + if (!tgt) + { + continue; + } + switch(tgt->GetType()) + { + case cmTarget::SHARED_LIBRARY: + case cmTarget::STATIC_LIBRARY: + case cmTarget::UNKNOWN_LIBRARY: + break; + case cmTarget::EXECUTABLE: + if (tgt->IsExecutableWithExports()) + { + break; + } + default: + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "Only libraries may be used as try_compile IMPORTED " + "LINK_LIBRARIES. Got " + std::string(tgt->GetName()) + " of " + "type " + tgt->GetTargetTypeName(tgt->GetType()) + "."); + return -1; + } + if (!tgt->IsImported()) + { + continue; + } + targets.push_back(tgt); + } + break; + } + } + // look for COPY_FILE std::string copyFile; for (i = 3; i < argv.size(); ++i) @@ -247,6 +307,32 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) fprintf(fout, ")\n"); } + /* Use a random file name to avoid rapid creation and deletion + of the same executable name (some filesystems fail on that). */ + sprintf(targetNameBuf, "cmTryCompileExec%u", + cmSystemTools::RandomSeed()); + targetName = targetNameBuf; + + if (!targets.empty()) + { + std::string fname = "/" + std::string(targetName) + "Targets.cmake"; + cmExportTryCompileFileGenerator tcfg; + tcfg.SetExportFile((this->BinaryDirectory + fname).c_str()); + tcfg.SetExports(targets); + tcfg.SetConfig(this->Makefile->GetDefinition( + "CMAKE_TRY_COMPILE_CONFIGURATION")); + + if(!tcfg.GenerateImportFile()) + { + this->Makefile->IssueMessage(cmake::FATAL_ERROR, + "could not write export file."); + return -1; + } + fprintf(fout, + "\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/%s\")\n\n", + fname.c_str()); + } + /* for the TRY_COMPILEs we want to be able to specify the architecture. So the user can set CMAKE_OSX_ARCHITECTURE to i386;ppc and then set CMAKE_TRY_COMPILE_OSX_ARCHITECTURE first to i386 and then to ppc to @@ -286,18 +372,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector const& argv) fprintf(fout, "SET(CMAKE_POSITION_INDEPENDENT_CODE \"ON\")\n"); } - /* Use a random file name to avoid rapid creation and deletion - of the same executable name (some filesystems fail on that). */ - sprintf(targetNameBuf, "cmTryCompileExec%u", - cmSystemTools::RandomSeed()); - targetName = targetNameBuf; - /* Put the executable at a known location (for COPY_FILE). */ fprintf(fout, "SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n", this->BinaryDirectory.c_str()); /* Create the actual executable. */ fprintf(fout, "ADD_EXECUTABLE(%s \"%s\")\n", targetName, source.c_str()); - fprintf(fout, "TARGET_LINK_LIBRARIES(%s ${LINK_LIBRARIES})\n",targetName); + if (useOldLinkLibs) + { + fprintf(fout, + "TARGET_LINK_LIBRARIES(%s ${LINK_LIBRARIES})\n",targetName); + } + else + { + fprintf(fout, "TARGET_LINK_LIBRARIES(%s %s)\n", + targetName, + libsToLink.c_str()); + } fclose(fout); projectName = "CMAKE_TRY_COMPILE"; // if the source is not in CMakeTmp diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index 68ec666ec..6caa130ce 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -67,6 +67,7 @@ public: " try_compile(RESULT_VAR \n" " [CMAKE_FLAGS flags...]\n" " [COMPILE_DEFINITIONS flags...]\n" + " [LINK_LIBRARIES libs...]\n" " [OUTPUT_VARIABLE ]\n" " [COPY_FILE ])\n" "Try building a source file into an executable. " @@ -90,7 +91,12 @@ public: "Some extra flags that can be included are, " "INCLUDE_DIRECTORIES, LINK_DIRECTORIES, and LINK_LIBRARIES. " "COMPILE_DEFINITIONS are -Ddefinition that will be passed to the " - "compile line. " + "compile line.\n" + "The srcfile signature also accepts a LINK_LIBRARIES argument which " + "may contain a list of libraries or IMPORTED targets which will be " + "linked to in the generated project. If LINK_LIBRARIES is specified " + "as a parameter to try_compile, then any LINK_LIBRARIES passed as " + "CMAKE_FLAGS will be ignored.\n" "try_compile creates a CMakeList.txt " "file on the fly that looks like this:\n" " add_definitions(