Commit 96fd5909 authored by Brad King's avatar Brad King

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.
parent 0df9e690
......@@ -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)
......
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
......
This diff is collapsed.
/*=========================================================================
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);
}
}
}
......
This diff is collapsed.
......@@ -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);