File auctioning

Help
saber850
2004-08-06
2004-08-09
  • saber850
    saber850
    2004-08-06

    Can someone explain to me (or point me to some documentation on) how the file auctioning works in cpptask?
    From my rudimentary understanding, each file is auctioned to the compiler(s) and if it's not accepted, to the linker(s).

    Here's my situation:
    I have a project that contains C and C++ files.  I'm trying to compile w/ GCC.
    My stripped-down setup is essentially:

    <cc>
       <fileset dir="foo" includes="*.cpp,*.c,*.h" />
       <compiler name="gcc" />
       <compiler name="g++" />
    </cc>

    But when I run it, all the files are compiled by the first <compiler> element listed only.  So the C++ files (which have a .cpp extension) are sent to gcc, or the C files (which have a .c extension) are sent to g++.

    One solution I can think of is to specify a separate fileset as a child to each <compiler> element, and exclude the appropriate extension.  But is there a method such that I don't have to duplicate the <fileset> element?

     
    • Curt Arnold
      Curt Arnold
      2004-08-06

      gcc and g++ have the same source extension list.  That is they both bid on .c files and .cpp and don't bid on .idl, .res, .java, .pas, etc.   So when foo.cpp is sent out for bidding gcc, g++ and the implicit gcc from the cc element all bid 100, but since the explicit gcc is the first bidder, it wins all ties.  If you flipped the order, then g++ would win all the bids.

      If there are a few files that you want to steer to a particular compiler configuration (typically when it requires a few different defines or such), then you can include a fileset within a compiler element.  You do not need to try to exclude these files from the default compiler since the task will prevent one file from being compiled by multiple compilers.

      Compilers will make token bids on include files (.h files in this instance) so they are not passed through to the linker, but otherwise ignore them.  However, explicitly forcing header files to be bid and discarded by having *.h in the includes pattern is unnecessary.

      I don't know why you wouldn't let g++ compile all the files, but if you wanted gcc to compile the "*.c" and g++ to compile all the rest.

      <cc name="gcc">
      <fileset dir="foo" includes="*.cpp" />
      <compiler name="g++" />
      <compiler name="gcc">
         <fileset dir="foo" includes="*.c"/>
      </compiler>
      </cc>

       
      • saber850
        saber850
        2004-08-06

        Thanks for the info.

        g++ (at least v3.4) can't compile certain C code.  I wasn't aware of this until I tried compiling the zlib library (http://www.gzip.org/zlib).  It throws errors on methods that have different definitions (due to preprocessor macros).

        Out of curiosity, does it makes sense to lower the compiler's bidding a touch for the file it's not intended for?  For example, g++ would bid 99 for .c files instead of 100, and gcc would bid 99 for .cpp files.  This way, if both compilers are specified, the appropriate one would win, but both can handle the file in the absense of the other.

         
      • saber850
        saber850
        2004-08-06

        Not sure if this is a bug, but your suggestion:

        <cc name="gcc">
        <fileset dir="foo" includes="*.cpp" />
        <compiler name="g++" />
        <compiler name="gcc">
        <fileset dir="foo" includes="*.c"/>
        </compiler>
        </cc>

        did not work.

        I had to explicitly exclude *.cpp in the gcc compiler's fileset:

        <cc name="gcc">
        <fileset dir="foo" includes="*.cpp" />
        <compiler name="g++" />
        <compiler name="gcc">
        <fileset dir="foo" includes="*.c" excludes="*.cpp"/>
        </compiler>
        </cc>

         
        • Curt Arnold
          Curt Arnold
          2004-08-06

          I wouldn't use 99 since they leaves no space for further refinement.  The only values currently in use are 0 (not recognized), 1 (header files) and 100 (default).  The current implementation of the Gcc compilers takes an undifferentiated array of source extensions and an array of header extensions, so that would need to be reworked if multiple bid levels were to be supported.  But it would make sense that, for example, g77 would win the bidding for ".f" files over gcc.

          The excludes="*.cpp" behavior is curious.  The fileset is a wrapper on the base Ant fileset (adding if and unless attributes) and the compiler just sees the matching files.  However, the set of matching files for includes="*.c" should not be modified by a non intersecting excludes clause like "*.cpp".  If you attempt to <copy><fileset dir="foo" includes="*.cpp"/></copy> are .cpp files copied too?  If so that seems like a pretty serious Ant bug to me.  Is it present in the most current CVS build?

           
          • saber850
            saber850
            2004-08-06

            Yeah, I just chose 99 as an arbitrarily close number.  Actually, if the returned "bid" was a float, you wouldn'thave to worry about running out of space.  You can always squeeze something in between.

            Regarding the excludes="*.cpp" behavior, I wonder if it has to do w/ the fileset.  These are my actual filesets:

            In the <cc> element:
            <fileset
                dir="${SrcDir}"
                includesfile="SourceFiles.list"
                includes="*.cpp" />

            In the gcc compiler element:
            <fileset
                dir="${SrcDir}"
                includesfile="SourceFiles.list"
                includes="*.c"
                excludes="*.cpp" />

            As you can see, the list of files is coming from a file.  I'm not grabbing everything from a particular directory.  Not sure if this makes a difference.

            I'm using Ant 1.6.1 and the latest released version of cpptask.

             
            • Curt Arnold
              Curt Arnold
              2004-08-07

              There is still an epsilon and you would still eventually run out of distinguishable values with a float.  Since we are only using 3 values out of 4 billion and can rescale without penalty, I don't see any motivation to switch to a float.

              Throwing the includesfile definitely changes things, it effectively adds the patterns in the file to the includes attribute.  What I think that you would want to do is (take your pick of three different nested filesets)

              <cc>
                 <fileset dir="${src.dir}" includesfiles="SourceFiles.list"/>
                 <compiler name="gcc">
                     <!-- one of the following  -->
                     <!--  compile all *.c files  -->
                     <fileset dir="${src.dir}" include=*.c"/>
                     <!--  compile all files in .list that don't end with *.cpp  -->
                      <fileset dir="${src.dir}" includesfiles="SourceFiles.lists" excludes="*.cpp"/>
                      <!--  if there are specific files that you want to compile with gcc -->
                       <fileset dir="${src.dir}" includes="foo.c"/>
                 </compiler>
              <cc>

              Your existing fragment would compile all files in SourceFiles.list AND all files matching *.cpp and *.c.

               
              • saber850
                saber850
                2004-08-09

                > you would still eventually run out of distinguishable values with a float
                True, but you would run out of distinguishable values with a int much sooner, especially if the range is 0 - 100.
                Certainly there is a limit to how many values can be squeezed in-between a float, but it's far more than will ever be needed.  I figured if there are several compilers which are close to one another and have dependencies, it will require more work to determine and reassign the bids w/ an integral value.  Whereas you can insert a value in between any other two w/ a float.
                Now that I think about it, the determination of the correct bids would be the difficult part (tracing down dependencies) and thus the most error prone.
                Don't get me wrong, this isn't a feature request or anything, I just figured I'd mention it.  Afterall, we're discussing a once-in-a-blue-moon situation.

                Thanks for the fileset suggestions.  I'm currently using the 2nd one successfully.
                While on the topic, I have a question regarding filesets.  When using the "includesfile" property, is it possible to list filenames w/ paths (as opposed to just filenames)?
                Let's say I have this tree:
                +-foo.cpp
                +-bar.cpp
                +-sub/foo.c
                +-sub/bar.c

                Can I assign the "includesfile" property to a file w/ these contents:
                foo.cpp
                bar.cpp
                sub/foo.c
                sub/bar.c

                The reason I ask is that it seems if the files have a "./" prefix (ie. ./foo.cpp), it gets ignored.

                 
                • Curt Arnold
                  Curt Arnold
                  2004-08-09

                  From the documentation, it seems that you should be able to use anything that you could use in the includes attribute.  If you are seeing unusual behavior, then try to reproduce it using a standard Ant task, copy for example, and report it as an Ant bug or ask a question on the ant-users list.  You can cc me if you'd like.  cpptasks just wraps the Ant fileset and inherits any underlying bugs that it has.