I would like to get the "expanded CMakeLists.txt" that replace each include(foo.cmake) with corresponding content. Don't know if it is possible.
For example, I have CMakeLists.txt with contents:
cmake_minimum_required(VERSION 3.20)
project(hello)
include(hello.cmake)
message(STATUS "***** hello_str is ${hello_str}")
and hello.cmake with contents:
set(hello_str "Hello, World")
I would get an expaned CMakeLists.txt with contents (yeah, just like C/C++'s preprocess)
cmake_minimum_required(VERSION 3.20)
project(hello)
set(hello_str "Hello, World") ##!!
message(STATUS "***** hello_str is ${hello_str}")
Is that possible? And how?
OK, due to people in the comments really didn't understand, I have to make it more clear.
In the cross-compilation stage, the commonly usage is:
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=qnx-aarch64.toolchain.cmake
cmake --build .
But actually the qnx-aarch64.toolchain.cmake contains one line:
include(linux-aarch64.toolchain.cmake)
Thus, people have to have both qnx-aarch64.toolchain.cmake and linux-aarch64.toolchain.cmake, instead only one qnx-aarch64.toolchain.cmake file.
What I expected is only one qnx-aarch64.toolchain.cmake file to finish the cross-compilation.
#fabian You don't understand my question and keep telling very simple stuffs and assumes I don't know those stuffs.
Is that possible?
No. CMake 3.22 (the current at time of writing) and below do not provide this feature.
Related
How can I force CMake to ignore cached value? I want to require the caller to pass variable each time, for example
cmake .. -DSOME_VAR=value
and if I call CMake like
cmake ..
without SOME_VAR I want that this piece of CMake code to fail:
if (NOT DEFINED)
message(FATAL_ERROR " SOME_VAR is missing.")
endif()
It seems that unset(SOME_VAR CACHE) doesn't do what I expect. I actually don't care for cached variables at all, I don't mind if it slower.
You can achieve that by testing for the SOME_VAR before the project statement, i.e. your root CMakeLists.txt should contain a piece of code like this:
#very first lines of a CMakeLists.txt
#note: the test must be done **BEFORE** project statement
if(NOT SOME_VAR)
message(FATAL_ERROR "SOME_VAR must be defined in command line")
endif()
project(project_requiring_some_var_in_cmd_line)
#the rest of your CMakeLists.txt
Also, as already pointed out, note that this is not the natural way of using CMake. It may be beneficial if you explained the problem you are trying to solve.
Stumbled upon something like this in a cmake file and couldn't find the syntax explanation neither in cmake documentation, nor on the Internet.
SET(%MY_LIB_TYPE% ON)
The same line is defined in a .cmake and in a similarly named .cmake.in files, and MY_LIB_NAME does not appear anywhere else.
What does %string% syntax do?
In CMake, nothing. It looks like a template placeholder for something that's generating CMake files. I believe this is the most likely option.
Otherwise, % is technically an allowable variable name character in CMake, though you have to indirect through another variable to read it.
$ cat test.cmake
cmake_minimum_required(VERSION 3.20)
set(%FOO% bar)
set(var "%FOO%")
message("${${var}}")
$ cmake -P test.cmake
bar
I'm trying to compile some Java code with CMake (I'm aware that Java is not really the use-case for CMake) and I want to provide the class paths for the files. The compilation should work on both Unix and Windows systems. The problem I have is with separating the different class paths. Using:
set(CLASS_PATH ${PATH1} ${PATH2})
message(STATUS "${CLASS_PATH}")
prints
<PATH1>;<PATH2>
But this happens on both Unix and Windows. So I have to manually add separators. The way I'm doing it is
if(${CMAKE_HOST_WIN32})
set(SEP "\;")
elseif(${CMAKE_HOST_UNIX})
set(SEP ":")
endif(${CMAKE_HOST_WIN32})
Is this really the best way to deal with separators? I feel like I'm missing something.
Update - MCVE
To describe my thought: FILE_LIST would be contain all the java files that I want to compile. I defined a custom function which I can call on this FILE_LIST and compile the files. Maybe I'm doing something wrong with the function parameters?
cmake_minimum_required(VERSION 3.11)
set(CLASS_PATH E:/tmp/cmake/separator C:/tmp/)
set(FILE_LIST 1.txt 2.txt 3.txt)
add_custom_target(war ALL)
function(compile_java clp)
foreach(java_file ${ARGN})
add_custom_command(
TARGET war
PRE_BUILD
COMMAND echo "${clp}" ${java_file}
)
endforeach(java_file)
endfunction()
compile_java("${CLASS_PATH}" ${FILE_LIST}) # I have to pass CLASS_PATH in quotes
So, based on comments, you want the path list as a single command-line argument, with a platform-specific separator. You can achieve this using string operations:
function(compile_java clp)
if(NOT CMAKE_HOST_WIN32)
string(REPLACE ";" ":" clp "${clp}")
endif()
foreach(java_file ${ARGN})
add_custom_command(
TARGET war
PRE_BUILD
COMMAND echo "${clp}" ${java_file}
)
endforeach(java_file)
endfunction()
In CMAKE, it defines the following variables to indicate the directories of files:
CMAKE_CURRENT_LIST_DIR
CMAKE_CURRENT_BINARY_DIR
CMAKE_CURRENT_SOURCE_DIR
They are useful when you process CMake scripts. However, none of them can tell you the directory where MACROs or functions are defined. Give the following example CMakeLists.txt to illustrate my question
project(Hello)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/my_macro.cmake)
test_macro()
Then for the my_macro.cmake, we have definitions for test_macro():
macro(test_macro)
message("hello")
#?? Can we know the folder of this macro is located?
#?? the macro definition file's location
endmacro()
I don't think there's an off-the-shelf variable for that, but you could easily make your own:
my_macro.cmake:
set(test_macro__internal_dir ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "")
macro(test_macro)
message(STATUS "Defined in: ${test_macro__internal_dir}")
endmacro()
The set() line will be processed when the file is included, and the value of CMAKE_CURRENT_LIST_DIR from that processing cached for future use inside the macro.
With CMake 3.17 there is CMAKE_CURRENT_FUNCTION_LIST_DIR that can be used in functions, see https://cmake.org/cmake/help/v3.17/variable/CMAKE_CURRENT_FUNCTION_LIST_DIR.html
Unfortunately, there is no such thing for macros yet.
Note: This is my first time using CMake. I don't know much about it, so I'm just posting a bunch of information to see if anyone can see my problem.
I would like the ability to automatically determine which c++11 flag is appropriate, given my compiler. There are many examples of this line. Here is my CMakeLists.txt following such an example:
cmake_minimum_required (VERSION 2.8)
#Add the c++11 flag, whatever it is
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG(-std=c++0x COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
project(AnalyzeGames)
set(AnalyzeGames_SRCS AnalyzeGames.cpp)
add_executable(AnalyzeGames ${AnalyzeGames_SRCS})
Here is my cmake output when trying to use this file: http://pastebin.com/3AUwqffD
Here is CMakeError.log: http://pastebin.com/EbNKvGt8
Here is CMakeOutput.log: http://pastebin.com/kVJ0enJC
echo $CC: /usr/bin/gcc
echo $CXX: /usr/bin/g++
I can compile a simple test executable with g++ using either flag manually.
cmake --version: cmake version 2.8.12.2
For some reason CMake is not recognizing that my compiler does support both of those flags.
The cmake output tells you that it does not recognize the '.cxx' extension because it doesn't know that your project is a C++ project. To fix this, you should enable C++ in the project command. Try to change the following line:
project(AnalyzeGames)
to:
project(AnalyzeGames CXX)
and then move it to the 2nd line of the CMakeLists.txt, right under cmake_minimum_required. The configuration should work as expected after this.
TLDR
Compiler checks are only performed in the variable passed is not previously defined, which includes in the cache from previous failed attempts. Use unset(my_var CACHE) to force checking to always occur, or just be aware of this behaviour and clear the cache manually when needed.
Detail
I too had this problem (with cmake 2.8.12.2) and I had to turn on trace output, and step through the code to get a similar toy build to work I had make sure the variables I used (COMPILER_SUPPORTS_CXX11_*) in these calls:
CHECK_CXX_COMPILER_FLAG(-std=c++11 COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG(-std=c++0x COMPILER_SUPPORTS_CXX0X)
Were set such that they named themselves:
set(COMPILER_SUPPORTS_CXX11 "COMPILER_SUPPORTS_CXX11")
The other posters solution didn't work for me, it mainly just seemed to limit the detecting of compilers to just CXX and ignored the C compiler.
The issue appears to be with this line of code in the cmake module:
if("${VAR}" MATCHES "^${VAR}$")
Which in the trace output is:
/usr/share/cmake/Modules/CheckCXXSourceCompiles.cmake(30): if(COMPILER_SUPPORTS_CXX0X MATCHES ^COMPILER_SUPPORTS_CXX0X$ )
It looks as if the expression on the left of the MATCHES is replaced with the variables value, but the expression on the right is assumed to be plain text.
If the MATCH fails then the main part of the macro is skipped and according the to the log the check fails.
Looking at later versions of this macro online it looks as if this line has changed to only perform the compile check if the variable is undefined.
It as at this point that I realise that this is the intent / hack of the original code; if the X is undefined then "X" MATCHES "^X$" will be true, but then the compile check can be performed, fail for some other reason and then never be performed again.
So the solution is either force unset of variable in cache before calling the macro using:
unset(COMPILER_SUPPORTS_CXX0X CACHE)
Or clear the cache manually and be prepared for this behaviour.