CUDA: Pass more link libraries to device linking

Previously we dropped non-target items from the device link line because
nvcc rejects paths to shared library files, and only with target items
do we know the kind of library.  However, this also prevents projects
from linking to system-provided libraries like `cublas_device` that
contain device code.

Fix this by passing more link items to device linking.  Items that are
not file paths, such as `-lfoo`, can simply be passed unconditionally.
Items that are targets known to be shared libraries can still be
skipped.  Items that are paths to library files can be passed directly
if they end in `.a`.  Otherwise, pass them using `-Xnvlink` to bypass
nvcc's front-end.  The nvlink tool knows to ignore shared library files.

Issue: #16317
This commit is contained in:
Robert Maynard
2018-03-27 14:59:34 -04:00
committed by Brad King
parent 88c7abb740
commit 41eab150a8
5 changed files with 118 additions and 31 deletions

View File

@@ -3,9 +3,9 @@
#include "cmLinkLineDeviceComputer.h"
#include <set>
#include <sstream>
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
@@ -32,38 +32,32 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries(
ItemVector const& items = cli.GetItems();
std::string config = cli.GetConfig();
for (auto const& item : items) {
if (!item.Target) {
continue;
}
bool skippable = false;
switch (item.Target->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
case cmStateEnums::MODULE_LIBRARY:
case cmStateEnums::INTERFACE_LIBRARY:
skippable = true;
break;
case cmStateEnums::STATIC_LIBRARY:
// If a static library is resolving its device linking, it should
// be removed for other device linking
skippable =
item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
break;
default:
break;
}
if (skippable) {
continue;
}
std::set<std::string> langs;
item.Target->GetLanguages(langs, config);
if (langs.count("CUDA") == 0) {
continue;
if (item.Target) {
bool skip = false;
switch (item.Target->GetType()) {
case cmStateEnums::MODULE_LIBRARY:
case cmStateEnums::INTERFACE_LIBRARY:
skip = true;
break;
case cmStateEnums::STATIC_LIBRARY:
skip = item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
break;
default:
break;
}
if (skip) {
continue;
}
}
if (item.IsPath) {
// nvcc understands absolute paths to libraries ending in '.a' should
// be passed to nvlink. Other extensions like '.so' or '.dylib' are
// rejected by the nvcc front-end even though nvlink knows to ignore
// them. Bypass the front-end via '-Xnvlink'.
if (!cmHasLiteralSuffix(item.Value, ".a")) {
fout << "-Xnvlink ";
}
fout << this->ConvertToOutputFormat(
this->ConvertToLinkReference(item.Value));
} else {