Generating include files

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

Generating include files

Urs Thuermann
How can I write a CMakeFile that will include a generated source file
into another C source?  I have read the FAQ, searched the mailing list
archives and have tried for two hours without success.

With standard make this would be quite simple:

        $ cat Makefile
        foo: foo.o
       
        foo.o: tab.c
       
        tab.c:
                awk -f mktab > $@
        $ cat foo.c
        #include "tab.c"
       
        int main() { return tab[0]; }
        $ cat mktab
        #!/usr/bin/awk
       
        BEGIN{ print "static int tab[] = { 0, 1, 2 };"; exit }
        $ make
        awk -f mktab > tab.c
        cc    -c -o foo.o foo.c
        cc   foo.o   -o foo
        $

How would I do this with cmake?

urs
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Michael Ellery

> On May 19, 2017, at 1:00 PM, Urs Thuermann <[hidden email]> wrote:
>
> How can I write a CMakeFile that will include a generated source file
> into another C source?  I have read the FAQ, searched the mailing list
> archives and have tried for two hours without success.
>
> With standard make this would be quite simple:
>
> $ cat Makefile
> foo: foo.o
>
> foo.o: tab.c
>
> tab.c:
> awk -f mktab > $@
> $ cat foo.c
> #include "tab.c"
>
> int main() { return tab[0]; }
> $ cat mktab
> #!/usr/bin/awk
>
> BEGIN{ print "static int tab[] = { 0, 1, 2 };"; exit }
> $ make
> awk -f mktab > tab.c
> cc    -c -o foo.o foo.c
> cc   foo.o   -o foo
> $
>
> How would I do this with cmake?
>
> urs
> —
>

if your source can be generated by simple substitution of variable values (like a template file), then configure_file() will do the trick. If the process to create the file is more complex, then add_custom_command() with an appropriate OUTPUT specification is probably what you want, something like:

add_custom_command(OUTPUT tab.c  COMMAND "awk -f mktab > tab.c")

If you don’t like where the files are generated, you can tweak WORKING_DIR and/or use full-paths to the file(s).

You will need to make sure that some other target explicitly depends on tab.c (or whatever you name the output) to cause this custom rule to be executed.

-Mike


--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Urs Thuermann
Michael Ellery <[hidden email]> writes:

> if your source can be generated by simple substitution of variable
> values (like a template file), then configure_file() will do the
> trick. If the process to create the file is more complex, then
> add_custom_command() with an appropriate OUTPUT specification is
> probably what you want, something like:

Yes, the awk example was a simplification.  The table to be generated
is much larger using a somewhat more complex specification.  I don't
want to calculate at run-time in foo.c, but at compile-time so that it
can go into a static const int array.

> add_custom_command(OUTPUT tab.c  COMMAND "awk -f mktab > tab.c")

I have tried dozens of combinations with add_custom_command(),
include_directories(), and ${CMAKE_BINARY_DIR}.  Also the way you
show.  But the only way I found to have tab.c actually generated was
to put tab.c into the add_executable() specification, but then it
generates a tab.o which is linked into the executable.  But I want to
have the tab[] static, i.e. included into a C file, not linked in.

> You will need to make sure that some other target explicitly depends
> on tab.c (or whatever you name the output) to cause this custom rule
> to be executed.

Is there a way to specify that foo.o depends on tab.c?  For some
reason cmake's scan does not seem to find this.

urs
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Michael Ellery

> On May 19, 2017, at 2:00 PM, Urs Thuermann <[hidden email]> wrote:
>
> Michael Ellery <[hidden email]> writes:
>
>> if your source can be generated by simple substitution of variable
>> values (like a template file), then configure_file() will do the
>> trick. If the process to create the file is more complex, then
>> add_custom_command() with an appropriate OUTPUT specification is
>> probably what you want, something like:
>
> Yes, the awk example was a simplification.  The table to be generated
> is much larger using a somewhat more complex specification.  I don't
> want to calculate at run-time in foo.c, but at compile-time so that it
> can go into a static const int array.
>
>> add_custom_command(OUTPUT tab.c  COMMAND "awk -f mktab > tab.c")
>
> I have tried dozens of combinations with add_custom_command(),
> include_directories(), and ${CMAKE_BINARY_DIR}.  Also the way you
> show.  But the only way I found to have tab.c actually generated was
> to put tab.c into the add_executable() specification, but then it
> generates a tab.o which is linked into the executable.  But I want to
> have the tab[] static, i.e. included into a C file, not linked in.
>
>> You will need to make sure that some other target explicitly depends
>> on tab.c (or whatever you name the output) to cause this custom rule
>> to be executed.
>
> Is there a way to specify that foo.o depends on tab.c?  For some
> reason cmake's scan does not seem to find this.
>

well, if you rename tab.c to tab.h, I’m pretty sure CMAKE will honor it as a dependency but won’t compile it..so that might be the easiest.

Alternatively, use set_source_file_properties to set https://cmake.org/cmake/help/v3.8/prop_sf/OBJECT_DEPENDS.html#prop_sf:OBJECT_DEPENDS

-Mike
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Craig Scott-3
In reply to this post by Urs Thuermann
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 file as the one where you create the target that pulls in foo.c or else the dependency relationship isn't created by CMake. I wrote an article on working with generated sources recently which covers some of these details, maybe it contains some useful info for you.



On Sat, May 20, 2017 at 7:00 AM, Urs Thuermann <[hidden email]> wrote:
Michael Ellery <[hidden email]> writes:

> if your source can be generated by simple substitution of variable
> values (like a template file), then configure_file() will do the
> trick. If the process to create the file is more complex, then
> add_custom_command() with an appropriate OUTPUT specification is
> probably what you want, something like:

Yes, the awk example was a simplification.  The table to be generated
is much larger using a somewhat more complex specification.  I don't
want to calculate at run-time in foo.c, but at compile-time so that it
can go into a static const int array.

> add_custom_command(OUTPUT tab.c  COMMAND "awk -f mktab > tab.c")

I have tried dozens of combinations with add_custom_command(),
include_directories(), and ${CMAKE_BINARY_DIR}.  Also the way you
show.  But the only way I found to have tab.c actually generated was
to put tab.c into the add_executable() specification, but then it
generates a tab.o which is linked into the executable.  But I want to
have the tab[] static, i.e. included into a C file, not linked in.

> You will need to make sure that some other target explicitly depends
> on tab.c (or whatever you name the output) to cause this custom rule
> to be executed.

Is there a way to specify that foo.o depends on tab.c?  For some
reason cmake's scan does not seem to find this.

urs
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake



--
Craig Scott
Melbourne, Australia

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Urs Thuermann
Craig Scott <[hidden email]> 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
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Andrew Fuller-2
In reply to this post by Urs Thuermann

Is there a way to specify that foo.o depends on tab.c?  For some

> reason cmake's scan does not seem to find this.

Does the following work for you?  The first bit is just putting some fixed files for convenience.  The second bit is the interesting bit.  In your build directory you won't have a data.c file until you compile.  When it compiles, data.c will first be generated, placed in your build directory, then compiled into data.c.o and archived into libdata.a.  Finally the executable links against libdata.a


cmake_minimum_required( VERSION 3.0 )

# Files that exist before the build starts:

# Header file with with no matching .c file
file( WRITE ${CMAKE_CURRENT_SOURCE_DIR}/data.h "extern int somevalue;" )
# main() that references the header
file( WRITE ${CMAKE_CURRENT_SOURCE_DIR}/hello.c "
#include \"data.h\"  
#include <stdio.h>
int main()
{
   printf( \"Magic data: %d\\n\", somevalue );
}
" )



# This file is generated at build time and is relative to the binary dir
add_custom_command( OUTPUT data.c
 COMMAND echo "int somevalue = 42; " > data.c
 VERBATIM
)

add_library( data ${CMAKE_CURRENT_BINARY_DIR}/data.c )
add_executable( hello hello.c )

target_link_libraries( hello
 PRIVATE data
)



--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Michael Ellery
In reply to this post by Urs Thuermann

> On May 19, 2017, at 3:48 PM, Urs Thuermann <[hidden email]> wrote:
>
> Craig Scott <[hidden email]> 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.
>


Here:

https://github.com/mellery451/gen_header

works for with me with makefile generator.

-Mike
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Andrew Fuller-2
In reply to this post by Urs Thuermann

> 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.

I missed that you wanted a .h file that other libraries would pick up.  Since CMake isn't aware of which header files a library #includes, you're not getting that dependency information which I guess is what you're running into.  I haven't needed to do it myself, but have you tried setting your generated header file in the SOURCES property of your library PUBLICly (or possibly INTERFACE).  CMake knows the custom command that OUTPUTs a file, so when it tracks the file it should know the dependency to make it happen.  By exporting the header it should convey the dependency to the consumer(s).

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Craig Scott-3
In reply to this post by Michael Ellery
Okay you got me curious so I did some further digging and testing. Michael's example works because the generated header is listed as a source file in the add_executable() call. Therefore CMake automatically sets up the required dependency for you. If you don't want to do that, two other approaches also achieve your end goal. The wording of the OBJECT_DEPENDS source property documentation gives a clue for one method, although it's easy to miss (emphasis added by me):

This property need not be used to specify the dependency of a source file on a generated header file that it includes. Although the property was originally introduced for this purpose, it is no longer necessary. If the generated header file is created by a custom command in the same target as the source file, the automatic dependency scanning process will recognize the dependency. If the generated header file is created by another target, an inter-target dependency should be created with the add_dependencies() command (if one does not already exist due to linking relationships).

As far as I can tell, the only way to create a custom command in the same target and have that custom command execute before the source file compiles is to use a PRE_BUILD custom command, but these are only supported with the Visual Studio generator and therefore are not so useful. Instead, you can create another target with add_custom_target() which depends on the generated header and then use add_dependencies() to specify the executable target depends on the new custom target, something like this:

    cmake_minimum_required(VERSION 3.0)
    project(simple)

    add_custom_command(
        OUTPUT           ${CMAKE_BINARY_DIR}/tab.h
        COMMAND "mktab > ${CMAKE_BINARY_DIR}/tab.h"
    )
    add_custom_target(gentab DEPENDS ${CMAKE_BINARY_DIR}/tab.h)

    include_directories(${CMAKE_BINARY_DIR})

    add_executable(foo foo.c)
    add_dependencies(foo gentab)

Another choice is to set the OBJECT_DEPENDS property on foo.c, even though the documentation for that source property says it shouldn't be needed. The OBJECT_DEPENDS property sets up a dependency between files rather than targets and can be used like this:

    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)
    set_source_files_properties(foo.c PROPERTIES OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/tab.h)

Either approach or Michael's would seem to achieve the goal of your original question.




On Sat, May 20, 2017 at 9:10 AM, Michael Ellery <[hidden email]> wrote:

> On May 19, 2017, at 3:48 PM, Urs Thuermann <[hidden email]> wrote:
>
> Craig Scott <[hidden email]> 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.
>


Here:

https://github.com/mellery451/gen_header

works for with me with makefile generator.

-Mike
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake



--
Craig Scott
Melbourne, Australia

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Urs Thuermann
In reply to this post by Michael Ellery
Michael Ellery <[hidden email]> writes:

> https://github.com/mellery451/gen_header
>
> works for with me with makefile generator.

Yes, that's similar to what I have found yesterday after my posting.
It works but I'd prefer not to have to add the dependency to the
add_executable() specification.

I am new to cmake, but I still prefer standard make.  I work in a
project were I am supposed to use cmake, so I try to learn about it by
doing little examples.

But I find cmake makes simple things more complicated, it seems much
bigger and more complex than make and provides less flexibility.  I
prefer simple tools with simple basic primitives that can be combined
flexibly to build powerful systems.

I dislike that I should add tab.h as dependency to the executable
since it's actually the object file that depends on the header file.
The executable then only depends on the object file.

Say I have

        add_custom_command(output crctab.h command mkcrctab > crctab.h)
        add_executable(send send.c crc.c)
        add_executable(recv recv.c crc.c)
        add_executable(foo  foo.c  crc.c)

and crc.c does #include "crctab.h".  Would I then really have to add
crctab.h to all add_executable() specifications?  IMO the executables
shouldn't have to "know" how crc.c is implemented.  The just link
crc.o.        

urs
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Urs Thuermann
In reply to this post by Craig Scott-3
Craig Scott <[hidden email]> writes:

> This property need not be used to specify the dependency of a source file
> on a generated header file that it includes. Although the property was
> originally introduced for this purpose, it is no longer necessary. If the
> generated header file is created by a custom command *in the same target as
> the source file*, the automatic dependency scanning process will recognize
> the dependency. If the generated header file is created *by another target*,
> an inter-target dependency should be created with the add_dependencies()
> command (if one does not already exist due to linking relationships).

>     cmake_minimum_required(VERSION 3.0)
>     project(simple)
>
>     add_custom_command(
>         OUTPUT           ${CMAKE_BINARY_DIR}/tab.h
>         COMMAND "mktab > ${CMAKE_BINARY_DIR}/tab.h"
>     )
>     add_custom_target(gentab DEPENDS ${CMAKE_BINARY_DIR}/tab.h)
>
>     include_directories(${CMAKE_BINARY_DIR})
>
>     add_executable(foo foo.c)
>     add_dependencies(foo gentab)

I have to add that to executables that use foo.o, when only foo.o
actually depends on tab.h?  That looks cumbersome.

> Another choice is to set the OBJECT_DEPENDS property on foo.c, even though
> the documentation for that source property says it shouldn't be needed. The
> OBJECT_DEPENDS property sets up a dependency between files rather than
> targets and can be used like this:
>
>     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)
>     set_source_files_properties(foo.c PROPERTIES OBJECT_DEPENDS
> ${CMAKE_BINARY_DIR}/tab.h)

IMO that feels just wrong.  foo.c does NOT depend on tab.h, foo.c does
not depend on anything, it's not even generated by the build system.
*I* edit it.  Instead, it is the object file foo.o that depends on
tab.h.  But it seems that cmake doesn't want the developer to see or
talk about object files.  It hides them somewhere in subdirs (with
unpredictable names (sometimes foo.o, sometimes a silly name like
foo.c.o, sometimes both), so after make foo.o I don't know which one
is current), gives error messages if I use them in CMakeLists.txt...

urs
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Craig Scott-3


On Sat, May 20, 2017 at 7:16 PM, Urs Thuermann <[hidden email]> wrote:
Craig Scott <[hidden email]> writes:

> Another choice is to set the OBJECT_DEPENDS property on foo.c, even though
> the documentation for that source property says it shouldn't be needed. The
> OBJECT_DEPENDS property sets up a dependency between files rather than
> targets and can be used like this:
>
>     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)
>     set_source_files_properties(foo.c PROPERTIES OBJECT_DEPENDS
> ${CMAKE_BINARY_DIR}/tab.h)

IMO that feels just wrong.  foo.c does NOT depend on tab.h, foo.c does
not depend on anything, it's not even generated by the build system.
*I* edit it.  Instead, it is the object file foo.o that depends on
tab.h.  But it seems that cmake doesn't want the developer to see or
talk about object files.  It hides them somewhere in subdirs (with
unpredictable names (sometimes foo.o, sometimes a silly name like
foo.c.o, sometimes both), so after make foo.o I don't know which one
is current), gives error messages if I use them in CMakeLists.txt...

OBJECT_DEPENDS expresses exactly that. It says "object files built from this source file depend on these things". That's why it's called OBJECT_DEPENDS instead of just DEPENDS like other dependency-related keywords. But I do agree with your general feeling that this is more complicated than it should ideally be. Intuitively, it feels like something CMake should be able to work out for itself, but perhaps there's some limitation in the implementation of one or more of the generator types which makes it hard. I'll leave that for those with a more intimate knowledge of CMake's internals to comment on.

--
Craig Scott
Melbourne, Australia

--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Hendrik Sattler
In reply to this post by Urs Thuermann


Am 20. Mai 2017 11:16:54 MESZ schrieb Urs Thuermann <[hidden email]>:

>Craig Scott <[hidden email]> writes:
>>     add_executable(foo foo.c)
>>     set_source_files_properties(foo.c PROPERTIES OBJECT_DEPENDS
>> ${CMAKE_BINARY_DIR}/tab.h)
>
>IMO that feels just wrong.  foo.c does NOT depend on tab.h, foo.c does
>not depend on anything, it's not even generated by the build system.
>*I* edit it.  Instead, it is the object file foo.o that depends on
>tab.h.  But it seems that cmake doesn't want the developer to see or
>talk about object files.  It hides them somewhere in subdirs (with
>unpredictable names (sometimes foo.o, sometimes a silly name like
>foo.c.o, sometimes both), so after make foo.o I don't know which one
>is current), gives error messages if I use them in CMakeLists.txt...

This is not quite correct.
Either your code generates a header file to be included by foo.c, then foo.c depends on it. Or it creates data and methods that need to be linked, then the executable depends on it.

An object file only makes the executable need unresolved symbols but that is not a dependency of the object file.

Or you simply failed to explain how parts relate to each other and the dependency between the parts is totally different.

OTOH, table-driven CRC is usually not that complicates to integrate.

CMake handles lots of compilers that REQUIRE other object file extensions than .o. It also generates for more that only make, allowing better working with IDEs. These bring their own strange rules that you cannot match to any make logic.

HS

--
Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9 Mail gesendet.
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Urs Thuermann
Hendrik Sattler <[hidden email]> writes:

> >IMO that feels just wrong.  foo.c does NOT depend on tab.h, foo.c does
> >not depend on anything, it's not even generated by the build system.
> >*I* edit it.  Instead, it is the object file foo.o that depends on
> >tab.h.

> This is not quite correct.

Obviously, we have different definitions of "depends on".  My use of
the term (and IMO that's the common meaning of "depends on" in build
systems) means "is generated from".  That is, when I say a depend on
b, that means the a has to be recreated when b changes.  As far as I
have read (admittedly not very much yet) in the cmake doc and
tutorial, that terminolgy is also use in cmake.  For example as Craig
writes,

    set_source_files_properties(foo.c PROPERTIES OBJECT_DEPENDS bar.h)

means that the object generated from foo.c depends on bar.h, and not
that foo.c depends on bar.h.

> Either your code generates a header file to be included by foo.c,
> then foo.c depends on it.

Not with the usual use of "depends on".  See above.

> Or it creates data and methods that need to be linked, then the
> executable depends on it.

Yes, but not directly.  The executable depends on the object file, and
the object file depends on the (created) source file.  Since "depends
on" is transitive, the executable also depends on the source file.

Still, I would prefer to write add_executable(foo foo.o) and have
cmake determine that foo.o depends on foo.c like in make.

> OTOH, table-driven CRC is usually not that complicates to integrate.

Of course, it was just a simple experiment to how to deal with
generated sources in cmake.  Using set_source_files_properties() it
looks quite OK:

        cmake_minimum_required(VERSION 3.0)
        project(simple)
       
        add_custom_command(
            OUTPUT  ${CMAKE_BINARY_DIR}/tab.c
            COMMAND awk -f ${CMAKE_SOURCE_DIR}/mktab > ${CMAKE_BINARY_DIR}/tab.c
        )
       
        include_directories(${CMAKE_BINARY_DIR})
       
        set_source_files_properties(crc.c PROPERTIES OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/tab.c)
        add_executable(foo foo.c crc.c)
        add_executable(bar bar.c crc.c)

> CMake handles lots of compilers that REQUIRE other object file
> extensions than .o. It also generates for more that only make,
> allowing better working with IDEs. These bring their own strange
> rules that you cannot match to any make logic.

Maybe, I don't use fancy GUI IDEs.  My IDE is Unix and have never
found rules that cannot be matched with make and other simple Unix
tools.

urs

--
GUIs normally make it simple to accomplish simple actions and
impossible to accomplish complex actions.
                -- Doug Gwyn (22/Jun/91 in comp.unix.wizards)
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Generating include files

Florent Castelli
On 20/05/2017 13:32, Urs Thuermann wrote:
> Yes, but not directly. The executable depends on the object file, and
> the object file depends on the (created) source file.  Since "depends
> on" is transitive, the executable also depends on the source file.
>
> Still, I would prefer to write add_executable(foo foo.o) and have
> cmake determine that foo.o depends on foo.c like in make.

But "foo.o" is an intermediate file, an implementation detail that isn't
cross-platform when CMake wants to work everywhere.
You shouldn't try to express that, it is just wrong.

The proper solution for CMake that works cross-platform is the one
expressed before with another target that generates only the headers and
your executable depending on it.
You can't really have the header generated in the same target that is
using them as that doesn't port well to some build systems that are more
high level (aka not Make or Ninja). Files will sometimes fail to
preprocess. Since your foo.c file can be preprocessed before the data
has been generated and build tools can't extract the dependency
information automatically as they usually do.
That preprocessing step needs to always work for most build tool, if it
doesn't they'll just fail the build and they won't check if it did fail
because that's a file generated in the same target.

Another solution is just not to have that weird requirement to compile
it "static". From what I understand, you had it as a .c file and
included it. So you know the object that is exported and its type.
You could just decouple your files using an extern declaration, this way
you can compile them both in parallel without an actual compile
dependency from foo.c to tab.c, but instead use a link dependency.

/Florent
--

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake