MantisBT - CMake |
View Issue Details |
|
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() |
Additional Information | |
Tags | No tags attached. |
Relationships | |
Attached Files | |
|
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 | bug_revision_view_page.php?bugnote_id=36110#r1467 |
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 | bug_revision_view_page.php?bugnote_id=36112#r1469 |
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 | bug_revision_view_page.php?bugnote_id=36114#r1471 |
2014-06-03 12:20 | thokra | Note Edited: 0036114 | bug_revision_view_page.php?bugnote_id=36114#r1472 |
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 |
Notes |
|
(0036103)
|
Brad King
|
2014-06-03 08:53
|
|
|
|
(0036105)
|
thokra
|
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
|
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
|
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
|
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
|
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
|
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
|
2014-06-03 12:09
|
|
You could make someFunc a macro. Its only argument is the name of a variable. |
|
|
(0036114)
|
thokra
|
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
|
2015-01-05 08:38
|
|
Closing resolved issues that have not been updated in more than 4 months. |
|