[CMake] How to write a correct wrapper of MESSAGE()?

Johannes Zarl johannes.zarl at jku.at
Wed Oct 9 07:44:09 EDT 2013


I guess you search for something like this:

function(info)
    set(msg)
    foreach(i RANGE ${ARGC})
        set(msg "${msg}${ARGV${i}}")
    endforeach()
    message(STATUS "[info] ${msg}")
endfunction()

message("Foo:bar;baz space" "FOO")
info("Foo:bar;baz space" "FOO")
message(two words)
info(two words)

...which yields the following output:

Foo:bar;baz spaceFOO
-- [info] Foo:bar;baz spaceFOO
twowords
-- [info] twowords

The "IN LISTS" signature of foreach seems to do additional list splitting, 
leading to ("foo;bar" "baz") appearing as 3 elements. Accessing the ARGV array 
by the positional indices (e.g. ${ARGV0}) prevents the splitting.

HTH,
  Johannes

On Wednesday, 9. October 2013, 05:33:26, Clark WANG wrote:
> On Sat, Oct 5, 2013 at 1:38 AM, Matthew Woehlke
> <matthew.woehlke at kitware.com
> 
> > wrote:
> > 
> > On 2013-09-27 04:18, Clark WANG wrote:
> >> I'm trying to write some MESSAGE() wrappers like info(), warning(),
> >> fatal(), etc which may be a bit easier to use. But I failed to simulate
> >> the
> >> correct MESSAGE() behavior no matter I use MACRO or FUNCTION. For
> >> example: [snip]
> > 
> > FUNCTION vs MACRO shouldn't make a difference in argument parsing AFAIK.
> > The difference is primarily that FUNCTION creates a scope, while MACRO
> > operates in the scope from which it is called.
> > 
> > The behavior of MESSAGE seems to concatenate multiple arguments with no
> > separators. So maybe you could do something like:
> > 
> > set(msg "")
> > foreach(part IN LISTS ARGN)
> > 
> >   set(msg "${msg}{$part}")
> > 
> > endforeach()
> > # ...do stuff with ${msg}
> 
> This does not work either. For example:
> 
> $ cat CMakeLists.txt
> cmake_minimum_required(VERSION 2.8)
> 
> FUNCTION(info_f)
>     set(msg "")
>     foreach(part IN LISTS ARGN)
>           set(msg "${msg}${part}")
>       endforeach()
>     message("[info_f] ${msg}")
> ENDFUNCTION()
> 
> MACRO(info_m)
>     set(msg "")
>     foreach(part IN LISTS ARGN)
>           set(msg "${msg}${part}")
>       endforeach()
>     message("[info_m] ${msg}")
> ENDMACRO()
> 
> message("foo;bar")
> info_f("foo;bar")
> info_m("foo;bar")
> $ cmake .
> foo;bar
> [info_f] foobar
> [info_m]
> $
> 
> > (I like ARGN since it is 'unnamed positional arguments'. Since you have
> > no named arguments, ARGV == ARGN, but generally speaking I can't think
> > of why you'd ever need to use ARGV.)
> 
> Good point.
> 
> > --
> > Matthew
> > 
> > --
> > 
> > Powered by www.kitware.com
> > 
> > Please keep messages on-topic and check the CMake FAQ at:
> > http://www.cmake.org/Wiki/**CMake_FAQ<http://www.cmake.org/Wiki/CMake_FAQ
> > >
> > 
> > Kitware offers various services to support the CMake community. For more
> > information on each offering, please visit:
> > 
> > CMake Support:
> > http://cmake.org/cmake/help/**support.html<http://cmake.org/cmake/help/s
> > upport.html> CMake Consulting:
> > http://cmake.org/cmake/help/**consulting.html<http://cmake.org/cmake/hel
> > p/consulting.html> CMake Training Courses:
> > http://cmake.org/cmake/help/**training.html<http://cmake.org/cmake/help/
> > training.html>
> > 
> > Visit other Kitware open-source projects at http://www.kitware.com/**
> > opensource/opensource.html<http://www.kitware.com/opensource/opensource.h
> > tml>
> > 
> > Follow this link to subscribe/unsubscribe:
> > http://www.cmake.org/mailman/**listinfo/cmake<http://www.cmake.org/mailma
> > n/listinfo/cmake>



More information about the CMake mailing list