Skip to content

Building libcmaes on Windows 11 with Visual Studio 2022 #245

@chobby

Description

@chobby

I recently attempted to build libcmaes on Windows 11 using Visual Studio 2022 (MSVC) and encountered several issues. After resolving them, I wanted to share the complete build process for other Windows users.

  • Windows 11
  • Visual Studio 2022
  • vcpkg package manager
  • CMake

Steps

1. Install Dependencies using vcpkg

First, install the required dependencies using vcpkg:

vcpkg install eigen3:x64-windows
vcpkg install glog:x64-windows
vcpkg install gflags:x64-windows

2. Modify CMakeLists.txt

The original CMakeLists.txt needs to be modified to support MSVC compiler flags. Locate the compiler flags section and replace it with the following:

if(MSVC)
    # MSVC compiler flags
    set(CMAKE_CXX_FLAGS "/W4")
    set(CMAKE_CXX_FLAGS_DEBUG "/Zi /Od")
    set(CMAKE_CXX_FLAGS_RELEASE "/O2")
else()
    # GCC/Clang compiler flags
    set(CMAKE_CXX_FLAGS "-Wall -Wextra")
    set(CMAKE_CXX_FLAGS_DEBUG "-g")
    set(CMAKE_CXX_FLAGS_RELEASE "-O3")
endif()

3. Modify eigenmvn.h

The file include/libcmaes/eigenmvn.h needs to be modified to properly handle std::normal_distribution with MSVC. Locate the scalar_normal_dist_op class and replace it with the following implementation:

    template<typename Scalar>
      class scalar_normal_dist_op
      {
private:
    void swap(scalar_normal_dist_op &other) {
      std::swap(rng, other.rng);
      std::swap(norm, other.norm);
    }
public:
	static std::mt19937 rng;                        // The uniform pseudo-random algorithm
	mutable std::normal_distribution<Scalar> norm; // gaussian combinator
	
    scalar_normal_dist_op() : norm(Scalar(0), Scalar(1)) {}

    scalar_normal_dist_op(const scalar_normal_dist_op& other)
        : norm(other.norm) {
    }

    scalar_normal_dist_op& operator=(const scalar_normal_dist_op& other) {
        if (this != &other) {
            norm = other.norm;
        }
        return *this;
    }

    scalar_normal_dist_op(scalar_normal_dist_op&& other) noexcept
        : norm(std::move(other.norm)) {
    }

    scalar_normal_dist_op& operator=(scalar_normal_dist_op&& other) noexcept {
        if (this != &other) {
            norm = std::move(other.norm);
        }
        return *this;
    }

	template<typename Index>
	inline const Scalar operator() (Index, Index = 0) const { return norm(rng); }
	inline void seed(const uint64_t &s) { rng.seed(s); }
      };

    template<typename Scalar>
      std::mt19937 scalar_normal_dist_op<Scalar>::rng;
      
    template<typename Scalar>
      struct functor_traits<scalar_normal_dist_op<Scalar> >
      { enum { Cost = 50 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = false }; };
    

4. Build the Library

Now you can build the library:

# Create and enter build directory
mkdir build
cd build

# Configure with CMake
cmake .. -DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake -DLIBCMAES_BUILD_TESTS=OFF -DLIBCMAES_BUILD_PYTHON=OFF -DLIBCMAES_USE_OPENMP=OFF -G "Visual Studio 17 2022" -A x64

# Build the library
cmake --build . --config Release

Replace [path to vcpkg] with your actual vcpkg installation path.

Key Changes Summary

  1. Compiler Flags: Added MSVC-specific compiler flags in CMakeLists.txt to handle the -Wextra flag issue.

  2. Dependencies: Used vcpkg for managing dependencies (eigen3, glog, gflags) instead of manual installation.

  3. MSVC Compatibility: Modified the scalar_normal_dist_op class in eigenmvn.h to:

    • Add proper constructors and assignment operators
    • Handle std::normal_distribution correctly
    • Ensure compatibility with MSVC's requirements

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions