Startec
Startec

Reputation: 13236

How to include a library using CMAKE in a cross-platform way

I am trying to use the assimp library in a cross platform C++ project. I include the repo as a git submodule, so, effectively, if someone downloads my project they will also download the ASSIMP project.

After I go through the assimp build / CMAKE instructions and (on Linux) type make install and from then on in my project I can use:

target_link_libraries(${PROJECT_NAME} assimp)

However, there is no make install on Windows.

The only other way I have been able to include the library on Linux is to put (in my CmakeLists.txt file):

target_link_libraries(${PROJECT_NAME} ${CMAKE_SOURCE_DIR}/build/assimp/code/libassimp.so)

This is not cross platform as it hardcodes the name and location of the .so file which will not work on Windows.

How can I expose the library so that I can do something like target_link_libraries(${PROJECT_NAME} assimp) on all platforms?

My directory tree looks like:

- src
- include
    - assimp
- bin

Where the assimp directory in the include directory is the git submodule

Upvotes: 1

Views: 2566

Answers (1)

Cinder Biscuits
Cinder Biscuits

Reputation: 5261

I think you're going about this the wrong way. You don't need to build assimp in a separate step from your project, and you don't need to make install to make it available.

There are a number of ways of handling third party dependencies in Cmake, since you've already chosen to submodule the assimp repository, we'll start there. Assuming assimp is located in the root of your repository in a directory called assimp/ this would be a barebones project including it:

cmake_minimum_required(VERSION 3.0)
project(Project myassimpproj)

# include your directories
include_directories(
  ${CMAKE_CURRENT_SOURCE_DIR}
  )

# set any variables you might need to set for your app and assimp
set(BUILD_ASSIMP_TOOLS  ON)
set(ASSIMP_BUILD_STATIC_LIB ON)

# add assimp source dir as a subdirectory, effectively making 
# assimp's CMakeLists.txt part of your build
add_subdirectory(/path/to/assimp ${CMAKE_BINARY_DIR}/assimp)

add_executable(assimp_target main.cpp)

# be sure to link in assimp, use platform-agnostic syntax for the linker
target_link_libraries(assimp_target assimp)

There may be a better way of phrasing this using generator expressions syntax, but I haven't looked at assimp's CMakeLists.txt to know if it's supported (and this is a more generic way anyway.)

Not every project uses Cmake, so you may not be able to just add_subdirectory(). In those cases, you can effectively "fake" a user call to build them using their build commands on respective platforms. execute_process() runs a command at configure time add_custom_command() and add_custom_target() run commands at build time. You then create a fake target to make integration and cross your fingers they support Cmake someday.

You can also use the ExternalProject commands added to Cmake to create a custom target to drive download, update/patch, configure, build, install and test steps of an external project, but note that this solution and the next download the dependency rather than using the submodule'd source code.

Finally, I prefer to work with prebuilt dependencies, cuts down on build time, and they can be unit tested on their own outside of the project. Conan is an open source, decentralized and multi-platform package manager with very good support for C++ and almost transparent support for Cmake when used the right way. They have grown very stable in the last year. More information on how to use Conan with Cmake can be found here.

Upvotes: 1

Related Questions