tags:

views:

33

answers:

1

I'm just starting out with cmake, and trying to set up a fairly simple project. Although the project itself is simple, it links to a number of static libraries which aren't built by cmake. They could be, I suppose - they are my libraries - but I need to sort out how to link to third party libraries anyway.

Here is what I have so far...

cmake_minimum_required(VERSION 2.8.1)
cmake_policy(VERSION 2.8.1)

project( test01 )

include_directories("../../cpplib/sh_core" "../../cpplib/sh_core2" "../../cpplib/sh_genlib")

link_directories("../../cpplib/_vc_debug")

add_library( sh_core   STATIC IMPORTED )
add_library( sh_core2  STATIC IMPORTED )
add_library( sh_genlib STATIC IMPORTED )

add_executable( test01 test01 test01_ast test01_parse test01_scan test01_main )
target_link_libraries(test01 sh_core sh_core2 sh_genlib)

The problem is that the three libraries that I'm trying to link to aren't being referenced correctly in the generated project file. They are listed as sh_core-NOTFOUND, sh_core2-NOTFOUND and sh_genlib-NOTFOUND.

I think perhaps I don't need the link_directories from above, but I do need a find_library command. But I've taken a quick look at that command in the docs and... WTF!!! I already have a headache, and I really can't cope with that mass of seemingly redundant complexity ATM. Besides, seeing this much complexity for something that should be perfectly simple suggests to me that I'm looking in the wrong place.

So... how do I tell cmake where to find those libraries?

Bonus question - how do I set this up so the generated project handles both a debug build and a release build? Note - the release versions of the imported libraries have the same filenames, but are in a "../../cpplib/_vc_release" folder.

+2  A: 

I think you've misunderstood the include_directories and add_library directives.

include_directories adds directories to be searched for include files, while add_library can be used like this (in your case):

add_library(core UNKNOWN IMPORTED)
set_target_properties(core PROPERTIES IMPORTED_LOCATION "../../cpplib/_vs_release/core.lib")

However, if I correctly understand what you're trying to accomplish, something like this should do it:

set(CPPLIB_DIR "${CMAKE_SOURCE_DIR}/../../cpplib")

set(CPPLIB_DEBUG_DIR "${CPPLIB_DIR}/_vc_debug")
set(CPPLIB_RELEASE_DIR "$(CPPLIB_DIR}/_vc_release")

if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
    set(CPPLIB_LIB_HINT ${CPPLIB_RELEASE_DIR})
else ()
    set(CPPLIB_LIB_HINT ${CPPLIB_DEBUG_DIR})
endif ()

find_library(CPPLIB_CORE_LIBRARY NAMES "core"
                                 PATHS ${CPPLIB_LIB_HINT})

find_library(CPPLIB_CORE2_LIBRARY NAMES "core2"
                                  PATHS ${CPPLIB_LIB_HINT})

find_library(CPPLIB_GENLIB_LIBRARY NAMES "genlib"
                                   PATHS ${CPPLIB_LIB_HINT})

if (("${CPPLIB_CORE_LIBRARY}" STREQUAL "CPPLIB_CORE_LIBRARY-NOTFOUND") OR
    ("${CPPLIB_CORE2_LIBRARY}" STREQUAL "CPPLIB_CORE2_LIBRARY-NOTFOUND") OR
    ("${CPPLIB_GENLIB_LIBRARY}" STREQUAL "CPPLIB_GENLIB_LIBRARY-NOTFOUND"))
    message(FATAL_ERROR "One of the libs wasn't found!")
endif ()

set(CPPLIB_LIBRARIES ${CPPLIB_CORE_LIBRARY} ${CPPLIB_CORE2_LIBRARY} ${CPPLIB_GENLIB_LIBRARY})

target_link_libraries(my_exe ${CPPLIB_LIBRARIES})

EDIT: If you also want to include some headers, it's as simple as:

find_path(CPPLIB_INCLUDE_DIR "my_header.h"
    PATHS ${CPPLIB_HINT_INCLUDE_DIR})

...

include_directories(${CPPLIB_INCLUDE_DIR})
the_void
Perfect! I figured out the set_target_properties version myself and just came back to write that up, but this is so much better. Also, with an example like this, the reference docs now make a lot more sense. Thanks.
Steve314
Mind you - I do still need that "include_directories" directive. Those folders are where the header files (and all the source) for those libraries lives. Though it's definitely time for a tidy-up, and as I'm dumping an old version of Visual Studio for a newer one, I'm taking the opportunity to re-organise a few things.
Steve314
See my edit on how to `include` directories.
the_void
@the_void - interesting, and if I could give you some more votes I would. But... it does feel like unnecessary complexity. In this case, I already know the relative paths to the header files, so why search? More generally, I can see that libraries may be installed in different places on different systems, but you need "hint" variables anyway to tell cmake where to search - what's wrong with an environment variable that directly tells cmake (or make or whatever) the exact path? Why have searches with "hints" when it seems just as easy to specify exact answers as it does to specify the "hints"?
Steve314
It's more like a best practice, than a necessity in your case. However, if you build on multiple platforms, headers might be in different directories. The `hint` just variables tell `cmake` where to look first. Do note that `find_path` will search additional directories, as defined in `Modules/Platform/UnixPaths.cmake` and `Modules/Platform/WindowsPaths.cmake` unless `NO_DEFAULT_PATH` is specified. You also might want to take a look at `CMAKE_SYSTEM_INCLUDE_PATH` and `CMAKE_SYSTEM_LIBRARY_PATH`.
the_void