https://public.kitware.com/Wiki/api.php?action=feedcontributions&user=JoseFonseca&feedformat=atomKitwarePublic - User contributions [en]2024-03-29T11:16:28ZUser contributionsMediaWiki 1.38.6https://public.kitware.com/Wiki/index.php?title=CMake_Editors_Support&diff=9112CMake Editors Support2007-05-11T08:12:11Z<p>JoseFonseca: Eclipse CDT tips</p>
<hr />
<div>==CMake Editor Modes==<br />
<br />
There are [[CMake]] syntax highlighting and indentation supports for several editors:<br />
<br />
* Emacs [http://www.cmake.org/CMakeDocs/cmake-mode.el combined syntax highlighting and indentation mode]. To enable it, add the following to your ''.emacs'' file:<br />
<br />
<pre><br />
; Add cmake listfile names to the mode list.<br />
(setq auto-mode-alist<br />
(append<br />
'(("CMakeLists\\.txt\\'" . cmake-mode))<br />
'(("\\.cmake\\'" . cmake-mode))<br />
auto-mode-alist))<br />
<br />
(autoload 'cmake-mode "~/CMake/Docs/cmake-mode.el" t)<br />
</pre><br />
<br />
* VIM [http://www.cmake.org/CMakeDocs/cmake-syntax.vim syntax highlighting] and [http://www.cmake.org/CMakeDocs/cmake-indent.vim indentation mode]. To enable indentation, copy indentation file to your .vim/indent directory, syntax highlighting file to your .vim/syntax directory and add the following to your .vimrc:<br />
<br />
<pre><br />
:autocmd BufRead,BufNewFile *.cmake,CMakeLists.txt,*.cmake.in runtime! indent/cmake.vim <br />
:autocmd BufRead,BufNewFile *.cmake,CMakeLists.txt,*.cmake.in setf cmake<br />
</pre><br />
<br />
* Eclipse [http://www.cthing.com/CMakeEd.asp CMake Editor]. Plug-in for the Eclipse IDE providing syntax coloring and content assist for editing CMakeLists.txt and any file ending in a .cmake extension. Integrates the CMake command reference documentation into the Eclipse Help system.<br />
<br />
* [http://kate.kde.org Kate], KWrite, [http://www.kdevelop.org KDevelop] and all other [http://www.kde.org KDE] applications, which use the kate text-editing component support cmake syntax highlighting. Currently you have to open the settings dialog and choose download (Settings -> Configure Kate -> Editor -> Highlighting -> Download) and there select CMake in the listbox. Then the cmake syntax highlighting definition file for kate will be downloaded and installed. From KDE 3.4 and later cmake syntax highlighting will come with standard KDE.<br />
<br />
* UltraEdit (an approach) save the jpg as text: [[Image:wordfile.jpg]]<br />
<br />
* Enscript [http://tristan-carel.com/pub/patches/enscript/cmake.st syntax highlighting rules]. To enable it:<br />
*# copy <tt>cmake.st</tt> in the <tt>hl/</tt> directory.<br />
*#add the following in the <tt>namerules</tt> section of the <tt>hl/enscript.st</tt> file:<br />
<br />
<pre><br />
/CMakeLists\.txt/ cmake;<br />
/\.cmake.*$/ cmake;<br />
/\.ctest.*$/ cmake;<br />
</pre><br />
<br />
* [http://scintilla.sourceforge.net/SciTEDownload.html SciTE] version 1.73 has CMake support. To enable the feature edit SciTEGlobal.Properties and remove the comment before cmake lines.<br />
<br />
==Creating New Editor Mode==<br />
<br />
The best way to start is to check the logic in existing ones. Make sure to enable indentation for files that match the following file names:<br />
<br />
* CMakeLists.txt<br />
* *.cmake<br />
* *.cmake.in<br />
* *.ctest<br />
* *.ctest.in<br />
<br />
<br />
==Using CMake from Eclipse CDT==<br />
<br />
Eclipse CDT can interoperate with CMake by creating a "Standard Makefile" project, running CMake, and then having CDT to run make on the generated makefiles. Eclipse CDT works better if the build files are somewhere in project directory, either in the top-level directory, or a subdirectory (for example Build).<br />
<br />
The CDT Error Parser cannot handle error messages that span more than one line, which is the default gcc behavior. In order to<br />
force gcc to generate single line error messages with no line wrapping, add to your CMakeLists.txt:<br />
<br />
IF(CMAKE_COMPILER_IS_GNUCC)<br />
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fmessage-length=0")<br />
ENDIF(CMAKE_COMPILER_IS_GNUCC)<br />
IF(CMAKE_COMPILER_IS_GNUCXX)<br />
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmessage-length=0")<br />
ENDIF(CMAKE_COMPILER_IS_GNUCXX)<br />
<br />
In order for the CDT discovery mechanism to catch the compiler options and definitions automatically from the<br />
build output, enable the "Enable build output info discovery" in the project properties and set the CMAKE_VERBOSE_MAKEFILE <br />
variable in your CMakeLists.txt.<br />
<br />
SET(CMAKE_VERBOSE_MAKEFILE ON)<br />
<br />
If you don't want to hard-code this behavior in CMakeLists.txt, you can achieve the same effect by <br />
telling CDT to invoke make as <br />
<br />
make VERBOSE=1<br />
<br />
<br />
{{CMake/Template/Footer}}</div>JoseFonsecahttps://public.kitware.com/Wiki/index.php?title=CMake_User_Contributed_Macros&diff=9111CMake User Contributed Macros2007-05-11T05:38:25Z<p>JoseFonseca: Add another macro, and a link to the CMakeMacro category.</p>
<hr />
<div>'''User Contributed Macros'''<br />
<br />
== Find Modules ==<br />
Although CMake comes with a whole bunch of FindXXX packages, there is a large number of packages there are not covered. The hope is that these user-contributed macros will eventually make their way into the official distribution. Before contributing, please have your FindXXX package conform to the [http://www.cmake.org/cgi-bin/viewcvs.cgi/Modules/readme.txt?root=CMake&view=markup CMake Module Guidelines].<br />
<br />
#[[CMakeUserFindAUTOPACK | Find Autopack]]<br />
#[[CMakeUserFindDirectShow | Find DirectShow]]<br />
#[[CMakeUserFindMySQL | Find MySQL]]<br />
#[[CMakeUserFindPARMETIS | Find ParMetis]]<br />
#[[CMakeUserFindVLD| Find VLD - Visual Leak Debugger]]<br />
#[[CMakeUserUseLATEX| Use LaTeX - Build LaTeX Documents]]<br />
<br />
<br />
[[CMake|Home]] [[CMake_User_Contributed_Macros|Back]]<br />
<br />
== Make Equivalents ==<br />
While attempting to convert a gnu makefile to Cmake, there was <br />
a need to provide some macros to provide equivalent functionality. <br />
<br />
#[[CMakeMacroFilterOut | FILTER_OUT (filter-out)]]<br />
#[[CMakeMacroLibtoolFile | CREATE_LIBTOOL_FILE (create a libtool archive file)]]<br />
<br />
[[CMake|Home]] [[CMake_User_Contributed_Macros|Back]]<br />
<br />
== Some helpers along the way ==<br />
#[[CMakeCopyIfDifferent | COPY_IF_DIFFERENT]]<br />
#[[CMakeMacroMerge | MERGE]] --- Merges two sorted lists into a single sorted list. Useful to keep source and header files next to each other.<br />
#[[CMakeMacroCreateFinalFile | CREATE_FINAL_FILE]] -- create a KDE style final file, which includes all source files, so that the compilation will be noticable faster.<br />
#[[CMakeMacroListOperations | List Operations]] -- A compilation of some helpful list operations.<br />
#[[CMakeMacroParseArguments | PARSE_ARGUMENTS]] -- A macro to help parse arguments for other macros.<br />
#[[CMakeMacroAddCxxTest | ADD_CXXTEXT]] -- A macro to add tests written the CxxTest testing framework.<br />
<br />
See also the list of all macros in the [[:Category:CMakeMacro | CMake Macro category]].<br />
<br />
[[CMake|Home]] <br />
[[CMake_User_Contributed_Macros|Back]]<br />
<br />
== Visual Studio generator helpers ==<br />
When generating Visual Studio projects, the priorities can be <br />
sometimes different than for other generators. These are some<br />
VS-specific (and sometimes not-so-specific) macros that could<br />
help you generate better VS projects.<br />
<br />
#[[CMakeMacroGatherProjectFiles | GatherProjectFiles]] -- create and cache a list of project files by recursively globbing a directory structure<br />
#[[CMakeMacroGenerateProject | GenerateProject]] -- creates a VS project with subgroups that mimic the directory structure<br />
<br />
<br />
[[CMake|Home]] [[CMake_User_Contributed_Macros|Back]]<br />
<br />
{{CMake/Template/Footer}}</div>JoseFonsecahttps://public.kitware.com/Wiki/index.php?title=CMakeCopyIfDifferent&diff=9110CMakeCopyIfDifferent2007-05-11T05:28:22Z<p>JoseFonseca: Add CMakeMacro category</p>
<hr />
<div>Generates a rule to copy each source file from source directory <br />
to destination directory. <br />
<br />
Typical use - <br />
<br />
SET(SRC_FILES head1.h head2.h head3.h)<br><br />
COPY_IF_DIFFERENT( /from_dir /to_dir ${SRC_FILES} IncludeTargets "Includes")<br><br />
ADD_TARGET(CopyIncludes ALL DEPENDS ${IncludeTargets})<br><br />
<br />
will generate rules that look <br />
----<br />
<br />
CopyIncludes: $(CopyIncludes_DEPEND_LIBS) \<br><br />
Include\head1.h \<br><br />
Include\head2.h \<br><br />
Include\head3.h <br><br />
<br><br />
Include\head1.h:<br><br />
@echo Building Copying head1.h /to_dir head1.h...<br><br />
cmake.exe -E copy_if_different /from_dir/head1.h /to_dir/head1.h <br><br />
<br />
----<br />
<br />
MACRO(COPY_IF_DIFFERENT FROM_DIR TO_DIR FILES TARGETS TAGS)<br />
# Macro to implement copy_if_different for a list of files<br />
# Arguments - <br />
# FROM_DIR - this is the source directory<br />
# TO_DIR - this is the destination directory<br />
# FILES - names of the files to copy <br />
# TODO: add globing. <br />
# TARGETS - List of targets<br />
# TAGS - Since only the file name is used<br />
# to generate rules, pre-pend a user <br />
# supplied tag to prevent duplicate rule errors. <br />
SET(AddTargets "")<br />
FOREACH(SRC ${FILES})<br />
GET_FILENAME_COMPONENT(SRCFILE ${SRC} NAME) <br />
# Command to copy the files to ${STEP1}/src, if changed.<br />
SET(TARGET "${TAGS}/${SRCFILE}")<br />
IF("${FROM_DIR}" STREQUAL "")<br />
SET(FROM ${SRC})<br />
ELSE("${FROM_DIR}" STREQUAL "")<br />
SET(FROM ${FROM_DIR}/${SRC})<br />
ENDIF("${FROM_DIR}" STREQUAL "") <br />
IF("${TO_DIR}" STREQUAL "")<br />
SET(TO ${SRCFILE})<br />
ELSE("${TO_DIR}" STREQUAL "")<br />
SET(TO ${TO_DIR}/${SRCFILE})<br />
ENDIF("${TO_DIR}" STREQUAL "")<br />
ADD_CUSTOM_COMMAND(<br />
OUTPUT ${TARGET}<br />
COMMAND ${CMAKE_COMMAND}<br />
ARGS -E copy_if_different ${FROM} ${TO}<br />
COMMENT "Copying ${SRCFILE} ${TO_DIR}"<br />
)<br />
SET(AddTargets ${AddTargets} ${TARGET})<br />
ENDFOREACH(SRC ${FILES})<br />
SET(${TARGETS} ${AddTargets})<br />
ENDMACRO(COPY_IF_DIFFERENT FROM_DIR TO_DIR FILES TARGETS TAGS)<br />
<br />
{{CMake/Template/Footer}}<br />
[[Category:CMakeMacro]]</div>JoseFonsecahttps://public.kitware.com/Wiki/index.php?title=CMakeMacroParseArguments&diff=9109CMakeMacroParseArguments2007-05-11T05:27:54Z<p>JoseFonseca: Add CMakeMacro category</p>
<hr />
<div>[[CMake_User_Contributed_Macros|Back]]<br />
<br />
== Definition ==<br />
<br />
There is a general convention for CMake commands that take optional flags and/or variable arguments. Optional flags are all caps and are added to the arguments to turn on. Variable arguments have an all caps identifier to determine where each variable argument list starts. The PARSE_ARGUMENTS macro, defined below, can be used by other macros to parse arguments defined in this way. Note that this macro relies on the [[CMakeMacroListOperations#LIST_CONTAINS | LIST_CONTAINS]] command.<br />
<br />
<pre><br />
MACRO(PARSE_ARGUMENTS prefix arg_names option_names)<br />
SET(DEFAULT_ARGS)<br />
FOREACH(arg_name ${arg_names})<br />
SET(${prefix}_${arg_name})<br />
ENDFOREACH(arg_name)<br />
FOREACH(option ${option_names})<br />
SET(${prefix}_${option} FALSE)<br />
ENDFOREACH(option)<br />
<br />
SET(current_arg_name DEFAULT_ARGS)<br />
SET(current_arg_list)<br />
FOREACH(arg ${ARGN})<br />
LIST_CONTAINS(is_arg_name ${arg} ${arg_names})<br />
IF (is_arg_name)<br />
SET(${prefix}_${current_arg_name} ${current_arg_list})<br />
SET(current_arg_name ${arg})<br />
SET(current_arg_list)<br />
ELSE (is_arg_name)<br />
LIST_CONTAINS(is_option ${arg} ${option_names})<br />
IF (is_option)<br />
SET(${prefix}_${arg} TRUE)<br />
ELSE (is_option)<br />
SET(current_arg_list ${current_arg_list} ${arg})<br />
ENDIF (is_option)<br />
ENDIF (is_arg_name)<br />
ENDFOREACH(arg)<br />
SET(${prefix}_${current_arg_name} ${current_arg_list})<br />
ENDMACRO(PARSE_ARGUMENTS)<br />
</pre><br />
<br />
== Usage ==<br />
<br />
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.<br />
<br />
<tt><br />
:PARSE_ARGUMENTS(''prefix'' ''arg_names'' ''options'' ''arg1'' ''arg2''...)<br />
</tt><br />
<br />
For each item in ''options'', PARSE_ARGUMENTS will create a variable with that name, prefixed with <tt>''prefix''_</tt>. So, for example, if ''prefix'' is <tt>MY_MACRO</tt> and ''options'' is <tt>OPTION1;OPTION2</tt>, 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.<br />
<br />
For each item in ''arg_names'', PARSE_ARGUMENTS will create a variable with that name, prefixed with <tt>''prefix''_</tt>. 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 <tt>''prefix''_DEFAULT_ARGS</tt> variable containing the list of all arguments up to the first arg_name encountered.<br />
<br />
Here is a simple, albeit impractical, example of using PARSE_ARGUMENTS that demonstrates its behavior.<br />
<br />
<pre><br />
SET(arguments<br />
hello OPTION3 world<br />
LIST3 foo bar<br />
OPTION2<br />
LIST1 fuz baz<br />
)<br />
PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments})<br />
</pre><br />
<br />
PARSE_ARGUMENTS creates 7 variables and sets them as follows:<br />
*<tt>ARG_DEFAULT_ARGS</tt>: <tt>hello;world</tt><br />
*<tt>ARG_LIST1</tt>: <tt>fuz;baz</tt><br />
*<tt>ARG_LIST2</tt>: <tt></tt><br />
*<tt>ARG_LIST3</tt>: <tt>foo;bar</tt><br />
*<tt>ARG_OPTION1</tt>: <tt>FALSE</tt><br />
*<tt>ARG_OPTION2</tt>: <tt>TRUE</tt><br />
*<tt>ARG_OPTION3</tt>: <tt>TRUE</tt><br />
<br />
If you don't have any options, use an empty string in its place.<br />
<pre><br />
PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "" ${arguments})<br />
</pre><br />
Likewise if you have no lists.<br />
<pre><br />
PARSE_ARGUMENTS(ARG "" "OPTION1;OPTION2;OPTION3" ${arguments})<br />
</pre><br />
<br />
== Example ==<br />
<br />
Here is a somewhat more realistic usage of <tt>PARSE_ARGUMENTS</tt>. Let us say that we are creating an application that accepts plugins with components, and we need a CMake macro that makes it easy to compile and link a plugin. The plugin will have some code in it, and it will have to have some sort of factory built in that allows the introspection and creation of components in the plugin. We also may want to embed some scripts in the plugin. The plugin may depend on other libraries and plugins. Finally, we may have some options to determine how the plugin may be compiled or used. We will create a macro command that can be called as follows.<br />
<br />
ADD_PLUGIN(name [AUTO_INSTALL] [NO_MODULE] source1 source2 ...<br />
EXPORTS object1 object2 ...<br />
[AUTOLOAD_SCRIPTS script1 script2 ...]<br />
[LINK_LIBRARIES lib1 lib2 ...]<br />
[DEPENDS plugin1 plugin2 ...]<br />
)<br />
<br />
Although the argument usage is easy for a user to understand (especially one familiar with using other CMake commands), but it can be a hassle for a macro to parse. Of course, <tt>PARSE_ARGUMENTS</tt> will do it for us.<br />
<br />
Here is a vacuous implementation of <tt>ADD_PLUGIN</tt>. It uses <tt>PARSE_ARGUMENTS</tt> to parse the argument specification above, and then simply prints out each argument list and option. Note that this example uses the [[CMakeMacroListOperations#CAR and CDR|CAR and CDR]] macros.<br />
<br />
<pre><br />
MACRO(ADD_PLUGIN)<br />
PARSE_ARGUMENTS(PLUGIN<br />
"EXPORTS;AUTOLOAD_SCRIPTS;LINK_LIBRARIES;DEPENDS"<br />
"AUTO_INSTALL;NO_MODULE"<br />
${ARGN}<br />
)<br />
CAR(PLUGIN_NAME ${PLUGIN_DEFAULT_ARGS})<br />
CDR(PLUGIN_SOURCES ${PLUGIN_DEFAULT_ARGS})<br />
<br />
MESSAGE("*** Arguments for ${PLUGIN_NAME}")<br />
MESSAGE("Sources: ${PLUGIN_SOURCES}")<br />
MESSAGE("Exports: ${PLUGIN_EXPORTS}")<br />
MESSAGE("Autoload scripts: ${PLUGIN_AUTOLOAD_SCRIPTS}")<br />
MESSAGE("Link libraries: ${PLUGIN_LINK_LIBRARIES}")<br />
MESSAGE("Depends: ${PLUGIN_DEPENDS}")<br />
IF (PLUGIN_AUTO_INSTALL)<br />
MESSAGE("Auto install")<br />
ENDIF (PLUGIN_AUTO_INSTALL)<br />
IF (PLUGIN_NO_MODULE)<br />
MESSAGE("No module")<br />
ENDIF (PLUGIN_NO_MODULE)<br />
ENDMACRO(ADD_PLUGIN)<br />
</pre><br />
<br />
Here are some examples of using this macro so you can see how <tt>PARSE_ARGUMENTS</tt> breaks up the arguments.<br />
<br />
{|<br />
|-<br />
! Input || Output<br />
|- style="vertical-align:top"<br />
|<pre><br />
ADD_PLUGIN(MyAppCore NO_MODULE<br />
CoreSource1.cxx CoreSource2.cxx<br />
EXPORTS RequiredObject1 RequredObject2<br />
AUTOLOAD_SCRIPTS startup.py initialize.py<br />
)<br />
</pre><br />
|<pre><br />
*** Arguments for MyAppCore<br />
Sources: CoreSource1.cxx;CoreSource2.cxx<br />
Exports: RequiredObject1;RequredObject2<br />
Autoload scripts: startup.py;initialize.py<br />
Link libraries: <br />
Depends: <br />
No module<br />
</pre><br />
|- style="vertical-align:top"<br />
|<pre><br />
ADD_PLUGIN(MyAppDefaultComponents<br />
Component1.cxx Component2.cxx<br />
EXPORTS Component1 Component2<br />
DEPENDS MyAppCore<br />
AUTO_INSTALL<br />
)<br />
</pre><br />
|<pre><br />
*** Arguments for MyAppDefaultComponents<br />
Sources: Component1.cxx;Component2.cxx<br />
Exports: Component1;Component2<br />
Autoload scripts: <br />
Link libraries: <br />
Depends: MyAppCore<br />
Auto install<br />
</pre><br />
|- style="vertical-align:top"<br />
|<pre><br />
ADD_PLUGIN(PartialDiffEqu<br />
Solver.cxx<br />
DEPENDS MyAppCore MyAppDefaultComponents<br />
LINK_LIBRARIES NumericalAnalysisPackage<br />
EXPORTS SolverObject<br />
)<br />
</pre><br />
|<pre><br />
*** Arguments for PartialDiffEqu<br />
Sources: Solver.cxx<br />
Exports: SolverObject<br />
Autoload scripts: <br />
Link libraries: NumericalAnalysisPackage<br />
Depends: MyAppCore;MyAppDefaultComponents<br />
</pre><br />
|}<br />
<br />
<br />
-----<br />
[[CMake_User_Contributed_Macros|Back]]<br />
<br />
{{CMake/Template/Footer}}<br />
[[Category:CMakeMacro]]</div>JoseFonsecahttps://public.kitware.com/Wiki/index.php?title=CMakeMacroListOperations&diff=9108CMakeMacroListOperations2007-05-11T05:27:14Z<p>JoseFonseca: Add CMakeMacro category</p>
<hr />
<div>[[CMake_User_Contributed_Macros|Back]]<br />
<br />
Lists are an important component of most CMakeLists.txt files. Lists are built automatically from arguments to commands and macros. Thus, we often build lists in variables by calling SET with more than one variable argument. Surprisingly, there are very few CMake commands to handle lists. Here is a compilation of a few basic list manipulation commands.<br />
<br />
== CAR and CDR ==<br />
<br />
Our first operations we take from lisp, a programming language built entirely around lists. Two fundamental functions of lisp are car, which returns the first element of a list, and cdr, which returns a list minus the first element. Here we give implementations of car and cdr CMake macros. Although they are not as efficient as their counterparts in lisp, they can still be surprisingly useful.<br />
<br />
<pre><br />
MACRO(CAR var)<br />
SET(${var} ${ARGV1})<br />
ENDMACRO(CAR)<br />
<br />
MACRO(CDR var junk)<br />
SET(${var} ${ARGN})<br />
ENDMACRO(CDR)<br />
</pre><br />
<br />
Here is a simple example of their use.<br />
<pre><br />
SET(MYLIST hello world foo bar)<br />
<br />
CAR(car ${MYLIST})<br />
CDR(cdr ${MYLIST})<br />
MESSAGE("car: ${car}")<br />
MESSAGE("cdr: ${cdr}")<br />
</pre><br />
The output of the command above is<br />
<pre><br />
car: hello<br />
cdr: world;foo;bar<br />
</pre><br />
<br />
Note that the CAR and CDR macros (as well as the rest of the macros in this document) take advantage of CMake's calling convention of expanding lists into arguments. If you quote the list argument, you get a very different result. If you change the previous example to<br />
<pre><br />
CAR(car "${MYLIST}")<br />
CDR(cdr "${MYLIST}")<br />
MESSAGE("car: ${car}")<br />
MESSAGE("cdr: ${cdr}")<br />
</pre><br />
you get<br />
<pre><br />
car: hello;world;foo;bar<br />
cdr: <br />
</pre><br />
<br />
== LIST_LENGTH ==<br />
<br />
Here is a macro to get the length of a list.<br />
<br />
<pre><br />
MACRO(LIST_LENGTH var)<br />
SET(entries)<br />
FOREACH(e ${ARGN})<br />
SET(entries "${entries}.")<br />
ENDFOREACH(e)<br />
STRING(LENGTH ${entries} ${var})<br />
ENDMACRO(LIST_LENGTH)<br />
</pre><br />
<br />
If you use the LIST_LENGTH macro as follows<br />
<pre><br />
SET(MYLIST hello world foo bar)<br />
<br />
LIST_LENGTH(length ${MYLIST})<br />
MESSAGE("length: ${length}")<br />
</pre><br />
you get this output:<br />
<pre><br />
length: 4<br />
</pre><br />
<br />
== LIST_INDEX ==<br />
<br />
Sometimes you want to get a particular entry of a list. This macro lets you grab the <math>n^\mathrm{th}</math> entry in a list (indexed from 1).<br />
<pre><br />
MACRO(LIST_INDEX var index)<br />
SET(list . ${ARGN})<br />
FOREACH(i RANGE 1 ${index})<br />
CDR(list ${list})<br />
ENDFOREACH(i)<br />
CAR(${var} ${list})<br />
ENDMACRO(LIST_INDEX)<br />
</pre><br />
<br />
If you use LIST_INDEX with the following commands<br />
<pre><br />
SET(MYLIST hello world foo bar)<br />
<br />
LIST_INDEX(first 1 ${MYLIST})<br />
LIST_INDEX(second 2 ${MYLIST})<br />
LIST_INDEX(third 3 ${MYLIST})<br />
LIST_INDEX(fourth 4 ${MYLIST})<br />
MESSAGE("first: ${first}")<br />
MESSAGE("second: ${second}")<br />
MESSAGE("third: ${third}")<br />
MESSAGE("fourth: ${fourth}")<br />
</pre><br />
you get this output:<br />
<pre><br />
first: hello<br />
second: world<br />
third: foo<br />
fourth: bar<br />
</pre><br />
<br />
== LIST_CONTAINS ==<br />
<br />
Sometimes you just want to know if a list contains a particular entry.<br />
<br />
<pre><br />
MACRO(LIST_CONTAINS var value)<br />
SET(${var})<br />
FOREACH (value2 ${ARGN})<br />
IF (${value} STREQUAL ${value2})<br />
SET(${var} TRUE)<br />
ENDIF (${value} STREQUAL ${value2})<br />
ENDFOREACH (value2)<br />
ENDMACRO(LIST_CONTAINS)<br />
</pre><br />
<br />
Here are some simple examples of using LIST_CONTAINS.<br />
<pre><br />
SET(MYLIST hello world foo bar)<br />
<br />
LIST_CONTAINS(contains foo ${MYLIST})<br />
IF (contains)<br />
MESSAGE("MYLIST contains foo")<br />
ENDIF (contains)<br />
<br />
LIST_CONTAINS(contains baz ${MYLIST})<br />
IF (NOT contains)<br />
MESSAGE("MYLIST does not contain baz")<br />
ENDIF (NOT contains)<br />
</pre><br />
The result of the previous examples is:<br />
<pre><br />
MYLIST contains foo<br />
MYLIST does not contain baz<br />
</pre><br />
<br />
-----<br />
[[CMake_User_Contributed_Macros|Back]]<br />
<br />
{{CMake/Template/Footer}}<br />
[[Category:CMakeMacro]]</div>JoseFonsecahttps://public.kitware.com/Wiki/index.php?title=CMakeMacroCreateFinalFile&diff=9107CMakeMacroCreateFinalFile2007-05-11T05:26:35Z<p>JoseFonseca: Add CMakeMacro category</p>
<hr />
<div>[[CMake_User_Contributed_Macros|Back]]<br />
<br />
Sometimes it's faster (and the compiler might be able to optimize better) to include all source files of a project into one source file and compile only this one file instead of all files each one by one. This can be done with the macro CREATE_FINAL_FILE().<br />
<br />
Usage is like this:<br />
<br />
-----<br />
<br />
SET(app_SRCS main.cpp app.cpp bar.c foo.c)<br />
OPTION(ENABLE_FINAL "Enable final all-in-one compilation.")<br />
IF(ENABLE_FINAL)<br />
CREATE_FINAL_FILE(_final.cpp ${_app_SRCS} )<br />
ADD_EXECUTABLE(foo _final.cpp)<br />
ELSE(ENABLE_FINAL)<br />
ADD_EXECUTABLE(foo ${app_SRCS} )<br />
ENDIF(ENABLE_FINAL)<br />
-----<br />
<br />
This example creates an executable named "foo" from the sources main.cpp, app.cpp, bar.c and foo.c. If the option "ENABLE_FINAL" is enabled, these for files will be included in the file "_final.cpp" and only this will be compiled. Otherwise the four source files are compiled one by one as you know it.<br />
And here comes the macro:<br />
<br />
-----<br />
<br />
MACRO(CREATE_FINAL_FILE _filename)<br />
FILE(WRITE ${_filename} "//autogenerated file\n")<br />
FOREACH (_current_FILE ${ARGN})<br />
FILE(APPEND ${_filename} "#include \"${_current_FILE}\"\n")<br />
ENDFOREACH (_current_FILE)<br />
ENDMACRO(CREATE_FINAL_FILE _filename)<br />
<br />
<br />
-----<br />
[[CMake_User_Contributed_Macros|Back]]<br />
<br />
{{CMake/Template/Footer}}<br />
[[Category:CMakeMacro]]</div>JoseFonsecahttps://public.kitware.com/Wiki/index.php?title=CMakeMacroMerge&diff=9106CMakeMacroMerge2007-05-11T05:25:48Z<p>JoseFonseca: Add CMakeMacro category</p>
<hr />
<div>[[CMake_User_Contributed_Macros|Back]]<br />
<br />
# This macro merges elements in sorted lists ALIST and BLIST and stored the result in OUTPUT<br />
MACRO(MERGE ALIST BLIST OUTPUT)<br />
SET(BTEMP ${BLIST})<br />
FOREACH(A ${ALIST})<br />
SET(SORTED)<br />
SET(UNINSERTED 1)<br />
FOREACH(B ${BTEMP})<br />
IF(${UNINSERTED})<br />
IF(${A} STRLESS ${B})<br />
SET(SORTED ${SORTED} ${A})<br />
SET(UNINSERTED 0)<br />
ENDIF(${A} STRLESS ${B})<br />
ENDIF(${UNINSERTED})<br />
SET(SORTED ${SORTED} ${B})<br />
ENDFOREACH(B ${BLIST})<br />
IF(${UNINSERTED})<br />
SET(SORTED ${SORTED} ${A})<br />
ENDIF(${UNINSERTED})<br />
SET(BTEMP ${SORTED})<br />
ENDFOREACH(A ${ALIST})<br />
SET(${OUTPUT} ${BTEMP})<br />
ENDMACRO(MERGE ALIST BLIST OUTPUT)<br />
<br />
# Here is an example that merges *.cpp files and *.h files into a single sorted list<br />
# This would be easier if FILE(GLOB...) properly matches "*.{cpp,h}"<br />
FILE(GLOB ALGEBRAIC_SRCS Implicit/Algebraic/*.cpp)<br />
FILE(GLOB ALGEBRAIC_H Implicit/Algebraic/*.h)<br />
MERGE("${ALGEBRAIC_H}" "${ALGEBRAIC_SRCS}" ALGEBRAIC_SRCS)<br />
<br />
[[CMake_User_Contributed_Macros|Back]]<br />
<br />
{{CMake/Template/Footer}}<br />
[[Category:CMakeMacro]]</div>JoseFonsecahttps://public.kitware.com/Wiki/index.php?title=Category:CMakeMacro&diff=9105Category:CMakeMacro2007-05-11T05:22:35Z<p>JoseFonseca: New page: ''User contributed CMake macros.''</p>
<hr />
<div>''User contributed CMake macros.''</div>JoseFonsecahttps://public.kitware.com/Wiki/index.php?title=CMakeMacroAddCxxTest&diff=9104CMakeMacroAddCxxTest2007-05-11T05:21:37Z<p>JoseFonseca: Initial submission</p>
<hr />
<div>== About ==<br />
<br />
This macro simplifies the inclusion of tests written using the [http://cxxtest.sourceforge.net/ CxxTest testing framework].<br />
<br />
Python is required to generate the test source files on the developer machine.<br />
However, since the generated source files will be placed on the source directory<br />
where the macro is called, there is no need for the end user to have Python<br />
in order to build and run the tests.<br />
<br />
== Definition ==<br />
<br />
Some preamble code:<br />
<pre><br />
# Make sure testing is enabled<br />
ENABLE_TESTING()<br />
<br />
# Use Python interpreter<br />
FIND_PACKAGE(PythonInterp)<br />
</pre><br />
<br />
You need to specify the path to the cxxtestgen.py script. Modify accordingly:<br />
<pre><br />
# Path to the cxxtestgen.py script<br />
SET(CXXTESTGEN ${CMAKE_SOURCE_DIR}/thirdparty/cxxtest/cxxtestgen.py)<br />
</pre><br />
<br />
The actual macro definition:<br />
<pre><br />
MACRO(ADD_CXXTEST NAME)<br />
IF(PYTHONINTERP_FOUND)<br />
ADD_CUSTOM_COMMAND(<br />
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}.cpp<br />
COMMAND<br />
${PYTHON_EXECUTABLE} ${CXXTESTGEN}<br />
--runner=ErrorPrinter<br />
-o ${NAME}.cpp ${ARGN}<br />
DEPENDS ${ARGN}<br />
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}<br />
)<br />
ENDIF(PYTHONINTERP_FOUND)<br />
<br />
ADD_EXECUTABLE(${NAME} ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}.cpp ${ARGN})<br />
<br />
ADD_TEST(${NAME} ${NAME})<br />
ENDMACRO(ADD_CXXTEST)<br />
<br />
</pre><br />
<br />
<br />
== Separate compilation ==<br />
<br />
The above macro generates a single source file for all input test headers. If by some reason you prefer separate compilation of each part, you may use the variation:<br />
<br />
<pre><br />
MACRO(ADD_CXXTEST_SEP NAME)<br />
IF(PYTHONINTERP_FOUND)<br />
# generate the parts<br />
FOREACH(_PART ${ARGN})<br />
GET_FILENAME_COMPONENT(_NAME ${_PART} NAME)<br />
GET_FILENAME_COMPONENT(_NAME_WE ${_PART} NAME_WE)<br />
ADD_CUSTOM_COMMAND(<br />
OUTPUT ${_NAME_WE}.cpp<br />
COMMAND<br />
${PYTHON_EXECUTABLE} ${CXXTESTGEN}<br />
--part<br />
-o ${_NAME_WE}.cpp<br />
${_NAME}<br />
DEPENDS ${_PART}<br />
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}<br />
)<br />
ENDFOREACH(_PART)<br />
<br />
# generate the runner<br />
ADD_CUSTOM_COMMAND(<br />
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}_runner.cpp<br />
COMMAND<br />
${PYTHON_EXECUTABLE} ${CXXTESTGEN}<br />
--runner=ErrorPrinter --root<br />
-o ${NAME}_runner.cpp<br />
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}<br />
)<br />
ENDIF(PYTHONINTERP_FOUND)<br />
<br />
# enumerate all generated files<br />
SET(PARTS ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}_runner.cpp)<br />
FOREACH(_PART ${ARGN})<br />
GET_FILENAME_COMPONENT(_PART_WE ${_PART} NAME_WE)<br />
SET(PARTS ${PARTS} ${_PART_WE}.cpp)<br />
ENDFOREACH(_PART)<br />
<br />
ADD_EXECUTABLE(${NAME} ${PARTS})<br />
<br />
ADD_TEST(${NAME} ${NAME})<br />
ENDMACRO(ADD_CXXTEST_SEP)<br />
</pre><br />
<br />
[[Category:CMake]]<br />
[[Category:CMakeMacro]]</div>JoseFonseca