Tutorial Step 10: missing header 'mathfunctions_export.h'

I’m just run through Step 10 of the Tutorial, and am trying to use the GenerateExportHeader module.
However, when I build, I get the error:

fatal error: mathfunctions_export.h: No such file or directory
   10 | #include "mathfunctions_export.h"

In MathFunctions/CMakeFiles.txt I’ve added:

include(GenerateExportHeader)
generate_export_header(MathFunctions)

I can see the generated file: ‘Step10_build/MathFunctions/mathfunctions_export.h’.

MathFunctions.h includes the new generated file.

What am I missing?

Probably missing target_include_directories() or linking to the library target?
I am not familiar with that project, and you haven’t provided what you have.

This is the link to Step 10 of the tutorial: Step 10

MathFunctions/CMakeLists.txt includes:

target_include_directories(MathFunctions
                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
                           )

The source code is held at: tutorial archive

This is the contents of my Step10_build/MathFunctions folder:
CMakeFiles cmake_install.cmake libSqrtLibrary.a Makefile MakeTable mathfunctions_export.h Table.h

The missing line is the following??:
target_include_directories(MathFunctions PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

This should help:

# cmake-format: off
target_sources(
  MathFunctions PUBLIC
    FILE_SET HEADERS
    BASE_DIRS ${PROJECT_BINARY_DIR}
    FILES ${PROJECT_BINARY_DIR}/mathfunctions_export.h
)
# cmake-format: on

Hi, @ClausKlein Is that an alternative to my solution where I set the target_include_directories? Or should I be using ‘target_sources’ instead?

This is the modern way to set the include path and install public headers.

@ClausKlein I’ve updated my MathFunctions/CMakeLists.txt with your change.
Like so:

include(GenerateExportHeader)
add_library(MathFunctions MathFunctions.cxx )
generate_export_header(MathFunctions EXPORT_FILE_NAME 
                        ${PROJECT_BINARY_DIR}/exports/mathfunctions_export.h)
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
target_include_directories(MathFunctions
                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
                           )
target_sources(
  MathFunctions PUBLIC
    FILE_SET HEADERS
    BASE_DIRS ${PROJECT_BINARY_DIR}
    FILES ${PROJECT_BINARY_DIR}/exports/mathfunctions_export.h
)

But still get the error message:

Step10/MathFunctions/MathFunctions.h:10:10: fatal error: mathfunctions_export.h: No such file or directory
   10 | #include "mathfunctions_export.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

Clearly I’m still missing something obvious here :frowning:

include(GenerateExportHeader)
generate_export_header(MathFunctions EXPORT_FILE_NAME
                       ${CMAKE_CURRENT_BINARY_DIR}/exports/mathfunctions_export.h
                       )

# cmake-format: off
target_sources(
  MathFunctions PUBLIC
    FILE_SET HEADERS
    BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
    FILES ${CMAKE_CURRENT_BINARY_DIR}/exports/mathfunctions_export.h
          ${CMAKE_CURRENT_SOURCE_DIR}/MathFunctions.h

)
# cmake-format: on

The include path is set to CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR.

And the “EXPORTING_MYMATH” is not longer needed and wrong.

Do not forget to install it:

install(TARGETS ${installable_libs} DESTINATION lib FILE_SET HEADERS)

Thanks @ClausKlein, that works very well, and keeps the exported headers during build local to the library. It also installs perfectly. My final version (hopefully) is as follows:

include(GenerateExportHeader)

# add the library that runs
add_library(MathFunctions MathFunctions.cxx )

generate_export_header(MathFunctions EXPORT_FILE_NAME 
                         ${CMAKE_CURRENT_BINARY_DIR}/exports/mathfunctions_export.h)

# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
                           )

target_include_directories(MathFunctions PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/exports)

#BASE_DIRS ${PROJECT_BINARY_DIR}
target_sources(
  MathFunctions PUBLIC
    FILE_SET HEADERS
    BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
    FILES ${CMAKE_CURRENT_BINARY_DIR}/exports/mathfunctions_export.h
         ${CMAKE_CURRENT_SOURCE_DIR}/MathFunctions.h
)

# link MathFunctions to tutorial_compiler_flags
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)

# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
  list(APPEND installable_libs SqrtLibrary)
endif()

install(TARGETS ${installable_libs} DESTINATION lib FILE_SET HEADERS)

# install include headers
install(FILES MathFunctions.h DESTINATION include)

However I assume there should not be any reason why I can’t change the build to use ‘USE_MYMATH’.

The calls to

should not be needed.

And the last install(FILES ...) call is also not needed.

@ben.boeckel should we modernize the Tutorial?

2 Likes

Thanks for all your help @ClausKlein !
I still seemed to need just one target_include_directories(). It will not build otherwise.

Have removed the final install(FILES ...)
Installs OK!

This looks a lot tidier :grinning: :

include(GenerateExportHeader)

# add the library that runs
add_library(MathFunctions MathFunctions.cxx )

generate_export_header(MathFunctions EXPORT_FILE_NAME 
                         ${CMAKE_CURRENT_BINARY_DIR}/exports/mathfunctions_export.h)

target_include_directories(MathFunctions PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/exports)

target_sources(
  MathFunctions PUBLIC
    FILE_SET HEADERS
    BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
    FILES ${CMAKE_CURRENT_BINARY_DIR}/exports/mathfunctions_export.h
         ${CMAKE_CURRENT_SOURCE_DIR}/MathFunctions.h
)

# link MathFunctions to tutorial_compiler_flags
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)

# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
  list(APPEND installable_libs SqrtLibrary)
endif()

install(TARGETS ${installable_libs} DESTINATION lib FILE_SET HEADERS)

I would not use this exports subdirectory!

-- Install configuration: ""
-- Installing: /usr/local/lib/libMathFunctions.dylib
-- Installing: /usr/local/lib/MathFunctions.h
-- Installing: /usr/local/lib/exports/mathfunctions_export.h
-- Installing: /usr/local/lib/libSqrtLibrary.a
-- Installing: /usr/local/bin/Tutorial
-- Installing: /usr/local/include/TutorialConfig.h
bash-5.2$ 

If you do, you must also change your code:

#pragma once

#include <exports/mathfunctions_export.h>

namespace mathfunctions {
double MATHFUNCTIONS_EXPORT sqrt(double x);
}

This

target_include_directories(MathFunctions PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/exports)

helps you build your code, but does not help the user trying to use your installed files!

Thanks @ClausKlein that’s a very valid point. With just that final change I have:

include(GenerateExportHeader)

# add the library that runs
add_library(MathFunctions MathFunctions.cxx )

generate_export_header(MathFunctions EXPORT_FILE_NAME 
                         ${CMAKE_CURRENT_BINARY_DIR}/mathfunctions_export.h)

target_include_directories(MathFunctions PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

target_sources(
  MathFunctions PUBLIC
    FILE_SET HEADERS
    BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
    FILES ${CMAKE_CURRENT_BINARY_DIR}/mathfunctions_export.h
         ${CMAKE_CURRENT_SOURCE_DIR}/MathFunctions.h
)

# link MathFunctions to tutorial_compiler_flags
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)

# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
  list(APPEND installable_libs SqrtLibrary)
endif()

install(TARGETS ${installable_libs} DESTINATION lib FILE_SET HEADERS)

This builds correctly. And when I install, I get:

-- Install configuration: ""
-- Installing: /usr/local/lib/libMathFunctions.so
-- Installing: /usr/local/lib/mathfunctions_export.h
-- Up-to-date: /usr/local/lib/MathFunctions.h
-- Installing: /usr/local/bin/Tutorial
-- Set non-toolchain portion of runtime path of "/usr/local/bin/Tutorial" to ""
-- Installing: /usr/local/include/TutorialConfig.h

Many thanks! :grinning: