Move on.

Moved all my stuff to my new blog: nazavode.github.io

See you there!

Idiomatic C++

A minimal collection of most wanted and widely accepted idioms and coding conventions for C++ development presented with examples and comments. The lecture targets performance oriented codes so emphasis is on performance-friendly techiques.

Topics covered:
1. Design issues: idioms and best practices

  • Resource Aquisition Is Initialization (RAII)
  • Ownership semantics and smart pointers
  • Header files: dependencies and decoupling

2. Objects Construction/Destruction/Copying

  • Designing constructors
  • Rule Of Three
  • Transactional programming

3. Namespaces

  • ADL/Koenig Lookup

4. Static analyzers survey

You can find full presentation materials here.

Advertisement
Tagged , , , , , , , , , , ,

How to generate code documentation with Doxygen and CMake: a (slightly) improved approach.

Well, after days of hard work we ended up with our lovely code base, a portable CMake build system and we are now facing the task to generate an elegant Doxygen documentation for our anxious customer. The typical solution, widely adopted, seems to be the one and only that can be found while googling:

#-- Add an Option to toggle the generation of the API documentation
option(BUILD_DOCUMENTATION "Use Doxygen to create the HTML based API documentation" OFF)
if(BUILD_DOCUMENTATION)
  FIND_PACKAGE(Doxygen)
  if (NOT DOXYGEN_FOUND)
    message(FATAL_ERROR
      "Doxygen is needed to build the documentation. Please install it correctly")
  endif()
  #-- Configure the Template Doxyfile for our specific project
  configure_file(Doxyfile.in
                 ${PROJECT_BINARY_DIR}/Doxyfile  @ONLY IMMEDIATE)
  #-- Add a custom target to run Doxygen when ever the project is built
  add_custom_target (Docs ALL
                     COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/Doxyfile
                     SOURCES ${PROJECT_BINARY_DIR}/Doxyfile)
  # IF you do NOT want the documentation to be generated EVERY time you build the project
  # then leave out the 'ALL' keyword from the above command.
endif()

Well, even if the above solution works like a charm, it exposes a flaw that makes itself very annoying: Doxygen will be triggered every time we run make, even if nothing has changed. Oh, when I say “every time”, I mean exactly that: each make invocation (make, make install, etc…) will flood your shell with the utterly verbose output from Doxygen even if that step is obviously useless. Yes, we have added that ALL flag to ADD_CUSTOM_TARGET but this is the only way to have our documentation generated along with the default targets (otherwise our BUILD_DOCUMENTATION flag would be ignored except for an explicit make doc). This behavior is correct and the point is well highlighted in the CMake reference for ADD_CUSTOM_TARGET:

The target has no output file and is ALWAYS CONSIDERED OUT OF DATE even if the commands try to create a file with the name of the target. Use ADD_CUSTOM_COMMAND to generate a file with dependencies.

So, it seems that we are using the wrong tool. How can we add a Doxygen target with a real dependency checking? The neat trick lies in the combined use of two different commands:

  1. ADD_CUSTOM_COMMAND will take care of dependency checking, firing up Doxygen if and only if something (which the documentation depends on) has really changed since last build;
  2. ADD_CUSTOM_TARGET will allow us to have a convenient and elegant make doc target, eventually added to default set.

After a bit of trial-and-error, I ended up with a bunch of lines of code that seems to work as we wanted:

option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" OFF)
IF(BUILD_DOCUMENTATION)

  FIND_PACKAGE(Doxygen)
  IF(NOT DOXYGEN_FOUND)
    MESSAGE(FATAL_ERROR
      "Doxygen is needed to build the documentation.")
  ENDIF()

  SET( doxyfile_in          ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in     )
  SET( doxyfile             ${PROJECT_BINARY_DIR}/Doxyfile              )
  SET( doxy_html_index_file ${CMAKE_CURRENT_BINARY_DIR}/html/index.html )
  SET( doxy_output_root     ${CMAKE_CURRENT_BINARY_DIR}                 ) # Pasted into Doxyfile.in
  SET( doxy_input           ${PROJECT_SOURCE_DIR}/src                   ) # Pasted into Doxyfile.in
  SET( doxy_extra_files     ${CMAKE_CURRENT_SOURCE_DIR}/mainpage.dox    ) # Pasted into Doxyfile.in

  CONFIGURE_FILE( ${doxyfile_in} ${doxyfile} @ONLY )

  ADD_CUSTOM_COMMAND( OUTPUT ${doxy_html_index_file}
                      COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
                      # The following should be ${doxyfile} only but it
					  # will break the dependency.
                      # The optimal solution would be creating a 
					  # custom_command for ${doxyfile} generation
					  # but I still have to figure out how...
                      MAIN_DEPENDENCY ${doxyfile} ${doxyfile_in}
                      DEPENDS project_targets ${doxy_extra_files}
                      COMMENT "Generating HTML documentation")

  ADD_CUSTOM_TARGET( doc ALL DEPENDS ${doxy_html_index_file} )

  INSTALL( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc )
ENDIF()

The point is that we still have our doc custom target (added to default targets) that is going to be fired forever but the actual build step is “shielded” by the custom command that will check for the right dependencies. Just a couple of remarks:

  1. the DEPENDS option on the custom command must list all of the targets, files and whatever your documentation depends on;
  2. the ${doxyfile_in} dependecy is an overshoot but, as I say in the comment, removing it will break the dependency checking. The ideal solution would be specifying ${doxyfile} only, letting it to trigger a lower-level custom command intended to configure and generate ${doxyfile_in}. I’m still trying to find an elegant solution to this little aesthetic stain.

Thats all folks!

Resources:
* [1] CMake Reference Manual
* [2] Use Doxygen with a CMake Based Project

Tagged , ,