Cmake (cmake)

Cmake Use tutorial (1) – start

Cmake Tutorial 2 – Adding libraries

Cmake use tutorial (3) – installation, testing, system self – check

Cmake Use tutorial (4) – file generator

Cmake Use tutorial (5) -cpack generate installation package

Cmake Use tutorial (6) – lousy syntax

Cmake Use Tutorial (7) – Processes and loops

Cmake: Macro and Function

Cmake Use Tutorial (9) – About android cross compilation

This series of articles was translated from the official Cmake tutorial: CMake Tutorial.

Example program address: github.com/rangaofei/t…

It will not stop at the official tutorial. I as an Android developer, is really no Linux C program development experience, hope big guys forgive. The tutorial is done on MacOS, and I’ve tested most Linux as well, so IF there are special instructions, I’ll note them. This tutorial is based on cmake-3.10.2 and assumes that you have cmake installed.

Cmake has two similar keywords, macro and function. Both of these create a piece of code with a name that you can call later, and you can pass arguments.

Macro is the same as function

The macro form is as follows:

macro(<name> [arg1 [arg2 [arg3 ...]]]) COMMAND1(ARGS ...) COMMAND2(ARGS ...) .endmacro(<name>)
Copy the code

Function form is as follows:

function(<name> [arg1 [arg2 [arg3 ...]]]) COMMAND1(ARGS ...) COMMAND2(ARGS ...) .function(<name>)
Copy the code

Define a macro (function) named name, arg1… Is the parameter passed in. In addition to using ${arg1} to reference variables, the system provides us with some special variables:

variable instructions
ARGV# # is a subscript, 0 refers to the first argument, sum
ARGV All definitions are required to pass in parameters
ARGN For example, if one macro (function) is required and three are entered, the remaining two are stored as an array in ARGN
ARGC The number of actual arguments passed, that is, the number of arguments passed to the calling function

Macro The difference between a macro definition and a function

Macro arguments such as ARGN and ARGV are not variables in the usual CMake sense. They are string substitutions, much like the C preprocessor does with macros. Therefore, the following command is incorrect:

if(ARGV1) # ARGV1 is not a variable 
if(DEFINED ARGV2) # ARGV2 is not a variable
if(ARGC GREATER 2) # ARGC is not a variable
foreach(loop_var IN LISTS ARGN) # ARGN is not a variable
Copy the code

The correct way to write it is as follows:

if(${ARGV1})
if(DEFINED ${ARGV2})
if(${ARGC} GREATER 2)
foreach(loop_var IN LISTS ${ARGN})
or
set(list_var "${ARGN}")
foreach(loop_var IN LISTS list_var)

Copy the code

A simple example

macro(FOO arg1 arg2 arg3)
    message(STATUS "this is arg1:${arg1},ARGV0=${ARGV0}")
    message(STATUS "this is arg2:${arg2},ARGV1=${ARGV1}")
    message(STATUS "this is arg3:${arg3},ARGV2=${ARGV2}")
    message(STATUS "this is argc:${ARGC}")
    message(STATUS "this is args:${ARGV},ARGN=${ARGN}")
    if(arg1 STREQUAL one)
        message(STATUS "this is arg1")
    endif(a)if(ARGV2 STREQUAL "two")
        message(STATUS "this is arg2")
    endif(a)set(${arg1} nine)
    message(STATUS "after set arg1=${${arg1}}")
endmacro(FOO)

function(BAR arg1)
    message(STATUS "this is arg1:${arg1},ARGV0=${ARGV0}")
    message(STATUS "this is argn:${ARGN}")
    if(arg1 STREQUAL first)
        message(STATUS "this is first")
    endif(a)set(arg1 ten)
    message(STATUS "after set arg1=${arg1}")
endfunction(BAR arg1)

set(p1 one)
set(p2 two)
set(p3 three)
set(p4 four)
set(p5 five)
set(p6 first)
set(p7 second)

FOO(${p1} ${p2} ${p3} ${p4} ${p5})
BAR(${p6} ${p7})
message(STATUS "after bar p6=${p6}")
Copy the code

The output is as follows:

-- this is arg1:one,ARGV0=one -- this is arg2:two,ARGV1=two -- this is arg3:three,ARGV2=three -- this is argc:5 -- this is args:one; two; three; four; five,ARGN=four; five -- after set arg1=nine -- this is arg1:first,ARGV0=first -- this is argn:second -- this is first -- after set arg1=ten -- after bar p6=firstCopy the code

Here’s an example that makes our eggs break. I don’t want to use cmake:

macro(_bar)
  foreach(arg IN LISTS ARGN)
    message(STATUS "this is in macro ${arg}")
  endforeach(a)endmacro(a)function(_foo)
    foreach(arg IN LISTS ARGN)
        message(STATUS "this in function is ${arg}")
    endforeach()
  _bar(x y z)
endfunction()

_foo(a b c)
Copy the code

Look at the output:

-- this in function is a
-- this in function is b
-- this in function is c
-- this is in macro a
-- this is in macro b
-- this is in macro c
Copy the code

Foreach (arg IN LISTS ${ARGN}) foreach(arg IN LISTS ${ARGN}) foreach(arg IN LISTS ${ARGN})

-- this in function is a
-- this in function is b
-- this in function is c
Copy the code

No output information in _bar. Why? Because the scope of this ARGN is in function, which is the ARGN in _foo. If you’re interested, try calling function from your Macro.