/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
MacOS build (tested on OS X El Capitan)

Install Prerequisites
---------------------

0.1) Install XCode 
  Download and install from here: https://developer.apple.com/xcode/downloads/
  or from the App store https://itunes.apple.com/us/app/xcode/id497799835?mt=12
  In Terminal, install the command line tools 
    $> xcode-select --install

0.2) Install brew following the instructions here: http://brew.sh/

1) CMAKE 3.1.3 or above
  Download and install Cmake : https://cmake.org/download/
  or use brew to install 
  $> brew install cmake

2.0) Install cppunit 
  $> brew install cppunit 

2.1) Install protobuf 3.6.1 (or higher)
  $> brew install protobuf

2.2) Install zookeeper
  $> brew install zookeeper

2.3) Install or build Cyrus SASL 
   To Install (need macports, brew did not work for me)
       port install cyrus-sasl2

   To build your own 
   See readme.sasl for instructions

2.4) Install OpenSSL
   [NOTE: MacOS has a neutered version of openssl installed. Install the build using brew. Make sure the brew installation is picked up]
   brew install openssl

2.5) Install boost
  $> brew install boost

2.5.1) For production builds, see the readme.boost file  
  
2.6) Build using XCODE
=========================  
(Optional) Refresh protobuf source files
----------------------------------------
When changes have been introduced to the protocol module, you might need to refresh the protobuf C++ source files too.
  $> cd DRILL_DIR/contrib/native/client
  $> mkdir build
  $> cd build && cmake -G "Xcode" -D CMAKE_BUILD_TYPE=Debug ..
  $> xcodebuild -project drillclient.xcodeproj -configuration ${BUILDTYPE} -target fixProtobufs
  $> xcodebuild -project drillclient.xcodeproj -configuration ${BUILDTYPE} -target cpProtobufs

Open a pull request with the changes to DRILL_DIR/contrib/native/client/src/protobuf

Build drill client
-------------------
  $> cd DRILL_DIR/contrib/native/client
  $> mkdir build
  $> cd build && cmake -G "Xcode" -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl "-D CMAKE_BUILD_TYPE=Debug ..
  $> xcodebuild -project drillclient.xcodeproj -configuration ${BUILDTYPE} -target ALL_BUILD


XCode IDE
---------
  You can open the drillclient.xcodeproj file in the XCode ide and run/debug as with any other command line app

2.7) Build using MAKE
========================
(Optional) Refresh protobuf source files
----------------------------------------
When changes have been introduced to the protocol module, you might need to refresh the protobuf C++ source files too.
    $> cd DRILL_DIR/contrib/native/client
    $> mkdir build
    $> cd build && cmake3 -G "Unix Makefiles" ..
    $> make cpProtobufs

Open a pull request with the changes to DRILL_DIR/contrib/native/client/src/protobuf

Build drill client
-------------------
    $> cd DRILL_DIR/contrib/native/client
    $> mkdir build
    $> cd build && cmake3 -G "Unix Makefiles" -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" -D CMAKE_BUILD_TYPE=Debug ..
    $> make

2.10) Build using CLion
CLion can recognize cmake projects automatically. Check CLion documentation for help on how to use CMake with CLion.
To prevent CLion's cmake from picking up the system installed OpenSSL set the following define in CLion/Preferences/Build, Execution, Deployment/CMake/CMake Options
-DOPENSSL_ROOT_DIR="/usr/local/opt/openssl
Then reload the CMake project making sure to invalidate the CMake cache
Tools/CMake/Reset Cache and Reload Project

2.9 Test
--------
Run query submitter from the command line
  $> querySubmitter query='select * from dfs.`/Users/pchandra/work/data/tpc-h/customer.parquet`' type=sql connectStr=local=10.250.0.146:31010 api=async logLevel=trace user=yourUserName password=yourPassWord

2.10 Valgrind
------------
  Install valgrind using brew
  $> brew install valgrind
  $> valgrind --leak-check=yes querySubmitter query='select LINEITEM from dfs.`/Users/pchandra/work/data/tpc-h/customer.parquet`' type=sql connectStr=local=10.250.0.146:31010 api=async logLevel=trace




