diff options
-rw-r--r-- | Help/generator/MSYS Makefiles.rst | 10 | ||||
-rw-r--r-- | Help/generator/MinGW Makefiles.rst | 11 | ||||
-rw-r--r-- | Help/manual/cmake-modules.7.rst | 1 | ||||
-rw-r--r-- | Help/module/FindGSL.rst | 1 | ||||
-rw-r--r-- | Help/release/dev/add-FindGSL.rst | 5 | ||||
-rw-r--r-- | Modules/FindGSL.cmake | 238 | ||||
-rw-r--r-- | Source/CMakeLists.txt | 10 | ||||
-rw-r--r-- | Source/CMakeVersion.cmake | 2 | ||||
-rw-r--r-- | Source/cmConfigure.cmake.h.in | 1 | ||||
-rw-r--r-- | Source/cmMachO.cxx | 419 | ||||
-rw-r--r-- | Source/cmMachO.h | 51 | ||||
-rw-r--r-- | Source/cmSystemTools.cxx | 34 | ||||
-rw-r--r-- | Tests/CMakeLists.txt | 4 | ||||
-rw-r--r-- | Tests/FindGSL/CMakeLists.txt | 9 | ||||
-rw-r--r-- | Tests/FindGSL/rng/CMakeLists.txt | 14 | ||||
-rw-r--r-- | Tests/FindGSL/rng/main.cc | 24 | ||||
-rw-r--r-- | Utilities/Release/dash2win64_release.cmake | 7 | ||||
-rw-r--r-- | Utilities/Release/dashmacmini5_release.cmake | 11 |
18 files changed, 819 insertions, 33 deletions
diff --git a/Help/generator/MSYS Makefiles.rst b/Help/generator/MSYS Makefiles.rst index 0b89126..f7cfa44 100644 --- a/Help/generator/MSYS Makefiles.rst +++ b/Help/generator/MSYS Makefiles.rst @@ -1,7 +1,11 @@ MSYS Makefiles -------------- -Generates MSYS makefiles. +Generates makefiles for use with MSYS ``make`` under the MSYS shell. -The makefiles use /bin/sh as the shell. They require msys to be -installed on the machine. +Use this generator in a MSYS shell prompt and using ``make`` as the build +tool. The generated makefiles use ``/bin/sh`` as the shell to launch build +rules. They are not compatible with a Windows command prompt. + +To build under a Windows command prompt, use the +:generator:`MinGW Makefiles` generator. diff --git a/Help/generator/MinGW Makefiles.rst b/Help/generator/MinGW Makefiles.rst index ed4ccdd..9fe5fe3 100644 --- a/Help/generator/MinGW Makefiles.rst +++ b/Help/generator/MinGW Makefiles.rst @@ -1,7 +1,12 @@ MinGW Makefiles --------------- -Generates a make file for use with mingw32-make. +Generates makefiles for use with ``mingw32-make`` under a Windows command +prompt. -The makefiles generated use cmd.exe as the shell. They do not require -msys or a unix shell. +Use this generator under a Windows command prompt with MinGW in the ``PATH`` +and using ``mingw32-make`` as the build tool. The generated makefiles use +``cmd.exe`` as the shell to launch build rules. They are not compatible with +MSYS or a unix shell. + +To build under the MSYS shell, use the :generator:`MSYS Makefiles` generator. diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 8337118..5196485 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -108,6 +108,7 @@ All Modules /module/FindGLUT /module/FindGnuplot /module/FindGnuTLS + /module/FindGSL /module/FindGTest /module/FindGTK2 /module/FindGTK diff --git a/Help/module/FindGSL.rst b/Help/module/FindGSL.rst new file mode 100644 index 0000000..baf2213 --- /dev/null +++ b/Help/module/FindGSL.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindGSL.cmake diff --git a/Help/release/dev/add-FindGSL.rst b/Help/release/dev/add-FindGSL.rst new file mode 100644 index 0000000..47a0a25 --- /dev/null +++ b/Help/release/dev/add-FindGSL.rst @@ -0,0 +1,5 @@ +add-FindGSL +----------- + +* A :module:`FindGSL` module was introduced to find the + GNU Scientific Library. diff --git a/Modules/FindGSL.cmake b/Modules/FindGSL.cmake new file mode 100644 index 0000000..ef125c0 --- /dev/null +++ b/Modules/FindGSL.cmake @@ -0,0 +1,238 @@ +#.rst: +# FindGSL +# -------- +# +# Find the native GSL includes and libraries. +# +# The GNU Scientific Library (GSL) is a numerical library for C and C++ +# programmers. It is free software under the GNU General Public +# License. +# +# Imported Targets +# ^^^^^^^^^^^^^^^^ +# +# If GSL is found, this module defines the following :prop_tgt:`IMPORTED` +# targets:: +# +# GSL::gsl - The main GSL library. +# GSL::gslcblas - The CBLAS support library used by GSL. +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# This module will set the following variables in your project:: +# +# GSL_FOUND - True if GSL found on the local system +# GSL_INCLUDE_DIRS - Location of GSL header files. +# GSL_LIBRARIES - The GSL libraries. +# GSL_VERSION - The version of the discovered GSL install. +# +# Hints +# ^^^^^ +# +# Set ``GSL_ROOT_DIR`` to a directory that contains a GSL installation. +# +# This script expects to find libraries at ``$GSL_ROOT_DIR/lib`` and the GSL +# headers at ``$GSL_ROOT_DIR/include/gsl``. The library directory may +# optionally provide Release and Debug folders. For Unix-like systems, this +# script will use ``$GSL_ROOT_DIR/bin/gsl-config`` (if found) to aid in the +# discovery GSL. +# +# Cache Variables +# ^^^^^^^^^^^^^^^ +# +# This module may set the following variables depending on platform and type +# of GSL installation discovered. These variables may optionally be set to +# help this module find the correct files:: +# +# GSL_CLBAS_LIBRARY - Location of the GSL CBLAS library. +# GSL_CBLAS_LIBRARY_DEBUG - Location of the debug GSL CBLAS library (if any). +# GSL_CONFIG_EXECUTABLE - Location of the ``gsl-config`` script (if any). +# GSL_LIBRARY - Location of the GSL library. +# GSL_LIBRARY_DEBUG - Location of the debug GSL library (if any). +# + +#============================================================================= +# Copyright 2014 Kelly Thompson <kgt@lanl.gov> +# +# 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.) + +# Include these modules to handle the QUIETLY and REQUIRED arguments. +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + +#============================================================================= +# If the user has provided ``GSL_ROOT_DIR``, use it! Choose items found +# at this location over system locations. +if( EXISTS "$ENV{GSL_ROOT_DIR}" ) + file( TO_CMAKE_PATH "$ENV{GSL_ROOT_DIR}" GSL_ROOT_DIR ) + set( GSL_ROOT_DIR "${GSL_ROOT_DIR}" CACHE PATH "Prefix for GSL installation." ) +endif() +if( NOT EXISTS "${GSL_ROOT_DIR}" ) + set( GSL_USE_PKGCONFIG ON ) +endif() + +#============================================================================= +# As a first try, use the PkgConfig module. This will work on many +# *NIX systems. See :module:`findpkgconfig` +# This will return ``GSL_INCLUDEDIR`` and ``GSL_LIBDIR`` used below. +if( GSL_USE_PKGCONFIG ) + find_package(PkgConfig) + pkg_check_modules( GSL QUIET gsl ) + + if( EXISTS "${GSL_INCLUDEDIR}" ) + get_filename_component( GSL_ROOT_DIR "${GSL_INCLUDEDIR}" DIRECTORY CACHE) + endif() +endif() + +#============================================================================= +# Set GSL_INCLUDE_DIRS and GSL_LIBRARIES. If we skipped the PkgConfig step, try +# to find the libraries at $GSL_ROOT_DIR (if provided) or in standard system +# locations. These find_library and find_path calls will prefer custom +# locations over standard locations (HINTS). If the requested file is not found +# at the HINTS location, standard system locations will be still be searched +# (/usr/lib64 (Redhat), lib/i386-linux-gnu (Debian)). + +find_path( GSL_INCLUDE_DIR + NAMES gsl/gsl_sf.h + HINTS ${GSL_ROOT_DIR}/include ${GSL_INCLUDEDIR} +) +find_library( GSL_LIBRARY + NAMES gsl + HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} + PATH_SUFFIXES Release Debug +) +find_library( GSL_CBLAS_LIBRARY + NAMES gslcblas cblas + HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} + PATH_SUFFIXES Release Debug +) +# Do we also have debug versions? +find_library( GSL_LIBRARY_DEBUG + NAMES gsl + HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} + PATH_SUFFIXES Debug +) +find_library( GSL_CBLAS_LIBRARY_DEBUG + NAMES gslcblas cblas + HINTS ${GSL_ROOT_DIR}/lib ${GSL_LIBDIR} + PATH_SUFFIXES Debug +) +set( GSL_INCLUDE_DIRS ${GSL_INCLUDE_DIR} ) +set( GSL_LIBRARIES ${GSL_LIBRARY} ${GSL_CBLAS_LIBRARY} ) + +# If we didn't use PkgConfig, try to find the version via gsl-config or by +# reading gsl_version.h. +if( NOT GSL_VERSION ) + # 1. If gsl-config exists, query for the version. + find_program( GSL_CONFIG_EXECUTABLE + NAMES gsl-config + HINTS "${GSL_ROOT_DIR}/bin" + ) + if( EXISTS "${GSL_CONFIG_EXECUTABLE}" ) + execute_process( + COMMAND "${GSL_CONFIG_EXECUTABLE}" --version + OUTPUT_VARIABLE GSL_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE ) + endif() + + # 2. If gsl-config is not available, try looking in gsl/gsl_version.h + if( NOT GSL_VERSION AND EXISTS "${GSL_INCLUDE_DIRS}/gsl/gsl_version.h" ) + file( STRINGS "${GSL_INCLUDE_DIRS}/gsl/gsl_version.h" gsl_version_h_contents REGEX "define GSL_VERSION" ) + string( REGEX REPLACE ".*([0-9].[0-9][0-9]).*" "\\1" GSL_VERSION ${gsl_version_h_contents} ) + endif() + + # might also try scraping the directory name for a regex match "gsl-X.X" +endif() + +#============================================================================= +# handle the QUIETLY and REQUIRED arguments and set GSL_FOUND to TRUE if all +# listed variables are TRUE +find_package_handle_standard_args( GSL + FOUND_VAR + GSL_FOUND + REQUIRED_VARS + GSL_INCLUDE_DIR + GSL_LIBRARY + GSL_CBLAS_LIBRARY + VERSION_VAR + GSL_VERSION + ) + +mark_as_advanced( GSL_ROOT_DIR GSL_VERSION GSL_LIBRARY GSL_INCLUDE_DIR + GSL_CBLAS_LIBRARY GSL_LIBRARY_DEBUG GSL_CBLAS_LIBRARY_DEBUG + GSL_USE_PKGCONFIG GSL_CONFIG ) + +#============================================================================= +# Register imported libraries: +# 1. If we can find a Windows .dll file (or if we can find both Debug and +# Release libraries), we will set appropriate target properties for these. +# 2. However, for most systems, we will only register the import location and +# include directory. + +# Look for dlls, or Release and Debug libraries. +if(WIN32) + string( REPLACE ".lib" ".dll" GSL_LIBRARY_DLL "${GSL_LIBRARY}" ) + string( REPLACE ".lib" ".dll" GSL_CBLAS_LIBRARY_DLL "${GSL_CBLAS_LIBRARY}" ) + string( REPLACE ".lib" ".dll" GSL_LIBRARY_DEBUG_DLL "${GSL_LIBRARY_DEBUG}" ) + string( REPLACE ".lib" ".dll" GSL_CBLAS_LIBRARY_DEBUG_DLL "${GSL_CBLAS_LIBRARY_DEBUG}" ) +endif() + +if( GSL_FOUND AND NOT TARGET GSL::gsl ) + if( EXISTS "${GSL_LIBRARY_DLL}" AND EXISTS "${GSL_CBLAS_LIBRARY_DLL}") + + # Windows systems with dll libraries. + add_library( GSL::gsl SHARED IMPORTED ) + add_library( GSL::gslcblas SHARED IMPORTED ) + + # Windows with dlls, but only Release libraries. + set_target_properties( GSL::gslcblas PROPERTIES + IMPORTED_LOCATION_RELEASE "${GSL_CBLAS_LIBRARY_DLL}" + IMPORTED_IMPLIB "${GSL_CBLAS_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GSL_INCLUDE_DIRS}" + IMPORTED_CONFIGURATIONS Release + IMPORTED_LINK_INTERFACE_LANGUAGES "C" ) + set_target_properties( GSL::gsl PROPERTIES + IMPORTED_LOCATION_RELEASE "${GSL_LIBRARY_DLL}" + IMPORTED_IMPLIB "${GSL_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GSL_INCLUDE_DIRS}" + IMPORTED_CONFIGURATIONS Release + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + INTERFACE_LINK_LIBRARIES GSL::gslcblas ) + + # If we have both Debug and Release libraries + if( EXISTS "${GSL_LIBRARY_DEBUG_DLL}" AND EXISTS "${GSL_CBLAS_LIBRARY_DEBUG_DLL}") + set_property( TARGET GSL::gslcblas APPEND PROPERTY IMPORTED_CONFIGURATIONS Debug ) + set_target_properties( GSL::gslcblas PROPERTIES + IMPORTED_LOCATION_DEBUG "${GSL_CBLAS_LIBRARY_DEBUG_DLL}" + IMPORTED_IMPLIB_DEBUG "${GSL_CBLAS_LIBRARY_DEBUG}" ) + set_property( TARGET GSL::gsl APPEND PROPERTY IMPORTED_CONFIGURATIONS Debug ) + set_target_properties( GSL::gsl PROPERTIES + IMPORTED_LOCATION_DEBUG "${GSL_LIBRARY_DEBUG_DLL}" + IMPORTED_IMPLIB_DEBUG "${GSL_LIBRARY_DEBUG}" ) + endif() + + else() + + # For all other environments (ones without dll libraries), create + # the imported library targets. + add_library( GSL::gsl UNKNOWN IMPORTED ) + add_library( GSL::gslcblas UNKNOWN IMPORTED ) + set_target_properties( GSL::gslcblas PROPERTIES + IMPORTED_LOCATION "${GSL_CBLAS_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GSL_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" ) + set_target_properties( GSL::gsl PROPERTIES + IMPORTED_LOCATION "${GSL_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${GSL_INCLUDE_DIRS}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + INTERFACE_LINK_LIBRARIES GSL::gslcblas ) + endif() +endif() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a4c982f..97f57a3 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -39,6 +39,10 @@ else() set(CMAKE_USE_ELF_PARSER) endif() +if(APPLE) + set(CMAKE_USE_MACH_PARSER 1) +endif() + set(EXECUTABLE_OUTPUT_PATH ${CMake_BIN_DIR}) # ensure Unicode friendly APIs are used on Windows @@ -140,6 +144,11 @@ if(CMAKE_USE_ELF_PARSER) set(ELF_SRCS cmELF.h cmELF.cxx) endif() +# Check if we can build the Mach-O parser. +if(CMAKE_USE_MACH_PARSER) + set(MACH_SRCS cmMachO.h cmMachO.cxx) +endif() + # # Sources for CMakeLib # @@ -267,6 +276,7 @@ set(SRCS cmLocalGenerator.cxx cmLocalGenerator.h cmLocalUnixMakefileGenerator3.cxx + ${MACH_SRCS} cmMakeDepend.cxx cmMakeDepend.h cmMakefile.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a33b829..4c4c90d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 1) -set(CMake_VERSION_PATCH 20141222) +set(CMake_VERSION_PATCH 20141223) #set(CMake_VERSION_RC 1) diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index 2b0280d..79776f4 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -16,5 +16,6 @@ #cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE #cmakedefine HAVE_UNSETENV #cmakedefine CMAKE_USE_ELF_PARSER +#cmakedefine CMAKE_USE_MACH_PARSER #cmakedefine CMAKE_ENCODING_UTF8 #define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@" diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx new file mode 100644 index 0000000..1607845 --- /dev/null +++ b/Source/cmMachO.cxx @@ -0,0 +1,419 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + 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 "cmStandardIncludes.h" // to get CMAKE_USE_MACH_PARSER first +#include "cmMachO.h" + +#include <cmsys/FStream.hxx> + +// Include the Mach-O format information system header. +#include <mach-o/loader.h> +#include <mach-o/fat.h> + +/** + + https://developer.apple.com/library/mac/documentation/ + DeveloperTools/Conceptual/MachORuntime/index.html + + A Mach-O file has 3 major regions: header, load commands and segments. + Data Structures are provided from <mach-o/loader.h> which + correspond to the file structure. + + The header can be either a struct mach_header or struct mach_header_64. + One can peek at the first 4 bytes to identify the type of header. + + Following is the load command region which starts with + struct load_command, and is followed by n number of load commands. + + In the case of a universal binary (an archive of multiple Mach-O files), + the file begins with a struct fat_header and is followed by multiple + struct fat_arch instances. The struct fat_arch indicates the offset + for each Mach-O file. + + */ + +namespace { + + // peek in the file + template <typename T> + bool peek(cmsys::ifstream& fin, T &v) + { + std::streampos p = fin.tellg(); + if(!fin.read(reinterpret_cast<char*>(&v), sizeof(T))) + { + return false; + } + fin.seekg(p); + return fin.good(); + } + + // read from the file and fill a data structure + template <typename T> + bool read(cmsys::ifstream& fin, T& v) + { + if(!fin.read(reinterpret_cast<char*>(&v), sizeof(T))) + { + return false; + } + return true; + } + + // read from the file and fill multiple data structures where + // the vector has been resized + template <typename T> + bool read(cmsys::ifstream& fin, std::vector<T>& v) + { + // nothing to read + if(v.empty()) + { + return true; + } + if(!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size())) + { + return false; + } + return true; + } +} + + +// Contains header and load commands for a single Mach-O file +class cmMachOHeaderAndLoadCommands +{ +public: + // A load_command and its associated data + struct RawLoadCommand + { + uint32_t type(const cmMachOHeaderAndLoadCommands* m) const + { + if(this->LoadCommand.size() < sizeof(load_command)) + { + return 0; + } + const load_command* cmd = + reinterpret_cast<const load_command*>(&this->LoadCommand[0]); + return m->swap(cmd->cmd); + } + std::vector<char> LoadCommand; + }; + + cmMachOHeaderAndLoadCommands(bool _swap) + : Swap(_swap) + { + } + virtual ~cmMachOHeaderAndLoadCommands() + { + } + + virtual bool read_mach_o(cmsys::ifstream& fin) = 0; + + const std::vector<RawLoadCommand>& load_commands() const + { + return this->LoadCommands; + } + + uint32_t swap(uint32_t v) const + { + if(this->Swap) + { + char* c = reinterpret_cast<char*>(&v); + std::swap(c[0], c[3]); + std::swap(c[1], c[2]); + } + return v; + } + +protected: + bool read_load_commands(uint32_t ncmds, uint32_t sizeofcmds, + cmsys::ifstream& fin); + + bool Swap; + std::vector<RawLoadCommand> LoadCommands; +}; + +// Implementation for reading Mach-O header and load commands. +// This is 32 or 64 bit arch specific. +template <class T> +class cmMachOHeaderAndLoadCommandsImpl : public cmMachOHeaderAndLoadCommands +{ +public: + cmMachOHeaderAndLoadCommandsImpl(bool _swap) + : cmMachOHeaderAndLoadCommands(_swap) + { + } + bool read_mach_o(cmsys::ifstream& fin) + { + if(!read(fin, this->Header)) + { + return false; + } + this->Header.cputype = swap(this->Header.cputype); + this->Header.cpusubtype = swap(this->Header.cpusubtype); + this->Header.filetype = swap(this->Header.filetype); + this->Header.ncmds = swap(this->Header.ncmds); + this->Header.sizeofcmds = swap(this->Header.sizeofcmds); + this->Header.flags = swap(this->Header.flags); + + return read_load_commands(this->Header.ncmds, + this->Header.sizeofcmds, + fin); + } +protected: + T Header; +}; + + +bool cmMachOHeaderAndLoadCommands::read_load_commands(uint32_t ncmds, + uint32_t sizeofcmds, + cmsys::ifstream& fin) +{ + uint32_t size_read = 0; + this->LoadCommands.resize(ncmds); + for(uint32_t i = 0; i<ncmds; i++) + { + load_command lc; + if(!peek(fin, lc)) + { + return false; + } + lc.cmd = swap(lc.cmd); + lc.cmdsize = swap(lc.cmdsize); + size_read += lc.cmdsize; + + RawLoadCommand& c = this->LoadCommands[i]; + c.LoadCommand.resize(lc.cmdsize); + if(!read(fin, c.LoadCommand)) + { + return false; + } + } + + if(size_read != sizeofcmds) + { + this->LoadCommands.clear(); + return false; + } + + return true; +} + +//---------------------------------------------------------------------------- +class cmMachOInternal +{ +public: + cmMachOInternal(const char* fname); + ~cmMachOInternal(); + + // read a Mach-O file + bool read_mach_o(uint32_t file_offset); + + // the file we are reading + cmsys::ifstream Fin; + + // The archs in the universal binary + // If the binary is not a universal binary, this will be empty. + std::vector<fat_arch> FatArchs; + + // the error message while parsing + std::string ErrorMessage; + + // the list of Mach-O's + std::vector<cmMachOHeaderAndLoadCommands*> MachOList; +}; + +cmMachOInternal::cmMachOInternal(const char* fname) + : Fin(fname) +{ + // Quit now if the file could not be opened. + if(!this->Fin || !this->Fin.get() ) + { + this->ErrorMessage = "Error opening input file."; + return; + } + + if(!this->Fin.seekg(0)) + { + this->ErrorMessage = "Error seeking to beginning of file."; + return; + } + + // Read the binary identification block. + uint32_t magic = 0; + if(!peek(this->Fin, magic)) + { + this->ErrorMessage = "Error reading Mach-O identification."; + return; + } + + // Verify the binary identification. + if(!(magic == MH_CIGAM || + magic == MH_MAGIC || + magic == MH_CIGAM_64 || + magic == MH_MAGIC_64 || + magic == FAT_CIGAM || + magic == FAT_MAGIC)) + { + this->ErrorMessage = "File does not have a valid Mach-O identification."; + return; + } + + if(magic == FAT_MAGIC || magic == FAT_CIGAM) + { + // this is a universal binary + fat_header header; + if(!read(this->Fin, header)) + { + this->ErrorMessage = "Error reading fat header."; + return; + } + + // read fat_archs + this->FatArchs.resize(OSSwapBigToHostInt32(header.nfat_arch)); + if(!read(this->Fin, this->FatArchs)) + { + this->ErrorMessage = "Error reading fat header archs."; + return; + } + + // parse each Mach-O file + for(size_t i=0; i<this->FatArchs.size(); i++) + { + const fat_arch& arch = this->FatArchs[i]; + if(!this->read_mach_o(OSSwapBigToHostInt32(arch.offset))) + { + return; + } + } + } + else + { + // parse Mach-O file at the beginning of the file + this->read_mach_o(0); + } +} + +cmMachOInternal::~cmMachOInternal() +{ + for(size_t i=0; i<this->MachOList.size(); i++) + { + delete this->MachOList[i]; + } +} + +bool cmMachOInternal::read_mach_o(uint32_t file_offset) +{ + if(!this->Fin.seekg(file_offset)) + { + this->ErrorMessage = "Failed to locate Mach-O content."; + return false; + } + + uint32_t magic; + if(!peek(this->Fin, magic)) + { + this->ErrorMessage = "Error reading Mach-O identification."; + return false; + } + + cmMachOHeaderAndLoadCommands* f = NULL; + if(magic == MH_CIGAM || magic == MH_MAGIC) + { + bool swap = false; + if(magic == MH_CIGAM) + { + swap = true; + } + f = new cmMachOHeaderAndLoadCommandsImpl<mach_header>(swap); + } + else if(magic == MH_CIGAM_64 || magic == MH_MAGIC_64) + { + bool swap = false; + if(magic == MH_CIGAM_64) + { + swap = true; + } + f = new cmMachOHeaderAndLoadCommandsImpl<mach_header_64>(swap); + } + + if(f && f->read_mach_o(this->Fin)) + { + this->MachOList.push_back(f); + } + else + { + delete f; + this->ErrorMessage = "Failed to read Mach-O header."; + return false; + } + + return true; +} + +//============================================================================ +// External class implementation. + +//---------------------------------------------------------------------------- +cmMachO::cmMachO(const char* fname): Internal(0) +{ + this->Internal = new cmMachOInternal(fname); + +} + +//---------------------------------------------------------------------------- +cmMachO::~cmMachO() +{ + delete this->Internal; +} + +std::string const& cmMachO::GetErrorMessage() const +{ + return this->Internal->ErrorMessage; +} + +//---------------------------------------------------------------------------- +bool cmMachO::Valid() const +{ + return !this->Internal->MachOList.empty(); +} + +bool cmMachO::GetInstallName(std::string& install_name) +{ + if(this->Internal->MachOList.empty()) + { + return false; + } + + // grab the first Mach-O and get the install name from that one + cmMachOHeaderAndLoadCommands* macho = this->Internal->MachOList[0]; + for(size_t i=0; i<macho->load_commands().size(); i++) + { + const cmMachOHeaderAndLoadCommands::RawLoadCommand &cmd = + macho->load_commands()[i]; + uint32_t lc_cmd = cmd.type(macho); + if(lc_cmd == LC_ID_DYLIB || + lc_cmd == LC_LOAD_WEAK_DYLIB || + lc_cmd == LC_LOAD_DYLIB) + { + if(sizeof(dylib_command) < cmd.LoadCommand.size()) + { + uint32_t namelen = cmd.LoadCommand.size() - sizeof(dylib_command); + install_name.assign(&cmd.LoadCommand[sizeof(dylib_command)], namelen); + return true; + } + } + } + + return false; +} + +void cmMachO::PrintInfo(std::ostream& /*os*/) const +{ +} diff --git a/Source/cmMachO.h b/Source/cmMachO.h new file mode 100644 index 0000000..f06f8de --- /dev/null +++ b/Source/cmMachO.h @@ -0,0 +1,51 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2009 Kitware, Inc., Insight Software Consortium + + 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 cmMachO_h +#define cmMachO_h + +#if !defined(CMAKE_USE_MACH_PARSER) +# error "This file may be included only if CMAKE_USE_MACH_PARSER is enabled." +#endif + +class cmMachOInternal; + +/** \class cmMachO + * \brief Executable and Link Format (Mach-O) parser. + */ +class cmMachO +{ +public: + /** Construct with the name of the Mach-O input file to parse. */ + cmMachO(const char* fname); + + /** Destruct. */ + ~cmMachO(); + + /** Get the error message if any. */ + std::string const& GetErrorMessage() const; + + /** Boolean conversion. True if the Mach-O file is valid. */ + operator bool() const { return this->Valid(); } + + /** Get Install name from binary **/ + bool GetInstallName(std::string& install_name); + + /** Print human-readable information about the Mach-O file. */ + void PrintInfo(std::ostream& os) const; + +private: + friend class cmMachOInternal; + bool Valid() const; + cmMachOInternal* Internal; +}; + +#endif diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index c83dc2a..1c8c387 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -63,6 +63,10 @@ # include "cmELF.h" #endif +#if defined(CMAKE_USE_MACH_PARSER) +# include "cmMachO.h" +#endif + class cmSystemToolsFileTime { public: @@ -2357,31 +2361,17 @@ bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath, bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath, std::string& soname) { - std::vector<std::string> cmds; - cmds.push_back("otool"); - cmds.push_back("-D"); - cmds.push_back(fullPath); - - std::string output; - if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE)) +#if defined(CMAKE_USE_MACH_PARSER) + cmMachO macho(fullPath.c_str()); + if(macho) { - cmds.insert(cmds.begin(), "-r"); - cmds.insert(cmds.begin(), "xcrun"); - if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE)) - { - return false; - } + return macho.GetInstallName(soname); } +#else + (void)fullPath; + (void)soname; +#endif - std::vector<std::string> strs = cmSystemTools::tokenize(output, "\n"); - // otool returns extra lines reporting multiple install names - // in case the binary is multi-arch and none of the architectures - // is native (e.g. i386;ppc on x86_64) - if(strs.size() >= 2) - { - soname = strs[1]; - return true; - } return false; } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 8528042..8df27f4 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1243,6 +1243,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release endif() endif() + if(CMake_TEST_FindGSL) + add_subdirectory(FindGSL) + endif() + find_package(GTK2 QUIET) if(GTK2_FOUND) add_subdirectory(FindGTK2) diff --git a/Tests/FindGSL/CMakeLists.txt b/Tests/FindGSL/CMakeLists.txt new file mode 100644 index 0000000..45a3471 --- /dev/null +++ b/Tests/FindGSL/CMakeLists.txt @@ -0,0 +1,9 @@ +add_test(NAME FindGSL.rng COMMAND ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindGSL/rng" + "${CMake_BINARY_DIR}/Tests/FindGSL/rng" + ${build_generator_args} + --build-project FindGSL_rng + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V + ) diff --git a/Tests/FindGSL/rng/CMakeLists.txt b/Tests/FindGSL/rng/CMakeLists.txt new file mode 100644 index 0000000..b15d6ac --- /dev/null +++ b/Tests/FindGSL/rng/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.0) +project(FindGSL_rng CXX) +include(CTest) + +find_package(GSL REQUIRED) + +add_executable(tstgslrng_tgt main.cc) +target_link_libraries(tstgslrng_tgt GSL::gsl) +add_test(NAME tstgslrng_tgt COMMAND tstgslrng_tgt) + +add_executable(tstgslrng_var main.cc) +target_link_libraries(tstgslrng_var ${GSL_LIBRARIES}) +target_include_directories(tstgslrng_var PRIVATE ${GSL_INCLUDE_DIRS}) +add_test(NAME tstgslrng_var COMMAND tstgslrng_var) diff --git a/Tests/FindGSL/rng/main.cc b/Tests/FindGSL/rng/main.cc new file mode 100644 index 0000000..72543be --- /dev/null +++ b/Tests/FindGSL/rng/main.cc @@ -0,0 +1,24 @@ +#include <math.h> +#include "gsl/gsl_rng.h" + +int main() +{ + // return code + int retval = 1; + + // create a generator + gsl_rng *generator; + generator = gsl_rng_alloc(gsl_rng_mt19937); + + // Read a value. + double const Result = gsl_rng_uniform(generator); + + // Check value + double const expectedResult( 0.999741748906672 ); + if( fabs( expectedResult - Result ) < 1.0e-6 ) + retval = 0; + + // free allocated memory + gsl_rng_free(generator); + return retval; +} diff --git a/Utilities/Release/dash2win64_release.cmake b/Utilities/Release/dash2win64_release.cmake index 848e2f4..345870b 100644 --- a/Utilities/Release/dash2win64_release.cmake +++ b/Utilities/Release/dash2win64_release.cmake @@ -7,8 +7,13 @@ set(CPACK_BINARY_GENERATORS "NSIS ZIP") set(CPACK_SOURCE_GENERATORS "ZIP") set(MAKE_PROGRAM "make") set(MAKE "${MAKE_PROGRAM} -j8") +if(CMAKE_CREATE_VERSION STREQUAL "nightly") + set(CMAKE_USE_OPENSSL OFF) +else() + set(CMAKE_USE_OPENSSL ON) +endif() set(INITIAL_CACHE "CMAKE_BUILD_TYPE:STRING=Release -CMAKE_USE_OPENSSL:BOOL=ON +CMAKE_USE_OPENSSL:BOOL=${CMAKE_USE_OPENSSL} CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE CMAKE_Fortran_COMPILER:FILEPATH=FALSE CMAKE_GENERATOR:INTERNAL=Unix Makefiles diff --git a/Utilities/Release/dashmacmini5_release.cmake b/Utilities/Release/dashmacmini5_release.cmake index 6c9b8f4..910fcbd 100644 --- a/Utilities/Release/dashmacmini5_release.cmake +++ b/Utilities/Release/dashmacmini5_release.cmake @@ -8,16 +8,21 @@ set(MAKE "${MAKE_PROGRAM} -j5") set(CPACK_BINARY_GENERATORS "DragNDrop TGZ TZ") set(CPACK_SOURCE_GENERATORS "TGZ TZ") set(CPACK_DMG_FORMAT "UDBZ") #build using bzip2 for smaller package size +if(CMAKE_CREATE_VERSION STREQUAL "nightly") + set(CMAKE_USE_OPENSSL OFF) +else() + set(CMAKE_USE_OPENSSL ON) +endif() set(INITIAL_CACHE " -CMAKE_USE_OPENSSL:BOOL=ON +CMAKE_USE_OPENSSL:BOOL=${CMAKE_USE_OPENSSL} OPENSSL_CRYPTO_LIBRARY:FILEPATH=/Users/kitware/openssl-1.0.1g-install/lib/libcrypto.a OPENSSL_INCLUDE_DIR:PATH=/Users/kitware/openssl-1.0.1g-install/include OPENSSL_SSL_LIBRARY:FILEPATH=/Users/kitware/openssl-1.0.1g-install/lib/libssl.a CMAKE_BUILD_TYPE:STRING=Release CMAKE_OSX_ARCHITECTURES:STRING=x86_64 -CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.5 +CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.6 CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE -CPACK_SYSTEM_NAME:STRING=Darwin64-universal +CPACK_SYSTEM_NAME:STRING=Darwin-x86_64 BUILD_QtDialog:BOOL=TRUE CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:BOOL=TRUE QT_QMAKE_EXECUTABLE:FILEPATH=/Users/kitware/Support/qt-4.8.0/install/bin/qmake |