Cmake to add VS2010 Project custom Build Events - visual-studio-2010

Is there a way I can set CMake to generate a VS2010 Project file that has Pre Build or Post Build event in them?
Thanks.

From the CMake documentation:
add_custom_command(TARGET target
PRE_BUILD | PRE_LINK | POST_BUILD`
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[WORKING_DIRECTORY dir]
[COMMENT comment] [VERBATIM])
This defines a new command that will be associated with building the specified
target. When the command will happen is determined by which of the following
is specified:
PRE_BUILD - run before all other dependencies
PRE_LINK - run after other dependencies
POST_BUILD - run after the target has been built
Note that the PRE_BUILD option is only supported on Visual Studio 7 or later.
For all other generators PRE_BUILD will be treated as PRE_LINK.
For example, if your target is named MyProject and you want to run the command SomeCommand with argument -1 -2 after the building, add the following line after your add_executable or add_library call, because the target has to be defined:
add_custom_command(TARGET MyProject
POST_BUILD
COMMAND SomeCommand ARGS "-1 -2"
COMMENT "Running SomeCommand")
See the docs for add_custom_command for more details on how to use it.

Related

CMake copy_if_different command copies the source file to destination, even if the source hasn't been changed

I am trying to use CMake's copy_if_different command to copy one tar.gz file to my folder, but every time I am rebuilding the project (event not with clean command), the command sees that it's executed always, even if the source file hasn't been changed. Here is an example below:
set(EXTERNAL_LIB_PATH_SRC "/home/pst/libs/void_lib.tar.gz")
set(EXTERNAL_LIB_PATH_DST "/home/pst/my_app/build/external_libs/void_lib.tar.gz")
set(UNPACK_PATH "/home/pst/my_app/build/external_libs/unpacked/")
add_custom_target(copy_libraries
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${EXTERNAL_LIB_PATH_SRC} ${EXTERNAL_LIB_PATH_DST}
COMMENT "Start copying external libraries to ${EXTERNAL_LIB_PATH_DST}")
add_custom_target(extract_libraries ALL
COMMAND ${CCRYPT} -d -k "some_key" ${EXTERNAL_LIB_PATH_DST} -c | ${TAR} -xf - -C ${UNPACK_PATH} -Z
COMMENT "Finished extracting libraries.."
VERBATIM)
add_dependencies(extract_libraries copy_libraries)
add_dependencies(my_app extract_libraries)
Am I doing something wrong here? copy_if_different seems that doesn't check the files at all, and the command is always invoked.
Also, Is there a way to avoid executing the "extract_libraries" command all the time, and executed it only if copy_libraries has been run?

CMake include resources in build [duplicate]

I've got some config files (xml, ini, ...) in the config directory next to the source files. How can I copy all the files in the config directory into the build directory (next to the executable file) each time I make the project?
You can use add_custom_command.
Say your target is called MyTarget, then you can do this:
add_custom_command(TARGET MyTarget PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/config/ $<TARGET_FILE_DIR:MyTarget>)
This executes every time you build MyTarget and copies the contents of "/config" into the directory where the target exe/lib will end up.
As Mark Lakata points out in a comment below, replacing PRE_BUILD with POST_BUILD in the add_custom_command ensures that copying will only happen if the build succeeds.
Explanation
${CMAKE_COMMAND} is the path to CMake
-E makes CMake run commands instead of building
copy_directory is a Command-Line Tool
config is the directory (that falls under the root of the project) whose contents will be copied into the build target
$<TARGET_FILE_DIR:MyTarget> is a generator expression, described in the add_custom_command documentation.
In addition to the top answer,
To copy the directory itself instead of the contents, you can add /${FOLDER_NAME} to the end of the second parameter.
Like this:
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/config $<TARGET_FILE_DIR:${PROJECT_NAME}>/config)
CMake supports a shell type file copy. This link should be helpful for you - How to copy directory from source tree to binary tree?
Use symbolic links
CMake enables symbolic links via create_symlink:
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink
${CMAKE_SOURCE_DIR}/config $<TARGET_FILE_DIR:${PROJECT_NAME}>/config)
It ensures that when you make a change to the files in the directory, build folder would subsequently be updated.
In my project i use INSTALL to specify in CMake, what and where i move my binary with conf file. After execution of cmake, use "make install".

Creating an archive with CMake at a location that I choose

I'm trying to learn how to create archives with CMake. I wrote this piece of code:
cmake_minimum_required(VERSION 3.5.1)
project(hello)
message("Creating archieve in: " ${CMAKE_CURRENT_BINARY_DIR})
message("Source dir is: " ${CMAKE_CURRENT_SOURCE_DIR})
add_executable(hello main.cpp)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(create_tar ALL COMMAND
${CMAKE_COMMAND} -E tar "cfvz" "archieve.tgz")
add_dependencies(create_tar hello)
My project structure is like this:
I have a main folder in which I have a CMakeLists.txt, a main.cpp and a build folder. I go into build and run the cmake file above by 'cmake ..' and then make. My archive is created in the build folder but as you can see I have specified that I want it in the CMAKE_CURRENT_SOURCE_DIR which is along with the main, cmakelists and build folder not in the actual build folder.
Please explain to me why is that happening and how can I make the archive be created in the CMAKE_CURRENT_SOURCE_DIR and not CMAKE_CURRENT_BINARY_DIR. Thanks.
Turning my comment into an answer
That would be WORKING_DIRECTORY parameter of the add_custom_target() command:
add_custom_target(
create_tar ALL
COMMAND ${CMAKE_COMMAND} -E tar cfvz "archieve.tgz"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
The CMAKE_ARCHIVE_OUTPUT_DIRECTORY is for changing the output directory of add_library(... STATIC ...)` targets.
And you can either run the cmake -E tar either the correct (sub-)directory by changing the WORKING_DIRECTORY accordingly (like "${CMAKE_CURRENT_SOURCE_DIR}/Dir") or give a list of files after -- command line option (see documentation of CMake Command Line Tool Mode).

Wrap a scons build process in a Makefile

I've written a scons build chain form a little C project, but I'm afraid users won't like to be told "You should install SCons first. Besides, it's really cool!" (expecially my professor, as he's kind of from the old guard).
Is there a way I can set up a Makefile that will wrap scons, not requiring it to be installed on the target system?
After looking for such a solution some time ago, I ended up writing a Makefile for this purpose.
Because SCons also comes as a drop-in userspace package scons-local (see the download page), one can fetch in and run it. Here is a dissectioned and commented version of my Makefile, which I also uploaded as a gist.
all: get_scons
#$(SCONS_EXE)
↑ The default action depends on scons being available, and simply runs the scons command (set later in the script) (the # symbol prevents make from printing the command)
SCONS_VERSION=2.3.4
scons-local-%.tar.gz:
curl -L http://sourceforge.net/projects/scons/files/scons-local/$(SCONS_VERSION)/scons-local-$(SCONS_VERSION).tar.gz > scons-local-$(SCONS_VERSION).tar.gz
touch scons-local-$(SCONS_VERSION).tar.gz
scons-local: scons-local-$(SCONS_VERSION).tar.gz
mkdir -p scons-local
tar xzf scons-local-$(SCONS_VERSION).tar.gz --directory scons-local
touch scons-local
↑ Set up the rules for fetching the tarball and unpack it into the scons-local directory
NATIVE_SCONS=$(strip $(shell which scons 2>/dev/null))
ifeq ($(NATIVE_SCONS),)
SCONS_EXE=python2 ./scons-local/scons.py
get_scons: scons-local
#echo "Couldn't find an installation of SCons, using a local copy"
else
SCONS_EXE=$(NATIVE_SCONS)
get_scons:
#echo "Found SCons installation at $(SCONS_EXE)"
endif
↑ Look for the scons executable in the search path (using the which command): if it is available, set up the get-scons target to simply print it is available. If, instead, it is not available, create the get-scons target instructing it to depend on the scons-local target defined earlier.
clean:
$(SCONS_EXE) -c
rm -rf scons-local
rm -f scons-local-*.tar.gz
.PHONY: all clean get_scons
↑ Finally, set-up the clean target that delegates to scons and deletes the local installation afterwards. The .PHONY rule tells make that the following rules do not correspond to files being created.
At this point, one could add more proxy rules of the kind:
mytarget: get_scons
#$(SCONS_EXE) mytarget
Which will invoke scons with the corresponding target.
Hope this is useful, feel free to correct me in case there's something wrong (I'm actually not a Makefile expert, and I'm trying not to become one by using SCons instead :P )

Running a bash command via CMake

I'm trying to have CMake either run three bash commands or a bash script. However, I can't seem to get it to work.
The bash commands are:
cd ${CMAKE_SOURCE_DIR}/dependencies/library
make
cd ${CMAKE_BINARY_DIR}
Essentially, I would like CMake to build the library in that directory if it does not already exist.
Here's the CMake code I tried:
if(NOT "${CMAKE_SOURCE_DIR}/dependencies/library/lib.o")
execute_process(COMMAND cd ${CMAKE_SOURCE_DIR}/dependencies/library)
execute_process(COMMAND make)
execute_process(COMMAND cd ${CMAKE_BINARY_DIR})
endif(NOT "${CMAKE_SOURCE_DIR}/dependencies/library/lib.o")
However, it's not building anything. What am I doing wrong?
Also, while I'm here asking this: should the third command, to move to the binary folder, be included?
Thanks!
execute_process() is executed during configure time. But you want this to run at build time, thus add_custom_command() and add_custom_target() is what you're looking for.
In this special case you want to generate an output file, so you should go for add_custom_command() (both are essentially the same, but command produces one or multiple output files, while target does not.
The cmake snippet for this should look something like the following:
add_custom_command(
OUTPUT ${CMAKE_SOURCE_DIR}/dependencies/library/lib.o
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dependencies/library
COMMAND make
)
You then have to add the output file in another target as dependency, and everything should (hopefully) work as expected.
You can also add DEPENDS statements to the add_custom_command() call to rebuild the object file in case some input sources have changed.

Resources