DevHeads.net

Triggering rebuild after changing a *.json file

Hey all,

in my quest for better *.json support in KF5 based applications, I noticed
that we currently do not rebuild properly on changes to the *.desktop or
*.json files.

For KDevelop, I'm thus playing around with something like this currently:

~~~~~~~~~~~~~~~+
function(kdevplatform_add_plugin plugin)
set(options )
set(oneValueArgs JSON)
set(multiValueArgs SOURCES)
cmake_parse_arguments(KDEV_ADD_PLUGIN "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN})

string(REGEX REPLACE "\\.cmake$" "" json_out ${KDEV_ADD_PLUGIN_JSON})
configure_file(${KDEV_ADD_PLUGIN_JSON}
${CMAKE_CURRENT_BINARY_DIR}/${json_out})

# ensure we recompile the corresponding object files when the json file
changes
set(dependent_sources )
foreach(header ${KDEV_ADD_PLUGIN_SOURCES})
file(STRINGS "${header}" match REGEX "K_PLUGIN_FACTORY_WITH_JSON")
if(match)
list(APPEND dependent_sources "${header}")
endif()
endforeach()
if(NOT dependent_sources)
# fallback to all sources - better safe than sorry...
set(dependent_sources ${KDEV_ADD_PLUGIN_SOURCES})
endif()
set_property(SOURCE ${dependent_sources} APPEND PROPERTY OBJECT_DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/${json_out})

add_library(${plugin} MODULE ${KDEV_ADD_PLUGIN_SOURCES})
set_property(TARGET ${plugin} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/${json_out})
endfunction()
~~~~~~~~~~~~~~~+

To be used like this:

kdevplatform_add_plugin(kdevgit JSON kdevgit.json.cmake SOURCES
${kdevgit_PART_SRCS})

This does trigger a rebuild, but the strings are still not updated properly.
I'm quite confused actually, does anyone know where the code comes from that
is embedded into the *.o that uses Q_PLUGIN_METADATA? I suspect CMake AUTOGEN?
But where does that put its generated binary JSON representation? How can I
make sure that it gets updated properly when the source file changes?

To reproduce this, you can just change any *.desktop file that is piped
through desktop_to_json. The change will be picked up by CMake and a
reconfigure is triggered, which is pretty slow as well. But nothing is
rebuilt. With the macro above, I trigger the build but still, the *.o file
that uses K_PLUGIN_FACTORY_WITH_JSON is still containing the "old" strings...
I'm at loss - can someone help me please?

Thanks

Comments

Re: Triggering rebuild after changing a *.json file

By Andreas Pakulat at 11/23/2014 - 04:39

Hi,

Is there a particular reason why you run the to-json part during cmake
time? If you setup a simple cmake script you could easily switch the
generation to be a custom target and then have the plugin depend on that
custom target (or rather its json output file).

I also think you're misunderstanding the AUTOGEN_TARGET_DEPENDS property,
according to the documentation it is to be set on an auto-generator target
and not on a 'standard' one like the library. As far as I can see you know
the input and output files of the desktop-to-json conversion so a custom
target should be easily doable (unlike automoc).

Andreas

Re: Triggering rebuild after changing a *.json file

By Milian Wolff at 11/23/2014 - 11:54

On Sunday 23 November 2014 10:39:02 Andreas Pakulat wrote:
That was apparently a side-effect of KDevelop using configure_file to embed
the version number in the *.desktop file. This is not required anymore with
the JSON-based plugin loading mechanism, as we install plugins into a
versioned directory path. I've changed this now and the CMake configure step
when changing a file is gone. Note that desktop_to_json already uses a custom
target internally.

This might be true, yes. Note that I just copied that line from
desktop_to_json. But note that in the ideal case, we wouldn't have any
desktop-to-json. Rather, we just have a *.json file, a *.cpp file that uses
K_PLUGIN_FACTORY_WITH_JSON. Currently, when the *.json file is changed, the
*.cpp.o is not updated, nor the plugin *.so rebuilt and thus the new strings
are not available at runtime.

This is what we need to fix somehow, and I still don't know how. Will we have
to fix this inside CMake?

Re: Triggering rebuild after changing a *.json file

By Kevin Funk at 11/23/2014 - 17:37

On Sunday 23 November 2014 17:54:21 Milian Wolff wrote:
Seems like a job for OBJECT_DEPENDS... That would require you to explicitly
name the .cpp containing the K_PLUGIN_FACTORY_WITH_JSON(...) use, though.

Something along:
SET_SOURCE_FILES_PROPERTIES(myplugin.cpp
PROPERTIES OBJECT_DEPENDS myplugin.json)

<a href="http://www.cmake.org/cmake/help/v2.8.12/cmake.html#prop_sf%3aOBJECT_DEPENDS" title="http://www.cmake.org/cmake/help/v2.8.12/cmake.html#prop_sf%3aOBJECT_DEPENDS">http://www.cmake.org/cmake/help/v2.8.12/cmake.html#prop_sf%3aOBJECT_DEPENDS</a>

Greets

PS: Thanks for providing a kdevplatform_add_plugin macro (awesome!)

Re: Triggering rebuild after changing a *.json file

By Alexander Neundorf at 11/24/2014 - 14:55

On Sunday, November 23, 2014 23:37:45 Kevin Funk wrote:
without looking at any details (and without remembering the exact details),
the OBJECT_DEPENDS property has issues, and if possible, an alternative
solution should be used.

Alex

Re: Triggering rebuild after changing a *.json file

By Kevin Funk at 11/23/2014 - 17:53

On Sunday 23 November 2014 23:37:45 Kevin Funk wrote:
Sorry for the noise. Should've read through your macro *completely*. You're
already doing this...

Re: Triggering rebuild after changing a *.json file

By Milian Wolff at 11/23/2014 - 17:48

On Sunday 23 November 2014 23:37:45 Kevin Funk wrote:
Take a look at the macro I added to KDevelop. It does that already and it is
not enough. As Volker mentions, it seems we must add the depends on the
*_moc.cpp :-/

Bye

Re: Triggering rebuild after changing a *.json file

By Volker Krause at 11/23/2014 - 03:58

On Sunday 23 November 2014 04:36:30 Milian Wolff wrote:
indeed, turns out I have the same problem in GammaRay.

moc puts it into the .moc file, so adding a dependency from the .o to the
.json doesn't help, we'd need that on the .moc file. Indeed ideally something
that CMake's automoc would add already.

The following little tool might be useful while debugging this, so you can
check the embedded JSON data without running the host application:
<a href="http://www.kdab.com/~volker/akademy/2014/qplugininfo/" title="http://www.kdab.com/~volker/akademy/2014/qplugininfo/">http://www.kdab.com/~volker/akademy/2014/qplugininfo/</a>

regards,
Volker