CMAKE_CURRENT_SOURCE_DIR

178 views
Skip to first unread message

Robin Rowe

unread,
Jan 11, 2018, 12:14:23 AM1/11/18
to fltkg...@googlegroups.com
I'm using DownloadProject, a cmake helper available on github, to
automatically download FLTK. That works fine, but I can't build FLTK:

1>CUSTOMBUILD : CMake error : File
C:/Code/gitlab/Cinepaint/glasgow/configh.cmake.in does not exist.
1>CMake Error at build/fltk/fltk-src/CMake/export.cmake:104

configure_file(
"${CMAKE_SOURCE_DIR}/${CONFIG_H_IN}"

That file is actually at:

C:/Code/gitlab/Cinepaint/glasgow/fltk/fltk-src/configh.cmake.in

Is export.cmake incorrect? Should it say CMAKE_CURRENT_SOURCE_DIR
instead of CMAKE_SOURCE_DIR in export.cmake? Is there a way I can fix
this without changing export.cmake?

My cmake below...

Robin

------------------------------------------------------------
#CinePaint FLTK.cmake
set(NAME "fltk")
project(${NAME})
message("--- Building " ${NAME} " ---")

set(PATH_FLTK "${CMAKE_BINARY_DIR}/fltk")
set(URL_FLTK "http://fltk.org/pub/fltk/snapshots/fltk-1.4.x-r12602.tar.gz")

if(WIN32)
add_definitions(-DWIN32)
endif()

set(OPTION_USE_SYSTEM_LIBPNG OFF)
link_directories("${PATH_FLTK}/build/lib/Debug")
include_directories(
${CMAKE_BINARY_DIR}/fltk/fltk-src
${CMAKE_BINARY_DIR}/fltk/fltk-build )

if(NOT IS_DIRECTORY "${PATH_FLTK}")
download_project(PROJ fltk
PREFIX "${PATH_FLTK}"
# UPDATE_COMMAND msbuild FLTK.sln
URL ${URL_FLTK}
UPDATE_DISCONNECTED ON
)
endif()

add_subdirectory("${PATH_FLTK}/fltk-src" "${PATH_FLTK}/fltk-build")

###

Albrecht Schlosser

unread,
Jan 11, 2018, 4:05:21 PM1/11/18
to fltkg...@googlegroups.com
On 11.01.2018 06:14 Robin Rowe wrote:
> I'm using DownloadProject, a cmake helper available on github, to
> automatically download FLTK. That works fine, but I can't build FLTK:
>
> 1>CUSTOMBUILD : CMake error : File
> C:/Code/gitlab/Cinepaint/glasgow/configh.cmake.in does not exist.
> 1>CMake Error at build/fltk/fltk-src/CMake/export.cmake:104
>
>   configure_file(
>      "${CMAKE_SOURCE_DIR}/${CONFIG_H_IN}"
>
> That file is actually at:
>
>   C:/Code/gitlab/Cinepaint/glasgow/fltk/fltk-src/configh.cmake.in
>
> Is export.cmake incorrect? Should it say CMAKE_CURRENT_SOURCE_DIR
> instead of CMAKE_SOURCE_DIR in export.cmake? Is there a way I can fix
> this without changing export.cmake?

This is an interesting coincidence: I just (i.e. about 7.5 hours before
your post) committed a change that does exactly that and changes many
more occurrences of CMAKE_SOURCE_DIR to CMAKE_CURRENT_SOURCE_DIR for
exactly the same reason: building FLTK as a subproject of another
project. I hope I got it all correct and I'd appreciate if you could
confirm this by posting here that (if) it works for you.

The commit is in svn r 12630 (and in git at
https://github.com/fltk/test-only) and will be in the next snapshot
tomorrow (Friday) morning at ~8am UTC. See also the pull request:
https://github.com/fltk/test-only/pull/4

See our download page for instructions how to get FLTK via svn or wait
until the next snapshot appears.

> My cmake below...
>
> Robin
>
> ------------------------------------------------------------
> #CinePaint FLTK.cmake
> set(NAME "fltk")
> project(${NAME})
> message("--- Building " ${NAME} " ---")
>
> set(PATH_FLTK "${CMAKE_BINARY_DIR}/fltk")
> set(URL_FLTK "http://fltk.org/pub/fltk/snapshots/fltk-1.4.x-r12602.tar.gz")

That's way too old (Dec 19, 2017), see above.

> if(WIN32)
> add_definitions(-DWIN32)
> endif()

This is no longer necessary to build FLTK itself (it's included in
FLTK's cmake build) but it may still be necessary to build your project
*using* FLTK under Windows (because some FLTK headers need it). We
strive to get rid of this requirement...

> set(OPTION_USE_SYSTEM_LIBPNG OFF)

okay.

> link_directories("${PATH_FLTK}/build/lib/Debug")
> include_directories(
>     ${CMAKE_BINARY_DIR}/fltk/fltk-src
>     ${CMAKE_BINARY_DIR}/fltk/fltk-build )

Using include_directories is not recommended by the CMake team. You
should try to use target_include_directories() to build your own
project, i.e. CinePaint itself, but not to build FLTK.

It *should* not be necessary here to build FLTK anyway, but it *may*
have been necessary _before_ the changes in svn r12630 (see above), so
I'd recommend to remove it and try how it works with r12630 or later
(upcoming snapshot).

I'm not sure about link_directories(), but it's likely the same case
(remove or comment out and try) and use target_link_directories() for
CinePaint.

> if(NOT IS_DIRECTORY "${PATH_FLTK}")
>     download_project(PROJ fltk
>     PREFIX "${PATH_FLTK}"
> #    UPDATE_COMMAND msbuild FLTK.sln
>     URL ${URL_FLTK}
>     UPDATE_DISCONNECTED ON
> )
> endif()

I can't comment on this.

> add_subdirectory("${PATH_FLTK}/fltk-src" "${PATH_FLTK}/fltk-build")

Looks okay to me.

Since I don't know your work on CinePaint CMake I'm not sure about
everything I wrote above, but I believe that the gist of what I wrote is
correct. So please try and report here about your success. This would be
helpful for FLTK development. TIA

Robin Rowe

unread,
Jan 24, 2018, 12:30:07 PM1/24/18
to fltkg...@googlegroups.com, Albrecht Schlosser
On 1/11/2018 1:05 PM, Albrecht Schlosser wrote:
> This is an interesting coincidence: I just (i.e. about 7.5 hours before
> your post) committed a change that does exactly that and changes many
> more occurrences of CMAKE_SOURCE_DIR to CMAKE_CURRENT_SOURCE_DIR for
> exactly the same reason: building FLTK as a subproject of another
> project. I hope I got it all correct and I'd appreciate if you could
> confirm this by posting here that (if) it works for you.

Yes, thanks Albrecht. That's much better.

The libjpeg build system also needs some CMAKE_CURRENT_SOURCE_DIR fixes.
I tried overriding CMAKE_SOURCE_DIR by setting that to
CMAKE_CURRENT_SOURCE_DIR, but cmake ignores it. Is there a hack solution
to this issue so I won't depend upon lib maintainers updating their
build systems right away as you have done?

>> link_directories("${PATH_FLTK}/build/lib/Debug")
>> include_directories(
>>      ${CMAKE_BINARY_DIR}/fltk/fltk-src
>>      ${CMAKE_BINARY_DIR}/fltk/fltk-build )
>
> Using include_directories is not recommended by the CMake team. You
> should try to use target_include_directories() to build your own
> project, i.e. CinePaint itself, but not to build FLTK.

I don't understand. Exactly what cmake syntax should I use here?

> It *should* not be necessary here to build FLTK anyway, but it *may*
> have been necessary _before_ the changes in svn r12630 (see above), so
> I'd recommend to remove it and try how it works with r12630 or later
> (upcoming snapshot).

Removed add_subdirectory. Works.

Robin

Albrecht Schlosser

unread,
Jan 24, 2018, 6:27:42 PM1/24/18
to fltkg...@googlegroups.com
On 24.01.2018 18:30 Robin Rowe wrote:
> On 1/11/2018 1:05 PM, Albrecht Schlosser wrote:
>> This is an interesting coincidence: I just (i.e. about 7.5 hours
>> before your post) committed a change that does exactly that and
>> changes many more occurrences of CMAKE_SOURCE_DIR to
>> CMAKE_CURRENT_SOURCE_DIR for exactly the same reason: building FLTK as
>> a subproject of another project. I hope I got it all correct and I'd
>> appreciate if you could confirm this by posting here that (if) it
>> works for you.
>
> Yes, thanks Albrecht. That's much better.

I'm glad to read this.

> The libjpeg build system also needs some CMAKE_CURRENT_SOURCE_DIR fixes.
> I tried overriding CMAKE_SOURCE_DIR by setting that to
> CMAKE_CURRENT_SOURCE_DIR, but cmake ignores it. Is there a hack solution
> to this issue so I won't depend upon lib maintainers updating their
> build systems right away as you have done?

Overriding CMAKE_SOURCE_DIR is a bad idea. If it would be technically
possible it would probably lead to all sorts of trouble.

I believe you should take a look at CMake's ExternalProject features. It
is on my personal to-do-list to investigate its features and usage. I
got the impression that this should be used to include third party
projects into one's own build rather than using add_subdirectory(). But
honestly, I don't know (yet).

https://cmake.org/cmake/help/latest/module/ExternalProject.html

>>> link_directories("${PATH_FLTK}/build/lib/Debug")
>>> include_directories(
>>>      ${CMAKE_BINARY_DIR}/fltk/fltk-src
>>>      ${CMAKE_BINARY_DIR}/fltk/fltk-build )
>>
>> Using include_directories is not recommended by the CMake team. You
>> should try to use target_include_directories() to build your own
>> project, i.e. CinePaint itself, but not to build FLTK.
>
> I don't understand. Exactly what cmake syntax should I use here?

include_diretories() is some kind of global definition of - as its name
says - include directories. This is no longer recommended, as I wrote
before. "Modern CMake" favors target_include_directories() instead.

https://cmake.org/cmake/help/latest/command/target_include_directories.html

The main difference is that you include the target that shall use the
include directories in the command, but there are many more options.

So instead of, let's say,

include_directories("/path/to/fltk") or
include_directories(${FLTK_INCLUDE_DIRS})
add_executable(CinePaint ${CinePaint_Sources})

you would write:

add_executable(CinePaint ${CinePaint_Sources})
target_include_directories(CinePaint ${FLTK_INCLUDE_DIRS})

and similar for target_link_directories().

This is much more flexible and you can set visibility attributes (my own
words, I don't recall the official wording) like PUBLIC, INTERFACE, or
PRIVATE, where PUBLIC and INTERFACE are "transitive" so that they are
carried over from library A that has a PUBLIC or INTERFACE
link_directory setting to the library B that links with library A so
your project (executable) can link with library B w/o knowing all
requirements of library A - these are automatically satisfied. More
information can be found in the CMake docs and is far beyond the scope
of this thread.

>> It *should* not be necessary here to build FLTK anyway, but it *may*
>> have been necessary _before_ the changes in svn r12630 (see above), so
>> I'd recommend to remove it and try how it works with r12630 or later
>> (upcoming snapshot).
>
> Removed add_subdirectory. Works.

I don't understand. Did you really remove "add_subdirectory"?

Robin Rowe

unread,
Jan 26, 2018, 4:40:54 PM1/26/18
to Albrecht Schlosser, fltkg...@googlegroups.com
Albrecht,

> I believe you should take a look at CMake's ExternalProject features.
> It is on my personal to-do-list to investigate its features and usage.

Using ExternalProject can be complicated. I'm using DownloadProject
instead. That downloads and builds external libraries at configure time
rather than build time. Here's why:

https://crascit.com/2015/07/25/cmake-gtest/
https://github.com/Crascit/DownloadProject

> I don't understand. Did you really remove "add_subdirectory"?

Ok, I've added it back. Trying to do what I thought you suggested.
(Didn't make sense to me, but am open to trying things.)

FLTK now builds but examples do not. I'm still using your github
test-only repo. Let me know when I can get off that or if I need to
install subversion or....

Too long and confusing to post VS2017 FLTK build error messages here.
I'm adding you as a CinePaint developer so you can clone and build to
see error messages yourself. Note the dependent library sources,
including FLTK, auto-download and build during configure. Will take a
while the first time you run cmake.

Robin

Robin Rowe

unread,
Jan 26, 2018, 5:10:30 PM1/26/18
to Albrecht Schlosser, fltkg...@googlegroups.com
Albrecht,

> I believe you should take a look at CMake's ExternalProject features. It
> is on my personal to-do-list to investigate its features and usage.

ExternalProject has issues. I use DownloadProject instead.

https://crascit.com/2015/07/25/cmake-gtest/
https://github.com/Crascit/DownloadProject

> I don't understand. Did you really remove "add_subdirectory"?

Ok, I've added it back. FLTK builds. FLTK examples do not.

Am still on your git test-only repo. Can I get off of that somehow? Do I
need subversion?

Too many noisy VS2017 FLTK errors to post here. I've granted you
CinePaint developer access so you can build to see for yourself. You
should have gotten an email...

Robin

Robin Rowe

unread,
Jan 26, 2018, 7:06:47 PM1/26/18
to fltkg...@googlegroups.com, Albrecht Schlosser
Albrecht,

FLTK and libjpeg86 both have targets named 'uninstall'. Cmake wants
globally unique names. Now what?

CMake Error at build/fltk/fltk-src/CMake/install.cmake:30
(add_custom_target):
add_custom_target cannot create target "uninstall" because another target
with the same name already exists. The existing target is a custom
target
created in source directory
"C:/Code/gitlab/Cinepaint/glasgow/build/libjpeg/libjpeg-src". See
documentation for policy CMP0002 for more details.
Call Stack (most recent call first):
build/fltk/fltk-src/CMakeLists.txt:77 (include)

Robin

Robin Rowe

unread,
Jan 26, 2018, 7:11:00 PM1/26/18
to fltkg...@googlegroups.com, Albrecht Schlosser

Albrecht Schlosser

unread,
Jan 27, 2018, 11:11:24 AM1/27/18
to fltkg...@googlegroups.com
On 26.01.2018 23:10 Robin Rowe wrote:
> Albrecht,
>
>> I believe you should take a look at CMake's ExternalProject features.
>> It is on my personal to-do-list to investigate its features and usage.
>
> ExternalProject has issues. I use DownloadProject instead.
>
> https://crascit.com/2015/07/25/cmake-gtest/
> https://github.com/Crascit/DownloadProject

Interesting. I'm far from understanding all the implications, but as you
could see this has issues as well, for instance adding another project
with add_subdirectory() that is not designed to work as a subproject.
This was also a problem with FLTK before we changed this (see one of
your previous posts and my reply).

In fact, all programs that use CMAKE_SOURCE_DIR to refer to the root of
the source directory or CMAKE_BINARY_DIR to refer to the root of the
build directory will fail with this approach. That's why I had to change
the FLTK CMake code to use CMAKE_CURRENT_SOURCE_DIR and
CMAKE_CURRENT_BINARY_DIR, resp..

To make things even more complicated I had to introduce another variable
(I called it FLTK_SOURCE_DIR) to be able to refer to the root of the
FLTK source code in _any_ subdirectory of the FLTK project because of
this scenario:

--- master project directory == CMAKE_SOURCE_DIR
|
+--- FLTK subdirectory == CMAKE_CURRENT_SOURCE_DIR [1]
|
+--- FLTK 'src' subdirectory == CMAKE_CURRENT_SOURCE_DIR [2]

You can see the ambiguity of the CMAKE_CURRENT_SOURCE_DIR in [1] and
[2]. I used a trick to define FLTK_SOURCE_DIR in FLTK's main
CMakeLists.txt file to get rid of this issue so I could use
FLTK_SOURCE_DIR wherever necessary to refer to the FLTK top directory
and CMAKE_CURRENT_SOURCE_DIR to refer to the any subdirectory of the
FLTK source (for instance in 'documentation' to find the documentation
root dir for doxygen).

>> I don't understand. Did you really remove "add_subdirectory"?
>
> Ok, I've added it back. FLTK builds. FLTK examples do not.

What I really meant was to remove the include_directory() and
link_directory() commands before add_subdirectory(<FLTK>) because these
two commands should no longer be necessary to build FLTK as a subproject.

> Am still on your git test-only repo. Can I get off of that somehow? Do I
> need subversion?

I thought you preferred git, so at least for now it would be okay to use
the github 'test-only' repo which is a mirror of our subversion
repository. The subversion repo is our current primary repository, but
since we plan to move to git (GitHub) in the future there should be no
need to learn or use subversion. The only thing you'd have to change
once we eventually moved to GitHub is the URL.

Before you ask: there is no schedule yet.

> Too many noisy VS2017 FLTK errors to post here. I've granted you
> CinePaint developer access so you can build to see for yourself. You
> should have gotten an email...

I didn't get an email from you. I checked my spam folders as well.
Please check the mail address you sent it to and send it again.

Albrecht Schlosser

unread,
Jan 27, 2018, 11:29:19 AM1/27/18
to Robin Rowe, fltkg...@googlegroups.com
This seems to be another issue of building another unrelated project as
a subproject of another one with add_subdirectory().

AFAICT the approach to use ExternalProject stuff as designed would avoid
this because the external project (in your case FLTK) would be built
independently w/o polluting the name space of your project. But I may be
wrong with this.

Note: I did not yet fully read and understand the implications of using
ExternalProject_Add() in its "normal" way as opposed to using it
together with DownloadProject() as you do now.

That said: there is an option to check whether a target already exists
in CMake. This is often done in projects where you don't know which
optional component would add to a particular target like "tests" or
"documentation" or as here "uninstall". The first component has to
create the target, all other components must then add their files or
whatever (custom commands, custom targets, ...) to the already existing
target.

Since this happens in the CinePaint (i.e. in YOUR) CMakeLists.txt file
you _could_ try to check for an existing uninstall target. But what if
other included projects also use the uninstall target? We're back to the
point where *all* projects you include as subdirs would likely need to
be changed, be it because of (IMHO legitimate) usage of CMAKE_SOURCE_DIR
or name collisions of targets or whatever. I'm sorry to say this, but
maybe the usage of DownloadProject() is not the best idea. Again, I may
be wrong...

Robin Rowe

unread,
Jan 27, 2018, 2:14:43 PM1/27/18
to fltkg...@googlegroups.com, Albrecht Schlosser
Albrecht,

> What I really meant was to remove the include_directory() and
> link_directory() commands before add_subdirectory(<FLTK>) because these
> two commands should no longer be necessary to build FLTK as a subproject.

Ok.

> the github 'test-only' repo which is a mirror of our subversion
> repository.

Ok.

> This seems to be another issue of building another unrelated project as
> a subproject of another one with add_subdirectory().
>
> AFAICT the approach to use ExternalProject stuff as designed would avoid
> this because the external project (in your case FLTK) would be built
> independently w/o polluting the name space of your project.

DownloadProject is a macro that calls ExternalProject_Add.

The cmake CMP0002 docs seem to say that cmake expects unique targets,
that it's a design choice by cmake because of issues with make.

> Note: I did not yet fully read and understand the implications of using
> ExternalProject_Add() in its "normal" way as opposed to using it
> together with DownloadProject() as you do now.

I've been using DownloadProject on another project for a year. Confident
it works. It's cmake that's difficult.

DownloadProject creates a CMAakelLists.txt in fltk-download that
contains this:

ExternalProject_Add(fltk-download

GIT_REPOSITORY;https://github.com/fltk/test-only.git;GIT_TAG;master;UPDATE_DISCONNECTED;ON
SOURCE_DIR
"C:/Code/gitlab/Cinepaint/glasgow/build/fltk/fltk-src"
BINARY_DIR
"C:/Code/gitlab/Cinepaint/glasgow/build/fltk/fltk-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

DownloadProject is moving up FLTK download and build to configure time
instead of being later at project build time. It makes sense to build
dependencies first, before the app. ExternalProject_Add is too
complicated to use without the nice DownloadProject wrapper.

> Since this happens in the CinePaint (i.e. in YOUR) CMakeLists.txt file
> you _could_ try to check for an existing uninstall target.

CinePaint doesn't have an uninstall target. Libjpeg86 and FLTK do.

> I'm sorry to say this, but maybe the usage of DownloadProject() is
not the best idea.

If I call ExternalProject_Add directly, it's going to collide target
uninstall at build time instead of configure time, right?

Why not rename the FLTK uninstall target to uninstall-fltk?

Robin

Ian MacArthur

unread,
Jan 27, 2018, 5:11:28 PM1/27/18
to fltkg...@googlegroups.com


> On 27 Jan 2018, at 00:10, Robin Rowe wrote:
>
>
> FLTK and libjpeg86 both have targets named 'uninstall'. Cmake wants globally unique names. Now what?


I’m going off at a (probably irrelevant) tangent here - but that’s a bit of a issue.

I have a heap of libs I use that have targets with the same names, like “uninstall” etc. - I guess it’s the “obvious” thing to call it - but if/when I switch to using cmake rather than autoconf, that sounds like it is going to prove “difficult” if I try and do a “unified” build...

We can’t be the first to hit this though, surely? Is there some generic workaround for it?



Albrecht Schlosser

unread,
Jan 27, 2018, 6:43:04 PM1/27/18
to fltkg...@googlegroups.com
I'm trying to explain the issue with my current knowledge, however I'm
still learning how to use CMake's ExternalProject features and the
DownloadProject function described and used by Robin. Please note that
parts of the following are educated guesses only. That said:

Such a "unified" build is somewhat similar to our FLTK build. The
standard autoconf/make build consists of a "super project" (say: fltk)
in the root directory and other projects: src (the FLTK libs), fluid,
and test (let's not talk about the bundled libs). If you run make from
the top level directory everything is built. However if you want to
build only the 'hello' test program with all its dependencies you have
to build the libs (in src) first, then 'cd test; make hello' will work
and build only the 'hello' target.

CMake is different. You can run 'make hello' or 'ninja hello' in the top
level build directory and it will build only the libs and target 'hello'
in the test directory (no fluid), like so (here with with ninja):

...
[174/177] Building CXX object
src/CMakeFiles/fltk.dir/drivers/PostScript/Fl_PostScript_image.cxx.o
[175/177] Linking CXX static library lib/libfltk.a
[176/177] Building CXX object test/CMakeFiles/hello.dir/hello.cxx.o
[177/177] Linking CXX executable bin/examples/hello

If you also want to build the tabs demo, then 'ninja tabs' (in the top
directory) builds some other FLTK image libs, fluid (required by tabs),
and the tabs demo:

...
[36/41] Building CXX object fluid/CMakeFiles/fluid.dir/widget_panel.cxx.o
[37/41] Building CXX object ...
[38/41] Linking CXX executable bin/fluid
[39/41] Generating tabs.cxx, tabs.h
[40/41] Building CXX object test/CMakeFiles/tabs.dir/tabs.cxx.o
[41/41] Linking CXX executable bin/examples/tabs

This explains why CMake requires unique targets in one build. It's a
design decision and very comfortable.

The CMake answer to doing a "unified" build of *different* projects (a
master project and its dependencies, i.e. libraries) is a so-called
super-build with ExternalProject_Add and related functions. I read a lot
about this in the CMake user mailing list. I believe that this approach
does NOT need unique target names over all external projects. This would
be impossible to achieve, as you can see in Robin's attempt to build
CinePaint, and from real life experience as you, Ian, noted: several
projects have their own 'install' and 'uninstall' targets and certainly
other targets like hello, help, doc, docs, documentation, and more.

But why did Robin experience this although I wrote that CMake's
ExternalProject feature doesn't suffer from the restriction of unique
target names?

Well, he said that using ExternalProject_Add directly was too
complicated so he used DownloadProject as a wrapper.
https://github.com/Crascit/DownloadProject

The docs of DownloadProject state:

"The primary advantage of this is that the project's source code can
then be included directly in the main CMake build using the
add_subdirectory() command, making all of the external project's
targets, etc. available without any further effort. The technique is
fully explained in the article available at:

https://crascit.com/2015/07/25/cmake-gtest/
"

The main points are:

(1) DownloadProject uses ExternalProject_Add in a special way to
download the external sources in the configure step rather than in the
build step.

I see no problem with this part.

(2) The external project is "included directly in the main CMake build
using the add_subdirectory() command, making all of the external
project's targets, etc. available without any further effort".

The difference to "normal" usage of ExternalProject_Add seems to be that
the author suggests to use add_subdirectory() which _includes_ the
entire external project in the main build. Hence the requirement of
unique target names. Robin tried to use this technique to build CinePaint.

I believe that the usage of add_subdirectory() is the cause of trouble.
*All* targets of *all* external projects are directly _included_ in the
main build which means that all these targets _must_ have unique names.
The global namespace is polluted with target names of all external projects.

[Side note: This can be compared with an "amalgamation" build of a
library where all source files are included in one file and compiled
together. In this case all static functions of all modules must have
unique names which is usually not enforced for good reasons (in
single-module builds). But here it is even worse because modules of
different authors are combined.]

The author writes that this is an advantage because you can now directly
access the targets of the external projects like (in our example) the
FLTK library "without any further effort". This seems to be true, but at
the price that all target names must be unique.

In the case of CinePaint we have at least two projects with identical
target names 'uninstall', but there may be all kinds of name collisions
with other projects. FLTK has, for instance, target names like 'hello',
'utf8', 'tabs', and such.

Taking my _little_ knowledge of (how to use) CMake's "original"
ExternalProject_Add and the additional function DownloadProject into
account my analysis may be wrong - but you have been warned.

I'll try to investigate further, and I have access to Robin's work on
CinePaint so I can test, but I certainly won't be able to post more
qualified answers or suggestions before Monday next week (or even later).

Besides that: add_subdirectory() of external projects has other issues
we solved recently (see subject of this thread:
CMAKE_CURRENT_SOURCE_DIR). Projects that are not designed to be included
with add_subdirectory(), i.e. projects that "assume" they are the main
projects, will fail to build when included with add_subdirectory(). This
is still true for FLTK 1.3.4 but was recently changed by me for FLTK
1.4.0. Other projects (libraries) may not be compatible with
add_subdirectory() usage.

Albrecht Schlosser

unread,
Jan 27, 2018, 7:00:58 PM1/27/18
to fltkg...@googlegroups.com
On 27.01.2018 20:14 Robin Rowe wrote:
>
> > This seems to be another issue of building another unrelated project as
> > a subproject of another one with add_subdirectory().
> >
> > AFAICT the approach to use ExternalProject stuff as designed would avoid
> > this because the external project (in your case FLTK) would be built
> > independently w/o polluting the name space of your project.
>
> DownloadProject is a macro that calls ExternalProject_Add.

I knew that meanwhile. But it uses ExternalProject_Add AFAICT only to
download and build the external project at configure time. After that
the external project is included with add_subdirectory() which cause
trouble. See my other recent post.

> The cmake CMP0002 docs seem to say that cmake expects unique targets,
> that it's a design choice by cmake because of issues with make.

I tried to explain this as well in my other reply.

> > Note: I did not yet fully read and understand the implications of using
> > ExternalProject_Add() in its "normal" way as opposed to using it
> > together with DownloadProject() as you do now.
>
> I've been using DownloadProject on another project for a year. Confident
> it works. It's cmake that's difficult.

Yes, it may work in some projects, and you may have had good luck. But
as you wrote in your first posting in this thread FLTK didn't build with
add_subdirectory() - before we changed FLTK's CMakeLists.txt files and
others to be "compatible with add_subdirectory()". Other projects may
not be designed to be included with add_subdirectory().

> DownloadProject creates a CMAakelLists.txt in fltk-download that
> contains this:
>
> ExternalProject_Add(fltk-download
>
> GIT_REPOSITORY;https://github.com/fltk/test-only.git;GIT_TAG;master;UPDATE_DISCONNECTED;ON
>
>                     SOURCE_DIR
> "C:/Code/gitlab/Cinepaint/glasgow/build/fltk/fltk-src"
>                     BINARY_DIR
> "C:/Code/gitlab/Cinepaint/glasgow/build/fltk/fltk-build"
>                     CONFIGURE_COMMAND   ""
>                     BUILD_COMMAND       ""
>                     INSTALL_COMMAND     ""
>                     TEST_COMMAND        ""
> )
>
> DownloadProject is moving up FLTK download and build to configure time
> instead of being later at project build time. It makes sense to build
> dependencies first, before the app. ExternalProject_Add is too
> complicated to use without the nice DownloadProject wrapper.
>
> > Since this happens in the CinePaint (i.e. in YOUR) CMakeLists.txt file
> > you _could_ try to check for an existing uninstall target.
>
> CinePaint doesn't have an uninstall target. Libjpeg86 and FLTK do.

Sorry for this misunderstanding.

> > I'm sorry to say this, but maybe the usage of DownloadProject() is
> not the best idea.
>
> If I call ExternalProject_Add directly, it's going to collide target
> uninstall at build time instead of configure time, right?

No, I don't think so. I believe that the external projects are more or
less kinda independent, i.e. they're using their own build environment
and targets. From my first (incomplete) tests I could see that the
external project is built *and* installed before the dependent (i.e. the
main) project is built - unless you specify INSTALL_COMMAND="" which
disables installation of the external project. You can use it directly
from its build directory (recommended for FLTK anyway).

> Why not rename the FLTK uninstall target to uninstall-fltk?

Because that doesn't make sense and it would be very inconvenient. FLTK
exists since about 30 years (1998) and has (AFAICT) always had install
and uninstall targets as other projects have as well (see Ian's reply).
If we renamed the uninstall target the next user/consumer might request
us to rename the 'hello' target and so on. FLTK has lots of demo
programs and all demo programs create their own target names ('make
help' lists 100 targets - most of these are demo programs). Basically
every project should be free to use its target names without having to
take care of other projects (worldwide!).

Robin Rowe

unread,
Jan 28, 2018, 12:56:51 AM1/28/18
to fltkg...@googlegroups.com, Albrecht Schlosser
Albrecht,

> I'm trying to explain the issue with my current knowledge, however I'm
> still learning how to use CMake's ExternalProject features and the
> DownloadProject function described and used by Robin.

I'm still learning too.

ExternalProject_Add will add the 3rd party lib and then at build time
will download and build it without target name collisions, at least so
the docs say. However, I'm using DownloadProject (from github, not
cmake) that will download during configure instead of build and does not
build it. To build the lib I use add_subdirectory, which will collide on
duplicate target names.

> I believe that the usage of add_subdirectory() is the cause of trouble.

You are correct. To avoid collision, I now have my cmake sed FLTK's
cmake file to rename its uninstall target to be uninstall-fltk. (Yes, I
have sed in Windows.)

Thanks for fixing CMAKE_CURRENT_SOURCE_DIR in FLTK. No further change
needed in FLTK repo. Thanks for your help and patience as I work through
build issues.

Robin
Reply all
Reply to author
Forward
0 new messages