xmake-io / xmake

🔥 A cross-platform build utility based on Lua
https://xmake.io
Apache License 2.0
10.08k stars 784 forks source link

使用了C++20 module的项目生成的CMakeLists.txt不正确 #5765

Open hghgthifg opened 1 week ago

hghgthifg commented 1 week ago

Xmake 版本

v2.9.5+HEAD.d30de52e9

操作系统版本和架构

Windows11 version 23H2

描述问题

src/main.cpp:

import Vec3;
import std;

int main(int argc, char** argv)
{
    auto point3 = vec3{0, 0, 0};

    int image_width = 256;
    int image_height = 256;

    std::cout << "P3\n"
              << image_width << " " << image_height << "\n255\n";

    for (int j = 0; j < image_height; j++) {
        std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush;
        for (int i = 0; i < image_width; i++) {
            auto r = double(i) / double(image_width - 1);
            auto g = double(j) / double(image_height - 1);
            auto b = 0.0;

            int ir = int(255.999 * r);
            int ig = int(255.999 * g);
            int ib = int(255.999 * b);

            std::cout << ir << " " << ig << " " << ib << "\n";
        }
    }

    std::clog << "\rDone.                  \n";

    return 0;
}

src/vec3.cppm:

export module Vec3;
import std;

export class vec3
{
public:
    double e[3];

    vec3() : e{0, 0, 0} {}
    vec3(double e0, double e1, double e2) : e{e0, e1, e2} {}

    double x() const { return e[0]; }
    double y() const { return e[1]; }
    double z() const { return e[2]; }

    vec3 operator-() const { return vec3(-e[0], -e[1], -e[2]); }
    double operator[](int i) const { return e[i]; }
    double& operator[](int i) { return e[i]; }

    vec3& operator+=(const vec3& v)
    {
        e[0] += v.e[0];
        e[1] += v.e[1];
        e[2] += v.e[2];
        return *this;
    }

    vec3& operator*=(double t)
    {
        e[0] *= t;
        e[1] *= t;
        e[2] *= t;
        return *this;
    }

    vec3& operator/=(double t) { return *this *= 1 / t; }

    double length() const { return std::sqrt(length_squared()); }

    double length_squared() const
    {
        return e[0] * e[0] + e[1] * e[1] + e[2] * e[2];
    }
};

// point3 is just an alias for vec3, but useful for geometric clarity in the
// code.
export using point3 = vec3;

// Vector Utility Functions

export inline std::ostream& operator<<(std::ostream& out, const vec3& v)
{
    return out << v.e[0] << ' ' << v.e[1] << ' ' << v.e[2];
}

export inline vec3 operator+(const vec3& u, const vec3& v)
{
    return vec3(u.e[0] + v.e[0], u.e[1] + v.e[1], u.e[2] + v.e[2]);
}

export inline vec3 operator-(const vec3& u, const vec3& v)
{
    return vec3(u.e[0] - v.e[0], u.e[1] - v.e[1], u.e[2] - v.e[2]);
}

export inline vec3 operator*(const vec3& u, const vec3& v)
{
    return vec3(u.e[0] * v.e[0], u.e[1] * v.e[1], u.e[2] * v.e[2]);
}

export inline vec3 operator*(double t, const vec3& v)
{
    return vec3(t * v.e[0], t * v.e[1], t * v.e[2]);
}

export inline vec3 operator*(const vec3& v, double t) { return t * v; }

export inline vec3 operator/(const vec3& v, double t) { return (1 / t) * v; }

export inline double dot(const vec3& u, const vec3& v)
{
    return u.e[0] * v.e[0] + u.e[1] * v.e[1] + u.e[2] * v.e[2];
}

export inline vec3 cross(const vec3& u, const vec3& v)
{
    return vec3(u.e[1] * v.e[2] - u.e[2] * v.e[1],
                u.e[2] * v.e[0] - u.e[0] * v.e[2],
                u.e[0] * v.e[1] - u.e[1] * v.e[0]);
}

export inline vec3 unit_vector(const vec3& v) { return v / v.length(); }

xmake.lua:

add_rules("mode.debug", "mode.release")
set_policy("build.c++.modules", true)

set_languages("c++23")

target("RayTracing")
    set_kind("binary")
    add_files("src/*.cpp")
    add_files("src/*.cppm")

直接使用 xmake 进行构建是正常的,但是生成的 CMakeLists.txt 无法正常使用。

CMakeLists.txt:

# this is the build file for project 
# it is autogenerated by the xmake build system.
# do not edit by hand.

# project
cmake_minimum_required(VERSION 3.28.0)
cmake_policy(SET CMP0091 NEW)
project(RayTracing LANGUAGES CXX)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)

# target
add_executable(RayTracing "")
set_target_properties(RayTracing PROPERTIES OUTPUT_NAME "RayTracing")
set_target_properties(RayTracing PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/windows/x64/debug")
if(MSVC)
    target_compile_options(RayTracing PRIVATE /EHsc)
elseif(Clang)
    target_compile_options(RayTracing PRIVATE -fexceptions)
    target_compile_options(RayTracing PRIVATE -fcxx-exceptions)
elseif(Gcc)
    target_compile_options(RayTracing PRIVATE -fexceptions)
endif()
set_target_properties(RayTracing PROPERTIES CXX_EXTENSIONS OFF)
target_compile_features(RayTracing PRIVATE cxx_std_23)
if(MSVC)
    target_compile_options(RayTracing PRIVATE $<$<CONFIG:Debug>:-Od>)
else()
    target_compile_options(RayTracing PRIVATE -O0)
endif()
if(MSVC)
    target_compile_options(RayTracing PRIVATE -Zi)
else()
    target_compile_options(RayTracing PRIVATE -g)
endif()
if(MSVC)
    set_property(TARGET RayTracing PROPERTY
        MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
target_sources(RayTracing PRIVATE
    src/main.cpp
    src/Vec3.cppm
)

CMake 构建得到的报错:

CMake Error: Output CMakeFiles\RayTracing.dir\src\Vec3.cppm.obj provides the `Vec3` module but it is not found in a `FILE_SET` of type `CXX_MODULES`
ninja: build stopped: subcommand failed.

期待的结果

期待生成的 CMakeLists.txt 能和用 xmake 一样成功构建

工程配置

add_rules("mode.debug", "mode.release")
set_policy("build.c++.modules", true)

set_languages("c++23")

target("RayTracing")
    set_kind("binary")
    add_files("src/*.cpp")
    add_files("src/*.cppm")

附加信息和错误日志

CMake 构建得到的报错:

CMake Error: Output CMakeFiles\RayTracing.dir\src\Vec3.cppm.obj provides the `Vec3` module but it is not found in a `FILE_SET` of type `CXX_MODULES`
ninja: build stopped: subcommand failed.
Issues-translate-bot commented 1 week ago

Bot detected the issue body's language is not English, translate it automatically.


Title: The CMakeLists.txt generated by projects using the C++20 module is incorrect

waruqi commented 1 week ago

你可以先自己调下 cmakelists.txt 看下哪里不对,xmake 能编译,不代表 cmake 一定也能很好支持 c++ modules。

Issues-translate-bot commented 1 week ago

Bot detected the issue body's language is not English, translate it automatically.


You can first adjust cmakelists.txt yourself to see what is wrong. If xmake can compile, it does not mean that cmake can also support c++ modules well.

Tomcat-42 commented 1 week ago

Actually CMake support modules (with one exception, header units). But you should add sources like the following:

target_sources(foo
  PUBLIC
    FILE_SET CXX_MODULES FILES
      foo.cxx
)

Note the FILE_SET CXX_MODULES FILES annotation. This should be rather easy to implement in the XMake side.

Sources:

https://www.kitware.com/import-cmake-the-experiment-is-over/ https://www.kitware.com/import-std-in-cmake-3-30/

waruqi commented 1 week ago

Note the FILE_SET CXX_MODULES FILES annotation. This should be rather easy to implement in the XMake side.

You can try add it in generated CMakeLists.txt manually. Does it work?

I think cmake is able to automatically recognize and support .cppm files for compiling as modules. It works for me.

Only non-module file suffixes (.cxx) need to be set CXX_MODULES file type explicitly.