Weird source files in multilevel CMake build
TimPushkin opened this issue · comments
I have a CMake project with layout like this:
project_root/
examples/
CMakeLists.txt
<some executable examples>
external/
CMakeLists.txt
scapix/
CMakeLists.txt <-- Scapix is loaded here
include/
<headers to parse are here>
src/
CMakeLists.txt <-- The main library target is created here
<sources are here>
CMakeLists.txt
The top-level CMake file includes other files via add_subdirectory
: firstly the main target is created in src
subfolder via add_library
, then Scapix and other libraries are configured, then examples
subfolder is added the same way, containing some executable targets created via add_executable
(the library is linked to them). The project builds and works fine without Scapix.
The problem is that when I add Scapix to the project with
scapix_bridge_headers(<main library target> com.example.something <path to SomeClass.h>)
and run CMake with -DSCAPIX_BRIDGE=java
I get the following errors at configure time:
CMake Error at src/CMakeLists.txt:3 (add_library):
Cannot find source file:
<my project path>/generated/bridge/java/SomeClass.cpp
Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm .h
.hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90 .f95 .f03 .hip .ispc
CMake Error at examples/CMakeLists.txt:2 (add_executable):
Cannot find source file:
<my project path>/generated/bridge/java/com/example/something/SomeClass.java
Tried extensions .c .C .c++ .cc .cpp .cxx .cu .mpp .m .M .mm .ixx .cppm .h
.hh .h++ .hm .hpp .hxx .in .txx .f .F .for .f77 .f90 .f95 .f03 .hip .ispc
I do not specify the missing files by myself, it seems like Scapix adds them to the targets somehow.
I can get rid of the first one if I place the content of the CMake file that loads Scapix into the CMake file that creates the library target (src/CMakeLists.txt
), but then the second one remains, and I can get rid of the second one if I place it into the CMake file that creates the example target (examples/CMakeLists.txt
), but then the first one remains.
Is it possible to fix these errors without throwing all CMake code into a single CMake file?
Thank you for reporting this.
Is your project available on github?
If not, can you please post skeleton CMake files, so I can setup the test project?
I tried to recreate your setup, here:
https://github.com/scapix-com/bug_multilevel
However, I do not get the error, everything works fine.
I gave you write access to this repository, can you please add necessary modifications to get the error?
Thanks.
I managed to recreate the error and commited it to the repository. It represents the current state of my project: if I use CMake 3.18 then the errors described above appear, if I use CMake 3.20 or higher then the configuration completes without errors, but build fails because the bridge file for SomeClass.cpp
doesn't get generated and thus cannot be found.
Thanks, I found that simply setting cmake_minimum_required(VERSION 3.18)
in my original test leads to error.
Starting from CMake 3.20 the error disappears because of this change in CMake 3.20:
https://cmake.org/cmake/help/latest/prop_sf/GENERATED.html
There is a workaround in Scapix using older CMake: when linking lib from another CMake file, call scapix_fix_sources(lib)
:
add_executable(example example.cpp)
target_link_libraries(example lib)
scapix_fix_sources(lib)
Please tell me if this workaround is good enough for your use case.
Yes, it works, thanks. But in my project I do not always build examples, so the corresponding CMake file gets skipped, scapix_fix_sources()
doesn't get called, and I get the same error with add_library
as described above (in my project Scapix is configured outside of the file where add_library
is, just like in the example project I commited).
Is there a place where I can find any documentation about scapix_fix_sources()
? If I add some new example targets into the same example/CMakeLists.txt
do I call this command after each new target, or do I call it only after the last one in the file? If I add new targets linking lib
in some other file do I call the command again or do I call it after all of the targets that link lib
in the project are added? Can I just put it at the bottom of my top level CMake file and use it even when no other targets apart from the library is present?
Turns out there were multiple issues affecting the situation when add_library
and scapix_bridge_headers
are called from different directories.
I submitted a fix, and now it should work correctly with CMake 3.18 or later (there is still an issue with CMake older then 3.18).
All you need in your case is a single call to scapix_fix_sources(lib)
in every CMake file where lib
is used, even if it's used multiple times in the same CMake file (but there is no harm in calling it multiple times). It should work now even if all these CMake files are skipped.
I will release new Scapix version soon.
Fixed in cmodule v1.0.34:
Can confirm that I no longer have these configure time errors with v1.0.34, thanks