MSVC工具链
一、MSVC工具链有哪些工具
MSVC(Microsoft Visual C++)工具链是用于开发C++应用程序的综合工具集。它包含了多种工具和组件,帮助开发者编写、编译、调试和优化C++代码。以下是MSVC工具链的一些主要组成部分:
1. 编译器(Compiler):
-cl.exe:MSVC的C/C++编译器,负责将源代码编译成目标代码(对象文件)。
2. 链接器(Linker):
- link.exe:负责将编译生成的对象文件和库文件链接成可执行文件或动态链接库(DLL)。
3. 调试器(Debugger):
- devenv.exe(Visual Studio IDE):集成开发环境,提供图形化的调试界面。
- cdb.exe、ntsd.exe、windbg.exe:命令行调试工具和高级调试器。
4. 库(Libraries):
- 标准库(Standard Library):包括C标准库和C++标准库(如STL)。
- MFC(Microsoft Foundation Classes):用于Windows应用程序开发的类库。
- ATL(Active Template Library):用于COM开发的模板库。
5. 构建工具(Build Tools):
- msbuild.exe:Microsoft Build Engine,用于构建项目和解决方案。
- nmake.exe:MSVC的命令行构建工具,类似于Unix的make。
6. 集成开发环境(IDE):
- Visual Studio:提供图形化的代码编辑、项目管理、调试和其他开发工具。
7. 分析工具(Analysis Tools):
- 静态分析工具:用于在编译时检测代码中的潜在错误和问题。
- 性能分析工具(Profiler):用于分析应用程序的性能瓶颈。
8. 包管理器(Package Manager):
- vcpkg:用于管理和安装C++库的包管理工具。
9. 代码生成工具(Code Generation Tools:
- midl.exe:用于生成COM接口的Microsoft Interface Definition Language编译器。
10. 其他辅助工具:
- editbin.exe:用于编辑可执行文件或对象文件的工具。
- dumpbin.exe:用于查看二进制文件内容的工具。
这些工具和组件共同组成了MSVC工具链,帮助开发者高效地开发、调试和部署C++应用程序。
二、MSVC 路径
MSVC 的路径因您安装的 Visual Studio 版本和安装位置而异。但是,通常可以在以下位置找到 MSVC:默认安装:
32 位系统:`C:\Program Files (x86)\Microsoft Visual Studio\20XX\VC\Tools`
64 位系统:`C:\Program Files\Microsoft Visual Studio\20XX\VC\Tools`
自定义安装:
查看 Visual Studio 安装程序中的“修改”选项卡,找到 MSVC 的安装路径。
MSVC 命令行
MSVC 命令行工具包括:
cl.exe:C++ 编译器
link.exe:链接器
lib.exe:库管理器
dumpbin.exe:二进制文件转储工具
cvtres.exe:**资源编译器
这些工具位于 MSVC 安装目录的 `bin` 子目录中。
示例命令行:
*编译源文件 main.cpp:
* cl.exe main.cpp
* 链接目标文件 `main.obj` 创建可执行文件 `main.exe`:
* link.exe main.obj
* 创建静态库 mylib.lib 从对象文件 obj1.obj和 obj2.obj:
* lib.exe /OUT:mylib.lib obj1.obj obj2.obj
* 转储可执行文件 `main.exe` 的符号信息:
* dumpbin.exe /SYMBOLS main.exe
* 编译资源文件 `resource.rc:
* cvtres.exe resource.rc
有关 MSVC 命令行工具的更多信息,请参阅 Microsoft 文档:https://docs.microsoft.com/en-us/cpp/build/reference/cl-compiler-options?view=msvc-170
三、MSVC项目使用MSBuild编译
是的,MSVC(Microsoft Visual C++)项目可以使用 MSBuild(Microsoft Build Engine)进行编译。MSBuild 是 Microsoft 提供的一个构建平台,能够构建各种类型的项目,包括 MSVC 项目。
编译过程概述
1. 准备环境:确保你已经安装了 Visual Studio 和相关的构建工具。
2. 打开开发者命令行:使用 Visual Studio 提供的“Developer Command Prompt”或“x64 Native Tools Command Prompt”来确保所有必要的环境变量都已设置。
3. 定位项目文件**:找到你的 `.vcxproj` 文件,这是 MSVC 项目的核心文件,包含了项目的配置信息。
4. 运行 MSBuild:使用 `msbuild` 命令来编译项目。
具体步骤
1. 打开开发者命令行
打开“Start”菜单,找到 Visual Studio 文件夹,然后选择“Developer Command Prompt for VS YYYY”或“x64 Native Tools Command Prompt for VS YYYY”,其中 `YYYY` 是你的 Visual Studio 版本年份。
2. 定位项目文件
假设你的项目文件路径为 `C:\Path\To\Your\Project\YourProject.vcxproj`。
3. 运行 MSBuild
在命令行中,使用以下命令来编译项目:
bash
msbuild C:\Path\To\Your\Project\YourProject.vcxproj
4. 指定配置和平台(可选)
你可以通过传递参数来指定编译配置(如 `Debug` 或 `Release`)和平台(如 `x86` 或 `x64`)。例如:
bash
msbuild C:\Path\To\Your\Project\YourProject.vcxproj /p:Configuration=Release /p:Platform=x64
示例
假设你的项目文件路径为 `C:\Projects\MyApp\MyApp.vcxproj`,并且你想使用 `Release` 配置和 `x64` 平台进行编译,命令行命令如下:
bash
msbuild C:\Projects\MyApp\MyApp.vcxproj /p:Configuration=Release /p:Platform=x64
常见参数
- /t:Rebuild:重建项目。
- /t:Clean:清理项目。
- /m:并行编译,加快编译速度。
- /verbosity:level:设置输出详细程度(如 `quiet`、`minimal`、`normal`、`detailed`、`diagnostic`)。
示例:并行编译并设置详细输出
bash
msbuild C:\Projects\MyApp\MyApp.vcxproj /p:Configuration=Release /p:Platform=x64 /m /verbosity:detailed
总结
使用 MSBuild 编译 MSVC 项目是一个非常灵活和强大的方法,特别适合自动化构建流程。通过正确设置命令行参数,你可以轻松地控制编译过程,满足各种构建需求。
四、MSVC项目中各文件详解
在 MSVC(Microsoft Visual C++)项目中,项目文件和配置文件的结构和内容对于理解和管理项目至关重要。以下是 MSVC 项目中常见文件及其详细说明:
1. .sln文件(Solution 文件)
用途:解决方案文件包含一个或多个项目的集合,定义了这些项目之间的关系和构建顺序。
内容:文本文件,包含解决方案的配置信息和项目列表。例如:
plaintext Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28729.10 MinimumVisualStudioVersion = 10.0.40219.1 Project("{GUID}") = "MyApp", "MyApp\MyApp.vcxproj", "{PROJECT_GUID}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {PROJECT_GUID}.Debug|x64.ActiveCfg = Debug|x64 {PROJECT_GUID}.Debug|x64.Build.0 = Debug|x64 {PROJECT_GUID}.Release|x64.ActiveCfg = Release|x64 {PROJECT_GUID}.Release|x64.Build.0 = Release|x64 EndGlobalSection EndGlobal
2. .vcxproj`文件(项目文件)
用途:项目文件包含单个项目的配置信息,包括源文件、头文件、编译选项、链接选项等。
内容:XML 文件,定义了项目的详细构建信息。例如:
xml
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|x64"> <Configuration>Debug</Configuration> <Platform>x64</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|x64"> <Configuration>Release</Configuration> <Platform>x64</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{PROJECT_GUID}</ProjectGuid> <RootNamespace>MyApp</RootNamespace> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v142</PlatformToolset> <CharacterSet>Unicode</CharacterSet> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <UseDebugLibraries>false</UseDebugLibraries> <PlatformToolset>v142</PlatformToolset> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>Unicode</CharacterSet> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ItemGroup> <ClCompile Include="main.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="stdafx.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> </Project>
3. .vcxproj.filters 文件
用途:定义项目中的文件在解决方案资源管理器中的分组和过滤器。
内容:XML 文件,包含文件分组信息。例如:
xml
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <ClInclude Include="stdafx.h"> <Filter>Header Files</Filter> </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="main.cpp"> <Filter>Source Files</Filter> </ClCompile> </ItemGroup> </Project>
4. `stdafx.h` 和 `stdafx.cpp`
用途:预编译头文件,用于加快编译速度。
内容:stdafx.h 通常包含项目中常用的头文件,而 stdafx.cpp 则包含 stdafx.h 的实现。例如:
stdafx.h:
cpp
#pragma once #include <iostream> #include <vector> #include <string>
`stdafx.cpp`:
#include "stdafx.h"
5. main.cpp(或其他源文件)
用途:包含项目的实际源代码。
内容:C++ 源文件,包含项目的主要逻辑。例如:
cpp
#include "stdafx.h" int main() { std::cout << "Hello, World!" << std::endl; return 0; }
6. 其他文件
- 资源文件(.rc):包含资源定义,如图标、菜单等。
- 配置文件(如 `app.config` 或 `settings.json`):用于定义应用程序的配置。
- 头文件(.h:声明函数、类和其他符号。
- 库文件(.lib:静态库文件。
- 动态链接库(.dll):动态库文件。
总结
MSVC 项目文件结构包含了从解决方案文件(`.sln`)到项目文件(`.vcxproj`)以及各种源文件和头文件的详细信息。理解这些文件的用途和内容有助于有效地管理和构建项目。
五、如何使用virsual studio的到出库模板
1、新建项目
选择 新建项目->动态链接库(DLL)(c++ windows 库 这些选项下的模板)->命名为myshare
创建后,内部会自动创建四个文件
framework.h
pch.h
dllmain.cpp
pch.cpp
在 Microsoft Visual C++ (MSVC) 项目中,framework.h
文件通常是一个预编译头文件(Precompiled Header,PCH)。预编译头文件是一种优化技术,用于加快编译速度。通过将不常更改的头文件和库文件预先编译成一个单独的文件,编译器可以避免在每次编译时重复处理这些文件,从而提高编译效率。
在 MSVC 项目中,framework.h
文件的具体作用包括以下几个方面:
-
包含常用头文件:
framework.h
通常会包含项目中频繁使用的标准库和第三方库的头文件。例如,Windows API 相关的头文件、C++ 标准库头文件等。// framework.h #pragma once #include <windows.h> #include <iostream> #include <vector>
-
定义项目范围的宏和常量:
这个文件可以用来定义一些在整个项目中都会用到的宏、常量和类型。// framework.h #pragma once #define PROJECT_NAME "MyProject" const int MAX_BUFFER_SIZE = 1024;
-
减少编译时间:
通过将不常更改的头文件放入framework.h
并将其设为预编译头文件,编译器在处理项目中的多个源文件时,可以显著减少重复解析头文件的时间。 -
统一项目设置:
通过在framework.h
中设置一些全局的编译选项或定义,可以确保整个项目的一致性。例如,可以在framework.h
中设置_CRT_SECURE_NO_WARNINGS
以抑制安全函数的警告。
在 MSVC 项目中,通常会有一个对应的 framework.cpp
文件来实现预编译头文件的功能:
// framework.cpp #include "framework.h"
在项目的属性设置中,可以将 framework.cpp
配置为生成预编译头文件,而其他源文件则配置为使用该预编译头文件。
总结来说,framework.h
在 MSVC 项目中主要用于包含常用头文件、定义全局宏和常量,并通过预编译头文件机制加快编译速度。
在 Windows 下开发动态链接库(DLL)时,dllmain.cpp
文件通常包含 DLL 的入口函数 DllMain
。这个函数是在 DLL 被加载、卸载或线程附加/分离时调用的。DllMain
是一个可选的函数,但如果你需要在这些事件发生时执行特定的初始化或清理操作,定义它是非常有用的。
DllMain
函数的作用
DllMain
函数的签名如下:
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // 当 DLL 被加载到进程地址空间时执行的代码 break; case DLL_THREAD_ATTACH: // 当进程中的一个新线程被创建时执行的代码 break; case DLL_THREAD_DETACH: // 当进程中的一个线程退出时执行的代码 break; case DLL_PROCESS_DETACH: // 当 DLL 被卸载或进程终止时执行的代码 break; } return TRUE; }
各个事件的解释
- DLL_PROCESS_ATTACH: 当 DLL 被加载到进程的地址空间时调用。通常在这里进行一次性的初始化操作。
- DLL_THREAD_ATTACH: 当进程中的一个新线程被创建时调用。通常在这里进行与线程相关的初始化操作。
- DLL_THREAD_DETACH: 当进程中的一个线程退出时调用。通常在这里进行与线程相关的清理操作。
- DLL_PROCESS_DETACH: 当 DLL 被卸载或进程终止时调用。通常在这里进行清理操作。
示例代码
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include <windows.h> BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // DLL 被加载时执行的代码 break; case DLL_THREAD_ATTACH: // 新线程被创建时执行的代码 break; case DLL_THREAD_DETACH: // 线程退出时执行的代码 break; case DLL_PROCESS_DETACH: // DLL 被卸载时执行的代码 break; } return TRUE; }
使用方法
-
创建 DLL 项目:
在 Visual Studio 中,创建一个新的 DLL 项目。可以选择 "Dynamic-Link Library (DLL)" 模板。 -
添加
dllmain.cpp
文件:
在项目中添加一个新的 C++ 文件,命名为dllmain.cpp
,并将上述代码粘贴进去。 -
编译项目:
编译项目会生成一个.dll
文件和一个.lib
文件。.dll
文件是动态链接库,.lib
文件是导入库,用于在其他项目中链接 DLL。 -
在其他项目中使用 DLL:
- 将生成的
.dll
文件放置在目标应用程序的可执行文件所在目录,或者将其路径添加到系统的环境变量中。 - 在目标应用程序的项目设置中,添加生成的
.lib
文件到链接器输入中。 - 在代码中包含相应的头文件,并使用
__declspec(dllimport)
声明要使用的 DLL 中的函数和变量。
- 将生成的
例如:
// example.h #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif extern "C" MYDLL_API void MyFunction();
在 DLL 项目中定义 MyFunction
:
#include "example.h" #include <iostream> void MyFunction() { std::cout << "Hello from DLL!" << std::endl; }
在使用 DLL 的项目中:
#include "example.h" int main() { MyFunction(); return 0; }
通过这种方式,你可以在不同的项目中共享和复用代码。
可以在pch.h中定义导出符号
#ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif
编写自定义头文件
#pragma once #include "pch.h" extern "C" MYDLL_API void myctest(); class MYDLL_API myfunction { private: ~myfunction(); public: myfunction() = default; void dosomething(); };
编写cpp
#include "pch.h" #include "myfunction.h" #include <iostream> void myctest() { std::cout << "mytest" << std::endl; } void myfunction::dosomething() { std::cout << "dosomething" << std::endl; } myfunction::~myfunction() { }
编写测试程序
#include <iostream> #include "myfunction.h" int main() { myctest(); myfunction* my = new myfunction(); my->dosomething(); std::cout << "Hello World!\n"; }