I have a project organized as follows:
include/
src/
share/myprogram/
where share/myprogram/ contains resources.
My program is accessing these resources using relative paths. The executable expects to find them in ../share/myprogram/.
I would like when I run:
mkdir build
cd build
cmake ..
make
to have the following to happen:
make a bin directory
compile and put the executable in bin/
copy the share directory in the build directory
I am looking for a clean way of doing this. Ideally, I would like CMake to be aware of the resources as resources.
I know that I could use a copy custom command. Is this the only way to achieve this?
Bonus
If the resources could appear under Resources in Xcode when using the Xcode generator, and the copy be a clean copy phase under the mybin target, that would be awesome (and that's what I mean by CMake being aware of the resources as resources.)
Update:
What I have thus far:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
add_executable(mybin ${Headers} ${Sources})
add_custom_target(
Resources ALL
${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/share ${PROJECT_BINARY_DIR}/share
SOURCES ${Resources}
)
You may use Configure_file for copying files from source dir to binary dir. it has parameter Copyonly.
I am doing a unix command line tool, I am not doing a Mac OS X bundle and Xcode's resource folder is only for bundle resources so forget the bonus.
I realized that I wasn't doing things correctly.
Using a relative path to access a resource is not reliable since the program can be executed from anywhere.
What I did is to look for resources in a hierarchy of folder, starting from user specified, to environment variable, to relative directories and finally to standard unix directories.
So actually, the copy phase during the build is not necessary anymore. Only the installation matters and that is fairly easy:
install(DIRECTORY share/ DESTINATION share)
FYI, I kept my custom_target as is since I like having resources visible in Xcode, and calling it Resources makes it pretty :)
Related
We have multiple libraries in different folder, The main application needs to build those libraries in other folders and install them to output folder and then the main application needs to link to libraries to build executable.
I am able to build the libraries present in other folders using add_subdirectory() in a loop, but I am not able to install them to output folder by main cmake file. Could anyone help me out on this.
The main application needs to build those libraries in other folders and install them to output folder and then the main application needs to link to libraries to build executable.
It is not necessary in CMake to install libraries in order to link to them. You can build the libraries and have your main executable link to them without installing the libraries. When you need to install your application as a whole, you can install libraries along with the executable if needed i.e. if the libraries are shared ones and not static ones.
One example of how you can organize things: assume you have the following structure in your project:
CMakeLists.txt # root of project
|
|--lib
| |--CMakeLists.txt # library subproject
|
|--app
|--CMakeLists.txt # app subproject
Then your root CMakeLists.txt can look like this:
project(MyProject)
add_subdirectory(lib)
add_subdirectory(app)
The lib subproject's CMakeLists.txt can look like this:
project(MyLib)
set(SOURCES <...>) # specify library's sources
add_library(${PROJECT_NAME} ${SOURCES})
set(MyLib ${PROJECT_NAME} CACHE INTERNAL "")
The last line in the snippet above is aimed to make MyLib variable available everywhere within the project. I found this trick here and used it successfully in my projects. Maybe there are better options here, if anyone knows them, feel free to suggest.
The app's CMakeLists.txt can then look like this:
project(MyApp)
set(SOURCES <...>) # specify app's sources
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} ${MyLib})
I haven't covered the installation here but it's actually straightforward: if your libraries are static ones, you only need to install the executable using install TARGETS. If your libraries are shared ones, you need to install them along with the executable.
How can I include an SO file when I build for linux? With windows I simply put the dll in the same folder but that did not work with the linux build. In particular, I am building a go sciter project and need to include the libsciter-gtk-64.so in the executable/package.
My way of solving this was to use an additional tool, which had the added benefit of an optional desktop file and other metadata. AppImage solves the library problem, all I had to do was create an AppImage with the so files in /usr/lib/ and build through their command.
#Robert's solution is nice. One could also place the *.so file in the same directory as the executable and create a start.sh script with the line:
LD_LIBRARY_PATH="$(dirname "$0")" "$(dirname "$0")/your_executable"
After installing cmake-3.8.1-win64-x64 I got thisenter image description here
So what can I do with this? Thanks.
cmake-gui does not help you create cmake configuration files, it parses these files to generate and configure projects.
In your source code directory, you should have a CMakeLists.txt file which defines the rules for CMAKE to configure your problem. That directory should be entered into the first box.
Next, you get to decide where to build the binaries. We could do it in the source directory, but the generated artifacts could pollute what is already there. "Cleaning" the build by deleting all of those artifacts while keeping the original sources is tedious at best, so it's a good idea to make an empty directory and use that as your binaries path.
Once you have those fields entered, you should be able to "Generate" or "Configure" your project. If you need help creating a CMakeLists.txt file (that's really the complicated part), then check out their tutorial.
I'm working on my first project using cmake, and for the most part it's been going well but I've run into one problem I can't figure out.
Let's say I have my CMakeLists.txt file located at ~/project/build. I would like for the output from cmake (not the binaries, but the makefile/configuration files) to be independent of where I run cmake from.
As an example, if my terminal is sitting in the ~/project/build directory, calling cmake ~/project/build creates the makefile and everything else within the ~/project/build directory. This is the behaviour that I'd like. If I call cmake ~/project/build from anywhere else, it creates the makefile and everything else in whatever directory the terminal called the program from.
Is it possible to force cmake to generate its makefile and associated files in the same folder as the CMakeLists.txt file? I've taken a look through the documentation and I've had no problems figuring out how to change binary output directories, but I can't really find any mention of what I'm trying to do.
I realize this is a pretty minor annoyance (it's not that hard to move into my build folder before building the project) but I'm just wondering if it's possible and if there's some reason it wouldn't be advised.
You have to use 2 commands for this
1) cmake -B "Dest path(Any path in which u want to generate the output files)" -H"Source path(root CMakeLists.txt path)"
2) cmake --build "Dest path"
I'm using CMake on Windows to build test suite based on Boost.Test. As I'm linking to Boost.Test dynamically, my executable needs to be able to find the DLL (which is under ../../../boost/boost_1_47/lib or something like that relative to the executable).
So I need to either copy the DLL into the folder where the executable is, or make it findable in some other way. What's the best way to achieve this with CMake?
-- Additional info --
My CMakeLists.txt has this Boost related configuration at the moment:
set(Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0")
set(BOOST_ROOT "../boost")
find_package(Boost 1.47 COMPONENTS unit_test_framework REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIR})
add_executable(test-suite test-suite.cpp)
target_link_libraries(test-suite ${Boost_LIBRARIES})
Assuming you are running your tests by building the RUN_TESTS target in Visual Studio:
I always add .../boost/boost_1_47/lib to my command PATH environment variable, so the boost unit_test_framework dlls can be found at run time. That's what I recommend.
If for some reason changing your PATH is not possible, you could copy the files with cmake.
(untested)
get_filename_component(LIBNAME "${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}" NAME)
add_custom_command(TARGET test-suite POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE}" "${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME}"
)
3. If you are NOT only running the tests at build time (as I was assuming above), then you need a series of INSTALL commands, like Hans Passant suggested. In your snippet you don't have an INSTALL command for your executable; so even your executable won't end up "in the executable folder". First add a cmake INSTALL command to put your executable someplace in response to the cmake INSTALL target. Once you have that working, we can work on figuring out how to add another INSTALL command to put the boost unit_test_framework library into the same location. After that, if you want to make an installer using CPACK, the library will automatically be installed with the executable.
I ended up using the install command to copy the Boost DLL over to the executable's folder:
get_filename_component(UTF_BASE_NAME ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE} NAME_WE)
get_filename_component(UTF_PATH ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_RELEASE} PATH)
install(FILES ${UTF_PATH}/${UTF_BASE_NAME}.dll
DESTINATION ../bin
CONFIGURATIONS Release RelWithDebInfo
)
get_filename_component(UTF_BASE_NAME_DEBUG ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY_DEBUG} NAME_WE)
install(FILES ${UTF_PATH}/${UTF_BASE_NAME_DEBUG}.dll
DESTINATION ../bin
CONFIGURATIONS Debug
)
I have a very similar problem, but the solution presented here is not really satisfactory.
Like the original poster, I want to run unit tests based on boost::test.
I have multiple test projects, one for each mayor component of our product.
Having to run the install target prior to every test means recompiling the whole thing just to run the tests belonging to a core component. That's what I want to avoid.
If I change something in a core component, I want to compile that core component and the associated tests. And then run the tests. When the tests succeed, only then do I want to compile and eventually install the rest of it.
For running the tests in the debugger, I found some very useful cmake scripts at :
https://github.com/rpavlik/cmake-modules
With this, I can specify all the directories of the required dlls, and the PATH environment variable is set for the new process:
# for debugging
INCLUDE(CreateLaunchers)
create_target_launcher(PLCoreTests
ARGS "--run-test=Core1"
RUNTIME_LIBRARY_DIRS ${PL_RUNTIME_DIRS_DEBUG} ${PROJECT_BINARY_DIR}/bin/Debug
WORKING_DIRECTORY ${PL_MAIN_DIR}/App/PL/bin
)
Where ${PL_RUNTIME_DIRS_DEBUG} contains the directories where the dlls from boost and all the other libraries can be found.
Now I'm looking for how I can achieve something similar with ADD_CUSTOM_COMMAND()
Update:
ADD_CUSTOM_COMMAND() can have multiple commands that cmake writes into a batch file. So, you can first set the path with all the runtime directories, and then execute the test executable. To be able to easily execute the tests manually, I let cmake create an additional batch file in the build directory:
MACRO(RunUnitTest TestTargetName)
IF(RUN_UNIT_TESTS)
SET(TEMP_RUNTIME_DIR ${PROJECT_BINARY_DIR}/bin/Debug)
FOREACH(TmpRuntimeDir ${PL_RUNTIME_DIRS_DEBUG})
SET(TEMP_RUNTIME_DIR ${TEMP_RUNTIME_DIR} ${TmpRuntimeDir})
ENDFOREACH(TmpRuntimeDir)
ADD_CUSTOM_COMMAND(TARGET ${TestTargetName} POST_BUILD
COMMAND echo "PATH=${TEMP_RUNTIME_DIR};%PATH%" > ${TestTargetName}_script.bat
COMMAND echo ${TestTargetName}.exe --result_code=no --report_level=no >> ${TestTargetName}_script.bat
COMMAND ${TestTargetName}_script.bat
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug
)
ENDIF(RUN_UNIT_TESTS)
ENDMACRO()
With this, the unit tests catch the errors as soon as possible, without having to compile the whole lot first.