From 4865f958305de5de457b4991a3da8d3bd5ae6931 Mon Sep 17 00:00:00 2001
From: Tianqi Chen <tqchen@users.noreply.github.com>
Date: Sun, 8 Oct 2017 15:28:36 -0700
Subject: [PATCH] [BUILD] Windows support of DLL exports (#522)

---
 CMakeLists.txt                    |  2 ++
 HalideIR                          |  2 +-
 include/tvm/buffer.h              | 34 +++++++++++++++----------------
 include/tvm/expr.h                | 16 +++++++--------
 include/tvm/ir.h                  | 14 ++++++-------
 include/tvm/ir_mutator.h          |  2 +-
 include/tvm/ir_operator.h         |  6 +++---
 include/tvm/ir_visitor.h          |  2 +-
 include/tvm/operation.h           | 34 +++++++++++++++----------------
 include/tvm/runtime/device_api.h  |  6 +++---
 include/tvm/runtime/module.h      | 14 ++++++-------
 include/tvm/runtime/packed_func.h |  4 ++--
 include/tvm/runtime/registry.h    | 10 ++++-----
 include/tvm/target_info.h         |  2 +-
 include/tvm/tensor.h              | 14 ++++++-------
 python/setup.py                   |  2 +-
 16 files changed, 83 insertions(+), 81 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 84122c77b..edcd4afb7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,6 +44,8 @@ if(MSVC)
   add_definitions(-D_CRT_SECURE_NO_WARNINGS)
   add_definitions(-D_SCL_SECURE_NO_WARNINGS)
   add_definitions(-DTVM_EXPORTS)
+  add_definitions(-DHalide_SHARED)
+  add_definitions(-DHalide_EXPORTS)
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /bigobj")
diff --git a/HalideIR b/HalideIR
index cb3c025d5..dbf043a8d 160000
--- a/HalideIR
+++ b/HalideIR
@@ -1 +1 @@
-Subproject commit cb3c025d5b91ab994b063a85bc935fc364d8f491
+Subproject commit dbf043a8d8bf379b05c56d8aa9025db55f589d6d
diff --git a/include/tvm/buffer.h b/include/tvm/buffer.h
index b9c79eda1..25f5dde86 100644
--- a/include/tvm/buffer.h
+++ b/include/tvm/buffer.h
@@ -37,7 +37,7 @@ class Buffer : public NodeRef {
    *  but always add stride field.
    * \return The strided version of the buffer.
    */
-  Buffer MakeStrideView() const;
+  TVM_DLL Buffer MakeStrideView() const;
   /*!
    * \brief Make a new symbolic buffer representing a slice of the buffer.
    * \param begins The beginning position of each dimension.
@@ -46,25 +46,25 @@ class Buffer : public NodeRef {
    *  If stride is not needed in the slice, it won't be presented
    * \return the result buffer.
    */
-  Buffer MakeSlice(Array<Expr> begins, Array<Expr> extents) const;
+  TVM_DLL Buffer MakeSlice(Array<Expr> begins, Array<Expr> extents) const;
   /*!
    * \brief Get access ptr to the entire buffer.
    * \param access_mask The access mask
    * \param ptr_type The type of the pointer.
    */
-  Expr access_ptr(int access_mask, Type ptr_type = Handle()) const;
+  TVM_DLL Expr access_ptr(int access_mask, Type ptr_type = Handle()) const;
   /*!
    * \brief Create an Expr that does a vector load at begin index.
    * \param begin The beginning index
    * \param dtype The data type to be loaded.
    */
-  Expr vload(Array<Expr> begin, Type dtype) const;
+  TVM_DLL Expr vload(Array<Expr> begin, Type dtype) const;
   /*!
    * \brief Create a Stmt that does a vector store at begin index.
    * \param begin The beginning index
    * \param value The value to be stored.
    */
-  Stmt vstore(Array<Expr> begin, Expr value) const;
+  TVM_DLL Stmt vstore(Array<Expr> begin, Expr value) const;
   /*!
    * \brief access the internal node container
    * \return the pointer to the internal node container
@@ -124,15 +124,15 @@ class BufferNode : public Node {
 
   // User can specify data_alignment and offset_factor to be 0
   // A default value will be picked.
-  static Buffer make(Var ptr,
-                     Type dtype,
-                     Array<Expr> shape,
-                     Array<Expr> strides,
-                     Expr byte_offset,
-                     std::string name,
-                     std::string scope,
-                     int data_alignment,
-                     int offset_factor);
+  TVM_DLL static Buffer make(Var ptr,
+                             Type dtype,
+                             Array<Expr> shape,
+                             Array<Expr> strides,
+                             Expr byte_offset,
+                             std::string name,
+                             std::string scope,
+                             int data_alignment,
+                             int offset_factor);
 
   static constexpr const char* _type_key = "Buffer";
   TVM_DECLARE_NODE_TYPE_INFO(BufferNode, Node);
@@ -150,8 +150,8 @@ inline const BufferNode* Buffer::operator->() const {
  * \return The created buffer.
  * \sa BufferNode::make for complete constructor.
  */
-Buffer decl_buffer(Array<Expr> shape,
-                   Type dtype = Float(32),
-                   std::string name = "buffer");
+TVM_DLL Buffer decl_buffer(Array<Expr> shape,
+                           Type dtype = Float(32),
+                           std::string name = "buffer");
 }  // namespace tvm
 #endif  // TVM_BUFFER_H_
diff --git a/include/tvm/expr.h b/include/tvm/expr.h
index 5570014cf..4e4e25c0c 100644
--- a/include/tvm/expr.h
+++ b/include/tvm/expr.h
@@ -112,9 +112,9 @@ class Range : public Halide::IR::Range {
    * \param begin The begin of the range.
    * \param end The end of the range.
    */
-  Range(Expr begin, Expr end);
+  TVM_DLL Range(Expr begin, Expr end);
 
-  static Range make_by_min_extent(Expr min, Expr extent);
+  TVM_DLL static Range make_by_min_extent(Expr min, Expr extent);
 };
 
 /*!
@@ -216,7 +216,7 @@ class IterVar : public NodeRef {
  * \param dom Optional, domain of the thread axis.
  * \param tag The thread tag of the axis.
  */
-IterVar thread_axis(Range dom, std::string tag);
+TVM_DLL IterVar thread_axis(Range dom, std::string tag);
 
 /*!
  * \brief Create a new IterVar for reduction operations.
@@ -224,12 +224,12 @@ IterVar thread_axis(Range dom, std::string tag);
  * \param dom The domain of the reduction axis.
  * \param name The name of the reduction axis.
  */
-IterVar reduce_axis(Range dom, std::string name = "rv");
+TVM_DLL IterVar reduce_axis(Range dom, std::string name = "rv");
 
 using Domain = Array<Range>;
 
 // print functions for expr
-std::ostream& operator<<(std::ostream& os, const NodeRef& n);  // NOLINT(*)
+TVM_DLL std::ostream& operator<<(std::ostream& os, const NodeRef& n);  // NOLINT(*)
 // definition of Node.
 /*!
  * \brief An iteration variable representing an iteration
@@ -259,9 +259,9 @@ class IterVarNode : public Node {
     v->Visit("thread_tag", &thread_tag);
   }
 
-  static IterVar make(Range dom, Var var,
-                      IterVarType iter_type,
-                      std::string thread_tag = "");
+  TVM_DLL static IterVar make(Range dom, Var var,
+                              IterVarType iter_type,
+                              std::string thread_tag = "");
 
   static constexpr const char* _type_key = "IterVar";
   TVM_DECLARE_NODE_TYPE_INFO(IterVarNode, Node);
diff --git a/include/tvm/ir.h b/include/tvm/ir.h
index 5769e59b5..ae53d38b8 100644
--- a/include/tvm/ir.h
+++ b/include/tvm/ir.h
@@ -62,8 +62,8 @@ struct CommReducerNode : public Node {
   /*! \brief Function call operator to combine a and b */
   Array<Expr> operator()(Array<Expr> a, Array<Expr> b) const;
   /*! \brief construct CommReducer from args, result and identity_element */
-  static CommReducer make(Array<Var> lhs, Array<Var> rhs,
-                          Array<Expr> result, Array<Expr> identity_element);
+  TVM_DLL static CommReducer make(Array<Var> lhs, Array<Var> rhs,
+                                 Array<Expr> result, Array<Expr> identity_element);
 
   void VisitAttrs(AttrVisitor* v) final {
     v->Visit("lhs", &lhs);
@@ -100,11 +100,11 @@ struct Reduce : public ExprNode<Reduce> {
   int value_index;
 
   /*! \brief construct expr from op and rdom */
-  static Expr make(CommReducer combiner,
-                   Array<Expr> src,
-                   Array<IterVar> rdom,
-                   Expr condition,
-                   int value_index);
+  TVM_DLL static Expr make(CommReducer combiner,
+                           Array<Expr> src,
+                           Array<IterVar> rdom,
+                           Expr condition,
+                           int value_index);
 
   void VisitAttrs(AttrVisitor* v) final {
     v->Visit("dtype", &type);
diff --git a/include/tvm/ir_mutator.h b/include/tvm/ir_mutator.h
index 904a16530..1faf1724d 100644
--- a/include/tvm/ir_mutator.h
+++ b/include/tvm/ir_mutator.h
@@ -25,7 +25,7 @@ namespace ir {
  *       Simply following the same pattern as IRMutator and create a seperate class.
  * \sa IRFunctor
  */
-class IRMutator {
+class TVM_DLL IRMutator {
  public:
   /*!
    * \brief mutate expression
diff --git a/include/tvm/ir_operator.h b/include/tvm/ir_operator.h
index 755379b50..a0726f003 100644
--- a/include/tvm/ir_operator.h
+++ b/include/tvm/ir_operator.h
@@ -26,21 +26,21 @@ using Halide::select;
  * \param source The source expression.
  * \param axis List of iteration variables that will be used for reduction.
  */
-Expr sum(Expr source, Array<IterVar> axis);
+TVM_DLL Expr sum(Expr source, Array<IterVar> axis);
 
 /*!
  * \brief max of of source expression over axis
  * \param source The source expression.
  * \param axis List of iteration variables that will be used for reduction.
  */
-Expr max(Expr source, Array<IterVar> axis);
+TVM_DLL Expr max(Expr source, Array<IterVar> axis);
 
 /*!
  * \brief max of of source expression over axis
  * \param source The source expression.
  * \param axis List of iteration variables that will be used for reduction.
  */
-Expr min(Expr source, Array<IterVar> axis);
+TVM_DLL Expr min(Expr source, Array<IterVar> axis);
 
 // Unary intrinsic operators
 #define TVM_DECLARE_INTRIN_UNARY(OpName)                                \
diff --git a/include/tvm/ir_visitor.h b/include/tvm/ir_visitor.h
index a1963655b..7cfd45b83 100644
--- a/include/tvm/ir_visitor.h
+++ b/include/tvm/ir_visitor.h
@@ -64,7 +64,7 @@ namespace ir {
  *
  * \endcode
  */
-class IRVisitor {
+class TVM_DLL IRVisitor {
  public:
   /*!
    * \brief recursively visit an IR node
diff --git a/include/tvm/operation.h b/include/tvm/operation.h
index f44cfe895..8242bfbee 100644
--- a/include/tvm/operation.h
+++ b/include/tvm/operation.h
@@ -376,9 +376,9 @@ using FBatchCompute = std::function<Array<Expr> (const Array<Var>& i)>;
  * \param dtype the data type of the tensor.
  * \param name The name of the Tensor.
  */
-Tensor placeholder(Array<Expr> shape,
-                   Type dtype = Float(32),
-                   std::string name = "placeholder");
+TVM_DLL Tensor placeholder(Array<Expr> shape,
+                           Type dtype = Float(32),
+                           std::string name = "placeholder");
 
 /*!
  * \brief Construct a new tensor by computing over shape,
@@ -388,10 +388,10 @@ Tensor placeholder(Array<Expr> shape,
  * \param name The optional name of the tensor.
  * \param tag The optional tag of the tensor.
  */
-Tensor compute(Array<Expr> shape,
-               FCompute fcompute,
-               std::string name = "tensor",
-               std::string tag = "");
+TVM_DLL Tensor compute(Array<Expr> shape,
+                       FCompute fcompute,
+                       std::string name = "tensor",
+                       std::string tag = "");
 
 /*!
  * \brief Construct a new tensor by computing over shape,
@@ -401,10 +401,10 @@ Tensor compute(Array<Expr> shape,
  * \param name The optional name of the tensor.
  * \param tag The optional tag of the tensor.
  */
-Array<Tensor> compute(Array<Expr> shape,
-                      FBatchCompute fcompute,
-                      std::string name = "tensor",
-                      std::string tag = "");
+TVM_DLL Array<Tensor> compute(Array<Expr> shape,
+                              FBatchCompute fcompute,
+                              std::string name = "tensor",
+                              std::string tag = "");
 
 /*!
  * \brief Construct new tensors by scan.
@@ -417,12 +417,12 @@ Array<Tensor> compute(Array<Expr> shape,
  * \param name The optional name of the tensor.
  * \param tag The optional tag of the tensor.
  */
-Array<Tensor> scan(Array<Tensor> init,
-                   Array<Tensor> update,
-                   Array<Tensor> state_placeholder,
-                   Array<Tensor> inputs = Array<Tensor>(),
-                   std::string name = "scan",
-                   std::string tag = "");
+TVM_DLL Array<Tensor> scan(Array<Tensor> init,
+                           Array<Tensor> update,
+                           Array<Tensor> state_placeholder,
+                           Array<Tensor> inputs = Array<Tensor>(),
+                           std::string name = "scan",
+                           std::string tag = "");
 
 // same as compute, specialized for different fcompute function
 inline Tensor compute(Array<Expr> shape,
diff --git a/include/tvm/runtime/device_api.h b/include/tvm/runtime/device_api.h
index d50a23c80..318a53637 100644
--- a/include/tvm/runtime/device_api.h
+++ b/include/tvm/runtime/device_api.h
@@ -111,21 +111,21 @@ class DeviceAPI {
    * \param ctx The context of allocation.
    * \param size The size to be allocated.
    */
-  virtual void* AllocWorkspace(TVMContext ctx, size_t size);
+  TVM_DLL virtual void* AllocWorkspace(TVMContext ctx, size_t size);
   /*!
    * \brief Free temporal workspace in backend execution.
    *
    * \param ctx The context of allocation.
    * \param ptr The pointer to be freed.
    */
-  virtual void FreeWorkspace(TVMContext ctx, void* ptr);
+  TVM_DLL virtual void FreeWorkspace(TVMContext ctx, void* ptr);
   /*!
    * \brief Get device API base don context.
    * \param ctx The context
    * \param allow_missing Whether allow missing
    * \return The corresponding device API.
    */
-  static DeviceAPI* Get(TVMContext ctx, bool allow_missing = false);
+  TVM_DLL static DeviceAPI* Get(TVMContext ctx, bool allow_missing = false);
 };
 
 /*! \brief The device type bigger than this is RPC device */
diff --git a/include/tvm/runtime/module.h b/include/tvm/runtime/module.h
index 1eecf8685..3d0991034 100644
--- a/include/tvm/runtime/module.h
+++ b/include/tvm/runtime/module.h
@@ -39,7 +39,7 @@ class Module {
    * \return The result function.
    *  This function will return PackedFunc(nullptr) if function do not exist.
    */
-  PackedFunc GetFunction(const std::string& name, bool query_imports = false);
+  TVM_DLL PackedFunc GetFunction(const std::string& name, bool query_imports = false);
   /*!
    * \brief Import another module into this module.
    * \param other The module to be imported.
@@ -47,7 +47,7 @@ class Module {
    * \note Cyclic dependency is not allowed among modules,
    *  An error will be thrown when cyclic dependency is detected.
    */
-  void Import(Module other);
+  TVM_DLL void Import(Module other);
   /*!
    * \brief Load a module from file.
    * \param file_name The name of the host function module.
@@ -55,8 +55,8 @@ class Module {
    * \note This function won't load the import relationship.
    *  Re-create import relationship by calling Import.
    */
-  static Module LoadFromFile(const std::string& file_name,
-                             const std::string& format = "");
+  TVM_DLL static Module LoadFromFile(const std::string& file_name,
+                                     const std::string& format = "");
   /*! \return internal container */
   inline ModuleNode* operator->();
   /*! \return internal container */
@@ -110,13 +110,13 @@ class ModuleNode {
    *   but not necessarily host modules.
    *   We can use this to do AOT loading of bundled device functions.
    */
-  virtual void SaveToBinary(dmlc::Stream* stream);
+  TVM_DLL virtual void SaveToBinary(dmlc::Stream* stream);
   /*!
    * \brief Get the source code of module, when available.
    * \param format Format of the source code, can be empty by default.
    * \return Possible source code when available.
    */
-  virtual std::string GetSource(const std::string& format = "");
+  TVM_DLL virtual std::string GetSource(const std::string& format = "");
   /*!
    * \brief Get a function from current environment
    *  The environment includes all the imports as well as Global functions.
@@ -124,7 +124,7 @@ class ModuleNode {
    * \param name name of the function.
    * \return The corresponding function.
    */
-  const PackedFunc* GetFuncFromEnv(const std::string& name);
+  TVM_DLL const PackedFunc* GetFuncFromEnv(const std::string& name);
   /*! \return The module it imports from */
   const std::vector<Module>& imports() const {
     return imports_;
diff --git a/include/tvm/runtime/packed_func.h b/include/tvm/runtime/packed_func.h
index 3653c6714..41537760e 100644
--- a/include/tvm/runtime/packed_func.h
+++ b/include/tvm/runtime/packed_func.h
@@ -203,11 +203,11 @@ class ExtTypeVTable {
    * \param type_code The type code
    * \return The registered vtable.
    */
-  static ExtTypeVTable* Get(int type_code);
+  TVM_DLL static ExtTypeVTable* Get(int type_code);
 
  private:
   // Internal registration function.
-  static ExtTypeVTable* RegisterInternal(int type_code, const ExtTypeVTable& vt);
+  TVM_DLL static ExtTypeVTable* RegisterInternal(int type_code, const ExtTypeVTable& vt);
 };
 
 /*!
diff --git a/include/tvm/runtime/registry.h b/include/tvm/runtime/registry.h
index e325c3b5a..61feccadf 100644
--- a/include/tvm/runtime/registry.h
+++ b/include/tvm/runtime/registry.h
@@ -39,7 +39,7 @@ class Registry {
    * \brief set the body of the function to be f
    * \param f The body of the function.
    */
-  Registry& set_body(PackedFunc f);  // NOLINT(*)
+  TVM_DLL Registry& set_body(PackedFunc f);  // NOLINT(*)
   /*!
    * \brief set the body of the function to be f
    * \param f The body of the function.
@@ -53,25 +53,25 @@ class Registry {
    * \param override Whether allow oveeride existing function.
    * \return Reference to theregistry.
    */
-  static Registry& Register(const std::string& name, bool override = false);  // NOLINT(*)
+  TVM_DLL static Registry& Register(const std::string& name, bool override = false);  // NOLINT(*)
   /*!
    * \brief Erase global function from registry, if exist.
    * \param name The name of the function.
    * \return Whether function exist.
    */
-  static bool Remove(const std::string& name);
+  TVM_DLL static bool Remove(const std::string& name);
   /*!
    * \brief Get the global function by name.
    * \param name The name of the function.
    * \return pointer to the registered function,
    *   nullptr if it does not exist.
    */
-  static const PackedFunc* Get(const std::string& name);  // NOLINT(*)
+  TVM_DLL static const PackedFunc* Get(const std::string& name);  // NOLINT(*)
   /*!
    * \brief Get the names of currently registered global function.
    * \return The names
    */
-  static std::vector<std::string> ListNames();
+  TVM_DLL static std::vector<std::string> ListNames();
 
   // Internal class.
   struct Manager;
diff --git a/include/tvm/target_info.h b/include/tvm/target_info.h
index 73dc2c598..d00cd1e2b 100644
--- a/include/tvm/target_info.h
+++ b/include/tvm/target_info.h
@@ -48,7 +48,7 @@ TVM_DEFINE_NODE_REF(MemoryInfo, MemoryInfoNode);
  * \param scope The scope name.
  * \return info The memory info.
  */
-MemoryInfo GetMemoryInfo(const std::string& scope);
+TVM_DLL MemoryInfo GetMemoryInfo(const std::string& scope);
 
 }  // namespace tvm
 #endif  // TVM_TARGET_INFO_H_
diff --git a/include/tvm/tensor.h b/include/tvm/tensor.h
index 58cec86ec..a6613a4dc 100644
--- a/include/tvm/tensor.h
+++ b/include/tvm/tensor.h
@@ -62,13 +62,13 @@ class Tensor : public NodeRef {
    * \param indices the indices.
    * \return the result expression representing tensor read.
    */
-  Expr operator()(Array<Expr> indices) const;
+  TVM_DLL Expr operator()(Array<Expr> indices) const;
   /*!
    * \brief Take elements from the tensor
    * \param indices the indices.
    * \return the result expression representing tensor read.
    */
-  Expr operator()(Array<Var> indices) const;
+  TVM_DLL Expr operator()(Array<Var> indices) const;
   /*!
    * \brief data structure to represent a slice that fixes first k coordinates.
    *  This is used to enable syntax sugar of Tensor[x][y][z] to get the element.
@@ -129,7 +129,7 @@ class Operation : public FunctionRef {
    * \param i the output index.
    * \return The i-th output.
    */
-  Tensor output(size_t i) const;
+  TVM_DLL Tensor output(size_t i) const;
   /*! \brief specify container node */
   using ContainerType = OperationNode;
 };
@@ -154,10 +154,10 @@ class TensorNode : public Node {
     v->Visit("op", &op);
     v->Visit("value_index", &value_index);
   }
-  static Tensor make(Array<Expr> shape,
-                     Type dtype,
-                     Operation op,
-                     int value_index);
+  TVM_DLL static Tensor make(Array<Expr> shape,
+                             Type dtype,
+                             Operation op,
+                             int value_index);
 
   static constexpr const char* _type_key = "Tensor";
   TVM_DECLARE_NODE_TYPE_INFO(TensorNode, Node);
diff --git a/python/setup.py b/python/setup.py
index a997c6f52..168729391 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -18,7 +18,7 @@ else:
     from setuptools import setup
     from setuptools.extension import Extension
 
-# We can not import `mxnet.info.py` in setup.py directly since mxnet/__init__.py
+# We can not import `libinfo.py` in setup.py directly since __init__.py
 # Will be invoked which introduces dependences
 CURRENT_DIR = os.path.dirname(__file__)
 libinfo_py = os.path.join(CURRENT_DIR, './tvm/_ffi/libinfo.py')
-- 
GitLab