https://public.kitware.com/Wiki/api.php?action=feedcontributions&user=Dakon&feedformat=atomKitwarePublic - User contributions [en]2024-03-28T09:46:53ZUser contributionsMediaWiki 1.38.6https://public.kitware.com/Wiki/index.php?title=BuildingWinDLL&diff=54137BuildingWinDLL2013-09-22T18:58:01Z<p>Dakon: remover superfluous }</p>
<hr />
<div><b> CMake Version 2.8.6 Now has all of this functionality built in</b><br />
<br />
You need to add the following to your CMake file:<br />
<pre><br />
include (GenerateExportHeader)<br />
</pre><br />
Then after you add your library using add_library(...) you should also do the following in your CMake file.<br />
<pre><br />
add_library(MyLibrary ${LIB_TYPE} ${srcs})<br />
GENERATE_EXPORT_HEADER( MyLibrary<br />
BASE_NAME MyLibrary<br />
EXPORT_MACRO_NAME MyLibrary_EXPORT<br />
EXPORT_FILE_NAME MyLibrary_Export.h<br />
STATIC_DEFINE MyLibrary_BUILT_AS_STATIC<br />
)<br />
</pre><br />
<br />
See [http://cmake.org/cmake/help/cmake-2-8-docs.html#module:GenerateExportHeader http://cmake.org/cmake/help/cmake-2-8-docs.html#module:GenerateExportHeader] for the complete help contents.<br />
<br />
<b>PRE CMake 2.8.5 and earlier </b><br />
<br />
'''How to build a Windows DLL (for the NON-Windows Developer). A Short introduction.'''<br />
<br />
Those folks coming from an environment like Linux, OS X or even MinGW may have some initial issues when trying to create a DLL on windows. Usually the problems involve the library symbols NOT getting exported. This article will try to walk you through what needs to be done in order for you to bring your code to an MS compiler successfully.<br />
<br />
<b><br />
This short explanation was taken from a recent post to the cmake mailing list and generally sums up the problem.</b><br/><br />
<code><br />
<i>Visual Studio generates 2 files: one import library (.lib) and one - dynamic library (.dll). GCC (and mingw family) exports all symbols by default, VS doesn't export anything by default. And if your dll doesn't export anything, VS simply doesn't generate the import library (for example, if you generate resource-only dll). The only thing cmake knows is when you using VS generator, library extension to link with -- is .lib. And when you use __declspec( dllexport ), cl.exe puts special marks in objects indicating that this symbol should be exported or imported. Also, VS can tell linker to add some library, as boost does with #pragma's.<br />
</i><br />
<br />
----<br />
<br />
So with all this information, how does all this work with CMake? There are a few pieces of code that you will need to add to your project.<br />
<br />
* Let us first consider the CMake code. In your CMakeLists.txt file you will have something along the lines of:<br />
<br />
<pre><br />
# Allow the developer to select if Dynamic or Static libraries are built<br />
OPTION (BUILD_SHARED_LIBS "Build Shared Libraries" OFF)<br />
# Set the LIB_TYPE variable to STATIC<br />
SET (LIB_TYPE STATIC)<br />
IF (BUILD_SHARED_LIBS)<br />
# User wants to build Dynamic Libraries, so change the LIB_TYPE variable to CMake keyword 'SHARED'<br />
SET (LIB_TYPE SHARED)<br />
ENDIF (BUILD_SHARED_LIBS)<br />
<br />
# Create a target for the library<br />
ADD_LIBRARY(MyLibrary ${LIB_TYPE} MyLibrary.cpp)<br />
</pre><br />
<br />
On MSVC platforms and when building a DLL, CMake will add the following preprocessor definition for you:<br/><br />
<br />
<pre>MyLibrary_EXPORTS</pre><br />
<br />
This is generated by concatenating the name of the target 'MyLibrary' with '_EXPORTS'.<br/><br />
<br />
Now we have to exploit that definition in our code so we need to add some c code into a header that will get included by every class or file in the project. A Good name for this might be <b>DLLDefines.h</b>. Notice I did NOT call it Win32Exports.h as GCC 4.x series has some of these types of definitions that can be used and we should keep all this in a single file (see [http://gcc.gnu.org/wiki/Visibility GCC Visibility] ). So, what is the contents of "DLLDefines.h" you might ask? <br/><br />
<br />
<pre><br />
// Contents of DLLDefines.h<br />
#ifndef _MyLibrary_DLLDEFINES_H_<br />
#define _MyLibrary_DLLDEFINES_H_<br />
<br />
/* Cmake will define MyLibrary_EXPORTS on Windows when it<br />
configures to build a shared library. If you are going to use<br />
another build system on windows or create the visual studio<br />
projects by hand you need to define MyLibrary_EXPORTS when<br />
building a DLL on windows.<br />
*/<br />
// We are using the Visual Studio Compiler and building Shared libraries<br />
<br />
#if defined (_WIN32) <br />
#if defined(MyLibrary_EXPORTS)<br />
#define MYLIB_EXPORT __declspec(dllexport)<br />
#else<br />
#define MYLIB_EXPORT __declspec(dllimport)<br />
#endif /* MyLibrary_EXPORTS */<br />
#else /* defined (_WIN32) */<br />
#define MYLIB_EXPORT<br />
#endif<br />
<br />
#endif /* _MyLibrary_DLLDEFINES_H_ */<br />
</pre><br />
<br />
Ok. Now that we have that code, what do we do with it?<br />
<br />
For every class or function that you want to be exported from your library you need to declare like the following: <br/><br />
<br />
<pre><br />
class MYLIB_EXPORT SomeLibrary<br />
{<br />
// All your normal code here.<br />
};<br />
</pre><br />
<br />
If you have some static functions then you will need something like the following: <br/><br />
<br />
<pre><br />
class MyStaticFunctionClass<br />
{<br />
public:<br />
static MYLIB_EXPORT void MyExportedFunction(int i);<br />
};<br />
</pre><br />
<br />
After all this code is put in place then when you compile your library as a dll, Visual Studio should create the proper set of libraries. <br />
<br />
----<br />
<br />
<b>But wait!</b> I have an existing project that I am bringing to cmake and it already has this type of code in place but the definition that the project uses is different than what CMake produces, now what do I do? Say that project uses <b>COMPILING_DLL</b> as its definition, then you can do the following in CMake: <br/><br />
<br />
<pre><br />
SET_TARGET_PROPERTIES (MyLibrary PROPERTIES DEFINE_SYMBOL "COMPILING_DLL" )<br />
</pre><br />
<br />
I hope this helps explain what needs to be done when porting a linux, OS X or MinGW shared library to Windows.</div>Dakonhttps://public.kitware.com/Wiki/index.php?title=CMakeMacroParseArguments&diff=48942CMakeMacroParseArguments2012-10-13T18:10:12Z<p>Dakon: add obsolete mark</p>
<hr />
<div>[[CMake_User_Contributed_Macros|Back]]<br />
<br />
{{CMake/Template/Obsolete}}<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.<br />
<br />
If you are using CMake 2.8.3 or newer please use the [http://www.cmake.org/cmake/help/v2.8.9/cmake.html#module:CMakeParseArguments CMakeParseArguments] macro provided by the default CMake installation instead of the code below.<br />
<br />
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 />
If you are using CMake version greater than 2.4.7 you may use the following version<br />
which use LIST builtin command FIND which may be more efficient:<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 />
SET(larg_names ${arg_names}) <br />
LIST(FIND larg_names "${arg}" is_arg_name) <br />
IF (is_arg_name GREATER -1)<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 GREATER -1)<br />
SET(loption_names ${option_names}) <br />
LIST(FIND loption_names "${arg}" is_option) <br />
IF (is_option GREATER -1)<br />
SET(${prefix}_${arg} TRUE)<br />
ELSE (is_option GREATER -1)<br />
SET(current_arg_list ${current_arg_list} ${arg})<br />
ENDIF (is_option GREATER -1)<br />
ENDIF (is_arg_name GREATER -1)<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>Dakonhttps://public.kitware.com/Wiki/index.php?title=CMakeMacroParseArguments&diff=48941CMakeMacroParseArguments2012-10-13T18:06:01Z<p>Dakon: /* Definition */ link to CMakeParseArguments documentation</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.<br />
<br />
If you are using CMake 2.8.3 or newer please use the [http://www.cmake.org/cmake/help/v2.8.9/cmake.html#module:CMakeParseArguments CMakeParseArguments] macro provided by the default CMake installation instead of the code below.<br />
<br />
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 />
If you are using CMake version greater than 2.4.7 you may use the following version<br />
which use LIST builtin command FIND which may be more efficient:<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 />
SET(larg_names ${arg_names}) <br />
LIST(FIND larg_names "${arg}" is_arg_name) <br />
IF (is_arg_name GREATER -1)<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 GREATER -1)<br />
SET(loption_names ${option_names}) <br />
LIST(FIND loption_names "${arg}" is_option) <br />
IF (is_option GREATER -1)<br />
SET(${prefix}_${arg} TRUE)<br />
ELSE (is_option GREATER -1)<br />
SET(current_arg_list ${current_arg_list} ${arg})<br />
ENDIF (is_option GREATER -1)<br />
ENDIF (is_arg_name GREATER -1)<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>Dakon