Dlib: Fix dlib installation

Created on 10 Sep 2015  路  6Comments  路  Source: davisking/dlib

dlib recommends a non-standard way of integrating with other projects CMake projects, by directly including dlib's CMake. Besides being non standard, it forces the user to recompile dlib everytime we use it.

dlib should support an official way to install it instead.
Amongst the advantages:

  • this would allow to compile the library only once
  • this would ease integration with CMake project (one would just write find_package(dlib) to include it)
  • providing a real installation target would make it possible to package dlib in the various Linux/MacOSX distributions
  • it would also permit a standard way to access the version number, which is really important considering the recent API break between minor versions

If the maintainer is willing to consider a pull-request implementing such changes, I am willing to contribute it

Most helpful comment

Fundamentally, installation is indeed really required for releases only, so I do like your suggestion to install only in release mode (I can not say much about the Windows side of things, though).

For debug scenarios, manually downloading dlib sounds like a reasonable option to me.

To summarize:

  • release mode installation and use by external projects:
$ cd $DLIB
$ mkdir build && cd build
$ cmake ../dlib
$ make && make install

In external projects:

find_package(dlib REQUIRED) #possibly supporting components!
message(STATUS "Using dlib-${dlib_VERSION}")
include_directories(${dlib_INCLUDE_DIRS})
#...
target_link_libraries(my_target ${dlib_LIBRARIES})
  • debug mode installation and use by external projects:
$ # just extract dlib to some place

In external projects:

set(DLIB_PATH "" CACHE PATH "Path to DLIB")
include(${DLIB_PATH}/dlib/cmake)

# no need for include_directories()
target_link_libraries(my_target dlib)

Besides, in release mode, we configure (and install) config.h to disable asserts.

Advantages:

  • 100% compatible with the current compilation steps. Nothing to change there.
  • address the concerns with having a proper installation workflow + cmake workflow

Drawback:

  • no transparent way to change from release to debug _when using the installed dlib_

All 6 comments

Possibly, however, the thing that has kept me from doing this is the behavior of the DLIB_ASSERT macro. A user can turn it on to do debugging but otherwise leaves it off for release/optimized builds. So how does someone enable/disable this once dlib is compiled and installed? There could be two shared libraries, dlib.so and dlib-debug.so say, but you would also need to somehow make sure the users of dlib-debug.so always #defined ENABLE_ASSERTS to avoid one-definition-rule violations. This would be easy to avoid if two copies of the dlib header files could be installed and a fool proof way of always pointing a compiler to the right include path corresponding to any shared library is found, but I'm not sure how to accomplish that.

I'm certainly open to suggestions though. Maybe cmake could be configured to use dlib.so in release mode and compile it from scratch for debug mode. Let me know.

P.S. There is a dlib/config.h that controls some of this stuff already.

Thanks for the quick feedback!

The 'usual' way this is handled is by... not handling it :-)
I mean, the user downloads dlib, decide whether he/she wants to compile it with or without the debug functionalities, install it and that's it.

Typically, one would install the library twice: within a dev/ prefix, with the library installed with the asserts enabled, and within a release/ (or whatever you call it) prefix where the library is installed in release mode. Then, when compiling other projects which depends on dlib, the user tells CMake which prefix to use for dlib, but in both prefix, a single library (dlib.so) is installed.

We can also easily conditionally configure a FindDlib.cmake so that, when compiled in 'Debug' mode only, dlib generates a FindDlib.cmake that exports add_definitions(-DENABLE_ASSERTS).

Would it do, or do I miss something?

Yeah, that's definitely the usual way :) Hardly any other libraries do rigorous precondition checking so they don't care, but precondition checking is hugely useful. But that's an entirely different rant.

Anyway, here are some things to consider.

  • The usual method of having multiple .so files that use the same header files is fine for a C library but isn't going to work with a C++ template library like dlib due to the difficulty of avoiding ORD violations.
  • The existing way of compiling dlib should still work after any of these changes (also don't complicate the build process).
  • People will compile dlib on the command line without cmake. e.g. g++ gui_ex.cpp -ldlib and they definitely won't remember or even know that they might have to provide a -DENABLE_ASSERTS to avoid ORD violations. So whatever we do, a statement like g++ your_program.cpp -ldlib should generate a valid executable.
  • Definitely things should be easy with cmake.
  • #include statements of the form #include <dlib/svm.h> should always work. A user should never be required to type something like #include <dlib-debug/svm.h> instead.
  • What if dlib is installed as an OS package (e.g. through apt-get say) and its headers are in /usr/include and a release mode dlib.so is available but a user wants to run their program in debug mode? How do they do that? Do they download a separate copy of dlib and compile it using the current method or some other way? How are conflicts with the existing dlib (e.g. accidentally including the wrong files) made easy to avoid if this is the suggested approach?
  • How does this work on windows? Visual Studio has at least 8 different runtimes for each version of visual studio and you can't mix and match them.

The other thing to keep in mind is that most people don't understand things like C++'s build process, how linkers work, what the ODR is or even that it exists, and so forth. Right now the way dlib is built avoids any trouble with any of these issues at the cost of requiring each user to always compile dlib themselves. While it would be nice to be able to say g++ main.cpp -ldlib and have it just work it really really needs to just work _always_ no matter what. My general philosophy is that it's better to not provide a feature at all if it can't be implemented 100% correctly.

As for how to proceed, I'm inclined to think that the "only install a release mode library" path is reasonable. If someone wants to compile in debug mode they have to compile dlib themselves. If a debug mode .so file were available it would be too easy for someone to do something like g++ main.cpp -ldlib-debug (note the missing -DENABLE_ASSERTS) and cause ORD violations. So maybe it's setup like this: The installed dlib has its dlib/config.h setup to permanently disable asserts no matter what preprocessor directives are active. Then when FinDlib.cmake looks for a system copy of dlib it just uses it and everything is simple. The only question is how does someone compile dlib in debug mode? Do they have to download a separate copy of dlib and use the current build process or is there some simpler way? They can't use the copy in /usr/include because the config.h file there will thwart any attempt to enable asserts. Is there some clever way to make cmake locally replace the config.h file just during a debug build by adjusting the include search path?

Also, it's probably not a good idea to create dlib.dll files on windows. I'm pretty sure that will only lead to user misery. So maybe the CMake files only allow installing dlib on unix systems.

Any FindDlib.cmake should also probably be able to automatically compile dlib if no compiled library is found so that the examples/CMakeLists.txt file can be switched to use FindDlib.cmake in a way that just works.

What do you think?

Fundamentally, installation is indeed really required for releases only, so I do like your suggestion to install only in release mode (I can not say much about the Windows side of things, though).

For debug scenarios, manually downloading dlib sounds like a reasonable option to me.

To summarize:

  • release mode installation and use by external projects:
$ cd $DLIB
$ mkdir build && cd build
$ cmake ../dlib
$ make && make install

In external projects:

find_package(dlib REQUIRED) #possibly supporting components!
message(STATUS "Using dlib-${dlib_VERSION}")
include_directories(${dlib_INCLUDE_DIRS})
#...
target_link_libraries(my_target ${dlib_LIBRARIES})
  • debug mode installation and use by external projects:
$ # just extract dlib to some place

In external projects:

set(DLIB_PATH "" CACHE PATH "Path to DLIB")
include(${DLIB_PATH}/dlib/cmake)

# no need for include_directories()
target_link_libraries(my_target dlib)

Besides, in release mode, we configure (and install) config.h to disable asserts.

Advantages:

  • 100% compatible with the current compilation steps. Nothing to change there.
  • address the concerns with having a proper installation workflow + cmake workflow

Drawback:

  • no transparent way to change from release to debug _when using the installed dlib_

That sounds good :)

@davisking here #35 a first pass on the 'installation' part. Let me know if it would work for you.

Was this page helpful?
0 / 5 - 0 ratings