[CMake] Generating include files

Urs Thuermann urs at isnogud.escape.de
Fri May 19 18:48:34 EDT 2017


Craig Scott <craig.scott at crascit.com> writes:

> A bit of a long-shot, have you tried generating the file with the extension
> .h instead of .c? That might allow it to be picked up by the dependency
> scanner (I don't know if it treats file extensions differently). Also, the
> add_custom_command(OUTPUT...) call needs to be in the same
> CMakeLists.txt

No, I have tried that before in several variations, and nothing
worked.

For exmaple:

	$ cat simple/mktab 
	#!/usr/bin/awk
	
	BEGIN{ print "static int tab[] = { 0, 1, 2 };"; exit }
	$ cat simple/foo.c 
	#include "tab.h"
	
	int main() { return tab[0]; }
	$ cat simple/CMakeLists.txt 
	cmake_minimum_required(VERSION 3.0)
	project(simple)
	
	add_custom_command(
	    OUTPUT           ${CMAKE_BINARY_DIR}/tab.h
	    COMMAND "mktab > ${CMAKE_BINARY_DIR}/tab.h"
	)
	
	include_directories(${CMAKE_BINARY_DIR})
	
	add_executable(foo foo.c)
	$ mkdir simple-build
	$ cd simple-build
	$ cmake ../simple
	-- 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
	-- Configuring done
	-- Generating done
	-- Build files have been written to: /home/urs/playground/cmake/simple-build
	$ make
	Scanning dependencies of target foo
	[100%] Building C object CMakeFiles/foo.dir/foo.c.o
	/home/urs/playground/cmake/simple/foo.c:1:17: fatal error: tab.h: No such file or directory
	 #include "tab.h"
	                 ^
	compilation terminated.
	CMakeFiles/foo.dir/build.make:54: recipe for target 'CMakeFiles/foo.dir/foo.c.o' failed
	make[2]: *** [CMakeFiles/foo.dir/foo.c.o] Error 1
	CMakeFiles/Makefile2:60: recipe for target 'CMakeFiles/foo.dir/all' failed
	make[1]: *** [CMakeFiles/foo.dir/all] Error 2
	Makefile:76: recipe for target 'all' failed
	make: *** [all] Error 2
	$ make tab.h
	make: *** No rule to make target 'tab.h'.  Stop.

The call to make seems to show that cmake does not even try to
generate tab.h and the next command shows that it also does not know
how to generate it, if it would try.

How does cmake scan for dependencies of target foo?  Using gcc -MM
would fail and gcc -MM -MG would yield the correct dependency:

	$ cc -MG ../simple/foo.c 
	cc1: error: to generate dependencies you must specify either -M or -MM
	cc1: error: -MG may only be used with -M or -MM
	$ cc -MM -MG ../simple/foo.c 
	foo.o: ../simple/foo.c tab.h

> I wrote an article on working with generated sources
> <https://crascit.com/2017/04/18/generated-sources-in-cmake-builds/>
> recently which covers some of these details, maybe it contains some useful
> info for you.

Hm, it's the same info I've already found in other places.
Unfortunately, I still don't see a way to generate a source file that
should be #include'd instead of linked into an executable.

urs


More information about the CMake mailing list