View Issue Details [ Jump to Notes ] | [ Print ] | ||||||||
ID | Project | Category | View Status | Date Submitted | Last Update | ||||
0014948 | CMake | CMake | public | 2014-06-03 06:42 | 2015-01-05 08:38 | ||||
Reporter | thokra | ||||||||
Assigned To | |||||||||
Priority | normal | Severity | major | Reproducibility | always | ||||
Status | closed | Resolution | no change required | ||||||
Platform | OS | Linux/Mac/Windows | OS Version | ||||||
Product Version | |||||||||
Target Version | Fixed in Version | ||||||||
Summary | 0014948: list() command does not work universally on implicitly defined lists (ARGN inside function) | ||||||||
Description | While 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 Reproduce | macro(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() | ||||||||
Tags | No tags attached. | ||||||||
Attached Files | |||||||||
Relationships | |
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. |
Notes |
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 |
Issue History |
Copyright © 2000 - 2018 MantisBT Team |