Merge topic 'auto_export_dll_symbols'
8f86407c Windows: Optionally generate DLL module definition files automatically 069aa93b bindexplib: Add support for "/bigobj" format objects 61bbbdcf bindexplib: Fix treatment of some symbols de70c922 bindexplib: Teach DumpFile to return errors 8ea69dfe bindexplib: Build source as part of CMakeLib 2963cb2a bindexplib: Wrap long lines 4ff09893 bindexplib: Drop code that CMake does not need 7de8276c bindexplib: Add copyright/license notice block 65086ad7 bindexplib: Import original implementation from CERN
This commit is contained in:
commit
ad91d0edd5
@ -251,6 +251,7 @@ Properties on Targets
|
|||||||
/prop_tgt/VS_WINRT_EXTENSIONS
|
/prop_tgt/VS_WINRT_EXTENSIONS
|
||||||
/prop_tgt/VS_WINRT_REFERENCES
|
/prop_tgt/VS_WINRT_REFERENCES
|
||||||
/prop_tgt/WIN32_EXECUTABLE
|
/prop_tgt/WIN32_EXECUTABLE
|
||||||
|
/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS
|
||||||
/prop_tgt/XCODE_ATTRIBUTE_an-attribute
|
/prop_tgt/XCODE_ATTRIBUTE_an-attribute
|
||||||
/prop_tgt/XCTEST
|
/prop_tgt/XCTEST
|
||||||
|
|
||||||
|
@ -275,6 +275,7 @@ Variables that Control the Build
|
|||||||
/variable/CMAKE_USE_RELATIVE_PATHS
|
/variable/CMAKE_USE_RELATIVE_PATHS
|
||||||
/variable/CMAKE_VISIBILITY_INLINES_HIDDEN
|
/variable/CMAKE_VISIBILITY_INLINES_HIDDEN
|
||||||
/variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD
|
/variable/CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD
|
||||||
|
/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
|
||||||
/variable/CMAKE_WIN32_EXECUTABLE
|
/variable/CMAKE_WIN32_EXECUTABLE
|
||||||
/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute
|
/variable/CMAKE_XCODE_ATTRIBUTE_an-attribute
|
||||||
/variable/EXECUTABLE_OUTPUT_PATH
|
/variable/EXECUTABLE_OUTPUT_PATH
|
||||||
|
18
Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
Normal file
18
Help/prop_tgt/WINDOWS_EXPORT_ALL_SYMBOLS.rst
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
WINDOWS_EXPORT_ALL_SYMBOLS
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
This property is implemented only for MS-compatible tools on Windows.
|
||||||
|
|
||||||
|
Enable this boolean property to automatically create a module definition
|
||||||
|
(``.def``) file with all global symbols found in the input ``.obj`` files
|
||||||
|
for a ``SHARED`` library on Windows. The module definition file will be
|
||||||
|
passed to the linker causing all symbols to be exported from the ``.dll``.
|
||||||
|
For global *data* symbols, ``__declspec(dllimport)`` must still be used when
|
||||||
|
compiling against the code in the ``.dll``. All other function symbols will
|
||||||
|
be automatically exported and imported by callers. This simplifies porting
|
||||||
|
projects to Windows by reducing the need for explicit ``dllexport`` markup,
|
||||||
|
even in ``C++`` classes.
|
||||||
|
|
||||||
|
This property is initialized by the value of
|
||||||
|
the :variable:`CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS` variable if it is set
|
||||||
|
when a target is created.
|
6
Help/release/dev/auto_export_dll_symbols.rst
Normal file
6
Help/release/dev/auto_export_dll_symbols.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
auto_export_dll_symbols
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
* On Windows with MS-compatible tools, CMake learned to optionally
|
||||||
|
generate a module definition (``.def``) file for ``SHARED`` libraries.
|
||||||
|
See the :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property.
|
6
Help/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.rst
Normal file
6
Help/variable/CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS.rst
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
Default value for :prop_tgt:`WINDOWS_EXPORT_ALL_SYMBOLS` target property.
|
||||||
|
This variable is used to initialize the property on each target as it is
|
||||||
|
created.
|
@ -46,8 +46,10 @@ else()
|
|||||||
set(_PLATFORM_LINK_FLAGS "")
|
set(_PLATFORM_LINK_FLAGS "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 1)
|
||||||
if(CMAKE_GENERATOR MATCHES "Visual Studio 6")
|
if(CMAKE_GENERATOR MATCHES "Visual Studio 6")
|
||||||
set (CMAKE_NO_BUILD_TYPE 1)
|
set (CMAKE_NO_BUILD_TYPE 1)
|
||||||
|
set(CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 0) # not implemented for VS6
|
||||||
endif()
|
endif()
|
||||||
if(NOT CMAKE_NO_BUILD_TYPE AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
if(NOT CMAKE_NO_BUILD_TYPE AND CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
set (CMAKE_NO_BUILD_TYPE 1)
|
set (CMAKE_NO_BUILD_TYPE 1)
|
||||||
|
@ -430,6 +430,7 @@ if (WIN32)
|
|||||||
set(SRCS ${SRCS}
|
set(SRCS ${SRCS}
|
||||||
cmCallVisualStudioMacro.cxx
|
cmCallVisualStudioMacro.cxx
|
||||||
cmCallVisualStudioMacro.h
|
cmCallVisualStudioMacro.h
|
||||||
|
bindexplib.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT UNIX)
|
if(NOT UNIX)
|
||||||
|
428
Source/bindexplib.cxx
Normal file
428
Source/bindexplib.cxx
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
/*============================================================================
|
||||||
|
CMake - Cross Platform Makefile Generator
|
||||||
|
Copyright 2000-2015 Kitware, Inc.
|
||||||
|
|
||||||
|
Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
see accompanying file Copyright.txt for details.
|
||||||
|
|
||||||
|
This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the License for more information.
|
||||||
|
============================================================================*/
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
Portions of this source have been derived from the 'bindexplib' tool
|
||||||
|
provided by the CERN ROOT Data Analysis Framework project (root.cern.ch).
|
||||||
|
Permission has been granted by Pere Mato <pere.mato@cern.ch> to distribute
|
||||||
|
this derived work under the CMake license.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
* Program: dumpexts.exe
|
||||||
|
* Author: Gordon Chaffee
|
||||||
|
*
|
||||||
|
* History: The real functionality of this file was written by
|
||||||
|
* Matt Pietrek in 1993 in his pedump utility. I've
|
||||||
|
* modified it to dump the externals in a bunch of object
|
||||||
|
* files to create a .def file.
|
||||||
|
*
|
||||||
|
* Notes: Visual C++ puts an underscore before each exported symbol.
|
||||||
|
* This file removes them. I don't know if this is a problem
|
||||||
|
* this other compilers. If _MSC_VER is defined,
|
||||||
|
* the underscore is removed. If not, it isn't. To get a
|
||||||
|
* full dump of an object file, use the -f option. This can
|
||||||
|
* help determine the something that may be different with a
|
||||||
|
* compiler other than Visual C++.
|
||||||
|
* ======================================
|
||||||
|
* Corrections (Axel 2006-04-04):
|
||||||
|
* Conversion to C++. Mostly.
|
||||||
|
*
|
||||||
|
* Extension (Axel 2006-03-15)
|
||||||
|
* As soon as an object file contains an /EXPORT directive (which
|
||||||
|
* is generated by the compiler when a symbol is declared as
|
||||||
|
* declspec(dllexport)) no to-be-exported symbols are printed,
|
||||||
|
* as the linker will see these directives, and if those directives
|
||||||
|
* are present we only export selectively (i.e. we trust the
|
||||||
|
* programmer).
|
||||||
|
*
|
||||||
|
* ======================================
|
||||||
|
* ======================================
|
||||||
|
* Corrections (Valery Fine 23/02/98):
|
||||||
|
*
|
||||||
|
* The "(vector) deleting destructor" MUST not be exported
|
||||||
|
* To recognize it the following test are introduced:
|
||||||
|
* "@@UAEPAXI@Z" scalar deleting dtor
|
||||||
|
* "@@QAEPAXI@Z" vector deleting dtor
|
||||||
|
* "AEPAXI@Z" vector deleting dtor with thunk adjustor
|
||||||
|
* ======================================
|
||||||
|
* Corrections (Valery Fine 12/02/97):
|
||||||
|
*
|
||||||
|
* It created a wrong EXPORTS for the global pointers and constants.
|
||||||
|
* The Section Header has been involved to discover the missing information
|
||||||
|
* Now the pointers are correctly supplied supplied with "DATA" descriptor
|
||||||
|
* the constants with no extra descriptor.
|
||||||
|
*
|
||||||
|
* Corrections (Valery Fine 16/09/96):
|
||||||
|
*
|
||||||
|
* It didn't work for C++ code with global variables and class definitons
|
||||||
|
* The DumpExternalObject function has been introduced to generate .DEF file
|
||||||
|
*
|
||||||
|
* Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch)
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cmsys/Encoding.hxx>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
typedef struct cmANON_OBJECT_HEADER_BIGOBJ {
|
||||||
|
/* same as ANON_OBJECT_HEADER_V2 */
|
||||||
|
WORD Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN
|
||||||
|
WORD Sig2; // Must be 0xffff
|
||||||
|
WORD Version; // >= 2 (implies the Flags field is present)
|
||||||
|
WORD Machine; // Actual machine - IMAGE_FILE_MACHINE_xxx
|
||||||
|
DWORD TimeDateStamp;
|
||||||
|
CLSID ClassID; // {D1BAA1C7-BAEE-4ba9-AF20-FAF66AA4DCB8}
|
||||||
|
DWORD SizeOfData; // Size of data that follows the header
|
||||||
|
DWORD Flags; // 0x1 -> contains metadata
|
||||||
|
DWORD MetaDataSize; // Size of CLR metadata
|
||||||
|
DWORD MetaDataOffset; // Offset of CLR metadata
|
||||||
|
|
||||||
|
/* bigobj specifics */
|
||||||
|
DWORD NumberOfSections; // extended from WORD
|
||||||
|
DWORD PointerToSymbolTable;
|
||||||
|
DWORD NumberOfSymbols;
|
||||||
|
} cmANON_OBJECT_HEADER_BIGOBJ;
|
||||||
|
|
||||||
|
typedef struct _cmIMAGE_SYMBOL_EX {
|
||||||
|
union {
|
||||||
|
BYTE ShortName[8];
|
||||||
|
struct {
|
||||||
|
DWORD Short; // if 0, use LongName
|
||||||
|
DWORD Long; // offset into string table
|
||||||
|
} Name;
|
||||||
|
DWORD LongName[2]; // PBYTE [2]
|
||||||
|
} N;
|
||||||
|
DWORD Value;
|
||||||
|
LONG SectionNumber;
|
||||||
|
WORD Type;
|
||||||
|
BYTE StorageClass;
|
||||||
|
BYTE NumberOfAuxSymbols;
|
||||||
|
} cmIMAGE_SYMBOL_EX;
|
||||||
|
typedef cmIMAGE_SYMBOL_EX UNALIGNED *cmPIMAGE_SYMBOL_EX;
|
||||||
|
|
||||||
|
PIMAGE_SECTION_HEADER GetSectionHeaderOffset(PIMAGE_FILE_HEADER
|
||||||
|
pImageFileHeader)
|
||||||
|
{
|
||||||
|
return (PIMAGE_SECTION_HEADER)
|
||||||
|
((DWORD_PTR)pImageFileHeader +
|
||||||
|
IMAGE_SIZEOF_FILE_HEADER +
|
||||||
|
pImageFileHeader->SizeOfOptionalHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
PIMAGE_SECTION_HEADER GetSectionHeaderOffset(cmANON_OBJECT_HEADER_BIGOBJ*
|
||||||
|
pImageFileHeader)
|
||||||
|
{
|
||||||
|
return (PIMAGE_SECTION_HEADER)
|
||||||
|
((DWORD_PTR)pImageFileHeader +
|
||||||
|
sizeof(cmANON_OBJECT_HEADER_BIGOBJ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * Utility func, strstr with size
|
||||||
|
+ */
|
||||||
|
const char* StrNStr(const char* start, const char* find, size_t &size) {
|
||||||
|
size_t len;
|
||||||
|
const char* hint;
|
||||||
|
|
||||||
|
if (!start || !find || !size) {
|
||||||
|
size = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
len = strlen(find);
|
||||||
|
|
||||||
|
while ((hint = (const char*) memchr(start, find[0], size-len+1))) {
|
||||||
|
size -= (hint - start);
|
||||||
|
if (!strncmp(hint, find, len))
|
||||||
|
return hint;
|
||||||
|
start = hint + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <
|
||||||
|
// cmANON_OBJECT_HEADER_BIGOBJ or IMAGE_FILE_HEADER
|
||||||
|
class ObjectHeaderType,
|
||||||
|
// cmPIMAGE_SYMBOL_EX or PIMAGE_SYMBOL
|
||||||
|
class SymbolTableType>
|
||||||
|
class DumpSymbols
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
* Constructor --
|
||||||
|
*
|
||||||
|
* Initialize variables from pointer to object header.
|
||||||
|
*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
DumpSymbols(ObjectHeaderType* ih,
|
||||||
|
FILE* fout) {
|
||||||
|
this->ObjectImageHeader = ih;
|
||||||
|
this->SymbolTable = (SymbolTableType*)
|
||||||
|
((DWORD_PTR)this->ObjectImageHeader
|
||||||
|
+ this->ObjectImageHeader->PointerToSymbolTable);
|
||||||
|
this->FileOut = fout;
|
||||||
|
this->SectionHeaders =
|
||||||
|
GetSectionHeaderOffset(this->ObjectImageHeader);
|
||||||
|
this->ImportFlag = true;
|
||||||
|
this->SymbolCount = this->ObjectImageHeader->NumberOfSymbols;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
* HaveExportedObjects --
|
||||||
|
*
|
||||||
|
* Returns true if export directives (declspec(dllexport)) exist.
|
||||||
|
*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool HaveExportedObjects() {
|
||||||
|
WORD i = 0;
|
||||||
|
size_t size = 0;
|
||||||
|
const char * rawdata = 0;
|
||||||
|
PIMAGE_SECTION_HEADER pDirectivesSectionHeader = 0;
|
||||||
|
PIMAGE_SECTION_HEADER pSectionHeaders = this->SectionHeaders;
|
||||||
|
for(i = 0; (i < this->ObjectImageHeader->NumberOfSections &&
|
||||||
|
!pDirectivesSectionHeader); i++)
|
||||||
|
if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8))
|
||||||
|
pDirectivesSectionHeader = &pSectionHeaders[i];
|
||||||
|
if (!pDirectivesSectionHeader) return 0;
|
||||||
|
|
||||||
|
rawdata=(const char*)
|
||||||
|
this->ObjectImageHeader+pDirectivesSectionHeader->PointerToRawData;
|
||||||
|
if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0;
|
||||||
|
|
||||||
|
size = pDirectivesSectionHeader->SizeOfRawData;
|
||||||
|
const char* posImportFlag = rawdata;
|
||||||
|
while ((posImportFlag = StrNStr(posImportFlag, " /EXPORT:", size))) {
|
||||||
|
const char* lookingForDict = posImportFlag + 9;
|
||||||
|
if (!strncmp(lookingForDict, "_G__cpp_",8) ||
|
||||||
|
!strncmp(lookingForDict, "_G__set_cpp_",12)) {
|
||||||
|
posImportFlag = lookingForDict;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* lookingForDATA = posImportFlag + 9;
|
||||||
|
while (*(++lookingForDATA) && *lookingForDATA != ' ');
|
||||||
|
lookingForDATA -= 5;
|
||||||
|
// ignore DATA exports
|
||||||
|
if (strncmp(lookingForDATA, ",DATA", 5)) break;
|
||||||
|
posImportFlag = lookingForDATA + 5;
|
||||||
|
}
|
||||||
|
if(posImportFlag) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
* DumpObjFile --
|
||||||
|
*
|
||||||
|
* Dump an object file's exported symbols.
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
void DumpObjFile() {
|
||||||
|
if(!HaveExportedObjects()) {
|
||||||
|
this->DumpExternalsObjects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
* DumpExternalsObjects --
|
||||||
|
*
|
||||||
|
* Dumps a COFF symbol table from an OBJ.
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
void DumpExternalsObjects() {
|
||||||
|
unsigned i;
|
||||||
|
PSTR stringTable;
|
||||||
|
std::string symbol;
|
||||||
|
DWORD SectChar;
|
||||||
|
/*
|
||||||
|
* The string table apparently starts right after the symbol table
|
||||||
|
*/
|
||||||
|
stringTable = (PSTR)&this->SymbolTable[this->SymbolCount];
|
||||||
|
SymbolTableType* pSymbolTable = this->SymbolTable;
|
||||||
|
for ( i=0; i < this->SymbolCount; i++ ) {
|
||||||
|
if (pSymbolTable->SectionNumber > 0 &&
|
||||||
|
( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
|
||||||
|
if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
|
||||||
|
/*
|
||||||
|
* The name of the Function entry points
|
||||||
|
*/
|
||||||
|
if (pSymbolTable->N.Name.Short != 0) {
|
||||||
|
symbol = "";
|
||||||
|
symbol.insert(0, (const char *)pSymbolTable->N.ShortName, 8);
|
||||||
|
} else {
|
||||||
|
symbol = stringTable + pSymbolTable->N.Name.Long;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear out any leading spaces
|
||||||
|
while (isspace(symbol[0])) symbol.erase(0,1);
|
||||||
|
// if it starts with _ and has an @ then it is a __cdecl
|
||||||
|
// so remove the @ stuff for the export
|
||||||
|
if(symbol[0] == '_') {
|
||||||
|
std::string::size_type posAt = symbol.find('@');
|
||||||
|
if (posAt != std::string::npos) {
|
||||||
|
symbol.erase(posAt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (symbol[0] == '_') symbol.erase(0,1);
|
||||||
|
if (this->ImportFlag) {
|
||||||
|
this->ImportFlag = false;
|
||||||
|
fprintf(this->FileOut,"EXPORTS \n");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Check whether it is "Scalar deleting destructor" and
|
||||||
|
"Vector deleting destructor"
|
||||||
|
*/
|
||||||
|
const char *scalarPrefix = "??_G";
|
||||||
|
const char *vectorPrefix = "??_E";
|
||||||
|
// original code had a check for
|
||||||
|
// symbol.find("real@") == std::string::npos)
|
||||||
|
// but if this disallows memmber functions with the name real
|
||||||
|
// if scalarPrefix and vectorPrefix are not found then print
|
||||||
|
// the symbol
|
||||||
|
if (symbol.compare(0, 4, scalarPrefix) &&
|
||||||
|
symbol.compare(0, 4, vectorPrefix) )
|
||||||
|
{
|
||||||
|
SectChar =
|
||||||
|
this->
|
||||||
|
SectionHeaders[pSymbolTable->SectionNumber-1].Characteristics;
|
||||||
|
if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) {
|
||||||
|
// Read only (i.e. constants) must be excluded
|
||||||
|
fprintf(this->FileOut, "\t%s \t DATA\n", symbol.c_str());
|
||||||
|
} else {
|
||||||
|
if ( pSymbolTable->Type ||
|
||||||
|
!(SectChar & IMAGE_SCN_MEM_READ)) {
|
||||||
|
fprintf(this->FileOut, "\t%s\n", symbol.c_str());
|
||||||
|
} else {
|
||||||
|
// printf(" strange symbol: %s \n",symbol.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED &&
|
||||||
|
!pSymbolTable->Type && 0) {
|
||||||
|
/*
|
||||||
|
* The IMPORT global variable entry points
|
||||||
|
*/
|
||||||
|
if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
|
||||||
|
symbol = stringTable + pSymbolTable->N.Name.Long;
|
||||||
|
while (isspace(symbol[0])) symbol.erase(0,1);
|
||||||
|
if (symbol[0] == '_') symbol.erase(0,1);
|
||||||
|
if (!this->ImportFlag) {
|
||||||
|
this->ImportFlag = true;
|
||||||
|
fprintf(this->FileOut,"IMPORTS \n");
|
||||||
|
}
|
||||||
|
fprintf(this->FileOut, "\t%s DATA \n", symbol.c_str()+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take into account any aux symbols
|
||||||
|
*/
|
||||||
|
i += pSymbolTable->NumberOfAuxSymbols;
|
||||||
|
pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
|
||||||
|
pSymbolTable++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool ImportFlag;
|
||||||
|
FILE* FileOut;
|
||||||
|
DWORD_PTR SymbolCount;
|
||||||
|
PIMAGE_SECTION_HEADER SectionHeaders;
|
||||||
|
ObjectHeaderType* ObjectImageHeader;
|
||||||
|
SymbolTableType* SymbolTable;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
DumpFile(const char* filename, FILE *fout)
|
||||||
|
{
|
||||||
|
HANDLE hFile;
|
||||||
|
HANDLE hFileMapping;
|
||||||
|
LPVOID lpFileBase;
|
||||||
|
PIMAGE_DOS_HEADER dosHeader;
|
||||||
|
|
||||||
|
hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(),
|
||||||
|
GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||||||
|
fprintf(stderr, "Couldn't open file '%s' with CreateFile()\n", filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
|
if (hFileMapping == 0) {
|
||||||
|
CloseHandle(hFile);
|
||||||
|
fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
|
||||||
|
if (lpFileBase == 0) {
|
||||||
|
CloseHandle(hFileMapping);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
|
||||||
|
if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
|
||||||
|
fprintf(stderr, "File is an executable. I don't dump those.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* Does it look like a i386 COFF OBJ file??? */
|
||||||
|
else if (
|
||||||
|
((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) ||
|
||||||
|
(dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64))
|
||||||
|
&& (dosHeader->e_sp == 0)
|
||||||
|
) {
|
||||||
|
/*
|
||||||
|
* The two tests above aren't what they look like. They're
|
||||||
|
* really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
|
||||||
|
* and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
|
||||||
|
*/
|
||||||
|
DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL>
|
||||||
|
symbolDumper((PIMAGE_FILE_HEADER) lpFileBase, fout);
|
||||||
|
symbolDumper.DumpObjFile();
|
||||||
|
} else {
|
||||||
|
// check for /bigobj format
|
||||||
|
cmANON_OBJECT_HEADER_BIGOBJ* h =
|
||||||
|
(cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase;
|
||||||
|
if(h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
|
||||||
|
DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX>
|
||||||
|
symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*) lpFileBase, fout);
|
||||||
|
symbolDumper.DumpObjFile();
|
||||||
|
} else {
|
||||||
|
printf("unrecognized file format in '%s'\n", filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnmapViewOfFile(lpFileBase);
|
||||||
|
CloseHandle(hFileMapping);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
return true;
|
||||||
|
}
|
@ -13,12 +13,14 @@
|
|||||||
#include "cmGlobalVisualStudioGenerator.h"
|
#include "cmGlobalVisualStudioGenerator.h"
|
||||||
|
|
||||||
#include "cmCallVisualStudioMacro.h"
|
#include "cmCallVisualStudioMacro.h"
|
||||||
|
#include "cmGeneratedFileStream.h"
|
||||||
#include "cmGeneratorTarget.h"
|
#include "cmGeneratorTarget.h"
|
||||||
#include "cmLocalVisualStudioGenerator.h"
|
#include "cmLocalVisualStudioGenerator.h"
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
#include "cmSourceFile.h"
|
#include "cmSourceFile.h"
|
||||||
#include "cmTarget.h"
|
#include "cmTarget.h"
|
||||||
#include <cmsys/Encoding.hxx>
|
#include <cmsys/Encoding.hxx>
|
||||||
|
#include "cmAlgorithms.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm)
|
cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm)
|
||||||
@ -896,3 +898,71 @@ std::string cmGlobalVisualStudioGenerator::ExpandCFGIntDir(
|
|||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
|
||||||
|
cmGeneratorTarget* gt, std::vector<cmCustomCommand>& commands,
|
||||||
|
std::string const& configName)
|
||||||
|
{
|
||||||
|
std::vector<std::string> outputs;
|
||||||
|
std::string deffile = gt->ObjectDirectory;
|
||||||
|
deffile += "/exportall.def";
|
||||||
|
outputs.push_back(deffile);
|
||||||
|
std::vector<std::string> empty;
|
||||||
|
std::vector<cmSourceFile const*> objectSources;
|
||||||
|
gt->GetObjectSources(objectSources, configName);
|
||||||
|
std::map<cmSourceFile const*, std::string> mapping;
|
||||||
|
for(std::vector<cmSourceFile const*>::const_iterator it
|
||||||
|
= objectSources.begin(); it != objectSources.end(); ++it)
|
||||||
|
{
|
||||||
|
mapping[*it];
|
||||||
|
}
|
||||||
|
gt->LocalGenerator->
|
||||||
|
ComputeObjectFilenames(mapping, gt);
|
||||||
|
std::string obj_dir = gt->ObjectDirectory;
|
||||||
|
std::string cmakeCommand = cmSystemTools::GetCMakeCommand();
|
||||||
|
cmSystemTools::ConvertToWindowsExtendedPath(cmakeCommand);
|
||||||
|
cmCustomCommandLine cmdl;
|
||||||
|
cmdl.push_back(cmakeCommand);
|
||||||
|
cmdl.push_back("-E");
|
||||||
|
cmdl.push_back("__create_def");
|
||||||
|
cmdl.push_back(deffile);
|
||||||
|
std::string obj_dir_expanded = obj_dir;
|
||||||
|
cmSystemTools::ReplaceString(obj_dir_expanded,
|
||||||
|
this->GetCMakeCFGIntDir(),
|
||||||
|
configName.c_str());
|
||||||
|
std::string objs_file = obj_dir_expanded;
|
||||||
|
cmSystemTools::MakeDirectory(objs_file.c_str());
|
||||||
|
objs_file += "/objects.txt";
|
||||||
|
cmdl.push_back(objs_file);
|
||||||
|
cmGeneratedFileStream fout(objs_file.c_str());
|
||||||
|
if(!fout)
|
||||||
|
{
|
||||||
|
cmSystemTools::Error("could not open ", objs_file.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(std::vector<cmSourceFile const*>::const_iterator it
|
||||||
|
= objectSources.begin(); it != objectSources.end(); ++it)
|
||||||
|
{
|
||||||
|
// Find the object file name corresponding to this source file.
|
||||||
|
std::map<cmSourceFile const*, std::string>::const_iterator
|
||||||
|
map_it = mapping.find(*it);
|
||||||
|
// It must exist because we populated the mapping just above.
|
||||||
|
assert(!map_it->second.empty());
|
||||||
|
std::string objFile = obj_dir + map_it->second;
|
||||||
|
// replace $(ConfigurationName) in the object names
|
||||||
|
cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(),
|
||||||
|
configName.c_str());
|
||||||
|
if(cmHasLiteralSuffix(objFile, ".obj"))
|
||||||
|
{
|
||||||
|
fout << objFile << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmCustomCommandLines commandLines;
|
||||||
|
commandLines.push_back(cmdl);
|
||||||
|
cmCustomCommand command(gt->Target->GetMakefile(),
|
||||||
|
outputs, empty, empty,
|
||||||
|
commandLines,
|
||||||
|
"Auto build dll exports",
|
||||||
|
".");
|
||||||
|
commands.push_back(command);
|
||||||
|
}
|
||||||
|
@ -103,6 +103,10 @@ public:
|
|||||||
const std::string& config) const;
|
const std::string& config) const;
|
||||||
|
|
||||||
void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
|
void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
|
||||||
|
|
||||||
|
void AddSymbolExportCommand(
|
||||||
|
cmGeneratorTarget*, std::vector<cmCustomCommand>& commands,
|
||||||
|
std::string const& configName);
|
||||||
protected:
|
protected:
|
||||||
virtual void Generate();
|
virtual void Generate();
|
||||||
|
|
||||||
|
@ -1081,6 +1081,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||||||
this->ConvertToOutputFormat(this->ModuleDefinitionFile, SHELL);
|
this->ConvertToOutputFormat(this->ModuleDefinitionFile, SHELL);
|
||||||
linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
|
linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
|
||||||
}
|
}
|
||||||
|
if (target.GetType() == cmTarget::SHARED_LIBRARY &&
|
||||||
|
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
if (target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)/exportall.def");
|
||||||
|
}
|
||||||
|
}
|
||||||
switch(target.GetType())
|
switch(target.GetType())
|
||||||
{
|
{
|
||||||
case cmTarget::UNKNOWN_LIBRARY:
|
case cmTarget::UNKNOWN_LIBRARY:
|
||||||
@ -2015,7 +2023,28 @@ void cmLocalVisualStudio7Generator
|
|||||||
// Add pre-link event.
|
// Add pre-link event.
|
||||||
tool = this->FortranProject? "VFPreLinkEventTool":"VCPreLinkEventTool";
|
tool = this->FortranProject? "VFPreLinkEventTool":"VCPreLinkEventTool";
|
||||||
event.Start(tool);
|
event.Start(tool);
|
||||||
event.Write(target.GetPreLinkCommands());
|
bool addedPrelink = false;
|
||||||
|
if (target.GetType() == cmTarget::SHARED_LIBRARY &&
|
||||||
|
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
if (target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
addedPrelink = true;
|
||||||
|
std::vector<cmCustomCommand> commands =
|
||||||
|
target.GetPreLinkCommands();
|
||||||
|
cmGlobalVisualStudioGenerator* gg
|
||||||
|
= static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator);
|
||||||
|
cmGeneratorTarget* gt =
|
||||||
|
this->GlobalGenerator->GetGeneratorTarget(&target);
|
||||||
|
gg->AddSymbolExportCommand(
|
||||||
|
gt, commands, configName);
|
||||||
|
event.Write(commands);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!addedPrelink)
|
||||||
|
{
|
||||||
|
event.Write(target.GetPreLinkCommands());
|
||||||
|
}
|
||||||
cmsys::auto_ptr<cmCustomCommand> pcc(
|
cmsys::auto_ptr<cmCustomCommand> pcc(
|
||||||
this->MaybeCreateImplibDir(target, configName, this->FortranProject));
|
this->MaybeCreateImplibDir(target, configName, this->FortranProject));
|
||||||
if(pcc.get())
|
if(pcc.get())
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "cmSourceFile.h"
|
#include "cmSourceFile.h"
|
||||||
#include "cmTarget.h"
|
#include "cmTarget.h"
|
||||||
#include "cmake.h"
|
#include "cmake.h"
|
||||||
|
#include "cmAlgorithms.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
cmMakefileLibraryTargetGenerator
|
cmMakefileLibraryTargetGenerator
|
||||||
@ -563,6 +564,58 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||||||
useResponseFileForObjects, buildObjs, depends,
|
useResponseFileForObjects, buildObjs, depends,
|
||||||
useWatcomQuote);
|
useWatcomQuote);
|
||||||
|
|
||||||
|
// maybe create .def file from list of objects
|
||||||
|
if (this->Target->GetType() == cmTarget::SHARED_LIBRARY &&
|
||||||
|
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
if(this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
std::string name_of_def_file =
|
||||||
|
this->Target->GetSupportDirectory();
|
||||||
|
name_of_def_file += std::string("/") +
|
||||||
|
this->Target->GetName();
|
||||||
|
name_of_def_file += ".def";
|
||||||
|
std::string cmd = cmSystemTools::GetCMakeCommand();
|
||||||
|
cmd = this->Convert(cmd, cmLocalGenerator::NONE,
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
cmd += " -E __create_def ";
|
||||||
|
cmd += this->Convert(name_of_def_file,
|
||||||
|
cmLocalGenerator::START_OUTPUT,
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
cmd += " ";
|
||||||
|
std::string objlist_file = name_of_def_file;
|
||||||
|
objlist_file += ".objs";
|
||||||
|
cmd += this->Convert(objlist_file,
|
||||||
|
cmLocalGenerator::START_OUTPUT,
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
real_link_commands.push_back(cmd);
|
||||||
|
// create a list of obj files for the -E __create_def to read
|
||||||
|
cmGeneratedFileStream fout(objlist_file.c_str());
|
||||||
|
for(std::vector<std::string>::const_iterator i = this->Objects.begin();
|
||||||
|
i != this->Objects.end(); ++i)
|
||||||
|
{
|
||||||
|
if(cmHasLiteralSuffix(*i, ".obj"))
|
||||||
|
{
|
||||||
|
fout << *i << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(std::vector<std::string>::const_iterator i =
|
||||||
|
this->ExternalObjects.begin();
|
||||||
|
i != this->ExternalObjects.end(); ++i)
|
||||||
|
{
|
||||||
|
fout << *i << "\n";
|
||||||
|
}
|
||||||
|
// now add the def file link flag
|
||||||
|
linkFlags += " ";
|
||||||
|
linkFlags +=
|
||||||
|
this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
|
||||||
|
linkFlags += this->Convert(name_of_def_file,
|
||||||
|
cmLocalGenerator::START_OUTPUT,
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
linkFlags += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmLocalGenerator::RuleVariables vars;
|
cmLocalGenerator::RuleVariables vars;
|
||||||
vars.TargetPDB = targetOutPathPDB.c_str();
|
vars.TargetPDB = targetOutPathPDB.c_str();
|
||||||
|
|
||||||
|
@ -486,6 +486,22 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
|||||||
linkPath,
|
linkPath,
|
||||||
&genTarget,
|
&genTarget,
|
||||||
useWatcomQuote);
|
useWatcomQuote);
|
||||||
|
if(this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS")
|
||||||
|
&& target.GetType() == cmTarget::SHARED_LIBRARY)
|
||||||
|
{
|
||||||
|
if(target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
std::string dllname = targetOutput;
|
||||||
|
std::string name_of_def_file
|
||||||
|
= target.GetSupportDirectory();
|
||||||
|
name_of_def_file += "/" + target.GetName();
|
||||||
|
name_of_def_file += ".def ";
|
||||||
|
vars["LINK_FLAGS"] += " /DEF:";
|
||||||
|
vars["LINK_FLAGS"] += this->GetLocalGenerator()
|
||||||
|
->ConvertToOutputFormat(name_of_def_file.c_str(),
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this->addPoolNinjaVariable("JOB_POOL_LINK", &target, vars);
|
this->addPoolNinjaVariable("JOB_POOL_LINK", &target, vars);
|
||||||
|
|
||||||
@ -600,6 +616,44 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maybe create .def file from list of objects
|
||||||
|
if (target.GetType() == cmTarget::SHARED_LIBRARY &&
|
||||||
|
this->GetMakefile()->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
if(target.GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
std::string cmakeCommand =
|
||||||
|
this->GetLocalGenerator()->ConvertToOutputFormat(
|
||||||
|
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
|
||||||
|
std::string dllname = targetOutput;
|
||||||
|
std::string name_of_def_file
|
||||||
|
= target.GetSupportDirectory();
|
||||||
|
name_of_def_file += "/" + target.GetName();
|
||||||
|
name_of_def_file += ".def";
|
||||||
|
std::string cmd = cmakeCommand;
|
||||||
|
cmd += " -E __create_def ";
|
||||||
|
cmd += this->GetLocalGenerator()
|
||||||
|
->ConvertToOutputFormat(name_of_def_file.c_str(),
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
cmd += " ";
|
||||||
|
cmNinjaDeps objs = this->GetObjects();
|
||||||
|
std::string obj_list_file = name_of_def_file;
|
||||||
|
obj_list_file += ".objs";
|
||||||
|
cmd += this->GetLocalGenerator()
|
||||||
|
->ConvertToOutputFormat(obj_list_file.c_str(),
|
||||||
|
cmLocalGenerator::SHELL);
|
||||||
|
preLinkCmdLines.push_back(cmd);
|
||||||
|
// create a list of obj files for the -E __create_def to read
|
||||||
|
cmGeneratedFileStream fout(obj_list_file.c_str());
|
||||||
|
for(cmNinjaDeps::iterator i=objs.begin(); i != objs.end(); ++i)
|
||||||
|
{
|
||||||
|
if(cmHasLiteralSuffix(*i, ".obj"))
|
||||||
|
{
|
||||||
|
fout << *i << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
|
// If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
|
||||||
// the link commands.
|
// the link commands.
|
||||||
if (!preLinkCmdLines.empty())
|
if (!preLinkCmdLines.empty())
|
||||||
|
@ -429,6 +429,11 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
|||||||
{
|
{
|
||||||
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
|
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
|
||||||
}
|
}
|
||||||
|
if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY)
|
||||||
|
{
|
||||||
|
this->SetPropertyDefault("WINDOWS_EXPORT_ALL_SYMBOLS", 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY)
|
if (this->GetType() != INTERFACE_LIBRARY && this->GetType() != UTILITY)
|
||||||
{
|
{
|
||||||
this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0);
|
this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0);
|
||||||
|
@ -2466,6 +2466,15 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
|
|||||||
"%(IgnoreSpecificDefaultLibraries)");
|
"%(IgnoreSpecificDefaultLibraries)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->Target->GetType() == cmTarget::SHARED_LIBRARY &&
|
||||||
|
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
if (this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
linkOptions.AddFlag("ModuleDefinitionFile", "$(IntDir)exportall.def");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this->LinkOptions[config] = pOptions.release();
|
this->LinkOptions[config] = pOptions.release();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2613,8 +2622,25 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
|
|||||||
void
|
void
|
||||||
cmVisualStudio10TargetGenerator::WriteEvents(std::string const& configName)
|
cmVisualStudio10TargetGenerator::WriteEvents(std::string const& configName)
|
||||||
{
|
{
|
||||||
this->WriteEvent("PreLinkEvent",
|
bool addedPrelink = false;
|
||||||
this->Target->GetPreLinkCommands(), configName);
|
if (this->Target->GetType() == cmTarget::SHARED_LIBRARY &&
|
||||||
|
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
if (this->Target->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"))
|
||||||
|
{
|
||||||
|
addedPrelink = true;
|
||||||
|
std::vector<cmCustomCommand> commands =
|
||||||
|
this->Target->GetPreLinkCommands();
|
||||||
|
this->GlobalGenerator->AddSymbolExportCommand(
|
||||||
|
this->GeneratorTarget, commands, configName);
|
||||||
|
this->WriteEvent("PreLinkEvent", commands, configName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!addedPrelink)
|
||||||
|
{
|
||||||
|
this->WriteEvent("PreLinkEvent",
|
||||||
|
this->Target->GetPreLinkCommands(), configName);
|
||||||
|
}
|
||||||
this->WriteEvent("PreBuildEvent",
|
this->WriteEvent("PreBuildEvent",
|
||||||
this->Target->GetPreBuildCommands(), configName);
|
this->Target->GetPreBuildCommands(), configName);
|
||||||
this->WriteEvent("PostBuildEvent",
|
this->WriteEvent("PostBuildEvent",
|
||||||
|
@ -34,6 +34,10 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include <stdlib.h> // required for atoi
|
#include <stdlib.h> // required for atoi
|
||||||
|
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
|
||||||
|
// defined in binexplib.cxx
|
||||||
|
bool DumpFile(const char* filename, FILE *fout);
|
||||||
|
#endif
|
||||||
|
|
||||||
void CMakeCommandUsage(const char* program)
|
void CMakeCommandUsage(const char* program)
|
||||||
{
|
{
|
||||||
@ -211,6 +215,41 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
|
||||||
|
else if(args[1] == "__create_def")
|
||||||
|
{
|
||||||
|
if(args.size() < 4)
|
||||||
|
{
|
||||||
|
std::cerr <<
|
||||||
|
"__create_def Usage: -E __create_def outfile.def objlistfile\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+");
|
||||||
|
if(!fout)
|
||||||
|
{
|
||||||
|
std::cerr << "could not open output .def file: " << args[2].c_str()
|
||||||
|
<< "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cmsys::ifstream fin(args[3].c_str(),
|
||||||
|
std::ios::in | std::ios::binary);
|
||||||
|
if(!fin)
|
||||||
|
{
|
||||||
|
std::cerr << "could not open object list file: " << args[3].c_str()
|
||||||
|
<< "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::string objfile;
|
||||||
|
while(cmSystemTools::GetLineFromStream(fin, objfile))
|
||||||
|
{
|
||||||
|
if (!DumpFile(objfile.c_str(), fout))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// run include what you use command and then run the compile
|
// run include what you use command and then run the compile
|
||||||
// command. This is an internal undocumented option and should
|
// command. This is an internal undocumented option and should
|
||||||
// only be used by CMake itself when running iwyu.
|
// only be used by CMake itself when running iwyu.
|
||||||
|
7
Tests/RunCMake/AutoExportDll/AutoExport.cmake
Normal file
7
Tests/RunCMake/AutoExportDll/AutoExport.cmake
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
project(autoexport)
|
||||||
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${autoexport_BINARY_DIR}/bin)
|
||||||
|
add_subdirectory(sub)
|
||||||
|
add_library(autoexport SHARED hello.cxx world.cxx foo.c)
|
||||||
|
add_executable(say say.cxx)
|
||||||
|
target_link_libraries(say autoexport autoexport2)
|
1
Tests/RunCMake/AutoExportDll/AutoExportBuild-stderr.txt
Normal file
1
Tests/RunCMake/AutoExportDll/AutoExportBuild-stderr.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
^.*$
|
3
Tests/RunCMake/AutoExportDll/CMakeLists.txt
Normal file
3
Tests/RunCMake/AutoExportDll/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
project(${RunCMake_TEST} NONE)
|
||||||
|
include(${RunCMake_TEST}.cmake)
|
26
Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake
Normal file
26
Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
include(RunCMake)
|
||||||
|
set(RunCMake_TEST_NO_CLEAN TRUE)
|
||||||
|
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/AutoExport-build")
|
||||||
|
# start by cleaning up because we don't clean up along the way
|
||||||
|
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
|
||||||
|
# configure the AutoExport test
|
||||||
|
run_cmake(AutoExport)
|
||||||
|
unset(RunCMake_TEST_OPTIONS)
|
||||||
|
# don't run this test on VS 6 as it is not supported
|
||||||
|
if("${RunCMake_GENERATOR}" MATCHES "Visual Studio 6|Watcom WMake|Borland Makefiles")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
# we build debug so the say.exe will be found in Debug/say.exe for
|
||||||
|
# Visual Studio generators
|
||||||
|
if("${RunCMake_GENERATOR}" MATCHES "Visual Studio|Xcode")
|
||||||
|
set(INTDIR "Debug/")
|
||||||
|
endif()
|
||||||
|
# build AutoExport
|
||||||
|
run_cmake_command(AutoExportBuild ${CMAKE_COMMAND} --build
|
||||||
|
${RunCMake_TEST_BINARY_DIR} --config Debug --clean-first)
|
||||||
|
# run the executable that uses symbols from the dll
|
||||||
|
if(WIN32)
|
||||||
|
set(EXE_EXT ".exe")
|
||||||
|
endif()
|
||||||
|
run_cmake_command(AutoExportRun
|
||||||
|
${RunCMake_BINARY_DIR}/AutoExport-build/bin/${INTDIR}say${EXE_EXT})
|
15
Tests/RunCMake/AutoExportDll/foo.c
Normal file
15
Tests/RunCMake/AutoExportDll/foo.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifdef _MSC_VER
|
||||||
|
#include "windows.h"
|
||||||
|
#else
|
||||||
|
#define WINAPI
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int WINAPI foo()
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bar()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
13
Tests/RunCMake/AutoExportDll/hello.cxx
Normal file
13
Tests/RunCMake/AutoExportDll/hello.cxx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "hello.h"
|
||||||
|
int Hello::Data = 0;
|
||||||
|
void Hello::real()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void hello()
|
||||||
|
{
|
||||||
|
printf("hello");
|
||||||
|
}
|
||||||
|
void Hello::operator delete[](void*) {};
|
||||||
|
void Hello::operator delete(void*) {};
|
18
Tests/RunCMake/AutoExportDll/hello.h
Normal file
18
Tests/RunCMake/AutoExportDll/hello.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _MSC_VER
|
||||||
|
#define winexport
|
||||||
|
#else
|
||||||
|
#ifdef autoexport_EXPORTS
|
||||||
|
#define winexport
|
||||||
|
#else
|
||||||
|
#define winexport __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Hello
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static winexport int Data;
|
||||||
|
void real();
|
||||||
|
static void operator delete[](void*);
|
||||||
|
static void operator delete(void*);
|
||||||
|
};
|
37
Tests/RunCMake/AutoExportDll/say.cxx
Normal file
37
Tests/RunCMake/AutoExportDll/say.cxx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "hello.h"
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include "windows.h"
|
||||||
|
#else
|
||||||
|
#define WINAPI
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
// test __cdecl stuff
|
||||||
|
int WINAPI foo();
|
||||||
|
// test regular C
|
||||||
|
int bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
// test c++ functions
|
||||||
|
// forward declare hello and world
|
||||||
|
void hello();
|
||||||
|
void world();
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// test static data (needs declspec to work)
|
||||||
|
Hello::Data = 120;
|
||||||
|
Hello h;
|
||||||
|
h.real();
|
||||||
|
hello();
|
||||||
|
printf(" ");
|
||||||
|
world();
|
||||||
|
printf("\n");
|
||||||
|
foo();
|
||||||
|
printf("\n");
|
||||||
|
bar();
|
||||||
|
printf("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
5
Tests/RunCMake/AutoExportDll/sub/CMakeLists.txt
Normal file
5
Tests/RunCMake/AutoExportDll/sub/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
add_library(autoexport2 SHARED sub.cxx)
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
# Try msvc "big" object format.
|
||||||
|
target_compile_options(autoexport2 PRIVATE /bigobj)
|
||||||
|
endif()
|
4
Tests/RunCMake/AutoExportDll/sub/sub.cxx
Normal file
4
Tests/RunCMake/AutoExportDll/sub/sub.cxx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
int sub()
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
}
|
6
Tests/RunCMake/AutoExportDll/world.cxx
Normal file
6
Tests/RunCMake/AutoExportDll/world.cxx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "stdio.h"
|
||||||
|
|
||||||
|
void world()
|
||||||
|
{
|
||||||
|
printf("world");
|
||||||
|
}
|
@ -266,3 +266,6 @@ if("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_RunCMake_test_group(CPack "DEB;RPM")
|
add_RunCMake_test_group(CPack "DEB;RPM")
|
||||||
|
# add a test to make sure symbols are exported from a shared library
|
||||||
|
# for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used
|
||||||
|
add_RunCMake_test(AutoExportDll)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user