Skip to content

Commit

Permalink
Merge pull request #3529 from rcurtin/stb-header-detect
Browse files Browse the repository at this point in the history
Add mlpack/config.hpp and automatic CMake configuration
  • Loading branch information
rcurtin committed Sep 1, 2023
2 parents a013f07 + be9708d commit 1a6100a
Show file tree
Hide file tree
Showing 19 changed files with 286 additions and 64 deletions.
43 changes: 27 additions & 16 deletions CMake/FindStbImage.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,44 @@
# This module sets the following variables:
# STB_IMAGE_FOUND - set to true if the library is found
# STB_IMAGE_INCLUDE_DIR - list of required include directories
# STB_INCLUDE_NEEDS_STB_SUFFIX - whether or not the include files are under an
# stb/ directory; if "YES", then includes must be done as, e.g.,
# stb/stb_image.h.

file(GLOB STB_IMAGE_SEARCH_PATHS
${CMAKE_BINARY_DIR}/deps/
${CMAKE_BINARY_DIR}/deps/stb)
find_path(STB_IMAGE_INCLUDE_DIR
NAMES stb/stb_image.h stb/stb_image_write.h
PATHS ${STB_IMAGE_SEARCH_PATHS})
find_path(STB_IMAGE_INCLUDE_DIR_1
NAMES stb_image.h stb_image_write.h
PATHS ${STB_IMAGE_SEARCH_PATHS} ${STB_IMAGE_INCLUDE_DIR})

if(STB_IMAGE_INCLUDE_DIR)
if(STB_IMAGE_INCLUDE_DIR_1)
set(STB_IMAGE_FOUND YES)
set(STB_IMAGE_INCLUDE_DIR "${STB_IMAGE_INCLUDE_DIR_1}" CACHE PATH
"stb_image include directory")

# Either we found /usr/include/stb_image.h (or similar), or the user passed
# a directory in STB_IMAGE_SEARCH_PATHS that directly contains stb_image.h.
# In either of those cases, we want to include <stb_image.h>, not
# <stb/stb_image.h>.
set(STB_INCLUDE_NEEDS_STB_SUFFIX "NO")
else ()
find_path(STB_IMAGE_INCLUDE_DIR
find_path(STB_IMAGE_INCLUDE_DIR_2
NAMES stb_image.h stb_image_write.h
PATHS ${STB_IMAGE_SEARCH_PATHS})
PATHS ${STB_IMAGE_SEARCH_PATHS} ${STB_IMAGE_INCLUDE_DIR}
PATH_SUFFIXES stb/)

if(STB_IMAGE_INCLUDE_DIR)
if(STB_IMAGE_INCLUDE_DIR_2)
set(STB_IMAGE_FOUND YES)
endif ()
endif ()
set(STB_IMAGE_INCLUDE_DIR "${STB_IMAGE_INCLUDE_DIR_2}" CACHE PATH
"stb_image include directory")

# Make sure that stb/ is the last part of the include directory, if it was
# found.
if (STB_IMAGE_INCLUDE_DIR)
string(REGEX MATCH ".*stb[/]?" STB_INCLUDE_HAS_TRAILING_STB
"${STB_IMAGE_INCLUDE_DIR}")
if (NOT STB_INCLUDE_HAS_TRAILING_STB)
set(STB_IMAGE_INCLUDE_DIR "${STB_IMAGE_INCLUDE_DIR}/stb/")
# Since we searched the same paths but allowed an stb/ suffix this time,
# then there is definitely a suffix.
set(STB_INCLUDE_NEEDS_STB_SUFFIX "YES")
# Strip the suffix.
string(REGEX REPLACE ".*stb[/]?$" "" STB_IMAGE_INCLUDE_DIR
"${STB_IMAGE_INCLUDE_DIR}")
endif ()
endif ()

Expand Down
9 changes: 8 additions & 1 deletion CMake/TestStaticSTB.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,26 @@ implementation that can be used from multiple translation units.

if(NOT DEFINED CMAKE_HAS_WORKING_STATIC_STB)
message(STATUS "Check that STB static implementation mode links correctly...")

set(TEST_CXX_DEFS "")
if (NOT STB_INCLUDE_NEEDS_STB_SUFFIX)
set(TEST_CXX_DEFS "-DMLPACK_HAS_NO_STB_DIR")
endif ()

try_compile(CMAKE_HAS_WORKING_STATIC_STB
${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/
SOURCES
${CMAKE_SOURCE_DIR}/CMake/stb/main.cpp
${CMAKE_SOURCE_DIR}/CMake/stb/a.cpp
${CMAKE_SOURCE_DIR}/CMake/stb/b.cpp
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${STB_IMAGE_INCLUDE_DIR}"
COMPILE_DEFINITIONS "${TEST_CXX_DEFS}"
OUTPUT_VARIABLE out)
if (CMAKE_HAS_WORKING_STATIC_STB)
message(STATUS "Check that STB static implementation mode links "
"correctly... success")
set(CMAKE_HAS_WORKING_STATIC_STB 1 CACHE INTERNAL
"Does STB static implementation mode link correctly")
"Does STB static implementation mode link correctly")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if STB's static implementation can link correctly passed "
"with the following output:\n${out}\n\n")
Expand Down
9 changes: 7 additions & 2 deletions CMake/stb/a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
#define STB_IMAGE_WRITE_STATIC
#define STB_IMAGE_WRITE_IMPLEMENTATION

#include <stb_image.h>
#include <stb_image_write.h>
#ifdef MLPACK_HAS_NO_STB_DIR
#include <stb_image.h>
#include <stb_image_write.h>
#else
#include <stb/stb_image.h>
#include <stb/stb_image_write.h>
#endif

void A::A()
{
Expand Down
9 changes: 7 additions & 2 deletions CMake/stb/b.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
#define STB_IMAGE_WRITE_STATIC
#define STB_IMAGE_WRITE_IMPLEMENTATION

#include <stb_image.h>
#include <stb_image_write.h>
#ifdef MLPACK_HAS_NO_STB_DIR
#include <stb_image.h>
#include <stb_image_write.h>
#else
#include <stb/stb_image.h>
#include <stb/stb_image_write.h>
#endif

void B::B()
{
Expand Down
26 changes: 24 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
endif()

# Debugging CFLAGS. Turn optimizations off; turn debugging symbols on.
set (BFD_DL_AVAILABLE "NO")
if (DEBUG)
if (NOT MSVC)
add_definitions(-DDEBUG)
Expand All @@ -240,7 +241,7 @@ if (DEBUG)
${LIBDL_INCLUDE_DIRS})
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${LIBBFD_LIBRARIES}
${LIBDL_LIBRARIES})
add_definitions(-DMLPACK_HAS_BFD_DL)
set(BFD_DL_AVAILABLE "YES")
else()
message(WARNING "No libBFD and/or libDL has been found!")
endif()
Expand Down Expand Up @@ -319,7 +320,6 @@ else()
endif()

if (STB_IMAGE_FOUND)
add_definitions(-DHAS_STB)
set(STB_AVAILABLE "1")
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${STB_IMAGE_INCLUDE_DIR}")

Expand Down Expand Up @@ -470,6 +470,28 @@ if (BUILD_CLI_EXECUTABLES AND UNIX)
endif ()
endif ()

# Modify config.hpp as necessary.
file(READ ${CMAKE_SOURCE_DIR}/src/mlpack/config.hpp CONFIG_CONTENTS)
if (BFD_DL_AVAILABLE)
string(REGEX REPLACE "// #define MLPACK_HAS_BFD_DL\n"
"#define MLPACK_HAS_BFD_DL\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}")
endif ()
if (STB_AVAILABLE)
string(REGEX REPLACE "// #define MLPACK_HAS_STB\n"
"#define MLPACK_HAS_STB\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}")
if (NOT STB_INCLUDE_NEEDS_STB_SUFFIX)
string(REGEX REPLACE "// #define MLPACK_HAS_NO_STB_DIR\n"
"#define MLPACK_HAS_NO_STB_DIR\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}")
endif ()
endif ()
if (USING_GIT)
string(REGEX REPLACE "// #define MLPACK_GIT_VERSION\n"
"#define MLPACK_GIT_VERSION\n" CONFIG_CONTENTS "${CONFIG_CONTENTS}")
endif ()
file(WRITE ${CMAKE_BINARY_DIR}/include/mlpack/config-local.hpp "${CONFIG_CONTENTS}")
include_directories(${CMAKE_BINARY_DIR}/include/)
add_definitions(-DMLPACK_CUSTOM_CONFIG_FILE=mlpack/config-local.hpp)

# Finally, add any cross-compilation support libraries (they may need to come
# last). If we are not cross-compiling, no changes will happen here.
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${CROSS_COMPILE_SUPPORT_LIBRARIES})
Expand Down
16 changes: 10 additions & 6 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
###### ????-??-??
* Reinforcement Learning: Gaussian noise (#3515).

* Reinforcement Learning: Twin Delayed Deep Deterministic
* Reinforcement Learning: Twin Delayed Deep Deterministic
Policy Gradient (#3512).

* Reinforcement Learning: Ornstein-Uhlenbeck noise (#3499).
Expand All @@ -15,6 +15,10 @@
* Bipolar sigmoid activation function added and invertible functions
fixed (#3506).

* Add auto-configured `mlpack/config.hpp` to contain configuration details of
mlpack that are required at compile time. STB detection is now done in this
file with the `MLPACK_HAS_STB` macro (#3519).

### mlpack 4.2.0
###### 2023-06-14
* Adapt C_ReLU, ReLU6, FlexibleReLU layer for new neural network API (#3445).
Expand All @@ -23,9 +27,9 @@

* Fix bug in LogSoftMax derivative (#3469).

* Add `serialize` method to `GaussianInitialization`,
* Add `serialize` method to `GaussianInitialization`,
`LecunNormalInitialization`,
`KathirvalavakumarSubavathiInitialization`, `NguyenWidrowInitialization`,
`KathirvalavakumarSubavathiInitialization`, `NguyenWidrowInitialization`,
and `OrthogonalInitialization` (#3483).

* Allow categorical features to `preprocess_one_hot_encode` (#3487).
Expand Down Expand Up @@ -123,8 +127,8 @@
* Disable the usage of autodownloader by default (#2953).

* Install dependencies downloaded with the autodownloader (#2952).
* Download older Boost if the compiler is old (#2940).

* Download older Boost if the compiler is old (#2940).

* Add support for embedded systems (#2531).

Expand Down Expand Up @@ -218,7 +222,7 @@
`decision_tree()` and `hoeffding_tree()` (#2971).

* Depend on `pkgbuild` for R bindings (#3081).

* Replaced Numpy deprecated code in Python bindings (#3126).

### mlpack 3.4.2
Expand Down
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ If you are compiling Armadillo by hand, ensure that LAPACK and BLAS are enabled.
*See also the [C++ quickstart](doc/quickstart/cpp.md).*

Since mlpack is a header-only library, installing just the headers for use in a
C++ application is trivial.
C++ application is trivial.

From the root of the sources, configure and install
in the standard CMake way:
Expand All @@ -135,19 +135,24 @@ sudo make install
```

If the `cmake ..` command fails due to unavailable dependencies, consider either using the
`-DDOWNLOAD_DEPENDENCIES=ON` option as detailed in
[the following subsection](#31-additional-build-options), or ensure that mlpack's dependencies
are installed, e.g. using the system package manager. For example, on Debian and Ubuntu,
all relevant dependencies can be installed with `sudo apt-get install libarmadillo-dev libensmallen-dev libcereal-dev g++ cmake`.
`-DDOWNLOAD_DEPENDENCIES=ON` option as detailed in [the following
subsection](#31-additional-build-options), or ensure that mlpack's dependencies
are installed, e.g. using the system package manager. For example, on Debian
and Ubuntu, all relevant dependencies can be installed with `sudo apt-get
install libarmadillo-dev libensmallen-dev libcereal-dev libstb-dev g++ cmake`.

Alternatively, since CMake v3.14.0 the `cmake` command can create the build folder itself,
the above commands can be rewritten as follows:
Alternatively, since CMake v3.14.0 the `cmake` command can create the build
folder itself, and so the above commands can be rewritten as follows:

```sh
cmake -S . -B build
sudo cmake --build build --target install
```

During configuration, CMake adjusts the file `mlpack/config.hpp` using the
details of the local system. This file can be modified by hand as necessary
before or after installation.

### 3.1. Additional build options

You can add a few arguments to the `cmake` command to control the behavior of
Expand Down
3 changes: 2 additions & 1 deletion doc/user/formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,8 @@ mlpack's image saving/loading functionality is based on
### Image Utilities API
mlpack's image utilities support loading and saving of images.
mlpack's image utilities support loading and saving of images, if STB is
available on the system.
There is support for the following filetypes: `jpg`, `png`, `tga`, `bmp`, `psd`,
`gif`, `hdr`, `pic`, `pnm` for loading, and `jpg`, `png`, `tga`, `bmp`, `hdr`
Expand Down
5 changes: 5 additions & 0 deletions src/mlpack/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ install(FILES
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/base.hpp"
# Note: config.hpp does not get installed from the source directory!
# The configured version gets installed.
"${CMAKE_CURRENT_SOURCE_DIR}/core.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/namespace_compat.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/prereqs.hpp"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/mlpack/")
install(FILES "${CMAKE_BINARY_DIR}/include/mlpack/config-local.hpp"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/mlpack"
RENAME "config.hpp")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/core" DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}/mlpack")
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/methods" DESTINATION
Expand Down
22 changes: 12 additions & 10 deletions src/mlpack/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,18 @@
#define M_PI 3.141592653589793238462643383279
#endif
// MLPACK_COUT_STREAM is used to change the default stream for printing
// purpose.
#if !defined(MLPACK_COUT_STREAM)
#define MLPACK_COUT_STREAM std::cout
#endif
// MLPACK_CERR_STREAM is used to change the stream for printing warnings
// and errors.
#if !defined(MLPACK_CERR_STREAM)
#define MLPACK_CERR_STREAM std::cerr
// Include mlpack configuration.
#ifdef MLPACK_CUSTOM_CONFIG_FILE
// During the build process, CMake will generate a custom configuration file
// specific to the system. When CMake is used to build mlpack, that custom
// file is used via the MLPACK_CUSTOM_CONFIG_FILE macro. When mlpack is
// installed by CMake, the custom configuration file is installed as
// config.hpp, and MLPACK_CUSTOM_CONFIG_FILE is not set after installation.
#undef MLPACK_WRAP_INCLUDE
#define MLPACK_WRAP_INCLUDE(x) <x>
#include MLPACK_WRAP_INCLUDE(MLPACK_CUSTOM_CONFIG_FILE)
#else
#include "config.hpp"
#endif
// Give ourselves a nice way to force functions to be inline if we need.
Expand Down
6 changes: 6 additions & 0 deletions src/mlpack/bindings/R/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,12 @@ macro (post_r_setup)
)
endforeach()

# Copy configured config.hpp.
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy
"${CMAKE_BINARY_DIR}/include/mlpack/config-local.hpp"
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/R/mlpack/inst/include/mlpack/config.hpp")

foreach(r_src_file ${R_SRC_FILES})
if ("${r_src_file}" MATCHES "methods/" OR
"${r_src_file}" MATCHES "core/" OR
Expand Down

0 comments on commit 1a6100a

Please sign in to comment.