View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0014948CMakeCMakepublic2014-06-03 06:422015-01-05 08:38
Reporterthokra 
Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
StatusclosedResolutionno change required 
PlatformOSLinux/Mac/WindowsOS Version
Product Version 
Target VersionFixed in Version 
Summary0014948: list() command does not work universally on implicitly defined lists (ARGN inside function)
DescriptionWhile optimizing a large CMake based project I came across a problem involving lists and sub-commands of the list() command.

Suppose we have a

macro(some_macro mandatoryArg [opt1[opt2...]])

to which we pass a large list of files and, sub-optimally, copy the entire list via

set(newList ${ARGN})

so we are able to further process the resulting list using the list() command. This, depending on the current amount of entries, is obviously a costly operation which we want to get rid of. Also, we need to sort the list afterwards so the logical step is to invoke

list(SORT newList)

This all works, but seems unnecessary because we could just as well use a function and process ARGN directly.

The problem is that some list() sub-commands work properly and others don't. For instance, determining the length of the list using

list(LENGTH ARGN len)

works.

list(SORT ARGN) however

generates an error message that the second argument needs to be a list. Using the above macro leads to, AFAICT, correct error messages being generated by either sub-command.

I suppose the above is not intentional.
Steps To Reproducemacro(some_macro ARG1)
 list(LENGTH ARGN len) # generates an error
 message("Length: " ${len})
 list(SORT ARGN) # generates an error
endmacro()

function(some_func ARG1)
 list(LENGTH ARGN len)
 message("Length: " ${len}) # reports the correct size of ARGN
 list(SORT ARGN) # generates an error, ARGN supposedly not a list
endfunction()
TagsNo tags attached.
Attached Files

 Relationships

  Notes
(0036103)
Brad King (manager)
2014-06-03 08:53

The documentation of the list command explains that macro arguments are not lists:

 http://www.cmake.org/cmake/help/v3.0/command/list.html [^]
 "Note macro arguments are not variables, and therefore cannot be used in LIST commands."

See also the macro command documentation on macro argument caveats:

 http://www.cmake.org/cmake/help/v3.0/command/macro.html#macro-argument-caveats [^]

Inside a function the ARGN is a real variable and I cannot reproduce the behavior you report. Can you provide a more complete example for the function() case?
(0036105)
thokra (reporter)
2014-06-03 09:06

I should have mentioned we're working with CMake 2.8.12.2

I'm aware that inside a macro(), ARGN is merely an expanded string which cannot be used in conjuction with list(). That's why I proposed the use of a function() in the first place.

Also, if you read carefully, I already stated that I expected list() inside a macro NOT to work: "Using the above macro leads to, AFAICT, >> correct error messages being generated by either sub-command <<."
(0036107)
Brad King (manager)
2014-06-03 09:50

Inside a function I cannot reproduce the SORT error you report. Can you provide a more complete example for the function() case?

$ cat issue14948.cmake
function(some_func ARG1)
 list(LENGTH ARGN len)
 message("Length: " ${len}) # reports the correct size of ARGN
 list(SORT ARGN) # generates an error, ARGN supposedly not a list
 message("Sorted: ${ARGN}")
endfunction()

some_func(_)
some_func(_ x)
some_func(_ y x)
some_func(_ z y x)

$ cmake --version
cmake version 2.8.12.2

$ cmake -P issue14948.cmake
Length: 0
Sorted:
Length: 1
Sorted: x
Length: 2
Sorted: x;y
Length: 3
Sorted: x;y;z
(0036109)
thokra (reporter)
2014-06-03 11:39

My bad, I gave you insufficient information. ARGN is further processed and afterwards is invalid. If we create a local copy however, everthing works like a charm. See this contrived example, basically showing you what is currently done:

cmake_minimum_required(VERSION 2.8.12.2)

project(cmaketest)

function(someFunc listArg)
  list(LENGTH ${listArg} len)
  message("someFunc - length of ${listArg}: " ${len})
  message("someFunc - contents of ${listArg}: " ${${listArg}})
  set (${listArg} ${${listArg}} PARENT_SCOPE)
endfunction()

function (add_target_a targetName)
  # get initial length of ARGN
  list(LENGTH ARGN len)
  message("add_target_a - length of ARGN: " ${len})
  
  # create a local copy of ARGN first
  set(localARGN ${ARGN})
  
  # get length of local copy
  list(LENGTH localARGN len)
  message("add_target_a - length of local copy: " ${len})
  
  # call function with local copy
  someFunc(localARGN)
  
  # get length after function
  list(LENGTH localARGN len)
  message("add_target_a - length of local copy after someFunc(): " ${len})
  
  # get contents
  message("add_target_a - contents: " ${localARGN})
  
  # call some other list() sub-command
  list(SORT localARGN)
  
  # add target
  add_executable(${targetName} ${localARGN})
endfunction()

function (add_target_b targetName)
  # get initial length of ARGN
  list(LENGTH ARGN len)
  message("add_target_b - length of ARGN: " ${len})
 
  # call function
  someFunc(ARGN)
  
  # get length after function
  list(LENGTH ARGN len)
  message("add_target_b - length of ARGN after someFunc(): " ${len})
  
  # get contents
  message("add_target_b - contents: " ${localARGN})
  
    # call some other list() sub-command
  list(SORT ARGN)
  
  # add target
  add_executable(${targetName} ${ARGN})
endfunction()

set(SRCS main.cpp)

message("Configuring target a ...")
add_target_a(cmakeTest_a ${SRCS})

message(" ")

message("Configuring target b ...")
add_target_b(cmakeTest_b ${SRCS})
(0036110)
thokra (reporter)
2014-06-03 11:40
edited on: 2014-06-03 11:40

If you run this, the following messages are generated:

Configuring target a ...
add_target_a - length of ARGN: 1
add_target_a - length of local copy: 1
someFunc - length of localARGN: 1
someFunc - contents of localARGN: main.cpp
add_target_a - length of local copy after someFunc(): 1
add_target_a - contents: main.cpp
 
Configuring target b ...
add_target_b - length of ARGN: 1
someFunc - length of ARGN: 0
someFunc - contents of ARGN:
add_target_b - length of ARGN after someFunc(): 0
add_target_b - contents:
CMake Error at CMakeLists.txt:57 (list):
  list sub-command SORT requires list to be present.
Call Stack (most recent call first):
  CMakeLists.txt:71 (add_target_b)


Configuring incomplete, errors occurred!


Is it intentional that ARGN is treadted differently then a locally created variable when passed to another function INSIDE a function?

I'm quite confused.

(0036111)
Brad King (manager)
2014-06-03 12:02

Each function call on the stack has its own ARGN value. Your someFunc(ARGN) call is evaluating the ARGN from itself, not from the caller. When it does the "set(ARGN ${ARGN} PARENT_SCOPE)" call the value is empty so it removes the ARGN variable setting from the calling function.

list(LENGTH) tolerates an undefined list but list(SORT) does not.
(0036112)
thokra (reporter)
2014-06-03 12:06
edited on: 2014-06-03 12:06

So there is no way of reusing ARGN, which in our case contains a substantial number of elements multiple times, without copying it first?

Is there better workaround than inlining someFunc()?

(0036113)
Brad King (manager)
2014-06-03 12:09

You could make someFunc a macro. Its only argument is the name of a variable.
(0036114)
thokra (reporter)
2014-06-03 12:10
edited on: 2014-06-03 12:20

Thank you and please excuse the false alarm.

Maybe it's worth adding this to the doc - I really expected some pass-by-reference implementation under the hood and that ${listVar} and ARGN would not conflict.

(0037558)
Robert Maynard (manager)
2015-01-05 08:38

Closing resolved issues that have not been updated in more than 4 months.

 Issue History
Date Modified Username Field Change
2014-06-03 06:42 thokra New Issue
2014-06-03 08:53 Brad King Note Added: 0036103
2014-06-03 09:06 thokra Note Added: 0036105
2014-06-03 09:50 Brad King Note Added: 0036107
2014-06-03 11:39 thokra Note Added: 0036109
2014-06-03 11:40 thokra Note Added: 0036110
2014-06-03 11:40 thokra Note Edited: 0036110
2014-06-03 12:02 Brad King Note Added: 0036111
2014-06-03 12:06 thokra Note Added: 0036112
2014-06-03 12:06 thokra Note Edited: 0036112
2014-06-03 12:09 Brad King Note Added: 0036113
2014-06-03 12:10 thokra Note Added: 0036114
2014-06-03 12:12 thokra Note Edited: 0036114
2014-06-03 12:20 thokra Note Edited: 0036114
2014-06-03 12:48 Brad King Status new => resolved
2014-06-03 12:48 Brad King Resolution open => no change required
2015-01-05 08:38 Robert Maynard Note Added: 0037558
2015-01-05 08:38 Robert Maynard Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team