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

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

Open
hghgthifg opened this issue Oct 25, 2024 · 8 comments
Open

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

hghgthifg opened this issue Oct 25, 2024 · 8 comments
Labels

Comments

@hghgthifg
Copy link

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.
@hghgthifg hghgthifg added the bug label Oct 25, 2024
@Issues-translate-bot
Copy link

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
Copy link
Member

waruqi commented Oct 25, 2024

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

@Issues-translate-bot
Copy link

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
Copy link

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
Copy link
Member

waruqi commented Oct 28, 2024

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.

@whisper-bye
Copy link

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.

在我的环境下 windows + cmake 3.31.0 并使用 cppm 后缀无效,还是需要显式添加 PRIVATE FILE_SET CXX_MODULES FILES

@Chupakabra0
Copy link

Chupakabra0 commented Dec 4, 2024

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

I can confirm that this works for me only if I add to CMakeLists.txt:

target_sources(
    ${TARGET_NAME}
    PRIVATE Source.cpp
    PRIVATE FILE_SET cppHeaders TYPE HEADERS FILES Header.hpp
    PRIVATE FILE_SET cppModules TYPE CXX_MODULES FILES Module.cppm
)

I use cmake version 3.30.3

@Chupakabra0
Copy link

Chupakabra0 commented Dec 5, 2024

Also have to mention: if you wanna use import std; you must make more additions to CMakeLists.txt by yourself:

xmake.lua:

set_project("TestModules")
set_languages("c23", "c++23")
set_version("1.0.0")

add_rules("mode.debug", "mode.release")
set_policy("compatibility.version", "3.0")
set_warnings("all", "error")

if is_mode("debug") then
    set_symbols("debug")
    set_optimize("none")
else
    set_symbols("hidden")
    set_optimize("fastest")
    set_strip("all")
end

target("TestModules")
    set_kind("binary")
    add_files("Source.cpp", "Vec3.cppm")

CMakeLists.txt:

cmake_minimum_required(VERSION 3.28.0)
cmake_policy(SET CMP0091 NEW)
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") # for import std
project(TestModules VERSION 1.0.0 LANGUAGES CXX)
# set(CMAKE_CXX_SCAN_FOR_MODULES ON) works for me without this line
set(CMAKE_CXX_MODULE_STD ON) # for import std

# target
add_executable(TestModules "")
set_target_properties(TestModules PROPERTIES OUTPUT_NAME "TestModules")
set_target_properties(TestModules PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/build/windows/x64/debug")
if(MSVC)
    target_compile_options(TestModules PRIVATE -W3)
    target_compile_options(TestModules PRIVATE -WX)
elseif(Clang)
    target_compile_options(TestModules PRIVATE -Wall)
    target_compile_options(TestModules PRIVATE -Werror)
elseif(Gcc)
    target_compile_options(TestModules PRIVATE -Wall)
    target_compile_options(TestModules PRIVATE -Werror)
endif()
if(MSVC)
    target_compile_options(TestModules PRIVATE /EHsc)
elseif(Clang)
    target_compile_options(TestModules PRIVATE -fexceptions)
    target_compile_options(TestModules PRIVATE -fcxx-exceptions)
elseif(Gcc)
    target_compile_options(TestModules PRIVATE -fexceptions)
endif()
set_target_properties(TestModules PROPERTIES C_EXTENSIONS OFF)
target_compile_features(TestModules PRIVATE c_std_23)
set_target_properties(TestModules PROPERTIES CXX_EXTENSIONS OFF)
target_compile_features(TestModules PRIVATE cxx_std_23)
if(MSVC)
    target_compile_options(TestModules PRIVATE $<$<CONFIG:Debug>:-Od>)
else()
    target_compile_options(TestModules PRIVATE -O0)
endif()
if(MSVC)
    target_compile_options(TestModules PRIVATE -Zi)
else()
    target_compile_options(TestModules PRIVATE -g)
endif()
if(MSVC)
    set_property(TARGET TestModules PROPERTY
        MSVC_RUNTIME_LIBRARY "MultiThreadedDebugDLL")
endif()
target_sources(
    TestModules
    PRIVATE Source.cpp
    PRIVATE FILE_SET cppModules TYPE CXX_MODULES FILES Vec3.cppm
) # changed for CMake able to build C++20 modules support

Code of Source.cpp and Vec3.cppm same as @hghgthifg has. Tested this for the newest version of CMake 3.31.1. Works the same way like in 3.30.3.

If you use this CMakeLists.txt, you may encounter a warning after reloading the project. However, everything should work correctly, at least with the latest version of MSVC.

CMake Warning (dev) at C:/Program Files/CMake/share/cmake-3.31/Modules/Compiler/CMakeCommonCompilerMacros.cmake:248 (cmake_language):
  CMake's support for `import std;` in C++23 and newer is experimental.  It
  is meant only for experimentation and feedback to CMake developers.
Call Stack (most recent call first):
  C:/Program Files/CMake/share/cmake-3.31/Modules/CMakeDetermineCompilerSupport.cmake:113 (cmake_create_cxx_import_std)
  C:/Program Files/CMake/share/cmake-3.31/Modules/CMakeTestCXXCompiler.cmake:83 (CMAKE_DETERMINE_COMPILER_SUPPORT)
  CMakeLists.txt:9 (project)
This warning is for project developers.  Use -Wno-dev to suppress it.

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

No branches or pull requests

6 participants