Re: Compiling header files independently as a test.

Steven Watanabe via Boost-build <[email protected]>
Newsgroups gmane.comp.lib.boost.build
Organization Providere Consulting, Inc.
Message-ID <[email protected]>
AMDG

On 03/16/2018 02:13 PM, Thomas Brown via Boost-build wrote:
> 
> I have found it useful to (and there are some that require) test
> header file independence by including it by itself in a source file
> and checking that it compiles.  For example, the Bloomberg  BDE
> project states that the ".h file of each component should contain only
> those #include directives (and forward class declarations) necessary
> to ensure that the header file can compile in isolation."
> (https://github.com/bloomberg/bde/wiki/physical-code-organization).
> 
> I have been exploring doing this with Boost.Build and while I've
> figured out a way to get it done, it is not nearly as nice as I'd like
> it to be.  Does anyone have a better approach?  if not, could we add
> something to testing.jam to support this directly?
> 
> I've cobbled together some code that works for me but has several
> limitations that I don't like and don't know how to fix.
> 
> 1. I implement the tests in the library's Jamfile since that is where
> the actual header file names are known.  I actually put all required
> files (headers, sources, etc.) in the sources list of the alias or
> lib.  Is that something others are doing?  This forces me to put the
> source file names and header file names into separate variables so I
> can iterate over them.  I also do this in order to specify the sources
> for a doxygen target within Boost.Build.
> 

  I've never seen that before.  Listing the headers
as sources for a library will just cause them to
be ignored.

>   I have a separate Jamfile for tests to simplify using just the
> library with other Boost.Build-based projects.  I'd prefer to have all
> the tests together, but I don't want to repeat the headers nor use a
> glob.
> 
>   I might consider using a glob, but that would again be in the
> library definition, not the test file.
> 
> 2. I'd really prefer to iterate through the sources of any target (at
> least any alias or lib) to run the compile-header tests in the test
> Jamfile without knowing what they are named.  This would actually make
> it possible to have a separate Jamfile to generate doxygen as well.
> 

Iterating over the sources of a target is a bad idea.
Instead, use an alias and handle the processing at the
virtual target layer (via generate, a generator, or
a custom target class).  In particular, for checking
headers, you can use a composing generator to handle
all of the following:
- compile each header in a separate translation unit.
- include all headers in a single translation unit (useful
  for catching duplicate #include guards)
- link two translation units that #include all headers.  (catches
  functions that should be inlined)

> 3. The "compile-header" target might require more information if the
> library has dependencies, which have to be specified in both the
> library and the compile-header targets.  This seems to usually be
> handled by depending on the library itself in the compile-header
> target, so maybe it's not a big deal, but it is a bit strange to say
> that compiling the header that is part of libx depends on libx.
> 

<use>libx will pick up the usage-requirements, but otherwise
ignore libx, which I think is the behavior you want.

> I've included inline some code that reflects what I am currently
> doing.  It is extremely preliminary.  I could see, at the minimum,
> adding a "compile-header" and maybe "compile-header-fail" (not
> implemented here)

I don't think that compile-header-fail is useful.

> that generates a source file and attempts to compile
> it to testing.jam.  However, this approach still leaves a lot of
> boilerplate to the user and requires the tests are in the same Jamfile
> as the alias / lib target definition.
> 
> I would not mind doing the work to get something in if others agree on
> the concept and an approach to implement it.
> 
> Best regards,
> Tom
> 
> 1. I have a local testing-additions.jam file that adds a "compile-header" rule
> 
> ```
> # testing-additions.jam
> import testing ;
> 
> # generate a source file and check for compile success
> rule compile-header ( sources : requirements * : target-name ? )
> {
>   local s ;
>   local t ;
> 
>   if ! $(target-name)
>   {
>     target-name = compile_test_$(sources:D=:S=) ;
>   }
> 
>   s = $(target-name).cpp ;
> 
>   make $(s) : $(sources) : @testing-additions.generate-source-for-header ;
> 
>   compile $(s) : $(requirements) : $(target-name) ;
> }
> 
> actions generate-source-for-header
> {
>   echo "" > $(<)
>   echo "#include \"$(>)\"" >> $(<)
>   echo "int main () { return 0; }" >> $(<)
>   echo "" >> $(<)
> }
> ```
> 
> 2. Wherever I have header files in my projects (in an alias or a lib,
> etc).  I do something like the following.
> 
> ```
> # a Jamfile for the header-only library libx
> import testing-additions ;
> 
> # other header-only libraries that libx depends on
> alias dep0 ;
> alias dep1 ;
> 
> local headers =
>   x0.hpp
>   x1.hpp
>   x2.h
>   ;
> 
> alias libx
>   : # sources
>     $(headers)
> 
>     dep0
>     dep1
> 
>   : # requirements
>   : # default-build
>   : # usage-requirements
>     <include>src
>   ;
> 
> for h in $(headers)
> {
>   compile-header $(h) : <dependency>libx ;
> }
> ```
> 
_______________________________________________
Unsubscribe & other changes: https://lists.boost.org/mailman/listinfo.cgi/boost-build
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.