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.
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
.