📄 build.headers.html
字号:
<!-- Copyright (C) 2003 Red Hat, Inc. --><!-- This material may be distributed only subject to the terms --><!-- and conditions set forth in the Open Publication License, v1.0 --><!-- or later (the latest version is presently available at --><!-- http://www.opencontent.org/openpub/). --><!-- Distribution of the work or derivative of the work in any --><!-- standard (paper) book form is prohibited unless prior --><!-- permission is obtained from the copyright holder. --><HTML><HEAD><TITLE>Configuration Header File Generation</TITLE><meta name="MSSmartTagsPreventParsing" content="TRUE"><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+"><LINKREL="HOME"TITLE="The eCos Component Writer's Guide"HREF="cdl-guide.html"><LINKREL="UP"TITLE="The Build Process"HREF="build.html"><LINKREL="PREVIOUS"TITLE="The Build Process"HREF="build.html"><LINKREL="NEXT"TITLE="Building eCos"HREF="build.make.html"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">The <SPANCLASS="APPLICATION">eCos</SPAN> Component Writer's Guide</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="build.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 4. The Build Process</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="build.make.html"ACCESSKEY="N">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="BUILD.HEADERS">Configuration Header File Generation</H1><P>Configuration options can affect a build in two main ways. First,enabling a configuration option or other <SPANCLASS="APPLICATION">CDL</SPAN> entity can result invarious files being built and added to a library, thus providingfunctionality to the application code. However this mechanism can onlyoperate at a rather coarse grain, at the level of entire source files.Hence the component framework also generates configuration headerfiles containing mainly C preprocessor <TTCLASS="LITERAL">#define</TT>directives. Package source code can then <TTCLASS="LITERAL">#include</TT>the appropriate header files and use <TTCLASS="LITERAL">#if</TT>,<TTCLASS="LITERAL">#ifdef</TT> and <TTCLASS="LITERAL">#ifndef</TT> directives toadapt accordingly. In this way configuration options can be used toenable or disable entire functions within a source file or just asingle line, whichever is appropriate.</P><P>The configuration header files end up in the <TTCLASS="FILENAME">include/pkgconf</TT> subdirectory of theinstall tree. There will be one header file for the system as a whole,<TTCLASS="FILENAME">pkgconf/system.h</TT>, and there willbe additional header files for each package, for example<TTCLASS="FILENAME">pkgconf/kernel.h</TT>. The header filesare generated when creating or updating the build and install trees,which needs to happen after every change to the configuration.</P><P>The component framework processes each package in the configurationone at a time. The exact order in which the packages are processed isnot defined, so the order in which <TTCLASS="LITERAL">#define's</TT> willend up in the global <TTCLASS="FILENAME">pkgconf/system.h</TT> header may vary. Howeverfor any given configuration the order should remain consistent untilpackages are added to or removed from the system. This avoidsunnecessary changes to the global header file and hence unnecessaryrebuilds of the packages and of application code because of headerfile dependency handling.</P><P>Within a given package the various components, options and interfaceswill be processed in the order in which they were defined in thecorresponding <SPANCLASS="APPLICATION">CDL</SPAN> scripts. Typically the data in the configurationheaders consists only of a sequence of <TTCLASS="LITERAL">#define's</TT> sothe order in which these are generated is irrelevant, but someproperties such as <SPANCLASS="PROPERTY">define_proc</SPAN> can be used to add arbitrary data toa configuration header and hence there may be dependencies on theorder. It should be noted that re-parenting an option below some otherpackage has no effect on which header file will contain thecorresponding <TTCLASS="LITERAL">#define</TT>: the preprocessor directiveswill always end up in the header file for the package that defines theoption, or in the global configuration header.</P><P>There are six properties which affect the process of generating headerfiles:<AHREF="ref.define-header.html"><SPANCLASS="PROPERTY">define_header</SPAN></A>,<AHREF="ref.no-define.html"><SPANCLASS="PROPERTY">no_define</SPAN></A>,<AHREF="ref.define-format.html"><SPANCLASS="PROPERTY">define_format</SPAN></A>,<AHREF="ref.define.html"><SPANCLASS="PROPERTY">define</SPAN></A>,<AHREF="ref.if-define.html"><SPANCLASS="PROPERTY">if_define</SPAN></A>, and<AHREF="ref.define-proc.html"><SPANCLASS="PROPERTY">define_proc</SPAN></A>.</P><P>The <SPANCLASS="PROPERTY">define_header</SPAN> property can only occur in the body of a<TTCLASS="LITERAL">cdl_package</TT> command and specifies the name of the header file whichshould contain the package's configuration data, for example:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">cdl_package <some_package> { … define_header xyzzy.h}</PRE></TD></TR></TABLE><P>Given such a <SPANCLASS="PROPERTY">define_header</SPAN> property the component framework willuse the file <TTCLASS="FILENAME">pkgconf/xyzzy.h</TT> forthe package's configuration data. If a package does not havea <SPANCLASS="PROPERTY">define_header</SPAN> property then a suitable file name is constructedfrom the package's name. This involves:</P><P></P><OLTYPE="1"><LI><P>All characters in the package name up to and including the firstunderscore are removed. For example <TTCLASS="VARNAME">CYGPKG_KERNEL</TT>is converted to <TTCLASS="LITERAL">KERNEL</TT>, and<TTCLASS="VARNAME">CYGPKG_HAL_ARM</TT> is converted to<TTCLASS="LITERAL">HAL_ARM</TT>.</P></LI><LI><P>Any upper case letters in the resulting string will be converted tolower case, yielding e.g. <TTCLASS="LITERAL">kernel</TT> and<TTCLASS="LITERAL">hal_arm</TT>.</P></LI><LI><P>A <TTCLASS="LITERAL">.h</TT> suffix is appended, yielding e.g.<TTCLASS="LITERAL">kernel.h</TT> and <TTCLASS="LITERAL">hal_arm.h</TT>.</P></LI></OL><P>Because of the naming restrictions on configuration options, thisshould result in a valid filename. There is a small possibility of afile name class, for example <TTCLASS="VARNAME">CYGPKG_PLUGH</TT> and<TTCLASS="VARNAME">CYGPKG_plugh</TT> would both end up trying to use thesame header file <TTCLASS="FILENAME">pkgconf/plugh.h</TT>,but the use of lower case letters for package names violates thenaming conventions. It is not legal to use the <SPANCLASS="PROPERTY">define_header</SPAN>property to put the configuration data for several packages in asingle header file. The resulting behaviour is undefined.</P><P>Once the name of the package's header file has been determined and thefile has been opened, the various components, options and interfacesin the package will be processed starting with the package itself. Thefollowing steps are involved:</P><P></P><OLTYPE="1"><LI><P>If the current option or other <SPANCLASS="APPLICATION">CDL</SPAN> entity is inactive or disabled,the option is ignored for the purposes of header file generation.<TTCLASS="LITERAL">#define's</TT> are only generated for options that areboth active and enabled.</P></LI><LI><P>The next step is to generate a default <TTCLASS="LITERAL">#define</TT> forthe current option. If this option has a <SPANCLASS="PROPERTY">no_define</SPAN> property then thedefault <TTCLASS="LITERAL">#define</TT> is suppressed, and processingcontinues for <SPANCLASS="PROPERTY">define</SPAN>, <SPANCLASS="PROPERTY">if_define</SPAN> and <SPANCLASS="PROPERTY">define_proc</SPAN> properties.</P><P></P><OLTYPE="a"><LI><P>The header file appropriate for the default <TTCLASS="LITERAL">#define</TT>is determined. For a <TTCLASS="LITERAL">cdl_package</TT> this will be <TTCLASS="FILENAME">pkgconf/system.h</TT>, for any other option thiswill be the package's own header file. The intention here is thatpackages and application code can always determine which packages arein the configuration by <TTCLASS="LITERAL">#include'ing</TT> <TTCLASS="FILENAME">pkgconf/system.h</TT>. The C preprocessor lacksany facilities for including a header file only if it exists, andtaking appropriate action otherwise.</P></LI><LI><P>For options with the flavors <TTCLASS="LITERAL">bool</TT> or<TTCLASS="LITERAL">none</TT>, a single <TTCLASS="LITERAL">#define</TT> will begenerated. This takes the form:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">#define <option> 1</PRE></TD></TR></TABLE><P>For example:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">#define CYGFUN_LIBC_TIME_POSIX 1</PRE></TD></TR></TABLE><P>Package source code can check whether or not an option is active andenabled by using the <TTCLASS="LITERAL">#ifdef</TT>,<TTCLASS="LITERAL">#ifndef</TT> or <TTCLASS="LITERAL">#ifdefined(…)</TT>directives.</P></LI><LI><P>For options with the flavors <TTCLASS="LITERAL">data</TT> or<TTCLASS="LITERAL">booldata</TT>, either one or two<TTCLASS="LITERAL">#define's</TT> will be generated. The first of these maybe affected by a <SPANCLASS="PROPERTY">define_format</SPAN> property. If this property is notdefined then the first <TTCLASS="LITERAL">#define</TT> will take the form:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">#define <option> <value></PRE></TD></TR></TABLE><P>For example:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">#define CYGNUM_LIBC_ATEXIT_HANDLERS 32</PRE></TD></TR></TABLE><P>Package source code can examine this value using the<TTCLASS="LITERAL">#if</TT> directive, or by using the symbol incode such as:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING"> for (i = 0; i < CYGNUM_LIBC_ATEXIT_HANDLERS; i++) { … }</PRE></TD></TR></TABLE><P>It must be noted that the <TTCLASS="LITERAL">#define</TT> will be generatedonly if the corresponding option is both active and enabled. Optionswith the <TTCLASS="LITERAL">data</TT> flavor are always enabled but may notbe active. Code like the above should be written only if it is knownthat the symbol will always be defined, for example if thecorresponding source file will only get built if the containingcomponent is active and enabled. Otherwise the use of additional<TTCLASS="LITERAL">#ifdef</TT> or similar directives will be necessary.</P></LI><LI><P>If there is a <SPANCLASS="PROPERTY">define_format</SPAN> property then this controls how theoption's value will appear in the header file. Given a format stringsuch as <TTCLASS="LITERAL">%08x</TT> and a value 42, the componentframework will execute the <SPANCLASS="APPLICATION">Tcl</SPAN> command<TTCLASS="LITERAL">format %08x 42</TT> and the result will beused for the <TTCLASS="LITERAL">#define's</TT> value. It is theresponsibility of the component writer to make sure that this <SPANCLASS="APPLICATION">Tcl</SPAN>command will be valid given the format string and the legal values forthe option.</P></LI><LI><P>In addition a second <TTCLASS="LITERAL">#define</TT> may or may not begenerated. This will take the form:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">#define <option>_<value></PRE></TD></TR></TABLE><P>For example:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">#define CYGNUM_LIBC_ATEXIT_HANDLERS_32</PRE></TD></TR></TABLE><P>The <TTCLASS="LITERAL">#define</TT> will be generated only if it wouldresult in a valid C preprocessor symbol. If the value is a string suchas <TTCLASS="LITERAL">"/dev/ser0"</TT> then the <TTCLASS="LITERAL">#define</TT>would be suppressed. This second <TTCLASS="LITERAL">#define</TT> is notparticularly useful for numerical data, but can be valuable in othercircumstances. For example if the legal values for an option<TTCLASS="LITERAL">XXX_COLOR</TT> are <TTCLASS="LITERAL">red</TT>,<TTCLASS="LITERAL">green</TT> and <TTCLASS="LITERAL">blue</TT> then code likethe following can be used:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING">#ifdef XXX_COLOR_red …#endif#ifdef XXX_COLOR_green …#endif#ifdef XXX_COLOR_blue …#endif</PRE></TD></TR></TABLE><P>The expression syntax provided by the C preprocessor is limited tonumerical data and cannot perform string comparisons. By generatingtwo <TTCLASS="LITERAL">#define's</TT> in this way it is possible to workaround this limitation of the C preprocessor. However some care has tobe taken: if a component writer also defined a configuration option<TTCLASS="LITERAL">XXX_COLOR_green</TT> then there will be confusion. Sincesuch a configuration option violates the naming conventions, theproblem is unlikely to arise in practice.</P></LI></OL></LI><LI><P>For some options it may be useful to generate one or more additional<TTCLASS="LITERAL">#define's</TT> or, in conjunction with the <SPANCLASS="PROPERTY">no_define</SPAN>property, to define a symbol with a name different from the option'sname. This can be achieved with the <SPANCLASS="PROPERTY">define</SPAN> property, which takes thefollowing form:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRECLASS="PROGRAMLISTING"> define [-file=<filename>] [-format=<format>] <symbol></PRE></TD></TR></TABLE><P>For example:</P><TABLEBORDER="5"BGCOLOR="#E0E0F0"WIDTH="70%"><TR><TD><PRE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -