0

CMake's add_executable requires providing at least one source file. I find this requirement very strange and I don't see any justification for it.

Before I will continue with illustrating example let me emphasis that I'm not asking for a way around this problem (a trivial one is to use an empty source file as show below). Also I'm not asking for being persuaded that not having there any source file is a bad idea.

What I'm asking is what was the reasoning behind CMake's choice. Maybe there is some obstacle that I just don't know about?

Sources

Let's consider a simple example where we have command line application with plugins to do some actions.

The plugins will be provided by static libraries.

Then we also have a framework for command line tool provided by static library as well. A framework only since it doesn't have the crucial part - action done by plugin.

Finally producing the application is just joining those two static libraries.

plugin.hpp - plugin interface header

#ifndef PLUGIN_HPP
#define PLUGIN_HPP

int invoke_plugin(char const* command);

#endif

my_plugin.cpp - a sample implementation of a plugin

#include <cstdlib>
#include <iostream>

int invoke_plugin(char const* command)
{
    std::cout << "my_plugin invoking command >" << command << "<\n";
    return EXIT_SUCCESS;
}

main.cpp - program framework

#include "plugin.hpp"
#include <cstdlib>

int main(int argc, char* argv[])
{
    if(argc == 2)
        return invoke_plugin(argv[1]);
    else
        return EXIT_FAILURE;
}

Building

Below I show sample steps to build such configuration in both g++ (I used g++ 5.4.0 from Cygwin) and Visual C++ (from 2013 Express).

Both produce what is expected, a running application. And with that approach I can produce various plugin libs and just link them with the framework lib to make new applications with new functionalities.

g++

g++ -c my_plugin.cpp -o my_plugin.o
ar rcs libmy_plugin.a my_plugin.o

g++ main.cpp -o main.o
ar rcs libmain.a main.o

g++ -L./ -lmain -lmy_plugin -o my_app

Visual C++

cl /EHsc /MDd -c ../src/my_plugin.cpp
lib my_plugin.obj

cl /EHsc /MDd -c ../src/main.cpp
lib main.obj

link /MACHINE:X86 /SUBSYSTEM:CONSOLE /OUT:my_app.exe main.lib my_plugin.lib msvcrtd.lib

CMake

This however will not work with CMake. Following CMakeLists.txt:

add_library(my_plugin STATIC my_plugin.cpp)
add_library(main STATIC main.cpp plugin.hpp)

add_executable(my_app)
target_link_libraries(my_app
    PRIVATE main
    PRIVATE my_plugin
)

results in following error (CMake 3.6.2, under Cygwin):

CMake Error at CMakeLists.txt:4 (add_executable):
  add_executable called with incorrect number of arguments


CMake Error at CMakeLists.txt:5 (target_link_libraries):
  Cannot specify link libraries for target "my_app" which is not built by
  this project.


-- Configuring incomplete, errors occurred!

Workaround

There is a trivial workaround. You just have to make an empty source file and add it to add_executable. Then it works just fine.

Why?!

But why does CMake puts such a requirement?

It doesn't seem to make it any simpler for CMake.

It doesn't seem to make it any simpler for CMake users. Even if the scenario shown here is not probable and has a simple workaround it is still some issue.

So what's the point behind CMake making such a requirement?

Adam Badura
  • 5,069
  • 1
  • 35
  • 70
  • 1
    You aren't supposed to put a main function inside a library. The rest of the explanation flows naturally after that. – Matthew Schuchard Jan 07 '17 at 15:18
  • 5
    Possible duplicate of [CMake: Is it possible to build an executable from only static libraries and no source?](http://stackoverflow.com/questions/34234446/cmake-is-it-possible-to-build-an-executable-from-only-static-libraries-and-no-s). I've put the reasoning why CMake forces you to put a source file into [my answer](http://stackoverflow.com/questions/34234446/cmake-is-it-possible-to-build-an-executable-from-only-static-libraries-and-no-s/34255438#34255438) there. – Florian Jan 07 '17 at 20:16
  • Why do you want an application generated by no source files ? What's your aim with CMake? – devopsfun Jan 08 '17 at 12:33
  • Why is it necessary/useful/required to put the unused main function into the lib? Isn't better to make the static lib and link the main function only in case the command line tool is built? This answers your question and made better results. (Most of my projects do not allow unused code for security reasons.) – Th. Thielemann Jan 08 '17 at 22:36
  • @MattSchuchard: Who and where says that I'm not supposed to put a `main` function inside a library? What is his reasoning for that? And if so then why neither of the checked compilers forbids it - only CMake doesn't allow it. Finally have a look at Google Test which does exactly that - provides default `main` as a library that you can link with. – Adam Badura Jan 09 '17 at 01:22
  • @kristian The question you ask doesn't seem to be related to what I ask about. How will my answer help you in explaining CMake choice of forbidding me what I otherwise could do manually (as demonstrated in examples). But to answer your question - it could arise as an edge case or with testing code. Never the less - question remains valid even with no useful purpose. – Adam Badura Jan 09 '17 at 01:25
  • @Th.Thielemann Why "unused"? It is used by the final application. For example have a look at Google Test which does exactly that - provides default main as a library that you can link with. – Adam Badura Jan 09 '17 at 01:25
  • @Florian I didn't find that question earlier. And it seems to me that StackOverflow didn't suggest it while I was typing my question. Your answer there does answer my question as well (as it is basically the same question). I don't find that reasoning convincing - but it is as its. Thanks! – Adam Badura Jan 09 '17 at 01:30
  • Regards unused main(): This function does not add any functionality or interface to the lib. Any application can use invoke_plugin() to achieve the same. The main() is only necessary in case an application shall be created. – Th. Thielemann Jan 09 '17 at 09:28
  • @Th.Thielemann I'm not sure whether you understood provided example. `main` is provided by lib containing the application. So it is very much used there. – Adam Badura Jan 09 '17 at 10:45

0 Answers0