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

Use <mpark/variant.hpp> indiscriminately #1121

Closed
wants to merge 1 commit into from

Conversation

franzpoeschel
Copy link
Contributor

Our header include/openPMD/auxiliary/VariantSrc.hpp currently inspects the C++ version with a macro and uses either std::variant or mpark::variant depending on the found version. In a public header, that can lead to trouble if the user code uses a different C++ version compared to openPMD-api.

Bug can be reproduced with the following writer:

cmake_minimum_required(VERSION 3.14.0)
set(CMAKE_CXX_STANDARD 17)

project(openpmd_debug)

find_package(openPMD REQUIRED)

add_executable(openpmd_write openpmd_write.cpp)

target_link_libraries(openpmd_write PRIVATE openPMD::openPMD adios2::cxx11)
#include <openPMD/openPMD.hpp>

// example: data handling
#include <numeric>  // std::iota
#include <vector>   // std::vector

/**@file test example for writing histogram woth openPMD-api from c++ code
  *
  */

int main(){
    /// open
    auto series = openPMD::Series(
        "myOutput/data_%05T.bp",
        openPMD::Access::CREATE);

    /// open iteration
    auto iteration = series.iterations[42];

    constexpr int xExtent = 1;
    constexpr int yExtent = 2;
    constexpr int maxNumBins = 3;

    openPMD::Extent extent = {xExtent, yExtent, maxNumBins};

    /// create test data
    // set up is xExtent x yExtent grid points and for each grid point a histogram with maxNumBins bins
    std::vector<float> x_data(
        xExtent * yExtent * maxNumBins);

    x_data = {1., 2., 3., 4., 5., 6.}; // by convention x is fastest changing index

    // create a new record for mesh
    auto histogramMesh = iteration.meshes["adaptiveHistogram"];

    // create 1 record component each corresponding to one single entry n histogram
    auto entry = histogramMesh[openPMD::MeshRecordComponent::SCALAR];

    ///create new dataset, description of how data is to be stored
    openPMD::Datatype dataType = openPMD::determineDatatype<float>();
    openPMD::Dataset dataSet = openPMD::Dataset(dataType, extent);

    /// set what records actually store(what record components actually are)
    entry.resetDataset(dataSet);

    /// actual data is passed
    entry.storeChunk(
        x_data,
        {0, 0, 0}, // offset
        extent); // extent, artificially inflated

    /// actual write happens
    series.flush();

    // destruct series object,
    // e.g. when out-of-scope

    return 0;
}

@ax3l
Copy link
Member

ax3l commented Oct 11, 2021

I think we might want to store the mpark-variant choice used at openPMD-api compile time in our Config.hpp and then base our chose on that.

@franzpoeschel
Copy link
Contributor Author

franzpoeschel commented Oct 12, 2021

I think we might want to store the mpark-variant choice used at openPMD-api compile time in our Config.hpp and then base our chose on that.

This PR is only going to be a workaround until we switch to C++17 and can use std::optional instead of mpark::optional entirely. So I'm not sure it's worth the effort for that?

@ax3l
Copy link
Member

ax3l commented Oct 16, 2021

The problem is that our variant is part of the public API, thus it needs to be installed as well.
If we want to make this non-optional, we need to also change the CMake logic that installs mpark-variant currently only conditionally in the default super-build.

@ax3l
Copy link
Member

ax3l commented Oct 16, 2021

Just for the record: For the reproducer above: which compiler did you use and what's the error message?

@franzpoeschel
Copy link
Contributor Author

Just for the record: For the reproducer above: which compiler did you use and what's the error message?

I tried this with several compilers, and with different results:

My guess is that mpark::optional and std::optional have different ABI layouts, leading to wrongly interpreted values

The problem is that our variant is part of the public API, thus it needs to be installed as well.

Ok, so memorizing the chosen version with config.hpp could actually be the simpler solution

@ax3l
Copy link
Member

ax3l commented Oct 18, 2021 via email

@franzpoeschel
Copy link
Contributor Author

Is there even a way to use configure_file for writing the used C++ standard level to config.hpp? I did not find an obvious way.

If we want to make this non-optional, we need to also change the CMake logic that installs mpark-variant currently only conditionally in the default super-build.

I think that's currently only a todo, mpark is always linked to our built library and either installed from our shipped version or linked from an already-installed version from the system:

# C++11 std::variant (C++17 stdlib preview)
# TODO not needed with C++17 compiler
add_library(openPMD::thirdparty::mpark_variant INTERFACE IMPORTED)
set(openPMD_PC_EXTRA_INCLUDE "")
if(openPMD_USE_INTERNAL_VARIANT)
    target_include_directories(openPMD::thirdparty::mpark_variant SYSTEM INTERFACE
        $<BUILD_INTERFACE:${openPMD_SOURCE_DIR}/share/openPMD/thirdParty/variant/include>
    )
    message(STATUS "MPark.Variant: Using INTERNAL version '1.4.0'")
else()
    find_package(mpark_variant 1.3.0 REQUIRED) # TODO: we want 1.4.1+
    target_link_libraries(openPMD::thirdparty::mpark_variant
        INTERFACE mpark_variant)
    get_target_property(EXTERNAL_MPARK_INCLUDE mpark_variant INTERFACE_INCLUDE_DIRECTORIES)
    if(openPMD_HAVE_PKGCONFIG AND EXTERNAL_MPARK_INCLUDE)
        set(openPMD_PC_EXTRA_INCLUDE "-I${EXTERNAL_MPARK_INCLUDE}")
    endif()
    message(STATUS "MPark.Variant: Found version '${mpark_variant_VERSION}'")
endif()
target_link_libraries(openPMD PUBLIC openPMD::thirdparty::mpark_variant)

@ax3l ax3l self-requested a review October 18, 2021 23:36
@ax3l ax3l self-assigned this Oct 18, 2021
@ax3l
Copy link
Member

ax3l commented Oct 19, 2021

I'll propose something based on try_compile https://cmake.org/cmake/help/latest/command/try_compile.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants