CMake's find_library() ignoring any specified path - cmake

I'm trying to find a library that's built alongside a subsection of a project, the library is built with a "externalproject_add" call and builds successfully. It puts a library (.so.2) in a subdirectory within itself
I've specified a directory with PATHS (I've also tried HINTS, and adding the trailing /lib as part of the path), and am using debug mode to get CMake to print the information as it tries to find this library.
find_library(METADX1_LIB NAMES libmdx1host.so.2 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/meta-dx1/sdk/builds/debug/ PATH_SUFFIXES lib NO_DEFAULT_PATH)
I'm very clear here about the path I have my library in. I've also tried suspending the leading lib, trailing *.so.2, etc to no avail, it looks like CMake isn't even trying:
CMake Debug Log at Sub-project/CMakeLists.txt:187 (find_library):
find_library called with the following settings:
VAR: METADX1_LIB
NAMES: "libmdx1host.so.2"
Documentation: Path to a library.
Framework
Only Search Frameworks: 0
Search Frameworks Last: 0
Search Frameworks First: 0
AppBundle
Only Search AppBundle: 0
Search AppBundle Last: 0
Search AppBundle First: 0
NO_DEFAULT_PATH Enabled
find_library considered the following locations:
The item was not found.
If I supply /usr/bin as a path to PATHS as an experiment, CMake appends that to some output directory somewhere deep within the project, even though it's an absolute path.
I'm finding CMake to be extremely counterintuitive. I've given it an exact location where there is a library, how can I get it to actually look in that directory?
Edit
IT seems find_library is modifying the paths for some reason:
CMake Debug Log at TMX-4400/CMakeLists.txt:190 (find_library):
find_library(METADX1_LIB) removed original suffix
/home/brydon/embedded/product/../../tools/optelinux/bdrt/output/rootfs.tmx4400/staging/home/brydon/embedded/product/TMX-4400/meta-dx1/sdk/builds/debug/
from PATH_SUFFIXES while adding architecture paths for suffix '64'

I'm not sure what else is going on in your CMakeLists.txt, but I can't replicate your failure with the code and paths you provided.
First, I created a CMakeLists.txt file with the following contents:
cmake_minimum_required(VERSION 3.23)
project(test)
find_library(
METADX1_LIB
NAMES libmdx1host.so.2
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/meta-dx1/sdk/builds/debug/
PATH_SUFFIXES lib
NO_DEFAULT_PATH
)
message(STATUS "METADX1_LIB = ${METADX1_LIB}")
Then, I replicated the directory layout described in your post and created an empty library file with the appropriate name:
$ mkdir -p meta-dx1/sdk/builds/debug
$ touch meta-dx1/sdk/builds/debug/libmdx1host.so.2
$ tree
.
├── CMakeLists.txt
└── meta-dx1
└── sdk
└── builds
└── debug
└── libmdx1host.so.2
Finally, I configured the build using Ninja and the --debug-find-var option of CMake 3.23 to see how the search proceeded.
$ cmake -G Ninja -S . -B build --debug-find-var=METADX1_LIB
Running with debug output on for the variable(s) METADX1_LIB.
-- The C compiler identification is GNU 11.3.0
-- The CXX compiler identification is GNU 11.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Debug Log at CMakeLists.txt:4 (find_library):
find_library called with the following settings:
VAR: METADX1_LIB
NAMES: "libmdx1host.so.2"
Documentation: Path to a library.
Framework
Only Search Frameworks: 0
Search Frameworks Last: 0
Search Frameworks First: 0
AppBundle
Only Search AppBundle: 0
Search AppBundle Last: 0
Search AppBundle First: 0
NO_DEFAULT_PATH Enabled
find_library considered the following locations:
/home/alex/test2/meta-dx1/sdk/builds/debug/lib//(lib)libmdx1host.so.2(\.so|\.a)
/home/alex/test2/meta-dx1/sdk/builds/debug/lib/(lib)libmdx1host.so.2(\.so|\.a)
The item was found at
/home/alex/test2/meta-dx1/sdk/builds/debug/
-- METADX1_LIB = /home/alex/test2/meta-dx1/sdk/builds/debug/libmdx1host.so.2
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test2/build
And this apparently works.

The library locations are cached by cmake, so if you added the path location and cmake found the library previously elsewhere, make sure to clear the build directory.

Related

CMake Setup for Dual Environment Builds

Goal
I am using CMake to make the build for my project which is an embedded firmware based on ARM Cortex platform built using arm-none-eabi-gcc-6.3.1 compiler, using VSCode Editor, and on Windows host. I am trying to make a second build for testing on the Windows system I am using for the same project.
The First Solution Problem
The issue I am having is that whenever I need to switch my build from production to test, I have to delete the build files and rerun the CMake command with the test argument, when I do not do that, the build does not change the ARM compiler to the one I intend to use (I am guessing it is a caching problem). I have tried make clean and make rebuild_cache thinking that it may clean the cache and solve the problem for me, and did not work.
A fresh build Example:
Project\build> cmake -G"MinGW Makefiles" -DTARGET_GROUP=test ..
You have changed variables that require your cache to be deleted.
Configure will be re-run and you may have to reset some variables.
The following variables have changed:
CMAKE_C_COMPILER= C:/MinGW/bin/gcc.exe
CMAKE_CXX_COMPILER= C:/MinGW/bin/g++.exe
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/MinGW/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: Path\to\Project\build
Project\build>make
(successful make)
The second build:
Project\build> cmake -G"MinGW Makefiles" -DTARGET_GROUP=production ..
You have changed variables that require your cache to be deleted.
Configure will be re-run and you may have to reset some variables.
The following variables have changed:
CMAKE_C_COMPILER= Path/to/arm-gnu-toolchain/bin/arm-none-eabi-gcc.exe
CMAKE_CXX_COMPILER= Path/to/arm-gnu-toolchain/bin/arm-none-eabi-g++.exe
-- The C compiler identification is GNU 6.3.0
-- The CXX compiler identification is GNU 6.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/MinGW/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/MinGW/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: Path\to\Project\build
Project\build>make
(Cached make -did not change the compiler or the files to be built)
The CMakeLists.txt:
set(TARGET_GROUP test CACHE STRING "Group to build")
if(TARGET_GROUP STREQUAL production)
# ARM Lib
include("arm-gnu.cmake")
else()
include("win-gcc-for-testing.cmake")
endif()
# include the files based on the TARGET_GROUP value
# ...
Current Solution
Currently, I have a temporary solution by making a separate folder for each building type and they work perfectly.
The question
Is the current solution (making two build directories each is for a different environment) right in terms of best practices? If not, what could be a better one?
As #Tsyvarev says, you have to use different directories if you want different builds. Here you are trying to build both in the same build directory. Instead, create a subdirectory test to build the -DTARGET_GROUP=test, and a different subdirectory prod to build the -DTARGET_GROUP=production:
Project> mkdir test
Project> cd test
Project\test> cmake -G"MinGW Makefiles" -DTARGET_GROUP=test ..
Project\test> cd ..
Project> mkdir prod
Project> cd prod
Project\prod> cmake -G"MinGW Makefiles" -DTARGET_GROUP=production ..
Of course you can call the directories whatever you like.
Since you'd like this to integrate into VSCode, do the configuration change with the CMake build kits, which is what sets the compiler prior to calling CMake. You can specify additional user kit definitions, and in the VSCode interface choose between compiler kits.
Rewrite the CMake files just enough to condition everything else on the selection of compiler.
THEN, the VSCode cmake-tools extension supports variable expansion for the name of the build directory. Among the options are ${buildKit} and ${buildKitTargetArch}. Make this suffix part of the Build Directory setting (your choice of whether to set this only in your workspace, or more globally on your system).
Now, when you switch kits, CMake will pick up the directory change and happily exist with two different build directories.
Alternatively, cmake-tools now provides variants, which could be used to add additional Production and Test to the normal Release, Debug, RelWithDebInfo, etc. There are additional build directory expansion variables for information from the currently selected variant.

CMake/FindDoxygen: Path handling in MSYS2

I'm trying to add a target to generate API doc with Doxygen to my CMake project by find_package(Doxygen ...) and doxygen_add_docs(). I'm in a MSYS2 environment on Windows 10. For some reason CMake and Doxygen seem to not handle paths in the expected way (see the example).
At first, Doxygen complains that it cannot create the output directory. The DOXYGEN_OUTPUT_DIRECTORY prepared by CMake is a Windows path with regular forward slashes. Doxygen seems to not recognize this as an absolute path and prepends it with its working directory in the Unix format (/c/Users/...). I tried this by executing the generated target as well as calling Doxygen manually with the generated Doxyfile.doc. It works if I convert the path to a Unix path with cygpath.
The second problem is about finding dot. I have GraphViz installed as a native Windows package and generally the MSYS2 CMake finds this. Then, in the FindDoxygen.cmake DOXYGEN_DOT_PATH is set as the path portion of the dot executable and is modified by file(TO_NATIVE_PATH ...) because I'm on Windows. Trying this manually I could see that it sets that path to "C:/Program Files (x86)/Graphviz/bin" and converts it to "C:/Program\ Files\ (x86)/Graphviz/bin". The latter ends up in Doxyfile.doc. If I remove the backslashes there, it works. I suppose Doxygen considers these backslashes which are meant to escape the spaces as path separators.
For the first problem I have a (hopefully) portable workaround, but the second I can only fix if I manually repeat the retrieval of DOXYGEN_DOT_PATH from the Find module without the conversion step. This doesn't feel like a good solution.
Do I miss something here about path handling in CMake, e.g. some documentation or setting/policy?
Is this anyways the expected behavior, esp. for file(TO_NATIVE_PATH ...), in MSYS2?
Example
Very basic example: Just a CMakeLists.txt to generate Makefiles and invoke Doxygen. The output of make doc shows the 2 problems described above - the error is for #1, the warning for #2.
CMakeLists.txt
cmake_minimum_required(VERSION 3.19)
project(DoxyTest VERSION 0.1)
find_package(Doxygen OPTIONAL_COMPONENTS dot)
doxygen_add_docs(doc)
Trying to build the doc target
$ cmake -G"MSYS Makefiles" ..
-- The C compiler identification is GNU 10.2.0
-- The CXX compiler identification is GNU 10.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/msys64/mingw64/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Doxygen: C:/msys64/usr/bin/doxygen.exe (found version "1.9.1 (ec8203f43232e7e7b16b1c85351c7c48d128f924)") found components: doxygen dot
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/myUser/tmp/foo/build
$ make doc
Scanning dependencies of target doc
[100%] Generate API documentation for doc
warning: the dot tool could not be found at C:/Program\ Files\ (x86)/Graphviz/bin
Doxygen version used: 1.9.1 (ec8203f43232e7e7b16b1c85351c7c48d128f924)
error: Could not create output directory /C/Users/myUser/tmp/foo/C:/Users/myUser/tmp/foo/build/html
Exiting...
make[3]: *** [CMakeFiles/doc.dir/build.make:78: CMakeFiles/doc] Error 1
make[2]: *** [CMakeFiles/Makefile2:95: CMakeFiles/doc.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:102: CMakeFiles/doc.dir/rule] Error 2
make: *** [Makefile:137: doc] Error 2
It turned out that the proper Doxygen package was not installed in the MSYS2 environment.
I use the MinGW64 shell, which uses the binaries from the mingw-w64-x86_64-* packages. The CMake output from the question shows that the binaries for the C and CXX compilers are under C:/msys64/mingw64/ (as well as the CMake binary) while Doxygen is in C:/msys64/usr/bin/.
Installing mingw-w64-x86_64-doxygen solved the issue. Now, the CMake output shows the mingw64 path also for Doxygen in the MSYS2 MinGW64-bit shell and API doc generation works flawlessly. Trying the MSYS2 MSYS shell also works fine with CMake using binaries from C:/msys64/usr/bin/.

find_package(ACL REQUIRED) does not stop processing

I am currently trying to set up a CMake-based build system for a small C library of mine. Since this library depends on libacl, CMake should verify that it is present on the system, or fail otherwise.
Since there is no predefined FindACL module, I used the one from the KDE project:
[...] check_include_files [...] find_library [...]
if (ACL_HEADERS_FOUND AND ACL_LIBS AND ATTR_LIBS)
set(ACL_FOUND TRUE)
set(ACL_LIBS ${ACL_LIBS} ${ATTR_LIBS})
message(STATUS "Found ACL support: ${ACL_LIBS}")
endif (ACL_HEADERS_FOUND AND ACL_LIBS AND ATTR_LIBS)
I call it using the following (minimal) CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(
cmaketest
VERSION 1.0
DESCRIPTION "cmake test"
LANGUAGES C
)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(ACL REQUIRED) # ACL_LIBS
It correctly detects that my system is lacking the libacl includes, but does not stop processing, even though the manual states that
The REQUIRED option stops processing with an error message if the package cannot be found.
Do I have to explicitly check whether ACL_FOUND is set, through an if statement?
I am using CMake 3.13.4. Terminal output:
-- The C compiler identification is GNU 8.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for include file attr/libattr.h
-- Looking for include file attr/libattr.h - not found
-- Looking for include file sys/xattr.h
-- Looking for include file sys/xattr.h - found
-- Looking for include file sys/acl.h
-- Looking for include file sys/acl.h - not found
-- Looking for include file acl/libacl.h
-- Looking for include file acl/libacl.h - not found
-- Configuring done
-- Generating done
-- Build files have been written to: [redacted]/build
It seems that since some time CMake expects a FindXXX.cmake script (used in MODULE mode of find_package) to check REQUIRED option and emit an error if needed. Such change in CMake behavior makes old legacy "Find" scripts, like FindACL.cmake, to be broken.
Indirect confirmation of that can be found in this "Common bug in find module", described in CMake wiki:
The module does not check _FIND_REQUIRED or
_FIND_QUIETLY - and thus the find_package arguments QUIET
and REQUIRED will have no effect
So, FindACL.cmake script could be rewritten as follows:
# FindACL.cmake
# ...
if (ACL_HEADERS_FOUND AND ACL_LIBS AND ATTR_LIBS)
set(ACL_FOUND TRUE)
set(ACL_LIBS ${ACL_LIBS} ${ATTR_LIBS})
message(STATUS "Found ACL support: ${ACL_LIBS}")
elif (ACL_FIND_REQUIRED)
# ACL hasn't been found but REQUIRED. Emit an error.
message(FATAL_ERROR "Cannot find ACL")
endif (ACL_HEADERS_FOUND AND ACL_LIBS AND ATTR_LIBS)
Actually, most "Find" scripts use the special helper which sets result of find_package and cares about its options. FindACL.cmake could also use this helper:
# FindACL.cmake
# ...
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ACL
# Use default message on fail.
DEFAULT_MSG
# Variables which should be true-evaluated for assume the package to be found
ACL_HEADERS_FOUND ACL_LIBS ATTR_LIBS
)
The things are different for XXXConfig.cmake scripts, which are processed in CONFIG mode of find_package. These scripts should only set XXX_FOUND variable to false, and CMake will handle REQUIRED option by itself.

Cmake: how to force it to use colormake?

in order to use colormake I did set this alias in my .bashrc
alias make="/usr/bin/colormake"
It works, as if I try to compile (with qmake) a simple C++ example code with errors (just a main.cpp with a cout ), they are correctly coloured.
However, if I compile the same code with cmake, colormake is not used. What can I do to force cmake to use it?
my minimal CMakeList.txt example is
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
ADD_DEFINITIONS(-std=c++11)
ADD_EXECUTABLE(exe main.cpp)
System: Debian 8.8 jessie
Thanks, Valerio
Update:
I modified the CMakeLists.txt in this way, but no success:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
ADD_DEFINITIONS(-std=c++11)
set(CMAKE_MAKE_PROGRAM /usr/bin/colormake)
ADD_EXECUTABLE(exe main.cpp)
message("CMAKE_MAKE_PROGRAM: " ${CMAKE_MAKE_PROGRAM})
Update 2:
I modified the CMakeList in this way:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.2)
ADD_DEFINITIONS(-std=c++11)
#set(CMAKE_COLOR_MAKEFILE OFF)
#set(CMAKE_MAKE_PROGRAM /usr/bin/colormake)
ADD_EXECUTABLE(exe main.cpp)
message("CMAKE_MAKE_PROGRAM: " ${CMAKE_MAKE_PROGRAM})
message("CMAKE_COLOR_MAKEFILE: " ${CMAKE_COLOR_MAKEFILE})
then launched cmake with this argument from command line:
cmake -DCMAKE_MAKE_PROGRAM=/usr/bin/colormake -DCMAKE_COLOR_MAKEFILE=OFF ../
But again, the main.cpp synthax error after make is not coloured.
This is the output of cmake, note the messages about CMAKE_MAKE_PROGRAM and CMAKE_COLOR_MAKEFILE
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
CMAKE_MAKE_PROGRAM: /usr/bin/colormake
CMAKE_COLOR_MAKEFILE: OFF
-- Configuring done
-- Generating done
-- Build files have been written to: /home/valeriosperati/Desktop/VALERIO_SPERATI/prova_codice_c/colormake/cmake/build
Some additional (maybe helpful) info: this is the output
I obtain when compiling with qmake, the error 'hjskf' is in red.
this is the output when comiling with cmake:
It should be enough to set the CMAKE_MAKE_PROGRAM cache variable to point at the build tool you want to use. You can do this by running cmake with a -D option like so:
cmake -DCMAKE_MAKE_PROGRAM=/usr/bin/colormake path/to/src
For the benefit of others, this technique can be used with other generators too, not just make. Just be aware that it is your responsibility to make sure the build tool specified matches the generator type CMake is using (i.e. don't pass a make tool if you've told CMake to use Ninja with -G Ninja instead).
Note, however, that this only really matters if you are invoking the build via CMake like so:
cmake --build path/to/build/dir
Some IDE tools may invoke the build that way. Most of the time, however, developers invoke the tool directly. In your case, you can simply invoke colormake instead of make. If you are still not getting colored output after doing that, then your problem must be elsewhere (check your terminal type settings perhaps).

add_custom_command -- update dependency list over rebuilds

See last status update
Initial conditions
code generator that generates set of c++ sources taking one input file as parameter
input file may include other input files
already solved task of getting list of output files, parsing input codegen files to get full list of codegen inputs.
I.e. add_custom_command is provided with correct set of dependencies for the first time:
add_custom_command(OUTPUT ${generatedSources}
COMMAND ${codegenCommand} ARGS ${codegenArgs}
DEPENDS ${codegenInputFiles})
Problem scenario
current system works well until someone modifies one of codegen input files to include new input file or remove include of existing one.
This case, it is required to update list of codegen input file provided to add_custom_command as dependencies, but I have no idea how
What is missing
ability to update add_custom_command dependencies over project rebuilds
Is there any way to solve it without making full project rebuild ?
UPDATE - Alternative (better?) problem description
I`ve found similar not answered question on cmake mailing list, post it here for better clarity:
http://article.gmane.org/gmane.comp.programming.tools.cmake.user/52279
I am trying to get a code generation tool to behave "the same as" a C source file with respect to dependencies. By that I mean, suppose you have a C file "a.c". Because it can #include files, every time the content of a.c changes, its dependencies may have changed also. The dependencies get rescanned with -MMD. I would like some way to emulate this for my code generator.
First I tried add_custom_command, which takes a fixed DEPENDS list, determined at the time the custom command is defined. Concretely, I mean something like this:
function(add_generated_library)
figure_out_dependencies(deps ${ARGN})
add_custom_command(... DEPENDS ${deps})
endfunction()
But that only captures the dependencies at build-system-generation time. Every time the custom command runs, the DEPENDS list may need to change, because the changes may imply new dependencies.How should I go about doing this?
UPDATE 2 - Possible solution
Following I consider as facts
- there are voices across the web regarding cmake support of dynamic
dependencies, which is required for smooth integration of many
non-trivial code generation tools
- there`s no ready-for-use optimal solution available, as what we actually need is hook to add support of custom DSL to IMPLICIT_DEPENDS
From cmake manual:
The IMPLICIT_DEPENDS option requests scanning of implicit dependencies of an input file. The language given specifies the programming language whose corresponding dependency scanner should be used. Currently only C and CXX language scanners are supported. The language has to be specified for every file in the IMPLICIT_DEPENDS list. Dependencies discovered from the scanning are added to those of the custom command at build time.
Solution below adheres (hopefully) to following criteria:
avoid not necessary dependency scanning on rebuild
avoid not necessary code generator run on rebuild
allow providing cmake functions to clients to register their models and
generate code/create libraries from that code, without imposing any project structure requirements (i.e. no sub-project responsible for code generation, models are distributed across project hierarchy using project-specific policy)
Solution idea
It is not possible to register custom language scanner, but it is possible to reuse existing one. The idea is that dependencies / hierarchy of custom model files get reflected as hierarchy of "C" header files. Each hierarchy node get added on registering of model file and C file includes match model file includes. If model file includes get changed, C file includes get changed. Therefore, each codegen invocation would depend on just one generated C header reflecting passed model. Each reflected file will have a dependency on the model file and get touched on model file change.
To sum up : probably, my wording is not that clear at this point, but with respect to other people needs and community helped me to investigate this problem, I will post generic solution (+ link to github or new cmake wiki page) without my project specifics once it is ready (in 1-3 days).
Can you show how you initialize the variable codegenInputFiles? You can probably use a file(GLOB ... ) or file(GLOB_RECURSE ... ) command there.
See documentation.
Note, though, that you will have to rerun cmake to have your command being generated. Are you working with git? Then you can have a hook that forces a cmake call every time you pull (so that if somebody modified the codegenInputFiles your auto generated files will be updated).
After clarification of the problem, you should be able to find a workaround by using IMPLICIT_DEPENDS instead of DEPENDS. Limitations:
It can only work if your input file is C/C++ (check the syntax, as you must specify the language for each file specified)
You might need to check your cmake version supports that command, even though it looks that it has been around for a while
It's only supported for Makefile generator, which sounds pretty bad...
EDIT
After some iterations, I finally got what is your problem.
I propose the following solution: separate the file generation in a separate cmake subproject. When you will build your main project (by calling make), you will trigger both cmake and make for your subproject. Calling cmake is necessary for keeping updated the dependencies, while calling make to actually build your auto-generated sources.
Here I show an example of a project and a subproject, with the project invoking cmake and make for the subproject.
Structure:
.
├── CMakeLists.txt
├── a.cpp
├── build
└── subProject
└── CMakeLists.txt
File content
./CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
add_custom_target(subProjectTarget ALL)
add_custom_command(TARGET subProjectTarget PRE_BUILD COMMAND mkdir -p ${CMAKE_BINARY_DIR}/subProject && cd ${CMAKE_BINARY_DIR}/subProject && ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/subProject && make)
include_directories(${CMAKE_BINARY_DIR}/subProject)
add_executable (dummy a.cpp)
add_dependencies (dummy subProjectTarget)
./a.cpp (Note that b.h doesn't exist yet)
#include "b.h"
int main () {
}
./SubProject/CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
file(WRITE ${CMAKE_BINARY_DIR}/b.h "//I am a dummy file\n")
Building the project (using default make)
me#here:~/example/build$ cmake ..
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build
me#here:~/example/build$ make
Scanning dependencies of target subProjectTarget
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build/subProject
[ 0%] Built target subProjectTarget
Scanning dependencies of target dummy
[100%] Building CXX object CMakeFiles/dummy.dir/a.cpp.o
Linking CXX executable dummy
[100%] Built target dummy
Note that the second time the cmake calls is on the subproject.
At the next call everything is even faster:
me#here:~/example/build$ make
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build/subProject
[ 0%] Built target subProjectTarget
Scanning dependencies of target dummy
[100%] Building CXX object CMakeFiles/dummy.dir/a.cpp.o
Linking CXX executable dummy
[100%] Built target dummy
(Although here the file b.h is written every time causing a.cpp to be recompiled)
This stub can be very much improved by using cmake commands to generate the output directories (and not mkdir) and cascading the generator chosen for the main project (here I am assuming everything is using make)
Let me know if you need any further clarification.
I think that ${codegenInputFiles} should contain a list of hardcoded source files and include files required by the custom command. Documentation of file(GLOB ...) states:
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.
The hard work (for which we are paid) is to keep the ${codegenInputFiles} up to date (causing the full project rebuild). Anyway, you would have similar problem if someone created a new source file and hadn't added it to the ${codegenInputFiles}, right? So I believe the additional dependency on include file should be treated the same.