How do I use ExternalProject_Add to get a simple make invocation? - cmake

I need ExternalProject_Add to invoke just one command for an external project whose makefile does all the needed steps. I need to have that command be "make WITH_OPTION1=no WITH_OPTION2=no" in the directory at the top of the external project's source tree. This is one of a few dozen external projects we use. Most of them fit the model of 'configure; make; make install' but a good third don't and this is one that I thought would be easy.
If I try to have the make command invoked like this:
ExternalProject_Add(build-example
PREFIX "${CMAKE_CURRENT_BINARY_DIR}/example"
DEPENDS ""
SOURCE_DIR "${PROJECT_TOPDIR}/External/example"
CONFIGURE_COMMAND ""
BUILD_COMMAND COMMAND make WITH_OPTION1=no WITH_OPTION2=no
INSTALL_COMMAND "")
The resulting make step is done from the wrong directory and therefore the Makefile is not found.
If I add a -C option to the make command it seems to use the right directory, but it ignores the WITH_OPTION stuff. That doesn't compile properly, because those features use things I don't want to provide, and if it did work, I still don't want those features.
If I then add quotes around the entire desired make command, it goes wrong. Apparently the command is passed to 'sh' in such a way that sh fails.
If I use a mechanism to pass the command into a 'configure-file' step and invoke that file from the BUILD_COMMAND, then CMake actually tries to use a broken CMakeLists.txt file that's in the external project, and I wonder what makes CMake think that it should do so.
I just want to invoke the makefile properly, using CMake to organize that build within the dozens of other builds that have to be done to build the complete project.

Related

cmake third party project step

We are using a vendor code as third party project in our source code. The Vendor code uses Makefile, for which we wrote new CMake add_custom_target for vendor source code.
To copy library from vendor specific build/lib dir to Our CMAKE binary/library dir, I coded Step to copy all the libs as
ExternalProject_Add_Step(CopyStep)
However I see that whenever I build, CopyStep is executed all the time. Is there any way to control the CopyStep to exec only if there is change in library (something similar as Make, whenever there is not code change, source code is not rebuilt).
Let me know if there is any other way I could do copy etc.
For make an ExternalProject's step to be re-executed only when some file(s) are changed, add DEPENDS option to it:
ExternalProject_Add_Step(extLibrary CopyStep
COMMAND cp <BINARY_DIR>/lib/libext.a <...>
DEPENDS <BINARY_DIR>/lib/libext.a
)
Alternatively (e.g. if you don't want to list all files you depends on), you may make the step to be a part of the build step. For that, modify ExternalProject_Add by adding appropriate command:
ExternalProject_Add(extLibrary
...
BUILD_COMMAND make # Need to explicitely specify build command.
COMMAND cp -r <BINARY_DIR>/lib <...> # Additional action for the build step
)

CMake Windows Command Path Elegant Solution

I'm using an external library without CMake and building this library is a little tedious so I decided to use external scripts for that purpose:
one for configuration which runs the projects own build system, and
one for the actual build which simply runs MSBuild on the generated VS solution.
I want to copy the script to the directory where the archive is unpacked to, and execute it afterwards.
Current CMake File
file(TO_NATIVE_PATH ${CMAKE_CURRENT_LIST_DIR}/scripts/configure_OpenDDS_template.bat CONFIGURE_SCRIPT)
file(TO_NATIVE_PATH ${CMAKE_CURRENT_LIST_DIR}/scripts/build_OpenDDS_template.bat BUILD_SCRIPT)
ExternalProject_Add(OpenDDS
PREFIX OpenDDS
URL ${CLD}/OpenDDS-DDS-3.12.1.zip
CONFIGURE_COMMAND cmd /C "cd ../OpenDDS && copy ${CONFIGURE_SCRIPT} configure_OpenDDS.bat && call configure_OpenDDS.bat"
BUILD_COMMAND copy ${BUILD_SCRIPT} ${BUILD_COPY}
INSTALL_COMMAND "")
My question is whether there is a better or shorter or more elegant solution to have the absolute paths used in CONFIGURE_COMMAND and BUILD_COMMAND in correct Windows form than to use the conversion function from file. My current solution is acceptable for small projects in my opinion but you really want CMake to handle the path conversion for you without the excessive use of additional variables. I mean, CMake already handles the OS specific configuration of absolute paths for normal use but not within functions that execute pure OS commands like execute_process.

How to configure external cmake libraries?

What I wanted to do is call
add_subdirectory(ext/oglplus)
and be done with it. Unfortunately it is not that simple. There is a huge buildscript which detects various opengl settings. So I tried the following
ExternalProject_Add(liboglplus
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/oglplus
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/ext/oglplus/configure.py --use-glew
BUILD_COMMAND ${MAKE})
The problem that I have is don't really want to build it like that. It also doesn't build correctly because for some reason it wants to install the library and because there is no install target it will abort the compilation.
But the build script is calling cmake under the hood.
So what I want to do is to tell cmake to use "cofigure.py" instead of "cmake .." and then use it like any other cmake library.
Is this possible?
I used to call Linux Kernel KBuild from CMake using
ADD_CUSTOM_COMMAND() and ADD_CUSTOM_TARGET()
This way you can run arbitrary commands (like your config.py) and use the output.
First setup the command with all command-line options as CMake-variables, in tou case this would be calling the config.py script ${CMAKE_CURRENT_SOURCE_DIR}/ext/oglplus/.
Instead of encoding the Path to your script in the command (adding ext/oglplus) I think it may be better adding WORKING_DIRECTORY to the custom command:
add_custom_command
SET(KBUILD_CMD ${CMAKE_MAKE_PROGRAM}
-C ${KERNEL_BUILD_DIR}
CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH}
EXTRA_CFLAGS=${KBUILD_EXTRA_CFLAGS}
INSTALL_MOD_PATH=${INSTALL_MOD_PATH}
M=${CMAKE_CURRENT_SOURCE_DIR}
KBUILD_EXTRA_SYMBOLS=${depends_module_ksyms}
)
Add a custom command that calls your build-script and creates a file in the CMAKE_CURRENT_BINARY_DIRECTORY (note the second COMMAND to touch a file)
ADD_CUSTOM_COMMAND(
OUTPUT ${module_name}.built
COMMAND ${KBUILD_CMD} modules
COMMAND cmake -E touch ${module_name}.built
COMMENT "Kernel make modules ${module_name}"
VERBATIM
)
Add a custom target, its always out of date, but if you want it to be called automatically add ALL otherwise you have to explicityly call make module_build, I guess this is what you want.
ADD_CUSTOM_TARGET("${module_name}_build" ALL
DEPENDS ${depends_module_ksyms}
${CMAKE_CURRENT_BINARY_DIR}/${module_name}.built
COMMENT "Building Kernel Module ${module_name}"
)

How do I redefine target "clean"?

My CMmake build script includes an "external native makefile". Target-all has a dependency with an "external make". This dependency is made by CMake.
CMakeLists.txt
|____( add_custom_target )_____ GNU make file
But Target-clean doesn't have a dependency with an "external make clean". I can't make dependency clean - external make clean. I can make a new custom-target (for example, newClean), and it has a dependency with "clean" and "external make clean". But "clean" and "newClean" exist. It may be the confusion.
How do I resolve this problem?
There are three possible solutions I can think of:
Make sure all output files from custom commands are listed in the OUTPUT line. They will then be removed as part of clean (this behaviour is mentioned with the CLEAN_NO_CUSTOM property).
Add extra files to the ADDITIONAL_MAKE_CLEAN_FILES directory property.
Create a new custom command which calls the normal clean target and your other make file. Example:
add_custom_target(really-clean
COMMAND "$(CMAKE)" --build "${CMAKE_BINARY_DIR}" clean
COMMAND cd "${CMAKE_BINARY_DIR}/otherproject" && make clean
)

CMake Configure File Build Rule

I'm using CMake for my build system and in the project, we will have a bunch of configuration files. Some of them will just need to be copied over, some will need to be modified per computer. I'm currently using CMake's "configure_file" command to copy/replace parts of the file. This works great, and I love how I can use any variable from CMake in the configure routine.
But if you change the original file, CMake will not pick this up and you have to rerun cmake for it to configure the directory. When I run "make", I want it to pick up that I've changed the file and rerun configure.
It will also reconfigure files always, even if the file it is overwriting is newer. I want it to act like a custom target.
I think I can do this with add_custom_command, but I don't think I can run a CMake command from add_custom_command. So is there anyway to duplicate the behaviour that configure_file does in CMake?
I recently upgraded to CMake 2.8. It seems like it automatically has the exact behavior I wanted.
I do not think this has an easy answer. I see two options:
To trigger a re-run of cmake if an input changes, you might be able to make your input file depend on CMakeLists.txt.
To run a cmake command as part of and add_custom_command, there is the variable ${CMAKE_COMMAND}, which will give you the path to the running cmake. You could, as part of the configure step, generate a fragment of CMake code (that calls configure_file) that is invoked using the -P option. Either pass substitutions on the command line using -D, or write them to the CMake fragment.