- Program.global["rgInstStatic"] = RandGen.create({range: 20, seed: 4});
复制代码
第五课,lesson5:
xdctools_3_10_05_61/docs/docs/rtscpedia/RTSC_Module_Primer/RTSC_Module_Primer__Lesson_5.html
终于说到包了,这与
codec engine是很相关的了。
这里我们要创建一个非常简单的包,这个包里没有模块,只是为了介绍一些概念。
我们的examples文件夹己经被包含在XDCPATH目录下了,所以如果我们想建一个包,名字叫lesson5,我们就在examples目录下建一个目录叫做lesson5,这体现了XDC中包结构的物理,逻辑两个层次的对应。
要
声明lesson5下面是一个包,它下面就要有丙个文件,一个是package.xdc,另一个就是package.bld.前者声明这个包的名字,后者描述了这个的创建方法。
- j@j-desktop:~/test/examples/lesson5$ ls
- package package.bld package.mak package.xdc prog.c prog.cfg
复制代码
在
package.xdc中,可以这样声明一个包:
- j@j-desktop:~/test/examples/lesson5$ cat package.xdc
- /*
- * ======== lesson5/package.xdc ========
- */
- /*! Our first package [RTSC Module Primer] */
- package lesson5 {
- /* module declarations normally go here */
- };
复制代码
去掉无用的注释,其实就是:
这有点像C语言的给构体,然而却不是,它是用
XDCspec语言来写的。这里我们应该得到一个结论,examples下的Lesson5文件夹,对应一个包称为lessen5,但同样的文件夹lesson4却不是一个包,因为它下面没有package.xdc。]
另一个文件是package.bld,它是用
XDCscript写的。它的功能与makefile差不多。也用于控制程序的编译流程。
另外,lesson0中的config.bld也是XDCscript写的。config.bld通常放在XDCPATH指定的各个目录下,
- for each (var targ in Build.targets) {
- Pkg.addExecutable("prog", targ, targ.platform).addObjects(["prog.c"]);
- }
复制代码
这句话大有讲究,它针对每个Build.targets对象中的每一个target,用targ范指,都执行同一个操作,addExecutable("prog",targ,targ.platform).addObjects([“prog.c"]);
Package模块有很多函数,其中addExecutabe执行了添加构建模块所谓的所有信息。"prog"是可执行文件的名字也是.cfg文件的名 字。targ是编译的目标,targ.platform是目标所在的平台,target有一个platform属性,它有默认值,可以在 config.bld中配置。addexecutable根据不同的target返回一个不同类型XDCscript类型,不同的XDCscript调用 的addObject自然也就一样。addObject函数枚举需要进行编译的文件。我们看一下config.bld中的内容,更有助于理解:
- j@j-desktop:~/test/examples/lesson5$ cat ../config.bld
- /*
- * ======== config.bld ========
- */
- var Build = xdc.useModule('xdc.bld.BuildEnvironment');
- var C64P = xdc.useModule('ti.targets.C64P');
- var GCC = xdc.useModule('gnu.targets.Mingw');
- C64P.rootDir = /home/pheobe/davinci/cg6x_6_0_21_1; /* modify to match %c6xtools% */
- C64P.platform = 'ti.platforms.sim64Pxx';
- GCC.rootDir = /usr/bin; /* modify to match %gcctools% */
- Build.targets = [C64P, GCC];
复制代码
可见这里Build.targets里有两个target,一个是C64P,另一个是GCC.
C64P的platform域被指定为'ti.platforms.sim64Pxx,GCC则使用默认的。
现在一切都明了了,可以进行编译了:
xdc工具集中有两个最常用的命令,其他的基本用不到:
xs和xdc.其中xs己经用过了,它是用于启动xdcscript写的代码的。而xdc基本等价于make,用于package.bld之类的XDCscript写的代码的。
常用的xdc命令是xdc clean和xdc all,前者清楚上次编译出来的东西,后者按照package.bld编译全部。
嗯,编译时发现config.bld配置错了,examples目录下的,应为:
- /*
- * ======== config.bld ========
- */
- var Build = xdc.useModule('xdc.bld.BuildEnvironment');
- var C64P = xdc.useModule('ti.targets.C64P');
- var GCC = xdc.useModule('gnu.targets.Linux86');
- C64P.rootDir ='/home/pheobe/davinci/cg6x_6_0_21_1'; /* modify to match %c6xtools% */
- C64P.platform = 'ti.platforms.sim64Pxx';
- GCC.rootDir ='/usr'; /* modify to match %gcctools% */
- Build.targets = [C64P, GCC];
复制代码
因为我们是在linux下的,找不到minggw,我们是纯的gcc啊。
下面编译:
- j@j-desktop:~/test/examples/lesson5$ xdc clean
- j@j-desktop:~/test/examples/lesson5$ xdc all
- making package.mak (because of package.bld) ...
- generating interfaces for package lesson5 (because package/package.xdc.inc is older than package.xdc) ...
- configuring prog.x64P from package/cfg/prog_x64P.cfg ...
- cl64P prog.c ...
- cl64P package/cfg/prog_x64P.c ...
- lnk64P prog.x64P ...
- configuring prog.x86U from package/cfg/prog_x86U.cfg ...
- cl86U prog.c ...
- cl86U package/cfg/prog_x86U.c ...
- lnk86U prog.x86U ...
- all files complete.
复制代码
测试:
- j@j-desktop:~/test/examples/lesson5$ xdc test
- running prog.x64P ...
- Hello World
- running prog.x86U ...
- Hello World
复制代码
第五课搞定了。
第六课:
上一节课我们讲到了包,但是我们的包里并没有什么东西,这一节课我们讲的叫模块,并且会涉及到XDC编程中的一个常用技巧,即把C语言中的常量写成可配置的模块参数。
我们的模块名字叫做Talker,它在文件夹lesson6里面,也在包lesson6里面,lesson6里面有一个文件package.xdc来描述这个模块,但这里面只是给了一个声明,但并没有说明这个模块的详细属性,详细的属性写在Talker.xdc里面。
- j@j-desktop:~/test/examples/lesson5$ cd ../lesson6
- j@j-desktop:~/test/examples/lesson6$ cat package.xdc
- /*
- * ======== lesson6/package.xdc ========
- */
- /*! Contains our first module [RTSC Module Primer] */
- package lesson6 {
- module Talker;
- };
复制代码
先不谈Talker.xdc,这里先看一下客户程序怎么用这个模块:
- j@j-desktop:~/test/examples/lesson6$ cat prog.c
- /*
- * ======== lesson6/prog.c ========
- */
- #include
- Int main()
- {
- Talker_print();
- return 0;
- }
- j@j-desktop:~/test/examples/lesson6$ cat prog.cfg
- /*
- * ======== lesson6/prog.cfg ========
- */
- var Talker = xdc.useModule('lesson6.Talker');
- Talker.text = "Goodnight Moon";
- Talker.count = 3;
复制代码
prog.c中调用了Talker的print函数,而prog.cfg中对Talker.text和.count属性进行了配置。
现在我们可以看Talker.xdc了,这个文件定义了Talker模块的详细属性。它是由XDCspec,一种与C差不多的语言写的。我们注意到 prog.c中include了lesson6/Talker.h,这个文件是不用手写的,XDC会自动根据Talker.xdc生成talker.h.
- j@j-desktop:~/test/examples/lesson6$ xdc clean
- j@j-desktop:~/test/examples/lesson6$ ls
- lib package.xdc prog.cfg Talker.xdc
- package.bld prog.c Talker.c Talker.xs
复制代码
看,没有talker.h
- j@j-desktop:~/test/examples/lesson6$ cat Talker.xdc
- /*
- * ======== lesson6/Talker.xdc ========
- */
- /*! Our first module */
- module Talker {
- /*! What to say */
- config String text = "Hello World";
- /*! How many times */
- config Int count = 1;
- /*! Say it */
- Void print();
- }
复制代码
看,上面对应的东西都与标准C语言头文件对应的,函数声明,常量声明并初始化,注意,这里的count和text最终都会转化为常量extern const 而config关键字则指明,对于某些优化过程,也可以将count和text视为#define来优化。
Talker.xdc仅是模块的声明,其实现部分写在Talker.c中。
- j@j-desktop:~/test/examples/lesson6$ cat Talker.c
- /*
- * ======== lesson6/Talker.c ========
- */
- #include
- #include "package/internal/Talker.xdc.h"
- Void Talker_print()
- {
- Int i;
- for (i = 0; i < Talker_count; i++) {
- System_printf("%s\n", Talker_text);
- }
- }
复制代码
上面的代码中有两个头文件,最后一个是称为内部头文件,package/internal/Talker.xdc.h,显然不存在Talker.xdc.h文件,也没有internal文件夹,这是在编译时才产生的.
这种内部头文件必须写有所有其他头文件之后。这里写了Talker的print函数的实现。
对应prog.c和jprog.cfg,Talker.c也有一个Talker.xs文件:
- j@j-desktop:~/test/examples/lesson6$ cat Talker.xs
- /*
- * ======== lesson6/Talker.xs ========
- */
- function module$use()
- {
- xdc.useModule('xdc.runtime.System');
- }
复制代码
大家是否还记得useModule对应着.c文件中的include指令。这里显然没包括内部头文件,除了内部头文件,Talker.c中还包含了:#include
这里的function module$use()表明函数体的内容是某个外部函数调用useModule(lesson6.Talker)时返回的语句。
我们看prog.cfg里有一句:
- j@j-desktop:~/test/examples/lesson6$ cat prog.cfg
- /*
- * ======== lesson6/prog.cfg ========
- */
- var Talker = xdc.useModule('lesson6.Talker');
- Talker.text = "Goodnight Moon";
- Talker.count = 3;
复制代码
这实际上做在prog.cfg中展开成xdc.useModule('xdc.runtime.System').
最终是xdc.useModule('lesson6.Talker')对应prog.c中的#include ,而xdc.useModule('xdc.runtime.System')对应的是 Talker.c中的#include 。
另外还有一个函数module$validate可以用来验证某个条件是否成立,不成立最终可能停止编译。
下面可以编译了:
- j@j-desktop:~/test/examples/lesson6$ xdc all,64P
- generating interfaces for package lesson6 (because package/package.xdc.inc is older than package.xdc) ...
- translating Talker
- cl64P Talker.c ...
- cl64P package/package_lesson6.c ...
- archiving package/lib/lib/lesson6/Talker.o64P package/lib/lib/lesson6/package/package_lesson6.o64P into lib/lesson6.a64P ...
- configuring prog.x64P from package/cfg/prog_x64P.cfg ...
- cl64P prog.c ...
- cl64P package/cfg/prog_x64P.c ...
- lnk64P prog.x64P ...
- j@j-desktop:~/test/examples/lesson6$ xdc test,64P
- running prog.x64P ...
- Goodnight Moon
- Goodnight Moon
- Goodnight Moon
复制代码
下面我们可以看看编译前后的文件变化:
前:
- j@j-desktop:~/test/examples/lesson6$ xdc clean
- j@j-desktop:~/test/examples/lesson6$ ls
- lib package.xdc prog.cfg Talker.xdc
- package.bld prog.c Talker.c Talker.xs
复制代码
后:
- j@j-desktop:~/test/examples/lesson6$ ls
- lib package.bld package.xdc prog.cfg Talker.c Talker.xdc
- package package.mak prog.c prog.x64P Talker.h Talker.xs
复制代码
我们看到生成了Talker.h头文件,package.mak也是生成用来指导make编译的。prog.x64P是DSP的可执行文件。package是一个文件夹:
- j@j-desktop:~/test/examples/lesson6$ ls package
- build.cfg internal lesson6.sch package.defs.h package.xdc.dep
- cfg lesson6.ccs lib package.doc.xml package.xdc.inc
- external lesson6.pjt package.bld.xml package_lesson6.c rel
复制代码
我们看到现在有internal文件夹了,下面会不会有Talker.xdc.h呢?
- j@j-desktop:~/test/examples/lesson6$ ls package/internal/
- Talker.xdc.h
复制代码
有。
- j@j-desktop:~/test/examples/lesson6$ cat Talker.h |grep text
- String Talker_text;
- typedef xdc_String CT__lesson6_Talker_text;
- __extern __FAR__ const CT__lesson6_Talker_text lesson6_Talker_text__C;
- #define lesson6_Talker_text (lesson6_Talker_text__C)
- #define Talker_text lesson6_Talker_text
复制代码
我们可以看到Talker的text域的确是#define的。
我试了下去掉config,但是编译不通过了,呵呵。
好,第六课结束。
这个文章实际上是为读示例代码服务的,下面转而进入读代码系统的第四篇: codec engine代码阅读四---CE_DIR/examples/ti/sdo/ce/examles/codecs/videnc_copy(http://alphamailpost.blog.163.com/blog/static/20111808120127219241667/)
稍微总结了一下几个文件之间的关系,有不对的地方还请楼主改正:
prog.cfg中的var Talker = xdc.useModule('lesson6.Talker');对应prog.c中的#include
package.xdc:用来描述模块,一般只进行声明,
package lesson6 {
module Talker;
};
块的详细描述在Talker.xdc中,进行了函数的声明,常量的声明和初始化。
/*! Our first module */
module Talker {
/*! What to say */
config String text = "Hello World"; //这里的config相当于#define
/*! How many times */
config Int count = 1;
/*! Say it */
Void print();
}
函数的实现在Talker.c中
#include
#include "package/internal/Talker.xdc.h"(内部声明文件,可能有也可能在编译阶段生成,这种内部头文件必须写在所有其他头文件之后)
Void Talker_print()
{
Int i;
for (i = 0; i < Talker_count; i++) {
System_printf("%s\n", Talker_text);
}
}
Talker.c文件也有一个对应的文件Talker.xs。跟prog.c和prog.cfg的对应关系是一样的,只是Talker.xs中没有加Talker.c中包含的内部头文件
function module$use() //表明函数体的内容是某个外部函数调用useModule(lesson6.Talker)时返回的语句 ,这句没明白啥意思。
{
xdc.useModule('xdc.runtime.System');
}