From 071b138f74779e7fff5b47cf7b1f1369065cb2be Mon Sep 17 00:00:00 2001
From: Tianqi Chen <tqchen@users.noreply.github.com>
Date: Mon, 4 Sep 2017 19:36:46 -0700
Subject: [PATCH] [BUILD] Improve build instruction with llvm. (#422)

---
 CMakeLists.txt         | 45 +++++++++++++++++++++++++++++++-----------
 docs/how_to/install.md |  9 +++++++--
 2 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2748e6f9d..6e615fe54 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,13 +5,24 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build/private/local_config.cmake)
   include(${CMAKE_CURRENT_SOURCE_DIR}/build/private/local_config.cmake)
 endif()
 
-if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/config.cmake)
-  include(${CMAKE_CURRENT_SOURCE_DIR}/config.cmake)
+include(cmake/Util.cmake)
+
+if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/config.cmake)
+  include(${CMAKE_CURRENT_BINARY_DIR}/config.cmake)
+else()
+  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/config.cmake)
+    include(${CMAKE_CURRENT_SOURCE_DIR}/config.cmake)
+  endif()
 endif()
 
-include(cmake/Util.cmake)
-tvm_option(USE_CUDA "Build with CUDA" ON)
+# NOTE: do not modify this file to change option values.
+# You can create a config.cmake at build folder
+# and add set(OPTION VALUE) to override these build options.
+# Alernatively, use cmake -DOPTION=VALUE through command-line.
+
+tvm_option(USE_CUDA "Build with CUDA" OFF)
 tvm_option(USE_OPENCL "Build with OpenCL" OFF)
+tvm_option(USE_METAL "Build with Metal" OFF)
 tvm_option(USE_RPC "Build with RPC" OFF)
 tvm_option(USE_LLVM "Build with LLVM" OFF)
 tvm_option(USE_RTTI "Build with RTTI" ON)
@@ -73,6 +84,7 @@ file(GLOB RUNTIME_SRCS src/runtime/*.cc)
 file(GLOB COMPILER_LLVM_SRCS src/codegen/llvm/*.cc)
 file(GLOB RUNTIME_CUDA_SRCS src/runtime/cuda/*.cc)
 file(GLOB RUNTIME_OPENCL_SRCS src/runtime/opencl/*.cc)
+file(GLOB RUNTIME_METAL_SRCS src/runtime/metal/*.mm)
 file(GLOB RUNTIME_RPC_SRCS src/runtime/rpc/*.cc)
 
 if(USE_CUDA)
@@ -87,7 +99,7 @@ find_library(CUDA_NVRTC_LIBRARIES nvrtc
   set(CUDA_CUDA_LIBRARY ${CUDA_CUDA_LIBRARIES})
 
   find_package(CUDA QUIET REQUIRED)
-  message(STATUS "Build with CUDA support...")
+  message(STATUS "Build with CUDA support")
 	include_directories(${CUDA_INCLUDE_DIRS})
   list(APPEND TVM_RUNTIME_LINKER_LIBS ${CUDA_CUDART_LIBRARY})
   list(APPEND TVM_RUNTIME_LINKER_LIBS ${CUDA_CUDA_LIBRARY})
@@ -110,7 +122,7 @@ endif(USE_CUDA)
 
 if(USE_OPENCL)
   find_package(OPENCL QUIET REQUIRED)
-  message(STATUS "Build with OpenCL support...")
+  message(STATUS "Build with OpenCL support")
   include_directories(${OPENCL_INCLUDE_DIRS})
   list(APPEND TVM_RUNTIME_LINKER_LIBS ${OpenCL_LIBRARIES})
   list(APPEND RUNTIME_SRCS ${RUNTIME_OPENCL_SRCS})
@@ -119,19 +131,30 @@ else(USE_OPENCL)
   add_definitions(-DTVM_OPENCL_RUNTIME=0)
 endif(USE_OPENCL)
 
+if(USE_METAL)
+  find_package(OPENCL QUIET REQUIRED)
+  message(STATUS "Build with Metal support")
+  FIND_LIBRARY(METAL_LIB Metal)
+  FIND_LIBRARY(FOUNDATION_LIB Foundation)
+  list(APPEND TVM_RUNTIME_LINKER_LIBS ${METAL_LIB} ${FOUNDATION_LIB})
+  list(APPEND RUNTIME_SRCS ${RUNTIME_METAL_SRCS})
+  add_definitions(-DTVM_METAL_RUNTIME=1)
+else(USE_METAL)
+  add_definitions(-DTVM_METAL_RUNTIME=0)
+endif(USE_METAL)
+
 if(USE_RPC)
   message(STATUS "Build with RPC support...")
   list(APPEND RUNTIME_SRCS ${RUNTIME_RPC_SRCS})
 endif(USE_RPC)
 
 if(USE_LLVM)
-  find_package(LLVM REQUIRED CONFIG)
-  message(STATUS "Build with LLVM support...")
+  find_package(LLVM CONFIG REQUIRED)
   include_directories(${LLVM_INCLUDE_DIRS})
   add_definitions(${LLVM_DEFINITIONS})
-  string(REPLACE "." "" TVM_LLVM_VERSION ${LLVM_PACKAGE_VERSION})
-  string(SUBSTRING ${TVM_LLVM_VERSION} 0 2 TVM_LLVM_VERSION)
-  message(STATUS "TVM_LLVM_VERSION=" ${TVM_LLVM_VERSION})
+  set(TVM_LLVM_VERSION ${LLVM_VERSION_MAJOR}${LLVM_VERSION_MINOR})
+  message(STATUS "Build with LLVM " ${LLVM_PACKAGE_VERSION})
+  message(STATUS "Set TVM_LLVM_VERSION=" ${TVM_LLVM_VERSION})
   add_definitions(-DTVM_LLVM_VERSION=${TVM_LLVM_VERSION})
   llvm_map_components_to_libnames(LLVM_LIBS all)
   list(REMOVE_ITEM LLVM_LIBS LTO)
diff --git a/docs/how_to/install.md b/docs/how_to/install.md
index c4d90302d..f08830155 100644
--- a/docs/how_to/install.md
+++ b/docs/how_to/install.md
@@ -46,7 +46,7 @@ This will generate the VS project using the MSVC 14 64 bit generator. Open the .
 
 ### Customized Building
 
-Install prerequisites first: 
+Install prerequisites first:
 
 ```bash
 sudo apt-get update
@@ -57,7 +57,12 @@ The configuration of tvm can be modified by ```config.mk```
 - First copy ```make/config.mk``` to the project root, on which
   any local modification will be ignored by git, then modify the according flags.
 - TVM optionally depends on LLVM. LLVM is required for CPU codegen that needs LLVM.
-  - LLVM 4.0 or higher is needed for build with LLVM. The verison of LLVM from apt may lower than 4.0. you can download pre-built version of LLVM 4.0 from [LLVM Download Page](http://releases.llvm.org/download.html#4.0.1) and choose your matched pre-built binary package using `gcc -v` in command line to check `Target` value.
+  - LLVM 4.0 or higher is needed for build with LLVM. Note that verison of LLVM from default apt may lower than 4.0.
+  - Since LLVM takes long time to build from source, you can download pre-built version of LLVM frorm
+    [LLVM Download Page](http://releases.llvm.org/download.html).
+    - Unzip to a certain location, modify ```config.mk``` to add ```LLVM_CONFIG=/path/to/your/llvm/bin/llvm-config```
+  - You can also use [LLVM Nightly Ubuntu Build](https://apt.llvm.org/)
+    - Note that apt-package append ```llvm-config``` with version number. For example, set ```LLVM_CONFIG=llvm-config-4.0``` if you installed 4.0 package
   - By default CUDA and OpenCL code generator do not require llvm.
 
 ## Python Package Installation
-- 
GitLab