Error in condition check inside add_custom_command of CMAKE [duplicate] - unit-testing

I want to take advantage of Ninja's "job pools" in my custom commands; something finally directly supported in cmake 3.15.0. Many/most people won't have this version, so I would like to simply ADD this support without requiring that anyone update their cmake version.
A more general question is...
"What's the best way to specify a conditional clause of a custom command …?"
add_custom_command(
OUTPUT foo
COMMAND ${CMAKE_COMMAND} -E touch foo
if("${CMAKE_VERSION}" STRGREATER_EQUAL "3.15.0") # <-- syntax error
JOB_POOL my_job_pool # <-- syntax error
endif() # <-- syntax error
VERBATIM
)
Maybe...?
if("${CMAKE_VERSION}" STRGREATER_EQUAL "3.15.0")
set(USE_JOB_POOL JOB_POOL my_job_pool)
endif()
add_custom_command(
OUTPUT foo
COMMAND ${CMAKE_COMMAND} -E touch foo
${USE_JOB_POOL}
VERBATIM
)
Or...?
add_custom_command(
OUTPUT foo
COMMAND ${CMAKE_COMMAND} -E touch foo
$<IF:$<VERSION_GREATER_EQUAL:${CMAKE_VERSION},3.15.0>:JOB_POOL my_job_pool>
VERBATIM
)

According to #Tsyvarev, my approach is reasonable. In my code, which "works", I implemented something similar to this:
set(USE_JOB_POOL 0)
if("${CMAKE_GENERATOR}" STREQUAL "Ninja" AND
"${CMAKE_VERSION}" STRGREATER_EQUAL "3.15.0")
set(USE_JOB_POOL JOB_POOL my_job_pool)
endif()
...
add_custom_command(
OUTPUT foo
COMMAND ${CMAKE_COMMAND} -E touch foo
$<${JOB_POOL}:${JOB_POOL}>
VERBATIM
)

Related

How do file paths and including files/directories with CMake work? [duplicate]

Copying directory from source tree to binary tree. For example: How to copy www to bin folder.
work
├─bin
└─src
├─doing
│ └─www
├─include
└─lib
Thanks.
Since version 2.8, the file command has a COPY sub-command:
file(COPY yourDir DESTINATION yourDestination)
Note that:
Relative input paths are evaluated with respect to the current source
directory, and a relative destination is evaluated with respect to the
current build directory
With CMake 2.8 or later, use the file(COPY ...) command.
With CMake versions below 2.8, the following macro copies files from one directory to another. If you don't want to substitute variables in the copied files, then change the configure_file #ONLY argument (for example to COPYONLY).
# Copy files from source directory to destination directory, substituting any
# variables. Create destination directory if it does not exist.
macro(configure_files srcDir destDir)
message(STATUS "Configuring directory ${destDir}")
make_directory(${destDir})
file(GLOB templateFiles RELATIVE ${srcDir} "${srcDir}/*")
foreach(templateFile ${templateFiles})
set(srcTemplatePath ${srcDir}/${templateFile})
if(NOT IS_DIRECTORY ${srcTemplatePath})
message(STATUS "Configuring file ${templateFile}")
configure_file(
${srcTemplatePath}
${destDir}/${templateFile}
#ONLY)
endif(NOT IS_DIRECTORY ${srcTemplatePath})
endforeach(templateFile)
endmacro(configure_files)
As nobody has mentioned cmake -E copy_directory as a custom target, here's what I've used:
add_custom_target(copy-runtime-files ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/runtime-files-dir ${CMAKE_BINARY_DIR}/runtime-files-dir
DEPENDS ${MY_TARGET})
The configure command will only copy files when cmake is run. Another option is to create a new target, and use the custom_command option. Here's one that I use (if you run it more than once, you'll have to modify the add_custom_target line to make it unique for each call).
macro(copy_files GLOBPAT DESTINATION)
file(GLOB COPY_FILES
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
${GLOBPAT})
add_custom_target(copy ALL
COMMENT "Copying files: ${GLOBPAT}")
foreach(FILENAME ${COPY_FILES})
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}")
set(DST "${DESTINATION}/${FILENAME}")
add_custom_command(
TARGET copy
COMMAND ${CMAKE_COMMAND} -E copy ${SRC} ${DST}
)
endforeach(FILENAME)
endmacro(copy_files)
Use execute_process and call cmake -E. If you want a deep copy, you can use the copy_directory command. Even better, you could create a symlink (if your platform supports it) with the create_symlink command. The latter can be achieved like this:
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/path/to/www
${CMAKE_BINARY_DIR}/path/to/www)
From: http://www.cmake.org/pipermail/cmake/2009-March/028299.html
Thank! That is really helpful advice to use bunch of add_custom_target and add_custom_command. I wrote the following function to use everywhere in my projects. Is also specifies the installation rule. I use it primarily to export interface header files.
#
# export file: copy it to the build tree on every build invocation and add rule for installation
#
function (cm_export_file FILE DEST)
if (NOT TARGET export-files)
add_custom_target(export-files ALL COMMENT "Exporting files into build tree")
endif (NOT TARGET export-files)
get_filename_component(FILENAME "${FILE}" NAME)
add_custom_command(TARGET export-files COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}" "${CMAKE_CURRENT_BINARY_DIR}/${DEST}/${FILENAME}")
install(FILES "${FILE}" DESTINATION "${DEST}")
endfunction (cm_export_file)
Usage looks like this:
cm_export_file("API/someHeader0.hpp" "include/API/")
cm_export_file("API/someHeader1.hpp" "include/API/")
Based on the answer from Seth Johnson; wrote for more convenience:
# Copy files
macro(resource_files files)
foreach(file ${files})
message(STATUS "Copying resource ${file}")
file(COPY ${file} DESTINATION ${Work_Directory})
endforeach()
endmacro()
# Copy directories
macro(resource_dirs dirs)
foreach(dir ${dirs})
# Replace / at the end of the path (copy dir content VS copy dir)
string(REGEX REPLACE "/+$" "" dirclean "${dir}")
message(STATUS "Copying resource ${dirclean}")
file(COPY ${dirclean} DESTINATION ${Work_Directory})
endforeach()
endmacro()

FLEX/BISON generate location.hh, position.hh, stack.hh in different folder

I have folder structure like this
include/
src/
| parser.yy
| scanner.ll
and in the src/CMakeLists.txt:
SET(BisonOutput ${CMAKE_SOURCE_DIR}/src/_parser.cpp)
IF(BISON_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${BisonOutput}
COMMAND ${BISON_EXECUTABLE}
--defines=${CMAKE_SOURCE_DIR}/include/_parser.hpp
--output=${BisonOutput}
${CMAKE_SOURCE_DIR}/src/parser.yy
COMMENT "Generating parser"
)
ENDIF()
SET(FlexOutput ${CMAKE_SOURCE_DIR}/src/_scanner.cpp)
IF(FLEX_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${FlexOutput}
COMMAND ${FLEX_EXECUTABLE}
--outfile=${FlexOutput}
${CMAKE_SOURCE_DIR}/src/scanner.ll
COMMENT "Generating scanner"
)
ENDIF()
However the files locations.hh, position.hh and stack.hh are generated inside the src directory. Is it possible to somehow specify that i want these files generated inside the include directory?
I am using Bison 3.0.4 and Flex 2.6.4
I'm not sure if Bison/Flex allows you to generate them in a separate location, but you can use CMake to copy them to the include directory once they are generated. Add another add_custom_command call with PRE_BUILD to ensure they are copied before building your target:
ADD_CUSTOM_COMMAND(
TARGET MyTarget PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/locations.hh ${CMAKE_SOURCE_DIR}/include
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/position.hh ${CMAKE_SOURCE_DIR}/include
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/stack.hh ${CMAKE_SOURCE_DIR}/include
)

CMake - Alternative to generator expression for build output directory?

I have a cmake build system gone wild. Before supporting IDEs, everything was ok.
I need to copy files (shaders in this case) to the build directory. They need to be copied when they've changed, regardless of whether the main target is built or not.
I had success before, as I could add a custom command with ${CMAKE_CURRENT_BINARY_DIR}, add dependencies later and everything was fine.
The problem is, when using a generator expression for the command output, it creates a dependency from my custom command to the main target. This means adding a dependency backwards (which is needed to trigger the copy) throws an error because of cyclic dependencies.
This is what I have so far, which doesn't work because the custom target (thus custom command) is not triggered when the main target doesn't need rebuilding.
set(SHADER_IN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/shaders)
file(GLOB_RECURSE SHADERS "${SHADER_IN_DIR}/*.glsl")
add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${PROJECT_NAME}>/shaders/)
set(STAMP_DIR ${CMAKE_CURRENT_BINARY_DIR}/.stamps)
add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${STAMP_DIR})
set(STAMP_FILES "")
foreach(SHADER ${SHADERS})
get_filename_component(SHADER_FILENAME ${SHADER} NAME)
set(STAMP_FILE ${STAMP_DIR}/${SHADER_FILENAME}.stamp)
add_custom_command(
OUTPUT ${STAMP_FILE}
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_FILE}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SHADER} $<TARGET_FILE_DIR:${PROJECT_NAME}>/shaders/${SHADER_FILENAME}
DEPENDS ${SHADER}
)
list(APPEND STAMP_FILES ${STAMP_FILE})
endforeach()
add_custom_target(Shaders
SOURCES ${SHADERS}
DEPENDS ${STAMP_FILES})
# Need to add dependency here! But I can't :(
So, is there any other way to get what output directory will be used in an IDE? All "solutions" I've read to force building a target have failed (they pretty much all rely on add_dependencies).
Thank you for saving my sanity.
In the end, instead of trying to find out where the IDE is going to output the binary, I forced output in a predictable bin/ dir.
set(BINARY_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BINARY_OUT_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BINARY_OUT_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BINARY_OUT_DIR})
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${BINARY_OUT_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${BINARY_OUT_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${BINARY_OUT_DIR})
endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)

Clion: auto documenting functions, classes

Is there any shortcut or something like this to add, e.g. documentation of a function or class (similar to "///" in Visual Studio and C#)?
Thanks!
You can use /** <Enter>.
I have found a way to do it. I personally use Doxygen for documentation.
CLion plans to integrate it.
You have to write all of it at this time. But when you have documented your code, you can build it with CMake (and then it appears in your build target on CLion).
Here's an example:
cmake_minimum_required(VERSION 3.2)
project(doxygen_test)
find_package(Doxygen)
set(SOURCE_FILES main.cc)
if(DOXYGEN_FOUND)
set(DOXYGEN_INPUT ${SOURCE_FILES})
set(DOXYGEN_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
add_custom_command(
OUTPUT ${DOXYGEN_OUTPUT}
COMMAND ${CMAKE_COMMAND} -E echo_append "Building API Documentation..."
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_INPUT}
COMMAND ${CMAKE_COMMAND} -E echo "Done."
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${DOXYGEN_INPUT}
)
add_custom_target(apidoc ALL DEPENDS ${DOXYGEN_OUTPUT})
add_custom_target(apidoc_forced
COMMAND ${CMAKE_COMMAND} -E echo_append "Building API Documentation..."
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_INPUT}
COMMAND ${CMAKE_COMMAND} -E echo "Done."
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endif(DOXYGEN_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_executable(doxygen_test ${SOURCE_FILES})
Sources:
http://www.cmake.org/pipermail/cmake/2007-February/012796.html
https://www.tty1.net/blog/2014/cmake-doxygen_en.html
https://mementocodex.wordpress.com/2013/01/19/how-to-generate-code-documentation-with-doxygen-and-cmake-a-slightly-improved-approach/
https://majewsky.wordpress.com/2010/08/14/tip-of-the-day-cmake-and-doxygen/
Starting from 2016.2 EAP CLion supports Doxygen (http://blog.jetbrains.com/clion/2016/05/keep-your-code-documented/). Start with typing “/**” or “/*!” and then press Enter. In case your function has parameters, returns a value or throws an exception, you’ll get a stub to fill with the documentation text

CMake and Flex/Bison

I am converting my build system from configure/make to a cmake system
The system has some autogenerated files, from bison/flex. The original makefile commands are:
bison --defines=tokens.h --output=parser.cpp parser.y
flex --outfile=scanner.cpp scanner.l
I came across this ancient link which seems to explain how to do it, but when i run cmake with the following custom commands, nothing appears to happen (no error messages, no file generation)
FIND_PACKAGE(BISON REQUIRED)
IF(BISON_FOUND)
ADD_CUSTOM_COMMAND(
SOURCE ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.y
COMMAND ${BISON_EXECUTABLE}
ARGS --defines=${CMAKE_SOURCE_DIR}/src/rcdgen/tokens.h
-o ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.cpp
${CMAKE_SOURCE_DIR}/src/rcdgen/parser.y
COMMENT "Generating parser.cpp"
OUTPUT ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.cpp
)
ENDIF(BISON_FOUND)
FIND_PACKAGE(FLEX REQUIRED)
IF(FLEX_FOUND)
ADD_CUSTOM_COMMAND(
SOURCE ${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.l
COMMAND ${FLEX_EXECUTABLE}
ARGS -o${CMAKE_SOURCE_DIR}/src/rcdgen/parser.cpp
${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.l
COMMENT "Generating scanner.cpp"
OUTPUT ${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.cpp
)
ENDIF(FLEX_FOUND)
I am new to cmake, so it's a bit confusing to me. Does anyone have any idea what a working custom_command would be?
The new hotness for bison usage is actually documented in FindBison So for a simple parser project:
find_package(BISON)
BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp
DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/parser.h)
add_executable(Foo main.cpp ${BISON_MyParser_OUTPUTS})
is what you'd do. Likewise for Flex.
The format of your add_custom_commands is not quite right, but they appear to be almost correct. There are two versions of add_custom_command, and the one you want is the one which produces an output file (the parts inside square brackets are optional):
add_custom_command(OUTPUT output1 [output2 ...]
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[MAIN_DEPENDENCY depend]
[DEPENDS [depends...]]
[IMPLICIT_DEPENDS <lang1> depend1
[<lang2> depend2] ...]
[WORKING_DIRECTORY dir]
[COMMENT comment] [VERBATIM] [APPEND])
The idea is that the custom command only executes if the file specified as the OUTPUT of this command is used as an input elsewhere in the same CMakeLists.txt (e.g. in an add_library or add_executable call).
The custom command therefore will only run at build time (i.e. when you run make), not at configure time (when you run CMake), and only if you're building a target which directly or indirectly needs the OUTPUT file.
To fix your commands, I think the following should work (untested):
FIND_PACKAGE(BISON REQUIRED)
SET(BisonOutput ${CMAKE_SOURCE_DIR}/src/rcdgen/parser.cpp)
IF(BISON_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${BisonOutput}
COMMAND ${BISON_EXECUTABLE}
--defines=${CMAKE_SOURCE_DIR}/src/rcdgen/tokens.h
--output=${BisonOutput}
${CMAKE_SOURCE_DIR}/src/rcdgen/parser.y
COMMENT "Generating parser.cpp"
)
ENDIF()
FIND_PACKAGE(FLEX REQUIRED)
SET(FlexOutput ${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.cpp)
IF(FLEX_FOUND)
ADD_CUSTOM_COMMAND(
OUTPUT ${FlexOutput}
COMMAND ${FLEX_EXECUTABLE}
--outfile=${FlexOutput}
${CMAKE_SOURCE_DIR}/src/rcdgen/scanner.l
COMMENT "Generating scanner.cpp"
)
ENDIF()
ADD_LIBRARY(MyLib ${BisonOutput} ${FlexOutput})