Issue
I've been using CMake and Eclipse on linux for a while and have been working with multiple target projects containing numerous executables and shared objects.
I use out of source builds and on linux the binaries are put into their own directories. When I do this on linux eclipse is somehow able to find the shared objects and run the executables fine but on windows this doesn't happen.
On Windows I am having to add a PATH environment variable that points to the dlls or I could build into a single bin and lib directory (although I had an issue I've forgotten in the past with CMake that made me want to avoid this).
Why is this working differently on Windows to linux? Is it a setting I'm missing or does this just not work?
The builds themselves are working perfectly. I'm using MinGW, Eclipse Kepler and Windows 7 64 bit.
Thanks in advance.
Solution
Windows simply doesn't have some of the necessary concepts to allow CMake to set up your build environment. When linking Windows will look in the same directory as the binary, and then search the directories in your PATH. There isn't anything like RPATH, which is used on most Unix platforms, to inject in other more appropriate paths. The DLLs should generally be installed alongside your binaries, in the same directory.
In my opinion, best practice on Windows is to put the DLLs next to your binaries. CMake attempts to make this easier,
install(TARGETS MyTarget
EXPORT "MyProjectTargets"
RUNTIME DESTINATION "${INSTALL_RUNTIME_DIR}"
LIBRARY DESTINATION "${INSTALL_LIBRARY_DIR}"
ARCHIVE DESTINATION "${INSTALL_ARCHIVE_DIR}")
would install DLLs to the RUNTIME destination, but put the libs in the LIBRARY destination. This means that typically on Unix-like OSes lib has the shared objects, but CMake knows that DLLs are effectively runtime and would go in bin. Hopefully this makes things clearer. It is impossible for CMake/Eclipse to really improve this much, beyond perhaps injecting additional directories into your PATH when clicking run from Eclipse (not sure if that is possible).
If you are concerned with the build tree, then the following would work well there (as suggested in the comments below):
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
If you want to allow these to be overridden (can be useful) they should be protected with if(NOT var_name) blocks too.
Answered By - Marcus D. Hanwell