Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Microsoft Visual Studio Compiler Support #351

Merged
merged 18 commits into from
Oct 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,13 @@ option(GINKGO_WITH_CLANG_TIDY "Make Ginkgo call `clang-tidy` to find programming
option(GINKGO_WITH_IWYU "Make Ginkgo call `iwyu` (Include What You Use) to find include issues." OFF)
set(GINKGO_VERBOSE_LEVEL "1" CACHE STRING
"Verbosity level. Put 0 to turn off. 1 activates a few important messages.")
set(GINKGO_COMPILER_FLAGS "-Wpedantic" CACHE STRING
"Set the required CXX compiler flags, mainly used for warnings. Current default is `-Wpedantic`")
if(MSVC)
set(GINKGO_COMPILER_FLAGS "" CACHE STRING
"Set the required CXX compiler flags, mainly used for warnings. Current default is ``")
else()
set(GINKGO_COMPILER_FLAGS "-Wpedantic" CACHE STRING
"Set the required CXX compiler flags, mainly used for warnings. Current default is `-Wpedantic`")
endif()
set(GINKGO_CUDA_COMPILER_FLAGS "" CACHE STRING
"Set the required NVCC compiler flags, mainly used for warnings. Current default is an empty string")
set(GINKGO_CUDA_ARCHITECTURES "Auto" CACHE STRING
Expand All @@ -32,7 +37,7 @@ option(GINKGO_CUDA_DEFAULT_HOST_COMPILER "Tell Ginkgo to not automatically set t
option(GINKGO_JACOBI_FULL_OPTIMIZATIONS "Use all the optimizations for the CUDA Jacobi algorithm" OFF)
option(BUILD_SHARED_LIBS "Build shared (.so, .dylib, .dll) libraries" ON)

if(BUILD_SHARED_LIBS AND WIN32 AND (GINKGO_BUILD_TESTS OR GINKGO_BUILD_EXAMPLES OR GINKGO_BUILD_BENCHMARKS))
if(BUILD_SHARED_LIBS AND (WIN32 OR CYGWIN) AND (GINKGO_BUILD_TESTS OR GINKGO_BUILD_EXAMPLES OR GINKGO_BUILD_BENCHMARKS))
# Change shared libraries output only if this build has executable program with shared libraries.
set(GINKGO_CHANGED_SHARED_LIBRARY TRUE)
option(GINKGO_CHECK_PATH "Tell Ginkgo to check if the environment variable PATH is available for this build." ON)
Expand Down Expand Up @@ -104,6 +109,19 @@ endif()
configure_file(${Ginkgo_SOURCE_DIR}/include/ginkgo/config.hpp.in
${Ginkgo_BINARY_DIR}/include/ginkgo/config.hpp @ONLY)

# This is modified from https://gitlab.kitware.com/cmake/community/wikis/FAQ#dynamic-replace
if(MSVC)
if(BUILD_SHARED_LIBS)
ginkgo_switch_to_windows_dynamic("CXX")
ginkgo_switch_to_windows_dynamic("C")
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
else()
ginkgo_switch_to_windows_static("CXX")
ginkgo_switch_to_windows_static("C")
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS FALSE)
endif()
endif()

# Try to find the third party packages before using our subdirectories
include(cmake/package_helpers.cmake)
ginkgo_find_package(GTest "GTest::GTest;GTest::Main" FALSE 1.8.1)
Expand Down Expand Up @@ -142,9 +160,13 @@ if(GINKGO_DEVEL_TOOLS)
endif()

# Generate the global `ginkgo/ginkgo.hpp` header with every call of make
add_custom_target(generate_ginkgo_header ALL
find_program(BASH bash)
if(NOT "${BASH}" STREQUAL "BASH-NOTFOUND")
add_custom_target(generate_ginkgo_header ALL
COMMAND ${Ginkgo_SOURCE_DIR}/dev_tools/scripts/update_ginkgo_header.sh
WORKING_DIRECTORY ${Ginkgo_SOURCE_DIR})
endif()
unset(BASH CACHE)


# Installation
Expand Down
12 changes: 12 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Use the standard cmake build procedure:
mkdir build; cd build
cmake -G "Unix Makefiles" [OPTIONS] .. && make
```
Use `cmake --build .` in some systems like MinGW or Microsoft Visual Studio which do not use `make`.

For Microsoft Visual Studio, use `cmake --build . --config <build_type>` to decide the build type. The possible options are `Debug`, `Release`, `RelWithDebInfo` and `MinSizeRel`.

Replace `[OPTIONS]` with desired cmake options for your build.
Ginkgo adds the following additional switches to control what is being built:

Expand Down Expand Up @@ -81,6 +85,14 @@ Ginkgo adds the following additional switches to control what is being built:
this option see the
[`ARCHITECTURES` specification list](https://github.com/ginkgo-project/CudaArchitectureSelector/blob/master/CudaArchitectureSelector.cmake#L58)
section in the documentation of the CudaArchitectureSelector CMake module.
* `-DGINKGO_WINDOWS_SHARED_LIBRARY_RELPATH=<path>` where <path> is a relative
path built with `PROJECT_BINARY_DIR`. Users must add the absolute path
(`PROJECT_BINARY_DIR`/`GINKGO_WINDOWS_SHARED_LIBRARY_RELPATH`) into the
environment variable PATH when building shared libraries and executable
program, default is `windows_shared_library`.
* `-DGINKGO_CHECK_PATH={ON, OFF}` checks if the environment variable PATH is valid.
It is checked only when building shared libraries and executable program,
default is `ON`
yhmtsai marked this conversation as resolved.
Show resolved Hide resolved

For example, to build everything (in debug mode), use:

Expand Down
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,27 @@ following:

### Windows

Windows is currently not supported, but we are working on porting the library
there. If you are interested in helping us with this effort, feel free to
contact one of the developers. (The library itself doesn't use any non-standard
C++ features, so most of the effort here is in modifying the build system.)
The prequirement needs to be verified
* _cmake 3.9+_
* C++11 compliant 64-bits compiler:
* _MinGW : gcc 5.3+, 6.3+, 7.3+, 8.1+_
* _CygWin : gcc 5.3+, 6.3+, 7.3+, 8.1+_
* _Microsoft Visual Studio : VS 2017 15.7+_

__NOTE:__ Need to add `--autocrlf=input` after `git clone` in _CygWin_.

The Ginkgo CUDA module has the following __additional__ requirements:

* _CUDA 9.0+_
* _Microsoft Visual Studio_
* Any host compiler restrictions your version of CUDA may impose also apply
here. For the newest CUDA version, this information can be found in the
[CUDA installation guide for Windows](https://docs.nvidia.com/cuda/cuda-installation-guide-microsoft-windows/index.html)

The Ginkgo OMP module has the following __additional__ requirements:
* _MinGW_ or _Cygwin_

__NOTE:__ _Microsoft Visual Studio_ only supports OpenMP 2.0, so it can not compile the ginkgo OMP module.

__NOTE:__ Some restrictions will also apply on the version of C and C++ standard
libraries installed on the system. This needs further investigation.
Expand Down
2 changes: 1 addition & 1 deletion benchmark/spmv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ if (GINKGO_BUILD_CUDA)
if(CMAKE_CUDA_COMPILER_VERSION GREATER_EQUAL "9.2")
target_compile_definitions(spmv PRIVATE ALLOWMP=1)
endif()
endif()
endif()
45 changes: 42 additions & 3 deletions cmake/build_helpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,30 @@ function(ginkgo_compile_features name)
RUNTIME_OUTPUT_DIRECTORY "${GINKGO_WINDOWS_SHARED_LIBRARY_PATH}")
set_property(TARGET "${name}" PROPERTY
ARCHIVE_OUTPUT_DIRECTORY "${GINKGO_WINDOWS_SHARED_LIBRARY_PATH}")
if(MSVC)
# MSVC would create subfolder according to build_type. Ginkgo forces the output be the same whatever build_type is.
foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${CONFIG} CONFIG )
set_property(TARGET "${name}" PROPERTY
RUNTIME_OUTPUT_DIRECTORY_${CONFIG} "${GINKGO_WINDOWS_SHARED_LIBRARY_PATH}")
set_property(TARGET "${name}" PROPERTY
ARCHIVE_OUTPUT_DIRECTORY_${CONFIG} "${GINKGO_WINDOWS_SHARED_LIBRARY_PATH}")
endforeach()
endif()
if(GINKGO_CHECK_PATH)
ginkgo_check_shared_library("${CMAKE_SHARED_LIBRARY_PREFIX}${name}${CMAKE_SHARED_LIBRARY_SUFFIX}")
endif()
endif()
endfunction()

function(ginkgo_check_shared_library name)
set(PATH_LIST $ENV{PATH})
# Cygwin uses : not ; to split path
if(CYGWIN)
string(REPLACE ":" ";" ENV_PATH "$ENV{PATH}")
else()
set(ENV_PATH "$ENV{PATH}")
endif()
set(PATH_LIST ${ENV_PATH})
set(PASSED_TEST FALSE)
foreach(ITEM IN LISTS PATH_LIST)
string(REPLACE "\\" "/" ITEM "${ITEM}")
Expand All @@ -49,10 +65,33 @@ function(ginkgo_check_shared_library name)
# do not keep this variable in cache
unset(EXISTING_DLL CACHE)
endif()
endforeach(ITEM)
endforeach()
if(NOT PASSED_TEST)
# Did not find this build in the environment variable PATH
message(FATAL_ERROR "Did not find this build in the environment variable PATH. "
"Please add ${GINKGO_WINDOWS_SHARED_LIBRARY_PATH} into the environment variable PATH.")
endif()
endfunction()
endfunction()

function(ginkgo_switch_windows_link lang from to)
foreach(flag_var
"CMAKE_${lang}_FLAGS" "CMAKE_${lang}_FLAGS_DEBUG" "CMAKE_${lang}_FLAGS_RELEASE"
"CMAKE_${lang}_FLAGS_MINSIZEREL" "CMAKE_${lang}_FLAGS_RELWITHDEBINFO"
)
if(${flag_var} MATCHES "/${from}")
string(REGEX REPLACE "/${from}" "/${to}" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/${from}")
if(${flag_var} MATCHES "-${from}")
string(REGEX REPLACE "-${from}" "-${to}" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "-${from}")
set(${flag_var} "${${flag_var}}" CACHE STRING "" FORCE)
endforeach()
endfunction()

macro(ginkgo_switch_to_windows_static lang)
ginkgo_switch_windows_link(${lang} "MD" "MT")
endmacro()

macro(ginkgo_switch_to_windows_dynamic lang)
ginkgo_switch_windows_link(${lang} "MT" "MD")
endmacro()
54 changes: 42 additions & 12 deletions cmake/package_helpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,30 @@ function(ginkgo_load_git_package package_name package_url package_tag)
message(FATAL_ERROR
"CMake step for ${package_name}/download failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/download)
if(result)
message(FATAL_ERROR
"Build step for ${package_name}/download failed: ${result}")
if(MSVC)
# MSVC decides the build_type in build step not cmake step, so Ginkgo builds Debug and Release type.
execute_process(COMMAND ${CMAKE_COMMAND} --build . --config Debug
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/download)
if(result)
message(FATAL_ERROR
"Build Debug step for ${package_name}/download failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build . --config Release
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/download)
if(result)
message(FATAL_ERROR
"Build Release step for ${package_name}/download failed: ${result}")
endif()
else()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/download)
if(result)
message(FATAL_ERROR
"Build step for ${package_name}/download failed: ${result}")
endif()
endif()
endfunction()

Expand Down Expand Up @@ -76,9 +94,14 @@ macro(ginkgo_add_external_target new_target external_name includedir libdir buil
# Declare include directories and library files
set(${external_name}_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${libdir})
set(${external_name}_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${includedir}")
set(${external_name}_LIBRARY_RELEASE "${${external_name}_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_${build_type}_LIBRARY_PREFIX}${external_name}${CMAKE_${build_type}_LIBRARY_SUFFIX}")
set(${external_name}_LIBRARY_DEBUG "${${external_name}_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_${build_type}_LIBRARY_PREFIX}${external_name}${debug_postfix}${CMAKE_${build_type}_LIBRARY_SUFFIX}")

if(MSVC)
# Ginkgo only builds Debug and Release, so set the path without CMAKE_CFG_INTDIR.
set(${external_name}_LIBRARY_RELEASE "${${external_name}_BINARY_DIR}/Release/${CMAKE_${build_type}_LIBRARY_PREFIX}${external_name}${CMAKE_${build_type}_LIBRARY_SUFFIX}")
set(${external_name}_LIBRARY_DEBUG "${${external_name}_BINARY_DIR}/Debug/${CMAKE_${build_type}_LIBRARY_PREFIX}${external_name}${debug_postfix}${CMAKE_${build_type}_LIBRARY_SUFFIX}")
else()
set(${external_name}_LIBRARY_RELEASE "${${external_name}_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_${build_type}_LIBRARY_PREFIX}${external_name}${CMAKE_${build_type}_LIBRARY_SUFFIX}")
set(${external_name}_LIBRARY_DEBUG "${${external_name}_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_${build_type}_LIBRARY_PREFIX}${external_name}${debug_postfix}${CMAKE_${build_type}_LIBRARY_SUFFIX}")
endif()
# Create an IMPORTED external library available in the GLOBAL scope
if (${header_only})
add_library(${new_target} INTERFACE)
Expand All @@ -94,10 +117,17 @@ macro(ginkgo_add_external_target new_target external_name includedir libdir buil
set_target_properties(${new_target} PROPERTIES IMPORTED_LOCATION_RELEASE ${${external_name}_LIBRARY_RELEASE})
set_target_properties(${new_target} PROPERTIES IMPORTED_LOCATION_DEBUG ${${external_name}_LIBRARY_DEBUG})
# Since we do not really manage other build types, let's globally use the DEBUG symbols
if (NOT CMAKE_BUILD_TYPE MATCHES "[Rr][Ee][Ll][Ee][Aa][Ss][Ee]"
AND NOT CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
if(MSVC)
# Only Debug build uses MDd or MTd, and others use MD or MT.
# MSVC would like to use same runtime library, so we use Debug third-party in Debug and Release third-party in others.
set_target_properties(${new_target} PROPERTIES IMPORTED_LOCATION
${${external_name}_LIBRARY_DEBUG})
${${external_name}_LIBRARY_RELEASE})
tcojean marked this conversation as resolved.
Show resolved Hide resolved
else()
if (NOT CMAKE_BUILD_TYPE MATCHES "[Rr][Ee][Ll][Ee][Aa][Ss][Ee]"
AND NOT CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
set_target_properties(${new_target} PROPERTIES IMPORTED_LOCATION
${${external_name}_LIBRARY_DEBUG})
endif()
endif()
endif()
set_target_properties(${new_target} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${${external_name}_INCLUDE_DIR})
Expand Down
2 changes: 1 addition & 1 deletion core/base/combination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void Combination<ValueType>::apply_impl(const LinOp *alpha, const LinOp *b,
{
if (cache_.intermediate_x == nullptr ||
cache_.intermediate_x->get_size() != x->get_size()) {
cache_.intermediate_x = clone(x);
cache_.intermediate_x = x->clone();
}
this->apply_impl(b, lend(cache_.intermediate_x));
auto dense_x = as<matrix::Dense<ValueType>>(x);
Expand Down
9 changes: 5 additions & 4 deletions core/base/mtx_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <ginkgo/core/base/exception_helpers.hpp>
#include <ginkgo/core/base/math.hpp>
#include <ginkgo/core/base/utils.hpp>


namespace gko {
Expand Down Expand Up @@ -162,15 +163,15 @@ class mtx_io {

private:
template <typename T>
static xstd::enable_if_t<is_complex<T>()> write_entry_impl(
static xstd::enable_if_t<is_complex_s<T>::value> write_entry_impl(
std::ostream &, const T &)
{
throw GKO_STREAM_ERROR(
"trying to write a complex matrix into a real entry format");
}

template <typename T>
static xstd::enable_if_t<!is_complex<T>()> write_entry_impl(
static xstd::enable_if_t<!is_complex_s<T>::value> write_entry_impl(
std::ostream &os, const T &value)
{
GKO_CHECK_STREAM(os << static_cast<double>(value),
Expand Down Expand Up @@ -209,7 +210,7 @@ class mtx_io {

private:
template <typename T>
static xstd::enable_if_t<is_complex<T>(), T> read_entry_impl(
static xstd::enable_if_t<is_complex_s<T>::value, T> read_entry_impl(
std::istream &is)
{
using real_type = remove_complex<T>;
Expand All @@ -221,7 +222,7 @@ class mtx_io {
}

template <typename T>
static xstd::enable_if_t<!is_complex<T>(), T> read_entry_impl(
static xstd::enable_if_t<!is_complex_s<T>::value, T> read_entry_impl(
std::istream &)
{
throw GKO_STREAM_ERROR(
Expand Down
7 changes: 4 additions & 3 deletions core/test/base/math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ void test_real_isfinite()
{
using limits = std::numeric_limits<T>;
constexpr auto inf = limits::infinity();

// Use volatile to avoid MSVC report divided by zero.
volatile const T zero{0};
ASSERT_TRUE(gko::isfinite(T{0}));
ASSERT_TRUE(gko::isfinite(-T{0}));
ASSERT_TRUE(gko::isfinite(T{1}));
Expand All @@ -60,8 +61,8 @@ void test_real_isfinite()
ASSERT_FALSE(gko::isfinite(inf - inf)); // results in nan
ASSERT_FALSE(gko::isfinite(inf / inf)); // results in nan
ASSERT_FALSE(gko::isfinite(inf * T{2})); // results in inf
ASSERT_FALSE(gko::isfinite(T{1} / T{0})); // results in inf
ASSERT_FALSE(gko::isfinite(T{0} / T{0})); // results in nan
ASSERT_FALSE(gko::isfinite(T{1} / zero)); // results in inf
ASSERT_FALSE(gko::isfinite(T{0} / zero)); // results in nan
}


Expand Down
17 changes: 17 additions & 0 deletions core/test/base/mtx_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream>


#include <ginkgo/core/base/exception.hpp>
#include <ginkgo/core/base/lin_op.hpp>


Expand Down Expand Up @@ -256,6 +257,22 @@ TEST(MtxReader, ReadsSparseComplexHermitianMtx)
}


TEST(MtxReader, FailsWhenReadingSparseComplexMtxToRealMtx)
{
using cpx = std::complex<double>;
using tpl = gko::matrix_data<cpx, gko::int32>::nonzero_type;
std::istringstream iss(
"%%MatrixMarket matrix coordinate complex general\n"
"2 3 4\n"
"1 1 1.0 2.0\n"
"2 2 5.0 3.0\n"
"1 2 3.0 1.0\n"
"1 3 2.0 4.0\n");

ASSERT_THROW((gko::read_raw<double, gko::int32>(iss)), gko::StreamError);
}


TEST(MatrixData, WritesRealMatrixToMatrixMarketArray)
{
// clang-format off
Expand Down
Loading