VS2019 C++20的module
-
- 01 module一些資料
- 02 vs2019中關于module的配置
-
- 02.01 安裝配置
- 02.02 項目配置
- 03 測試項目
01 module一些資料
對于大型項目,include頭檔案的方式會嚴重影響編譯性能。比如類似chromium的開源項目。module是一個工程化特性,頭檔案中的資訊現在分成導出的部分和不導出的部分,可以有效減少實作細節影響的範圍,帶來一個非常有用的特性——重新編譯速度變快。
module是很早就被提及的概念,微軟在vs2015中就開始部分支援,參考VS 2015 Update 1中C++Modules;在vs2017中的支援更進一步,參考在Visual Studio 2017 中使用C++ Modules。
參考資料:
- github上有代碼,有文檔較詳細的資料
- cppreference.com的子產品 (C++20 起):
- 在Visual Studio 2017中使用C ++子產品
- 使用Visual Studio 2017 C++17子產品(module)特性
- C++ 中的子產品概述
- 子產品,導入,導出
02 vs2019中關于module的配置
02.01 安裝配置
vs2019 到2019年11月為止,隻在實驗功能中支援module。需要安裝實驗元件:
在vs2019的16.4.1中選擇 [使用C++的桌面開發] 中的 [用于v142生産工具的C++子產品(x64/x86-實驗性)]
如下圖所示:
02.02 項目配置
-
項目工程配置
vs2019中不需要(像vs2017中那樣)在
的C/C++
中配置指令行
/experimental:module /module:stdIfcDir "$(VCToolsInstallDir_150)ifc\$(PlatformTarget)
;
如果項目中使用了module功能,隻要再
的C/C++
中配置如下兩項即可:語言
=C++語言标準
/std:c++latest
=啟用C++子產品(實驗性)
/experimental:module
-
獨立子產品編譯配置
如果在項目中自己獨立使用子產品,需要使用指令行編譯。而且如果在子產品中引用了标準子產品,需要在指令行中指定
/module:stdIfcDir
。
編譯的相關指令行參數有:
:啟用C++子產品屬性/experimental:module
:C++語言标準/std:c++latest
:導出子產品/module:export
:指定标準庫子產品路徑/module:stdIfcDir
/MD|/MDd|/MT|/MTd
:運作時庫
還要注意平台屬性:即
最後把這個彙總到一個bat檔案中,把平台屬性和運作時庫做為bat檔案的參數,配置到配置屬性的x64|x86
–>生成事件
–>生成前事件
裡,如圖指令行
- 子產品編譯腳本樣例
@echo off
rem 這裡要根據你編譯的x86/x64;relase/debug選擇對應目錄下的cl.exe
rem set clcmd=D:\install\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\bin\Hostx64\x64\cl.exe
rem 在vs中自己會找到準确的cl.exe版本,不需要特别指定
set clcmd=cl.exe
rem 如果module中引用了标準庫,需要指定/module:stdIfcDir
rem /experimental:module /module:stdIfcDir "$(VCToolsInstallDir_160)ifc\$(PlatformTarget)"
rem $(VCToolsInstallDir_160)=D:\install\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\
rem $(PlatformTarget)=x64
set target=%1%
if "%target%"=="" set target=x64
@echo %target%
rem 根據自己的實際目錄設定
set stdIfcDir="D:\install\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\ifc\%target%"
rem 指定代碼生成的運作庫md mdd mt mtd(動态庫 動态調試庫 靜态庫 靜态調試庫)
rem 本bat的第一個參數指定是否是debug版本,如果是debug版本,第一個參數是 d
set rundll=%2%
if "%rundll%"=="" set rundll=MD
rem 顯示運作時庫參數
@echo %rundll%
set CFLAGS=/experimental:module /std:c++latest /EHsc /%rundll% /c /module:stdIfcDir %stdIfcDir% /module:export
rem cl.exe /experimental:module /std:c++latest /EHsc /MD /c /module:stdIfcDir "D:\install\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.24.28314\ifc\x64" /module:export module01.cpp
"%clcmd%" %CFLAGS% module01.cpp
rem "%clcmd%" %CFLAGS% 子產品檔案
"%clcmd%" %CFLAGS% hello.mpp hello.cpp
"%clcmd%" %CFLAGS% module02.cpp
-
/module:stdIfcDir參數确定方式
在項目屬性的
中的預處理器
裡檢視預處理器定義
$(VCToolsInstallDir_150)ifc\$(PlatformTarget)
03 測試項目
C++20的module在vs2019 16.4.1上面的測試
- module01.cpp
module module01;
// 在子產品中未使用基礎庫,極少數情況
// 編譯時,可以不指定/module:stdIfcDir
namespace module01 {
int test(int x)
{
return x * x;
}
}
- module02.cpp
module module02;
// 在子產品中未使用基礎庫,極少數情況
// 編譯時,必須指定/module:stdIfcDir
import std.core;
using namespace std;
namespace module02 {
void say(const char* str) {
cout << str << endl;
}
}
- hello.mpp
#pragma once
// 子產品接口單元(module interface unit),類似于頭檔案
export module hello;
namespace hello {
void say_hi();
}
export namespace hello {
void say_hello();
void say_xz();
}
- hello.cpp
// 子產品實作單元(module implementation unit)
module hello;
// 在子產品中使用import标準子產品,需要在編譯語句中指定/module:stdIfcDir 參數
import std.core;
using namespace std;
namespace hello {
void say_hi() {
cout << "hello hi!" << endl;
}
void say_hello() {
cout << "hello world!" << endl;
}
void say_xz() {
cout << "hello xz!" << endl;
}
}
- module.cpp
import std.core; // 使用标準導入子產品
import module01; // 導入自定義子產品
import hello;
import module02;
using namespace module01; // 使用自定義子產品的命名空間
// 使用标準導入子產品(import std.core;)
void use_standard_import_module() {
std::cout << "hello world! use_standard_import_module" << std::endl;
}
int main(int argc, char** argv)
{
use_standard_import_module();
// 直接使用子產品中的函數名
std::cout << "module01::test(100) = " << test(100) << std::endl;
hello::say_hello();
hello::say_xz();
hello::say_hi();
module02::say("module02::say!");
return 0;
}
運作結果:
這裡隻測試了 https://github.com/mutouyun/cncppcon2018-cppmodules/blob/master/About-Cpp-Modules.md 中介紹的2.1/2.2/2.3;2.4/2.5/2.6沒有測試通過。
2.4 Module Partitions vs2019應該還不支援;
2.5 Global Module Fragment
2.6 Legacy Header Unit