了解一下msbuild工程文件的基本结构,作为练习,用它编译一个用到Qt库的C++控制台程序
C#例子
一个简单的例子:
// file: hello.cs
using System;
class CSharpTest
{
static void Main()
{
Console.WriteLine("Hello world not using Qt");
}
}
如果直接用命令行的话,可以直接这么编译:
csc /out:hello_cs.exe hello.cs
msbuild
可是如果我想用msbuild,工程文件怎么写呢?
恩,大致可以这样:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Compile">
<CSC Sources="hello.cs" OutputAssembly="hello_cs.exe" />
</Target>
</Project>
而后直接
msbuild hello.csproj
即可。
一个工程中可以有多个目标(Target),如果这样的话,我们需要指定执行哪一个(和nmake是类似的)
msbuild hello.csproj /t:Compile
也可以在Project的属性中指定
<Project DefaultTargets="Compile"
每一个目标(Target)由若干个任务(Task)组成。比如:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Compile">
<CSC Sources="hello.cs" OutputAssembly="hello_cs.exe" />
</Target>
<Target Name="Compile2">
<Message Text="Before"/>
<CSC Sources="hello.cs" OutputAssembly="hello_cs.exe" />
<Message Text="After"/>
</Target>
</Project>
然后我们
msbuild hello.csproj /t:Compile2
这样在编译命令前后分别输出一条信息。其中CSC和Message都是MSBuild内置的Task
继续
前面的东西太简陋了,一般情况下,我们需要将一些东西分开设置,也就是需要变量或宏一类的东西
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<appname>hello_cs</appname>
</PropertyGroup>
<ItemGroup>
<CSSource Include="hello.cs"/>
</ItemGroup>
<Target Name="Compile">
<CSC Sources="@(CSSource)" OutputAssembly="$(appname).exe" />
</Target>
</Project>
这儿引入的Property(属性)和Item这两个东西。
- 属性类似于宏,一个简单的键值对,在任务中可以直接通过 $(...)来引用
- Item 比较复杂,在任务中通过 @(...)来引用,大致相当于一个数组吧(fixme)
- Include和Exclude,中还支持通配符
<ItemGroup>
<CSSource Include="hello.cs"/>
<CSSource Include="class1.cs"/>
<CSSource Include="class2.cs;class3"/>
</ItemGroup>
看个具体的?
用Visual Studio创建一个具体的C#控制台工程,然后打开看看
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
...
</Project>
真够复杂的,尽管大量东西都隐藏在Microsoft.CSharp.targets中了
我想用它编译个Qt程序
简单的Qt的例子:
#include <QtGui/QLabel>
#include <QtGui/QApplication>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QLabel label("Qt Program built using MSBuild....");
label.show();
app.exec();
}
使用命令行时,只需:
E:\msbuild>cl hello.cpp /ID:\Qt\4.7.3\include /link /libpath:D:\Qt\4.7.3\lib QtCore4.lib QtGui4.lib
现在我想试试MSBuild,可以快速写个工程文件 hello.qtproj ?
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<appname>hello_qt</appname>
</PropertyGroup>
<ItemGroup>
<QtPart Include="core;gui" />
</ItemGroup>
<ItemGroup>
<QtSource Include="hello.cpp"/>
</ItemGroup>
<Target Name="Compile">
<QTC Sources="@(QTSource)" QtParts="@(QtPart)" Output="$(appname).exe" />
</Target>
</Project>
现在,我们在里面指定了:
- 源文件
- 可执行程序名
- 需要的Qt模块名
但是我们需要有一个Task来做这件事情
QTC任务
为了让我们前面的QTC能工作,需要先为MSBuild写个Task插件
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Dbzhang800
{
public class QTC:Task
{
public override bool Execute()
{
string qtdir = Environment.GetEnvironmentVariable("QTDIR");
var arguments = new List<string>();
foreach (string src in sourcesname)
{
arguments.Add(src);
}
arguments.Add(string.Format("/Fe{0}", outputname));
arguments.Add(string.Format("/I{0}\\include", qtdir));
arguments.Add(string.Format("/link /libpath:{0}\\lib", qtdir));
foreach (string part in partsname)
{
arguments.Add(String.Format("Qt{0}4.lib", part));
}
Process proc = new Process();
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.FileName = "cl";
proc.StartInfo.Arguments = string.Join(" ", arguments.ToArray());
proc.Start();
Console.WriteLine("{0}", string.Join(" ", arguments.ToArray()));
return true;
}
private string outputname;
public string Output
{
get {return outputname;}
set {outputname = value;}
}
private string[] sourcesname;
public string[] Sources
{
get {return sourcesname;}
set {sourcesname = value;}
}
private string[] partsname;
public string[] QtParts
{
get {return partsname;}
set {partsname = value;}
}
}
}
这是一个C#文件,编译成dll文件
csc /target:library /r:Microsoft.Build.Framework.dll;Microsoft.Build.Utilities.v3.5.dll qttask.cs
而后在工程 hello.qtproj 中注册一下这个Task
...
<UsingTask TaskName="QTC" AssemblyFile="qttask.dll"/>
<Target Name="Compile">
<QTC Sources="@(QTSource)" QtParts="@(QtPart)" Output="$(appname).exe" />
</Target>
...
现在,总算可以用
msbuild test.qtproj
来生成我们的Qt程序了
本文介绍如何使用MSBuild进行C#及Qt C++项目的编译,包括基本结构、变量设置、自定义任务等内容,并提供了编译Qt程序的具体实例。
1655

被折叠的 条评论
为什么被折叠?



