Add a guard function to check Caffe2 linking setup.

Summary:
This helps diagnosing issues like #346
Closes https://github.com/caffe2/caffe2/pull/354

Differential Revision: D4928347

Pulled By: Yangqing

fbshipit-source-id: b45685f1da18cbc49be293260b1fc2268fe5cd4c
This commit is contained in:
Yangqing Jia 2017-04-21 03:19:50 -07:00 committed by Facebook Github Bot
parent 4dafb608e7
commit 57b51db8d7
3 changed files with 30 additions and 0 deletions

View file

@ -1,4 +1,5 @@
#include "caffe2/core/init.h"
#include "caffe2/core/operator.h" // for StaticLinkingProtector
#ifndef CAFFE2_BUILD_STRING
#define CAFFE2_BUILD_STRING "build_version_not_set"
@ -14,6 +15,7 @@ Caffe2InitializeRegistry* Caffe2InitializeRegistry::Registry() {
bool GlobalInit(int* pargc, char*** pargv) {
static bool global_init_was_already_run = false;
static StaticLinkingProtector g_protector;
if (global_init_was_already_run) {
VLOG(1) << "GlobalInit has already been called: did you double-call?";
return true;

View file

@ -54,10 +54,12 @@ unique_ptr<OperatorBase> TryCreateOperator(
return nullptr;
}
}
} // namespace
unique_ptr<OperatorBase> CreateOperator(
const OperatorDef& operator_def, Workspace* ws) {
static StaticLinkingProtector g_protector;
// first, check with OpSchema if the operator is legal.
auto* schema = OpSchemaRegistry::Schema(operator_def.type());
if (schema) {

View file

@ -449,6 +449,32 @@ CAFFE_DECLARE_REGISTRY(
#define REGISTER_CUDNN_OPERATOR(name, ...) \
REGISTER_CUDA_OPERATOR_WITH_ENGINE(name, CUDNN, __VA_ARGS__)
// StaticLinkingProtector is a helper class that ensures that the Caffe2
// library is linked correctly with whole archives (in the case of static
// linking). What happens is that when CreateOperator is called for the first
// time, it instantiates an OperatorLinkingProtector object to check if the
// operator registry is empty. If it is empty, this means that we are not
// properly linking the library.
//
// You should not need to use this class.
struct StaticLinkingProtector {
StaticLinkingProtector() {
const int registered_ops = CPUOperatorRegistry()->Keys().size();
// Note: this is a check failure instead of an exception, because if
// the linking is wrong, Caffe2 won't be able to run properly anyway,
// so it's better to fail loud.
// If Caffe2 is properly linked with whole archive, there should be more
// than zero registered ops.
if (registered_ops == 0) {
LOG(FATAL) <<
"You might have made a build error: the Caffe2 library does not seem "
"to be linked with whole-static library option. To do so, use "
"-Wl,-force_load (clang) or -Wl,--whole-archive (gcc) to link the "
"Caffe2 library.";
}
}
};
// An exception that can be thrown by an operator constructor that notifies
// that it does not support the given setting. This can be usually used for
// specific engines that only implement a subset of the features required by