Skip to content

Building ArrayFire with Mingw on Windows

villekf edited this page Jun 11, 2021 · 4 revisions

This document outlines how to build ArrayFire with Mingw on Windows. This is necessary if you wish to use implementation 2 on Windows with Octave. It is also necessary if you want use the Mingw-w64 compiler on MATLAB on Windows. Only OpenCL is supported. Note that these instructions are mainly for Octave and MATLAB use is slightly different (though a bit easier).

Prerequisites

You'll need to have Octave installed in a location that has no spaces (i.e. Program files folder will not work). Note that the default location in your own user-folder includes GNU Octave folder that will not work (you can just use Octave instead). You'll also need CMake (e.g. 3.20.3 was used here), ArrayFire source, an OpenCL SDK (see installation help for details) and Boost (e.g. 1.76.0). Note that other than CMake, all of these should be located in folders with no spaces. For OpenCL, you could download OCL-SDK and extract it into the same folder as the ArrayFire source was extracted. For OpenCL library in OCL-SDK, you should use the one in x86_64 folder (you can delete the one in x86 if you don't need it). You could also simply copy the headers (CL folder) and library (OpenCL.lib) from any OpenCL SDK to the ArrayFire source-folder.

After installing Octave, you should add the full paths of Octave-installation-folder\mingw64\bin and Octave-installation-folder\usr\bin to the Windows Path (System --> Advanced system settings --> Environment variables --> Path), e.g. C:\Users\username\AppData\Local\Programs\Octave\Octave-6.2.0\mingw64\bin and C:\Users\username\AppData\Local\Programs\Octave\Octave-6.2.0\usr\bin. This, however, is not necessary and will simply simplify some things.

FOR MATLAB ONLY: If you want to use MinGW-w64 on MATLAB, you don't need Octave. However, instead you should get Mingw-w64 (use x86_64 architecture, the rest shouldn't matter). AFter installing MinGW, make sure Mingw is in Windows Path (System --> Advanced system settings --> Environment variables --> Path), e.g. C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin.

Building

  1. Have Octave (or Mingw-w64 for MATLAB), CMake and OpenCL installed. Extract the contents of Boost-archive and ArrayFire source (when using Octave, the OpenCL files are best to to be included in the same folder as ArrayFire source). The folder containing ArrayFire source will be referred to as arrayfire-source.
  2. Open defines.hpp in arrayfire-source\src\backend\common\ and comment (add \\ in front) lines 31-38 and line 41, i.e.
//#if defined(_WIN32) || defined(_MSC_VER)
//#define __PRETTY_FUNCTION__ __FUNCSIG__
//#if _MSC_VER < 1900
//#define snprintf sprintf_s
//#endif
//#define STATIC_ static
//#define __AF_FILENAME__ (clipFilePath(__FILE__, "src\\").c_str())
//#else
#define STATIC_ inline
#define __AF_FILENAME__ (clipFilePath(__FILE__, "src/").c_str())
//#endif
  1. Modify module_loading_windows.cpp in arrayfire-source\src\backend\common\ and switch line 21 return GetProcAddress(handle, symbolName); with return (void *)GetProcAddress(handle, symbolName);

  2. Open defines.h in arrayfire-source\include\af\ and comment (add \\ in front) lines 16-37 and line 46, i.e.

//#if defined(_WIN32) || defined(_MSC_VER)
    // http://msdn.microsoft.com/en-us/library/b0084kay(v=VS.80).aspx
    // http://msdn.microsoft.com/en-us/library/3y1sfaz2%28v=VS.80%29.aspx
//    #ifdef AFDLL // libaf
//        #define AFAPI  __declspec(dllexport)
//    #else
//        #define AFAPI  __declspec(dllimport)
//    #endif

//    // bool
//    #ifndef __cplusplus
//        #define bool unsigned char
//        #define false 0
//        #define true  1
//    #endif
//    #define __PRETTY_FUNCTION__ __FUNCSIG__
//    #define SIZE_T_FRMT_SPECIFIER "%Iu"
//    #define AF_DEPRECATED(msg) __declspec(deprecated( msg ))
//    #if _MSC_VER >= 1800
//        #define AF_HAS_VARIADIC_TEMPLATES
//    #endif
//#else
    #define AFAPI   __attribute__((visibility("default")))
    #include <stdbool.h>
    #define SIZE_T_FRMT_SPECIFIER "%zu"
#if __GNUC__ >= 4 && __GNUC_MINOR > 4
    #define AF_DEPRECATED(msg) __attribute__((deprecated( msg )))
#else
    #define AF_DEPRECATED(msg) __attribute__((deprecated))
#endif
//#endif
  1. Modify homography.hpp in arrayfire-source\src\backend\opencl\kernel\, add #include <cfloat> on the next line after #include <vector>

  2. Modify FindMKL.cmake (in arrayfire-source\CMakeModules folder), lines 164-170 and comment (add # in front) them, i.e.

if(WIN32)
#  if(${MSVC_VERSION} GREATER_EQUAL 1900)
#    set(msvc_dir "vc_mt")
 #   set(shared_suffix "_dll")
 #   set(md_suffix "md")
 # else()
 #   message(WARNING "MKL: MS Version not supported for MKL")
 # endif()
endif()
  1. Modify platform.cmake (in arrayfire-source\CMakeModules folder), line 26 and comment (add # in front) it, i.e.

# add_compile_options(/wd4068 /wd4275)

  1. Run CMake-gui.

  2. Select the arrayfire-source folder as the source.

  3. Select any location for the build, this will be referred later as arrayfire-build.

  4. Hit Configure, select MSYS Makefiles (when building for MATLAB, use MinGW Makefiles). You will most likely get an error here.

  5. If you did not add the Octave folders specified above to the Windows Path, you need to manually select the make, g++ and gcc locations. If you did add the folders to the path and CMAKE_CXX_COMPILER has g++.exe, proceed to the next step. Otherwise, add the make.exe executable to CMAKE_MAKE_PROGRAM (in the Octave \usr\bin folder), g++.exe to CMAKE_CXX_COMPILER (in the Octave \mingw64\bin folder) and gcc.exe to CMAKE_C_COMPILER (in the Octave \mingw64\bin folder). Hit Configure and proceed to the next step. For MATLAB, use mingw32-make as the make program.

  6. Select Grouped and Advanced. Open section Boost and see if Boost_INCLUDE_DIR has a folder. If there is message Boost_INCLUDE_DIR-NOTFOUND, go to the next step, otherwise skip to step 14.

  7. If you get an error in the previous step, it is most likely because boost was not found. You need to add the main boost-folder to the Boost_INCLUDE_DIR in CMake, i.e. the folder that contains README.md, libs folder, etc.. You can also add this folder to the Boost_DIR, but that may not be necessary. After this, hit Configure again. You should get another error.

  8. In AF group, deselect AF_BUILD_CPU, AF_BUILD_CUDA, AF_BUILD_EXAMPLES, make sure AF_BUILD_FORGE is NOT selected and deselect AF_BUILD_UNIFIED. Optionally deselect both options in BUILD group. Also, make sure that the OpenCL group points to the include folder and OpenCL library without any spaces on the file/folder path. Manually point these to the locations without spaces if needed.

  9. Modify CMAKE_INSTALL_PREFIX to be the folder you want the ArrayFire libraries and headers to be installed in.

  10. Hit Configure. This time there should be no errors.

  11. Hit Generate.

  12. Modify fft_binary_lookup.cpp in arrayfire-build\extern\ocl_clfft-src\src\library\, comment (add \\ in front) lines 119-134 and line 142, i.e.

bool FFTBinaryLookup::CacheEntry::exclusive_create()
{
//#ifdef _WIN32
//    std::wstring tmp;
//    tmp.assign(this->m_filename.begin(), this->m_filename.end());
//
//    HANDLE handle = CreateFile(tmp.c_str(), 
//                               GENERIC_WRITE, 
//                               0, // no share with other process
//                               NULL,
//                               CREATE_NEW,
//                               FILE_ATTRIBUTE_NORMAL,
//                               NULL);
//
//    this->m_handle = handle;
//    this->m_successful_creation = (handle != INVALID_HANDLE_VALUE);
//    return this->m_successful_creation;
//#else
    int * fd = new int;
    *fd = open (this->m_filename.c_str(),
                O_CREAT | O_EXCL, 
                S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
    this->m_handle = fd;
    this->m_successful_creation = (*fd != -1);
    return *fd >= 0;
//#endif
}
  1. Run Windows command prompt (cmd.exe). You need to run it as an admin if you are installing to a protected folder. It is in general recommended to run as admin.

  2. Go to the arrayfire-build folder (e.g. cd /d D:\path\to\arrayfire-buid).

  3. If you did not add the Octave folders to the Windows Path, you need to specify the full path to the make executable (e.g. C:\Users\username\AppData\Local\Octave\Octave-6.2.0\usr\bin\make), otherwise just run make. Note that you can speed up the process by running e.g. make -j4, where the number is the number of CPU cores available. For MATLAB, use mingw32-make instead here and later.

  4. Run make install (use full path if the folders are not on Path).

  5. Run install_mex(0,'','','C:\arrayfire\installation\folder'), i.e. use the folder you specified in CMAKE_INSTALL_PREFIX, in Octave/MATLAB.

  6. Either add the arrayfire\installation\folder to the Windows Path, or simply copy/move libafopencl.dll (and possibly also libafopencl.dll.a) to the OMEGA\source folder. Note that when using MATLAB, you need to rename libafopencl.dll into afopencl.dll and libafopencl.dll.a into afopencl.lib.

  7. Implementation 2 (OpenCL) should now be usable in Octave/MATLAB.