4

I have some libs that are in non-standard locations. This is from OpenFrameworks and the libs are inside:

/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/openFrameworksCompiled/lib/osx/openFrameworks.a
...
/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/boost/lib/osx/boost_system.a
...
etc.

When linking those in my CMake, I am using the following approach:

set(LIB_OF ${OF_DIRECTORY}/libs/openFrameworksCompiled/lib/osx/openFrameworks.a)
...
set(LIB_BOOST_MAIN ${OF_DIRECTORY}/libs/boost/lib/osx/boost.a)
...
set(LIB_CAIRO1 ${OF_DIRECTORY}/libs/cairo/lib/osx/cairo-script-interpreter.a)
...
set(LIB_FREETYPE ${OF_DIRECTORY}/libs/freetype/lib/osx/freetype.a)
...

Then I merge those variables into one big variable:

set(OF_CORE_LIBS
    ${LIB_OF}
    ...
    ${LIB_BOOST_MAIN}
    ...
    ${LIB_CAIRO1}
    ...
    ${LIB_FREETYPE}
    ...
)

So eventually all the libs are concatenated and passed into the linker:

link_directories (${OF_CORE_LIBS})

Then I use:

target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})

to link them.

However, I am getting the following warning during the linking stage:

Linking CXX executable ../bin/3DPrimitiveExample
ld: warning: -L path '/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/openFrameworksCompiled/lib/osx/openFrameworks.a' is not a directory
...
(All the libs are listed in this way)

How can I tell CMake to look into those directories, even if they are not called blah/lib but blah/lib/osx? I could change the structure of the package but then I do not want to modify the way it has been designed.

I know the answer has something to do with the PROPERTIES or the default CMAKE variables but the help is still a bit cryptic for me. I am guessing it is the set_target_properties() but not sure about the syntax. (I am on cmake 2.8.12)

UPDATE(1): So I have changed my approach in the following way:

set(LIB_OF ${OF_DIRECTORY}/libs/openFrameworksCompiled/lib/)
set(LIB_FREEIMAGE ${OF_DIRECTORY}/libs/FreeImage/lib/)
set(LIB_BOOST ${OF_DIRECTORY}/libs/boost/lib/)
set(LIB_CAIRO ${OF_DIRECTORY}/libs/cairo/lib/)
set(LIB_FMODEX ${OF_DIRECTORY}/libs/fmodex/lib/)
set(LIB_FREETYPE ${OF_DIRECTORY}/libs/freetype/lib/)
set(LIB_GLEW ${OF_DIRECTORY}/libs/glew/lib/)
set(LIB_OPENSSL ${OF_DIRECTORY}/libs/openssl/lib/)
set(LIB_POCO ${OF_DIRECTORY}/libs/poco/lib/)
set(LIB_RTAUDIO ${OF_DIRECTORY}/libs/rtAudio/lib/)
set(LIB_TESS ${OF_DIRECTORY}/libs/tess2/lib/)

Once those location variables are created, they are merged once again:

set(OF_CORE_LIBS
    ${LIB_OF}
    ${LIB_FREEIMAGE}
    ${LIB_BOOST}
    ${LIB_CAIRO}
    ${LIB_FMODEX}
    ${LIB_FREETYPE}
    ${LIB_GLEW}
    ${LIB_GLFW} 
    ${LIB_OPENSS}
    ${LIB_POCO}
    ${LIB_RTAUDIO}
    ${LIB_TESS}
)

So when I verbose it, I get the following:

OF_CORE_LIBS: /Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/openFrameworksCompiled/lib/;/Users/me/packages/builds/x86_64/of- 0.9.3-osx-release/libs/FreeImage/lib/;/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/boost/lib/; (etc)

Then I pass those folders to the linker:

link_directories (${OF_CORE_LIBS})

Now the part that is wrong is this:

target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})

Clearly, I cannot pass the folders directly here? I need lib names. Do I need another list with the lib names at this stage?

UPDATE(2):

For the lib search folders:

set(OF_CORE_LIB_DIRS
    ${LIB_OF}
    ${LIB_FREEIMAGE}
    ${LIB_BOOST}
    ${LIB_CAIRO}
    ${LIB_FMODEX}
    ${LIB_FREETYPE}
    ${LIB_GLEW}
    ${LIB_GLFW} 
    ${LIB_OPENSS}
    ${LIB_POCO}
    ${LIB_RTAUDIO}
    ${LIB_TESS}
)

For the actual libs:

set(OF_CORE_LIBS
    openFrameworks
    freeimage
    boost_system
    boost_filesyste
    freeimage
    cairo-script-interpreter
    cairo
    pixman-1
    fmodex
    freetype
    glew
    ssl
    crypto
    PocoCrypto
    PocoData
    PocoDataSQLite
    PocoJSON
    PocoMongoDB
    PocoXML
    PocoNet
    PocoNetSSL
    PocoUtil
    PocoZip
    PocoFoundation
    rtAudio
    tess2
)

And at linking stage:

link_directories (${OF_CORE_LIB_DIRS})
add_executable(${APP_NAME} ${SOURCE_FILES})
target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})

Now I am getting the following error:

Linking CXX executable ../bin/3DPrimitiveExample.app/Contents/MacOS/3DPrimitiveExample
ld: library not found for -lopenFrameworks

This is the directory bit:

set(LIB_OF ${OF_DIRECTORY}/libs/openFrameworksCompiled/lib/osx)

And the file is in there:

openFrameworks.a

Further Questions:

The answer below helped me to understand the difference between lib folders and the actual lib names. However, there is still one question answered: How to tell CMake to accept and link arbitrary lib names?

In the question above, the libs are called just with their names, for example, openFrameworks.a should be called libopenFrameworks.a in order to be picked up by the linker, but it is not. That, I shall ask under a different question.

mbilyanov
  • 2,315
  • 4
  • 29
  • 49
  • This [question](http://stackoverflow.com/questions/14077611/how-do-i-tell-cmake-to-link-in-a-static-library-in-the-source-directory) seems to be cover similar ground? The solution(s) might work in your case as well? – Wuggy Jun 14 '16 at 18:11
  • Thanks. But this is not helpful for me. I am doing exactly the same thing, and I am getting those warnings described above. I would like to know the way to fix the warning and pass the folder to the linker, not the actual lib file. – mbilyanov Jun 14 '16 at 18:18
  • 3
    No, the problem here is you're passing the full path to the library. You need to pass the path to the folder where the library resides. Then you can simply like with your typical -l – alfalfasprout Jun 14 '16 at 18:38
  • Yes. How can I do that with CMake. When I do `set(LIB_BOOST_MAIN ${OF_DIRECTORY}/libs/boost/lib/osx)` CMake is complaining about the fact that this is not an official lib, as the `*.a` files are not inside a `/lib` folder. – mbilyanov Jun 14 '16 at 19:01
  • So your **actual problem** is that CMake complains about absence of `.a` files in `/lib` folder. [edit] your **question post**, so it will describe the problem **clearly**. – Tsyvarev Jun 15 '16 at 08:16
  • I do not think it is CMake that complains, it is the LD linker. CMake would just take care of what is passed to the compiler and the linker. So I need to find a way to tell CMake to pass the lib folder through the '-L' flag and the actual '.a' file through the '-l' flag. The question is clear I believe. – mbilyanov Jun 15 '16 at 08:29

1 Answers1

2

So eventually all the libs are concatenated and passed into the linker:

link_directories (${OF_CORE_LIBS})

No they're not. From the manual

link_directories

Specify directories in which the linker will look for libraries.

link_directories(directory1 directory2 ...)

Specify the paths in which the linker should search for libraries.

So you've specified the directories in which the linker should search for the libraries you want to link. Now you want to specify that the linker should link a library, say, libfoo.a with your_executable.

Again, the manual:

target_link_libraries(your_executable foo)

You tell the linker where to look and also what to look for.

Later

I think I am doing exactly what you have described in your answer, right?

No, you're not.

You are giving a list of files (apparently they are static libraries, although they lack the conventional lib prefix) to link_directories. It requires a list of directories in which the linker is to look for the libraries that you specify with target_link_libraries.

That is why the linker says:

ld: warning: -L path '/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/\
libs/openFrameworksCompiled/lib/osx/openFrameworks.a' is not a directory

It is a file. Correct this and then:

target_link_libraries(your_executable foo)

will cause the linker to look for a library libfoo.{so|a} in each of the link_directories.

Community
  • 1
  • 1
Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
  • Apologies, I skipped some of the steps that I am performing and omitted them from the question, for that reason the question might be a bit confusing as it is. I have just updated the contents, so that the question is clearer and it covers all of the stages that I am utilising. I think I am doing exactly what you have described in your answer, right? – mbilyanov Jun 15 '16 at 14:06
  • When I do that, I mean when I pass the folders, I get this: `WARNING: Target "3DPrimitiveExample" requests linking to directory "/Users/me/packages/builds/x86_64/of-0.9.3-osx-release/libs/openFrameworksCompiled/lib/". Targets may link only to libraries. CMake is dropping the item.` – mbilyanov Jun 15 '16 at 14:45
  • @symbolix That is because `target_link_libraries(${APP_NAME} ${OF_CORE_LIBS})` is now giving a list of *directories* to `target_link_libraries` when it requires a list of *library names*. `${OF_CORE_LIBS}` cannot be both a list of directories and a list of library names! You can't use it in both places. For `link_directories` you need a list of directories to be searched. For `target_link_libraries` you need a list of library names that shall be searched for. – Mike Kinghan Jun 15 '16 at 14:59
  • Now I am starting to understand. Thank you very much for your help and your patience. I have been totally ignorant on this matter. Please see the **update(1)** below my question. – mbilyanov Jun 15 '16 at 15:05
  • @symbolix The answer to your update(1) question is Yes. You will need to name your static libraries by the convention `libfoo.a`. In order to for the linkage option `-lfoo` to locate them, which is generated by `target_link_libraries(app foo)` – Mike Kinghan Jun 15 '16 at 15:10
  • I am trying this now. Thanks. – mbilyanov Jun 15 '16 at 15:13
  • All of the warnings seem to have gone. However I am getting an error. Could you please check **Update(2)**. The linker fails to find `-lopenFrameworks`. – mbilyanov Jun 15 '16 at 16:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/114774/discussion-between-mike-kinghan-and-symbolix). – Mike Kinghan Jun 15 '16 at 18:29