Skip to content
114 changes: 90 additions & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ project(
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()

message(VERBOSE "*")
message(VERBOSE "* ${PROJECT_NAME} v${PROJECT_VERSION} (${CMAKE_BUILD_TYPE})")
message(VERBOSE "* Copyright (c) 2017-2026 Michele Caini <michele.caini@gmail.com>")
Expand All @@ -37,6 +37,13 @@ list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
option(ENTT_USE_LIBCPP "Use libc++ by adding -stdlib=libc++ flag if available." OFF)
option(ENTT_USE_SANITIZER "Enable sanitizers by adding -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined flags if available." OFF)
option(ENTT_USE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF)
option(ENTT_MODULE "Build EnTT module instead of a regular header-only library." OFF)

set(ENTT_USER_CONFIG "" CACHE FILEPATH "Path to a file containing user EnTT configuration.")

if (NOT ENTT_MODULE AND ENTT_USER_CONFIG)
message(FATAL_ERROR "The option ENTT_USER_CONFIG can be used only when ENTT_MODULE is ON")
endif()

if(ENTT_USE_LIBCPP)
if(NOT WIN32)
Expand Down Expand Up @@ -83,25 +90,54 @@ endif()

include(GNUInstallDirs)

add_library(EnTT INTERFACE)
if (ENTT_MODULE)
if (CMAKE_VERSION VERSION_LESS 3.28)
message(FATAL_ERROR "CMake >= 3.28 is required to build EnTT as a module")
endif()

set(ENTT_LIBRARY_TYPE STATIC)
set(ENTT_SCOPE PUBLIC)
else()
set(ENTT_LIBRARY_TYPE INTERFACE)
set(ENTT_SCOPE INTERFACE)
endif()

add_library(EnTT ${ENTT_LIBRARY_TYPE})
add_library(EnTT::EnTT ALIAS EnTT)

target_include_directories(
EnTT
INTERFACE
${ENTT_SCOPE}
$<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

target_compile_features(EnTT INTERFACE cxx_std_20)

if(ENTT_HAS_LIBCPP)
target_compile_options(EnTT BEFORE INTERFACE -stdlib=libc++)
target_compile_options(EnTT BEFORE ${ENTT_SCOPE} -stdlib=libc++)
if(ENTT_MODULE)
target_link_options(EnTT ${ENTT_SCOPE} -stdlib=libc++)
endif()
endif()

if(ENTT_HAS_SANITIZER)
target_compile_options(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>)
target_link_libraries(EnTT INTERFACE $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>)
target_compile_options(EnTT ${ENTT_SCOPE} $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>)
target_link_options(EnTT ${ENTT_SCOPE} $<$<CONFIG:Debug>:-fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined>)
endif()

if (ENTT_USER_CONFIG)
target_compile_definitions(EnTT ${ENTT_SCOPE} ENTT_USER_CONFIG=\"${ENTT_USER_CONFIG}\")
endif()

if (ENTT_MODULE)
target_sources(EnTT
PUBLIC
FILE_SET cxx_modules TYPE CXX_MODULES
BASE_DIRS ${EnTT_SOURCE_DIR}/src/entt
FILES
${EnTT_SOURCE_DIR}/src/entt/entt.ixx
)
endif()

if(ENTT_CLANG_TIDY_EXECUTABLE)
Expand Down Expand Up @@ -295,11 +331,22 @@ if(ENTT_INSTALL)

include(CMakePackageConfigHelpers)

install(
TARGETS EnTT
EXPORT EnTTTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
if(ENTT_MODULE)
install(
TARGETS EnTT
EXPORT EnTTTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILE_SET cxx_modules DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/entt
)
else()
install(
TARGETS EnTT
EXPORT EnTTTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
endif()

write_basic_package_version_file(
EnTTConfigVersion.cmake
Expand All @@ -313,18 +360,37 @@ if(ENTT_INSTALL)
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
)

export(
EXPORT EnTTTargets
FILE ${CMAKE_CURRENT_BINARY_DIR}/EnTTTargets.cmake
NAMESPACE EnTT::
)
if(ENTT_MODULE)
export(
TARGETS EnTT
FILE "${CMAKE_CURRENT_BINARY_DIR}/EnTTTargets.cmake"
NAMESPACE EnTT::
CXX_MODULES_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/cxx-modules"
)
else()
export(
TARGETS EnTT
FILE "${CMAKE_CURRENT_BINARY_DIR}/EnTTTargets.cmake"
NAMESPACE EnTT::
)
endif()

install(
EXPORT EnTTTargets
FILE EnTTTargets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
NAMESPACE EnTT::
)
if(ENTT_MODULE)
install(
EXPORT EnTTTargets
FILE EnTTTargets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
NAMESPACE EnTT::
CXX_MODULES_DIRECTORY ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake/cxx-modules
)
else()
install(
EXPORT EnTTTargets
FILE EnTTTargets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/EnTT/cmake
NAMESPACE EnTT::
)
endif()

install(
FILES
Expand Down Expand Up @@ -357,12 +423,12 @@ if(ENTT_BUILD_TESTING OR ENTT_BUILD_TESTBED)
# Tests and tesetbed do not work together because SDL gets confused with EnTT tests
if(ENTT_BUILD_TESTING)
option(ENTT_FIND_GTEST_PACKAGE "Enable finding gtest package." OFF)

option(ENTT_BUILD_BENCHMARK "Build benchmark." OFF)
option(ENTT_BUILD_EXAMPLE "Build examples." OFF)
option(ENTT_BUILD_LIB "Build lib tests." OFF)
option(ENTT_BUILD_SNAPSHOT "Build snapshot test with Cereal." OFF)

include(CTest)
enable_testing()
add_subdirectory(test)
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ mind.

```cpp
#include <entt/entt.hpp>
// or import entt;
// See Integration > CMake for details.

struct position {
float x;
Expand Down Expand Up @@ -246,6 +248,9 @@ using `EnTT` as a submodule without conflicting with user logic.<br/>
It is therefore necessary to set the option to true to take advantage of the
installation logic provided by this library.

Note that `EnTT` can be consumed also as a C++ module. To enable module support,
the `ENTT_MODULE` option has to be set to `ON` in `CMake`.

## Natvis support

When using `CMake`, just enable the option `ENTT_INCLUDE_NATVIS` and enjoy
Expand Down
32 changes: 32 additions & 0 deletions docs/md/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,35 @@ paths appropriately.<br/>
For example, `CMake` allows users to _bind_ additional include directories to a
target with `target_include_directories`. See the test suite, and in particular
the `config_ext` test for a practical example.

## When consumed as a module

When `EnTT` is consumed as a C++20 module, all the above definitions can be
put into a custom configuration file that can be referred to through the
`ENTT_USER_CONFIG` compile definition using its path. <br/>

In case the module is built through CMake, the variable
`ENTT_USER_CONFIG` can be set directly from the `CMakeLists.txt` file before
including the library through `add_subdirectory`.<br/>

Example of a custom configuration file and CMake setup:
```c++
// user_config.h

#define ENTT_ID_TYPE std::uint64_t
#define ENTT_USE_ATOMIC
```
```c++
// CMakeLists.txt
set(ENTT_MODULE ON)
set(ENTT_USER_CONFIG "path/to/user_config.h")
...
add_subdirectory(path/to/entt)
...
target_link_libraries(your_target PUBLIC EnTT::EnTT)
```
16 changes: 16 additions & 0 deletions src/entt/config/module.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifndef ENTT_MODULE_H
#define ENTT_MODULE_H

#ifndef ENTT_MODULE_EXPORT
# define ENTT_MODULE_EXPORT
#endif // ENTT_MODULE_EXPORT

#ifndef ENTT_MODULE_EXPORT_BEGIN
# define ENTT_MODULE_EXPORT_BEGIN
#endif // ENTT_MODULE_EXPORT_BEGIN

#ifndef ENTT_MODULE_EXPORT_END
# define ENTT_MODULE_EXPORT_END
#endif // ENTT_MODULE_EXPORT_END

#endif // ENTT_MODULE_H
Loading