0

最新的 Android NDK(版本 8)允许在ndk-build不安装额外cygwin的情况下调用。

我的问题是:我可以将它插入 CruiseControl.Net 进行定期原生构建吗?

我假设我很可能需要使用Ant作为构建方法,然后将其添加到ccnet服务器配置中。

所以问题是:

  • 如何ndk-build.cmdAnt命令调用

  • 如何配置build.xml文件?我尝试了几种方法,但都失败了。如果可能的话,你能给我一些线索吗?

4

4 回答 4

2

在 Windows 上使用 CC.net 尝试直接从 build.xml 调用“ndk-build.cmd”时,我遇到了同样的问题(CreateProcess 失败等)。我想出了如何让它发挥作用,所以我觉得有必要分享我的解决方案。

首先,创建一个 1 行 Windows 命令文件,如下所示(我将其命名为“ndkwrapper.cmd”):

sh ndkwrap.sh %1 %2 %3

接下来,创建一个简单的 bash shell 脚本,如下所示(名为“ndkwrap.sh”):

#!/usr/bin/sh
# Wrapper around ndk-build script for Windows
#

NDK_PROJECT_PATH=/cygdrive/c/workspace/agnc_android
export NDK_PROJECT_PATH
/cygdrive/c/Android/android-ndk-r8b/ndk-build $1 $2 $3

当然,您的确切路径(对于您的工作区和 NDK 目录)可能会有所不同,但请特别注意,“/cygdrive/c”指的是“C:”。

在您创建上面的脚本之后,这里的一个非常重要的步骤是将行尾从 Windows 转换为 UNIX。您可以使用免费提供的名为“dos2unix.exe”的实用程序来执行此操作。我不记得我从哪里得到它,但它是移植到 Windows 的 GNU/Linux 工具的一些开源包的一部分。(谷歌在“Windows 的 UNIX 文件实用程序”上。)如果你不转换行尾,那么 sh 或 bash 将无法读取脚本,你会得到关于 "\r" 的各种错误......

因此,例如,要调用“ndk-build.cmd clean”的等效项,您需要键入“ndkwrapper.cmd clean”来删除与NDK 相关的中间和输出构建文件,为完整的NDK 构建做准备。

在 Windows 上 CC.net 的 build.xml 文件中,您可以调用 NDK 生成文件,如下所示:

<tasks>
  <exec>
    <executable>cmd.exe</executable>
    <baseDirectory>C:\Android</baseDirectory>
    <buildArgs>/C ndkwrapper.cmd clean</buildArgs>
  </exec>

希望这可以帮助!

于 2012-11-02T19:10:30.723 回答
1

我也观察到将 ndk-build 作为 CCNET 任务运行的问题。我花了一段时间,但最后我注意到,你必须提供HOST_OSndk HOST_ARCH-build 参数才能让它运行。

<exec>
  <executable>cmd</executable>          
  <buildArgs>/C ndk-build HOST_OS=windows HOST_ARCH=x86 -B NDK_PROJECT_PATH=[PROJECT] APP_BUILD_SCRIPT=[ANDROIDMKFILE] NDK_APPLICATION_MK=[APPLICATIONMKFILE] NDK_LOG=1</buildArgs>
  <buildTimeoutSeconds>120</buildTimeoutSeconds>
</exec>

希望它可以帮助任何人节省时间。

于 2013-03-01T13:44:14.697 回答
0

好的,我取得了一些进展,我能够通过 ant 或 nant 构建 jni 代码,但在这两种情况下,将其插入 cc.net 服务器配置都会出现 strane 错误:

但现在 CC.net 给了我奇怪的错误:

    <builderror>
      <type>NAnt.Core.BuildException</type>
      <message><![CDATA[External Program Failed: G:\\android-ndk-r8b\\ndk-build.cmd (return code was 2)]]></message>
      <location>
        <filename>G:/MYPath/project.build</filename>
        <linenumber>7</linenumber>
        <columnnumber>4</columnnumber>
      </location>
      <stacktrace><![CDATA[   at NAnt.Core.Tasks.ExternalProgramBase.ExecuteTask()
   at NAnt.Core.Tasks.ExecTask.ExecuteTask()
   at NAnt.Core.Task.Execute()
   at NAnt.Core.Target.Execute()
   at NAnt.Core.Project.Execute(String targetName, Boolean forceDependencies)
   at NAnt.Core.Project.Execute()
   at NAnt.Core.Project.Run()]]></stacktrace>
    </builderror>
  </failure>
  <duration>296.40000000000003</duration>
</buildresults>Buildfile: file:///G:/MYPath/project.build
Target framework: Microsoft .NET Framework 4.0
Target(s) specified: build

干净的:

 [echo] Starting Android ndk CLEAN ...
 [exec] Android NDK: Unable to determine HOST_OS from uname -s:     
 [exec] Android NDK: Please define HOST_OS in your environment.    
 [exec] process_begin: CreateProcess(NULL, uname -s, ...) failed.
 [exec] G:/android-ndk-r8b/build/core/init.mk:131: *** Android NDK: Aborting.    .  Stop.

构建失败 - 0 个非致命错误,2 个警告

我在 cc.net 配置中的项目:

<project>
    <name>MY_PROJECT_NAME</name> 
    <workingDirectory>PATH_TO_MY_PROJECT</workingDirectory>
    <tasks>
        <nant>
            <executable>G:\nant-0.92\bin\Nant.exe</executable>
            <baseDirectory>PATH_TO_MY_PROJECT</baseDirectory>
            <buildFile>MYPROJECTNAME.build</buildFile>
            <buildArgs>build</buildArgs> 
            <buildTimeoutSeconds>1200</buildTimeoutSeconds>
        </nant>
    </tasks>
</project>

还有我的 NAnt 构建文件:

<project name="my name" default="build" basedir=".">
    <description>My project Build Files.</description>
    <target name="clean" description="remove all generated files">
        <echo message="Starting Android ndk CLEAN ..."/>
        <exec program="G:\\android-ndk-r8b\\ndk-build.cmd" failonerror="true"
            basedir="MY PROJECT PATH">
            <arg value="clean" />
        </exec>
        <echo message="Android ndk CLEAN done."/>
    </target>
    <target name="build" description="remove all generated files"  depends="clean">
        <echo message="Starting Android ndk BUILD ..."/>
        <exec program="G:/android-ndk-r8b/ndk-build.cmd" failonerror="true" />
        <echo message="Android ndk BUILD done."/>
    </target>
</project>

正如我所说,我可以为我的项目运行 Nant.exe,它可以正确清理和构建。看起来 cc.net 尝试运行另一个用于 linux 的 ndk-build 推荐,并且缺少一些命令作为 uname。你知道 cI 可能做错了什么吗?

于 2012-08-16T09:28:15.693 回答
0

最初的问题是询问蚂蚁构建。这个答案与 CC.NET 中的一个问题有关,ant 和 gradle 构建将以同样的方式受到影响。

我们正在使用 gradle 并且通过一些自定义 gradle 任务,也可以通过调用 ndk-build.cmd(从其中没有空格的路径)来编译项目的本机代码。

正确准备好 gradle 文件后,shell 启动的 gradle 构建将起作用,但 cc.net 启动的构建将失败。

我们的 CC.NET 任务定义如下:

<exec executable=".\gradlew.bat">
    <baseDirectory>$(projSrcDir)</baseDirectory>
    <buildArgs>clean assemblePlayRelease assembleProRelease</buildArgs>
    <buildTimeoutSeconds>900</buildTimeoutSeconds>
</exec>

该问题与导致 shell 变量名称为小写的 CC.NET 错误有关。Windows shell 脚本不关心 shell 变量名的大小写,但是因为 NDK 启动了使变量大小写成为问题。作为构建过程一部分的 init.mk make 文件依赖于 shell 变量名称来识别主机操作系统类型。特别是 shell 变量 OS。通常 OS 值是这样定义的:

OS=Windows_NT

但是当变量从 CC.NET 传递给 gradle 时,它​​会变成这样:

os=Windows_NT

这会导致 init.mk 中的检测机制失败并尝试执行 unix 检测序列并查找 Windows 上不存在的 Unix uname 实用程序,从而导致:

Android NDK: Unable to determine HOST_OS from uname -s:
Android NDK: Please define HOST_OS in your environment.
make.exe: Entering directory `D:/CC.NET/svncheckout/pes/src/project/src/main/jni'
make.exe: Leaving directory `D:/CC.NET/svncheckout/pes/src/project/src/main/jni'

最终:

process_begin: CreateProcess(NULL, uname -s, ...) failed.
c:/ndk/build/core/init.mk:160: *** Android NDK: Aborting.    .  Stop.
FAILURE: Build failed with an exception.

解决方法不太理想,但可以完成工作。我们的想法是编辑 ndk-build.cmd 并仅在我们从 CC.NET 构建时更改传递变量的大小写。

只需在 ndk-build.cmd 中的 @echo off 行之后插入此代码:

IF DEFINED ccnetproject (
  ECHO Applying Environment variable hack for CC.NET.
  SET OS2=%os%
  SET OS=
  REM SET PATH=%path%
  SET TEMP2=%temp%
  SET TEMP=
)

IF DEFINED ccnetproject (
  SET OS=%OS2%
  SET OS2=
  SET TEMP=%TEMP2%
  SET TEMP2=
)

该脚本首先对小写 OS 和 TEMP 变量中的值进行临时复制。接下来,它通过清除它们的值来取消定义它们。最后完成了相反的操作。

需要两个步骤,因为只是说

SET OS=%os%

由于脚本不区分大小写,因此没有多大作用。它首先定位 OS 变量,找到一个小写版本并将自己的值赋回给自己。

这是在 CC.NET v1.6.7981.1、gradle v1.1.0 和 Android NDK v10(64 位)上测试的。

于 2015-02-27T20:35:56.100 回答