CMake 和不同版本的 Visual Studio
CMake and different versions of Visual Studio
我实际上正在编写一个库,我愿意让它成为多平台的。我已经使用了多平台依赖项(主要是提升)并且我已经开始使用 CMake。
过去几个月我一直在使用 CLion,虽然它非常棒 IDE,但在 Windows 上使用它非常复杂,因为它需要 MinGW 或 Cygwin .之前我一直在用Cygwin,因为Unix的仿真让我很满意,但是自从上次更新之后,boost在它上面就完全不能用了
我认为对我来说最好的选择是回到 Visual Studio。但是如何将它与 CMake 一起使用呢?
我的库需要部署在多个版本的VS下(从VS2013开始,一直到2015)
到目前为止,我一直在做的是每次添加文件时都重新生成项目,但我发现这个解决方案非常低效,您可以猜到。
我还需要能够编译到不同的位置,具体取决于编译器。例如:
- 包括
- 库
- VS2013-x64
- 调试
- 发布
- VS2013-x86
- 调试
- 发布
- VS2015-x64
- 调试
- 发布
- VS2015-x86
- 调试
- 发布
- 源码
可以用CMake处理吗?如果是这样,怎么做?
只要在运行ning cmake时指定即可生成不同版本的VS工程文件,例如:
cmake -G "Visual Studio 14 2015 Win64" ..
或
cmake -G "Visual Studio 12 2013 Win64" ..
您只需为每个版本使用正确的生成器名称。
至于每次添加文件时都重新生成,目前运行暂时没有办法解决这个问题。如果您愿意,可以在工作时将其简单地添加到 visual studio 中的项目中?顺便说一下,您不必在重新生成时删除所有构建工件,因此当您将文件添加到目录时,运行 命令应该是微不足道的,并且项目将在 visual studio 中自动更新。与通过 VS 中的 gui 添加它相比,它需要一点时间来适应,但并不是什么大问题。
编辑:
调试与发布不是生成器的一部分。您仍然可以像往常一样在 visual studio 中设置它们。
这不是 Visual Studio 特定问题。
一般来说,C++ 不保证使用一个编译器版本构建的库可以与由同一编译器的不同版本或不同编译器构建的可执行文件一起工作。这是因为 C++ 在如何生成其对象的二进制布局方面给予编译器一定的自由。
这是一个很老的问题,没有简单的解决办法。如果您不想接受对库接口的任何限制,您将需要为每个支持的编译器版本重建库,并进行重大的 ABI 更改(这通常意味着为每个编译器单独构建 and 编译器版本中的主要版本颠簸)。
CMake 无法为您执行此操作,因为每个 CMake 配置 运行 只会为一个特定的编译器 生成一个 CMake 配置 。您在这里可以做的最好的事情是编写一个 shell 脚本,该脚本从不同的二进制目录重复调用 cmake
和 cmake --build
以自动依次在所有支持的编译器上构建。由于手动完成这仍然很乏味,您可能需要设置一个持续集成系统来帮助解决这个问题。
另一种方法是以二进制接口定义明确的方式限制您的库接口。通常这意味着以下两种情况之一:
- 使用 C API 作为外部库接口。您的代码仍然可以是 C++,但是想要与您的库交互的应用程序必须通过 C API。这里明显的缺点是界面上不再有 类,而是结构和自由函数。此解决方案比您想象的更常见。 Stefanus Du Toit 在 CppCon 2014 上就此方法发表了演讲 (video; slides)。
- 使用像 Microsoft's COM 这样的对象模型技术。缺乏标准化的 ABI 困扰了人们很长时间,业界已经提出了几种解决方案来解决如何在接口上获取 类 和对象。不幸的是,了解这些技术并非易事,所以如果您决定走这条路,请做好认真研究的准备。这种方法在 Windows 世界中非常普遍。
您可以使用 CMake 预定义变量和一些脚本来实现它。
So far, what I've been doing was regenerating the project everytime I added a file, but I find this solution very unproductive as you can guess.
添加文件时,您正在更改项目配置,因此别无选择,只能重新生成它。但是,您可以使用一个简单的 .bat
文件使其自动化。
mkdir build
cd build
SET VS_DIR=VS2013-x64
mkdir %VS_DIR%
cd %VS_DIR%
cmake ../.. -G "Visual Studio 12 2013 Win64"
cd ..
SET VS_DIR=VS2013-x86
mkdir %VS_DIR%
cd %VS_DIR%
cmake ../.. -G "Visual Studio 12 2013"
cd ..
SET VS_DIR=VS2015-x64
mkdir %VS_DIR%
cd %VS_DIR%
cmake ../.. -G "Visual Studio 14 2015 Win64"
cd ..
SET VS_DIR=VS2015-x86
mkdir %VS_DIR%
cd %VS_DIR%
cmake ../.. -G "Visual Studio 14 2015"
I also need to be able to compile into different locations, depending
on the compiler.
CMakeLists.txt
可以使用CMake预定义的${PROJECT_SOURCE_DIR}
和.bat
文件中设置的环境变量VS_DIR
自动配置每个项目中的输出目录。
cmake_minimum_required(VERSION 3.8)
project (CppProject)
add_executable(app main.cpp)
set_target_properties(app PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/lib/$ENV{VS_DIR}/Debug
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/lib/$ENV{VS_DIR}/Release)
我实际上正在编写一个库,我愿意让它成为多平台的。我已经使用了多平台依赖项(主要是提升)并且我已经开始使用 CMake。
过去几个月我一直在使用 CLion,虽然它非常棒 IDE,但在 Windows 上使用它非常复杂,因为它需要 MinGW 或 Cygwin .之前我一直在用Cygwin,因为Unix的仿真让我很满意,但是自从上次更新之后,boost在它上面就完全不能用了
我认为对我来说最好的选择是回到 Visual Studio。但是如何将它与 CMake 一起使用呢? 我的库需要部署在多个版本的VS下(从VS2013开始,一直到2015)
到目前为止,我一直在做的是每次添加文件时都重新生成项目,但我发现这个解决方案非常低效,您可以猜到。 我还需要能够编译到不同的位置,具体取决于编译器。例如:
- 包括
- 库
- VS2013-x64
- 调试
- 发布
- VS2013-x86
- 调试
- 发布
- VS2015-x64
- 调试
- 发布
- VS2015-x86
- 调试
- 发布
- VS2013-x64
- 源码
可以用CMake处理吗?如果是这样,怎么做?
只要在运行ning cmake时指定即可生成不同版本的VS工程文件,例如:
cmake -G "Visual Studio 14 2015 Win64" ..
或
cmake -G "Visual Studio 12 2013 Win64" ..
您只需为每个版本使用正确的生成器名称。
至于每次添加文件时都重新生成,目前运行暂时没有办法解决这个问题。如果您愿意,可以在工作时将其简单地添加到 visual studio 中的项目中?顺便说一下,您不必在重新生成时删除所有构建工件,因此当您将文件添加到目录时,运行 命令应该是微不足道的,并且项目将在 visual studio 中自动更新。与通过 VS 中的 gui 添加它相比,它需要一点时间来适应,但并不是什么大问题。
编辑: 调试与发布不是生成器的一部分。您仍然可以像往常一样在 visual studio 中设置它们。
这不是 Visual Studio 特定问题。
一般来说,C++ 不保证使用一个编译器版本构建的库可以与由同一编译器的不同版本或不同编译器构建的可执行文件一起工作。这是因为 C++ 在如何生成其对象的二进制布局方面给予编译器一定的自由。
这是一个很老的问题,没有简单的解决办法。如果您不想接受对库接口的任何限制,您将需要为每个支持的编译器版本重建库,并进行重大的 ABI 更改(这通常意味着为每个编译器单独构建 and 编译器版本中的主要版本颠簸)。
CMake 无法为您执行此操作,因为每个 CMake 配置 运行 只会为一个特定的编译器 生成一个 CMake 配置 。您在这里可以做的最好的事情是编写一个 shell 脚本,该脚本从不同的二进制目录重复调用 cmake
和 cmake --build
以自动依次在所有支持的编译器上构建。由于手动完成这仍然很乏味,您可能需要设置一个持续集成系统来帮助解决这个问题。
另一种方法是以二进制接口定义明确的方式限制您的库接口。通常这意味着以下两种情况之一:
- 使用 C API 作为外部库接口。您的代码仍然可以是 C++,但是想要与您的库交互的应用程序必须通过 C API。这里明显的缺点是界面上不再有 类,而是结构和自由函数。此解决方案比您想象的更常见。 Stefanus Du Toit 在 CppCon 2014 上就此方法发表了演讲 (video; slides)。
- 使用像 Microsoft's COM 这样的对象模型技术。缺乏标准化的 ABI 困扰了人们很长时间,业界已经提出了几种解决方案来解决如何在接口上获取 类 和对象。不幸的是,了解这些技术并非易事,所以如果您决定走这条路,请做好认真研究的准备。这种方法在 Windows 世界中非常普遍。
您可以使用 CMake 预定义变量和一些脚本来实现它。
So far, what I've been doing was regenerating the project everytime I added a file, but I find this solution very unproductive as you can guess.
添加文件时,您正在更改项目配置,因此别无选择,只能重新生成它。但是,您可以使用一个简单的 .bat
文件使其自动化。
mkdir build
cd build
SET VS_DIR=VS2013-x64
mkdir %VS_DIR%
cd %VS_DIR%
cmake ../.. -G "Visual Studio 12 2013 Win64"
cd ..
SET VS_DIR=VS2013-x86
mkdir %VS_DIR%
cd %VS_DIR%
cmake ../.. -G "Visual Studio 12 2013"
cd ..
SET VS_DIR=VS2015-x64
mkdir %VS_DIR%
cd %VS_DIR%
cmake ../.. -G "Visual Studio 14 2015 Win64"
cd ..
SET VS_DIR=VS2015-x86
mkdir %VS_DIR%
cd %VS_DIR%
cmake ../.. -G "Visual Studio 14 2015"
I also need to be able to compile into different locations, depending on the compiler.
CMakeLists.txt
可以使用CMake预定义的${PROJECT_SOURCE_DIR}
和.bat
文件中设置的环境变量VS_DIR
自动配置每个项目中的输出目录。
cmake_minimum_required(VERSION 3.8)
project (CppProject)
add_executable(app main.cpp)
set_target_properties(app PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/lib/$ENV{VS_DIR}/Debug
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/lib/$ENV{VS_DIR}/Release)