How can I set with CMake in VisualStudio2010 the property "Additional Library Directories".
Example:
%(AdditionalLibraryDiretories) = "d:/librarys/wnt/i386/debug/"
configuration parameter -> linker -> general-> "Additional Library Directories"
I tried this and it doesn't work.
link_directories("d:/librarys/wnt/i386/debug/")
Turning my comments into an answer
What does link_directories() cover?
I tested it with VS2012 / CMake 3.3.0 and if you put your link_directories(...) before your add_executable(...) call it seems to work fine.
link_directories("d:/librarys/wnt/i386")
get_directory_property(_my_link_dirs LINK_DIRECTORIES)
message(STATUS "_my_link_dirs = ${_my_link_dirs}")
add_executable(...)
Everything you add with link_directories() will be appended to the directory property LINK_DIRECTORIES and assigned to whatever targets are listed afterwards.
In the upper example I get in Visual Studio "Additional Library Directories" property:
d:/librarys/wnt/i386;d:/librarys/wnt/i386/$(Configuration);%(AdditionalLibraryD‌​irectories)
CMake does - to cover libraries depending on Config - include two variants of what you have given in link_directories(): d:/librarys/wnt/i386 and d:/librarys/wnt/i386/$(Configuration).
What if you need more flexiblity?
If your debug/release path names are not matching the VS configuration name (e.g. fooba for debug), then you can't use link_directories(). One approach would be to extend the linker flags directly:
project(...)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /LIBPATH:\"d:/librarys/wnt/i386/fooba\"")
Then I get in the Debug config properties:
%(AdditionalLibraryDirectories);d:/librarys/wnt/i386/fooba
For the lack of flexibility of link_directories() I normally only use the target_link_libraries() command. E.g.:
target_link_libraries(MyExe debug "d:/librarys/wnt/i386/fooba/foo.lib")
would give in the Debug "Additional Dependencies" property:
kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;d:\librarys\wnt\i386\fooba\foo.lib
References
CMake link_directories from library
cmake - Global linker flag setting (for all targets in directory)
Related
I have 2 folders "inc" and "lib" in my project which have headers and static libs respectively. How do I tell cmake to use those 2 directories for include and linking respectively?
The simplest way of doing this would be to add
include_directories(${CMAKE_SOURCE_DIR}/inc)
link_directories(${CMAKE_SOURCE_DIR}/lib)
add_executable(foo ${FOO_SRCS})
target_link_libraries(foo bar) # libbar.so is found in ${CMAKE_SOURCE_DIR}/lib
The modern CMake version that doesn't add the -I and -L flags to every compiler invocation would be to use imported libraries:
add_library(bar SHARED IMPORTED) # or STATIC instead of SHARED
set_target_properties(bar PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/lib/libbar.so"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/include/libbar"
)
set(FOO_SRCS "foo.cpp")
add_executable(foo ${FOO_SRCS})
target_link_libraries(foo bar) # also adds the required include path
If setting the INTERFACE_INCLUDE_DIRECTORIES doesn't add the path, older versions of CMake also allow you to use target_include_directories(bar PUBLIC /path/to/include). However, this no longer works with CMake 3.6 or newer.
You had better use find_library command instead of link_directories. Concretely speaking there are two ways:
designate the path within the command
find_library(NAMES gtest PATHS path1 path2 ... pathN)
set the variable CMAKE_LIBRARY_PATH
set(CMAKE_LIBRARY_PATH path1 path2)
find_library(NAMES gtest)
the reason is as flowings:
Note This command is rarely necessary and should be avoided where there are other choices. Prefer to pass full absolute paths to
libraries where possible, since this ensures the correct library will
always be linked. The find_library() command provides the full path,
which can generally be used directly in calls to
target_link_libraries(). Situations where a library search path may be
needed include: Project generators like Xcode where the user can
switch target architecture at build time, but a full path to a library
cannot be used because it only provides one architecture (i.e. it is
not a universal binary).
Libraries may themselves have other private library dependencies that
expect to be found via RPATH mechanisms, but some linkers are not able
to fully decode those paths (e.g. due to the presence of things like
$ORIGIN).
If a library search path must be provided, prefer to localize the
effect where possible by using the target_link_directories() command
rather than link_directories(). The target-specific command can also
control how the search directories propagate to other dependent
targets.
might fail working with link_directories, then add each static library like following:
target_link_libraries(foo /path_to_static_library/libbar.a)
I have a CMake build that sends /IMPLIB to the linker on Windows. This is a problem in my case because the argument to implib is the same path as one of the input files.
It looks to me that CMake will always issue /IMPLIB when building with Visual Studio, and the passed argument cannot be modified.
Is there a way to control this behaviour?
Looking at CMake's source cmComputeLinkInformation.cxx it will only add a valid /implib:... option if CMAKE_IMPORT_LIBRARY_SUFFIX is set:
// Check whether we should use an import library for linking a target.
this->UseImportLibrary =
this->Makefile->IsDefinitionSet("CMAKE_IMPORT_LIBRARY_SUFFIX");
So in the following test the import library was removed from my executable project's options:
cmake_minimum_required(VERSION 3.0)
project(NoImpLib CXX)
unset(CMAKE_IMPORT_LIBRARY_SUFFIX)
file(WRITE main.cpp "int main() { return 0; }")
add_executable(${PROJECT_NAME} main.cpp)
An VS specific alternative - because this option is not set otherwise/per configuration - would be to add the global property IgnoreImportLibrary with:
set_target_properties(${PROJECT_NAME} PROPERTIES VS_GLOBAL_IgnoreImportLibrary "true")
I don't think its possible to prevent CMake from issuing an /IMPLIB option to the linker.
You can however control the name of the generated import library by setting the following properties of a shared library target:
add_library(foo SHARED foo.cpp)
# set base name of generated DLL import library
set_target_properties(foo PROPERTIES ARCHIVE_OUTPUT_NAME "bar")
# set prefix of generated DLL import library
set_target_properties(foo PROPERTIES IMPORT_PREFIX "")
# set suffix of generated DLL import library
set_target_properties(foo PROPERTIES IMPORT_SUFFIX ".lib")
The name of the generated shared library can be adjusted by setting the following target properties:
# set base name of generated DLL shared library
set_target_properties(foo PROPERTIES RUNTIME_OUTPUT_NAME "bar")
# set prefix of generated DLL shared library
set_target_properties(foo PROPERTIES PREFIX "")
# set suffix of generated DLL shared library
set_target_properties(foo PROPERTIES SUFFIX ".dll")
This answer suggests adding the /noimplib option to target_link_options() should prevent the generation of an import library, but in my experience, it still gets generated.
This e-mail has the answer that worked for me; simply avoid specifying ARCHIVE DESTINATION and LIBRARY DESTINATION in your install() command.
I'm currently trying to get CMake running for my project (on windows). I want to use a custom location where all libraries are installed. To inform CMake about that path I tried to do that:
set(CMAKE_PREFIX_PATH D:/develop/cmake/libs)
But when I try to find the library with
find_library(CURL_LIBRARY NAMES curl curllib libcurl_imp curllib_static)
CMake can't find it.
When I set my prefix path to
set(CMAKE_PREFIX_PATH D:/develop/cmake/libs/curl)
... the library is located.
So my question is:
How can I configure CMake properly to work with a directory structore at a custom location which looks like that:
D:/develop/cmake/libs/
-> libA
-> include
-> lib
-> libB
-> include
-> lib
-> ...
-> include
-> lib
In "include" lie the public headers and in "lib" are the compiled libraries.
edit:
The current workaround for me is, to do this before i search for libraries:
set(CUSTOM_LIBRARY_PATH D:/develop/cmake/libs)
file(GLOB sub-dir ${CUSTOM_LIBRARY_PATH}/*)
foreach(dir ${sub-dir})
if(IS_DIRECTORY ${dir})
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH};${dir})
endif()
endforeach()
But that way the default module for boost wont find it until it because the directory structore of boost is a bit different.
boost -> include -> boost-1_50 -> *.hpp
When I move the content if "boost-1_50" to "include" the library can be found but that way it's not possible to handle multiple versions right?
The simplest solution may be to add HINTS to each find_* request.
For example:
find_library(CURL_LIBRARY
NAMES curl curllib libcurl_imp curllib_static
HINTS "${CMAKE_PREFIX_PATH}/curl/lib"
)
For Boost I would strongly recommend using the FindBoost standard module and setting the BOOST_DIR variable to point to your Boost libraries.
I saw that two people put that question to their favorites so I will try to answer the solution which works for me:
Instead of using find modules I'm writing configuration files for all libraries which are installed. Those files are extremly simple and can also be used to set non-standard variables. CMake will (at least on windows) search for those configuration files in
CMAKE_PREFIX_PATH/<<package_name>>-<<version>>/<<package_name>>-config.cmake
(which can be set through an environment variable).
So for example the boost configuration is in the path
CMAKE_PREFIX_PATH/boost-1_50/boost-config.cmake
In that configuration you can set variables. My config file for boost looks like that:
set(boost_INCLUDE_DIRS ${boost_DIR}/include)
set(boost_LIBRARY_DIR ${boost_DIR}/lib)
foreach(component ${boost_FIND_COMPONENTS})
set(boost_LIBRARIES ${boost_LIBRARIES} debug ${boost_LIBRARY_DIR}/libboost_${component}-vc110-mt-gd-1_50.lib)
set(boost_LIBRARIES ${boost_LIBRARIES} optimized ${boost_LIBRARY_DIR}/libboost_${component}-vc110-mt-1_50.lib)
endforeach()
add_definitions( -D_WIN32_WINNT=0x0501 )
Pretty straight forward + it's possible to shrink the size of the config files even more when you write some helper functions. The only issue I have with this setup is that I havn't found a way to give config files a priority over find modules - so you need to remove the find modules.
Hope this this is helpful for other people.
Use CMAKE_PREFIX_PATH by adding multiple paths (separated by semicolons and no white spaces). You can set it as an environmental variable to avoid having absolute paths in your cmake configuration files
Notice that cmake will look for config file in any of the following folders
where is any of the path in CMAKE_PREFIX_PATH and name is the name of the library you are looking for
<prefix>/ (W)
<prefix>/(cmake|CMake)/ (W)
<prefix>/<name>*/ (W)
<prefix>/<name>*/(cmake|CMake)/ (W)
<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/ (U)
<prefix>/(lib/<arch>|lib|share)/<name>*/ (U)
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)
In your case you need to add to CMAKE_PREFIX_PATH the following two paths:
D:/develop/cmake/libs/libA;D:/develop/cmake/libB
There is no way to automatically set CMAKE_PREFIX_PATH in a way you want. I see following ways to solve this problem:
Put all libraries files in the same dir. That is, include/ would contain headers for all libs, lib/ - binaries, etc. FYI, this is common layout for most UNIX-like systems.
Set global environment variable CMAKE_PREFIX_PATH to D:/develop/cmake/libs/libA;D:/develop/cmake/libs/libB;.... When you run CMake, it would aautomatically pick up this env var and populate it's own CMAKE_PREFIX_PATH.
Write a wrapper .bat script, which would call cmake command with -D CMAKE_PREFIX_PATH=... argument.
You have one extra level of nesting.
CMAKE will search under $CMAKE_PREFIX_PATH/include for headers and $CMAKE_PREFIX_PATH/libs for libraries.
From CMAKE documentation:
For each path in the CMAKE_PREFIX_PATH list, CMake will check
"PATH/include" and "PATH" when FIND_PATH() is called, "PATH/bin" and
"PATH" when FIND_PROGRAM() is called, and "PATH/lib and "PATH" when
FIND_LIBRARY() is called.
I've encountered a similar scenario. I solved it by adding in this following code just before find_library():
set(CMAKE_PREFIX_PATH /the/custom/path/to/your/lib/)
then it can find the library location.
I have to make a one click build of a projet made for Cmake ( already works on Linux) with a batch file that downloads all the 3rd party libraries and compiles them. (win64)
If posible i dont want to change projets CMakeLists.txt.
I already build the project in VS2010 GUI. and i had to change the folowing:
a. had to change Configuration properties-C++-Command line: added /DWNT /D "CAD_STATIC"
b. had to add a long list of libraries in Configuration properties- Linker input- additional dependencies.
c. add library directories for those libraries
d. add include directories.
The project compiled and worked ok.
Now i need to make the same with only batch commands.
I already build the project file with cmake with:
cmake ..\projectsource -G "Visual Studio 10 Win64" -DGLEW_LIBRARY:FILEPATH=%myroot%\glew\trunk\lib\Release\glew.lib -DGLUT_glut_LIBRARY:FILEPATH=%myroot%\freeglut\trunk\lib\Release\freeglut.lib -DMKL_LIBRARIES:FILEPATH=%myroot%\mkl\em64t\lib\mkl_core.lib -DOpenCascade_INCLUDE_DIR:PATH=%myroot%\OpenCascade
Now i need a command like "devenv project.sln /useenv " that does the same as the stuff i did under #2.
I tried with a env include & lib like:
set "include=%myroot%\glew\trunk\include;%myroot%\freeglut\trunk\include;%myroot%\mkl\include;%myroot%\qt\include;%myroot%\OpenCascade\include\oce;%myroot%\trimo\src\CadModel;%include%"
set "lib=%myroot%\glew\trunk\lib\Release\*.lib;%myroot%\freeglut\trunk\lib\Release\*.lib;%myroot%\mkl\em64t\lib\*.lib;%myroot%"\qt\lib\*.lib;%myroot%\OpenCascade\Win64\lib\*.lib;%lib%"
All the help is very much appreciated. I'm stuck. Thanks
Edit:
I got another problem:
How can i unlink a library that gets linked in a project.sln automaticly by cmake?
will "lib=%myroot%\glew\trunk\lib\Release*.lib; link all the .lib files like u would get if u put all the libs in a vs2010 gui -Linker input- additional dependencies?
If you're already setting the required include and lib variables, then probably all that's missing is:
set "cl=/DWNT /DCAD_STATIC"
then you should be able to use
devenv project.sln /useenv /build
Note, you've also got libpath available to set search paths for the libraries if required.
Answers to further questions
I don't know of a way to do that.
No. I hadn't noticed you were doing that in your original question - sorry! The LIB env var sets search paths in which libs could be found, it's not for the full path to the actual lib itself.
What you're trying to achieve is exactly the sort of scenario at which CMake excels. You're fighting CMake here when it's probably the solution to the problems :-)
If I were you, I'd edit the CMakeLists.txt to include things like:
SET(MY_ROOT <path to %myroot%>)
FIND_LIBRARY(GLEW_LIBRARY glew ${MY_ROOT}/glew/trunk/lib/Release)
IF(NOT GLEW_LIBRARY)
MESSAGE(FATAL_ERROR "glew.lib not found in ${MY_ROOT}/glew/trunk/lib/Release")
ENDIF()
FIND_LIBRARY(GLUT_glut_LIBRARY freeglut ${MY_ROOT}/freeglut/trunk/lib/Release)
IF(NOT GLUT_glut_LIBRARY)
MESSAGE(FATAL_ERROR "freeglut.lib not found in ${MY_ROOT}/freeglut/trunk/lib/Release")
ENDIF()
FIND_LIBRARY(MKL_LIBRARIES mkl_core ${MY_ROOT}/mkl/em64t/Release)
IF(NOT MKL_LIBRARIES)
MESSAGE(FATAL_ERROR "mkl_core.lib not found in ${MY_ROOT}/mkl/em64t/Release")
ENDIF()
INCLUDE_DIRECTORIES(${MY_ROOT}/OpenCascad)
ADD_DEFINITIONS(-DWNT -DCAD_STATIC)
TARGET_LINK_LIBRARIES(<your target>
${GLEW_LIBRARY}
${GLUT_glut_LIBRARY}
${MKL_LIBRARIES}
<any other libs...>
)
This is all Windows-specific, and Release-specific. You could adapt the FIND_LIBRARY calls to cater for Unix/OSX options too, or you could wrap this in IF(WIN32) ... ENDIF() blocks.
You could also do FIND_LIBRARY calls for the Debug versions too if required (giving them different variable names) and adding them like:
TARGET_LINK_LIBRARIES(<your target>
optimized ${GLEW_LIBRARY}
optimized ${GLUT_glut_LIBRARY}
optimized ${MKL_LIBRARIES}
debug ${GLEW_LIBRARY_DEBUG}
debug ${GLUT_glut_LIBRARY_DEBUG}
debug ${MKL_LIBRARIES_DEBUG}
<any other libs...>
)
You'll also be able to remove whatever libraries you want from whatever targets you want by modifying the list of libs passed in the TARGET_LINK_LIBRARIES call(s).
If you want to grab all *.lib files in a directory, add something like this:
FILE(GLOB ALL_GLEW_LIBS "${MY_ROOT}/glew/trunk/lib/Release/*.lib")
TARGET_LINK_LIBRARIES(<your target> ${ALL_GLEW_LIBS})
If you do use the GLOB call, and you also need Debug and Release, be sure to prefix each list item with debug or optimized as appropriate, e.g.
FOREACH(GLEW_ITR ${ALL_GLEW_LIBS_RELEASE})
SET(ALL_GLEW_LIBS ${ALL_GLEW_LIBS} optimized ${GLEW_ITR})
ENDFOREACH()
FOREACH(GLEW_ITR ${ALL_GLEW_LIBS_DEBUG})
SET(ALL_GLEW_LIBS ${ALL_GLEW_LIBS} debug ${GLEW_ITR})
ENDFOREACH()
TARGET_LINK_LIBRARIES(<your target> ${ALL_GLEW_LIBS})
If all this is then catered for by CMake, you don't need to set any env vars in the batch script; you just do:
devenv project.sln /build
I use CMake to generate a Visual Studio 2010 project and solution file. Actually I could set different settings,
like warning level, incremental building flag ect. from CMake. But I can't set additional includes and libraries,
listed in the VC++ Directory configuration tab. Actually I've to set up those directories manually. This is stupid
and boring...
I tried to set the following CMake variables: CMAKE_INCLUDE_PATH, INCLUDE_DIRECTORY
but nothing happend. If i open the project, the additional include directory of the solution is always empty (only standard MSVE settings are given).
I also tired to set this variables after executable creation, but this has also no effect.
This is what i do directly in the header of the cmake
file:
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(${MODULE_NAME})
IF (MSVC)
# Activate C++ exception handling
IF (NOT CMAKE_CXX_FLAGS MATCHES "/EHsc")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
ENDIF ()
# Set Warning level always to 4
IF (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
ELSE ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
ENDIF ()
#read path of dependency modules
file(READ "msvc.deps" MSVC_PROPERTIES)
STRING(REGEX REPLACE ";" "\\\\;" MSVC_PROPERTIES "${MSVC_PROPERTIES}")
STRING(REGEX REPLACE "\n" ";" MSVC_PROPERTIES "${MSVC_PROPERTIES}")
FOREACH(e ${MSVC_PROPERTIES})
SET(INCLUDE ${INCLUDE} ${e})
MESSAGE(STATUS "[INFO]: Value ${e}")
ENDFOREACH(e)
INCLUDE_DIRECTORIES(${INCLUDE})
ENDIF ()
In the .deps file I've added to path of my dependeny modules,
line separated:
c:\binrev\development\boost\1.47\includes
c:\binrev\repository\modules\brCore\trunk\includes
Both are read successfully but couldn't be set as additional
include directory in my MSVC solution.
Best regards,
Hellhound
CMake is pretty well documented, if I have understood your question then the commands I think you're looking for are
include_directories(...),
link_directories(...) and
target_link_libraries(...).
Although some configuration is done by setting variables, most of it is done using commands to add certain information to parts of the build and slightly less frequently by setting properties on targets.
I believe that include_directories ("path") somewhere in the CMakeLists.txt does add the path to C++ includes path.
Yes. Although it does not appear in "Include Directories" under the "VC++ Directories" tab, it does show up in the "Additional Include Directories" under C/C++ -> General.