title: How to resolve "relocation against undefined symbol can not be used when making a shared object" with shared object/library in c++
body: <p>I am setting up a self made tracer in PyTorch source code.
  When I try to build a previous version of the code, I encounter the following error : </p>
  
  <p>(edited the output, it is with <code>make VERBOSE=1</code>)</p>
  
  <pre class="lang-sh prettyprint-override"><code>[ 47%] Linking CXX shared library ../lib/libcaffe2.so
  cd /opt/pytorch/build/caffe2 &amp;&amp; /usr/bin/cmake -E cmake_link_script CMakeFiles/caffe2.dir/link.txt --verbose=1
  /usr/bin/c++  -fPIC  -Wno-deprecated -fvisibility-inlines-hidden -fopenmp -DUSE_FBGEMM -O2 -fPIC -Wno-narrowing -fPIC -Wall -Wextra -Wno-missing-field-initializers -Wno-type-limits -Wno-array-bounds -Wno-unknown-pragmas -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-unused-function -Wno-unused-result -Wno-strict-overflow -Wno-strict-aliasing -Wno-error=deprecated-declarations -Wno-error=pedantic 
  
  [...]
  
  ,--whole-archive,/opt/pytorch/build/lib/libonnx.a -Wl,--no-whole-archive ../lib/libonnx_proto.a ../lib/libprotobuf.a -pthread -Wl,-rpath,/opt/pytorch/build/lib:/opt/conda/envs/build/lib:/usr/local/cuda/lib64:
  /usr/bin/ld: CMakeFiles/caffe2.dir/__/aten/src/ATen/native/cpu/Activation.cpp.AVX2.cpp.o: relocation R_X86_64_PC32 against undefined symbol `_ZN2at6vec25612_GLOBAL__N_118SOURCE_CODE_TRACERE' can not be used when making a shared object; recompile with -fPIC
  /usr/bin/ld: final link failed: Bad value
  collect2: error: ld returned 1 exit status
  caffe2/CMakeFiles/caffe2.dir/build.make:17251: recipe for target 'lib/libcaffe2.so' failed
  make[3]: *** [lib/libcaffe2.so] Error 1
  make[3]: Leaving directory '/opt/pytorch/build'
  CMakeFiles/Makefile2:3900: recipe for target 'caffe2/CMakeFiles/caffe2.dir/all' failed
  make[2]: *** [caffe2/CMakeFiles/caffe2.dir/all] Error 2
  make[2]: Leaving directory '/opt/pytorch/build'
  Makefile:138: recipe for target 'all' failed
  make[1]: *** [all] Error 2
  make[1]: Leaving directory '/opt/pytorch/build'
  Makefile:4: recipe for target 'all' failed
  make: *** [all] Error 2
  
  </code></pre>
  
  <p>I am not sure if I am missing a step for the tracer class import, or maybe the problem is linked to a shared library (libcaffe2.so ?) that is needed (like here : <a href="https://stackoverflow.com/questions/54471287/relocation-r-x86-64-pc32-against-undefined-symbol-can-not-be-used-when-making-a">Relocation R_X86_64_PC32 against undefined symbol can not be used when making a shared object; recompile with -fPIC</a> ) ?</p>
  
  <p>To use the tracer, I am doing this :</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#include "ATen/cpu/vec256/SourceCodeTracer.h"
  
  namespace at {
  namespace vec256 {
  namespace {
  
  #ifdef __AVX2__
  
  struct Vec256i {
  protected:
    __m256i values;
  
    static inline __m256i invert(const __m256i&amp; v) {
      // some code
      extern SourceCodeTracer SOURCE_CODE_TRACER;
      SOURCE_CODE_TRACER.trace("vec256_int.h __m256i invert()");
      return something;
    }
  
  </code></pre>
  
  <p>The class cpp file :</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#include "SourceCodeTracer.h"
  
  SourceCodeTracer* SourceCodeTracer::_singleton = NULL;
  extern SourceCodeTracer SOURCE_CODE_TRACER = SourceCodeTracer::getInstance();
  
  SourceCodeTracer::~SourceCodeTracer() {
          // TODO: Write into
          std::cout &lt;&lt; "Destructing object" &lt;&lt; std::endl;
          ofstream traceOutputFile;
          try
          {
                  std::cout &lt;&lt; "Writing to " &lt;&lt; _filePath &lt;&lt; std::endl;
                  traceOutputFile.open(_filePath);
                  traceOutputFile &lt;&lt; "Run at TODO PUT TIME" &lt;&lt; std::endl;
                  for (auto it = _map.begin(); it != _map.end(); ++it) {
                          traceOutputFile &lt;&lt; it-&gt;first &lt;&lt; " =&gt; " &lt;&lt; it-&gt;second &lt;&lt; '\n';
                  }
          }
          catch (const std::exception&amp; e)
          {
                  std::cout &lt;&lt; "Got error while trying to write trace file:" &lt;&lt; e.what() &lt;&lt; std::endl;
          }
          traceOutputFile.close();
  }
  
  SourceCodeTracer &amp; SourceCodeTracer::getInstance() {
          if (SourceCodeTracer::_singleton == nullptr) {
                  std::cout &lt;&lt; "Constructing object" &lt;&lt; std::endl;
                  SourceCodeTracer::_singleton = new SourceCodeTracer();
          }
          return *SourceCodeTracer::_singleton;
  }
  
  void SourceCodeTracer::trace(const string &amp; tr) {
          _map[tr] = _map[tr] + 1;
  }
  
  SourceCodeTracer::SourceCodeTracer() {
          _filePath = "trace.txt"; //get_env_var("TRACER_OUTPUT_FILE_PATH");
          std::cout &lt;&lt; "Got environment value for TRACER_OUTPUT_FILE_PATH of " &lt;&lt; _filePath &lt;&lt; std::endl;
          if (_filePath == "") {
                  // Warn that no environment variable was set
                  std::cout &lt;&lt; "No value for TRACER_OUTPUT_FILE_PATH set !" &lt;&lt; std::endl;
                  exit(1);
          }
          // Assert path is writable
  }
  
  // https://stackoverflow.com/q/631664/9876427
  std::string SourceCodeTracer::get_env_var(std::string const &amp; key) const {
          char * val;
          val = std::getenv(key.c_str());
          std::string retval = "";
          if (val != NULL) {
                  retval = val;
          }
          return retval;
  }
  </code></pre>
  
  <p>header file :</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;fstream&gt;
  #include &lt;list&gt;
  #include &lt;map&gt;
  #include &lt;memory&gt;
  #include &lt;iomanip&gt;
  #include &lt;ios&gt;
  #include &lt;cstddef&gt;
  #include &lt;cstdlib&gt;
  
  
  #ifndef __SOURCE_CODE_TRACER_H__
  #define __SOURCE_CODE_TRACER_H__
  
  using namespace std;
  class SourceCodeTracer {
          public:
          ~SourceCodeTracer();
  
          static SourceCodeTracer&amp; getInstance();
          void trace(const string&amp; tr);
  private:
          SourceCodeTracer();
          // https://stackoverflow.com/q/631664/9876427
          std::string get_env_var(std::string const &amp; key) const;
          static SourceCodeTracer* _singleton;
          // Traceur() = delete;
          std::map&lt;string, long&gt; _map;
          string _filePath;
  };
  
  #endif // __SOURCE_CODE_TRACER_H__
  </code></pre>