关于windows下使用 cmake 的 nmake 方式构建项目

NMake环境变量配置

正常情况下,安装vs集成开发包时默认用户使用msbuild作为构建工具,虽然也顺带安装了nmake,但是实际上用户不进行一些配置的话,是不能直接使用nmake编译项目的,原因是没有配置环境变量,编译时找不到各种路径,win SDK库\Rtc库路径、头文件路径、甚至编译工具、构建工具路径也找不到。微软想让用户更傻瓜,最好啥原理也不懂,直接用就好。

于是乎,为了可以直接使用nmake构建项目,我们需要对环境变量做一些配置,以下以一个简单的示例介绍做法:

现有有代码,main.cpp

为了能在命令行下使用nmake,要将nmake.exe的目录加入到环境变量Path中

编译过程中会用到rc.exe、cl.exe、link.exe等工具,其所在目录也要加入Path

关于windows下使用 cmake 的 nmake 方式构建项目

 

然后将编译期间可能需要包含的头文件目录以及库目录分别加入到INCLUDE和LIB环境变量,如:

关于windows下使用 cmake 的 nmake 方式构建项目

关于windows下使用 cmake 的 nmake 方式构建项目

然后就可以编写Makefile,然后通过nmake构建项目了

 

使用cmake产生nmake脚本构建项目

CMakeLists.txt

#CMake最低版本号要求

cmake_minimum_required(VERSION 2.8)

#指定项目名称

project(CMakeDemo)

#添加子目录,这样进入源码文件src目录可以继续构建  

add_executable(hello main.cpp)

#PreLoad.cmake

#通过PreLoad.cmake可以强行指定编译器

set(CMAKE_GENERATOR "NMake Makefiles" CACHE INTERNAL "" FORCE)

set(CMAKE_CXX_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe"  CACHE INTERNAL "" FORCE)

set(CMAKE_C_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/cl.exe"  CACHE INTERNAL "" FORCE)

注:如果CMAKE_GENERATOR使用了" Visual Studio xx 20xx"则CMAKE_CXX_COMPILERCMAKE_C_COMPILER是被锁定的,PreLoad.cmake失效

问题:

1.NMAKE:fatal error U1077.“cl.exe” return code 0xc0000135

产生原因:在安装visual studio的时候没有勾选注册环境变量导致的。

解决办法:在系统环境变量中加入visual studio的安装路径:vs安装路径\VC\Bin,以及vs安装路径\Common7\IDE

2.NMAKE:fatal error U1077. return code 0x2

产生原因:找不到代码文件中包含的头文件

解决办法:cmd下进入到vs安装路径\VC\Bin下,执行vcvars32,此时会执行vcvas32.bat自动为vs设置环境变量

3.NMAKE:fatal error U1077. return code 0x460

产生原因:你的工程中连接了一个lib文件,链接的时候却出现不能解析的外部符号。可能问题是你包含的lib是错的,或者有不兼容问题。我的问题就是后者,我的系统的32位的,但是链接了一个64位的lib.

使用nmake构建项目时,使用vcvarsall.bat切换编译器架构

(这个优先级应该低于同手动写入环境)

一直以来我只知道vc设置命令行编译环境的批处理命令是%VS140COMNTOOLS%/Common7/Tools下的vsvars32.bat,(%VS140COMNTOOLS%为定义vs2015公共工具程序位置的环境变量,命令行窗口输入set就能找到,vs2010的对应定义为%VS100COMNTOOLS%) 微软的官网上有这个命令的说明: https://technet.microsoft.com/zh-cn/library/1700bbwd.aspx

但在执行这个命令生成的命令行环境下用nmake只能编译32位版本的代码,我一直都不知道如何用nmake编译64位的代码。 今天才搞明白vsvars32.bat已经过时了,正确的打开方式是vcvarsall.bat 。 至少从vs2010开始, %VS140COMNTOOLS%/VC下就有vcvarsall.bat,用于生成命令行编译环境。 如果要在命令行生成 32位代码,就执行vcvarsall x86 如果要在32位系统下生成64位代码,就执行vcvarsall x86_amd64 如果要在64位系统下生成32位代码,就执行vcvarsall x86vcvarsall amd64_x86 到了VS2015,已经支持arm平台了,所以如果要生成arm平台的代码,就执行vcvarsall x86_arm 如果你的操作系统是64位的也可以 vcvarsall amd64_arm

前面一个名字代表你的当前电脑的体系结构,后面的这个名字代表你要生成的代码的体系结构。如果两个名字一样,就简化为一个名字。 搞清楚了这个,今天终于顺利在命令行下实现nmake编译32位和64位版本代码:

生成用于编译32位代码的命令行编译环境

C:\Program Files (x86)\Microsoft Visual Studio 14.0>cd VC
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC>vcvarsall x86

执行cmake生成NMake格式的Makefile,指定处理器为x86,然后执行nmake编译所有代码,并安装

>cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RELEASE -DTARGET_PROCESSOR=x86 ..\facecl
>nmake install

安装成功的输出

Install the project...
-- Install configuration: "RELEASE"
-- Installing: C:/Program Files (x86)/facecl/lib/static/detect_cl.lib
-- Installing: C:/Program Files (x86)/facecl/bin/detect_cl.dll
-- Installing: C:/Program Files (x86)/facecl/lib/static/img_tool.lib
-- Installing: C:/Program Files (x86)/facecl/bin/img_tool.dll
-- Installing: C:/Program Files (x86)/facecl/bin/test_detect.exe
-- Up-to-date: C:/Program Files (x86)/facecl/./README_utf8.txt
-- Up-to-date: C:/Program Files (x86)/facecl/include/detect_cl_types.h
-- Up-to-date: C:/Program Files (x86)/facecl/include/detect_cl.h
-- Up-to-date: C:/Program Files (x86)/facecl/include/img_tool.h
-- Up-to-date: C:/Program Files (x86)/facecl/sample/test_detect.cpp
-- Up-to-date: C:/Program Files (x86)/facecl/sample/utility.h
-- Up-to-date: C:/Program Files (x86)/facecl/sample/raii.h
-- Up-to-date: C:/Program Files (x86)/facecl/sample/assert_macros.h
-- Up-to-date: C:/Program Files (x86)/facecl/sample/cmdline.h
-- Up-to-date: C:/Program Files (x86)/facecl/sample/dirent.h
-- Up-to-date: C:/Program Files (x86)/facecl/sample/file_utilits.h
-- Up-to-date: C:/Program Files (x86)/facecl/sample/time_utilits.h

如果要在32位系统下生成64位代码,也如法炮制

关于vcvarsall.bat更详细的说明,参见微软的官方文档: https://msdn.microsoft.com/zh-cn/library/f2ccy3wt.aspx