ENH: Implement linking with paths to library files instead of -L and -l separation. See bug #3832
- This is purely an implementation improvement. No interface has changed. - Create cmComputeLinkInformation class - Move and re-implement logic from: cmLocalGenerator::ComputeLinkInformation cmOrderLinkDirectories - Link libraries to targets with their full path (if it is known) - Dirs specified with link_directories command still added with -L - Make link type specific to library names without paths (name libfoo.a without path becomes -Wl,-Bstatic -lfoo) - Make directory ordering specific to a runtime path computation feature (look for conflicting SONAMEs instead of library names) - Implement proper rpath support on HP-UX and AIX.
This commit is contained in:
parent
0df9e6904c
commit
96fd5909d9
|
@ -149,6 +149,14 @@ IF(NOT CMAKE_C_LINK_EXECUTABLE)
|
|||
"<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||
ENDIF(NOT CMAKE_C_LINK_EXECUTABLE)
|
||||
|
||||
IF(NOT CMAKE_EXECUTABLE_RUNTIME_C_FLAG)
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_C_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG})
|
||||
ENDIF(NOT CMAKE_EXECUTABLE_RUNTIME_C_FLAG)
|
||||
|
||||
IF(NOT CMAKE_EXECUTABLE_RUNTIME_C_FLAG_SEP)
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_C_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP})
|
||||
ENDIF(NOT CMAKE_EXECUTABLE_RUNTIME_C_FLAG_SEP)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
CMAKE_C_FLAGS
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
|
|
|
@ -84,6 +84,18 @@ IF(NOT CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP)
|
|||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP})
|
||||
ENDIF(NOT CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP)
|
||||
|
||||
IF(NOT CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG)
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG})
|
||||
ENDIF(NOT CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG)
|
||||
|
||||
IF(NOT CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG_SEP)
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP})
|
||||
ENDIF(NOT CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG_SEP)
|
||||
|
||||
IF(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_CXX_WITH_RUNTIME_PATH)
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_C_WITH_RUNTIME_PATH})
|
||||
ENDIF(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_CXX_WITH_RUNTIME_PATH)
|
||||
|
||||
IF(NOT CMAKE_INCLUDE_FLAG_CXX)
|
||||
SET(CMAKE_INCLUDE_FLAG_CXX ${CMAKE_INCLUDE_FLAG_C})
|
||||
ENDIF(NOT CMAKE_INCLUDE_FLAG_CXX)
|
||||
|
|
|
@ -76,6 +76,18 @@ IF(NOT CMAKE_SHARED_MODULE_RUNTIME_Fortran_FLAG_SEP)
|
|||
SET(CMAKE_SHARED_MODULE_RUNTIME_Fortran_FLAG_SEP ${CMAKE_SHARED_MODULE_RUNTIME_C_FLAG_SEP})
|
||||
ENDIF(NOT CMAKE_SHARED_MODULE_RUNTIME_Fortran_FLAG_SEP)
|
||||
|
||||
IF(NOT CMAKE_EXECUTABLE_RUNTIME_Fortran_FLAG)
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_Fortran_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG})
|
||||
ENDIF(NOT CMAKE_EXECUTABLE_RUNTIME_Fortran_FLAG)
|
||||
|
||||
IF(NOT CMAKE_EXECUTABLE_RUNTIME_Fortran_FLAG_SEP)
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_Fortran_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG_SEP})
|
||||
ENDIF(NOT CMAKE_EXECUTABLE_RUNTIME_Fortran_FLAG_SEP)
|
||||
|
||||
IF(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_Fortran_WITH_RUNTIME_PATH)
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_Fortran_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_C_WITH_RUNTIME_PATH})
|
||||
ENDIF(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_Fortran_WITH_RUNTIME_PATH)
|
||||
|
||||
IF(NOT CMAKE_INCLUDE_FLAG_Fortran)
|
||||
SET(CMAKE_INCLUDE_FLAG_Fortran ${CMAKE_INCLUDE_FLAG_C})
|
||||
ENDIF(NOT CMAKE_INCLUDE_FLAG_Fortran)
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
SET(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib
|
||||
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so
|
||||
SET(CMAKE_DL_LIBS "-lld")
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-G -Wl,-brtl") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,-brtl,-bexpall") # +s, flag for exe link to use shared lib
|
||||
|
||||
# RPATH support on AIX is called libpath. By default the runtime
|
||||
# libpath is paths specified by -L followed by /usr/lib and /lib. In
|
||||
# order to prevent the -L paths from being used we must force use of
|
||||
# -Wl,-blibpath:/usr/lib:/lib whether RPATH support is on or not.
|
||||
# When our own RPATH is to be added it may be inserted before the
|
||||
# "always" paths.
|
||||
SET(CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH /usr/lib /lib)
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-blibpath:")
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":")
|
||||
|
||||
# CXX Compiler
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-shared -Wl,-G") # -shared
|
||||
ELSE(CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-G -Wl,-brtl") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-Wl,-brtl,-bexpall") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-G -Wl,-brtl,-bnoipath") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-Wl,-brtl,-bnoipath,-bexpall") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_CXX_FLAGS " ")
|
||||
SET(CMAKE_SHARED_MODULE_CXX_FLAGS " ")
|
||||
SET (CMAKE_CXX_FLAGS_DEBUG_INIT "-g")
|
||||
|
@ -22,8 +30,8 @@ ENDIF(CMAKE_COMPILER_IS_GNUCXX)
|
|||
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared -Wl,-G") # -shared
|
||||
ELSE(CMAKE_COMPILER_IS_GNUCC)
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-G -Wl,-brtl") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,-brtl,-bexpall") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-G -Wl,-brtl,-bnoipath") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,-brtl,-bnoipath,-bexpall") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_C_FLAGS " ")
|
||||
SET(CMAKE_SHARED_MODULE_C_FLAGS " ")
|
||||
SET (CMAKE_C_FLAGS_DEBUG_INIT "-g")
|
||||
|
|
|
@ -2,15 +2,18 @@ SET(CMAKE_SHARED_LIBRARY_SUFFIX ".sl") # .so
|
|||
SET(CMAKE_DL_LIBS "dld")
|
||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".sl" ".so" ".a")
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":") # : or empty
|
||||
# The HP linker needs to find transitive shared library dependencies
|
||||
# in the -L path. Therefore the runtime path must be added to the
|
||||
# link line with -L flags.
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_WITH_RUNTIME_PATH 1)
|
||||
|
||||
# fortran
|
||||
IF(CMAKE_COMPILER_IS_GNUG77)
|
||||
SET(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "-fPIC") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-shared -Wl,-E -Wl,-b") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,+s -Wl,-E") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,+b") # -rpath
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":") # : or empty
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-shared -Wl,-E,-b,+nodefaultrpath") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "-Wl,+s,-E,+nodefaultrpath") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG "-Wl,+b") # -rpath
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG_SEP ":") # : or empty
|
||||
SET(CMAKE_SHARED_LIBRARY_SONAME_Fortran_FLAG "-Wl,+h")
|
||||
SET(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "-fPIC") # -pic
|
||||
ELSE(CMAKE_COMPILER_IS_GNUG77)
|
||||
|
@ -19,16 +22,19 @@ ELSE(CMAKE_COMPILER_IS_GNUG77)
|
|||
"ld <CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_Fortran_FLAG><TARGET_SONAME> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
|
||||
SET(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "+Z") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-E -b -L/usr/lib") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,+s -Wl,-E") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "+b") # -rpath
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS "-Wl,+s,-E,+nodefaultrpath") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG "+b") # -rpath
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG_SEP ":") # : or empty
|
||||
SET(CMAKE_SHARED_LIBRARY_SONAME_Fortran_FLAG "+h")
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_Fortran_FLAG "-Wl,+b") # -rpath
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUG77)
|
||||
|
||||
# C compiler
|
||||
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||
# gnu gcc
|
||||
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "-fPIC") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared -Wl,-E -Wl,-b") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,+s -Wl,-E") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared -Wl,-E,-b,+nodefaultrpath") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,+s,-E,+nodefaultrpath") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,+b") # -rpath
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":") # : or empty
|
||||
SET(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,+h")
|
||||
|
@ -40,28 +46,33 @@ ELSE(CMAKE_COMPILER_IS_GNUCC)
|
|||
SET(CMAKE_C_CREATE_SHARED_LIBRARY
|
||||
"ld <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
|
||||
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "+Z") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-E -b -L/usr/lib") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,+s -Wl,-E") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-E -b +nodefaultrpath -L/usr/lib") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,+s,-E,+nodefaultrpath") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "+b") # -rpath
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":") # : or empty
|
||||
SET(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "+h")
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_C_FLAG "-Wl,+b") # -rpath
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
# CXX compiler
|
||||
IF(CMAKE_COMPILER_IS_GNUCXX)
|
||||
# for gnu C++
|
||||
SET(CMAKE_SHARED_LIBRARY_CXX_FLAGS "-fPIC") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-shared -Wl,-E -Wl,-b") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-Wl,+s -Wl,-E") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-shared -Wl,-E,-b,+nodefaultrpath") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-Wl,+s,-E,+nodefaultrpath") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG "-Wl,+b") # -rpath
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP ":") # : or empty
|
||||
SET(CMAKE_SHARED_LIBRARY_CXX_FLAGS "-fPIC") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG "-Wl,+h")
|
||||
ELSE(CMAKE_COMPILER_IS_GNUCXX)
|
||||
# for hp aCC
|
||||
SET(CMAKE_SHARED_LIBRARY_CXX_FLAGS "+Z") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "+Z -Wl,-E -b -L/usr/lib") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-Wl,+s -Wl,-E") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "+Z -Wl,-E -b +nodefaultrpath -L/usr/lib") # -shared
|
||||
SET(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-Wl,+s,-E,+nodefaultrpath") # +s, flag for exe link to use shared lib
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG "-Wl,+b") # -rpath
|
||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP ":") # : or empty
|
||||
SET(CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG "-Wl,+h")
|
||||
SET(CMAKE_EXECUTABLE_RUNTIME_CXX_FLAG "-Wl,+b") # -rpath
|
||||
SET (CMAKE_CXX_FLAGS_INIT "")
|
||||
SET (CMAKE_CXX_FLAGS_DEBUG_INIT "-g")
|
||||
SET (CMAKE_CXX_FLAGS_MINSIZEREL_INIT "+O3 -DNDEBUG")
|
||||
|
|
|
@ -87,6 +87,8 @@ SET(SRCS
|
|||
cmCommandArgumentLexer.cxx
|
||||
cmCommandArgumentParser.cxx
|
||||
cmCommandArgumentParserHelper.cxx
|
||||
cmComputeLinkInformation.cxx
|
||||
cmComputeLinkInformation.h
|
||||
cmCustomCommand.cxx
|
||||
cmCustomCommand.h
|
||||
cmDepends.cxx
|
||||
|
@ -151,7 +153,6 @@ SET(SRCS
|
|||
cmMakefileExecutableTargetGenerator.cxx
|
||||
cmMakefileLibraryTargetGenerator.cxx
|
||||
cmMakefileUtilityTargetGenerator.cxx
|
||||
cmOrderLinkDirectories.cxx
|
||||
cmProperty.cxx
|
||||
cmProperty.h
|
||||
cmPropertyDefinition.cxx
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,165 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmComputeLinkInformation_h
|
||||
#define cmComputeLinkInformation_h
|
||||
|
||||
#include "cmStandardIncludes.h"
|
||||
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
class cmGlobalGenerator;
|
||||
class cmLocalGenerator;
|
||||
class cmMakefile;
|
||||
class cmTarget;
|
||||
|
||||
/** \class cmComputeLinkInformation
|
||||
* \brief Compute link information for a target in one configuration.
|
||||
*/
|
||||
class cmComputeLinkInformation
|
||||
{
|
||||
public:
|
||||
cmComputeLinkInformation(cmTarget* target, const char* config);
|
||||
bool Compute();
|
||||
|
||||
struct Item
|
||||
{
|
||||
Item(): Value(), IsPath(true) {}
|
||||
Item(Item const& item): Value(item.Value), IsPath(item.IsPath) {}
|
||||
Item(std::string const& v, bool p): Value(v), IsPath(p) {}
|
||||
std::string Value;
|
||||
bool IsPath;
|
||||
};
|
||||
typedef std::vector<Item> ItemVector;
|
||||
ItemVector const& GetItems();
|
||||
std::vector<std::string> const& GetDirectories();
|
||||
std::vector<std::string> const& GetDepends();
|
||||
std::vector<std::string> const& GetFrameworkPaths();
|
||||
const char* GetLinkLanguage() const { return this->LinkLanguage; }
|
||||
std::vector<std::string> const& GetRuntimeSearchPath();
|
||||
private:
|
||||
void AddItem(std::string const& item);
|
||||
|
||||
// Output information.
|
||||
ItemVector Items;
|
||||
std::vector<std::string> Directories;
|
||||
std::vector<std::string> Depends;
|
||||
std::vector<std::string> FrameworkPaths;
|
||||
std::vector<std::string> RuntimeSearchPath;
|
||||
|
||||
// Context information.
|
||||
cmTarget* Target;
|
||||
cmMakefile* Makefile;
|
||||
cmLocalGenerator* LocalGenerator;
|
||||
cmGlobalGenerator* GlobalGenerator;
|
||||
|
||||
// Configuration information.
|
||||
const char* Config;
|
||||
const char* LinkLanguage;
|
||||
|
||||
// System info.
|
||||
bool UseImportLibrary;
|
||||
const char* LoaderFlag;
|
||||
std::string LibLinkFlag;
|
||||
std::string LibLinkSuffix;
|
||||
|
||||
// Link type adjustment.
|
||||
void ComputeLinkTypeInfo();
|
||||
enum LinkType { LinkUnknown, LinkStatic, LinkShared };
|
||||
LinkType StartLinkType;
|
||||
LinkType CurrentLinkType;
|
||||
std::string StaticLinkTypeFlag;
|
||||
std::string SharedLinkTypeFlag;
|
||||
bool LinkTypeEnabled;
|
||||
void SetCurrentLinkType(LinkType lt);
|
||||
|
||||
// Link item parsing.
|
||||
void ComputeItemParserInfo();
|
||||
std::vector<std::string> StaticLinkExtensions;
|
||||
std::vector<std::string> SharedLinkExtensions;
|
||||
std::vector<std::string> LinkExtensions;
|
||||
std::set<cmStdString> LinkPrefixes;
|
||||
cmsys::RegularExpression RemoveLibraryExtension;
|
||||
cmsys::RegularExpression ExtractStaticLibraryName;
|
||||
cmsys::RegularExpression ExtractSharedLibraryName;
|
||||
cmsys::RegularExpression ExtractAnyLibraryName;
|
||||
void AddLinkPrefix(const char* p);
|
||||
void AddLinkExtension(const char* e, LinkType type);
|
||||
std::string CreateExtensionRegex(std::vector<std::string> const& exts);
|
||||
std::string NoCaseExpression(const char* str);
|
||||
|
||||
// Handling of link items that are not targets or full file paths.
|
||||
void AddUserItem(std::string const& item);
|
||||
void AddDirectoryItem(std::string const& item);
|
||||
void AddFrameworkItem(std::string const& item);
|
||||
void DropDirectoryItem(std::string const& item);
|
||||
|
||||
// Framework info.
|
||||
void ComputeFrameworkInfo();
|
||||
void AddFrameworkPath(std::string const& p);
|
||||
std::set<cmStdString> FrameworkPathsEmmitted;
|
||||
cmsys::RegularExpression SplitFramework;
|
||||
|
||||
// Linker search path computation.
|
||||
void ComputeLinkerSearchDirectories();
|
||||
void AddLinkerSearchDirectories(std::vector<std::string> const& dirs);
|
||||
std::set<cmStdString> DirectoriesEmmitted;
|
||||
|
||||
// Runtime path computation.
|
||||
struct LibraryRuntimeEntry
|
||||
{
|
||||
// The file name of the library.
|
||||
std::string FileName;
|
||||
|
||||
// The soname of the shared library if it is known.
|
||||
std::string SOName;
|
||||
|
||||
// The directory in which the library is supposed to be found.
|
||||
std::string Directory;
|
||||
|
||||
// The index assigned to the directory.
|
||||
int DirectoryIndex;
|
||||
};
|
||||
bool RuntimeSearchPathComputed;
|
||||
std::vector<LibraryRuntimeEntry> LibraryRuntimeInfo;
|
||||
std::set<cmStdString> LibraryRuntimeInfoEmmitted;
|
||||
std::vector<std::string> RuntimeDirectories;
|
||||
std::map<cmStdString, int> RuntimeDirectoryIndex;
|
||||
std::vector<char> RuntimeDirectoryVisited;
|
||||
void AddLibraryRuntimeInfo(std::string const& fullPath, cmTarget* target);
|
||||
void AddLibraryRuntimeInfo(std::string const& fullPath,
|
||||
const char* soname = 0);
|
||||
void CollectRuntimeDirectories();
|
||||
int AddRuntimeDirectory(std::string const& dir);
|
||||
void FindConflictingLibraries();
|
||||
void FindDirectoriesForLib(unsigned int lri);
|
||||
void OrderRuntimeSearchPath();
|
||||
void VisitRuntimeDirectory(unsigned int i, bool top);
|
||||
void DiagnoseCycle();
|
||||
bool CycleDiagnosed;
|
||||
|
||||
// Adjacency-list representation of runtime path ordering graph.
|
||||
// This maps from directory to those that must come *before* it.
|
||||
// Each entry that must come before is a pair. The first element is
|
||||
// the index of the directory that must come first. The second
|
||||
// element is the index of the runtime library that added the
|
||||
// constraint.
|
||||
typedef std::pair<int, int> RuntimeConflictPair;
|
||||
struct RuntimeConflictList: public std::vector<RuntimeConflictPair> {};
|
||||
std::vector<RuntimeConflictList> RuntimeConflictGraph;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1035,6 +1035,12 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
|
|||
cmProperty::VARIABLE,0,0);
|
||||
cm->DefineProperty("CMAKE_SHARED_LIBRARY_RUNTIME_<LANG>_FLAG_SEP",
|
||||
cmProperty::VARIABLE,0,0);
|
||||
cm->DefineProperty("CMAKE_EXECUTABLE_RUNTIME_<LANG>_FLAG",
|
||||
cmProperty::VARIABLE,0,0);
|
||||
cm->DefineProperty("CMAKE_EXECUTABLE_RUNTIME_<LANG>_FLAG_SEP",
|
||||
cmProperty::VARIABLE,0,0);
|
||||
cm->DefineProperty("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH",
|
||||
cmProperty::VARIABLE,0,0);
|
||||
cm->DefineProperty("CMAKE_SHARED_MODULE_CREATE_<LANG>_FLAGS",
|
||||
cmProperty::VARIABLE,0,0);
|
||||
cm->DefineProperty("CMAKE_SHARED_MODULE_<LANG>_FLAGS",
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "cmVersion.h"
|
||||
#include "cmInstallExportGenerator.h"
|
||||
|
||||
#include <cmsys/Directory.hxx>
|
||||
|
||||
#include <stdlib.h> // required for atof
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -784,7 +786,7 @@ void cmGlobalGenerator::Generate()
|
|||
// Compute the manifest of main targets generated.
|
||||
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
||||
{
|
||||
this->LocalGenerators[i]->GenerateTargetManifest(this->TargetManifest);
|
||||
this->LocalGenerators[i]->GenerateTargetManifest();
|
||||
}
|
||||
|
||||
// Create a map from local generator to the complete set of targets
|
||||
|
@ -1880,3 +1882,42 @@ cmGlobalGenerator
|
|||
this->FilesReplacedDuringGenerate.end(),
|
||||
std::back_inserter(filenames));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmGlobalGenerator::AddToManifest(const char* config,
|
||||
std::string const& f)
|
||||
{
|
||||
// Add to the main manifest for this configuration.
|
||||
this->TargetManifest[config].insert(f);
|
||||
|
||||
// Add to the content listing for the file's directory.
|
||||
std::string dir = cmSystemTools::GetFilenamePath(f);
|
||||
std::string file = cmSystemTools::GetFilenameName(f);
|
||||
this->DirectoryContentMap[dir].insert(file);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::set<cmStdString> const&
|
||||
cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
|
||||
{
|
||||
DirectoryContent& dc = this->DirectoryContentMap[dir];
|
||||
if(needDisk && !dc.LoadedFromDisk)
|
||||
{
|
||||
// Load the directory content from disk.
|
||||
cmsys::Directory d;
|
||||
if(d.Load(dir.c_str()))
|
||||
{
|
||||
unsigned long n = d.GetNumberOfFiles();
|
||||
for(unsigned long i = 0; i < n; ++i)
|
||||
{
|
||||
const char* f = d.GetFile(i);
|
||||
if(strcmp(f, ".") != 0 && strcmp(f, "..") != 0)
|
||||
{
|
||||
dc.insert(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
dc.LoadedFromDisk = true;
|
||||
}
|
||||
return dc;
|
||||
}
|
||||
|
|
|
@ -150,6 +150,9 @@ public:
|
|||
///! Get the export target set with the given name
|
||||
const std::vector<cmTargetExport*>* GetExportSet(const char* name) const;
|
||||
|
||||
/** Add a file to the manifest of generated targets for a configuration. */
|
||||
void AddToManifest(const char* config, std::string const& f);
|
||||
|
||||
void EnableInstallTarget();
|
||||
|
||||
int TryCompileTimeout;
|
||||
|
@ -209,6 +212,13 @@ public:
|
|||
configuration. This is valid during generation only. */
|
||||
cmTargetManifest const& GetTargetManifest() { return this->TargetManifest; }
|
||||
|
||||
/** Get the content of a directory on disk including the target
|
||||
files to be generated. This may be called only during the
|
||||
generation step. It is intended for use only by
|
||||
cmComputeLinkInformation. */
|
||||
std::set<cmStdString> const& GetDirectoryContent(std::string const& dir,
|
||||
bool needDisk);
|
||||
|
||||
void AddTarget(cmTargets::value_type &v);
|
||||
|
||||
virtual const char* GetAllTargetName() { return "ALL_BUILD"; }
|
||||
|
@ -304,6 +314,17 @@ private:
|
|||
std::vector<cmTarget const*>& steps);
|
||||
typedef std::map<cmTarget const*, TargetDependSet> TargetDependMap;
|
||||
TargetDependMap TargetDependencies;
|
||||
|
||||
// Cache directory content and target files to be built.
|
||||
struct DirectoryContent: public std::set<cmStdString>
|
||||
{
|
||||
typedef std::set<cmStdString> derived;
|
||||
bool LoadedFromDisk;
|
||||
DirectoryContent(): LoadedFromDisk(false) {}
|
||||
DirectoryContent(DirectoryContent const& dc):
|
||||
derived(dc), LoadedFromDisk(dc.LoadedFromDisk) {}
|
||||
};
|
||||
std::map<cmStdString, DirectoryContent> DirectoryContentMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,7 @@ PURPOSE. See the above copyright notices for more information.
|
|||
#include "cmXCode21Object.h"
|
||||
#include "cmake.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmSourceFile.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -2107,23 +2108,27 @@ void cmGlobalXCodeGenerator
|
|||
}
|
||||
|
||||
// Compute the link library and directory information.
|
||||
std::vector<cmStdString> libNames;
|
||||
std::vector<cmStdString> libDirs;
|
||||
std::vector<cmStdString> fullPathLibs;
|
||||
this->CurrentLocalGenerator->ComputeLinkInformation(*cmtarget, configName,
|
||||
libNames, libDirs,
|
||||
&fullPathLibs);
|
||||
cmComputeLinkInformation cli(cmtarget, configName);
|
||||
if(!cli.Compute())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add dependencies directly on library files.
|
||||
for(std::vector<cmStdString>::iterator j = fullPathLibs.begin();
|
||||
j != fullPathLibs.end(); ++j)
|
||||
{
|
||||
std::vector<std::string> const& libDeps = cli.GetDepends();
|
||||
for(std::vector<std::string>::const_iterator j = libDeps.begin();
|
||||
j != libDeps.end(); ++j)
|
||||
{
|
||||
target->AddDependLibrary(configName, j->c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string linkDirs;
|
||||
// add the library search paths
|
||||
for(std::vector<cmStdString>::const_iterator libDir = libDirs.begin();
|
||||
{
|
||||
std::vector<std::string> const& libDirs = cli.GetDirectories();
|
||||
std::string linkDirs;
|
||||
for(std::vector<std::string>::const_iterator libDir = libDirs.begin();
|
||||
libDir != libDirs.end(); ++libDir)
|
||||
{
|
||||
if(libDir->size() && *libDir != "/usr/lib")
|
||||
|
@ -2141,45 +2146,50 @@ void cmGlobalXCodeGenerator
|
|||
}
|
||||
this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
|
||||
linkDirs.c_str(), configName);
|
||||
}
|
||||
|
||||
// add the framework search paths
|
||||
{
|
||||
const char* sep = "";
|
||||
std::string fdirs;
|
||||
std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
|
||||
for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
|
||||
fdi != fwDirs.end(); ++fdi)
|
||||
{
|
||||
fdirs += sep;
|
||||
sep = " ";
|
||||
fdirs += this->XCodeEscapePath(fdi->c_str());
|
||||
}
|
||||
if(!fdirs.empty())
|
||||
{
|
||||
this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
|
||||
fdirs.c_str(), configName);
|
||||
}
|
||||
}
|
||||
|
||||
// now add the link libraries
|
||||
if(cmtarget->GetType() != cmTarget::STATIC_LIBRARY)
|
||||
{
|
||||
std::string fdirs;
|
||||
std::set<cmStdString> emitted;
|
||||
emitted.insert("/System/Library/Frameworks");
|
||||
for(std::vector<cmStdString>::iterator lib = libNames.begin();
|
||||
lib != libNames.end(); ++lib)
|
||||
std::string linkLibs;
|
||||
const char* sep = "";
|
||||
typedef cmComputeLinkInformation::ItemVector ItemVector;
|
||||
ItemVector const& libNames = cli.GetItems();
|
||||
for(ItemVector::const_iterator li = libNames.begin();
|
||||
li != libNames.end(); ++li)
|
||||
{
|
||||
std::string& libString = *lib;
|
||||
// check to see if this is a -F framework path and extract it if it is
|
||||
// -F framework stuff should be in the FRAMEWORK_SEARCH_PATHS and not
|
||||
// OTHER_LDFLAGS
|
||||
if(libString.size() > 2 && libString[0] == '-'
|
||||
&& libString[1] == 'F')
|
||||
linkLibs += sep;
|
||||
sep = " ";
|
||||
if(li->IsPath)
|
||||
{
|
||||
std::string path = libString.substr(2);
|
||||
// remove escaped spaces from the path
|
||||
cmSystemTools::ReplaceString(path, "\\ ", " ");
|
||||
if(emitted.insert(path).second)
|
||||
{
|
||||
if(fdirs.size())
|
||||
{
|
||||
fdirs += " ";
|
||||
}
|
||||
fdirs += this->XCodeEscapePath(path.c_str());
|
||||
}
|
||||
linkLibs += this->XCodeEscapePath(li->Value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS",
|
||||
lib->c_str(), configName);
|
||||
linkLibs += li->Value;
|
||||
}
|
||||
}
|
||||
if(fdirs.size())
|
||||
{
|
||||
this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
|
||||
fdirs.c_str(), configName);
|
||||
}
|
||||
this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS",
|
||||
linkLibs.c_str(), configName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
=========================================================================*/
|
||||
#include "cmLocalGenerator.h"
|
||||
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmInstallGenerator.h"
|
||||
|
@ -23,7 +24,6 @@
|
|||
#include "cmInstallScriptGenerator.h"
|
||||
#include "cmInstallTargetGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmOrderLinkDirectories.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmTest.h"
|
||||
#include "cmake.h"
|
||||
|
@ -477,7 +477,7 @@ void cmLocalGenerator::GenerateInstallRules()
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmLocalGenerator::GenerateTargetManifest(cmTargetManifest& manifest)
|
||||
void cmLocalGenerator::GenerateTargetManifest()
|
||||
{
|
||||
// Collect the set of configuration types.
|
||||
std::vector<std::string> configNames;
|
||||
|
@ -500,34 +500,17 @@ void cmLocalGenerator::GenerateTargetManifest(cmTargetManifest& manifest)
|
|||
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
|
||||
{
|
||||
cmTarget& target = t->second;
|
||||
cmTarget::TargetType type = target.GetType();
|
||||
if(type == cmTarget::STATIC_LIBRARY ||
|
||||
type == cmTarget::SHARED_LIBRARY ||
|
||||
type == cmTarget::MODULE_LIBRARY ||
|
||||
type == cmTarget::EXECUTABLE)
|
||||
if(configNames.empty())
|
||||
{
|
||||
if(configNames.empty())
|
||||
target.GenerateTargetManifest(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::vector<std::string>::iterator ci = configNames.begin();
|
||||
ci != configNames.end(); ++ci)
|
||||
{
|
||||
manifest[""].insert(target.GetFullPath(0, false));
|
||||
if(type == cmTarget::SHARED_LIBRARY &&
|
||||
this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
|
||||
{
|
||||
manifest[""].insert(target.GetFullPath(0, true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::vector<std::string>::iterator ci = configNames.begin();
|
||||
ci != configNames.end(); ++ci)
|
||||
{
|
||||
const char* config = ci->c_str();
|
||||
manifest[config].insert(target.GetFullPath(config, false));
|
||||
if(type == cmTarget::SHARED_LIBRARY &&
|
||||
this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
|
||||
{
|
||||
manifest[config].insert(target.GetFullPath(config, true));
|
||||
}
|
||||
}
|
||||
const char* config = ci->c_str();
|
||||
target.GenerateTargetManifest(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1478,50 +1461,53 @@ bool cmLocalGenerator::GetLinkerArgs(std::string& rpath,
|
|||
// collect all the flags needed for linking libraries
|
||||
linkLibs = "";
|
||||
|
||||
// Try to emit each search path once
|
||||
std::set<cmStdString> emitted;
|
||||
// Embed runtime search paths if possible and if required.
|
||||
bool outputRuntime = true;
|
||||
std::string runtimeFlag;
|
||||
std::string runtimeSep;
|
||||
|
||||
const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
|
||||
const char* linkLanguage =
|
||||
tgt.GetLinkerLanguage(this->GetGlobalGenerator());
|
||||
if(!linkLanguage)
|
||||
|
||||
cmComputeLinkInformation cli(&tgt, config);
|
||||
if(!cli.Compute())
|
||||
{
|
||||
cmSystemTools::
|
||||
Error("CMake can not determine linker language for target:",
|
||||
tgt.GetName());
|
||||
return false;
|
||||
}
|
||||
std::string runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
|
||||
runTimeFlagVar += linkLanguage;
|
||||
runTimeFlagVar += "_FLAG";
|
||||
std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP";
|
||||
runtimeFlag = this->Makefile->GetSafeDefinition(runTimeFlagVar.c_str());
|
||||
runtimeSep = this->Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str());
|
||||
|
||||
const char* linkLanguage = cli.GetLinkLanguage();
|
||||
|
||||
// Embed runtime search paths if possible and if required.
|
||||
bool outputRuntime = !this->Makefile->IsOn("CMAKE_SKIP_RPATH");
|
||||
|
||||
// Lookup rpath specification flags.
|
||||
std::string runtimeFlag;
|
||||
std::string runtimeSep;
|
||||
if(tgt.GetType() != cmTarget::STATIC_LIBRARY)
|
||||
{
|
||||
std::string runTimeFlagVar = "CMAKE_";
|
||||
if(tgt.GetType() == cmTarget::EXECUTABLE)
|
||||
{
|
||||
runTimeFlagVar += "EXECUTABLE";
|
||||
}
|
||||
else
|
||||
{
|
||||
runTimeFlagVar += "SHARED_LIBRARY";
|
||||
}
|
||||
runTimeFlagVar += "_RUNTIME_";
|
||||
runTimeFlagVar += linkLanguage;
|
||||
runTimeFlagVar += "_FLAG";
|
||||
std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP";
|
||||
runtimeFlag = this->Makefile->GetSafeDefinition(runTimeFlagVar.c_str());
|
||||
runtimeSep = this->Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str());
|
||||
}
|
||||
// concatenate all paths or no?
|
||||
bool runtimeConcatenate = ( runtimeSep!="" );
|
||||
if(runtimeFlag == "" || this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
|
||||
bool runtimeConcatenate = !runtimeSep.empty();
|
||||
|
||||
const char* runtimeAlways =
|
||||
this->Makefile->GetDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH");
|
||||
|
||||
// Turn off rpath support if no flag is available to specify it.
|
||||
if(runtimeFlag.empty())
|
||||
{
|
||||
outputRuntime = false;
|
||||
runtimeAlways = 0;
|
||||
}
|
||||
|
||||
// Some search paths should never be emitted
|
||||
emitted.insert("");
|
||||
if(const char* implicitLinks =
|
||||
(this->Makefile->GetDefinition
|
||||
("CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES")))
|
||||
{
|
||||
std::vector<std::string> implicitLinkVec;
|
||||
cmSystemTools::ExpandListArgument(implicitLinks, implicitLinkVec);
|
||||
for(unsigned int k = 0; k < implicitLinkVec.size(); ++k)
|
||||
{
|
||||
emitted.insert(implicitLinkVec[k]);
|
||||
}
|
||||
}
|
||||
std::string libPathFlag =
|
||||
this->Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG");
|
||||
std::string libPathTerminator =
|
||||
|
@ -1539,10 +1525,43 @@ bool cmLocalGenerator::GetLinkerArgs(std::string& rpath,
|
|||
linkLibs += " ";
|
||||
}
|
||||
|
||||
// Compute the link library and directory information.
|
||||
std::vector<cmStdString> libNames;
|
||||
std::vector<cmStdString> libDirs;
|
||||
this->ComputeLinkInformation(tgt, config, libNames, libDirs);
|
||||
// Append the framework search path flags.
|
||||
std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
|
||||
for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
|
||||
fdi != fwDirs.end(); ++fdi)
|
||||
{
|
||||
linkLibs += "-F";
|
||||
linkLibs += this->Convert(fdi->c_str(), NONE, SHELL, false);
|
||||
linkLibs += " ";
|
||||
}
|
||||
|
||||
// Append the library search path flags.
|
||||
std::vector<std::string> const& libDirs = cli.GetDirectories();
|
||||
for(std::vector<std::string>::const_iterator libDir = libDirs.begin();
|
||||
libDir != libDirs.end(); ++libDir)
|
||||
{
|
||||
std::string libpath = this->ConvertToOutputForExisting(libDir->c_str());
|
||||
linkLibs += libPathFlag;
|
||||
linkLibs += libpath;
|
||||
linkLibs += libPathTerminator;
|
||||
linkLibs += " ";
|
||||
}
|
||||
|
||||
// Append the link items.
|
||||
typedef cmComputeLinkInformation::ItemVector ItemVector;
|
||||
ItemVector const& items = cli.GetItems();
|
||||
for(ItemVector::const_iterator li = items.begin(); li != items.end(); ++li)
|
||||
{
|
||||
if(li->IsPath)
|
||||
{
|
||||
linkLibs += this->Convert(li->Value.c_str(), START_OUTPUT, SHELL);
|
||||
}
|
||||
else
|
||||
{
|
||||
linkLibs += li->Value;
|
||||
}
|
||||
linkLibs += " ";
|
||||
}
|
||||
|
||||
// Select whether to generate an rpath for the install tree or the
|
||||
// build tree.
|
||||
|
@ -1562,68 +1581,46 @@ bool cmLocalGenerator::GetLinkerArgs(std::string& rpath,
|
|||
{
|
||||
const char* install_rpath = tgt.GetProperty("INSTALL_RPATH");
|
||||
cmSystemTools::ExpandListArgument(install_rpath, runtimeDirs);
|
||||
for(unsigned int i=0; i < runtimeDirs.size(); ++i)
|
||||
{
|
||||
runtimeDirs[i] =
|
||||
this->Convert(runtimeDirs[i].c_str(), FULL, SHELL, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Append the library search path flags.
|
||||
for(std::vector<cmStdString>::const_iterator libDir = libDirs.begin();
|
||||
libDir != libDirs.end(); ++libDir)
|
||||
if(use_build_rpath || use_link_rpath)
|
||||
{
|
||||
std::string libpath = this->ConvertToOutputForExisting(libDir->c_str());
|
||||
if(emitted.insert(libpath).second)
|
||||
std::vector<std::string> const& rdirs = cli.GetRuntimeSearchPath();
|
||||
for(std::vector<std::string>::const_iterator ri = rdirs.begin();
|
||||
ri != rdirs.end(); ++ri)
|
||||
{
|
||||
std::string fullLibPath;
|
||||
if(!this->WindowsShell && this->UseRelativePaths)
|
||||
// Put this directory in the rpath if using build-tree rpath
|
||||
// support or if using the link path as an rpath.
|
||||
if(use_build_rpath)
|
||||
{
|
||||
fullLibPath = "\"`cd ";
|
||||
runtimeDirs.push_back(*ri);
|
||||
}
|
||||
fullLibPath += libpath;
|
||||
if(!this->WindowsShell && this->UseRelativePaths)
|
||||
else if(use_link_rpath)
|
||||
{
|
||||
fullLibPath += ";pwd`\"";
|
||||
}
|
||||
std::string::size_type pos = libDir->find(libPathFlag.c_str());
|
||||
if((pos == std::string::npos || pos > 0)
|
||||
&& libDir->find("${") == std::string::npos)
|
||||
{
|
||||
linkLibs += libPathFlag;
|
||||
linkLibs += fullLibPath;
|
||||
linkLibs += libPathTerminator;
|
||||
linkLibs += " ";
|
||||
|
||||
// Put this directory in the rpath if using build-tree rpath
|
||||
// support or if using the link path as an rpath.
|
||||
if(use_build_rpath)
|
||||
// Do not add any path inside the source or build tree.
|
||||
const char* topSourceDir = this->Makefile->GetHomeDirectory();
|
||||
const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
|
||||
if(!cmSystemTools::ComparePath(ri->c_str(), topSourceDir) &&
|
||||
!cmSystemTools::ComparePath(ri->c_str(), topBinaryDir) &&
|
||||
!cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) &&
|
||||
!cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir))
|
||||
{
|
||||
runtimeDirs.push_back(fullLibPath);
|
||||
}
|
||||
else if(use_link_rpath)
|
||||
{
|
||||
// Do not add any path inside the source or build tree.
|
||||
const char* topSourceDir = this->Makefile->GetHomeDirectory();
|
||||
const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
|
||||
if(!cmSystemTools::ComparePath(libDir->c_str(), topSourceDir) &&
|
||||
!cmSystemTools::ComparePath(libDir->c_str(), topBinaryDir) &&
|
||||
!cmSystemTools::IsSubDirectory(libDir->c_str(), topSourceDir) &&
|
||||
!cmSystemTools::IsSubDirectory(libDir->c_str(), topBinaryDir))
|
||||
{
|
||||
runtimeDirs.push_back(fullLibPath);
|
||||
}
|
||||
runtimeDirs.push_back(*ri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append the link libraries.
|
||||
for(std::vector<cmStdString>::iterator lib = libNames.begin();
|
||||
lib != libNames.end(); ++lib)
|
||||
if(runtimeAlways)
|
||||
{
|
||||
linkLibs += *lib;
|
||||
linkLibs += " ";
|
||||
// Add runtime paths required by the platform to always be
|
||||
// present. This is done even when skipping rpath support.
|
||||
cmSystemTools::ExpandListArgument(runtimeAlways, runtimeDirs);
|
||||
}
|
||||
|
||||
// Convert the runtime directory names for use in the build file.
|
||||
for(std::vector<std::string>::iterator ri = runtimeDirs.begin();
|
||||
ri != runtimeDirs.end(); ++ri)
|
||||
{
|
||||
*ri = this->Convert(ri->c_str(), FULL, SHELL, false);
|
||||
}
|
||||
|
||||
if(!runtimeDirs.empty())
|
||||
|
@ -1714,257 +1711,6 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmLocalGenerator
|
||||
::ComputeLinkInformation(cmTarget& target,
|
||||
const char* config,
|
||||
std::vector<cmStdString>& outLibs,
|
||||
std::vector<cmStdString>& outDirs,
|
||||
std::vector<cmStdString>* fullPathLibs)
|
||||
{
|
||||
// Compute which library configuration to link.
|
||||
cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
|
||||
if(config && cmSystemTools::UpperCase(config) == "DEBUG")
|
||||
{
|
||||
linkType = cmTarget::DEBUG;
|
||||
}
|
||||
|
||||
// Get the language used for linking.
|
||||
const char* linkLanguage =
|
||||
target.GetLinkerLanguage(this->GetGlobalGenerator());
|
||||
|
||||
// Check whether we should use an import library for linking a target.
|
||||
bool implib =
|
||||
this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")?true:false;
|
||||
|
||||
// On platforms without import libraries there may be a special flag
|
||||
// to use when creating a plugin (module) that obtains symbols from
|
||||
// the program that will load it.
|
||||
const char* loader_flag = 0;
|
||||
if(!implib && target.GetType() == cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
if(!linkLanguage)
|
||||
{
|
||||
cmSystemTools::
|
||||
Error("CMake can not determine linker language for target:",
|
||||
target.GetName());
|
||||
return;
|
||||
}
|
||||
std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
|
||||
loader_flag_var += linkLanguage;
|
||||
loader_flag_var += "_FLAG";
|
||||
loader_flag = this->Makefile->GetDefinition(loader_flag_var.c_str());
|
||||
}
|
||||
|
||||
// Get the list of libraries against which this target wants to link.
|
||||
std::vector<std::string> linkLibraries;
|
||||
const cmTarget::LinkLibraryVectorType& inLibs = target.GetLinkLibraries();
|
||||
for(cmTarget::LinkLibraryVectorType::const_iterator j = inLibs.begin();
|
||||
j != inLibs.end(); ++j)
|
||||
{
|
||||
// For backwards compatibility variables may have been expanded
|
||||
// inside library names. Clean up the resulting name.
|
||||
std::string lib = j->first;
|
||||
std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
|
||||
if(pos != lib.npos)
|
||||
{
|
||||
lib = lib.substr(pos, lib.npos);
|
||||
}
|
||||
pos = lib.find_last_not_of(" \t\r\n");
|
||||
if(pos != lib.npos)
|
||||
{
|
||||
lib = lib.substr(0, pos+1);
|
||||
}
|
||||
if(lib.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Link to a library if it is not the same target and is meant for
|
||||
// this configuration type.
|
||||
if((target.GetType() == cmTarget::EXECUTABLE ||
|
||||
lib != target.GetName()) &&
|
||||
(j->second == cmTarget::GENERAL || j->second == linkType))
|
||||
{
|
||||
// Compute the proper name to use to link this library.
|
||||
cmTarget* tgt = this->GlobalGenerator->FindTarget(0, lib.c_str(), false);
|
||||
bool impexe = (tgt &&
|
||||
tgt->GetType() == cmTarget::EXECUTABLE &&
|
||||
tgt->GetPropertyAsBool("ENABLE_EXPORTS"));
|
||||
if(impexe && !implib && !loader_flag)
|
||||
{
|
||||
// Skip linking to executables on platforms with no import
|
||||
// libraries or loader flags.
|
||||
continue;
|
||||
}
|
||||
else if(tgt && (tgt->GetType() == cmTarget::STATIC_LIBRARY ||
|
||||
tgt->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
tgt->GetType() == cmTarget::MODULE_LIBRARY ||
|
||||
impexe))
|
||||
{
|
||||
// This is a CMake target. Ask the target for its real name.
|
||||
std::string linkItem;
|
||||
if(impexe && loader_flag)
|
||||
{
|
||||
// This link item is an executable that may provide symbols
|
||||
// used by this target. A special flag is needed on this
|
||||
// platform. Add it now.
|
||||
std::string exe = tgt->GetFullPath(config, implib);
|
||||
linkItem += loader_flag;
|
||||
linkItem += this->Convert(exe.c_str(), NONE, SHELL, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pass the full path to the target file but purposely leave
|
||||
// off the per-configuration subdirectory. The link directory
|
||||
// ordering knows how to deal with this.
|
||||
linkItem += tgt->GetDirectory(0, implib);
|
||||
// on apple if the FRAMEWORK prop is set, then
|
||||
// do not add the target full name but just use the directory
|
||||
// name
|
||||
#ifdef __APPLE__
|
||||
if (!(tgt->GetType() == cmTarget::SHARED_LIBRARY &&
|
||||
tgt->GetPropertyAsBool("FRAMEWORK")))
|
||||
#endif
|
||||
{
|
||||
linkItem += "/";
|
||||
linkItem += tgt->GetFullName(config, implib);
|
||||
}
|
||||
}
|
||||
linkLibraries.push_back(linkItem);
|
||||
// For full path, use the true location.
|
||||
if(fullPathLibs)
|
||||
{
|
||||
fullPathLibs->push_back(tgt->GetFullPath(config, implib));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is not a CMake target. Use the name given.
|
||||
linkLibraries.push_back(lib);
|
||||
|
||||
// Add to the list of full paths if this library is one.
|
||||
if(fullPathLibs &&
|
||||
cmSystemTools::FileIsFullPath(lib.c_str()) &&
|
||||
!cmSystemTools::FileIsDirectory(lib.c_str()))
|
||||
{
|
||||
fullPathLibs->push_back(lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the list of directories the target wants to search for libraries.
|
||||
const std::vector<std::string>&
|
||||
linkDirectories = target.GetLinkDirectories();
|
||||
|
||||
// Lookup link type selection flags.
|
||||
const char* static_link_type_flag = 0;
|
||||
const char* shared_link_type_flag = 0;
|
||||
const char* target_type_str = 0;
|
||||
switch(target.GetType())
|
||||
{
|
||||
case cmTarget::EXECUTABLE: target_type_str = "EXE"; break;
|
||||
case cmTarget::SHARED_LIBRARY: target_type_str = "SHARED_LIBRARY"; break;
|
||||
case cmTarget::MODULE_LIBRARY: target_type_str = "SHARED_MODULE"; break;
|
||||
default: break;
|
||||
}
|
||||
if(target_type_str)
|
||||
{
|
||||
if(!linkLanguage)
|
||||
{
|
||||
cmSystemTools::
|
||||
Error("CMake can not determine linker language for target:",
|
||||
target.GetName());
|
||||
return;
|
||||
}
|
||||
std::string static_link_type_flag_var = "CMAKE_";
|
||||
static_link_type_flag_var += target_type_str;
|
||||
static_link_type_flag_var += "_LINK_STATIC_";
|
||||
static_link_type_flag_var += linkLanguage;
|
||||
static_link_type_flag_var += "_FLAGS";
|
||||
static_link_type_flag =
|
||||
this->Makefile->GetDefinition(static_link_type_flag_var.c_str());
|
||||
|
||||
std::string shared_link_type_flag_var = "CMAKE_";
|
||||
shared_link_type_flag_var += target_type_str;
|
||||
shared_link_type_flag_var += "_LINK_DYNAMIC_";
|
||||
shared_link_type_flag_var += linkLanguage;
|
||||
shared_link_type_flag_var += "_FLAGS";
|
||||
shared_link_type_flag =
|
||||
this->Makefile->GetDefinition(shared_link_type_flag_var.c_str());
|
||||
}
|
||||
|
||||
// Compute the link directory order needed to link the libraries.
|
||||
cmOrderLinkDirectories orderLibs;
|
||||
orderLibs.SetLinkTypeInformation(cmOrderLinkDirectories::LinkShared,
|
||||
static_link_type_flag,
|
||||
shared_link_type_flag);
|
||||
orderLibs.AddLinkPrefix(
|
||||
this->Makefile->GetDefinition("CMAKE_STATIC_LIBRARY_PREFIX"));
|
||||
orderLibs.AddLinkPrefix(
|
||||
this->Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_PREFIX"));
|
||||
|
||||
// Import library names should be matched and treated as shared
|
||||
// libraries for the purposes of linking.
|
||||
orderLibs.AddLinkExtension(
|
||||
this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
|
||||
cmOrderLinkDirectories::LinkShared);
|
||||
orderLibs.AddLinkExtension(
|
||||
this->Makefile->GetDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"),
|
||||
cmOrderLinkDirectories::LinkStatic);
|
||||
orderLibs.AddLinkExtension(
|
||||
this->Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_SUFFIX"),
|
||||
cmOrderLinkDirectories::LinkShared);
|
||||
orderLibs.AddLinkExtension(
|
||||
this->Makefile->GetDefinition("CMAKE_LINK_LIBRARY_SUFFIX"));
|
||||
if(const char* linkSuffixes =
|
||||
this->Makefile->GetDefinition("CMAKE_EXTRA_LINK_EXTENSIONS"))
|
||||
{
|
||||
std::vector<std::string> linkSuffixVec;
|
||||
cmSystemTools::ExpandListArgument(linkSuffixes, linkSuffixVec);
|
||||
for(std::vector<std::string>::iterator i = linkSuffixVec.begin();
|
||||
i != linkSuffixVec.end(); ++i)
|
||||
{
|
||||
orderLibs.AddLinkExtension(i->c_str());
|
||||
}
|
||||
}
|
||||
std::string configSubdir;
|
||||
cmGlobalGenerator* gg = this->GetGlobalGenerator();
|
||||
gg->AppendDirectoryForConfig("", config, "", configSubdir);
|
||||
orderLibs.SetLinkInformation(target.GetName(),
|
||||
linkLibraries,
|
||||
linkDirectories,
|
||||
gg->GetTargetManifest(),
|
||||
configSubdir.c_str());
|
||||
orderLibs.DetermineLibraryPathOrder();
|
||||
std::vector<cmStdString> orderedLibs;
|
||||
orderLibs.GetLinkerInformation(outDirs, orderedLibs);
|
||||
|
||||
// Make sure libraries are linked with the proper syntax.
|
||||
std::string libLinkFlag =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG");
|
||||
std::string libLinkSuffix =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX");
|
||||
for(std::vector<cmStdString>::iterator l = orderedLibs.begin();
|
||||
l != orderedLibs.end(); ++l)
|
||||
{
|
||||
std::string lib = *l;
|
||||
if(lib[0] == '-' || lib[0] == '$' || lib[0] == '`')
|
||||
{
|
||||
// The library is linked with special syntax by the user.
|
||||
outLibs.push_back(lib);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate the proper link syntax.
|
||||
lib = libLinkFlag;
|
||||
lib += *l;
|
||||
lib += libLinkSuffix;
|
||||
outLibs.push_back(lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmLocalGenerator::AddLanguageFlags(std::string& flags,
|
||||
const char* lang,
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
/**
|
||||
* Generate a manifest of target files that will be built.
|
||||
*/
|
||||
virtual void GenerateTargetManifest(cmTargetManifest&);
|
||||
virtual void GenerateTargetManifest();
|
||||
|
||||
///! Get the makefile for this generator
|
||||
cmMakefile *GetMakefile() {
|
||||
|
@ -174,13 +174,6 @@ public:
|
|||
bool /*color*/)
|
||||
{ return true; }
|
||||
|
||||
/** Compute the list of link libraries and directories for the given
|
||||
target and configuration. */
|
||||
void ComputeLinkInformation(cmTarget& target, const char* config,
|
||||
std::vector<cmStdString>& outLibs,
|
||||
std::vector<cmStdString>& outDirs,
|
||||
std::vector<cmStdString>* fullPathLibs=0);
|
||||
|
||||
/** Get the include flags for the current makefile and language. */
|
||||
void GetIncludeDirectories(std::vector<std::string>& dirs,
|
||||
bool filter_system_dirs = true);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "cmCacheManager.h"
|
||||
#include "cmake.h"
|
||||
|
||||
#include "cmComputeLinkInformation.h"
|
||||
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
cmLocalVisualStudio6Generator::cmLocalVisualStudio6Generator()
|
||||
|
@ -1569,12 +1571,17 @@ void cmLocalVisualStudio6Generator
|
|||
std::string& options)
|
||||
{
|
||||
// Compute the link information for this configuration.
|
||||
std::vector<cmStdString> linkLibs;
|
||||
std::vector<cmStdString> linkDirs;
|
||||
this->ComputeLinkInformation(target, configName, linkLibs, linkDirs);
|
||||
cmComputeLinkInformation cli(&target, configName);
|
||||
if(!cli.Compute())
|
||||
{
|
||||
return;
|
||||
}
|
||||
typedef cmComputeLinkInformation::ItemVector ItemVector;
|
||||
ItemVector const& linkLibs = cli.GetItems();
|
||||
std::vector<std::string> const& linkDirs = cli.GetDirectories();
|
||||
|
||||
// Build the link options code.
|
||||
for(std::vector<cmStdString>::const_iterator d = linkDirs.begin();
|
||||
for(std::vector<std::string>::const_iterator d = linkDirs.begin();
|
||||
d != linkDirs.end(); ++d)
|
||||
{
|
||||
std::string dir = *d;
|
||||
|
@ -1592,11 +1599,19 @@ void cmLocalVisualStudio6Generator
|
|||
options += "\n";
|
||||
}
|
||||
}
|
||||
for(std::vector<cmStdString>::const_iterator l = linkLibs.begin();
|
||||
for(ItemVector::const_iterator l = linkLibs.begin();
|
||||
l != linkLibs.end(); ++l)
|
||||
{
|
||||
options += "# ADD LINK32 ";
|
||||
options += this->ConvertToOptionallyRelativeOutputPath(l->c_str());
|
||||
if(l->IsPath)
|
||||
{
|
||||
options +=
|
||||
this->ConvertToOptionallyRelativeOutputPath(l->Value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
options += l->Value;
|
||||
}
|
||||
options += "\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,24 @@
|
|||
#include "cmCacheManager.h"
|
||||
#include "cmake.h"
|
||||
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
|
||||
#include <cmsys/System.h>
|
||||
|
||||
#include <ctype.h> // for isspace
|
||||
|
||||
class cmLocalVisualStudio7GeneratorInternals
|
||||
{
|
||||
public:
|
||||
cmLocalVisualStudio7GeneratorInternals(cmLocalVisualStudio7Generator* e):
|
||||
LocalGenerator(e) {}
|
||||
typedef cmComputeLinkInformation::ItemVector ItemVector;
|
||||
void OutputLibraries(std::ostream& fout, ItemVector const& libs);
|
||||
private:
|
||||
cmLocalVisualStudio7Generator* LocalGenerator;
|
||||
};
|
||||
|
||||
extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -38,10 +50,12 @@ cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator()
|
|||
this->Version = 7;
|
||||
this->PlatformName = "Win32";
|
||||
this->ExtraFlagTable = 0;
|
||||
this->Internal = new cmLocalVisualStudio7GeneratorInternals(this);
|
||||
}
|
||||
|
||||
cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator()
|
||||
{
|
||||
delete this->Internal;
|
||||
}
|
||||
|
||||
void cmLocalVisualStudio7Generator::AddHelperCommands()
|
||||
|
@ -748,20 +762,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
targetNameImport, targetNamePDB, configName);
|
||||
|
||||
// Compute the link library and directory information.
|
||||
std::vector<cmStdString> linkLibs;
|
||||
std::vector<cmStdString> linkDirs;
|
||||
this->ComputeLinkInformation(target, configName, linkLibs, linkDirs);
|
||||
|
||||
// Get the language to use for linking.
|
||||
const char* linkLanguage =
|
||||
target.GetLinkerLanguage(this->GetGlobalGenerator());
|
||||
if(!linkLanguage)
|
||||
cmComputeLinkInformation cli(&target, configName);
|
||||
if(!cli.Compute())
|
||||
{
|
||||
cmSystemTools::Error
|
||||
("CMake can not determine linker language for target:",
|
||||
target.GetName());
|
||||
return;
|
||||
}
|
||||
const char* linkLanguage = cli.GetLinkLanguage();
|
||||
|
||||
// Compute the variable name to lookup standard libraries for this
|
||||
// language.
|
||||
|
@ -777,7 +783,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
|
||||
<< this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
|
||||
<< " ";
|
||||
this->OutputLibraries(fout, linkLibs);
|
||||
this->Internal->OutputLibraries(fout, cli.GetItems());
|
||||
fout << "\"\n";
|
||||
temp = target.GetDirectory(configName);
|
||||
temp += "/";
|
||||
|
@ -787,7 +793,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
this->WriteTargetVersionAttribute(fout, target);
|
||||
linkOptions.OutputFlagMap(fout, "\t\t\t\t");
|
||||
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
|
||||
this->OutputLibraryDirectories(fout, linkDirs);
|
||||
this->OutputLibraryDirectories(fout, cli.GetDirectories());
|
||||
fout << "\"\n";
|
||||
this->OutputModuleDefinitionFile(fout, target);
|
||||
temp = target.GetDirectory(configName);
|
||||
|
@ -825,20 +831,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
targetNameImport, targetNamePDB, configName);
|
||||
|
||||
// Compute the link library and directory information.
|
||||
std::vector<cmStdString> linkLibs;
|
||||
std::vector<cmStdString> linkDirs;
|
||||
this->ComputeLinkInformation(target, configName, linkLibs, linkDirs);
|
||||
|
||||
// Get the language to use for linking.
|
||||
const char* linkLanguage =
|
||||
target.GetLinkerLanguage(this->GetGlobalGenerator());
|
||||
if(!linkLanguage)
|
||||
cmComputeLinkInformation cli(&target, configName);
|
||||
if(!cli.Compute())
|
||||
{
|
||||
cmSystemTools::Error
|
||||
("CMake can not determine linker language for target:",
|
||||
target.GetName());
|
||||
return;
|
||||
}
|
||||
const char* linkLanguage = cli.GetLinkLanguage();
|
||||
|
||||
// Compute the variable name to lookup standard libraries for this
|
||||
// language.
|
||||
|
@ -854,7 +852,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
|
||||
<< this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
|
||||
<< " ";
|
||||
this->OutputLibraries(fout, linkLibs);
|
||||
this->Internal->OutputLibraries(fout, cli.GetItems());
|
||||
fout << "\"\n";
|
||||
temp = target.GetDirectory(configName);
|
||||
temp += "/";
|
||||
|
@ -864,7 +862,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
this->WriteTargetVersionAttribute(fout, target);
|
||||
linkOptions.OutputFlagMap(fout, "\t\t\t\t");
|
||||
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
|
||||
this->OutputLibraryDirectories(fout, linkDirs);
|
||||
this->OutputLibraryDirectories(fout, cli.GetDirectories());
|
||||
fout << "\"\n";
|
||||
fout << "\t\t\t\tProgramDataBaseFile=\""
|
||||
<< target.GetDirectory(configName) << "/" << targetNamePDB
|
||||
|
@ -936,14 +934,23 @@ void cmLocalVisualStudio7Generator
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmLocalVisualStudio7Generator
|
||||
::OutputLibraries(std::ostream& fout,
|
||||
std::vector<cmStdString> const& libs)
|
||||
cmLocalVisualStudio7GeneratorInternals
|
||||
::OutputLibraries(std::ostream& fout, ItemVector const& libs)
|
||||
{
|
||||
for(std::vector<cmStdString>::const_iterator l = libs.begin();
|
||||
l != libs.end(); ++l)
|
||||
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
|
||||
for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l)
|
||||
{
|
||||
fout << this->ConvertToXMLOutputPath(l->c_str()) << " ";
|
||||
if(l->IsPath)
|
||||
{
|
||||
std::string rel = lg->Convert(l->Value.c_str(),
|
||||
cmLocalGenerator::START_OUTPUT,
|
||||
cmLocalGenerator::UNCHANGED);
|
||||
fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
fout << l->Value << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -951,10 +958,10 @@ cmLocalVisualStudio7Generator
|
|||
void
|
||||
cmLocalVisualStudio7Generator
|
||||
::OutputLibraryDirectories(std::ostream& fout,
|
||||
std::vector<cmStdString> const& dirs)
|
||||
std::vector<std::string> const& dirs)
|
||||
{
|
||||
const char* comma = "";
|
||||
for(std::vector<cmStdString>::const_iterator d = dirs.begin();
|
||||
for(std::vector<std::string>::const_iterator d = dirs.begin();
|
||||
d != dirs.end(); ++d)
|
||||
{
|
||||
// Remove any trailing slash and skip empty paths.
|
||||
|
|
|
@ -27,6 +27,7 @@ struct cmVS7FlagTable;
|
|||
|
||||
class cmLocalVisualStudio7GeneratorOptions;
|
||||
class cmLocalVisualStudio7GeneratorFCInfo;
|
||||
class cmLocalVisualStudio7GeneratorInternals;
|
||||
|
||||
/** \class cmLocalVisualStudio7Generator
|
||||
* \brief Write Visual Studio .NET project files.
|
||||
|
@ -96,10 +97,8 @@ private:
|
|||
cmTarget &target, const char *libName);
|
||||
void OutputBuildTool(std::ostream& fout, const char* configName,
|
||||
cmTarget& t);
|
||||
void OutputLibraries(std::ostream& fout,
|
||||
std::vector<cmStdString> const& libs);
|
||||
void OutputLibraryDirectories(std::ostream& fout,
|
||||
std::vector<cmStdString> const& dirs);
|
||||
std::vector<std::string> const& dirs);
|
||||
void OutputModuleDefinitionFile(std::ostream& fout, cmTarget &target);
|
||||
void WriteProjectStart(std::ostream& fout, const char *libName,
|
||||
cmTarget &tgt, std::vector<cmSourceGroup> &sgs);
|
||||
|
@ -120,11 +119,13 @@ private:
|
|||
virtual std::string GetTargetDirectory(cmTarget const&) const;
|
||||
|
||||
friend class cmLocalVisualStudio7GeneratorFCInfo;
|
||||
friend class cmLocalVisualStudio7GeneratorInternals;
|
||||
|
||||
cmVS7FlagTable const* ExtraFlagTable;
|
||||
std::string ModuleDefinitionFile;
|
||||
int Version;
|
||||
std::string PlatformName; // Win32 or x64
|
||||
cmLocalVisualStudio7GeneratorInternals* Internal;
|
||||
};
|
||||
|
||||
// This is a table mapping XML tag IDE names to command line options
|
||||
|
|
|
@ -1,710 +0,0 @@
|
|||
#include "cmOrderLinkDirectories.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
#include <ctype.h>
|
||||
|
||||
//#define CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
cmOrderLinkDirectories::cmOrderLinkDirectories()
|
||||
{
|
||||
this->StartLinkType = LinkUnknown;
|
||||
this->LinkTypeEnabled = false;
|
||||
this->Debug = false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void
|
||||
cmOrderLinkDirectories
|
||||
::SetLinkTypeInformation(LinkType start_link_type,
|
||||
const char* static_link_type_flag,
|
||||
const char* shared_link_type_flag)
|
||||
{
|
||||
// We can support link type switching only if all needed flags are
|
||||
// known.
|
||||
this->StartLinkType = start_link_type;
|
||||
if(static_link_type_flag && *static_link_type_flag &&
|
||||
shared_link_type_flag && *shared_link_type_flag)
|
||||
{
|
||||
this->LinkTypeEnabled = true;
|
||||
this->StaticLinkTypeFlag = static_link_type_flag;
|
||||
this->SharedLinkTypeFlag = shared_link_type_flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->LinkTypeEnabled = false;
|
||||
this->StaticLinkTypeFlag = "";
|
||||
this->SharedLinkTypeFlag = "";
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void cmOrderLinkDirectories::SetCurrentLinkType(LinkType lt)
|
||||
{
|
||||
if(this->CurrentLinkType != lt)
|
||||
{
|
||||
this->CurrentLinkType = lt;
|
||||
|
||||
if(this->LinkTypeEnabled)
|
||||
{
|
||||
switch(this->CurrentLinkType)
|
||||
{
|
||||
case LinkStatic:
|
||||
this->LinkItems.push_back(this->StaticLinkTypeFlag); break;
|
||||
case LinkShared:
|
||||
this->LinkItems.push_back(this->SharedLinkTypeFlag); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
bool cmOrderLinkDirectories::LibraryInDirectory(const char* desiredLib,
|
||||
const char* dir,
|
||||
const char* libIn)
|
||||
{
|
||||
// first look for the library as given
|
||||
if(this->LibraryMayConflict(desiredLib, dir, libIn))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// next remove the extension (.a, .so ) and look for the library
|
||||
// under a different name as the linker can do either
|
||||
if(this->RemoveLibraryExtension.find(libIn))
|
||||
{
|
||||
cmStdString lib = this->RemoveLibraryExtension.match(1);
|
||||
cmStdString ext = this->RemoveLibraryExtension.match(2);
|
||||
for(std::vector<cmStdString>::iterator i = this->LinkExtensions.begin();
|
||||
i != this->LinkExtensions.end(); ++i)
|
||||
{
|
||||
if(ext != *i)
|
||||
{
|
||||
std::string fname = lib;
|
||||
lib += *i;
|
||||
if(this->LibraryMayConflict(desiredLib, dir, fname.c_str()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void cmOrderLinkDirectories::FindLibrariesInSearchPaths()
|
||||
{
|
||||
for(std::set<cmStdString>::iterator dir = this->LinkPathSet.begin();
|
||||
dir != this->LinkPathSet.end(); ++dir)
|
||||
{
|
||||
for(std::map<cmStdString, Library>::iterator lib
|
||||
= this->FullPathLibraries.begin();
|
||||
lib != this->FullPathLibraries.end(); ++lib)
|
||||
{
|
||||
if(lib->second.Path != *dir)
|
||||
{
|
||||
if(this->LibraryInDirectory(lib->second.FullPath.c_str(),
|
||||
dir->c_str(), lib->second.File.c_str()))
|
||||
{
|
||||
this->LibraryToDirectories[lib->second.FullPath].push_back(*dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void cmOrderLinkDirectories::FindIndividualLibraryOrders()
|
||||
{
|
||||
for(std::vector<Library>::iterator lib =
|
||||
this->MultiDirectoryLibraries.begin();
|
||||
lib != this->MultiDirectoryLibraries.end(); ++lib)
|
||||
{
|
||||
std::vector<cmStdString>& dirs =
|
||||
this->LibraryToDirectories[lib->FullPath];
|
||||
std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
||||
>::iterator i;
|
||||
for(i = this->DirectoryToAfterList.begin();
|
||||
i != this->DirectoryToAfterList.end(); ++i)
|
||||
{
|
||||
if(i->first == lib->Path)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == this->DirectoryToAfterList.end())
|
||||
{
|
||||
std::cerr << "ERROR: should not happen\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::vector<cmStdString>::iterator d = dirs.begin();
|
||||
d != dirs.end(); ++d)
|
||||
{
|
||||
i->second.push_back(*d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
std::string cmOrderLinkDirectories::NoCaseExpression(const char* str)
|
||||
{
|
||||
std::string ret;
|
||||
const char* s = str;
|
||||
while(*s)
|
||||
{
|
||||
if(*s == '.')
|
||||
{
|
||||
ret += *s;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret += "[";
|
||||
ret += tolower(*s);
|
||||
ret += toupper(*s);
|
||||
ret += "]";
|
||||
}
|
||||
s++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void cmOrderLinkDirectories::CreateRegularExpressions()
|
||||
{
|
||||
this->SplitFramework.compile("(.*)/(.*)\\.framework$");
|
||||
|
||||
// Compute a regex to match link extensions.
|
||||
cmStdString libext = this->CreateExtensionRegex(this->LinkExtensions);
|
||||
|
||||
// Create regex to remove any library extension.
|
||||
cmStdString reg("(.*)");
|
||||
reg += libext;
|
||||
this->RemoveLibraryExtension.compile(reg.c_str());
|
||||
|
||||
// Create a regex to match a library name. Match index 1 will be
|
||||
// the prefix if it exists and empty otherwise. Match index 2 will
|
||||
// be the library name. Match index 3 will be the library
|
||||
// extension.
|
||||
reg = "^(";
|
||||
for(std::set<cmStdString>::iterator p = this->LinkPrefixes.begin();
|
||||
p != this->LinkPrefixes.end(); ++p)
|
||||
{
|
||||
reg += *p;
|
||||
reg += "|";
|
||||
}
|
||||
reg += ")";
|
||||
reg += "([^/]*)";
|
||||
|
||||
// Create a regex to match any library name.
|
||||
cmStdString reg_any = reg;
|
||||
reg_any += libext;
|
||||
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
fprintf(stderr, "any regex [%s]\n", reg_any.c_str());
|
||||
#endif
|
||||
this->ExtractAnyLibraryName.compile(reg_any.c_str());
|
||||
|
||||
// Create a regex to match static library names.
|
||||
if(!this->StaticLinkExtensions.empty())
|
||||
{
|
||||
cmStdString reg_static = reg;
|
||||
reg_static += this->CreateExtensionRegex(this->StaticLinkExtensions);
|
||||
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
|
||||
#endif
|
||||
this->ExtractStaticLibraryName.compile(reg_static.c_str());
|
||||
}
|
||||
|
||||
// Create a regex to match shared library names.
|
||||
if(!this->SharedLinkExtensions.empty())
|
||||
{
|
||||
cmStdString reg_shared = reg;
|
||||
reg_shared += this->CreateExtensionRegex(this->SharedLinkExtensions);
|
||||
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str());
|
||||
#endif
|
||||
this->ExtractSharedLibraryName.compile(reg_shared.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
std::string
|
||||
cmOrderLinkDirectories::CreateExtensionRegex(
|
||||
std::vector<cmStdString> const& exts)
|
||||
{
|
||||
// Build a list of extension choices.
|
||||
cmStdString libext = "(";
|
||||
const char* sep = "";
|
||||
for(std::vector<cmStdString>::const_iterator i = exts.begin();
|
||||
i != exts.end(); ++i)
|
||||
{
|
||||
// Separate this choice from the previous one.
|
||||
libext += sep;
|
||||
sep = "|";
|
||||
|
||||
// Store this extension choice with the "." escaped.
|
||||
libext += "\\";
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
libext += this->NoCaseExpression(i->c_str());
|
||||
#else
|
||||
libext += *i;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Finish the list.
|
||||
libext += ").*";
|
||||
return libext;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void cmOrderLinkDirectories::PrepareLinkTargets()
|
||||
{
|
||||
std::vector<cmStdString> originalLinkItems = this->LinkItems;
|
||||
this->LinkItems.clear();
|
||||
this->CurrentLinkType = this->StartLinkType;
|
||||
for(std::vector<cmStdString>::iterator i = originalLinkItems.begin();
|
||||
i != originalLinkItems.end(); ++i)
|
||||
{
|
||||
// Parse out the prefix, base, and suffix components of the
|
||||
// library name. If the name matches that of a shared or static
|
||||
// library then set the link type accordingly.
|
||||
//
|
||||
// Search for shared library names first because some platforms
|
||||
// have shared libraries with names that match the static library
|
||||
// pattern. For example cygwin and msys use the convention
|
||||
// libfoo.dll.a for import libraries and libfoo.a for static
|
||||
// libraries. On AIX a library with the name libfoo.a can be
|
||||
// shared!
|
||||
if(this->ExtractSharedLibraryName.find(*i))
|
||||
{
|
||||
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
fprintf(stderr, "shared regex matched [%s] [%s] [%s]\n",
|
||||
this->ExtractSharedLibraryName.match(1).c_str(),
|
||||
this->ExtractSharedLibraryName.match(2).c_str(),
|
||||
this->ExtractSharedLibraryName.match(3).c_str());
|
||||
#endif
|
||||
this->SetCurrentLinkType(LinkShared);
|
||||
this->LinkItems.push_back(this->ExtractSharedLibraryName.match(2));
|
||||
}
|
||||
else if(this->ExtractStaticLibraryName.find(*i))
|
||||
{
|
||||
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
fprintf(stderr, "static regex matched [%s] [%s] [%s]\n",
|
||||
this->ExtractStaticLibraryName.match(1).c_str(),
|
||||
this->ExtractStaticLibraryName.match(2).c_str(),
|
||||
this->ExtractStaticLibraryName.match(3).c_str());
|
||||
#endif
|
||||
this->SetCurrentLinkType(LinkStatic);
|
||||
this->LinkItems.push_back(this->ExtractStaticLibraryName.match(2));
|
||||
}
|
||||
else if(this->ExtractAnyLibraryName.find(*i))
|
||||
{
|
||||
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
fprintf(stderr, "any regex matched [%s] [%s] [%s]\n",
|
||||
this->ExtractAnyLibraryName.match(1).c_str(),
|
||||
this->ExtractAnyLibraryName.match(2).c_str(),
|
||||
this->ExtractAnyLibraryName.match(3).c_str());
|
||||
#endif
|
||||
this->SetCurrentLinkType(this->StartLinkType);
|
||||
this->LinkItems.push_back(this->ExtractAnyLibraryName.match(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SetCurrentLinkType(this->StartLinkType);
|
||||
this->LinkItems.push_back(*i);
|
||||
}
|
||||
}
|
||||
|
||||
// Restore the original linking type so system runtime libraries are
|
||||
// linked properly.
|
||||
this->SetCurrentLinkType(this->StartLinkType);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
bool cmOrderLinkDirectories::FindPathNotInDirectoryToAfterList(
|
||||
cmStdString& path)
|
||||
{
|
||||
for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
||||
>::iterator i = this->DirectoryToAfterList.begin();
|
||||
i != this->DirectoryToAfterList.end(); ++i)
|
||||
{
|
||||
const cmStdString& p = i->first;
|
||||
bool found = false;
|
||||
for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
||||
>::iterator j = this->DirectoryToAfterList.begin();
|
||||
j != this->DirectoryToAfterList.end() && !found; ++j)
|
||||
{
|
||||
if(j != i)
|
||||
{
|
||||
found = (std::find(j->second.begin(), j->second.end(), p)
|
||||
!= j->second.end());
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
path = p;
|
||||
this->DirectoryToAfterList.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
path = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void cmOrderLinkDirectories::OrderPaths(std::vector<cmStdString>&
|
||||
orderedPaths)
|
||||
{
|
||||
cmStdString path;
|
||||
// This is a topological sort implementation
|
||||
// One at a time find paths that are not in any other paths after list
|
||||
// and put them into the orderedPaths vector in that order
|
||||
// FindPathNotInDirectoryToAfterList removes the path from the
|
||||
// this->DirectoryToAfterList once it is found
|
||||
while(this->FindPathNotInDirectoryToAfterList(path))
|
||||
{
|
||||
orderedPaths.push_back(path);
|
||||
}
|
||||
// at this point if there are still paths in this->DirectoryToAfterList
|
||||
// then there is a cycle and we are stuck
|
||||
if(this->DirectoryToAfterList.size())
|
||||
{
|
||||
for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
||||
>::iterator i = this->DirectoryToAfterList.begin();
|
||||
i != this->DirectoryToAfterList.end(); ++i)
|
||||
{
|
||||
this->ImpossibleDirectories.insert(i->first);
|
||||
// still put it in the path list in the order we find them
|
||||
orderedPaths.push_back(i->first);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void cmOrderLinkDirectories::SetLinkInformation(
|
||||
const char* targetName,
|
||||
const std::vector<std::string>& linkLibraries,
|
||||
const std::vector<std::string>& linkDirectories,
|
||||
const cmTargetManifest& manifest,
|
||||
const char* configSubdir
|
||||
)
|
||||
{
|
||||
// Save the target name.
|
||||
this->TargetName = targetName;
|
||||
|
||||
// Save the subdirectory used for linking in this configuration.
|
||||
this->ConfigSubdir = configSubdir? configSubdir : "";
|
||||
|
||||
// Merge the link directory search path given into our path set.
|
||||
std::vector<cmStdString> empty;
|
||||
for(std::vector<std::string>::const_iterator p = linkDirectories.begin();
|
||||
p != linkDirectories.end(); ++p)
|
||||
{
|
||||
std::string dir = *p;
|
||||
#ifdef _WIN32
|
||||
// Avoid case problems for windows paths.
|
||||
if(dir.size() > 2 && dir[1] == ':')
|
||||
{
|
||||
if(dir[0] >= 'A' && dir[0] <= 'Z')
|
||||
{
|
||||
dir[0] += 'a' - 'A';
|
||||
}
|
||||
}
|
||||
dir = cmSystemTools::GetActualCaseForPath(dir.c_str());
|
||||
#endif
|
||||
if(this->DirectoryToAfterListEmitted.insert(dir).second)
|
||||
{
|
||||
std::pair<cmStdString, std::vector<cmStdString> > dp;
|
||||
dp.first = dir;
|
||||
this->DirectoryToAfterList.push_back(dp);
|
||||
this->LinkPathSet.insert(dir);
|
||||
}
|
||||
}
|
||||
|
||||
// Append the link library list into our raw list.
|
||||
for(std::vector<std::string>::const_iterator l = linkLibraries.begin();
|
||||
l != linkLibraries.end(); ++l)
|
||||
{
|
||||
this->RawLinkItems.push_back(*l);
|
||||
}
|
||||
|
||||
// Construct a set of files that will exist after building.
|
||||
for(cmTargetManifest::const_iterator i = manifest.begin();
|
||||
i != manifest.end(); ++i)
|
||||
{
|
||||
for(cmTargetSet::const_iterator j = i->second.begin();
|
||||
j != i->second.end(); ++j)
|
||||
{
|
||||
this->ManifestFiles.insert(*j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
bool cmOrderLinkDirectories::DetermineLibraryPathOrder()
|
||||
{
|
||||
// set up all the regular expressions
|
||||
this->CreateRegularExpressions();
|
||||
std::vector<cmStdString> finalOrderPaths;
|
||||
// find all libs that are full paths
|
||||
Library aLib;
|
||||
cmStdString dir;
|
||||
cmStdString file;
|
||||
std::vector<cmStdString> empty;
|
||||
// do not add a -F for the system frameworks
|
||||
this->EmittedFrameworkPaths.insert("/System/Library/Frameworks");
|
||||
for(unsigned int i=0; i < this->RawLinkItems.size(); ++i)
|
||||
{
|
||||
bool framework = false;
|
||||
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
fprintf(stderr, "Raw link item [%s]\n", this->RawLinkItems[i].c_str());
|
||||
#endif
|
||||
// if it is a full path to an item then separate it from the path
|
||||
// this only works with files and paths
|
||||
cmStdString& item = this->RawLinkItems[i];
|
||||
|
||||
if(cmSystemTools::FileIsFullPath(item.c_str()))
|
||||
{
|
||||
if(cmSystemTools::IsPathToFramework(item.c_str()))
|
||||
{
|
||||
this->SplitFramework.find(item.c_str());
|
||||
cmStdString path = this->SplitFramework.match(1);
|
||||
// Add the -F path if we have not yet done so
|
||||
if(this->EmittedFrameworkPaths.insert(path).second)
|
||||
{
|
||||
std::string fpath = "-F";
|
||||
fpath += cmSystemTools::ConvertToOutputPath(path.c_str());
|
||||
this->LinkItems.push_back(fpath);
|
||||
}
|
||||
// now add the -framework option
|
||||
std::string frame = "-framework ";
|
||||
frame += this->SplitFramework.match(2);
|
||||
this->LinkItems.push_back(frame);
|
||||
framework = true;
|
||||
}
|
||||
if(cmSystemTools::FileIsDirectory(item.c_str()))
|
||||
{
|
||||
if(!framework)
|
||||
{
|
||||
// A full path to a directory was found as a link item
|
||||
// warn user
|
||||
std::string message =
|
||||
"Warning: Ignoring path found in link libraries for target: ";
|
||||
message += this->TargetName;
|
||||
message += ", path is: ";
|
||||
message += this->RawLinkItems[i];
|
||||
message +=
|
||||
". Expected a library name or a full path to a library name.";
|
||||
cmSystemTools::Message(message.c_str());
|
||||
continue;
|
||||
}
|
||||
} // is it a directory
|
||||
if(!framework)
|
||||
{
|
||||
dir = cmSystemTools::GetFilenamePath(this->RawLinkItems[i]);
|
||||
file = cmSystemTools::GetFilenameName(this->RawLinkItems[i]);
|
||||
#ifdef _WIN32
|
||||
// Avoid case problems for windows paths.
|
||||
if(dir.size() > 2 && dir[1] == ':')
|
||||
{
|
||||
if(dir[0] >= 'A' && dir[0] <= 'Z')
|
||||
{
|
||||
dir[0] += 'a' - 'A';
|
||||
}
|
||||
}
|
||||
dir = cmSystemTools::GetActualCaseForPath(dir.c_str());
|
||||
#endif
|
||||
if(this->DirectoryToAfterListEmitted.insert(dir).second)
|
||||
{
|
||||
std::pair<cmStdString, std::vector<cmStdString> > dp;
|
||||
dp.first = dir;
|
||||
this->DirectoryToAfterList.push_back(dp);
|
||||
}
|
||||
this->LinkPathSet.insert(dir);
|
||||
aLib.FullPath = this->RawLinkItems[i];
|
||||
aLib.File = file;
|
||||
aLib.Path = dir;
|
||||
this->FullPathLibraries[aLib.FullPath] = aLib;
|
||||
#ifdef CM_ORDER_LINK_DIRECTORIES_DEBUG
|
||||
fprintf(stderr, "Storing item [%s]\n", file.c_str());
|
||||
#endif
|
||||
this->LinkItems.push_back(file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->LinkItems.push_back(this->RawLinkItems[i]);
|
||||
}
|
||||
}
|
||||
this->FindLibrariesInSearchPaths();
|
||||
for(std::map<cmStdString, std::vector<cmStdString> >::iterator lib =
|
||||
this->LibraryToDirectories.begin();
|
||||
lib!= this->LibraryToDirectories.end();
|
||||
++lib)
|
||||
{
|
||||
if(lib->second.size() > 0)
|
||||
{
|
||||
this->MultiDirectoryLibraries.push_back
|
||||
(this->FullPathLibraries[lib->first]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SingleDirectoryLibraries.push_back
|
||||
(this->FullPathLibraries[lib->first]);
|
||||
}
|
||||
}
|
||||
this->FindIndividualLibraryOrders();
|
||||
this->SortedSearchPaths.clear();
|
||||
if(this->Debug)
|
||||
{
|
||||
this->PrintMap("this->LibraryToDirectories", this->LibraryToDirectories);
|
||||
this->PrintVector("this->DirectoryToAfterList",
|
||||
this->DirectoryToAfterList);
|
||||
}
|
||||
this->OrderPaths(this->SortedSearchPaths);
|
||||
// now turn libfoo.a into foo and foo.a into foo
|
||||
// This will prepare the link items for -litem
|
||||
this->PrepareLinkTargets();
|
||||
if(this->ImpossibleDirectories.size())
|
||||
{
|
||||
cmSystemTools::Message(this->GetWarnings().c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string cmOrderLinkDirectories::GetWarnings()
|
||||
{
|
||||
std::string warning =
|
||||
"It is impossible to order the linker search path in such a way "
|
||||
"that libraries specified as full paths will be picked by the "
|
||||
"linker.\nDirectories and libraries involved are:\n";
|
||||
|
||||
for(std::set<cmStdString>::iterator i = this->ImpossibleDirectories.begin();
|
||||
i != this->ImpossibleDirectories.end(); ++i)
|
||||
{
|
||||
warning += "Directory: ";
|
||||
warning += *i;
|
||||
warning += " contains:\n";
|
||||
std::map<cmStdString, std::vector<cmStdString> >::iterator j;
|
||||
for(j = this->LibraryToDirectories.begin();
|
||||
j != this->LibraryToDirectories.end(); ++j)
|
||||
{
|
||||
if(std::find(j->second.begin(), j->second.end(), *i)
|
||||
!= j->second.end())
|
||||
{
|
||||
warning += "Library: ";
|
||||
warning += j->first;
|
||||
warning += "\n";
|
||||
}
|
||||
}
|
||||
warning += "\n";
|
||||
}
|
||||
warning += "\n";
|
||||
return warning;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
void
|
||||
cmOrderLinkDirectories::PrintMap(const char* name,
|
||||
std::map<cmStdString, std::vector<cmStdString> >& m)
|
||||
{
|
||||
std::cout << name << "\n";
|
||||
for(std::map<cmStdString, std::vector<cmStdString> >::iterator i =
|
||||
m.begin(); i != m.end();
|
||||
++i)
|
||||
{
|
||||
std::cout << i->first << ": ";
|
||||
for(std::vector<cmStdString>::iterator l = i->second.begin();
|
||||
l != i->second.end(); ++l)
|
||||
{
|
||||
std::cout << *l << " ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
void
|
||||
cmOrderLinkDirectories::PrintVector(const char* name,
|
||||
std::vector<std::pair<cmStdString,
|
||||
std::vector<cmStdString> > >& m)
|
||||
{
|
||||
std::cout << name << "\n";
|
||||
for(std::vector<std::pair<cmStdString, std::vector<cmStdString> >
|
||||
>::iterator i = m.begin(); i != m.end(); ++i)
|
||||
{
|
||||
std::cout << i->first << ": ";
|
||||
for(std::vector<cmStdString>::iterator l = i->second.begin();
|
||||
l != i->second.end(); ++l)
|
||||
{
|
||||
std::cout << *l << " ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void cmOrderLinkDirectories::GetFullPathLibraries(std::vector<cmStdString>&
|
||||
libs)
|
||||
{
|
||||
for(std::map<cmStdString, Library>::iterator i =
|
||||
this->FullPathLibraries.begin();
|
||||
i != this->FullPathLibraries.end(); ++i)
|
||||
{
|
||||
libs.push_back(i->first);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmOrderLinkDirectories::LibraryMayConflict(const char* desiredLib,
|
||||
const char* dir,
|
||||
const char* fname)
|
||||
{
|
||||
// We need to check whether the given file may be picked up by the
|
||||
// linker. This will occur if it exists as given or may be built
|
||||
// using the name given.
|
||||
bool found = false;
|
||||
std::string path = dir;
|
||||
path += "/";
|
||||
path += fname;
|
||||
if(this->ManifestFiles.find(path) != this->ManifestFiles.end())
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
else if(cmSystemTools::FileExists(path.c_str()))
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
|
||||
// When linking with a multi-configuration build tool the
|
||||
// per-configuration subdirectory is added to each link path. Check
|
||||
// this subdirectory too.
|
||||
if(!found && !this->ConfigSubdir.empty())
|
||||
{
|
||||
path = dir;
|
||||
path += "/";
|
||||
path += this->ConfigSubdir;
|
||||
path += "/";
|
||||
path += fname;
|
||||
if(this->ManifestFiles.find(path) != this->ManifestFiles.end())
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
else if(cmSystemTools::FileExists(path.c_str()))
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// A library conflicts if it is found and is not a symlink back to
|
||||
// the desired library.
|
||||
if(found)
|
||||
{
|
||||
return !cmSystemTools::SameFile(desiredLib, path.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmOrderLinkDirectories_h
|
||||
#define cmOrderLinkDirectories_h
|
||||
|
||||
#include <cmStandardIncludes.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "cmTarget.h"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
|
||||
/** \class cmOrderLinkDirectories
|
||||
* \brief Compute the best -L path order
|
||||
*
|
||||
* This class computes the best order for -L paths.
|
||||
* It tries to make sure full path specified libraries are
|
||||
* used. For example if you have /usr/mylib/libfoo.a on as
|
||||
* a link library for a target, and you also have /usr/lib/libbar.a
|
||||
* and you also have /usr/lib/libfoo.a, then you would
|
||||
* want -L/usr/mylib -L/usr/lib to make sure the correct libfoo.a is
|
||||
* found by the linker. The algorithm is as follows:
|
||||
* - foreach library create a vector of directories it exists in.
|
||||
* - foreach directory create a vector of directories that must come
|
||||
* after it, put this in a map<dir, vector<dir>> mapping from a directory
|
||||
* to the vector of directories that it must be before.
|
||||
* - put all directories into a vector
|
||||
* - sort the vector with a compare function CanBeBefore
|
||||
* CanBeBefore returns true if a directory is OK to be before
|
||||
* another directory. This is determined by looking at the
|
||||
* map<dir vector<dir>> and seeing if d1 is in the vector for d2.
|
||||
*/
|
||||
class cmOrderLinkDirectories
|
||||
{
|
||||
public:
|
||||
cmOrderLinkDirectories();
|
||||
///! set link information from the target
|
||||
void SetLinkInformation(const char* targetName,
|
||||
const std::vector<std::string>& linkLibraries,
|
||||
const std::vector<std::string>& linkDirectories,
|
||||
const cmTargetManifest& manifest,
|
||||
const char* configSubdir);
|
||||
///! Compute the best order for -L paths from GetLinkLibraries
|
||||
bool DetermineLibraryPathOrder();
|
||||
///! Get the results from DetermineLibraryPathOrder
|
||||
void GetLinkerInformation(std::vector<cmStdString>& searchPaths,
|
||||
std::vector<cmStdString>& linkItems)
|
||||
{
|
||||
linkItems = this->LinkItems;
|
||||
searchPaths = this->SortedSearchPaths;
|
||||
}
|
||||
// should be set from CMAKE_STATIC_LIBRARY_SUFFIX,
|
||||
// CMAKE_SHARED_LIBRARY_SUFFIX
|
||||
// CMAKE_LINK_LIBRARY_SUFFIX
|
||||
enum LinkType { LinkUnknown, LinkStatic, LinkShared };
|
||||
void AddLinkExtension(const char* e, LinkType type = LinkUnknown)
|
||||
{
|
||||
if(e && *e)
|
||||
{
|
||||
if(type == LinkStatic)
|
||||
{
|
||||
this->StaticLinkExtensions.push_back(e);
|
||||
}
|
||||
if(type == LinkShared)
|
||||
{
|
||||
this->SharedLinkExtensions.push_back(e);
|
||||
}
|
||||
this->LinkExtensions.push_back(e);
|
||||
}
|
||||
}
|
||||
// should be set from CMAKE_STATIC_LIBRARY_PREFIX
|
||||
void AddLinkPrefix(const char* s)
|
||||
{
|
||||
if(s)
|
||||
{
|
||||
this->LinkPrefixes.insert(s);
|
||||
}
|
||||
}
|
||||
// Return any warnings if the exist
|
||||
std::string GetWarnings();
|
||||
// return a list of all full path libraries
|
||||
void GetFullPathLibraries(std::vector<cmStdString>& libs);
|
||||
|
||||
// Provide flags for switching library link type.
|
||||
void SetLinkTypeInformation(LinkType start_link_type,
|
||||
const char* static_link_type_flag,
|
||||
const char* shared_link_type_flag);
|
||||
|
||||
// structure to hold a full path library link item
|
||||
struct Library
|
||||
{
|
||||
cmStdString FullPath;
|
||||
cmStdString File;
|
||||
cmStdString Path;
|
||||
};
|
||||
friend struct cmOrderLinkDirectoriesCompare;
|
||||
void DebugOn()
|
||||
{
|
||||
this->Debug = true;
|
||||
}
|
||||
|
||||
private:
|
||||
void CreateRegularExpressions();
|
||||
std::string CreateExtensionRegex(std::vector<cmStdString> const& exts);
|
||||
void DetermineLibraryPathOrder(std::vector<cmStdString>& searchPaths,
|
||||
std::vector<cmStdString>& libs,
|
||||
std::vector<cmStdString>& sortedPaths);
|
||||
void PrepareLinkTargets();
|
||||
bool LibraryInDirectory(const char* desiredLib,
|
||||
const char* dir, const char* lib);
|
||||
void FindLibrariesInSearchPaths();
|
||||
void FindIndividualLibraryOrders();
|
||||
void PrintMap(const char* name,
|
||||
std::map<cmStdString, std::vector<cmStdString> >& m);
|
||||
void PrintVector(const char* name,
|
||||
std::vector<std::pair<cmStdString,
|
||||
std::vector<cmStdString> > >& m);
|
||||
void OrderPaths(std::vector<cmStdString>& paths);
|
||||
bool FindPathNotInDirectoryToAfterList(cmStdString& path);
|
||||
std::string NoCaseExpression(const char* str);
|
||||
bool LibraryMayConflict(const char* desiredLib,
|
||||
const char* dir, const char* fname);
|
||||
private:
|
||||
// set of files that will exist when the build occurs
|
||||
std::set<cmStdString> ManifestFiles;
|
||||
// map from library to directories that it is in other than its full path
|
||||
std::map<cmStdString, std::vector<cmStdString> > LibraryToDirectories;
|
||||
// map from directory to vector of directories that must be after it
|
||||
std::vector<std::pair<cmStdString, std::vector<cmStdString> > >
|
||||
DirectoryToAfterList;
|
||||
std::set<cmStdString> DirectoryToAfterListEmitted;
|
||||
// map from full path to a Library struct
|
||||
std::map<cmStdString, Library> FullPathLibraries;
|
||||
// libraries that are found in multiple directories
|
||||
std::vector<Library> MultiDirectoryLibraries;
|
||||
// libraries that are only found in one directory
|
||||
std::vector<Library> SingleDirectoryLibraries;
|
||||
// This is a vector of all the link objects -lm or m
|
||||
std::vector<cmStdString> LinkItems;
|
||||
// Unprocessed link items
|
||||
std::vector<cmStdString> RawLinkItems;
|
||||
// This vector holds the sorted -L paths
|
||||
std::vector<cmStdString> SortedSearchPaths;
|
||||
// This vector holds the -F paths
|
||||
std::set<cmStdString> EmittedFrameworkPaths;
|
||||
// This is the set of -L paths unsorted, but unique
|
||||
std::set<cmStdString> LinkPathSet;
|
||||
// the names of link extensions
|
||||
std::vector<cmStdString> StaticLinkExtensions;
|
||||
std::vector<cmStdString> SharedLinkExtensions;
|
||||
std::vector<cmStdString> LinkExtensions;
|
||||
// the names of link prefixes
|
||||
std::set<cmStdString> LinkPrefixes;
|
||||
// set of directories that can not be put in the correct order
|
||||
std::set<cmStdString> ImpossibleDirectories;
|
||||
// Name of target
|
||||
cmStdString TargetName;
|
||||
// Subdirectory used for this configuration if any.
|
||||
cmStdString ConfigSubdir;
|
||||
|
||||
// Link type adjustment.
|
||||
LinkType StartLinkType;
|
||||
LinkType CurrentLinkType;
|
||||
cmStdString StaticLinkTypeFlag;
|
||||
cmStdString SharedLinkTypeFlag;
|
||||
bool LinkTypeEnabled;
|
||||
void SetCurrentLinkType(LinkType lt);
|
||||
|
||||
// library regular expressions
|
||||
cmsys::RegularExpression RemoveLibraryExtension;
|
||||
cmsys::RegularExpression ExtractStaticLibraryName;
|
||||
cmsys::RegularExpression ExtractSharedLibraryName;
|
||||
cmsys::RegularExpression ExtractAnyLibraryName;
|
||||
cmsys::RegularExpression SplitFramework;
|
||||
bool Debug;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -35,7 +35,6 @@ cmTarget::cmTarget()
|
|||
{
|
||||
this->Makefile = 0;
|
||||
this->LinkLibrariesAnalyzed = false;
|
||||
this->LinkDirectoriesComputed = false;
|
||||
this->HaveInstallRule = false;
|
||||
this->DLLPlatform = false;
|
||||
this->IsImportedTarget = false;
|
||||
|
@ -843,71 +842,15 @@ void cmTarget::MergeLinkLibraries( cmMakefile& mf,
|
|||
void cmTarget::AddLinkDirectory(const char* d)
|
||||
{
|
||||
// Make sure we don't add unnecessary search directories.
|
||||
if(std::find(this->ExplicitLinkDirectories.begin(),
|
||||
this->ExplicitLinkDirectories.end(), d)
|
||||
== this->ExplicitLinkDirectories.end() )
|
||||
if(this->LinkDirectoriesEmmitted.insert(d).second)
|
||||
{
|
||||
this->ExplicitLinkDirectories.push_back( d );
|
||||
this->LinkDirectoriesComputed = false;
|
||||
this->LinkDirectories.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const std::vector<std::string>& cmTarget::GetLinkDirectories()
|
||||
{
|
||||
// Make sure all library dependencies have been analyzed.
|
||||
if(!this->LinkLibrariesAnalyzed && !this->LinkLibraries.empty())
|
||||
{
|
||||
cmSystemTools::Error(
|
||||
"cmTarget::GetLinkDirectories called before "
|
||||
"cmTarget::AnalyzeLibDependencies on target ",
|
||||
this->Name.c_str());
|
||||
}
|
||||
|
||||
// Make sure the complete set of link directories has been computed.
|
||||
if(!this->LinkDirectoriesComputed)
|
||||
{
|
||||
// Check whether we should use an import library for linking a target.
|
||||
bool implib =
|
||||
this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX") != 0;
|
||||
|
||||
// Compute the full set of link directories including the
|
||||
// locations of targets that have been linked in. Start with the
|
||||
// link directories given explicitly.
|
||||
this->LinkDirectories = this->ExplicitLinkDirectories;
|
||||
for(LinkLibraryVectorType::iterator ll = this->LinkLibraries.begin();
|
||||
ll != this->LinkLibraries.end(); ++ll)
|
||||
{
|
||||
// If this library is a CMake target then add its location as a
|
||||
// link directory.
|
||||
std::string lib = ll->first;
|
||||
cmTarget* tgt = 0;
|
||||
if(this->Makefile && this->Makefile->GetLocalGenerator() &&
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator())
|
||||
{
|
||||
tgt = (this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
|
||||
->FindTarget(0, lib.c_str(), false));
|
||||
}
|
||||
if(tgt)
|
||||
{
|
||||
// Add the directory only if it is not already present. This
|
||||
// is an N^2 algorithm for adding the directories, but N
|
||||
// should not get very big.
|
||||
const char* libpath = tgt->GetDirectory(0, implib);
|
||||
if(std::find(this->LinkDirectories.begin(),
|
||||
this->LinkDirectories.end(),
|
||||
libpath) == this->LinkDirectories.end())
|
||||
{
|
||||
this->LinkDirectories.push_back(libpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The complete set of link directories has now been computed.
|
||||
this->LinkDirectoriesComputed = true;
|
||||
}
|
||||
|
||||
// Return the complete set of link directories.
|
||||
return this->LinkDirectories;
|
||||
}
|
||||
|
||||
|
@ -2244,6 +2187,76 @@ void cmTarget::GetExecutableNamesInternal(std::string& name,
|
|||
pdbName = prefix+base+".pdb";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::GenerateTargetManifest(const char* config)
|
||||
{
|
||||
cmMakefile* mf = this->Makefile;
|
||||
cmLocalGenerator* lg = mf->GetLocalGenerator();
|
||||
cmGlobalGenerator* gg = lg->GetGlobalGenerator();
|
||||
|
||||
// Get the names.
|
||||
std::string name;
|
||||
std::string soName;
|
||||
std::string realName;
|
||||
std::string impName;
|
||||
std::string pdbName;
|
||||
if(this->GetType() == cmTarget::EXECUTABLE)
|
||||
{
|
||||
this->GetExecutableNames(name, realName, impName, pdbName, config);
|
||||
}
|
||||
else if(this->GetType() == cmTarget::STATIC_LIBRARY ||
|
||||
this->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
this->GetType() == cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the directory.
|
||||
std::string dir = this->GetDirectory(config, false);
|
||||
|
||||
// Add each name.
|
||||
std::string f;
|
||||
if(!name.empty())
|
||||
{
|
||||
f = dir;
|
||||
f += "/";
|
||||
f += name;
|
||||
gg->AddToManifest(config? config:"", f);
|
||||
}
|
||||
if(!soName.empty())
|
||||
{
|
||||
f = dir;
|
||||
f += "/";
|
||||
f += soName;
|
||||
gg->AddToManifest(config? config:"", f);
|
||||
}
|
||||
if(!realName.empty())
|
||||
{
|
||||
f = dir;
|
||||
f += "/";
|
||||
f += realName;
|
||||
gg->AddToManifest(config? config:"", f);
|
||||
}
|
||||
if(!pdbName.empty())
|
||||
{
|
||||
f = dir;
|
||||
f += "/";
|
||||
f += pdbName;
|
||||
gg->AddToManifest(config? config:"", f);
|
||||
}
|
||||
if(!impName.empty())
|
||||
{
|
||||
f = this->GetDirectory(config, true);
|
||||
f += "/";
|
||||
f += impName;
|
||||
gg->AddToManifest(config? config:"", f);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::SetPropertyDefault(const char* property,
|
||||
const char* default_value)
|
||||
|
|
|
@ -271,6 +271,9 @@ public:
|
|||
std::string& impName,
|
||||
std::string& pdbName, const char* config);
|
||||
|
||||
/** Add the target output files to the global generator manifest. */
|
||||
void GenerateTargetManifest(const char* config);
|
||||
|
||||
/**
|
||||
* Compute whether this target must be relinked before installing.
|
||||
*/
|
||||
|
@ -414,10 +417,9 @@ private:
|
|||
LinkLibraryVectorType LinkLibraries;
|
||||
LinkLibraryVectorType PrevLinkedLibraries;
|
||||
bool LinkLibrariesAnalyzed;
|
||||
bool LinkDirectoriesComputed;
|
||||
std::vector<std::string> Frameworks;
|
||||
std::vector<std::string> LinkDirectories;
|
||||
std::vector<std::string> ExplicitLinkDirectories;
|
||||
std::set<cmStdString> LinkDirectoriesEmmitted;
|
||||
bool HaveInstallRule;
|
||||
std::string InstallNameFixupPath;
|
||||
std::string InstallPath;
|
||||
|
|
|
@ -13,7 +13,6 @@ extern "C" {
|
|||
#include "cmSystemTools.h"
|
||||
#include "cmDynamicLoader.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmOrderLinkDirectories.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include <cmsys/DynamicLoader.hxx>
|
||||
#else
|
||||
|
@ -69,99 +68,6 @@ void cmPassed(const char* Message, const char* m2="")
|
|||
#endif
|
||||
|
||||
#ifdef COMPLEX_TEST_CMAKELIB
|
||||
// Here is a stupid function that tries to use std::string methods
|
||||
// so that the dec cxx compiler will instantiate the stuff that
|
||||
// we are using from the CMakeLib library....
|
||||
bool TestLibraryOrder(bool shouldFail)
|
||||
{
|
||||
std::string Adir = std::string(BINARY_DIR) + std::string("/A");
|
||||
std::string Bdir = std::string(BINARY_DIR) + std::string("/B");
|
||||
std::string Cdir = std::string(BINARY_DIR) + std::string("/C");
|
||||
#ifdef _WIN32
|
||||
// Avoid case problems for windows paths.
|
||||
if(Adir[0] >= 'A' && Adir[0] <= 'Z') { Adir[0] += 'a' - 'A'; }
|
||||
if(Bdir[0] >= 'A' && Bdir[0] <= 'Z') { Bdir[0] += 'a' - 'A'; }
|
||||
if(Cdir[0] >= 'A' && Cdir[0] <= 'Z') { Cdir[0] += 'a' - 'A'; }
|
||||
Adir = cmSystemTools::GetActualCaseForPath(Adir.c_str());
|
||||
Bdir = cmSystemTools::GetActualCaseForPath(Bdir.c_str());
|
||||
Cdir = cmSystemTools::GetActualCaseForPath(Cdir.c_str());
|
||||
#endif
|
||||
|
||||
if(!shouldFail)
|
||||
{
|
||||
std::string rm = Bdir;
|
||||
rm += "/libA.a";
|
||||
cmSystemTools::RemoveFile(rm.c_str());
|
||||
}
|
||||
std::vector<std::string> linkLibraries;
|
||||
std::vector<std::string> linkDirectories;
|
||||
linkDirectories.push_back(Adir);
|
||||
linkDirectories.push_back(Bdir);
|
||||
linkDirectories.push_back(Cdir);
|
||||
linkDirectories.push_back("/lib/extra/stuff");
|
||||
Adir += "/libA.a";
|
||||
Bdir += "/libB.a";
|
||||
Cdir += "/libC.a";
|
||||
linkLibraries.push_back(Adir);
|
||||
linkLibraries.push_back(Bdir);
|
||||
linkLibraries.push_back(Cdir);
|
||||
linkLibraries.push_back("-lm");
|
||||
std::vector<cmStdString> sortedpaths;
|
||||
std::vector<cmStdString> linkItems;
|
||||
cmOrderLinkDirectories orderLibs;
|
||||
orderLibs.DebugOn();
|
||||
orderLibs.AddLinkExtension(".so");
|
||||
orderLibs.AddLinkExtension(".a");
|
||||
orderLibs.AddLinkPrefix("lib");
|
||||
cmTargetManifest manifest;
|
||||
orderLibs.SetLinkInformation("test", linkLibraries, linkDirectories,
|
||||
manifest, "");
|
||||
bool ret = orderLibs.DetermineLibraryPathOrder();
|
||||
if(!ret)
|
||||
{
|
||||
std::cout << orderLibs.GetWarnings() << "\n";
|
||||
}
|
||||
orderLibs.GetLinkerInformation(sortedpaths, linkItems);
|
||||
std::cout << "Sorted Link Paths:\n";
|
||||
for(std::vector<cmStdString>::iterator i = sortedpaths.begin();
|
||||
i != sortedpaths.end(); ++i)
|
||||
{
|
||||
std::cout << *i << "\n";
|
||||
}
|
||||
std::cout << "Link Items: \n";
|
||||
for(std::vector<cmStdString>::iterator i = linkItems.begin();
|
||||
i != linkItems.end(); ++i)
|
||||
{
|
||||
std::cout << *i << "\n";
|
||||
}
|
||||
if(!(linkItems[0] == "A" &&
|
||||
linkItems[1] == "B" &&
|
||||
linkItems[2] == "C" &&
|
||||
linkItems[3] == "-lm" ))
|
||||
{
|
||||
std::cout << "fail because link items should be A B C -lm and the are not\n";
|
||||
return shouldFail;
|
||||
}
|
||||
|
||||
|
||||
// if this is not the fail test then the order should be f B C A
|
||||
if(!shouldFail)
|
||||
{
|
||||
char order[5];
|
||||
order[4] = 0;
|
||||
for(int i =0; i < 4; ++i)
|
||||
{
|
||||
order[i] = sortedpaths[i][sortedpaths[i].size()-1];
|
||||
}
|
||||
if(!(strcmp(order, "fBCA") == 0 || strcmp(order, "BCAf") == 0))
|
||||
{
|
||||
std::cout << "fail because order should be /lib/extra/stuff B C A and it is not\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void TestAndRemoveFile(const char* filename)
|
||||
|
@ -286,6 +192,9 @@ void TestCMGeneratedFileSTream()
|
|||
}
|
||||
#endif
|
||||
|
||||
// Here is a stupid function that tries to use std::string methods
|
||||
// so that the dec cxx compiler will instantiate the stuff that
|
||||
// we are using from the CMakeLib library....
|
||||
void ForceStringUse()
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
@ -1283,27 +1192,6 @@ int main()
|
|||
#endif
|
||||
|
||||
#ifdef COMPLEX_TEST_CMAKELIB
|
||||
// first run with shouldFail = true, this will
|
||||
// run with A B C as set by the CMakeList.txt file.
|
||||
if(!TestLibraryOrder(true))
|
||||
{
|
||||
cmPassed("CMake cmOrderLinkDirectories failed when it should.");
|
||||
}
|
||||
else
|
||||
{
|
||||
cmFailed("CMake cmOrderLinkDirectories failed to fail when given an impossible set of paths.");
|
||||
}
|
||||
// next run with shouldPass = true, this will
|
||||
// run with B/libA.a removed and should create the order
|
||||
// B C A
|
||||
if(TestLibraryOrder(false))
|
||||
{
|
||||
cmPassed("CMake cmOrderLinkDirectories worked.");
|
||||
}
|
||||
else
|
||||
{
|
||||
cmFailed("CMake cmOrderLinkDirectories failed.");
|
||||
}
|
||||
// Test the generated file stream.
|
||||
TestCMGeneratedFileSTream();
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,6 @@ extern "C" {
|
|||
#include "cmSystemTools.h"
|
||||
#include "cmDynamicLoader.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmOrderLinkDirectories.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include <cmsys/DynamicLoader.hxx>
|
||||
#else
|
||||
|
@ -69,99 +68,6 @@ void cmPassed(const char* Message, const char* m2="")
|
|||
#endif
|
||||
|
||||
#ifdef COMPLEX_TEST_CMAKELIB
|
||||
// Here is a stupid function that tries to use std::string methods
|
||||
// so that the dec cxx compiler will instantiate the stuff that
|
||||
// we are using from the CMakeLib library....
|
||||
bool TestLibraryOrder(bool shouldFail)
|
||||
{
|
||||
std::string Adir = std::string(BINARY_DIR) + std::string("/A");
|
||||
std::string Bdir = std::string(BINARY_DIR) + std::string("/B");
|
||||
std::string Cdir = std::string(BINARY_DIR) + std::string("/C");
|
||||
#ifdef _WIN32
|
||||
// Avoid case problems for windows paths.
|
||||
if(Adir[0] >= 'A' && Adir[0] <= 'Z') { Adir[0] += 'a' - 'A'; }
|
||||
if(Bdir[0] >= 'A' && Bdir[0] <= 'Z') { Bdir[0] += 'a' - 'A'; }
|
||||
if(Cdir[0] >= 'A' && Cdir[0] <= 'Z') { Cdir[0] += 'a' - 'A'; }
|
||||
Adir = cmSystemTools::GetActualCaseForPath(Adir.c_str());
|
||||
Bdir = cmSystemTools::GetActualCaseForPath(Bdir.c_str());
|
||||
Cdir = cmSystemTools::GetActualCaseForPath(Cdir.c_str());
|
||||
#endif
|
||||
|
||||
if(!shouldFail)
|
||||
{
|
||||
std::string rm = Bdir;
|
||||
rm += "/libA.a";
|
||||
cmSystemTools::RemoveFile(rm.c_str());
|
||||
}
|
||||
std::vector<std::string> linkLibraries;
|
||||
std::vector<std::string> linkDirectories;
|
||||
linkDirectories.push_back(Adir);
|
||||
linkDirectories.push_back(Bdir);
|
||||
linkDirectories.push_back(Cdir);
|
||||
linkDirectories.push_back("/lib/extra/stuff");
|
||||
Adir += "/libA.a";
|
||||
Bdir += "/libB.a";
|
||||
Cdir += "/libC.a";
|
||||
linkLibraries.push_back(Adir);
|
||||
linkLibraries.push_back(Bdir);
|
||||
linkLibraries.push_back(Cdir);
|
||||
linkLibraries.push_back("-lm");
|
||||
std::vector<cmStdString> sortedpaths;
|
||||
std::vector<cmStdString> linkItems;
|
||||
cmOrderLinkDirectories orderLibs;
|
||||
orderLibs.DebugOn();
|
||||
orderLibs.AddLinkExtension(".so");
|
||||
orderLibs.AddLinkExtension(".a");
|
||||
orderLibs.AddLinkPrefix("lib");
|
||||
cmTargetManifest manifest;
|
||||
orderLibs.SetLinkInformation("test", linkLibraries, linkDirectories,
|
||||
manifest, "");
|
||||
bool ret = orderLibs.DetermineLibraryPathOrder();
|
||||
if(!ret)
|
||||
{
|
||||
std::cout << orderLibs.GetWarnings() << "\n";
|
||||
}
|
||||
orderLibs.GetLinkerInformation(sortedpaths, linkItems);
|
||||
std::cout << "Sorted Link Paths:\n";
|
||||
for(std::vector<cmStdString>::iterator i = sortedpaths.begin();
|
||||
i != sortedpaths.end(); ++i)
|
||||
{
|
||||
std::cout << *i << "\n";
|
||||
}
|
||||
std::cout << "Link Items: \n";
|
||||
for(std::vector<cmStdString>::iterator i = linkItems.begin();
|
||||
i != linkItems.end(); ++i)
|
||||
{
|
||||
std::cout << *i << "\n";
|
||||
}
|
||||
if(!(linkItems[0] == "A" &&
|
||||
linkItems[1] == "B" &&
|
||||
linkItems[2] == "C" &&
|
||||
linkItems[3] == "-lm" ))
|
||||
{
|
||||
std::cout << "fail because link items should be A B C -lm and the are not\n";
|
||||
return shouldFail;
|
||||
}
|
||||
|
||||
|
||||
// if this is not the fail test then the order should be f B C A
|
||||
if(!shouldFail)
|
||||
{
|
||||
char order[5];
|
||||
order[4] = 0;
|
||||
for(int i =0; i < 4; ++i)
|
||||
{
|
||||
order[i] = sortedpaths[i][sortedpaths[i].size()-1];
|
||||
}
|
||||
if(!(strcmp(order, "fBCA") == 0 || strcmp(order, "BCAf") == 0))
|
||||
{
|
||||
std::cout << "fail because order should be /lib/extra/stuff B C A and it is not\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void TestAndRemoveFile(const char* filename)
|
||||
|
@ -286,6 +192,9 @@ void TestCMGeneratedFileSTream()
|
|||
}
|
||||
#endif
|
||||
|
||||
// Here is a stupid function that tries to use std::string methods
|
||||
// so that the dec cxx compiler will instantiate the stuff that
|
||||
// we are using from the CMakeLib library....
|
||||
void ForceStringUse()
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
@ -1283,27 +1192,6 @@ int main()
|
|||
#endif
|
||||
|
||||
#ifdef COMPLEX_TEST_CMAKELIB
|
||||
// first run with shouldFail = true, this will
|
||||
// run with A B C as set by the CMakeList.txt file.
|
||||
if(!TestLibraryOrder(true))
|
||||
{
|
||||
cmPassed("CMake cmOrderLinkDirectories failed when it should.");
|
||||
}
|
||||
else
|
||||
{
|
||||
cmFailed("CMake cmOrderLinkDirectories failed to fail when given an impossible set of paths.");
|
||||
}
|
||||
// next run with shouldPass = true, this will
|
||||
// run with B/libA.a removed and should create the order
|
||||
// B C A
|
||||
if(TestLibraryOrder(false))
|
||||
{
|
||||
cmPassed("CMake cmOrderLinkDirectories worked.");
|
||||
}
|
||||
else
|
||||
{
|
||||
cmFailed("CMake cmOrderLinkDirectories failed.");
|
||||
}
|
||||
// Test the generated file stream.
|
||||
TestCMGeneratedFileSTream();
|
||||
#endif
|
||||
|
|
|
@ -13,7 +13,6 @@ extern "C" {
|
|||
#include "cmSystemTools.h"
|
||||
#include "cmDynamicLoader.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmOrderLinkDirectories.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include <cmsys/DynamicLoader.hxx>
|
||||
#else
|
||||
|
@ -69,99 +68,6 @@ void cmPassed(const char* Message, const char* m2="")
|
|||
#endif
|
||||
|
||||
#ifdef COMPLEX_TEST_CMAKELIB
|
||||
// Here is a stupid function that tries to use std::string methods
|
||||
// so that the dec cxx compiler will instantiate the stuff that
|
||||
// we are using from the CMakeLib library....
|
||||
bool TestLibraryOrder(bool shouldFail)
|
||||
{
|
||||
std::string Adir = std::string(BINARY_DIR) + std::string("/A");
|
||||
std::string Bdir = std::string(BINARY_DIR) + std::string("/B");
|
||||
std::string Cdir = std::string(BINARY_DIR) + std::string("/C");
|
||||
#ifdef _WIN32
|
||||
// Avoid case problems for windows paths.
|
||||
if(Adir[0] >= 'A' && Adir[0] <= 'Z') { Adir[0] += 'a' - 'A'; }
|
||||
if(Bdir[0] >= 'A' && Bdir[0] <= 'Z') { Bdir[0] += 'a' - 'A'; }
|
||||
if(Cdir[0] >= 'A' && Cdir[0] <= 'Z') { Cdir[0] += 'a' - 'A'; }
|
||||
Adir = cmSystemTools::GetActualCaseForPath(Adir.c_str());
|
||||
Bdir = cmSystemTools::GetActualCaseForPath(Bdir.c_str());
|
||||
Cdir = cmSystemTools::GetActualCaseForPath(Cdir.c_str());
|
||||
#endif
|
||||
|
||||
if(!shouldFail)
|
||||
{
|
||||
std::string rm = Bdir;
|
||||
rm += "/libA.a";
|
||||
cmSystemTools::RemoveFile(rm.c_str());
|
||||
}
|
||||
std::vector<std::string> linkLibraries;
|
||||
std::vector<std::string> linkDirectories;
|
||||
linkDirectories.push_back(Adir);
|
||||
linkDirectories.push_back(Bdir);
|
||||
linkDirectories.push_back(Cdir);
|
||||
linkDirectories.push_back("/lib/extra/stuff");
|
||||
Adir += "/libA.a";
|
||||
Bdir += "/libB.a";
|
||||
Cdir += "/libC.a";
|
||||
linkLibraries.push_back(Adir);
|
||||
linkLibraries.push_back(Bdir);
|
||||
linkLibraries.push_back(Cdir);
|
||||
linkLibraries.push_back("-lm");
|
||||
std::vector<cmStdString> sortedpaths;
|
||||
std::vector<cmStdString> linkItems;
|
||||
cmOrderLinkDirectories orderLibs;
|
||||
orderLibs.DebugOn();
|
||||
orderLibs.AddLinkExtension(".so");
|
||||
orderLibs.AddLinkExtension(".a");
|
||||
orderLibs.AddLinkPrefix("lib");
|
||||
cmTargetManifest manifest;
|
||||
orderLibs.SetLinkInformation("test", linkLibraries, linkDirectories,
|
||||
manifest, "");
|
||||
bool ret = orderLibs.DetermineLibraryPathOrder();
|
||||
if(!ret)
|
||||
{
|
||||
std::cout << orderLibs.GetWarnings() << "\n";
|
||||
}
|
||||
orderLibs.GetLinkerInformation(sortedpaths, linkItems);
|
||||
std::cout << "Sorted Link Paths:\n";
|
||||
for(std::vector<cmStdString>::iterator i = sortedpaths.begin();
|
||||
i != sortedpaths.end(); ++i)
|
||||
{
|
||||
std::cout << *i << "\n";
|
||||
}
|
||||
std::cout << "Link Items: \n";
|
||||
for(std::vector<cmStdString>::iterator i = linkItems.begin();
|
||||
i != linkItems.end(); ++i)
|
||||
{
|
||||
std::cout << *i << "\n";
|
||||
}
|
||||
if(!(linkItems[0] == "A" &&
|
||||
linkItems[1] == "B" &&
|
||||
linkItems[2] == "C" &&
|
||||
linkItems[3] == "-lm" ))
|
||||
{
|
||||
std::cout << "fail because link items should be A B C -lm and the are not\n";
|
||||
return shouldFail;
|
||||
}
|
||||
|
||||
|
||||
// if this is not the fail test then the order should be f B C A
|
||||
if(!shouldFail)
|
||||
{
|
||||
char order[5];
|
||||
order[4] = 0;
|
||||
for(int i =0; i < 4; ++i)
|
||||
{
|
||||
order[i] = sortedpaths[i][sortedpaths[i].size()-1];
|
||||
}
|
||||
if(!(strcmp(order, "fBCA") == 0 || strcmp(order, "BCAf") == 0))
|
||||
{
|
||||
std::cout << "fail because order should be /lib/extra/stuff B C A and it is not\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void TestAndRemoveFile(const char* filename)
|
||||
|
@ -286,6 +192,9 @@ void TestCMGeneratedFileSTream()
|
|||
}
|
||||
#endif
|
||||
|
||||
// Here is a stupid function that tries to use std::string methods
|
||||
// so that the dec cxx compiler will instantiate the stuff that
|
||||
// we are using from the CMakeLib library....
|
||||
void ForceStringUse()
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
@ -1283,27 +1192,6 @@ int main()
|
|||
#endif
|
||||
|
||||
#ifdef COMPLEX_TEST_CMAKELIB
|
||||
// first run with shouldFail = true, this will
|
||||
// run with A B C as set by the CMakeList.txt file.
|
||||
if(!TestLibraryOrder(true))
|
||||
{
|
||||
cmPassed("CMake cmOrderLinkDirectories failed when it should.");
|
||||
}
|
||||
else
|
||||
{
|
||||
cmFailed("CMake cmOrderLinkDirectories failed to fail when given an impossible set of paths.");
|
||||
}
|
||||
// next run with shouldPass = true, this will
|
||||
// run with B/libA.a removed and should create the order
|
||||
// B C A
|
||||
if(TestLibraryOrder(false))
|
||||
{
|
||||
cmPassed("CMake cmOrderLinkDirectories worked.");
|
||||
}
|
||||
else
|
||||
{
|
||||
cmFailed("CMake cmOrderLinkDirectories failed.");
|
||||
}
|
||||
// Test the generated file stream.
|
||||
TestCMGeneratedFileSTream();
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue