1Compilation
2========================================================================================
3
4NanoGUI uses a CMake build system to ensure portability. All dependencies are
5cloned and compiled in one batch, which should generally reduce the amount of
6configuration effort to zero. Assuming that NanoGUI was cloned into the current
7working directory, the following commands need to be executed:
8
9.. code-block:: bash
10
11   # enter the top-level NanoGUI directory
12   $ cd nanogui
13
14   # make a build directory and enter that
15   $ mkdir build
16   $ cd build
17
18   # generate your Makefile
19   $ cmake ..
20
21   # now that you have a Makefile, use that to build
22   $ make -j 4
23
24For Windows, the process is nearly the same:
25
26.. code-block:: bash
27
28   # enter the top-level NanoGUI directory
29   $ cd nanogui
30
31   # make a build directory and enter that
32   $ mkdir build
33   $ cd build
34
35   # Specify VS Version AND 64bit, otherwise it defaults to 32.
36   # The version number and year may be different for you, Win64
37   # can be appended to any of them.  Execute `cmake -G` to get
38   # a listing of the available generators.
39   #
40   # 32 bit Windows builds are /not/ supported
41   $ cmake -G "Visual Studio 14 2015 Win64" ..
42
43   # Either open the .sln with Visual Studio, or run
44   $ cmake --build . --config Release
45
46Default Configurations
47----------------------------------------------------------------------------------------
48
49By default, NanoGUI will
50
51+---------------------------------+---------------------------+
52| Impact / effect                 | CMake Option              |
53+=================================+===========================+
54| Build the example programs.     | ``NANOGUI_BUILD_EXAMPLE`` |
55+---------------------------------+---------------------------+
56| Build as a *shared* library.    | ``NANOGUI_BUILD_SHARED``  |
57+---------------------------------+---------------------------+
58| Build the Python plugins.       | ``NANOGUI_BUILD_PYTHON``  |
59+---------------------------------+---------------------------+
60| Use GLAD if on Windows.         | ``NANOGUI_USE_GLAD``      |
61+---------------------------------+---------------------------+
62| Generate an ``install`` target. | ``NANOGUI_INSTALL``       |
63+---------------------------------+---------------------------+
64
65Users developing projects that reference NanoGUI as a ``git submodule`` (this
66is **strongly** encouraged) can set up the parent project's CMake configuration
67file as follows (this assumes that ``nanogui`` lives in the directory
68``ext/nanogui`` relative to the parent project):
69
70.. code-block:: cmake
71
72    # Disable building extras we won't need (pure C++ project)
73    set(NANOGUI_BUILD_EXAMPLE OFF CACHE BOOL " " FORCE)
74    set(NANOGUI_BUILD_PYTHON  OFF CACHE BOOL " " FORCE)
75    set(NANOGUI_INSTALL       OFF CACHE BOOL " " FORCE)
76
77    # Add the configurations from nanogui
78    add_subdirectory(ext/nanogui)
79
80    # For reliability of parallel build, make the NanoGUI targets dependencies
81    set_property(TARGET glfw glfw_objects nanogui PROPERTY FOLDER "dependencies")
82
83Required Variables Exposed
84----------------------------------------------------------------------------------------
85
86Due to the nature of building an OpenGL application for different platforms, three
87variables are populated to allow for easy incorporation with your CMake build.  After
88you have executed ``add_subdirectory`` as shown above, you will need to add the
89following (assuming the target you are building is called ``myTarget``):
90
91.. code-block:: cmake
92
93   # Various preprocessor definitions have been generated by NanoGUI
94   add_definitions(${NANOGUI_EXTRA_DEFS})
95
96   # On top of adding the path to nanogui/include, you may need extras
97   include_directories(${NANOGUI_EXTRA_INCS})
98
99   # Compile a target using NanoGUI
100   add_executable(myTarget myTarget.cpp)
101
102   # Lastly, additional libraries may have been built for you.  In addition to linking
103   # against NanoGUI, we need to link against those as well.
104   target_link_libraries(myTarget nanogui ${NANOGUI_EXTRA_LIBS})
105
106Advanced Compilation Details
107----------------------------------------------------------------------------------------
108
109NanoGUI and Python
110****************************************************************************************
111
112Although it is |year|, you may still for example wish to build the Python bindings for
113Python 2.7.  The variable you would set **before** ``add_subdirectory`` is
114``NANOGUI_PYTHON_VERSION``.  For example,
115
116.. code-block:: cmake
117
118   set(NANOGUI_PYTHON_VERSION "2.7")
119   # can also use minor versions
120   set(NANOGUI_PYTHON_VERSION "3.6.2")
121
122
123NanoGUI and Eigen
124****************************************************************************************
125
126NanoGUI uses Eigen_ internally for various vector types.  Eigen is an advanced header
127only template library, which NanoGUI vendors in the ``ext`` folder.  It is important to
128understand the implication of Eigen being header only: **only one version of Eigen can
129be included**.
130
131There is a CMake bypass variable available in NanoGUI: ``NANOGUI_EIGEN_INCLUDE_DIR``.
132You would set this variable **before** ``add_subdirectory``.  Since you will want to
133provide the same kind of bypass for users of your library, the following snippet is a
134good starting point.  For this example code:
135
1361. The parent CMake project is called ``myproj``.  A good CMake practice to adopt is to
137   prefix your project's name to any variables you intend to expose.  This allows parent
138   projects to know where the variable came from, and avoids name collisions.
1392. First ``find_package`` is used to try and find Eigen.  The philosophy is that the
140   user is responsible for ensuring that the version of Eigen they want to use will be
141   found.
1423. Since NanoGUI needs to remain self-contained, the side-effect is that even if the
143   user does *not* have Eigen installed, you can fallback and use the one vendored with
144   NanoGUI.
1454. The following directory structure:
146
147   .. code-block:: none
148
149      myproj/
150          CMakeLists.txt         <- Where this example code is
151          ext/
152              nanogui/
153                  CMakeLists.txt <- NanoGUI's build system
154                  ext/
155                      eigen/     <- NanoGUI's internal copy of Eigen
156
157
158.. code-block:: cmake
159
160   # `if NOT` is what enables the same bypass for your project
161   if(NOT MYPROJ_EIGEN3_INCLUDE_DIR)
162     # Grab or find the Eigen3 include directory.
163     find_package(Eigen3 QUIET)
164     if(EIGEN3_INCLUDE_DIR)
165       set(MYPROJ_EIGEN3_INCLUDE_DIR ${EIGEN3_INCLUDE_DIR})
166     else()
167       # use the internal NanoGUI copy of Eigen
168       set(MYPROJ_EIGEN3_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/nanogui/ext/eigen)
169     endif()
170   endif()
171
172   message(STATUS "Using Eigen3 from directory: ${MYPROJ_EIGEN3_INCLUDE_DIR}")
173   set(NANOGUI_EIGEN_INCLUDE_DIR ${EIGEN3_INCLUDE_DIR} CACHE BOOL " " FORCE)
174   # set any other NanoGUI specific variables you need (shown in above sections)
175   add_subdirectory(ext/nanogui)
176
177   # include it for your project as well (or append to a list
178   # and include that list later, depending on your setup)
179   include_directories(${MYPROJ_EIGEN3_INCLUDE_DIR})
180
181.. _Eigen: https://eigen.tuxfamily.org/dox/
182
183NanoGUI, GLFW, and Other Projects
184****************************************************************************************
185
186Suppose you want to use NanoGUI as your GUI toolkit, but you also have another library
187you want to use that depends on ``glfw``.  Call the second library Foo.  Generally
188speaking, it is unlikely that library Foo will provide you with mechanisms to explicitly
189specify where ``glfw`` comes from.  You could try to work on a patch with the developers
190of library Foo to allow this to be overridden, but you may need to maintain your own
191fork of library Foo.  There is just as much justification to allow the bypass as there
192is to not want it in a build system.
193
194Since NanoGUI merges the ``glfw`` objects into the library being built, you can actually
195just specify ``nanogui`` as the ``glfw`` dependency directly.  So lets suppose that
196library Foo was looking for ``glfw`` like this:
197
198.. code-block:: cmake
199
200   find_package(GLFW3)
201   if(GLFW3_FOUND)
202     include_directories(${GLFW3_INCLUDE_DIRS})
203     target_link_libraries(foo ${GLFW3_LIBRARIES})
204   endif()
205
206You can cheat around this pretty easily.  For the modification to library Foo's build
207system, all we do is wrap ``find_package``:
208
209.. code-block:: diff
210
211   + if(NOT GLFW3_FOUND)
212       find_package(GLFW3)
213   + endif()
214     if(GLFW3_FOUND)
215       include_directories(${GLFW3_INCLUDE_DIRS})
216       target_link_libraries(foo ${GLFW3_LIBRARIES})
217     endif()
218
219Now that ``find_package`` will only execute if ``NOT GLFW3_FOUND``, in your build system
220you make sure to set all three ``glfw`` variables (found, include, and libraries).  It
221might look something like this:
222
223.. code-block:: cmake
224
225   # ... any other nanogui configs ...
226   # same directory structure as Eigen example
227   add_subdirectory(ext/nanogui)
228
229   # nanogui needs to be added first so the 'nanogui' target is defined
230   # and can be used in the generator expression for the libraries
231   set(GLFW3_FOUND ON)
232   set(GLFW3_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/ext/nanogui/ext/glfw/include)
233   set(GLFW3_LIBRARIES $<TARGET_FILE:nanogui>)
234
235   add_subdirectory(ext/foo)
236
237   # IMPORTANT! You need to force NanoGUI to build first
238   # Assuming their library target is called 'foo'
239   add_dependencies(foo nanogui)
240
241
242Depending on what you need to do, the above may not be sufficient.  But it is at least
243a starting point to being able to "share" NanoGUI as the vendor of ``glfw``.
244
245.. _nanogui_including_custom_fonts:
246
247Including Custom Fonts
248****************************************************************************************
249
250NanoGUI uses the Roboto_ font for text, and Entypo_ font for icons.  If you wish to add
251your own custom font, all you need is a True Type file (a ``.ttf`` extension).  NanoGUI
252will glob all fonts found in ``resources`` by expanding ``resources/*.ttf``.  So if you
253had the directory structure
254
255.. code-block:: none
256
257   myproject/
258       CMakeLists.txt      <- where this code is
259       fonts/
260           superfont.ttf
261       ext/
262           nanogui/
263               resources/
264
265You simply need to copy the ``superfont.ttf`` to NanoGUI's resources directory:
266
267.. code-block:: cmake
268
269   file(
270     COPY ${CMAKE_CURRENT_SOURCE_DIR}/fonts/superfont.ttf
271     DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/ext/nanogui/resources/superfont.ttf
272   )
273
274When you build the code, there should be a file ``nanogui_resources.h`` generated.  If
275everything worked, your new font should have been included.
276
277.. note::
278
279   Since NanoGUI can support images as icons, you will want to make sure that the
280   *codepoint* for any *icon* fonts you create is greater than ``1024``.  See
281   :func:`nanogui::nvgIsImageIcon`.
282
283.. tip::
284
285   Some widgets allow you to set fonts directly, but if you want to apply the font
286   globally, you should create a sub-class of :class:`nanogui::Theme` and explicitly
287   call :func:`nanogui::Widget::setTheme` for each widget you create.
288
289.. _Roboto: https://fonts.google.com/specimen/Roboto
290
291.. _Entypo: http://www.entypo.com
292
293.. _utf8: http://www.utf8-chartable.de/
294
295.. _nanogui_compiling_the_docs:
296
297Compiling the Documentation
298----------------------------------------------------------------------------------------
299
300The documentation system relies on 'Doxygen', 'Sphinx', 'Breathe', and
301'Exhale'.  It uses the 'Read the Docs' theme for the layout of the generated
302html.  So you will need to first
303
3041. Install Doxygen for your operating system.  On Unix based systems, this
305   should be available through your package manager (apt-get, brew, dnf, etc).
306
3072. Install Sphinx, Breathe, Exhale, and the theme:
308
309   .. code-block:: py
310
311      pip3 install -r <path/to/nanogui>/docs/requirements.txt
312
313Now that you have the relevant tools, you can build the documentation with
314
315.. code-block:: bash
316
317   # Enter the documentation directory
318   $ cd <path/to/nanogui>/docs
319
320   # Build the documentation
321   $ make html
322
323The output will be generated in ``_build``, the root html document is located
324at ``_build/html/index.html``.
325
326.. note::
327
328   When building the documentation locally, there can be subtle differences in
329   the rendered pages than what is hosted online.  You should largely be able
330   to ignore this.
331