diff options
-rw-r--r-- | Modules/CMakeFindPackageMode.cmake | 187 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 2 | ||||
-rw-r--r-- | Source/cmMakefile.cxx | 19 | ||||
-rw-r--r-- | Source/cmake.cxx | 135 | ||||
-rw-r--r-- | Source/cmake.h | 31 | ||||
-rw-r--r-- | Source/cmakemain.cxx | 17 | ||||
-rw-r--r-- | Tests/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Tests/FindPackageModeMakefileTest/CMakeLists.txt | 30 | ||||
-rw-r--r-- | Tests/FindPackageModeMakefileTest/FindFoo.cmake.in | 9 | ||||
-rw-r--r-- | Tests/FindPackageModeMakefileTest/Makefile.in | 10 | ||||
-rw-r--r-- | Tests/FindPackageModeMakefileTest/foo.cpp | 4 | ||||
-rw-r--r-- | Tests/FindPackageModeMakefileTest/foo.h | 6 | ||||
-rw-r--r-- | Tests/FindPackageModeMakefileTest/main.cpp | 8 | ||||
-rw-r--r-- | Utilities/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Utilities/cmake.m4 | 53 |
16 files changed, 491 insertions, 25 deletions
diff --git a/Modules/CMakeFindPackageMode.cmake b/Modules/CMakeFindPackageMode.cmake new file mode 100644 index 0000000..4296577 --- /dev/null +++ b/Modules/CMakeFindPackageMode.cmake @@ -0,0 +1,187 @@ +# This file is executed by cmake when invoked with --find-package. +# It expects that the following variables are set using -D: +# NAME = name of the package +# COMPILER_ID = the CMake compiler ID for which the result is, i.e. GNU/Intel/Clang/MSVC, etc. +# LANGUAGE = language for which the result will be used, i.e. C/CXX/Fortan/ASM +# MODE = EXIST : only check for existance of the given package +# COMPILE : print the flags needed for compiling an object file which uses the given package +# LINK : print the flags needed for linking when using the given package +# QUIET = if TRUE, don't print anything + +#============================================================================= +# Copyright 2006-2011 Alexander Neundorf, <neundorf@kde.org> +# +# 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. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +if(NOT NAME) + message(FATAL_ERROR "Name of the package to be searched not specified. Set the CMake variable NAME, e.g. -DNAME=JPEG .") +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() + +# require the current version. If we don't do this, Platforms/CYGWIN.cmake complains because +# it doesn't know whether it should set WIN32 or not: +cmake_minimum_required(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} ) + +macro(ENABLE_LANGUAGE) + # disable the enable_language() command, otherwise --find-package breaks on Windows. + # On Windows, enable_language(RC) is called in the platform files unconditionally. + # But in --find-package mode, we don't want (and can't) enable any language. +endmacro() + +include(CMakeDetermineSystem) + +# short-cut some tests on Darwin, see Darwin-GNU.cmake: +if("${CMAKE_SYSTEM_NAME}" MATCHES Darwin AND "${COMPILER_ID}" MATCHES GNU) + set(${CMAKE_${LANGUAGE}_HAS_ISYSROOT} 0 ) + set(CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG "") +endif() + +# 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) + +if(UNIX) + + # try to guess whether we have a 64bit system, if it has not been set + # from the outside + if(NOT CMAKE_SIZEOF_VOID_P) + set(CMAKE_SIZEOF_VOID_P 4) + if(EXISTS /usr/lib64) + set(CMAKE_SIZEOF_VOID_P 8) + else() + # use the file utility to check whether itself is 64 bit: + find_program(FILE_EXECUTABLE file) + if(FILE_EXECUTABLE) + execute_process(COMMAND "${FILE_EXECUTABLE}" "${FILE_EXECUTABLE}" OUTPUT_VARIABLE fileOutput ERROR_QUIET) + if("${fileOutput}" MATCHES "64-bit") + set(CMAKE_SIZEOF_VOID_P 8) + endif() + endif() + endif() + endif() + + # guess Debian multiarch if it has not been set: + if(EXISTS /etc/debian_version) + if(NOT CMAKE_${LANGUAGE}_LANGUAGE_ARCHITECTURE ) + file(GLOB filesInLib RELATIVE /lib /lib/*-linux-gnu* ) + foreach(file ${filesInLib}) + if("${file}" MATCHES "${CMAKE_LIBRARY_ARCHITECTURE_REGEX}") + set(CMAKE_${LANGUAGE}_LANGUAGE_ARCHITECTURE ${file}) + break() + endif() + endforeach() + endif() + endif() + +endif() + +set(CMAKE_${LANGUAGE}_COMPILER "dummy") +set(CMAKE_${LANGUAGE}_COMPILER_ID "${COMPILER_ID}") +include(CMake${LANGUAGE}Information) + + +function(set_compile_flags_var _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(set_link_flags_var _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") + set_compile_flags_var(${NAME}) + elseif("${MODE}" STREQUAL "LINK") + set_link_flags_var(${NAME}) + else("${MODE}" STREQUAL "LINK") + message(FATAL_ERROR "Invalid mode argument ${MODE} given.") + endif() + +endif() + +set(PACKAGE_QUIET ${SILENT} ) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 27acf98..d62fb44 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -783,7 +783,7 @@ void cmGlobalGenerator::Configure() // so create the map from project name to vector of local generators this->FillProjectMap(); - if ( !this->CMakeInstance->GetScriptMode() ) + if ( this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE) { const char* msg = "Configuring done"; if(cmSystemTools::GetErrorOccuredFlag()) diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index aebf9f3..a204a73 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -307,7 +307,6 @@ public: std::string const& dir_max, bool* hasSourceExtension = 0); -protected: /** Fill out these strings for the given target. Libraries to link, * flags, and linkflags. */ void GetTargetFlags(std::string& linkLibs, @@ -315,6 +314,7 @@ protected: std::string& linkFlags, cmTarget&target); +protected: ///! put all the libraries for a target on into the given stream virtual void OutputLinkLibraries(std::ostream&, cmTarget&, bool relink); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 45165e5..e5b5443 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -384,7 +384,9 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, // Decide whether to invoke the command. if(pcmd->GetEnabled() && !cmSystemTools::GetFatalErrorOccured() && - (!this->GetCMakeInstance()->GetScriptMode() || pcmd->IsScriptable())) + (this->GetCMakeInstance()->GetWorkingMode() != cmake::SCRIPT_MODE + || pcmd->IsScriptable())) + { // if trace is one, print out invoke information if(this->GetCMakeInstance()->GetTrace()) @@ -411,7 +413,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, this->IssueMessage(cmake::FATAL_ERROR, pcmd->GetError()); } result = false; - if ( this->GetCMakeInstance()->GetScriptMode() ) + if ( this->GetCMakeInstance()->GetWorkingMode() != cmake::NORMAL_MODE) { cmSystemTools::SetFatalErrorOccured(); } @@ -422,7 +424,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff, this->UsedCommands.push_back(pcmd.release()); } } - else if ( this->GetCMakeInstance()->GetScriptMode() + else if ( this->GetCMakeInstance()->GetWorkingMode() == cmake::SCRIPT_MODE && !pcmd->IsScriptable() ) { std::string error = "Command "; @@ -3025,8 +3027,15 @@ cmCacheManager *cmMakefile::GetCacheManager() const void cmMakefile::DisplayStatus(const char* message, float s) { - this->GetLocalGenerator()->GetGlobalGenerator() - ->GetCMakeInstance()->UpdateProgress(message, s); + cmake* cm = this->GetLocalGenerator()->GetGlobalGenerator() + ->GetCMakeInstance(); + if (cm->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) + { + // don't output any STATUS message in FIND_PACKAGE_MODE, since they will + // directly be fed to the compiler, which will be confused. + return; + } + cm->UpdateProgress(message, s); } std::string cmMakefile::GetModulesFile(const char* filename) diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 99b1844..2b8c718 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -183,7 +183,7 @@ cmake::cmake() this->GlobalGenerator = 0; this->ProgressCallback = 0; this->ProgressCallbackClientData = 0; - this->ScriptMode = false; + this->CurrentWorkingMode = NORMAL_MODE; #ifdef CMAKE_BUILD_WITH_CMAKE this->VariableWatch = new cmVariableWatch; @@ -356,6 +356,7 @@ void cmake::RemoveUnscriptableCommands() // Parse the args bool cmake::SetCacheArgs(const std::vector<std::string>& args) { + bool findPackageMode = false; for(unsigned int i=1; i < args.size(); ++i) { std::string arg = args[i]; @@ -483,7 +484,17 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) } this->ReadListFile(args, path.c_str()); } + else if (arg.find("--find-package",0) == 0) + { + findPackageMode = true; + } } + + if (findPackageMode) + { + return this->FindPackage(args); + } + return true; } @@ -514,7 +525,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args, (cmSystemTools::GetCurrentWorkingDirectory().c_str()); lg->GetMakefile()->SetStartDirectory (cmSystemTools::GetCurrentWorkingDirectory().c_str()); - if (this->GetScriptMode()) + if (this->GetWorkingMode() != NORMAL_MODE) { std::string file(cmSystemTools::CollapseFullPath(path)); cmSystemTools::ConvertToUnixSlashes(file); @@ -535,6 +546,111 @@ void cmake::ReadListFile(const std::vector<std::string>& args, } } + +bool cmake::FindPackage(const std::vector<std::string>& args) +{ + // 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<cmLocalGenerator> 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<std::string> includeDirs; + cmSystemTools::ExpandListArgument(includes, includeDirs); + for(std::vector<std::string>::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<std::string> srcs; + cmTarget* tgt = mf->AddExecutable(targetName, srcs, true); + tgt->SetProperty("LINKER_LANGUAGE", language.c_str()); + + std::string libs = mf->GetSafeDefinition("PACKAGE_LIBRARIES"); + std::vector<std::string> libList; + cmSystemTools::ExpandListArgument(libs, libList); + for(std::vector<std::string>::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; +} + + // Parse the args void cmake::SetArgs(const std::vector<std::string>& args, bool directoriesSetBefore) @@ -607,6 +723,11 @@ void cmake::SetArgs(const std::vector<std::string>& args, // skip for now i++; } + else if(arg.find("--find-package",0) == 0) + { + // skip for now + i++; + } else if(arg.find("-Wno-dev",0) == 0) { // skip for now @@ -2035,7 +2156,7 @@ int cmake::ActualConfigure() this->CleanupCommandsAndMacros(); int res = 0; - if ( !this->ScriptMode ) + if ( this->GetWorkingMode() == NORMAL_MODE ) { res = this->DoPreConfigureChecks(); } @@ -2223,7 +2344,7 @@ int cmake::ActualConfigure() this->CacheManager->RemoveCacheEntry("CMAKE_EXTRA_GENERATOR"); } // only save the cache if there were no fatal errors - if ( !this->ScriptMode ) + if ( this->GetWorkingMode() == NORMAL_MODE ) { this->CacheManager->SaveCache(this->GetHomeOutputDirectory()); } @@ -2289,7 +2410,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) // set the cmake command this->CMakeCommand = args[0]; - if ( !this->ScriptMode ) + if ( this->GetWorkingMode() == NORMAL_MODE ) { // load the cache if(this->LoadCache() < 0) @@ -2310,7 +2431,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) } // In script mode we terminate after running the script. - if(this->ScriptMode) + if(this->GetWorkingMode() != NORMAL_MODE) { if(cmSystemTools::GetErrorOccuredFlag()) { @@ -2356,7 +2477,7 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) this->SetStartDirectory(this->GetHomeDirectory()); this->SetStartOutputDirectory(this->GetHomeOutputDirectory()); int ret = this->Configure(); - if (ret || this->ScriptMode) + if (ret || this->GetWorkingMode() != NORMAL_MODE) { #if defined(CMAKE_HAVE_VS_GENERATORS) if(!this->VSSolutionFile.empty() && this->GlobalGenerator) diff --git a/Source/cmake.h b/Source/cmake.h index 09f6c37..ae56e85 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -64,6 +64,25 @@ class cmake WARNING, LOG }; + + + /** Describes the working modes of cmake. + * NORMAL_MODE: cmake runs to create project files + * SCRIPT_MODE: in script mode there is no generator and no cache. Also, + * language are not enabled, so add_executable and things do + * not do anything. Started by using -P + * FIND_PACKAGE_MODE: cmake runs in pkg-config like mode, i.e. it just + * searches for a package and prints the results to stdout. + * This is similar to SCRIPT_MODE, but commands like + * add_library() work too, since they may be used e.g. in + * exported target files. Started via --find-package + */ + enum WorkingMode + { + NORMAL_MODE, + SCRIPT_MODE, + FIND_PACKAGE_MODE + }; typedef std::map<cmStdString, cmCommand*> RegisteredCommandsMap; ///! construct an instance of cmake @@ -274,13 +293,8 @@ class cmake ///! Do all the checks before running configure int DoPreConfigureChecks(); - /** - * Set and get the script mode option. In script mode there is no - * generator and no cache. Also, language are not enabled, so - * add_executable and things do not do anything. - */ - void SetScriptMode(bool mode) { this->ScriptMode = mode; } - bool GetScriptMode() { return this->ScriptMode; } + void SetWorkingMode(WorkingMode mode) { this->CurrentWorkingMode = mode; } + WorkingMode GetWorkingMode() { return this->CurrentWorkingMode; } ///! Debug the try compile stuff by not delelting the files bool GetDebugTryCompile(){return this->DebugTryCompile;} @@ -409,6 +423,7 @@ protected: ///! read in a cmake list file to initialize the cache void ReadListFile(const std::vector<std::string>& args, const char *path); + bool FindPackage(const std::vector<std::string>& args); ///! Check if CMAKE_CACHEFILE_DIR is set. If it is not, delete the log file. /// If it is set, truncate it to 50kb @@ -462,7 +477,7 @@ private: void* ProgressCallbackClientData; bool Verbose; bool InTryCompile; - bool ScriptMode; + WorkingMode CurrentWorkingMode; bool DebugOutput; bool Trace; bool WarnUninitialized; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 1fe9e82..9f213a5 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -103,6 +103,11 @@ static const char * cmDocumentationOptions[][3] = "No configure or generate step is performed and the cache is not" " modified. If variables are defined using -D, this must be done " "before the -P argument."}, + {"--find-package", "Run in pkg-config like mode.", + "Search a package using find_package() and print the resulting flags " + "to stdout. This can be used to use cmake instead of pkg-config to find " + "installed libraries in plain Makefile-based projects or in " + "autoconf-based projects (via share/aclocal/cmake.m4)."}, {"--graphviz=[file]", "Generate graphviz of dependencies.", "Generate a graphviz input file that will contain all the library and " "executable dependencies in the project."}, @@ -434,7 +439,7 @@ int do_cmake(int ac, char** av) bool list_all_cached = false; bool list_help = false; bool view_only = false; - bool script_mode = false; + cmake::WorkingMode workingMode = cmake::NORMAL_MODE; std::vector<std::string> args; for(int i =0; i < ac; ++i) { @@ -482,12 +487,18 @@ int do_cmake(int ac, char** av) } else { - script_mode = true; + workingMode = cmake::SCRIPT_MODE; args.push_back(av[i]); i++; args.push_back(av[i]); } } + else if (!command && strncmp(av[i], "--find-package", + strlen("--find-package")) == 0) + { + workingMode = cmake::FIND_PACKAGE_MODE; + args.push_back(av[i]); + } else { args.push_back(av[i]); @@ -512,7 +523,7 @@ int do_cmake(int ac, char** av) cmake cm; cmSystemTools::SetErrorCallback(cmakemainErrorCallback, (void *)&cm); cm.SetProgressCallback(cmakemainProgressCallback, (void *)&cm); - cm.SetScriptMode(script_mode); + cm.SetWorkingMode(workingMode); int res = cm.Run(args, view_only); if ( list_cached || list_all_cached ) diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index cfc1846..46b3c15 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -48,6 +48,8 @@ IF(BUILD_TESTING) ADD_SUBDIRECTORY(CMakeLib) + ADD_SUBDIRECTORY(FindPackageModeMakefileTest) + # Collect a list of all test build directories. SET(TEST_BUILD_DIRS) diff --git a/Tests/FindPackageModeMakefileTest/CMakeLists.txt b/Tests/FindPackageModeMakefileTest/CMakeLists.txt new file mode 100644 index 0000000..def8d63 --- /dev/null +++ b/Tests/FindPackageModeMakefileTest/CMakeLists.txt @@ -0,0 +1,30 @@ + + +if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Makefile") + + # Test whether the make is GNU make, and only add the test in this case, + # since the configured makefile in this test uses $(shell ...), which + # is AFAIK a GNU make extension. Alex + execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} -v + OUTPUT_VARIABLE makeVersionOutput + TIMEOUT 10) + string(TOUPPER "${makeVersionOutput}" MAKE_VERSION_OUTPUT) + if("${MAKE_VERSION_OUTPUT}" MATCHES ".*GNU MAKE.*") + + # build a library which we can search during the test + add_library(foo STATIC foo.cpp) + + # configure a FindFoo.cmake so it knows where the library can be found + configure_file(FindFoo.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FindFoo.cmake @ONLY) + + # now set up the test: + get_target_property(cmakeExecutable cmake LOCATION) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Makefile.in ${CMAKE_CURRENT_BINARY_DIR}/ConfMakefile @ONLY) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${CMAKE_CURRENT_BINARY_DIR}/main.cpp COPYONLY) + + add_test(FindPackageModeMakefileTest ${CMAKE_MAKE_PROGRAM} -f ${CMAKE_CURRENT_BINARY_DIR}/ConfMakefile ) + + endif() + +endif() diff --git a/Tests/FindPackageModeMakefileTest/FindFoo.cmake.in b/Tests/FindPackageModeMakefileTest/FindFoo.cmake.in new file mode 100644 index 0000000..dc62bac --- /dev/null +++ b/Tests/FindPackageModeMakefileTest/FindFoo.cmake.in @@ -0,0 +1,9 @@ + +find_library(FOO_LIBRARY NAMES foo HINTS "@CMAKE_CURRENT_BINARY_DIR@" ) +find_path(FOO_INCLUDE_DIR NAMES foo.h HINTS "@CMAKE_CURRENT_SOURCE_DIR@" ) + +set(FOO_LIBRARIES ${FOO_LIBRARY}) +set(FOO_INCLUDE_DIRS "${FOO_INCLUDE_DIR}" "/some/path/with a space/include" ) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Foo DEFAULT_MSG FOO_LIBRARY FOO_INCLUDE_DIR ) diff --git a/Tests/FindPackageModeMakefileTest/Makefile.in b/Tests/FindPackageModeMakefileTest/Makefile.in new file mode 100644 index 0000000..073d82e --- /dev/null +++ b/Tests/FindPackageModeMakefileTest/Makefile.in @@ -0,0 +1,10 @@ +all: clean pngtest + +main.o: main.cpp + "@CMAKE_CXX_COMPILER@" $(CXXFLAGS) -c $(shell "@cmakeExecutable@" --find-package -DCMAKE_MODULE_PATH="@CMAKE_CURRENT_BINARY_DIR@" -DNAME=Foo -DLANGUAGE=CXX -DCOMPILER_ID=@CMAKE_CXX_COMPILER_ID@ -DMODE=COMPILE) main.cpp + +pngtest: main.o + "@CMAKE_CXX_COMPILER@" $(LDFLAGS) -o pngtest main.o $(shell "@cmakeExecutable@" --find-package -DCMAKE_MODULE_PATH="@CMAKE_CURRENT_BINARY_DIR@" -DNAME=Foo -DLANGUAGE=CXX -DCOMPILER_ID=@CMAKE_CXX_COMPILER_ID@ -DMODE=LINK) + +clean: + rm -f *.o pngtest diff --git a/Tests/FindPackageModeMakefileTest/foo.cpp b/Tests/FindPackageModeMakefileTest/foo.cpp new file mode 100644 index 0000000..6aea226 --- /dev/null +++ b/Tests/FindPackageModeMakefileTest/foo.cpp @@ -0,0 +1,4 @@ +int foo() +{ + return 1477; +} diff --git a/Tests/FindPackageModeMakefileTest/foo.h b/Tests/FindPackageModeMakefileTest/foo.h new file mode 100644 index 0000000..4ec598a --- /dev/null +++ b/Tests/FindPackageModeMakefileTest/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +int foo(); + +#endif diff --git a/Tests/FindPackageModeMakefileTest/main.cpp b/Tests/FindPackageModeMakefileTest/main.cpp new file mode 100644 index 0000000..e5f9134 --- /dev/null +++ b/Tests/FindPackageModeMakefileTest/main.cpp @@ -0,0 +1,8 @@ +#include <stdio.h> +#include <foo.h> + +int main() +{ + printf("foo is: %d\n", foo()); + return 0; +} diff --git a/Utilities/CMakeLists.txt b/Utilities/CMakeLists.txt index 8b3e7f6..85db367 100644 --- a/Utilities/CMakeLists.txt +++ b/Utilities/CMakeLists.txt @@ -126,6 +126,7 @@ ADD_CUSTOM_COMMAND( INSTALL_FILES(${CMAKE_MAN_DIR}/man1 FILES ${MAN_FILES}) INSTALL_FILES(${CMAKE_DOC_DIR} FILES ${HTML_FILES} ${TEXT_FILES}) +INSTALL_FILES(share/aclocal FILES cmake.m4) # Drive documentation generation. ADD_CUSTOM_TARGET(documentation ALL DEPENDS ${DOC_FILES} ${CMake_BINARY_DIR}/Docs/cmake.txt ) diff --git a/Utilities/cmake.m4 b/Utilities/cmake.m4 new file mode 100644 index 0000000..a374a3b --- /dev/null +++ b/Utilities/cmake.m4 @@ -0,0 +1,53 @@ +dnl ============================================================================ +dnl CMake - Cross Platform Makefile Generator +dnl Copyright 2011 Matthias Kretz, kretz@kde.org +dnl +dnl Distributed under the OSI-approved BSD License (the "License"); +dnl see accompanying file Copyright.txt for details. +dnl +dnl This software is distributed WITHOUT ANY WARRANTY; without even the +dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +dnl See the License for more information. +dnl ============================================================================ + +AC_DEFUN([CMAKE_FIND_BINARY], +[AC_ARG_VAR([CMAKE_BINARY], [path to the cmake binary])dnl + +if test "x$ac_cv_env_CMAKE_BINARY_set" != "xset"; then + AC_PATH_TOOL([CMAKE_BINARY], [cmake])dnl +fi +])dnl + +# $1: package name +# $2: language (e.g. C/CXX/Fortran) +# $3: The compiler ID, defaults to GNU. +# Possible values are: GNU, Intel, Clang, SunPro, HP, XL, VisualAge, PGI, +# PathScale, Cray, SCO, MIPSpro, MSVC +# $4: optional extra arguments to cmake, e.g. "-DCMAKE_SIZEOF_VOID_P=8" +# $5: optional path to cmake binary +AC_DEFUN([CMAKE_FIND_PACKAGE], [ +AC_REQUIRE([CMAKE_FIND_BINARY])dnl + +AC_ARG_VAR([$1][_][$2][FLAGS], [$2 compiler flags for $1. This overrides the cmake output])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1. This overrides the cmake output])dnl + +failed=false +AC_MSG_CHECKING([for $1]) +if test -n "$1[]_$2[]FLAGS"; then + $1[]_$2[]FLAGS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=COMPILE $4` || failed=true +fi +if test -n "$1[]_LIBS"; then + $1[]_LIBS=`$CMAKE_BINARY --find-package "-DNAME=$1" "-DCOMPILER_ID=m4_default([$3], [GNU])" "-DLANGUAGE=$2" -DMODE=LINK $4` || failed=true +fi + +if $failed; then + unset $1[]_$2[]FLAGS + unset $1[]_LIBS + + AC_MSG_RESULT([no]) + $6 +else + AC_MSG_RESULT([yes]) + $5 +fi[]dnl +]) |