Running a custom command in Cmake - makefile

I am very new to Cmake and need to generate some files at compile time. once generated i need to compile and link the files. I ve created the cmake makefile to compile the already generated files like
cmake_minimum_required(VERSION 2.6)
project(demo)
set(CMAKE_CXX_FLAGS "-DWITH_COOKIES")
add_library(soapC soapC.cpp soapVimBindingProxy.cpp)
add_library(stdsoap2 /home/abdullah/installs/gsoap-shah_edits/gsoap/stdsoap2.cpp)
add_executable(demo test_file.cc test_app.cc)
target_link_libraries(demo soapC stdsoap2 gsoap++)
This successfully compiles the project. However the files soapC.cpp soapVimBindingProxy.cpp needs to be generated first. And I want to generate these files at runtime using the gsoap tool.
following is the command that needs to be run to generate the header file
wsdl2h -o outfile.h infile.wsdl
This takes an input wsdl file and creates a corresponding outfile.h.
Now I tried doing this in cmake like this
cmake_minimum_required(VERSION 2.6)
add_custom_command(
OUTPUT vsphere.h
COMMAND wsdl2h -o vsphere.h vim25/vim.wsdl
)
But something goes wrong here. No error pops up but no file is created either. Am I missing something ? All help much appreciated.
Thanks.

You've just created a command for producing your header file, so CMake knows just where to get vsphere.h from. I'd recommend using OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vsphere.h in the add_custom_command() call.
Now you need to create a target:
add_custom_target(vsphere_header ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vsphere.h)
Finally, make your soapC target depend on it:
add_dependencies(soapC vsphere_header)
Be sure to place add_dependencies() call after soapC target definition.

Thanks arrododger and TobyHijzen for your lighting on this issue.
I use add_custom_command with main_dependency feature for solution for this issue. Following is my CMakeLists.txt for famous calc example of gsoap tutorial.
cmake_minimum_required(VERSION 2.8)
# Proejct name
PROJECT(Calculator)
# Make verbose level on/off
SET(CMAKE_VERBOSE_MAKEFILE ON)
# Varialbes used in cmake
SET(TARGET calc_client)
SET(GSOAP_STATIC_LIB gsoap)
SET(CLIENT_SRC calc_client.c)
SET(WSDL2H_EXEC wsdl2h)
SET(WSDL2H_IN http://www.genivia.com/calc.wsdl)
#SET(WSDL2H_IN calc.wsdl)
SET(WSDL2H_OUT calc.h)
SET(WSDL2H_OPT -c -o)
# command for generating stub and xml serializer code
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${WSDL2H_OUT}
COMMAND ${WSDL2H_EXEC} -c -ttypemap.dat -o ${WSDL2H_OUT} ${WSDL2H_IN}
COMMENT "=================== Generating ${WSDL2H_OUT} gSOAP Header file ..."
)
SET(SOAPCPP2_EXEC soapcpp2)
SET(STUB soapClient.c soapC.c)
SET(SOAPCPP2_OUT
${STUB}
calc.add.req.xml
calc.add.res.xml
calc.sub.req.xml
calc.sub.res.xml
calc.mul.req.xml
calc.mul.res.xml
calc.div.res.xml
calc.div.req.xml
calc.pow.res.xml
calc.pow.req.xml
calc.nsmap
soapH.c
soapH.h
soapStub.h
soapClientLib.c
)
# command for generating stub and xml serializer code
ADD_CUSTOM_COMMAND(
OUTPUT ${STUB}
COMMAND ${SOAPCPP2_EXEC} -c -C ${WSDL2H_OUT}
MAIN_DEPENDENCY ${WSDL2H_OUT}
COMMENT "=================== Generating ${STUB} outputs ..."
)
# Exutable files and dependents
ADD_EXECUTABLE(${TARGET} ${CLIENT_SRC} ${STUB})
# libraries for taget : for gcc -l option
TARGET_LINK_LIBRARIES(${TARGET} ${GSOAP_STATIC_LIB})
# Compiler options
ADD_DEFINITIONS(-Wall -O2 -s)

Related

cmake 'add_custom_command' to pre-process header files?

i'm working on a project requiring cmake. i'd like to add some custom rules to my makefile, but can't quite get my head around how to do it.
both c source files and header files are in the same directory. also in this same directory are a number of .def files, which are the sources for some of the header files #included in the source during compilation.
if i were to do this in a makefile, i'd use a simple rule like
.SUFFIXES: .def
.def.h:
$(PREPROC) $< > $#
how can i do this with cmake ??
i've tried various permutations of the following, both with and without cmake working directory specifications :
add_custom_command(
OUTPUT vvr_const.h
PRE_BUILD
COMMAND preproc vvr_const.def > vvr_const.h
DEPENDS vvr_const.def
)
add_custom_target(vvr_const.h DEPENDS vvr_const.def)
but the header file isn't generated by the time the c source file is compiled, so the compile fails. i've also tried a variation where i replace the last line above with
set_property(SOURCE main.c APPEND PROPERTY OBJECT_DEPENDS vvr_const.h)
in this case, the header file is correctly generated in advance, but make can't find it, and complains that there's no rule to make the target .h.
ideally this would be a general rule, like the make rule above, but i'm not opposed to making a separate rule for each of the .def files if that's what it takes.
cheers.
There are 2 problems with the add_custom_command approach you present:
You did not specify a working directory; by default the command is run in the build directory, not in the source directory.
You rely on shell functionality here (the redirect to a file). Even though this probably still works. You should go with an approach that does not rely on the shell.
To solve issues 1 and 2 I recommend creating a seperate cmake script file receiving the absolute paths to input and output files and using those in the custom command. This allows you to use execute_process to specify the file to write without relying on the platform.
preprocess_def.cmake
# preprocess def file
# parameters INPUT_FILE and OUTPUT_FILE denote the file to use as source
# and the file to write the results to respectively
# use preproc tool to get data to write to the output file
execute_process(COMMAND preproc "${INPUT_FILE}"
RESULT_VARIABLE _EXIT_CODE
OUTPUT_FILE "${OUTPUT_FILE}")
if (_EXIT_CODE)
message(FATAL_ERROR "An error occured when preprocessing the file ${INPUT_FILE}")
endif()
CMakeLists.txt
set(_INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.def")
set(_OUTPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.h")
# not necessary to use build event here, if we mark the output file as generated
add_custom_command(OUTPUT "${_OUTPUT_FILE}"
COMMAND "${CMAKE_BUILD_TOOL}" -D "OUPUT_FILE=${_OUTPUT_FILE}" -D "INPUT_FILE=${_INPUT_FILE}" -P "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_def.cmake"
DEPENDS "${_INPUT_FILE}")
add_executable(my_target vvr_const.h ...)
set_source_files_properties(vvr_const.h PROPERTIES GENERATED 1)
Documentation from cmake:
PRE_BUILD
On Visual Studio Generators, run before any other rules are executed within the target. On other generators, run just before PRE_LINK commands.
So possibly your command is just running too late.

Cmake doesn't recognize custom command as valid source

I have a problem modifying existing CMake based build-system. All I want to do is add different build rule for some of .c files. For the sake of this problem, I will focus on only one file.
The simplified directories tree looks like this
Project:
./src
- file_of_interest.c
- CmakeFiles.txt
other_files.c
CmakeFiles.txt
So in order to compile file_of_interest.c in a different way I do:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/file_of_interest.s
COMMAND xt-xcc -S ${CMAKE_CURRENT_SOURCE_DIR}/file_of_interest.c
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/file.c
COMMENT "Generating file_of_interest.s"
)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/file_of_interest.c.o
COMMAND xt-xcc ${CMAKE_CURRENT_BINARY_DIR}/file_of_interest.s -o file_of_interest.c.o -c
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/file_of_interest.s
COMMENT "Generating file_of_interest.c.o"
)
message(" ${CMAKE_CURRENT_BINARY_DIR} \n ${CMAKE_CURRENT_SOURCE_DIR}")
target_sources(target_name PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/file_of_interest.c.o)
As you can see I used CMake's message() to print paths to be sure all is set up properly. It should work, but it doesn't! I expect CMake to register file_of_interest.c.o as source of target_name (and this is probably working), then "tie" it with my custom command which produces OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/file_of_interest.c.o and then to tie again ${CMAKE_CURRENT_BINARY_DIR}/file_of_interest.c.o with OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/file_of_interest.s and this certainly doesn't happen as CMake shows error message saying CMake Error at CMakeLists.txt:170 (add_executable): Cannot find source file: path/file_of_interest.c.o
The path is OK. So the question is why does CMake cannot recognize recipes for that file?
It seems that you create an executable (call add_executable) in the top-level CMakeLists.txt, but add_custom_command are called from the subdirectory (src/CMakeLists.txt).
This doesn't work: when CMake processes add_executable and searches for the commands generating its sources, it sees only add_custom_commands created in the same CMakeLists.txt.
From the add_custom_command documentation:
A target created in the same directory (CMakeLists.txt file) that specifies any output of the custom command as a source file is given a rule to generate the file using the command at build time.
It is unrelated that target_sources is called from the same directory as add_custom_command: the target is created by add_executable command, and target_sources just modifies its properties.

How to test the static_assert in my library with cmake?

in my library code I have a bunch of static_asserts. I want to test if they fire under the expected conditions.
I would like to write a range of test files and
ensure that they fail to compile
check the output of the compilation attempt for the expected message from the static assert
Does anyone know how to do that with cmake?
AFAICT, try_compile is not the answer, because it is executed while running cmake. I need these checks to be executed during make.
You could set up a "nested" project for these tests, configure it as part of your CMake run and then build it using cmake --build; something like this:
Your normal CMakeLists.txt:
# ...
execute_process(
COMMAND ${CMAKE_COMMAND} path/to/test/project
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TestProject
)
add_test(
NAME StaticAsserts
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TestProject
COMMAND ${CMAKE_COMMAND} --build .
)
# ...
Of course, the test command could actually be a wrapper script running cmake --build internally and processing its output.
As an alternative, you could move the configuration of the nested project into the test as well, perhaps using CTest to drive the configure & build.
After several more experiments, this is what I am doing now:
add_executable(
fail_test
EXCLUDE_FROM_ALL
fail_test.cpp
)
add_custom_command(OUTPUT fail_test.out
COMMAND ${CMAKE_MAKE_PROGRAM} fail_test > ${CMAKE_CURRENT_BINARY_DIR}/fail_test.out 2>&1 || true
COMMAND grep "int i = row.alpha" ${CMAKE_CURRENT_BINARY_DIR}/fail_test.out > /dev/null
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fail_test.cpp
COMMENT "fail_test"
)
add_custom_target(test_constraints DEPENDS fail_test.out COMMAND true)
This is what it does:
Create a target for compiling the code that is supposed to fail at compile time. Exclude this target from the default build so that it does not create a mess.
Add a custom command that calls make for this fail-target, pipes the compiler spew into a file, ignores the result code and then greps for the expected compiler message that indicates that the compilation failed due to the expected reason.
Make the custom command depend on the source file, so that the compilation is tested again when the source file is ended.
Add the custom command as dependency to a custom target.
Of course, for more tests, steps 1, 2 and 4 would go into a function.
So now I can call
make test_constraints
to test if the stuff I want to fail compiling actually does so. And if something does not fail as expected, I can even call
make fail_test
to tune the test or its basis until it fails correctly.
For platform independence, the custom command will probably have to be adjusted. Suggestions welcome.
Add this to your CMakeLists.txt:
include(CTest)
# Test that code is NOT able to compile
function(TestStaticCheck TEST_NAME)
add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_NAME}.cpp)
target_link_libraries(${TEST_NAME} MyLibrary)
add_test(NAME ${TEST_NAME}
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${TEST_NAME}
)
set_tests_properties(${TEST_NAME} PROPERTIES WILL_FAIL TRUE)
endfunction()
TestStaticCheck(TestFoo)
Then put this in TestFoo.cpp in the same directory as your CMakeLists.txt:
int main()
{
// Code that should NOT compile
}

Include mpi to make file

I am trying to include MPI compiler to my makefile. The makefile is already prepared such that I only need to include the address of the MPI compiler in a a separate env file. However doing so does not work. I can get the cpp file to run manually by typing:
mpicxx Demo_00.cpp -o aprogram
./aprogram
I test where the mpi compiler is located using:
which mpicxx
/usr/bin/mpicxx
In the env file the corresponding line is:
MPICXX=/usr/bin/mpicxx
However, when I try to 'make' he cpp file I get the following error:
make Demo_00
g++ Demo_00.cpp -o Demo_00
Demo_00.cpp:2:17: fatal error: mpi.h: No such file or directory
compilation terminated.
make: *** [Demo_00] Error 1
The cpp file is in the same folder as the env file and the makefile.
I am not quite sure how to identify the error.
Thank you for your help,
Tartaglia
If you want to change the name of the C++ compiler, you have to change the variable CXX. That's the default variable make uses when it wants to compile C++ code.
This line in your log file:
g++ Demo_00.cpp -o Demo_00
says that you are using g++ compiler instead of mpixx.
Usually in makefiles compiler definition is at the beginnig of the file and looks like this:
CC=g++
just change it to mpixx
CC=mpixx
Thank you all for your responses, I took a closer look into the makefile I thought I was using and it turns out, as you have already suggested, I was not using it at all. The makefile was only able to execute one specific cpp file with one specific name. So whenever I typed in make *.cpp I was using the standard make as you already pointed out.
Thanks again for your help.

How to compile to a different location

I am very new to using the a command line to compile code so I was wondering how to make the D compiler compile all its code to a certain location instead of where the source is. As in I want the final .exe and the obj code all in a particular directory. I know you can use the -of command but I currently don't know the format for using it.
Currently I have:
C:\D\dmd2\windows\bin\dmd.exe -w C:\Users\Kyle\Desktop\D\Test.d C:\Users\Kyle\Desktop\D\src\MyMod.d
What do I need to add?
Use -offilename switch. Example:
dmd factorial.d -offilename "d:\test_name.exe"
or short version:
dmd factorial.d "-ofd:\test_name.exe"
Note: The double quotes are necessary if your path contains spaces.
Note2: In short version you can skip .exe, but don't do it in full version, because compiler would search for source file with that name.
I know people do not like RTFM answers, but the following is kind of RTFM answer that answers your question:
Execute dmd --help and you will get the following:
DMD32 D Compiler v2.061
Copyright (c) 1999-2012 by Digital Mars written by Walter Bright
Documentation: http://www.dlang.org/index.html
Usage:
dmd files.d ... { -switch }
files.d D source files
#cmdfile read arguments from cmdfile
-c do not link
-cov do code coverage analysis
-D generate documentation
-Dddocdir write documentation file to docdir directory
-Dffilename write documentation file to filename
-d silently allow deprecated features
-dw show use of deprecated features as warnings (default)
-de show use of deprecated features as errors (halt compilation)
-debug compile in debug code
-debug=level compile in debug code <= level
-debug=ident compile in debug code identified by ident
-debuglib=name set symbolic debug library to name
-defaultlib=name set default library to name
-deps=filename write module dependencies to filename
-g add symbolic debug info
-gc add symbolic debug info, pretend to be C
-gs always emit stack frame
-H generate 'header' file
-Hddirectory write 'header' file to directory
-Hffilename write 'header' file to filename
--help print help
-Ipath where to look for imports
-ignore ignore unsupported pragmas
-inline do function inlining
-Jpath where to look for string imports
-Llinkerflag pass linkerflag to link
-lib generate library rather than object files
-man open web browser on manual page
-map generate linker .map file
-noboundscheck turns off array bounds checking for all functions
-O optimize
-o- do not write object file
-odobjdir write object & library files to directory objdir
-offilename name output file to filename <---- [1]
-op do not strip paths from source file
-profile profile runtime performance of generated code
-property enforce property syntax
-quiet suppress unnecessary messages
-release compile release version
-run srcfile args... run resulting program, passing args
-unittest compile in unit tests
-v verbose
-version=level compile in version code >= level
-version=ident compile in version code identified by ident
-vtls list all variables going into thread local storage
-w warnings as errors (compilation will halt)
-wi warnings as messages (compilation will continue)
-X generate JSON file
-Xffilename write JSON file to filename
I marked the line that answers your question with [1] and an arrow.
Have a look at the -of, -od and -op switches. It's hard to be more specific without knowing what exactly you mean by "compile all its code to a certain location".

Resources