Merge topic 'vs-pdb-output'
2ccca05
Run PDBDirectoryAndName test on MSVC and Intelefc83b3
Document that PDB_(NAME|OUTPUT_DIRECTORY) are ignored for VS 6b294457
Verify that PDB_(NAME|OUTPUT_DIRECTORY) are honored in test3f60dbf
Add PDB_OUTPUT_DIRECTORY and PDB_NAME target properties (#10830)
This commit is contained in:
commit
7dce31f3d0
|
@ -1210,6 +1210,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
|
|||
false,
|
||||
"Variables that Control the Build");
|
||||
|
||||
cm->DefineProperty
|
||||
("CMAKE_PDB_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
|
||||
"Where to put all the MS debug symbol files.",
|
||||
"This variable is used to initialize the "
|
||||
"PDB_OUTPUT_DIRECTORY property on all the targets. "
|
||||
"See that target property for additional information.",
|
||||
false,
|
||||
"Variables that Control the Build");
|
||||
|
||||
cm->DefineProperty
|
||||
("CMAKE_AUTOMOC", cmProperty::VARIABLE,
|
||||
"Whether to handle moc automatically for Qt targets.",
|
||||
|
|
|
@ -842,7 +842,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
|
|||
// non-debug configurations because VS still creates .idb files.
|
||||
fout << "\t\t\t\tProgramDataBaseFileName=\""
|
||||
<< this->ConvertToXMLOutputPathSingle(
|
||||
target.GetDirectory(configName).c_str())
|
||||
target.GetPDBDirectory(configName).c_str())
|
||||
<< "/"
|
||||
<< target.GetPDBName(configName) << "\"\n";
|
||||
}
|
||||
|
@ -1122,7 +1122,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
|
||||
this->OutputLibraryDirectories(fout, cli.GetDirectories());
|
||||
fout << "\"\n";
|
||||
temp = target.GetDirectory(configName);
|
||||
temp = target.GetPDBDirectory(configName);
|
||||
temp += "/";
|
||||
temp += targetNamePDB;
|
||||
fout << "\t\t\t\tProgramDatabaseFile=\"" <<
|
||||
|
@ -1210,7 +1210,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
|
|||
this->OutputLibraryDirectories(fout, cli.GetDirectories());
|
||||
fout << "\"\n";
|
||||
std::string path = this->ConvertToXMLOutputPathSingle(
|
||||
target.GetDirectory(configName).c_str());
|
||||
target.GetPDBDirectory(configName).c_str());
|
||||
fout << "\t\t\t\tProgramDatabaseFile=\""
|
||||
<< path << "/" << targetNamePDB
|
||||
<< "\"\n";
|
||||
|
|
|
@ -131,9 +131,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||
outpathImp += "/";
|
||||
}
|
||||
}
|
||||
|
||||
std::string pdbOutputPath = this->Target->GetPDBDirectory();
|
||||
cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
|
||||
pdbOutputPath += "/";
|
||||
|
||||
std::string targetFullPath = outpath + targetName;
|
||||
std::string targetFullPathReal = outpath + targetNameReal;
|
||||
std::string targetFullPathPDB = outpath + targetNamePDB;
|
||||
std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
|
||||
std::string targetFullPathImport = outpathImp + targetNameImport;
|
||||
std::string targetOutPathPDB =
|
||||
this->Convert(targetFullPathPDB.c_str(),
|
||||
|
|
|
@ -328,8 +328,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||
}
|
||||
}
|
||||
|
||||
std::string pdbOutputPath = this->Target->GetPDBDirectory();
|
||||
cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
|
||||
pdbOutputPath += "/";
|
||||
|
||||
std::string targetFullPath = outpath + targetName;
|
||||
std::string targetFullPathPDB = outpath + targetNamePDB;
|
||||
std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
|
||||
std::string targetFullPathSO = outpath + targetNameSO;
|
||||
std::string targetFullPathReal = outpath + targetNameReal;
|
||||
std::string targetFullPathImport = outpathImp + targetNameImport;
|
||||
|
|
|
@ -647,7 +647,7 @@ cmMakefileTargetGenerator
|
|||
this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
this->Target->GetType() == cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
targetFullPathPDB = this->Target->GetDirectory(this->ConfigName);
|
||||
targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName);
|
||||
targetFullPathPDB += "/";
|
||||
targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
|
||||
}
|
||||
|
|
|
@ -329,10 +329,10 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
|
|||
this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
this->Target->GetType() == cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
pdbPath = this->Target->GetDirectory(this->GetConfigName());
|
||||
pdbPath = this->Target->GetPDBDirectory(this->GetConfigName());
|
||||
pdbPath += "/";
|
||||
pdbPath += this->Target->GetPDBName(this->GetConfigName());
|
||||
}
|
||||
}
|
||||
|
||||
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
|
||||
ConvertToNinjaPath(pdbPath.c_str()).c_str(),
|
||||
|
|
|
@ -56,6 +56,7 @@ struct cmTarget::OutputInfo
|
|||
{
|
||||
std::string OutDir;
|
||||
std::string ImpDir;
|
||||
std::string PdbDir;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -739,6 +740,22 @@ void cmTarget::DefineProperties(cmake *cm)
|
|||
"This is a configuration-specific version of OUTPUT_NAME. "
|
||||
"Use OUTPUT_NAME_<CONFIG> instead.");
|
||||
|
||||
cm->DefineProperty
|
||||
("PDB_NAME", cmProperty::TARGET,
|
||||
"Output name for MS debug symbols .pdb file.",
|
||||
"Set the base name for debug symbols file created for an "
|
||||
"executable or library target. "
|
||||
"If not set, the logical target name is used by default. "
|
||||
"\n"
|
||||
"This property is not implemented by the Visual Studio 6 generator.");
|
||||
|
||||
cm->DefineProperty
|
||||
("PDB_NAME_<CONFIG>", cmProperty::TARGET,
|
||||
"Per-configuration name for MS debug symbols .pdb file. ",
|
||||
"This is the configuration-specific version of PDB_NAME. "
|
||||
"\n"
|
||||
"This property is not implemented by the Visual Studio 6 generator.");
|
||||
|
||||
cm->DefineProperty
|
||||
("PRE_INSTALL_SCRIPT", cmProperty::TARGET,
|
||||
"Deprecated install support.",
|
||||
|
@ -1188,6 +1205,27 @@ void cmTarget::DefineProperties(cmake *cm)
|
|||
"Per-configuration output directory for RUNTIME target files.",
|
||||
CM_TARGET_OUTDIR_CONFIG_DOC(RUNTIME));
|
||||
|
||||
cm->DefineProperty
|
||||
("PDB_OUTPUT_DIRECTORY", cmProperty::TARGET,
|
||||
"Output directory for MS debug symbols .pdb files.",
|
||||
"This property specifies the directory into which the MS debug symbols "
|
||||
"will be placed. "
|
||||
"This property is initialized by the value of the variable "
|
||||
"CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created."
|
||||
"\n"
|
||||
"This property is not implemented by the Visual Studio 6 generator.");
|
||||
cm->DefineProperty
|
||||
("PDB_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET,
|
||||
"Per-configuration output directory for MS debug symbols .pdb files.",
|
||||
"This is a per-configuration version of PDB_OUTPUT_DIRECTORY, "
|
||||
"but multi-configuration generators (VS, Xcode) do NOT append "
|
||||
"a per-configuration subdirectory to the specified directory. "
|
||||
"This property is initialized by the value of the variable "
|
||||
"CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG> "
|
||||
"if it is set when a target is created."
|
||||
"\n"
|
||||
"This property is not implemented by the Visual Studio 6 generator.");
|
||||
|
||||
cm->DefineProperty
|
||||
("ARCHIVE_OUTPUT_NAME", cmProperty::TARGET,
|
||||
"Output name for ARCHIVE target files.",
|
||||
|
@ -1262,6 +1300,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
|||
this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0);
|
||||
this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
|
||||
this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
|
||||
this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0);
|
||||
this->SetPropertyDefault("Fortran_FORMAT", 0);
|
||||
this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
|
||||
this->SetPropertyDefault("GNUtoMS", 0);
|
||||
|
@ -1281,6 +1320,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
|||
"ARCHIVE_OUTPUT_DIRECTORY_",
|
||||
"LIBRARY_OUTPUT_DIRECTORY_",
|
||||
"RUNTIME_OUTPUT_DIRECTORY_",
|
||||
"PDB_OUTPUT_DIRECTORY_",
|
||||
0};
|
||||
for(std::vector<std::string>::iterator ci = configNames.begin();
|
||||
ci != configNames.end(); ++ci)
|
||||
|
@ -2538,6 +2578,7 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config)
|
|||
OutputInfo info;
|
||||
this->ComputeOutputDir(config, false, info.OutDir);
|
||||
this->ComputeOutputDir(config, true, info.ImpDir);
|
||||
this->ComputePDBOutputDir(config, info.PdbDir);
|
||||
OutputInfoMapType::value_type entry(config_upper, info);
|
||||
i = this->Internal->OutputInfoMap.insert(entry).first;
|
||||
}
|
||||
|
@ -2562,6 +2603,17 @@ std::string cmTarget::GetDirectory(const char* config, bool implib)
|
|||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmTarget::GetPDBDirectory(const char* config)
|
||||
{
|
||||
if(OutputInfo const* info = this->GetOutputInfo(config))
|
||||
{
|
||||
// Return the directory in which the target will be built.
|
||||
return info->PdbDir;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char* cmTarget::GetLocation(const char* config)
|
||||
{
|
||||
|
@ -3008,6 +3060,28 @@ std::string cmTarget::GetPDBName(const char* config)
|
|||
std::string base;
|
||||
std::string suffix;
|
||||
this->GetFullNameInternal(config, false, prefix, base, suffix);
|
||||
|
||||
std::vector<std::string> props;
|
||||
std::string configUpper =
|
||||
cmSystemTools::UpperCase(config? config : "");
|
||||
if(!configUpper.empty())
|
||||
{
|
||||
// PDB_NAME_<CONFIG>
|
||||
props.push_back("PDB_NAME_" + configUpper);
|
||||
}
|
||||
|
||||
// PDB_NAME
|
||||
props.push_back("PDB_NAME");
|
||||
|
||||
for(std::vector<std::string>::const_iterator i = props.begin();
|
||||
i != props.end(); ++i)
|
||||
{
|
||||
if(const char* outName = this->GetProperty(i->c_str()))
|
||||
{
|
||||
base = outName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return prefix+base+".pdb";
|
||||
}
|
||||
|
||||
|
@ -3392,7 +3466,7 @@ void cmTarget::GetLibraryNames(std::string& name,
|
|||
}
|
||||
|
||||
// The program database file name.
|
||||
pdbName = prefix+base+".pdb";
|
||||
pdbName = this->GetPDBName(config);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -3471,7 +3545,7 @@ void cmTarget::GetExecutableNames(std::string& name,
|
|||
impName = this->GetFullNameInternal(config, true);
|
||||
|
||||
// The program database file name.
|
||||
pdbName = prefix+base+".pdb";
|
||||
pdbName = this->GetPDBName(config);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -3550,7 +3624,7 @@ void cmTarget::GenerateTargetManifest(const char* config)
|
|||
}
|
||||
if(!pdbName.empty())
|
||||
{
|
||||
f = dir;
|
||||
f = this->GetPDBDirectory(config);
|
||||
f += "/";
|
||||
f += pdbName;
|
||||
gg->AddToManifest(config? config:"", f);
|
||||
|
@ -3859,6 +3933,65 @@ bool cmTarget::ComputeOutputDir(const char* config,
|
|||
return usesDefaultOutputDir;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::ComputePDBOutputDir(const char* config, std::string& out)
|
||||
{
|
||||
// Look for a target property defining the target output directory
|
||||
// based on the target type.
|
||||
std::string targetTypeName = "PDB";
|
||||
const char* propertyName = 0;
|
||||
std::string propertyNameStr = targetTypeName;
|
||||
if(!propertyNameStr.empty())
|
||||
{
|
||||
propertyNameStr += "_OUTPUT_DIRECTORY";
|
||||
propertyName = propertyNameStr.c_str();
|
||||
}
|
||||
|
||||
// Check for a per-configuration output directory target property.
|
||||
std::string configUpper = cmSystemTools::UpperCase(config? config : "");
|
||||
const char* configProp = 0;
|
||||
std::string configPropStr = targetTypeName;
|
||||
if(!configPropStr.empty())
|
||||
{
|
||||
configPropStr += "_OUTPUT_DIRECTORY_";
|
||||
configPropStr += configUpper;
|
||||
configProp = configPropStr.c_str();
|
||||
}
|
||||
|
||||
// Select an output directory.
|
||||
if(const char* config_outdir = this->GetProperty(configProp))
|
||||
{
|
||||
// Use the user-specified per-configuration output directory.
|
||||
out = config_outdir;
|
||||
|
||||
// Skip per-configuration subdirectory.
|
||||
config = 0;
|
||||
}
|
||||
else if(const char* outdir = this->GetProperty(propertyName))
|
||||
{
|
||||
// Use the user-specified output directory.
|
||||
out = outdir;
|
||||
}
|
||||
if(out.empty())
|
||||
{
|
||||
// Default to the current output directory.
|
||||
out = ".";
|
||||
}
|
||||
|
||||
// Convert the output path to a full path in case it is
|
||||
// specified as a relative path. Treat a relative path as
|
||||
// relative to the current output directory for this makefile.
|
||||
out = (cmSystemTools::CollapseFullPath
|
||||
(out.c_str(), this->Makefile->GetStartOutputDirectory()));
|
||||
|
||||
// The generator may add the configuration's subdirectory.
|
||||
if(config && *config)
|
||||
{
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
|
||||
AppendDirectoryForConfig("/", config, "", out);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmTarget::UsesDefaultOutputDir(const char* config, bool implib)
|
||||
{
|
||||
|
|
|
@ -291,6 +291,12 @@ public:
|
|||
output directory is given. */
|
||||
std::string GetDirectory(const char* config = 0, bool implib = false);
|
||||
|
||||
/** Get the directory in which this targets .pdb files will be placed.
|
||||
If the configuration name is given then the generator will add its
|
||||
subdirectory for that configuration. Otherwise just the canonical
|
||||
pdb output directory is given. */
|
||||
std::string GetPDBDirectory(const char* config = 0);
|
||||
|
||||
/** Get the location of the target in the build tree for the given
|
||||
configuration. This location is suitable for use as the LOCATION
|
||||
target property. */
|
||||
|
@ -571,6 +577,7 @@ private:
|
|||
struct OutputInfo;
|
||||
OutputInfo const* GetOutputInfo(const char* config);
|
||||
bool ComputeOutputDir(const char* config, bool implib, std::string& out);
|
||||
void ComputePDBOutputDir(const char* config, std::string& out);
|
||||
|
||||
// Cache import information from properties for each configuration.
|
||||
struct ImportInfo;
|
||||
|
|
|
@ -1279,9 +1279,8 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
|
|||
this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
|
||||
if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
|
||||
{
|
||||
// TODO: PDB for object library?
|
||||
this->WriteString("<ProgramDataBaseFileName>", 3);
|
||||
*this->BuildFileStream << this->Target->GetDirectory(configName.c_str())
|
||||
*this->BuildFileStream << this->Target->GetPDBDirectory(configName.c_str())
|
||||
<< "/"
|
||||
<< this->Target->GetPDBName(configName.c_str())
|
||||
<< "</ProgramDataBaseFileName>\n";
|
||||
|
@ -1506,9 +1505,8 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
|
|||
config.c_str());
|
||||
}
|
||||
|
||||
std::string dir = this->Target->GetDirectory(config.c_str());
|
||||
dir += "/";
|
||||
std::string pdb = dir;
|
||||
std::string pdb = this->Target->GetPDBDirectory(config.c_str());
|
||||
pdb += "/";
|
||||
pdb += targetNamePDB;
|
||||
std::string imLib = this->Target->GetDirectory(config.c_str(), true);
|
||||
imLib += "/";
|
||||
|
|
|
@ -1254,6 +1254,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
|
|||
|
||||
if(CMAKE_TEST_MSVC)
|
||||
ADD_TEST_MACRO(ForceInclude foo)
|
||||
ADD_TEST_MACRO(PDBDirectoryAndName myexe)
|
||||
ADD_TEST_MACRO(PrecompiledHeader foo)
|
||||
endif()
|
||||
if(CMAKE_TEST_MSVC OR
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
project(PDBDirectoryAndName C)
|
||||
|
||||
# Make sure the proper compiler is in use.
|
||||
if(NOT MSVC AND NOT "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$")
|
||||
message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC or Intel")
|
||||
endif()
|
||||
|
||||
set(my_targets "")
|
||||
|
||||
add_library(mylibA SHARED mylibA.c)
|
||||
set_target_properties(mylibA PROPERTIES
|
||||
PDB_NAME "mylibA_Special"
|
||||
PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB"
|
||||
)
|
||||
list(APPEND my_targets mylibA)
|
||||
|
||||
add_library(mylibB STATIC mylibB.c)
|
||||
set_target_properties(mylibB PROPERTIES
|
||||
PDB_NAME "mylibB_Special"
|
||||
PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB"
|
||||
)
|
||||
list(APPEND my_targets mylibB)
|
||||
|
||||
add_library(mylibC SHARED mylibC.c)
|
||||
set_target_properties(mylibC PROPERTIES
|
||||
PDB_NAME "mylibC_Special"
|
||||
)
|
||||
list(APPEND my_targets mylibC)
|
||||
|
||||
add_library(mylibD STATIC mylibD.c)
|
||||
set_target_properties(mylibD PROPERTIES
|
||||
PDB_NAME "mylibD_Special"
|
||||
)
|
||||
list(APPEND my_targets mylibD)
|
||||
|
||||
add_executable(myexe myexe.c)
|
||||
set_target_properties(myexe PROPERTIES
|
||||
PDB_NAME "myexe_Special"
|
||||
PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/myexe_PDB"
|
||||
)
|
||||
list(APPEND my_targets myexe)
|
||||
|
||||
target_link_libraries(myexe mylibA mylibB mylibC mylibD)
|
||||
|
||||
add_executable(myexe2 myexe2.c)
|
||||
set_target_properties(myexe2 PROPERTIES
|
||||
PDB_NAME "myexe2_Special"
|
||||
)
|
||||
list(APPEND my_targets myexe2)
|
||||
|
||||
target_link_libraries(myexe2 mylibA mylibD)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Check that PDB files actually appear where expected.
|
||||
|
||||
# The PDB_NAME and PDB_OUTPUT_DIRECTORY options do not work in VS 6.
|
||||
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
|
||||
return()
|
||||
endif()
|
||||
# PDB output not fully implemented for Intel
|
||||
if("${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(pdbs "")
|
||||
foreach(t ${my_targets})
|
||||
get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME)
|
||||
get_property(pdb_dir TARGET ${t} PROPERTY PDB_OUTPUT_DIRECTORY)
|
||||
if(NOT pdb_dir)
|
||||
set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
list(APPEND pdbs ${pdb_dir}/${CMAKE_CFG_INTDIR}/${pdb_name}.pdb)
|
||||
endforeach()
|
||||
add_custom_target(check_pdbs ALL VERBATIM
|
||||
COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIGURATION> "-Dpdbs=${pdbs}"
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check_pdbs.cmake
|
||||
)
|
||||
add_dependencies(check_pdbs ${my_targets})
|
|
@ -0,0 +1,10 @@
|
|||
if(NOT "${config}" MATCHES "[Dd][Ee][Bb]")
|
||||
return()
|
||||
endif()
|
||||
foreach(pdb ${pdbs})
|
||||
if(EXISTS "${pdb}")
|
||||
message(STATUS "PDB Exists: ${pdb}")
|
||||
else()
|
||||
message(SEND_ERROR "PDB MISSING: ${pdb}")
|
||||
endif()
|
||||
endforeach()
|
|
@ -0,0 +1,5 @@
|
|||
extern int mylibA();
|
||||
extern int mylibB();
|
||||
extern int mylibC();
|
||||
extern int mylibD();
|
||||
int main() { return mylibA() + mylibB() + mylibC() + mylibD(); }
|
|
@ -0,0 +1,3 @@
|
|||
extern int mylibA();
|
||||
extern int mylibD();
|
||||
int main() { return mylibA() + mylibD(); }
|
|
@ -0,0 +1 @@
|
|||
__declspec(dllexport) int mylibA() { return 1; }
|
|
@ -0,0 +1 @@
|
|||
int mylibB() { return -1; }
|
|
@ -0,0 +1 @@
|
|||
__declspec(dllexport) int mylibC() { return 1; }
|
|
@ -0,0 +1 @@
|
|||
int mylibD() { return -1; }
|
Loading…
Reference in New Issue