[CMake] More problems with list()...

Michael Jackson mike.jackson at bluequartz.net
Wed Dec 3 12:05:39 EST 2008


On Dec 3, 2008, at 11:29 AM, Robert Dailey wrote:

> Hi,
>
> I have the following macro:
>
> macro( library_component project_name )
>     if( ${ARGC} EQUAL 2 )
>         list( GET ARGN 0 component_dependencies )
>     endif()
> endmacro()
>
> I call the macro like this:
>
> library_component( myProjectName item1 )
>
> The conditional in the macro above checks to see if the 1st optional  
> argument has been specified. If so, I proceed to obtain that  
> argument from the ARGN list. When I use message() to print the ARGN  
> list, I see "item1" in the output. However, when I call list( GET ),  
> I get NOTFOUND in the output. Why is this not working?

Working from some of the Boost CMake implementations if you are trying  
to create macros that take any number of arguments with some of them  
being optional then here is some code that you might be interested in.

https://svn.boost.org/trac/boost/wiki/CMakeLibraryProject

# This utility macro determines whether a particular string value
# occurs within a list of strings:
#
#  list_contains(result string_to_find arg1 arg2 arg3 ... argn)
#
# This macro sets the variable named by result equal to TRUE if
# string_to_find is found anywhere in the following arguments.
macro(list_contains var value)
   set(${var})
   foreach (value2 ${ARGN})
     if (${value} STREQUAL ${value2})
       set(${var} TRUE)
     endif (${value} STREQUAL ${value2})
   endforeach (value2)
endmacro(list_contains)

# This utility macro extracts the first argument from the list of
# arguments given, and places it into the variable named var.
#
#   car(var arg1 arg2 ...)
macro(car var)
   set(${var} ${ARGV1})
endmacro(car)

# This utility macro extracts all of the arguments given except the
# first, and places them into the variable named var.
#
#   car(var arg1 arg2 ...)
macro(cdr var junk)
   set(${var} ${ARGN})
endmacro(cdr)

# The PARSE_ARGUMENTS macro will take the arguments of another macro and
# define several variables. The first argument to PARSE_ARGUMENTS is a
# prefix to put on all variables it creates. The second argument is a
# list of names, and the third argument is a list of options. Both of
# these lists should be quoted. The rest of PARSE_ARGUMENTS are
# arguments from another macro to be parsed.
#
#     PARSE_ARGUMENTS(prefix arg_names options arg1 arg2...)
#
# For each item in options, PARSE_ARGUMENTS will create a variable with
# that name, prefixed with prefix_. So, for example, if prefix is
# MY_MACRO and options is OPTION1;OPTION2, then PARSE_ARGUMENTS will
# create the variables MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These
# variables will be set to true if the option exists in the command line
# or false otherwise.
#
# For each item in arg_names, PARSE_ARGUMENTS will create a variable
# with that name, prefixed with prefix_. Each variable will be filled
# with the arguments that occur after the given arg_name is encountered
# up to the next arg_name or the end of the arguments. All options are
# removed from these lists. PARSE_ARGUMENTS also creates a
# prefix_DEFAULT_ARGS variable containing the list of all arguments up
# to the first arg_name encountered.
MACRO(PARSE_ARGUMENTS prefix arg_names option_names)
   SET(DEFAULT_ARGS)
   FOREACH(arg_name ${arg_names})
     SET(${prefix}_${arg_name})
   ENDFOREACH(arg_name)
   FOREACH(option ${option_names})
     SET(${prefix}_${option} FALSE)
   ENDFOREACH(option)

   SET(current_arg_name DEFAULT_ARGS)
   SET(current_arg_list)
   FOREACH(arg ${ARGN})
     LIST_CONTAINS(is_arg_name ${arg} ${arg_names})
     IF (is_arg_name)
       SET(${prefix}_${current_arg_name} ${current_arg_list})
       SET(current_arg_name ${arg})
       SET(current_arg_list)
     ELSE (is_arg_name)
       LIST_CONTAINS(is_option ${arg} ${option_names})
       IF (is_option)
       SET(${prefix}_${arg} TRUE)
       ELSE (is_option)
       SET(current_arg_list ${current_arg_list} ${arg})
       ENDIF (is_option)
     ENDIF (is_arg_name)
   ENDFOREACH(arg)
   SET(${prefix}_${current_arg_name} ${current_arg_list})
ENDMACRO(PARSE_ARGUMENTS)

#----- And Now finally your macro can use it like the following:

macro(library_component project_name)
   parse_arguments(THIS_PROJECT
     "DEPENDENCIES"
     "SOME_OPTION"
     ${ARGN}
     )
    message(STATUS "THIS_PROJECT_DEPENDENCIES: $ 
{THIS_PROJECT_DEPENDENCIES}")
   list(LENGTH THIS_PROJECT_DEPENDENCIES  THIS_PROJECT_DEPENDENCIES_NUM)
   if (THIS_PROJECT_DEPENDENCIES_NUM EQUAL 1)
     set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}\n 
\nAuthor: ")
   else()
     set(THIS_PROJECT_DESCRIPTION "${THIS_PROJECT_DESCRIPTION}\n 
\nAuthors: ")
   endif()

macro(library_component project_name)

#--- and you should be able to call it like this:
library_component(MyNewLibrary DEPENDENCIES item1)
library_component(MyOtherLibrary DEPENDENCIES item1 item2 SOME_OPTION)

HTH
______________________________________________________
Mike Jackson                  mike.jackson at bluequartz.net
BlueQuartz Software                    www.bluequartz.net
Principal Software Engineer                  Dayton, Ohio





More information about the CMake mailing list