'Cannot determine link language for target...' issue in sub directory - cmake

In the main folder of my project, I have a CMakeLists.txt file. Inside this file, I include (using add_subdirectory) another CMakeLists.txt file located in my header file directory. The responsibility of this second file is to add all of my header files to the project:
file(GLOB gl_nbody_HEADERS "*.h")
add_executable(gl_nbody ${gl_nbody_HEADERS})
However, this files causes an error:
CMake Error: CMake can not determine linker language for target:gl_nbody
CMake Error: Cannot determine link language for target "gl_nbody".
What is strange is that when I include the two lines causing this error in my main CMakeLists.txt file (modified to work correctly for the change in directory), it works fine.
What is going wrong here?

add_executable causes the creation of an executable target, meaning the compilation of a list of source code files into an executable binary.
In order for this to work, and have CMake select a suitable compiler, the list of source files must contain at least one file with a "compilable" extension, ie. .c, or .cpp, or .cxx....
I don't see why you are trying to compile an executable here, since you only seem to try to list header files for inclusion into a project (which only makes sense for IDE-based generators, such as Visual Studio).
Also, it is not recommended to use globbing of files in CMake, because if you add more files to your project, CMake cannot detect them automatically, and will not regenerate build files. Please list all files explicitely.
The proper solution here is to list the header files in the proper add_executable command call where you list the actual source files that you want to compile.
You might also want to use the source_group() command, that allows you to group files into folders in the generated Visual Studio solution, for example:
source_group(header_files ${gl_nbody_HEADERS})

Related

CPPCheck: Errors in local header files are not caught

I have a project that uses CMake with a top level CMakeLists which references subdirectories each with their own targets and CMakeLists. Each subdirectory includes src, include dirs.
I'm trying to execute Cppcheck on my code base using the following command:
cppcheck --project=compile_commands.json --suppressions-list=suppressions.txt --output-file=cppcheck-results.log --xml --enable=all
My suppressions.txt file contains a bunch of style errors to skip.
The problem is that it doesn't catch any error/issue in local .h files (inside the include directories).
Unless I specify cppcheck to check a specific directory and give the -I flag, then it would. But for the whole project it does not.

CMake have a target depend on a generated file in a subdirectory

I have a scenario that I think is very similar to this one: CMake add_custom_command/_target in different directories for cross-compilation, however the solution for that issue isn't working for me.
In subdir/CMakeLists.txt I have:
add_custom_command(OUTPUT foo.h foo.cpp COMMAND ... DEPENDS foo.xml)
add_custom_target(generate_foo DEPENDS foo.h foo.cpp)
and then CMakeLists.txt:
add_executable(MyTarget
subdir/foo.h
subdir/foo.cpp
${OTHER_SOURCES})
add_dependencies(MyTarget generate_foo)
add_subdirectory(subdir)
This fails with "Cannot find source file: subdir/foo.h". The documentation for add_dependencies suggests that it will ensure that generate_foo builds before MyTarget, but if that's the case it looks like it's at least trying to access all source files before either target builds. Am I doing something wrong here? How can I compile source files that are generated by a custom target/command in a subdirectory?
The problem is that the GENERATED file property (that CMake uses to determine if it needs to check that a file exists at configure time) is not visible outside the directory in which the file is generated. The problem goes away in CMake 3.20. This is explained here.
I usually solve this problem by compiling generated source files into a static or object library in the subdirectory, then linking to that, since targets are globally visible. You can also explicitly set the GENERATED property on the generated files in the scope you wish to use them, but this hack breaks the encapsulation gained by using a subdirectory.
It's also worth noting that you can do away with the custom target and the call to add_dependencies because the generated files are already dependencies of the executable (this has always has been the case AFAIK).

In Cmake how to update the makefiles with new source files without cleaning the object files

I'm using cmake, and I just added new source files and I want to include that new source files in the cmake generated makefiles to include in the building. I tried rebuild_cache but nothing happens.
Thanks!
It depends how your cmake file was built. If you use GLOB, you must run cmake manually any time you add or remove a source file. If you explicitly list your source files, just run make again. CMake will detect the changed CMakeLists.text.
CMake suggests the latter for this reason:
We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
CMake documentation

Add file dependencies to a custom target

I would like to set up CMake to build qresource files when the contents of files referenced in the .qrc file change. For example I have some qml files that are packaged into a qrc file and the qrc needs to be recompiled if the qml files are changed.
I have the following macro to run the resource compiler but it will only rebuild it if the resource file itself changes.
MACRO(PYQT5_WRAP_RC outfiles)
FOREACH(it ${ARGN})
GET_FILENAME_COMPONENT(outfile ${it} NAME_WE)
GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE)
SET(outfile ${CMAKE_CURRENT_SOURCE_DIR}/${outfile}_rc.py)
ADD_CUSTOM_TARGET(${it} ALL
DEPENDS ${outfile}
)
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND ${PYRCC5BINARY} ${infile} -o ${outfile}
MAIN_DEPENDENCY ${infile}
)
SET(${outfiles} ${${outfiles}} ${outfile})
ENDFOREACH(it)
ENDMACRO (PYQT5_WRAP_RC)
The macro is used like this:
PYQT5_WRAP_RC(rc_gen file1.qrc file2.qrc ...)
How can I make it so the qrc file gets recompiled if one of files that it refers to changes?
Do I need to do something convoluted like this?
It seems to me that the command you are looking for is add_custom_command:
This defines a command to generate specified OUTPUT file(s). A target
created in the same directory (CMakeLists.txt file) that specifies any
output of the custom command as a source file is given a rule to
generate the file using the command at build time.
Configuring the dependencies correctly you should be able to get the file recompiled only when it is really needed.
If I understand correctly your situation, the problem is that CMake does not know anything about what qrc file is and it does not know, that qrc file references some other files. This dependency is implicit for CMake (compare with C++ includes; but for those cmake have special mechanisms to detect dependencies).
So, as I understand, what you can do is to use add_custom_target (which is executed always) but not only add qrc file to its depends, but also write some script, which whould check that files referenced in qrc are also up to date and if they are not, then touch qrc file).
Of course you can use methods from the other answer, which you reference above, to touch qrc file, but you have to develop your own script to extract paths of files referenced in qrc files. Then you can use CMake scripting facilities to check if they are up to date and to touch qrc file.

Avoid repeating the directory name for multiple file inclusions

I have a CMakeLists.txt file for a library. It's pretty basic:
set(LIB_FILES source/first.cpp)
add_library(first ${LIB_FILES})
I put the files in a list because I will eventually be adding more source files to the library. The problem is that all of the files will be in the source directory. And I don't want to constantly have to repeat that.
I also don't want to use the GLOB pattern matching solution, because I want to have to edit the CMakeLists.txt file when I add a new file. That way, my build will re-build the build solution, and new files will correctly appear (as I understand it. I'm still new with CMake).
I tried adding a CMakeLists.txt file into the source directory itself, just to build the LIB_FILES list. That didn't work out very well. Variables in CMake are file scoped. And even when I broke scoping (with PARENT_SCOPE), I still had to prefix each file with the directory. So that gained nothing.
I don't want to put the actual library definition in the source directory, as that will generate all the build files in the source directory. And I don't want that. Also, I will need to include headers that aren't in or under the source directory.
My directory structure looks like this:
libroot (where the project build files should go)
\-source (where the source code is)
\-include (where the headers that the user of the library includes go)
So how do I tell CMake that all of the source files come from the source directory, so that I don't have to constantly spell it out?
You could move the add_library call to your source/CMakeLists.txt also:
set(LIB_FILES first.cpp)
add_library(first ${LIB_FILES})
Then just use add_subdirectory in your top-level CMakeLists.txt:
add_subdirectory(source)
you could use a simple macro for that
macro(AddSrc dst_var basepath_var)
foreach(file ${ARGN})
list(APPEND ${dst_var} ${basepath_var}/${file})
endforeach()
endmacro()
set(MY_SRCFILES "")
AddSrc(MY_SRCFILES path/to/source
foo.cpp
bar.cpp
whatever.cpp
)