Skip to content

Adding a new submodule to 3rdparty

Przemog1 edited this page Nov 2, 2020 · 2 revisions

Prepare directory and use git to init your dependency

For the tutorial requirements a test will be a submodule name.

First of all you have to do is create a new directory where the submodule will be initialized to. So switch to 3rdparty directory and create one, eg. test. Having done it, switch yourself in git to main directory of project and type git submodule add *git-repository* 3rdparty/test where test is your already new created directory. If you wanted to clone on specific tag, you have to fork on that tag a desired submodule project and provide repository URL from your account. URL may be absolute or relative.

Filling CMake with appropriate configuration

3rdparty/CMakeLists.txt

At the beginning switch to 3rdparty/CMakeLists.txt. Find a section where all update_git_submodule are and update your submodule as well - type:

update_git_submodule(./test)

Remember, test is a name of directory created in section above.

In next step we will be adding a directory to CMake project. Choose appropriate place where you will type #test to make it easier to read. Bellow it you will be setting basic CMake variables overriding library settings to pass them to the submodule before adding it as directory to the main project. To do it, type:

set(_OLD_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
set(_OLD_BUILD_STATIC_LIBS ${BUILD_STATIC_LIBS})
set(_OLD_BUILD_TESTING ${BUILD_TESTING})
set(BUILD_SHARED_LIBS OFF)
set(BUILD_STATIC_LIBS ON)
set(BUILD_TESTING OFF)

set documentation is here: https://cmake.org/cmake/help/v3.3/command/set.html

The reason for that is we have to pass those variables to the new submodule's CMake, but we have to consider it could override those, so we save them to _OLD_BUILD_xxx.

Look at the OpenEXR submodule for a while. You may see something similar to:

set(PYILMBASE_ENABLE OFF CACHE STRING "" FORCE)
set(OPENEXR_BUILD_UTILS OFF CACHE STRING "" FORCE)
set(OPENEXR_VIEWERS_ENABLE OFF CACHE STRING "" FORCE)

What it does is ensuring those variables provided by OpenEXR submodule will be unset. These could be documentation variables for instance or variables that concerns building optional library used in your dependency - switch them off if there is no need for that. Pay attention that we are forcing it, and furthermore those variables aren't treated as local variables. So if you were to unset some variables provided by another submodule, test though - you have to deal with them like shown above.

https://cmake.org/cmake/help/v3.0/command/set.html in * Variable types in CMake *

Look also at Zlib submodule, you will see:

get_target_property(ZLIB_BINARY_DIR zlibstatic "BINARY_DIR")
get_target_property(ZLIB_NAME zlibstatic "NAME")
get_target_property(ZLIB_DEBUG_POSTFIX zlibstatic "DEBUG_POSTFIX")

As you may see, sometimes you will have to get some proporties from a submodule. After getting those proporties, you can used passed varibales to get_target_property to use them for various stuff, setting library path for instance.

set(ZLIB_LIBRARY_DEBUG "${ZLIB_BINARY_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}${ZLIB_NAME}${ZLIB_DEBUG_POSTFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" CACHE STRING "" FORCE)

Those variables are used in an example above to provide properly Zlib debug library path.

For more information about get_target_property, see: https://cmake.org/cmake/help/v3.12/command/get_target_property.html

Having done it, add your directory add_subdirectory(test test EXCLUDE_FROM_ALL) If you don't know what it does, look at: https://cmake.org/cmake/help/v3.0/command/add_subdirectory.html

The next step is to just recoup BUILD_xxx variables, so type:

set(BUILD_SHARED_LIBS ${_OLD_BUILD_SHARED_LIBS})
set(BUILD_STATIC_LIBS ${_OLD_BUILD_STATIC_LIBS})
set(BUILD_TESTING ${_OLD_BUILD_TESTING})

source/Nabla/CMakeLists.txt

Since our test directory is added to the project, we need to link it and add dependenies if needed and add include directories as well. We also do have to set option's variables if you were to deal with a new dependency that will be using _NBL_COMPILE_WITH_xxx variable. If it does, you will have to type for example:

option(_NBL_COMPILE_WITH_STL_LOADER_ "Compile with STL Loader" ON)
option(_NBL_COMPILE_WITH_STL_WRITER_ "Compile with STL Writer" ON)

The example considers STL loader and writer, where options string are Compile with STL Loader/Writer, and the default variables of those are true - on. For more information about option, look at: https://cmake.org/cmake/help/v3.13/command/option.html

If it doesn't, you can leave it alone and do nothing.

If your dependency uses dynamically generated config, you have to specify a path to it and add such, so find:

set(COMMON_INCLUDE_DIRS *some paths*)

and fill it with appropriate path if needed inserting a new path at the beginning of the paths.

The next step will introduce you into linking process. Find a section where macros begin, and define your own. It should look like bellow:

macro(nbl_target_link_test _trgt)
	add_dependencies(${_trgt} test)
	target_link_libraries(${_trgt} INTERFACE
		test
	)
	target_include_directories(${_trgt} PUBLIC ${THIRD_PARTY_SOURCE_DIR}/test/include)
endmacro()

As you may see, dependencies (in that case there is the only one - test submodule), libraries (also single library) and include directories are being added to the project. Having defined it you must use the macro, so go to nbl_target_link_xxx macros and add nbl_target_link_test(Nabla) and nbl_target_link_test(NablaServer) in appropriate places where all targets are linked to link test submodule to those projects. The convention is first targets are linked to Nabla project, some lines later to NablaServer project.

For more information about those commands, look at: