Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding multiple executables in CMake

My code in a C++ project is organised as follows

  • I have several .cpp and .h files which contains my classes
  • I have several .cxx files which have to be compiled against the .cpp files and some external libraries.

Now, each of the .cxx files have a main() method, so I need to add a different executable for each of these files having the same name as the file.

Also, these .cxx files might not get linked to the same external libraries.

I want to write this build in CMake, in which I am kind of a newbie, how do I go about this?

like image 549
ssb Avatar asked Jan 13 '13 18:01

ssb


People also ask

What does Add_subdirectory do in CMake?

Add a subdirectory to the build. Adds a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.

What is Add_executable?

add_executable(<name> IMPORTED [GLOBAL]) An IMPORTED executable target references an executable file located outside the project. No rules are generated to build it, and the IMPORTED target property is True .

What is Add_library in CMake?

add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [<source>...]) Adds a library target called <name> to be built from the source files listed in the command invocation. The <name> corresponds to the logical target name and must be globally unique within a project.


1 Answers

My suggestion is to tackle this in two phases:

  1. Build a library from the .cpp and .h files, using add_library
  2. Iterate through all your .cxx files and create an executable from each, using add_executable and foreach

Build the library

This could be something as simple as

file( GLOB LIB_SOURCES lib/*.cpp ) file( GLOB LIB_HEADERS lib/*.h ) add_library( YourLib ${LIB_SOURCES} ${LIB_HEADERS} ) 

Build all the executables

Simply loop over all the .cpp files and create separate executables.

# If necessary, use the RELATIVE flag, otherwise each source file may be listed  # with full pathname. RELATIVE may makes it easier to extract an executable name # automatically. # file( GLOB APP_SOURCES RELATIVE app/*.cxx ) file( GLOB APP_SOURCES app/*.cxx ) foreach( testsourcefile ${APP_SOURCES} )     # I used a simple string replace, to cut off .cpp.     string( REPLACE ".cpp" "" testname ${testsourcefile} )     add_executable( ${testname} ${testsourcefile} )     # Make sure YourLib is linked to each app     target_link_libraries( ${testname} YourLib ) endforeach( testsourcefile ${APP_SOURCES} ) 

Some warnings:

  • file( GLOB ) is usually not recommended, because CMake will not automatically rebuild if a new file is added. I used it here, because I do not know your sourcefiles.
  • In some situations, source-files may be found with a full pathname. If necessary, use the RELATIVE flag for find( GLOB ... ).
  • Manually setting the source-files requires a change to CMakeLists.txt, which triggers a rebuild. See this question for the (dis-)advantages of globbing.
  • I generated the testname using a string( REPLACE ... ). I could have used get_filename_component with the NAME_WE flag.

Concerning "general" CMake info, I advise you to read some of the broad "CMake Overview" questions already asked here on stackoverflow. E.g.:

  • CMake tutorial
  • What are the dusty corners a newcomer to CMake will want to know?
like image 192
André Avatar answered Oct 06 '22 14:10

André