Dependency cycle - why?

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

Dependency cycle - why?

Bill Somerville

Hi folks,

I am struggling to understand what the problem is with this:

find_program (GO go)
set (GOPATH "${CMAKE_CURRENT_BINARY_DIR}/go")
file (MAKE_DIRECTORY ${GOPATH})

set (sources ${CMAKE_CURRENT_SOURCE_DIR}/callback_generator.go)
set (build_command ${GO} build)
set (output callback_generator${CMAKE_EXECUTABLE_SUFFIX})
add_custom_command (OUTPUT ${output}
  COMMAND ${CMAKE_COMMAND} -E env GOPATH=${GOPATH} CGO_CFLAGS=${CMAKE_CGO_CFLAGS} ${build_command} -o ${output} ${CMAKE_GO_FLAGS} ${sources}
  DEPENDS ${sources}
  VERBATIM)
add_custom_target (callback_generator_target DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output})
add_executable (callback_generator IMPORTED)
set_target_properties (callback_generator
  PROPERTIES
  IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${output}
  )
add_dependencies (callback_generator callback_generator_target)

add_custom_target (server ALL DEPENDS callback_generator)

which gives this error:

>cmake --version
cmake --version
cmake version 3.14.3

>cmake -G "MinGW Makefiles" ..\..
cmake -G "MinGW Makefiles" ..\..
-- Configuring done
CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
  "callback_generator_target" of type UTILITY
    depends on "callback_generator_target" (strong)
The component contains at least one cycle consisting of strong dependencies (created by add_dependencies) that cannot be broken.

The set_target_properties () call seems to be part of the problem but I don't understand why.

Regards
Bill Somerville.


--

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:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Dependency cycle - why?

Bill Somerville
On 13/05/2019 12:03, Bill Somerville wrote:

Hi folks,

I am struggling to understand what the problem is with this:

find_program (GO go)
set (GOPATH "${CMAKE_CURRENT_BINARY_DIR}/go")
file (MAKE_DIRECTORY ${GOPATH})

set (sources ${CMAKE_CURRENT_SOURCE_DIR}/callback_generator.go)
set (build_command ${GO} build)
set (output callback_generator${CMAKE_EXECUTABLE_SUFFIX})
add_custom_command (OUTPUT ${output}
  COMMAND ${CMAKE_COMMAND} -E env GOPATH=${GOPATH} CGO_CFLAGS=${CMAKE_CGO_CFLAGS} ${build_command} -o ${output} ${CMAKE_GO_FLAGS} ${sources}
  DEPENDS ${sources}
  VERBATIM)
add_custom_target (callback_generator_target DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output})
add_executable (callback_generator IMPORTED)
set_target_properties (callback_generator
  PROPERTIES
  IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${output}
  )
add_dependencies (callback_generator callback_generator_target)

add_custom_target (server ALL DEPENDS callback_generator)

which gives this error:

>cmake --version
cmake --version
cmake version 3.14.3

>cmake -G "MinGW Makefiles" ..\..
cmake -G "MinGW Makefiles" ..\..
-- Configuring done
CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
  "callback_generator_target" of type UTILITY
    depends on "callback_generator_target" (strong)
The component contains at least one cycle consisting of strong dependencies (created by add_dependencies) that cannot be broken.

The set_target_properties () call seems to be part of the problem but I don't understand why.

Regards
Bill Somerville.

Hi again,

answering my own post since no one has replied. Clearly my question was too specific. Let me try again with a more general question. I have tools that can generate executables (programs, static libraries, and shared libraries, including DLL import libraries on MS Windows). These tools are not directly supported by CMake but they are both needed within a project that uses them and installs them as the project artefacts. How do I integrate, for example a shared library, into a CMake project as if it were produced by a supported toolchain like C or C++? The library is produced by an add_custom_target() command (not add_custom_command() since the underlying tools do their own dependency checking so it is right to run the target commands every build). I need to have a target that I can use in target_link_libraries() and install(TARGETS ...) just like one would with a CMake generated library made with add_library() and programs made with add_executable().

If it helps the tools that are not supported by CMake are the Go language build tools. The project builds some Go programs as utilities but the main project artefact is a shared library with a C language API built using the cgo tools. There are many of C and C++ test programs and example programs as well in the project which need to link against the project shared library etc.

Regards
Bill Somerville.


--

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:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Dependency cycle - why?

CMake mailing list
Hi,

The goal that you have is fully supported by CMake. You have just run
into a bug in CMake, and you should report this to
https://gitlab.kitware.com/cmake/cmake/issues .
Basically at a very high level the name out the add_executable target
`callback_generator` is the same as the internal name that CMake is
using for the add_custom_command. This than causes some logic in CMake
(cmTargetTraceDependencies) to incorrectly build another link between
the add_custom_command and your add_executable.

The easiest way to solve this issue is name the add_executable target
to have a different name than the output of your custom command minus
file extension. So maybe something like  `callback_generator_exec`

On Fri, May 24, 2019 at 2:02 PM Bill Somerville <[hidden email]> wrote:

>
> On 13/05/2019 12:03, Bill Somerville wrote:
>
> Hi folks,
>
> I am struggling to understand what the problem is with this:
>
> find_program (GO go)
> set (GOPATH "${CMAKE_CURRENT_BINARY_DIR}/go")
> file (MAKE_DIRECTORY ${GOPATH})
>
> set (sources ${CMAKE_CURRENT_SOURCE_DIR}/callback_generator.go)
> set (build_command ${GO} build)
> set (output callback_generator${CMAKE_EXECUTABLE_SUFFIX})
> add_custom_command (OUTPUT ${output}
>   COMMAND ${CMAKE_COMMAND} -E env GOPATH=${GOPATH} CGO_CFLAGS=${CMAKE_CGO_CFLAGS} ${build_command} -o ${output} ${CMAKE_GO_FLAGS} ${sources}
>   DEPENDS ${sources}
>   VERBATIM)
> add_custom_target (callback_generator_target DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output})
> add_executable (callback_generator IMPORTED)
> set_target_properties (callback_generator
>   PROPERTIES
>   IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${output}
>   )
> add_dependencies (callback_generator callback_generator_target)
>
> add_custom_target (server ALL DEPENDS callback_generator)
>
> which gives this error:
>
> >cmake --version
> cmake --version
> cmake version 3.14.3
>
> >cmake -G "MinGW Makefiles" ..\..
> cmake -G "MinGW Makefiles" ..\..
> -- Configuring done
> CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
>   "callback_generator_target" of type UTILITY
>     depends on "callback_generator_target" (strong)
> The component contains at least one cycle consisting of strong dependencies (created by add_dependencies) that cannot be broken.
>
> The set_target_properties () call seems to be part of the problem but I don't understand why.
>
> Regards
> Bill Somerville.
>
> Hi again,
>
> answering my own post since no one has replied. Clearly my question was too specific. Let me try again with a more general question. I have tools that can generate executables (programs, static libraries, and shared libraries, including DLL import libraries on MS Windows). These tools are not directly supported by CMake but they are both needed within a project that uses them and installs them as the project artefacts. How do I integrate, for example a shared library, into a CMake project as if it were produced by a supported toolchain like C or C++? The library is produced by an add_custom_target() command (not add_custom_command() since the underlying tools do their own dependency checking so it is right to run the target commands every build). I need to have a target that I can use in target_link_libraries() and install(TARGETS ...) just like one would with a CMake generated library made with add_library() and programs made with add_executable().
>
> If it helps the tools that are not supported by CMake are the Go language build tools. The project builds some Go programs as utilities but the main project artefact is a shared library with a C language API built using the cgo tools. There are many of C and C++ test programs and example programs as well in the project which need to link against the project shared library etc.
>
> Regards
> Bill Somerville.
>
> --
>
> 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:
> https://cmake.org/mailman/listinfo/cmake
--

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:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Dependency cycle - why?

Bill Somerville
Hi Robert,

thanks for that, the target name change does seem to help but I am still unable to achieve my goal. Here is a simplified example that demonstrates the problem:
cmake_minimum_required (VERSION  3.1.0 FATAL_ERROR)
project (demo LANGUAGES NONE)
add_custom_target (prog_target COMMAND ${CMAKE_COMMAND} -E touch prog${CMAKE_EXECUTABLE_SUFFIX})
add_executable (prog IMPORTED)
add_dependencies (prog prog_target)
set_target_properties (prog PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/prog${CMAKE_EXECUTABLE_SUFFIX})
install (TARGETS prog RUNTIME DESTINATION bin)
which gives the following error at CMake configuration:
CMake Error at CMakeLists.txt:7 (install):
  install TARGETS given target "prog" which does not exist.


-- Configuring incomplete, errors occurred!
So the target that 'add_executable(name IMPORTED)' creates is not a real executable target. I can change its properties but the 'install(TARGETS ...)' command thinks it does not exist. Note that a executable target is a very simple demonstration and I understand that I can use 'install(PROGRAM ...)' just about as easily, but when it comes to a shared library it gets a lot more complex when using, exporting, and instlling it, and it seems that IMPORTED targets fall well short of useful when they are actually produced by the current CMake project.

I can understand that an IMPORTED target is perhaps not meant to be installable but if so then your statement that "The goal that you have is fully supported by CMake" seems to be incorrect. To reiterate, I am trying to use foreign tools to make binary targets and wish to have CMake treat them *as if* they were created by supported languages like C, ++, or Fortran. Am I still missing something?

Regards
Bill Somerville.

On 24/05/2019 20:23, Robert Maynard wrote:
Hi,

The goal that you have is fully supported by CMake. You have just run
into a bug in CMake, and you should report this to
https://gitlab.kitware.com/cmake/cmake/issues .
Basically at a very high level the name out the add_executable target
`callback_generator` is the same as the internal name that CMake is
using for the add_custom_command. This than causes some logic in CMake
(cmTargetTraceDependencies) to incorrectly build another link between
the add_custom_command and your add_executable.

The easiest way to solve this issue is name the add_executable target
to have a different name than the output of your custom command minus
file extension. So maybe something like  `callback_generator_exec`

On Fri, May 24, 2019 at 2:02 PM Bill Somerville [hidden email] wrote:
On 13/05/2019 12:03, Bill Somerville wrote:

Hi folks,

I am struggling to understand what the problem is with this:

find_program (GO go)
set (GOPATH "${CMAKE_CURRENT_BINARY_DIR}/go")
file (MAKE_DIRECTORY ${GOPATH})

set (sources ${CMAKE_CURRENT_SOURCE_DIR}/callback_generator.go)
set (build_command ${GO} build)
set (output callback_generator${CMAKE_EXECUTABLE_SUFFIX})
add_custom_command (OUTPUT ${output}
  COMMAND ${CMAKE_COMMAND} -E env GOPATH=${GOPATH} CGO_CFLAGS=${CMAKE_CGO_CFLAGS} ${build_command} -o ${output} ${CMAKE_GO_FLAGS} ${sources}
  DEPENDS ${sources}
  VERBATIM)
add_custom_target (callback_generator_target DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output})
add_executable (callback_generator IMPORTED)
set_target_properties (callback_generator
  PROPERTIES
  IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${output}
  )
add_dependencies (callback_generator callback_generator_target)

add_custom_target (server ALL DEPENDS callback_generator)

which gives this error:

cmake --version
cmake --version
cmake version 3.14.3

cmake -G "MinGW Makefiles" ..\..
cmake -G "MinGW Makefiles" ..\..
-- Configuring done
CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
  "callback_generator_target" of type UTILITY
    depends on "callback_generator_target" (strong)
The component contains at least one cycle consisting of strong dependencies (created by add_dependencies) that cannot be broken.

The set_target_properties () call seems to be part of the problem but I don't understand why.

Regards
Bill Somerville.

Hi again,

answering my own post since no one has replied. Clearly my question was too specific. Let me try again with a more general question. I have tools that can generate executables (programs, static libraries, and shared libraries, including DLL import libraries on MS Windows). These tools are not directly supported by CMake but they are both needed within a project that uses them and installs them as the project artefacts. How do I integrate, for example a shared library, into a CMake project as if it were produced by a supported toolchain like C or C++? The library is produced by an add_custom_target() command (not add_custom_command() since the underlying tools do their own dependency checking so it is right to run the target commands every build). I need to have a target that I can use in target_link_libraries() and install(TARGETS ...) just like one would with a CMake generated library made with add_library() and programs made with add_executable().

If it helps the tools that are not supported by CMake are the Go language build tools. The project builds some Go programs as utilities but the main project artefact is a shared library with a C language API built using the cgo tools. There are many of C and C++ test programs and example programs as well in the project which need to link against the project shared library etc.

Regards
Bill Somerville.

--

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:
https://cmake.org/mailman/listinfo/cmake



--

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:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Dependency cycle - why?

CMake mailing list


Le sam. 25 mai 2019 à 13:51, Bill Somerville <[hidden email]> a écrit :
Hi Robert,

thanks for that, the target name change does seem to help but I am still unable to achieve my goal. Here is a simplified example that demonstrates the problem:
cmake_minimum_required (VERSION  3.1.0 FATAL_ERROR)
project (demo LANGUAGES NONE)
add_custom_target (prog_target COMMAND ${CMAKE_COMMAND} -E touch prog${CMAKE_EXECUTABLE_SUFFIX})
add_executable (prog IMPORTED)
add_dependencies (prog prog_target)
set_target_properties (prog PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/prog${CMAKE_EXECUTABLE_SUFFIX})
install (TARGETS prog RUNTIME DESTINATION bin)
which gives the following error at CMake configuration:
CMake Error at CMakeLists.txt:7 (install):
  install TARGETS given target "prog" which does not exist.


-- Configuring incomplete, errors occurred!
So the target that 'add_executable(name IMPORTED)' creates is not a real executable target. I can change its properties but the 'install(TARGETS ...)' command thinks it does not exist. Note that a executable target is a very simple demonstration and I understand that I can use 'install(PROGRAM ...)' just about as easily, but when it comes to a shared library it gets a lot more complex when using, exporting, and instlling it, and it seems that IMPORTED targets fall well short of useful when they are actually produced by the current CMake project.

I can understand that an IMPORTED target is perhaps not meant to be installable

Robert will give his advice on that but I bet IMPORTED target were never meant to be drop-in *replacement* of genuine target.

They were meant to ease *reference to* object/lib:executable that are outside the build of the project.
"An IMPORTED library target references a library file located outside the project"

Nmelly a target that is "already installed somewhere" and that you want to reference in your CMake build.
 
but if so then your statement that "The goal that you have is fully supported by CMake" seems to be incorrect. To reiterate, I am trying to use foreign tools to make binary targets and wish to have CMake treat them *as if* they were created by supported languages like C, ++, or Fortran. Am I still missing something?

My opinion is that IMPORTED target are not designed (as of today) for that purpose.

When you want to do what you seem to want you need to either:
1) add a "new LANGUAGE" (you seem to be willing to add golang)
    and may be: https://github.com/aadidenko/golang-cmake-example (or fork of this)

2) define a set of custom macros that mimic genuine target behaviour.

If you want to have a look at existing similar example shippped with CMake, have a look at UseJava.cmake module (https://cmake.org/cmake/help/latest/module/UseJava.html)
You'll see that you have 
add_jar, which is similar to add_executable and create a custom target
and
install_jar which is similar to install on genuine target but plays with target properties and install(FILES...) in order to mimic that.

I'm not developing with golang but AFAIK go has a builtin "build system" so bringing go as a language in CMake may not be the best option,
but again I am no Go expert.

The only reference of that kind of thing I found in the CMake mailing list is oldish:

May be adding the support for "install" command for IMPORTED target is doable but this seems to be a feature request to be discussed on developer mailing list;
Regards,
Eric


Regards
Bill Somerville.

On 24/05/2019 20:23, Robert Maynard wrote:
Hi,

The goal that you have is fully supported by CMake. You have just run
into a bug in CMake, and you should report this to
https://gitlab.kitware.com/cmake/cmake/issues .
Basically at a very high level the name out the add_executable target
`callback_generator` is the same as the internal name that CMake is
using for the add_custom_command. This than causes some logic in CMake
(cmTargetTraceDependencies) to incorrectly build another link between
the add_custom_command and your add_executable.

The easiest way to solve this issue is name the add_executable target
to have a different name than the output of your custom command minus
file extension. So maybe something like  `callback_generator_exec`

On Fri, May 24, 2019 at 2:02 PM Bill Somerville [hidden email] wrote:
On 13/05/2019 12:03, Bill Somerville wrote:

Hi folks,

I am struggling to understand what the problem is with this:

find_program (GO go)
set (GOPATH "${CMAKE_CURRENT_BINARY_DIR}/go")
file (MAKE_DIRECTORY ${GOPATH})

set (sources ${CMAKE_CURRENT_SOURCE_DIR}/callback_generator.go)
set (build_command ${GO} build)
set (output callback_generator${CMAKE_EXECUTABLE_SUFFIX})
add_custom_command (OUTPUT ${output}
  COMMAND ${CMAKE_COMMAND} -E env GOPATH=${GOPATH} CGO_CFLAGS=${CMAKE_CGO_CFLAGS} ${build_command} -o ${output} ${CMAKE_GO_FLAGS} ${sources}
  DEPENDS ${sources}
  VERBATIM)
add_custom_target (callback_generator_target DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output})
add_executable (callback_generator IMPORTED)
set_target_properties (callback_generator
  PROPERTIES
  IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${output}
  )
add_dependencies (callback_generator callback_generator_target)

add_custom_target (server ALL DEPENDS callback_generator)

which gives this error:

cmake --version
cmake --version
cmake version 3.14.3

cmake -G "MinGW Makefiles" ..\..
cmake -G "MinGW Makefiles" ..\..
-- Configuring done
CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
  "callback_generator_target" of type UTILITY
    depends on "callback_generator_target" (strong)
The component contains at least one cycle consisting of strong dependencies (created by add_dependencies) that cannot be broken.

The set_target_properties () call seems to be part of the problem but I don't understand why.

Regards
Bill Somerville.

Hi again,

answering my own post since no one has replied. Clearly my question was too specific. Let me try again with a more general question. I have tools that can generate executables (programs, static libraries, and shared libraries, including DLL import libraries on MS Windows). These tools are not directly supported by CMake but they are both needed within a project that uses them and installs them as the project artefacts. How do I integrate, for example a shared library, into a CMake project as if it were produced by a supported toolchain like C or C++? The library is produced by an add_custom_target() command (not add_custom_command() since the underlying tools do their own dependency checking so it is right to run the target commands every build). I need to have a target that I can use in target_link_libraries() and install(TARGETS ...) just like one would with a CMake generated library made with add_library() and programs made with add_executable().

If it helps the tools that are not supported by CMake are the Go language build tools. The project builds some Go programs as utilities but the main project artefact is a shared library with a C language API built using the cgo tools. There are many of C and C++ test programs and example programs as well in the project which need to link against the project shared library etc.

Regards
Bill Somerville.

--

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:
https://cmake.org/mailman/listinfo/cmake


--

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:
https://cmake.org/mailman/listinfo/cmake


--
Eric

--

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:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Dependency cycle - why?

Bill Somerville
Hi Eric,

thanks for the comprehensive reply to my query. My follow up comments in line below.

On 25/05/2019 15:47, Eric Noulard wrote:
Le sam. 25 mai 2019 à 13:51, Bill Somerville <[hidden email]> a écrit :
Hi Robert,

thanks for that, the target name change does seem to help but I am still unable to achieve my goal. Here is a simplified example that demonstrates the problem:
cmake_minimum_required (VERSION  3.1.0 FATAL_ERROR)
project (demo LANGUAGES NONE)
add_custom_target (prog_target COMMAND ${CMAKE_COMMAND} -E touch prog${CMAKE_EXECUTABLE_SUFFIX})
add_executable (prog IMPORTED)
add_dependencies (prog prog_target)
set_target_properties (prog PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/prog${CMAKE_EXECUTABLE_SUFFIX})
install (TARGETS prog RUNTIME DESTINATION bin)
which gives the following error at CMake configuration:
CMake Error at CMakeLists.txt:7 (install):
  install TARGETS given target "prog" which does not exist.


-- Configuring incomplete, errors occurred!
So the target that 'add_executable(name IMPORTED)' creates is not a real executable target. I can change its properties but the 'install(TARGETS ...)' command thinks it does not exist. Note that a executable target is a very simple demonstration and I understand that I can use 'install(PROGRAM ...)' just about as easily, but when it comes to a shared library it gets a lot more complex when using, exporting, and instlling it, and it seems that IMPORTED targets fall well short of useful when they are actually produced by the current CMake project.

I can understand that an IMPORTED target is perhaps not meant to be installable

Robert will give his advice on that but I bet IMPORTED target were never meant to be drop-in *replacement* of genuine target.

They were meant to ease *reference to* object/lib:executable that are outside the build of the project.
"An IMPORTED library target references a library file located outside the project"

Nmelly a target that is "already installed somewhere" and that you want to reference in your CMake build.
That is fine but I don't see why there is a problem with making IMPORTED targets better CMake citizens, it should be down to the CMake script author as to whether they take advantage of that. What is there now is a lie and the add_*(target ... IMPORTED ...) commands are not doing what they should IMHO.
 
but if so then your statement that "The goal that you have is fully supported by CMake" seems to be incorrect. To reiterate, I am trying to use foreign tools to make binary targets and wish to have CMake treat them *as if* they were created by supported languages like C, ++, or Fortran. Am I still missing something?

My opinion is that IMPORTED target are not designed (as of today) for that purpose.
Agreed.

When you want to do what you seem to want you need to either:
1) add a "new LANGUAGE" (you seem to be willing to add golang)
    and may be: https://github.com/aadidenko/golang-cmake-example (or fork of this)
I am not sure that adding a new CMake supported language is right for Go. For the Go ecosystem the Go build tools do the right thing and CMake is largely unnecessary. Particularly the Go build system deals with dependencies internally so I don't see how it could be added to CMake without using the lower level Go tools and having to list many source dependencies that the high level Go build system deals with without fuss. Note that I am dealing with cgo which allows Go language static or shared libraries to interoperate with other languages via a C API. This is where CMake needs to join in because a project using cgo is likely to build tests, tools, and libraries in languages that CMake does support. As far as I can see the Go build system support is weak in providing a "package" from, for example, a cgo shared library, it just builds the shared object and header files and stops there.

2) define a set of custom macros that mimic genuine target behaviour.
This is exactly where I started but it only covers tools written in Go and uses install(PROGRAMS ...) to install them. It uses add_custom_command() which means all source dependencies must be specified for reliable rebuilds, which is effectively discarding the dependency management of the Go build system. It would be very fragile in a large project and doesn't address the cgo capabilities to create libraries. My queries here are exactly because I am trying to extend this approach to tools and libraries that play well in the CMake ecosystem, without sacrificing the advantages of the Go build system. I can, and have, written CMake functions that use add_custom_target() to defer Go builds to the Go build system, but am failing so far to bridge the results with CMake. Clearly at present IMPORTED targets do not work for this, so I guess I am asking how to do this another way, e.g. by setting all the necessary target properties to make my targets proper CMake citizens?

If you want to have a look at existing similar example shippped with CMake, have a look at UseJava.cmake module (https://cmake.org/cmake/help/latest/module/UseJava.html)
You'll see that you have 
add_jar, which is similar to add_executable and create a custom target
and
install_jar which is similar to install on genuine target but plays with target properties and install(FILES...) in order to mimic that.
This looks more interesting and complete but the first thing I note is that it does not really integrate with the CMake ecosystem, instead it has a parallel set of commands (add|install|find|export)_jar() that mimic the CMake equivalents. That may work well for Java, even including a foreign function interface as it seems to support JNI, but there is a key difference. A Java class file is linked purely at runtime so there is no need for CMake to know about how to link the JAR file to a native executable target (it uses add_library(target INTERFACE ...) to integrate the generated API headers). With Go and cgo the generated library *is a native library*, just as Go tools are native binaries, and to use them seamlessly in CMake they have to behave as any other imported or built executable target, a parallel set of CMake commands that do not integrate the target will not get the job done.

I'm not developing with golang but AFAIK go has a builtin "build system" so bringing go as a language in CMake may not be the best option,
but again I am no Go expert.

You are correct and this is exactly why I am looking for a way to hook the products of the Go build system into CMake rather than trying to add it as a supported language. I do not know enough abut the low level Go build system commands to understand if they are suitable for driving from CMake like it does for C, C++, or Fortran compilers and the target system linker but that seems to be the wrong approach, I'd rather use the top level 'go build' command and tell CMake about what I expect it to build and what top level targets I want to be up to date before that step. This seems to be a simple add_custom_target() invocation. There is a small penalty that the 'go build' command will always run but that's fine since I expect 'go build' to do minimal re-builds based on its own dependency tracking.

The approach I am current trying is to treat cgo libraries as INTERFACE libraries and having my CMake scripts reference the library binaries by their path by misusing target_link_libraries(so_library_target INTERFACE ...) to hook things up. This doesn't help with installing the library target but that can be done using install(PROGRAMS ...). That at least allows install(EXPORT ...) to work, I think - I have not yet tried importing the shared library into anther CMake project.


The only reference of that kind of thing I found in the CMake mailing list is oldish:
That link shows exactly why using the Go build tools as a custom target command is right IMHO, it also doesn't address using the product of the build in the same or other projects.

May be adding the support for "install" command for IMPORTED target is doable but this seems to be a feature request to be discussed on developer mailing list;

I think there is justification since a CMake script author decides whether to take advantage of it. It seems to me that there is stuff that is internal to the CMake C++ application similar to properties but not addressable by the script author. Of course it all depends how complex that stuff is and whether if can be addressed by either some new target properties or extra arguments to the add_(executable|library)(target IMPORTED) commands. The latter seems easiest as the internal logic and data model need not be exposed for misuse by script authors.

If there really is not a practical way to build a library or tool with a foreign toolchain in CMake and have it integrated like the ones produced by supported languages then I will raise an issue on the development forum, but TBH I am disappointed that manipulating existing target properties is not sufficient. Custom targets seem to fall well short of what they promise.

Regards,
Eric
Regards
Bill Somerville.




Regards
Bill Somerville.

On 24/05/2019 20:23, Robert Maynard wrote:
Hi,

The goal that you have is fully supported by CMake. You have just run
into a bug in CMake, and you should report this to
https://gitlab.kitware.com/cmake/cmake/issues .
Basically at a very high level the name out the add_executable target
`callback_generator` is the same as the internal name that CMake is
using for the add_custom_command. This than causes some logic in CMake
(cmTargetTraceDependencies) to incorrectly build another link between
the add_custom_command and your add_executable.

The easiest way to solve this issue is name the add_executable target
to have a different name than the output of your custom command minus
file extension. So maybe something like  `callback_generator_exec`



--

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:
https://cmake.org/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: Dependency cycle - why?

CMake mailing list
In reply to this post by CMake mailing list
I misspoke. I meant that what you want to do with the custom commands
was supported by CMake.

Adding support for extra languages to CMake requires modifications at
the C++ level, if you want full support. Things such as installing,
and generator expressions require C++ level changes.

On Sat, May 25, 2019 at 10:47 AM Eric Noulard <[hidden email]> wrote:

>
>
>
> Le sam. 25 mai 2019 à 13:51, Bill Somerville <[hidden email]> a écrit :
>>
>> Hi Robert,
>>
>> thanks for that, the target name change does seem to help but I am still unable to achieve my goal. Here is a simplified example that demonstrates the problem:
>>
>> cmake_minimum_required (VERSION  3.1.0 FATAL_ERROR)
>> project (demo LANGUAGES NONE)
>> add_custom_target (prog_target COMMAND ${CMAKE_COMMAND} -E touch prog${CMAKE_EXECUTABLE_SUFFIX})
>> add_executable (prog IMPORTED)
>> add_dependencies (prog prog_target)
>> set_target_properties (prog PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/prog${CMAKE_EXECUTABLE_SUFFIX})
>> install (TARGETS prog RUNTIME DESTINATION bin)
>>
>> which gives the following error at CMake configuration:
>>
>> CMake Error at CMakeLists.txt:7 (install):
>>   install TARGETS given target "prog" which does not exist.
>>
>>
>> -- Configuring incomplete, errors occurred!
>>
>> So the target that 'add_executable(name IMPORTED)' creates is not a real executable target. I can change its properties but the 'install(TARGETS ...)' command thinks it does not exist. Note that a executable target is a very simple demonstration and I understand that I can use 'install(PROGRAM ...)' just about as easily, but when it comes to a shared library it gets a lot more complex when using, exporting, and instlling it, and it seems that IMPORTED targets fall well short of useful when they are actually produced by the current CMake project.
>>
>> I can understand that an IMPORTED target is perhaps not meant to be installable
>
>
> Robert will give his advice on that but I bet IMPORTED target were never meant to be drop-in *replacement* of genuine target.

That is correct. Specifically imported targets aren't meant to be
exported or installed. They are meant to represent some item that
already exists on disk, and as such you should install the logic that
constructs the imported targets.

>
> They were meant to ease *reference to* object/lib:executable that are outside the build of the project.
> e.g the doc says: https://cmake.org/cmake/help/latest/command/add_library.html#imported-libraries
> "An IMPORTED library target references a library file located outside the project"
>
> Nmelly a target that is "already installed somewhere" and that you want to reference in your CMake build.
>
>>
>> but if so then your statement that "The goal that you have is fully supported by CMake" seems to be incorrect. To reiterate, I am trying to use foreign tools to make binary targets and wish to have CMake treat them *as if* they were created by supported languages like C, ++, or Fortran. Am I still missing something?
>
>
> My opinion is that IMPORTED target are not designed (as of today) for that purpose.
>
> When you want to do what you seem to want you need to either:
> 1) add a "new LANGUAGE" (you seem to be willing to add golang)
>     see: https://stackoverflow.com/questions/7978517/how-do-i-get-cmake-to-work-with-the-go-programming-language
>     and may be: https://github.com/aadidenko/golang-cmake-example (or fork of this)
>
> 2) define a set of custom macros that mimic genuine target behaviour.
>     may be see: https://github.com/cpconduce/go_cmake
>
> If you want to have a look at existing similar example shippped with CMake, have a look at UseJava.cmake module (https://cmake.org/cmake/help/latest/module/UseJava.html)
> You'll see that you have
> add_jar, which is similar to add_executable and create a custom target
> and
> install_jar which is similar to install on genuine target but plays with target properties and install(FILES...) in order to mimic that.
> see: https://github.com/Kitware/CMake/blob/master/Modules/UseJava.cmake
>
> I'm not developing with golang but AFAIK go has a builtin "build system" so bringing go as a language in CMake may not be the best option,
> but again I am no Go expert.
>
> The only reference of that kind of thing I found in the CMake mailing list is oldish:
> https://cmake.org/pipermail/cmake-developers/2011-August/013715.html
>
> May be adding the support for "install" command for IMPORTED target is doable but this seems to be a feature request to be discussed on developer mailing list;
> Regards,
> Eric
>
>>
>> Regards
>> Bill Somerville.
>>
>> On 24/05/2019 20:23, Robert Maynard wrote:
>>
>> Hi,
>>
>> The goal that you have is fully supported by CMake. You have just run
>> into a bug in CMake, and you should report this to
>> https://gitlab.kitware.com/cmake/cmake/issues .
>> Basically at a very high level the name out the add_executable target
>> `callback_generator` is the same as the internal name that CMake is
>> using for the add_custom_command. This than causes some logic in CMake
>> (cmTargetTraceDependencies) to incorrectly build another link between
>> the add_custom_command and your add_executable.
>>
>> The easiest way to solve this issue is name the add_executable target
>> to have a different name than the output of your custom command minus
>> file extension. So maybe something like  `callback_generator_exec`
>>
>> On Fri, May 24, 2019 at 2:02 PM Bill Somerville <[hidden email]> wrote:
>>
>> On 13/05/2019 12:03, Bill Somerville wrote:
>>
>> Hi folks,
>>
>> I am struggling to understand what the problem is with this:
>>
>> find_program (GO go)
>> set (GOPATH "${CMAKE_CURRENT_BINARY_DIR}/go")
>> file (MAKE_DIRECTORY ${GOPATH})
>>
>> set (sources ${CMAKE_CURRENT_SOURCE_DIR}/callback_generator.go)
>> set (build_command ${GO} build)
>> set (output callback_generator${CMAKE_EXECUTABLE_SUFFIX})
>> add_custom_command (OUTPUT ${output}
>>   COMMAND ${CMAKE_COMMAND} -E env GOPATH=${GOPATH} CGO_CFLAGS=${CMAKE_CGO_CFLAGS} ${build_command} -o ${output} ${CMAKE_GO_FLAGS} ${sources}
>>   DEPENDS ${sources}
>>   VERBATIM)
>> add_custom_target (callback_generator_target DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${output})
>> add_executable (callback_generator IMPORTED)
>> set_target_properties (callback_generator
>>   PROPERTIES
>>   IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${output}
>>   )
>> add_dependencies (callback_generator callback_generator_target)
>>
>> add_custom_target (server ALL DEPENDS callback_generator)
>>
>> which gives this error:
>>
>> cmake --version
>>
>> cmake --version
>> cmake version 3.14.3
>>
>> cmake -G "MinGW Makefiles" ..\..
>>
>> cmake -G "MinGW Makefiles" ..\..
>> -- Configuring done
>> CMake Error: The inter-target dependency graph contains the following strongly connected component (cycle):
>>   "callback_generator_target" of type UTILITY
>>     depends on "callback_generator_target" (strong)
>> The component contains at least one cycle consisting of strong dependencies (created by add_dependencies) that cannot be broken.
>>
>> The set_target_properties () call seems to be part of the problem but I don't understand why.
>>
>> Regards
>> Bill Somerville.
>>
>> Hi again,
>>
>> answering my own post since no one has replied. Clearly my question was too specific. Let me try again with a more general question. I have tools that can generate executables (programs, static libraries, and shared libraries, including DLL import libraries on MS Windows). These tools are not directly supported by CMake but they are both needed within a project that uses them and installs them as the project artefacts. How do I integrate, for example a shared library, into a CMake project as if it were produced by a supported toolchain like C or C++? The library is produced by an add_custom_target() command (not add_custom_command() since the underlying tools do their own dependency checking so it is right to run the target commands every build). I need to have a target that I can use in target_link_libraries() and install(TARGETS ...) just like one would with a CMake generated library made with add_library() and programs made with add_executable().
>>
>> If it helps the tools that are not supported by CMake are the Go language build tools. The project builds some Go programs as utilities but the main project artefact is a shared library with a C language API built using the cgo tools. There are many of C and C++ test programs and example programs as well in the project which need to link against the project shared library etc.
>>
>> Regards
>> Bill Somerville.
>>
>> --
>>
>> 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:
>> https://cmake.org/mailman/listinfo/cmake
>>
>>
>> --
>>
>> 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:
>> https://cmake.org/mailman/listinfo/cmake
>
>
>
> --
> Eric
--

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:
https://cmake.org/mailman/listinfo/cmake