From e4f603b698a13857e79a5f6df18a7461b20d4bd4 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Sat, 2 Jul 2011 23:14:28 +0200 Subject: [PATCH] Implement find-package mode of cmake In find-package mode, cmake executes Modules/CMakeFindPackage.cmake, which calls find_package(), and this is then evaluated in cmake.cxx, which prints an appropriate message to stdout, so it can be used e.g. in a normal Makefile: $ /opt/cmake-HEAD/bin/cmake --find-package -DNAME=JPEG -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=EXIST JPEG found. $ /opt/cmake-HEAD/bin/cmake --find-package -DNAME=JPEG -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=COMPILE $ /opt/cmake-HEAD/bin/cmake --find-package -DNAME=JPEG -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=LINK -rdynamic -ljpeg Alex --- Modules/CMakeFindPackageMode.cmake | 125 +++++++++++++++++++++++++++++ Source/cmake.cxx | 100 ++++++++++++++++++++++- 2 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 Modules/CMakeFindPackageMode.cmake diff --git a/Modules/CMakeFindPackageMode.cmake b/Modules/CMakeFindPackageMode.cmake new file mode 100644 index 000000000..5842c7aef --- /dev/null +++ b/Modules/CMakeFindPackageMode.cmake @@ -0,0 +1,125 @@ +# COMPILER_ID = GNU/Intel/etc. +# LANGUAGE = C/CXX/Fortan/ASM +# MODE = EXIST/COMPILE/LINK +# NAME = name of the package +# QUIET = if TRUE, don't print anything + +if(NOT NAME) + message(FATAL_ERROR "NAME argument not specified.") +endif() + +if(NOT COMPILER_ID) + message(FATAL_ERROR "COMPILER_ID argument not specified. In doubt, use GNU.") +endif() + +if(NOT LANGUAGE) + message(FATAL_ERROR "LANGUAGE argument not specified. Use C, CXX or Fortran.") +endif() + +if(NOT MODE) + message(FATAL_ERROR "MODE argument not specified. Use either EXIST, COMPILE or LINK.") +endif() + + +include(CMakeDetermineSystem) + +# Also load the system specific file, which sets up e.g. the search paths. +# This makes the FIND_XXX() calls work much better +include(CMakeSystemSpecificInformation) + +# this is ugly, and not enough for the multilib-stuff I guess +if(UNIX AND EXISTS /usr/lib64) + set(CMAKE_SIZEOF_VOID_P 8) +endif() + +set(CMAKE_${LANGUAGE}_COMPILER "dummy") +set(CMAKE_${LANGUAGE}_COMPILER_ID "${COMPILER_ID}") +include(CMake${LANGUAGE}Information) + + +function(print_compile_flags _packageName) + string(TOUPPER "${_packageName}" PACKAGE_NAME) + # Check the following variables: + # FOO_INCLUDE_DIRS + # Foo_INCLUDE_DIRS + # FOO_INCLUDES + # Foo_INCLUDES + # FOO_INCLUDE_DIR + # Foo_INCLUDE_DIR + set(includes) + if(DEFINED ${_packageName}_INCLUDE_DIRS) + set(includes ${_packageName}_INCLUDE_DIRS) + elseif(DEFINED ${PACKAGE_NAME}_INCLUDE_DIRS) + set(includes ${PACKAGE_NAME}_INCLUDE_DIRS) + elseif(DEFINED ${_packageName}_INCLUDES) + set(includes ${_packageName}_INCLUDES) + elseif(DEFINED ${PACKAGE_NAME}_INCLUDES) + set(includes ${PACKAGE_NAME}_INCLUDES) + elseif(DEFINED ${_packageName}_INCLUDE_DIR) + set(includes ${_packageName}_INCLUDE_DIR) + elseif(DEFINED ${PACKAGE_NAME}_INCLUDE_DIR) + set(includes ${PACKAGE_NAME}_INCLUDE_DIR) + endif() + + set(PACKAGE_INCLUDE_DIRS "${${includes}}" PARENT_SCOPE) + + # Check the following variables: + # FOO_DEFINITIONS + # Foo_DEFINITIONS + set(definitions) + if(DEFINED ${_packageName}_DEFINITIONS) + set(definitions ${_packageName}_DEFINITIONS) + elseif(DEFINED ${PACKAGE_NAME}_DEFINITIONS) + set(definitions ${PACKAGE_NAME}_DEFINITIONS) + endif() + + set(PACKAGE_DEFINITIONS "${${definitions}}" ) + +endfunction() + + +function(print_link_flags _packageName) + string(TOUPPER "${_packageName}" PACKAGE_NAME) + # Check the following variables: + # FOO_LIBRARIES + # Foo_LIBRARIES + # FOO_LIBS + # Foo_LIBS + set(libs) + if(DEFINED ${_packageName}_LIBRARIES) + set(libs ${_packageName}_LIBRARIES) + elseif(DEFINED ${PACKAGE_NAME}_LIBRARIES) + set(libs ${PACKAGE_NAME}_LIBRARIES) + elseif(DEFINED ${_packageName}_LIBS) + set(libs ${_packageName}_LIBS) + elseif(DEFINED ${PACKAGE_NAME}_LIBS) + set(libs ${PACKAGE_NAME}_LIBS) + endif() + + set(PACKAGE_LIBRARIES "${${libs}}" PARENT_SCOPE ) + +endfunction() + + +find_package("${NAME}" QUIET) + +set(PACKAGE_FOUND FALSE) + +string(TOUPPER "${NAME}" UPPERCASE_NAME) + +if(${NAME}_FOUND OR ${UPPERCASE_NAME}_FOUND) + set(PACKAGE_FOUND TRUE) + + if("${MODE}" STREQUAL "EXIST") + # do nothing + elseif("${MODE}" STREQUAL "COMPILE") + print_compile_flags(${NAME}) + elseif("${MODE}" STREQUAL "LINK") + print_link_flags(${NAME}) + else("${MODE}" STREQUAL "LINK") + message(FATAL_ERROR "Invalid mode argument ${MODE} given.") + endif() + +endif() + +set(PACKAGE_QUIET ${SILENT} ) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 3d42c7fa4..5b6286eec 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -547,8 +547,104 @@ void cmake::ReadListFile(const std::vector& args, bool cmake::FindPackage(const std::vector& args) { - // create empty function for now, will be filled later - return true; + // if a generator was not yet created, temporarily create one + cmGlobalGenerator *gg = new cmGlobalGenerator; + gg->SetCMakeInstance(this); + this->SetGlobalGenerator(gg); + + // read in the list file to fill the cache + std::auto_ptr lg(gg->CreateLocalGenerator()); + cmMakefile* mf = lg->GetMakefile(); + mf->SetHomeOutputDirectory + (cmSystemTools::GetCurrentWorkingDirectory().c_str()); + mf->SetStartOutputDirectory + (cmSystemTools::GetCurrentWorkingDirectory().c_str()); + mf->SetHomeDirectory + (cmSystemTools::GetCurrentWorkingDirectory().c_str()); + mf->SetStartDirectory + (cmSystemTools::GetCurrentWorkingDirectory().c_str()); + + mf->SetArgcArgv(args); + + std::string systemFile = mf->GetModulesFile("CMakeFindPackageMode.cmake"); + mf->ReadListFile(0, systemFile.c_str()); + + std::string language = mf->GetSafeDefinition("LANGUAGE"); + std::string mode = mf->GetSafeDefinition("MODE"); + std::string packageName = mf->GetSafeDefinition("NAME"); + bool packageFound = mf->IsOn("PACKAGE_FOUND"); + bool quiet = mf->IsOn("PACKAGE_QUIET"); + + if (!packageFound) + { + if (!quiet) + { + printf("%s not found.\n", packageName.c_str()); + } + } + else if (mode == "EXIST") + { + if (!quiet) + { + printf("%s found.\n", packageName.c_str()); + } + } + else if (mode == "COMPILE") + { + std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS"); + std::vector includeDirs; + cmSystemTools::ExpandListArgument(includes, includeDirs); + for(std::vector::const_iterator dirIt=includeDirs.begin(); + dirIt != includeDirs.end(); + ++dirIt) + { + mf->AddIncludeDirectory(dirIt->c_str(), false); + } + + std::string includeFlags = lg->GetIncludeFlags(language.c_str(), false); + std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS"); + printf("%s %s\n", includeFlags.c_str(), definitions.c_str()); + } + else if (mode == "LINK") + { + const char* targetName = "dummy"; + std::vector srcs; + cmTarget* tgt = mf->AddExecutable(targetName, srcs, true); + tgt->SetProperty("LINKER_LANGUAGE", language.c_str()); + + std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES"); + std::vector libList; + cmSystemTools::ExpandListArgument(libs, libList); + for(std::vector::const_iterator libIt=libList.begin(); + libIt != libList.end(); + ++libIt) + { + mf->AddLinkLibraryForTarget(targetName, libIt->c_str(), cmTarget::GENERAL); + } + + + std::string linkLibs; + std::string flags; + std::string linkFlags; + lg->GetTargetFlags(linkLibs, flags, linkFlags, *tgt); + + printf("%s\n", linkLibs.c_str() ); + +/* if ( use_win32 ) + { + tgt->SetProperty("WIN32_EXECUTABLE", "ON"); + } + if ( use_macbundle) + { + tgt->SetProperty("MACOSX_BUNDLE", "ON"); + }*/ + } + + // free generic one if generated +// this->SetGlobalGenerator(0); // setting 0-pointer is not possible +// delete gg; // this crashes inside the cmake instance + + return packageFound; }