CMake生成VS2012 ARM project遇到的问题

ARM 243浏览

VS2012 目前比较新,最新版本的cmake 2.8.10.1)目前还不支持wp8的SDK,我在win8 中生成arm 项目后cmake就过不去了。具体操作如下:

在调用命令生成vs11的project 

cmake -G"Visual Studio 11 ARM" .

出现如下问题:

1>C:Program Files
(x86)MSBuildMicrosoft.Cppv4.0V110PlatformsARMPlatformToolsetsv110Microsoft.Cpp.ARM.v110.targets(36,5):
error MSB8022: Compiling Desktop applications for the ARM platform is not
supported.

========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

主要问题出现在检测编译器并运行trycompile。接下来打开trycompile调试开关,来看看究竟是怎么回事。运行完成后去build目录下的CMakeFilesCMakeTmp目录打开CMAKE_TRY_COMPILE.sln工程文件手工编译一把看看。出现的问题果然和命令行下的一样。问题终于找到了。

原来在vsproject里有一个项设置(PlatformToolset)估计和编译器有关系。cmake默认生成的指向是v110。需要改成v110_wp80 才能编译ARM版本。

另外在改成wp8后编译还是不通过提示不能连接kernel32.lib(这不明摆的事么。wp8肯定连接不了,一定是cmake在创建项目的时候没有考虑wp的问题)

1>LINK : fatal error LNK1104: cannot open file 'kernel32.lib'

接下来就是改正这两个问题,拔一下cmake源代码。

具体改动如下:

cmGlobalVisualStudio10Generator.cxx是生成platform toolset主要类,修改后的代码如下

void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
{
    ...
     if(const char* toolset = gg->GetPlatformToolset())	//通过GetPlatformToolset设置project属性
	{
		//get arch info
		if ( strstr(this->Platform.c_str(), "ARM") )
		{
			toolset = "v110_wp80";	// 如果是ARM架构就设置v110_wp8,这里用的hardcode,如果要制定SDK应该在添加一些针对winphone sdk的变量,
						// 通过cmake变量来设置这个值。大致方法是 this->Makefile->AddDefinition(); this->Makefile->GetDefinition();
		}
		std::string pts = "<PlatformToolset>";
		pts += toolset;
		pts += "</PlatformToolset>n";
		this->WriteString(pts.c_str(), 2);
	}
}

修改link flags 去掉相关的kernel32.lib

这个link flags在哪里加的呢?

cmake-2.8.10.1ModulesPlatformWindows-MSVC.cmake

cmake-2.8.10.1ModulesPlatformWindows-Intel.cmake

这两个module里面添加了

 set(CMAKE_C_STANDARD_LIBRARIES_INIT "kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib")

CMAKE_C_STANDARD_LIBRARIES  会在代码中调用并作为标准链接库,添加到每个项目的AdditionalDependencies

对应的代码如下

void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
                                                       config)
{

  ...
  std::string standardLibsVar = "CMAKE_";
  standardLibsVar += linkLanguage;
  standardLibsVar += "_STANDARD_LIBRARIES";
  std::string
    libs = this->Makefile->GetSafeDefinition(standardLibsVar.c_str());  //这里获取CMAKE_C_STANDARD_LIBRARIES
  // Remove trailing spaces from libs
  std::string::size_type pos = libs.size()-1;
  if(libs.size() != 0)
    {
    while(libs[pos] == ' ')
      {
      pos--;
      }
    }
  if(pos != libs.size()-1)
    {
    libs = libs.substr(0, pos+1);
    }
  // Replace spaces in libs with ;
  cmSystemTools::ReplaceString(libs, " ", ";");
  cmComputeLinkInformation* pcli =
    this->GeneratorTarget->GetLinkInformation(config.c_str());
  if(!pcli)
    {
    cmSystemTools::Error
      ("CMake can not compute cmComputeLinkInformation for target:",
       this->Name.c_str());
    return;
    }
  // add the libraries for the target to libs string
  cmComputeLinkInformation& cli = *pcli;
  if ( strstr(this->Platform.c_str(), "ARM") == 0 ) //这里是添加的代码,如果是ARM架构就不link了
  {
	  this->AddLibraries(cli, libs);
	  linkOptions.AddFlag("AdditionalDependencies", libs.c_str());
  }
  ...
}

修改后重新编译cmake 再生成 Visual Studio 11 ARM的工程文件就顺利完成了。我相信随着windowRT的普及,很快CMake 开发人员就会注意到这个问题,慢慢改正过来。