INTERFACE library and path to source.

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

INTERFACE library and path to source.

Eric Noulard
Hi there,

I encounter a weird issue with header-only library.

Somewhere in my source tree I have an header library which consist in a bunch of headers:

The concerned CMakeLists.txt looks like this:

add_library(MyHeaderLIB INTERFACE)

target_include_directories(MyHeaderLIB INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR})

target_sources(MyHeaderLIB INTERFACE
  whatever.h)


Somewhere else (in another directory) I have another CMakeLists.txt:

add_executable(myexe myexe.cpp)
target_link_libraries(myexe MyHeaderLIB)

and CMake complains when processing it that he cannot find "whatever.h"...

The problem disappear if I use full path in target_source, i.e.:

target_sources(MyHeaderLIB INTERFACE
 ${CMAKE_CURRENT_SOURCE_DIR}/whatever.h)


Why should I do that?
I this the expected behavior / way to create header only library?


--
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:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: INTERFACE library and path to source.

Oleksii Vilchanskyi
Hello Eric,

> Why should I do that?
> Is this the expected behavior / way to create header only library?

Yes, this is the expected behaviour. CMake interprets a relative path to
the file according to the target's add_library() or add_executable()
call directory. I will provide a minimal, reproducible example:

> .
> ├── CMakeLists.txt
> ├── lib
> │   ├── CMakeLists.txt
> │   └── lib.h
> └── main
>     ├── CMakeLists.txt
>     └── main.c

First listfile:

> cmake_minimum_required(VERSION 3.10)
> project(main LANGUAGES C)
> add_subdirectory(lib)
> add_subdirectory(main)

Listfile under `lib`:

> add_library(lib INTERFACE)
> target_include_directories(lib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
> target_sources(lib INTERFACE "lib.h")

Listfile under `main`:

> add_executable(main "main.c")
> target_link_libraries(main PRIVATE lib)

Now, let's look at the diagnostics:

> CMake Error at main/CMakeLists.txt:1 (add_executable):
>   Cannot find source file:
>
>     lib.h

So, the problem occurs when CMake cannot find `lib.h` relatively to
`add_executable(main "main.c")` call. Whether it's the expected
behaviour is debatable (I personally would prefer CMake to search
relatively to `add_library(lib INTERFACE)`), and the documentation is
silent on this caveat either, so there's that.

One way to solve this is to provide a path to `lib.h` relatively to
`main` directory, another way is to provide a full path.
On 12/8/17 4:42 PM, Eric Noulard wrote:

> Hi there,
>
> I encounter a weird issue with header-only library.
>
> Somewhere in my source tree I have an header library which consist in a
> bunch of headers:
>
> The concerned CMakeLists.txt looks like this:
>
> add_library(MyHeaderLIB INTERFACE)
>
> target_include_directories(MyHeaderLIB INTERFACE
>     ${CMAKE_CURRENT_SOURCE_DIR})
>
> target_sources(MyHeaderLIB INTERFACE
>   whatever.h)
>
>
> Somewhere else (in another directory) I have another CMakeLists.txt:
>
> add_executable(myexe myexe.cpp)
> target_link_libraries(myexe MyHeaderLIB)
>
> and CMake complains when processing it that he cannot find "whatever.h"...
>
> The problem disappear if I use full path in target_source, i.e.:
>
> target_sources(MyHeaderLIB INTERFACE
>  ${CMAKE_CURRENT_SOURCE_DIR}/whatever.h)
>
>
> Why should I do that?
> I this the expected behavior / way to create header only library?
>
>
> --
> Eric
>
>
--
Regards,
Oleksii Vilchanskyi
PGP:0x8D3A0E046BDE941F2A53867CE3FD952D48C0B338

***
All the world's a pipeline,
And all the men and women merely instructions.


--

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

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: INTERFACE library and path to source.

Eric Noulard


2017-12-09 1:37 GMT+01:00 Oleksii Vilchanskyi <[hidden email]>:
Hello Eric,

> Why should I do that?
> Is this the expected behavior / way to create header only library?

Yes, this is the expected behaviour. CMake interprets a relative path to
the file according to the target's add_library() or add_executable()
call directory. I will provide a minimal, reproducible example:

Hi Oleksii,

Thanks you for the minimal reproducible example.
I'm bot that sure that this is the "expected" behavior
 
Listfile under `lib`:

> add_library(lib INTERFACE)
> target_include_directories(lib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
> target_sources(lib INTERFACE "lib.h")

With the previous one would expect that any target linking to this interface target
will be provided with the include directories provided in its interface.
In your case (and in mine too) this is given with **full path**
 

Listfile under `main`:

> add_executable(main "main.c")
> target_link_libraries(main PRIVATE lib)

Now, let's look at the diagnostics:

> CMake Error at main/CMakeLists.txt:1 (add_executable):
>   Cannot find source file:
>
>     lib.h

So, the problem occurs when CMake cannot find `lib.h` relatively to
`add_executable(main "main.c")` call. Whether it's the expected
behaviour is debatable (I personally would prefer CMake to search
relatively to `add_library(lib INTERFACE)`), and the documentation is
silent on this caveat either, so there's that.

Yes precisely. This seems to work OK for imported targets but not for
header-only in-project lib.
 

One way to solve this is to provide a path to `lib.h` relatively to
`main` directory, another way is to provide a full path.

We (you and me) already provide 
 target_include_directories
with full path.

I cannot provide the file themselves with relative path since they may be used
from different place.

I guess I will open an issue unless someone explain me the rational behind that behavior.


--
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:
http://public.kitware.com/mailman/listinfo/cmake
Reply | Threaded
Open this post in threaded view
|

Re: INTERFACE library and path to source.

Oleksii Vilchanskyi
> I'm not that sure that this is the "expected" behavior

Yes, now it looks like a bug to me, too. Being written as it was in the
last message,
> target_sources(lib INTERFACE lib.h)
can be treated as the equivalent of
> target_sources(main PRIVATE lib.h)
(and therefore generating an error).

However,
> target_include_directories(lib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
on the command line resolves to
> -I/home/l2y/<...>/lib
and
> target_include_directories(lib INTERFACE ".")
resolves to
> -I/home/l2y/<...>/lib/.

Also, looking at `<build_dir>/main/CMakeFiles/main.dir/depend.internal`:

> main/CMakeFiles/main.dir/main.c.o
>  ../lib/lib.h
>  /home/l2y/<...>/main/main.c
So, all elements in `target_include_directories()` resolve to full
paths, as well as `target_sources()`, while `target_sources(INTERFACE)`
stay relative, which causes trouble.

On 11.12.2017 09:20, Eric Noulard wrote:

>
>
> 2017-12-09 1:37 GMT+01:00 Oleksii Vilchanskyi
> <[hidden email] <mailto:[hidden email]>>:
>
>     Hello Eric,
>
>     > Why should I do that?
>     > Is this the expected behavior / way to create header only library?
>
>     Yes, this is the expected behaviour. CMake interprets a relative path to
>     the file according to the target's add_library() or add_executable()
>     call directory. I will provide a minimal, reproducible example:
>
>
> Hi Oleksii,
>
> Thanks you for the minimal reproducible example.
> I'm bot that sure that this is the "expected" behavior
>  
>
>     Listfile under `lib`:
>
>     > add_library(lib INTERFACE)
>     > target_include_directories(lib INTERFACE
>     "${CMAKE_CURRENT_SOURCE_DIR}")
>     > target_sources(lib INTERFACE "lib.h")
>
>
> With the previous one would expect that any target linking to this
> interface target
> will be provided with the include directories provided in its interface.
> In your case (and in mine too) this is given with **full path**
>  
>
>
>     Listfile under `main`:
>
>     > add_executable(main "main.c")
>     > target_link_libraries(main PRIVATE lib)
>
>     Now, let's look at the diagnostics:
>
>     > CMake Error at main/CMakeLists.txt:1 (add_executable):
>     >   Cannot find source file:
>     >
>     >     lib.h
>
>     So, the problem occurs when CMake cannot find `lib.h` relatively to
>     `add_executable(main "main.c")` call. Whether it's the expected
>     behaviour is debatable (I personally would prefer CMake to search
>     relatively to `add_library(lib INTERFACE)`), and the documentation is
>     silent on this caveat either, so there's that.
>
>
> Yes precisely. This seems to work OK for imported targets but not for
> header-only in-project lib.
>  
>
>
>     One way to solve this is to provide a path to `lib.h` relatively to
>     `main` directory, another way is to provide a full path.
>
>
> We (you and me) already provide 
>  target_include_directories
> with full path.
>
> I cannot provide the file themselves with relative path since they may
> be used
> from different place.
>
> I guess I will open an issue unless someone explain me the rational
> behind that behavior.
>
>
> --
> Eric
--
Regards,
Oleksii Vilchanskyi
PGP:0x8D3A0E046BDE941F2A53867CE3FD952D48C0B338


--

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

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: INTERFACE library and path to source.

Eric Noulard

2017-12-11 15:12 GMT+01:00 Oleksii Vilchanskyi <[hidden email]>:
> I'm not that sure that this is the "expected" behavior

Yes, now it looks like a bug to me, too. Being written as it was in the
last message,
> target_sources(lib INTERFACE lib.h)
can be treated as the equivalent of
> target_sources(main PRIVATE lib.h)
(and therefore generating an error).

However,
> target_include_directories(lib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
on the command line resolves to
> -I/home/l2y/<...>/lib
and
> target_include_directories(lib INTERFACE ".")
resolves to
> -I/home/l2y/<...>/lib/.

Also, looking at `<build_dir>/main/CMakeFiles/main.dir/depend.internal`:

> main/CMakeFiles/main.dir/main.c.o
>  ../lib/lib.h
>  /home/l2y/<...>/main/main.c
So, all elements in `target_include_directories()` resolve to full
paths, as well as `target_sources()`, while `target_sources(INTERFACE)`
stay relative, which causes trouble.

On 11.12.2017 09:20, Eric Noulard wrote:
>
>
> 2017-12-09 1:37 GMT+01:00 Oleksii Vilchanskyi
> <[hidden email] <mailto:[hidden email]>>:
>
>     Hello Eric,
>
>     > Why should I do that?
>     > Is this the expected behavior / way to create header only library?
>
>     Yes, this is the expected behaviour. CMake interprets a relative path to
>     the file according to the target's add_library() or add_executable()
>     call directory. I will provide a minimal, reproducible example:
>
>
> Hi Oleksii,
>
> Thanks you for the minimal reproducible example.
> I'm bot that sure that this is the "expected" behavior
>  
>
>     Listfile under `lib`:
>
>     > add_library(lib INTERFACE)
>     > target_include_directories(lib INTERFACE
>     "${CMAKE_CURRENT_SOURCE_DIR}")
>     > target_sources(lib INTERFACE "lib.h")
>
>
> With the previous one would expect that any target linking to this
> interface target
> will be provided with the include directories provided in its interface.
> In your case (and in mine too) this is given with **full path**
>  
>
>
>     Listfile under `main`:
>
>     > add_executable(main "main.c")
>     > target_link_libraries(main PRIVATE lib)
>
>     Now, let's look at the diagnostics:
>
>     > CMake Error at main/CMakeLists.txt:1 (add_executable):
>     >   Cannot find source file:
>     >
>     >     lib.h
>
>     So, the problem occurs when CMake cannot find `lib.h` relatively to
>     `add_executable(main "main.c")` call. Whether it's the expected
>     behaviour is debatable (I personally would prefer CMake to search
>     relatively to `add_library(lib INTERFACE)`), and the documentation is
>     silent on this caveat either, so there's that.
>
>
> Yes precisely. This seems to work OK for imported targets but not for
> header-only in-project lib.
>  
>
>
>     One way to solve this is to provide a path to `lib.h` relatively to
>     `main` directory, another way is to provide a full path.
>
>
> We (you and me) already provide 
>  target_include_directories
> with full path.
>
> I cannot provide the file themselves with relative path since they may
> be used
> from different place.
>
> I guess I will open an issue unless someone explain me the rational
> behind that behavior.
>
>
> --
> Eric

--
Regards,
Oleksii Vilchanskyi
PGP:0x8D3A0E046BDE941F2A53867CE3FD952D48C0B338




--
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:
http://public.kitware.com/mailman/listinfo/cmake