summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuchen Deng <loaden@gmail.com>2012-09-25 01:30:42 (GMT)
committerBrad King <brad.king@kitware.com>2012-09-25 19:23:35 (GMT)
commit3f60dbf1484575f4c28a15c89e1af071648c8f2d (patch)
tree2ff89c5574c9515a4f1a61d210dfbcc7b020af56
parentd550801a3df96b991caf918435025aa233130bb4 (diff)
downloadCMake-3f60dbf1484575f4c28a15c89e1af071648c8f2d.zip
CMake-3f60dbf1484575f4c28a15c89e1af071648c8f2d.tar.gz
CMake-3f60dbf1484575f4c28a15c89e1af071648c8f2d.tar.bz2
Add PDB_OUTPUT_DIRECTORY and PDB_NAME target properties (#10830)
This enables changing the name and output folder of the debug symbol files produced by MS compilers. Inspired-by: Thomas Bernard <thomas.bernard@ipetronik.com>
-rw-r--r--Source/cmDocumentVariables.cxx9
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx6
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx7
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx6
-rw-r--r--Source/cmMakefileTargetGenerator.cxx2
-rw-r--r--Source/cmNinjaTargetGenerator.cxx4
-rw-r--r--Source/cmTarget.cxx131
-rw-r--r--Source/cmTarget.h7
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx8
-rw-r--r--Tests/CMakeLists.txt1
-rw-r--r--Tests/PDBDirectoryAndName/CMakeLists.txt43
-rw-r--r--Tests/PDBDirectoryAndName/myexe.c5
-rw-r--r--Tests/PDBDirectoryAndName/myexe2.c3
-rw-r--r--Tests/PDBDirectoryAndName/mylibA.c1
-rw-r--r--Tests/PDBDirectoryAndName/mylibB.c1
-rw-r--r--Tests/PDBDirectoryAndName/mylibC.c1
-rw-r--r--Tests/PDBDirectoryAndName/mylibD.c1
17 files changed, 220 insertions, 16 deletions
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 5e7e081..db3d055 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -1211,6 +1211,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"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.",
"This variable is used to initialize the "
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 2dfca02..ed17786 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -847,7 +847,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";
}
@@ -1125,7 +1125,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=\"" <<
@@ -1211,7 +1211,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";
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index ab5150a..d06dfc0 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -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(),
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 577e5fd..95b71f2 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -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;
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 95738c4..ab25907 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -652,7 +652,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);
}
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 385b4a0..2456bfc 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -335,10 +335,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(),
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 9a3812c..b932afc 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -57,6 +57,7 @@ struct cmTarget::OutputInfo
{
std::string OutDir;
std::string ImpDir;
+ std::string PdbDir;
};
//----------------------------------------------------------------------------
@@ -741,6 +742,18 @@ void cmTarget::DefineProperties(cmake *cm)
"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.");
+
+ 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.");
+
+ cm->DefineProperty
("PRE_INSTALL_SCRIPT", cmProperty::TARGET,
"Deprecated install support.",
"The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
@@ -1190,6 +1203,23 @@ void cmTarget::DefineProperties(cmake *cm)
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.");
+ 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.");
+
+ cm->DefineProperty
("ARCHIVE_OUTPUT_NAME", cmProperty::TARGET,
"Output name for ARCHIVE target files.",
"This property specifies the base name for archive target files. "
@@ -1263,6 +1293,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);
@@ -1282,6 +1313,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)
@@ -2539,6 +2571,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;
}
@@ -2564,6 +2597,17 @@ std::string cmTarget::GetDirectory(const char* config, bool implib)
}
//----------------------------------------------------------------------------
+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)
{
if (this->IsImported())
@@ -3028,6 +3072,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";
}
@@ -3412,7 +3478,7 @@ void cmTarget::GetLibraryNames(std::string& name,
}
// The program database file name.
- pdbName = prefix+base+".pdb";
+ pdbName = this->GetPDBName(config);
}
//----------------------------------------------------------------------------
@@ -3491,7 +3557,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);
}
//----------------------------------------------------------------------------
@@ -3570,7 +3636,7 @@ void cmTarget::GenerateTargetManifest(const char* config)
}
if(!pdbName.empty())
{
- f = dir;
+ f = this->GetPDBDirectory(config);
f += "/";
f += pdbName;
gg->AddToManifest(config? config:"", f);
@@ -3880,6 +3946,65 @@ bool cmTarget::ComputeOutputDir(const char* config,
}
//----------------------------------------------------------------------------
+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)
{
std::string dir;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 98eaeec..e1a9de7 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -301,6 +301,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. */
@@ -593,6 +599,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;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 3d2828d..6ce3fe2 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1284,9 +1284,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";
@@ -1511,9 +1510,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 += "/";
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index e03b926..4d071cb 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1259,6 +1259,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
if(CMAKE_TEST_MSVC OR
"${CMAKE_TEST_GENERATOR}" MATCHES "(MSYS|MinGW) Makefiles")
ADD_TEST_MACRO(ModuleDefinition example_exe)
+ ADD_TEST_MACRO(PDBDirectoryAndName myexe)
endif()
ADD_TEST_MACRO(CheckCompilerRelatedVariables CheckCompilerRelatedVariables)
diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
new file mode 100644
index 0000000..ef1cae1
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -0,0 +1,43 @@
+cmake_minimum_required(VERSION 2.8)
+project(PDBDirectoryAndName C)
+
+if(NOT MSVC)
+ MESSAGE(FATAL_ERROR "The PDB file test works only with MSVC")
+endif()
+
+add_library(mylibA SHARED mylibA.c)
+set_target_properties(mylibA PROPERTIES
+ PDB_NAME "mylibA_Special"
+ PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB"
+)
+
+add_library(mylibB STATIC mylibB.c)
+set_target_properties(mylibB PROPERTIES
+ PDB_NAME "mylibB_Special"
+ PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB"
+)
+
+add_library(mylibC SHARED mylibC.c)
+set_target_properties(mylibC PROPERTIES
+ PDB_NAME "mylibC_Special"
+)
+
+add_library(mylibD STATIC mylibD.c)
+set_target_properties(mylibD PROPERTIES
+ PDB_NAME "mylibD_Special"
+)
+
+add_executable(myexe myexe.c)
+set_target_properties(myexe PROPERTIES
+ PDB_NAME "myexe_Special"
+ PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/myexe_PDB"
+)
+
+target_link_libraries(myexe mylibA mylibB mylibC mylibD)
+
+add_executable(myexe2 myexe2.c)
+set_target_properties(myexe2 PROPERTIES
+ PDB_NAME "myexe2_Special"
+)
+
+target_link_libraries(myexe2 mylibA mylibD)
diff --git a/Tests/PDBDirectoryAndName/myexe.c b/Tests/PDBDirectoryAndName/myexe.c
new file mode 100644
index 0000000..c6d9065
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/myexe.c
@@ -0,0 +1,5 @@
+extern int mylibA();
+extern int mylibB();
+extern int mylibC();
+extern int mylibD();
+int main() { return mylibA() + mylibB() + mylibC() + mylibD(); }
diff --git a/Tests/PDBDirectoryAndName/myexe2.c b/Tests/PDBDirectoryAndName/myexe2.c
new file mode 100644
index 0000000..75b39cd
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/myexe2.c
@@ -0,0 +1,3 @@
+extern int mylibA();
+extern int mylibD();
+int main() { return mylibA() + mylibD(); }
diff --git a/Tests/PDBDirectoryAndName/mylibA.c b/Tests/PDBDirectoryAndName/mylibA.c
new file mode 100644
index 0000000..f4c553f
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibA.c
@@ -0,0 +1 @@
+__declspec(dllexport) int mylibA() { return 1; }
diff --git a/Tests/PDBDirectoryAndName/mylibB.c b/Tests/PDBDirectoryAndName/mylibB.c
new file mode 100644
index 0000000..2040c67
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibB.c
@@ -0,0 +1 @@
+int mylibB() { return -1; }
diff --git a/Tests/PDBDirectoryAndName/mylibC.c b/Tests/PDBDirectoryAndName/mylibC.c
new file mode 100644
index 0000000..adf7c70
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibC.c
@@ -0,0 +1 @@
+__declspec(dllexport) int mylibC() { return 1; }
diff --git a/Tests/PDBDirectoryAndName/mylibD.c b/Tests/PDBDirectoryAndName/mylibD.c
new file mode 100644
index 0000000..efa8a82
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibD.c
@@ -0,0 +1 @@
+int mylibD() { return -1; }