Build and install

Building ifw-fnd

Standard ESO IFW waf-module build:

cd ifw-fnd
waf configure install

Running the unit tests:

waf test --alltests

Build the user manual (this document) as part of install; HTML lands under ${DOCDIR}/sphinx/html.

Install layout

After waf install, the relevant artefacts are at:

$PREFIX/include/ifw/fnd/defs/      # public headers (base.hpp, logger.hpp, ...)
$PREFIX/include/ifw/fnd/tools/     # tools headers
$PREFIX/lib64/libifwFndDefs.so     # defs library
$PREFIX/lib64/libifwFndTools.so    # tools library
$PREFIX/share/wdep/ifw-fnd.defs.wdep    # wdep contract for waf consumers
$PREFIX/share/wdep/ifw-fnd.tools.wdep
$PREFIX/share/doc/ifw-fnd/sphinx/  # this manual

$PREFIX is whatever PREFIX / INTROOT is set to at install time (the usual ESO/IFW convention).

Consuming ifw-fnd from a waf project

A downstream waf project depends on ifw-fnd in two steps.

  1. Register the wdep at the project level (top-level wscript’s configure()):

    def configure(cnf):
        # ... your pkg-config and other deps ...
        wdeps = [
            "ifw-fnd.defs",
        ]
        for wdep in wdeps:
            cnf.check_wdep(wdep_name=wdep, uselib_store=wdep)
    

    Without this, the sub-module use= reference is a no-op. The wdep file is read at configure time and registers INCLUDES, LIB, LIBPATH under the chosen uselib_store.

  2. Reference the wdep at the target level (sub-module wscript):

    from wtools.module import declare_cshlib
    
    declare_cshlib(target='my_lib',
                   use='fmt ifw-fnd.defs')
    

Now the compiler resolves <ifw/fnd/defs/base.hpp> and the linker finds libifwFndDefs.so.

Consuming ifw-fnd from a CMake project

A downstream CMake project locates ifw-fnd via the standard find_path / find_library against $INTROOT / $PREFIX:

find_path(IFW_FND_INCLUDE_DIR
    NAMES ifw/fnd/defs/base.hpp
    HINTS $ENV{INTROOT}/include $ENV{PREFIX}/include /usr/local/include
)
find_library(IFW_FND_LIBRARY
    NAMES ifwFndDefs
    HINTS $ENV{INTROOT}/lib64 $ENV{INTROOT}/lib
          $ENV{PREFIX}/lib64 $ENV{PREFIX}/lib
          /usr/local/lib64 /usr/local/lib
)
if(NOT IFW_FND_INCLUDE_DIR OR NOT IFW_FND_LIBRARY)
    message(FATAL_ERROR "ifw-fnd not found (set INTROOT or PREFIX)")
endif()

target_include_directories(my_target PUBLIC ${IFW_FND_INCLUDE_DIR})
target_link_libraries(my_target PUBLIC ${IFW_FND_LIBRARY})

Then in your code:

#include <ifw/fnd/defs/base.hpp>

int main() {
    ifw::fnd::InstallLogger(ifw::fnd::MakeStdoutLogger());
    FNDINFO("hello {}", "world");
}

Common pitfalls

  • ``FNDTRACE not declared in this scope`` – usually means the consumer’s compile line is missing -I$INTROOT/include. Verify the waf project has registered ifw-fnd.defs via cnf.check_wdep (see above). The sub-module use='ifw-fnd.defs' alone is not sufficient.

  • Linker error about ``ifw::fnd::Log()`` or ``InstallLogger`` – the consumer compiles but doesn’t link libifwFndDefs.so. Add ifw-fnd.defs to the use= list (waf) or ${IFW_FND_LIBRARY} to target_link_libraries (CMake).

  • Runtime ``ifw-fnd: no logger installed`` – the executable never called InstallLogger. Either install one early in main(), or for unit tests install MakeNullLogger() in a global gtest SetUp step.

  • ``FNDTRACE`` placement error – the macro expands to a local variable declaration; it belongs at function body / scope statement level, not inside a conditional expression used as a single statement. Move it to the top of the enclosing block.