I am pretty new to cmake and wonder how I can do this is cmake. I want to place all the intermediate files (like the .o files) to be placed in a certain directory (say "build") and then once the build is done I want copy certain files I need (e.g., the .exe, .dll like the end product) from build directory to "stage" directory. how can I specify the path to these two directories (build and stage)? Cmake will also check if the build/stage directory exists or not. If does not exist, it will create the directories for me.
Any help will be appreciated.
What are you asking is the most often CMake use case.
To make whole build process to occur in arbitary dir, you should run cmake /path/to/your/project from that dir (or use cmake-gui).
Your source dir would be untouched until you explicitly tell CMake to output some files there.
As for point 2:
You should place install() invocations into your CMakeLists.txt (see documentation on install()) and set CMAKE_INSTALL_PREFIX to the dir where you wish files to be copied. After that you can run make install or cmake -P cmake_install.cmake from your build dir to install these files.
I would suggest another approach.
make out-of-source builds see here, so that all your build stuff is in an own folder
copy your executables from your build directory in an own folder with explicit copying see here
Or instead of choosing step 2 you also can provide an install routine where the needed executables are installed in a give path. see here
Related
Is it possible to specify build directory within CMakeLists file? If yes, how.
My aim is to be able to call "cmake" within top level source directory and have cmake figure out the build directory.
Afaik, with CMake the build directory is always the directory from where you invoke the cmake or ccmake command. So if you want to change the build directory, you have to change directories before running CMake.
To control the location where executables, static and shared libraries are placed once finished, you can modifiy CMAKE_RUNTIME_OUTPUT_DIRECTORY, CMAKE_ARCHIVE_OUTPUT_DIRECTORY, and CMAKE_LIBRARY_OUTPUT_DIRECTORY respectively.
By design, there is not a way to specify that in CMakeLists.txt. It is designed for the user to be able to build the project in whatever directory they want. The typical workflow is:
Check out the project source code.
Go to desired build directory, or the source dir if you plan to do an in-source build.
Run cmake or ccmake to configure the project in that build directory.
Build your project.
All of the directories specified within your CMakeLists.txt should be relative to the ${PROJECT_BINARY_DIR} and ${PROJECT_SOURCE_DIR} variables. In this way, your code becomes buildable across different platforms, which is the goal of CMake.
I have a project which uses CMake. Most of the project builds with CMake, but there's one subdirectory with a complicated build procedure that doesn't work with CMake. For this one directory, we have a hand-written Makefile. To build this one special directory, we manually copy it over to the build directory and call make on it after we've called cmake && make to build the rest of the project.
What I want CMake to do is just copy over this one directory to the build directory as is, with its existing Makefile, without trying to generate a Makefile. Then when I call make on the top level build directory, it just invokes the hand-written Makefile for this one directory. Is this possible?
I short: Yes, this is possible.
Steps:
Copy the Directory
Add the Makefile as a build step using either add_custom_target or add_custom_command depending on the purpose of the makefile
As I have to build both static and shared library for x86 and arm platform. So with the same CMakeLists.txt, I have to run it four times with different configuration. I want to use CPack to pack those libraries to one tar file. However, it seems that only the last cmake build results will be included in the tar file.
Is there any idea for this problem?
Here is part of my CMakeLists.txt:
install(FILES api_cpp.h api_c.h DESTINATION api_lib/include)
install(TARGETS lib
ARCHIVE DESTINATION api_lib/${lib_folder}
LIBRARY DESTINATION api_lib/${lib_folder})
INCLUDE(CPack)
SET(CPACK_GENERATOR "TGZ")
Obviously, you use a single-configuration generator -- meaning that you can't have more than one particular build configuration in the same build directory. Actually the problem exists even for the multi-configuration generators as well (at least for CMake < 3.16).
To make a package one ought to run CMake, which generates build files, then build a project, and finally can make a package (e.g., w/ make package). The last action runs CPack, which performs make install DESTDIR=<some-temporary-dir>, and then cpack just compress the directory into an archive. So, having a build directory with the only configuration it's impossible to have an archive with few of them.
To make your need possible you ought to run CMake 4 times doing install into the same location and then pack that directory into a package. It can be done with CMake+CPack, but IMHO easier to do w/ a trivial shell script :)
I've found that when I delete cpp files from my project using cmake and ninja, I can't easily compile it without first completely deleting my build directory and starting from scratch. CMake and/or Ninja apparently squirrels away a number of references to all the cpp files that it compiles, even deleting the CMake cache before re-running CMake doesn't remove all the references.
Is this a known issue? Is there a solution? I've occasionally just run rm $(grep -R <filename> <builddir>), but that's a terrible kludge.
EDIT: It appears I was mistaken, as I have not been able to duplicate this problem. Manually re-running CMake appears to always generate the correct list of .cpp files, even using GLOB to generate lists of sources.
Turning my comments into an answer
Collecting your source files with file(GLOB ...)
Yes, CMake won't know about new or deleted source files when collecting your source files with the file(GLOB ...) command. This is a known restriction with CMake. I've changed my CMake project(s) to list all source files individually exactly because of this. Out of convenience I'm still collecting my header files with the file(GLOB ...) command.
Quoting from CMake's file() command documentation:
We do not recommend using GLOB to collect a list of source files from
your source tree. If no CMakeLists.txt file changes when a source is
added or removed then the generated build system cannot know when to
ask CMake to regenerate.
Deleting CMakeCache.txt to retrigger Configuration
Just deleting CMakeCache.txt may not be enough to retrigger the CMake configuration. Issue 0014820: warn users about removing only CMakeCache.txt claims you need also to delete all CMakeFiles directories.
From my experience the most reliable way to retrigger the CMake configuration is to touch one of the projects CMakeLists.txt files.
Note: For ninja CMake adds a rebuild_cache target for conveniently running CMake for your project again.
Retrigger after Updates from Source Control
Just one thought: if the deletion of source files happens because they were removed from your source control there maybe a workaround that still allows you to use file(GLOB ...) on your source files.
E.g. if you use GIT you could add the following to your main CMakeLists.txt:
configure_file(${CMAKE_SOURCE_DIR}/.git/index ${PROJECT_BINARY_DIR}/git_index.tmp)
Disadvantage: It would retrigger configuration which each GIT operation (update, commit, ...).
Some References:
run cmake when adding file in eclipse
CMake: Correct way to make an arbitrary file trigger
I got the Box2D project source and want to compile the testbed portion of it.
The project folder contains folders like: freeglu glui testbed(a demo) helloword(a demo)
Box2D Build CMakeFiles
There are many CMakeLists.txt in all the different folders.
I was thinking that I should cmake all those files so that make files are created in all places required.
I read this (as instructions to do do want I want) :
wget http://box2d.googlecode.com/files/Box2D_v2.2.1.zip
unzip Box2D_v2.2.1.zip
cd Box2D_v2.2.1/Build
cmake ..
make
What does the cmake .. do?
There is no CMakeLists.txt in the build folder.
cmake is a Makefile generator.
When you call cmake [path], you ask it to generate a Makefile in the current directory following instructions given in [path]/CMakeLists.txt
Usually cmake output some messages while it is working, and after it is done without errors, you can type "make" to execute your newly created Makefile.
CMakeLists.txt files can reference other CMakeLists.txt file in sub-directories, so you are usually only interested by the CMakeLists.txt of the top directory, not the other ones.
Using an empty "build" directory is a technique called "out-of-source build", in which all your generated files (.o, executable, Makefile, .anything) are generated in the separate "build" directory and not mixed with source files. If you want to clean all, you can delete all the content of the build directory.
In fact, you can put your "build" directory in any place, as long as you give cmake the correct path of the top CMakeLists.txt. You can even have several build directories. It is very useful if you need several different builds at the same time (with different options, different versions of gcc, etc.)
In old programs, you generate the Makefile too, but using ./configure (this is called auto-tools. You may have encountered that already). cmake is considered a successor of the auto-tools.
cmake .. generates makefiles in the current directory, using ../CMakeLists.txt file as starting point. make command, executed after this, builds the program, using generated makefile(s) as an input. This is convenient to keep a source code and build results in different folders. General syntax is: cmake source-dir (of course, there are a lot of other switches).
Well, .. is shorthand for the parent folder, so it will presumably act upon whatever it finds in Box2D_v2.2.1.