1

With CMake if we wanted to create different executables with the same main function we could create a library containing the main function (which is in main.cpp, say) and link it to all execs by:

add_library(main_lib main.cpp)
add_executable(exe1 source1.cpp)
target_link_libraries(exe1 main_lib)

and so on for other executables. This way, however, we have to specify at least one source file for each exec. What if we have no source files and only want to link execs with different libs?

add_executable(exe1) #(1)
target_link_libraries(exe1 some_lib1 main_lib)

Unfortunately, CMake does not allow (1). There is an Object Library that we could use:

add_library(main_lib OBJECT main.cpp) 
add_executable(exe1 $<TARGET_OBJECTS:main_lib>) #(2)
target_link_libraries(exe1 some_lib1)

But (2) produces the following:

CMakeFiles/main_obj.dir/test_caffe_main.cpp.o: In function `main':
test_caffe_main.cpp:(.text+0x0): multiple definition of `main'
CMakeFiles/test_caffe_main.testbin.lib.dir/test_caffe_main.cpp.o:test_caffe_main.cpp:(.text+0x0): first defined here

How can we reuse an object file containing a main function in different executables when there are no other source files?

EDIT: Object Library works very well with main functions. It turned out I did include a second main by a mistake. Sorry for posting it!

Adam Kosiorek
  • 1,438
  • 1
  • 13
  • 17
  • How would you link your executable manually on the command line? – Meinersbur Sep 06 '14 at 00:15
  • 1
    Libraries are not meant to contain `main` functions. Think of the trouble linking multiple such libraries. Instead, consider creating a `library_main` that you call from the executable's main. You can actually add that `main.cpp` to multiple executables and link different libraries to it. – Meinersbur Sep 06 '14 at 00:21
  • Another suggestion: Create an /empty/ `main.cpp` (or just containing a never used symbol) and use that for `add_executable`. – Meinersbur Sep 06 '14 at 00:24
  • On the command line I'd create an object file from `main.cpp` and reuse that object file in every executable I wanted to create. CMake's Object Library is supposed to behave this way, but it doesn't work when a `main` is involved. A dummy source file added in each `add_executable` call works, but it's a hack I'd rather not use. – Adam Kosiorek Sep 06 '14 at 08:20
  • @Meinersbur `Libraries are not meant to contain main functions` it's not true, e.g. gtest is designed this way. –  Sep 06 '14 at 08:53
  • 1
    `it doesn't work when a main is involved` works for me. Seems that in case `(2)` library `some_lib1` already using `$` (?) –  Sep 06 '14 at 08:56
  • 1
    Also note that for some generators object-library not working if target contain no real sources, from [documentation](http://www.cmake.org/cmake/help/v3.0/command/add_library.html): `Some native build systems may not like targets that have only object files, so consider adding at least one real source file to any target that references $`. So you have to add a dummy file anyway if you want to use objects. –  Sep 06 '14 at 08:58
  • 2
    I've created a dummy executable with no real sources, but there are a one more problem: cmake determine the linker language (like C or CXX) from the sources of executable (like if foo.cpp -> CXX, foo.c -> C), so if you not specifying any sources you need to set it explicitly with `set_target_properties(... PROPERTIES LINKER_LANGUAGE CXX)` –  Sep 06 '14 at 09:10
  • 1
    @ruslo thanks for your tips. It turned out that I did include a second main by a mistake and that object libs work very well with a main function. I didn't know about the dummy exe with explicitly set target properties, thanks! If you posted an answer I'd accept it. – Adam Kosiorek Sep 06 '14 at 12:23
  • 1
    @Meinersbur: I too used to think that shared libraries were not to contain `main()`. Then I read this: http://stackoverflow.com/questions/1449987/building-a-so-that-is-also-an-executable/1451482#1451482 - another commenter here mentioned gtest, ld-linux.so is another example. – John Zwinck Sep 06 '14 at 12:32

1 Answers1

1

Using object library

Looks like you unintentionally link library to target:

add_library(with_main OBJECT main.cpp)
add_executable(foo $<TARGET_OBJECTS:with_main>) # Target without any source files

# target_link_libraries(foo with_main) # Not needed here

Issues

The object-library approach may not work* for some generators. See documentation:

Some native build systems may not like targets that have only object files,
so consider adding at least one real source file to any
target that references $<TARGET_OBJECTS:objlib>

*I have some troubles on Xcode earlier, but now I test this example an it works (cmake 3.0.1 installed by homebrew)

Without objects

You can do it without objects (just pass empty string):

add_library(with_main main.cpp)
add_executable(foo "")
target_link_libraries(foo with_main)

but in this case CMake can't determine the linker for target foo. Usually this done by analizing list of sources (foo.cpp -> linker CXX, foo.c -> linker C). Now you need to set it explicitly:

set_target_properties(foo PROPERTIES LINKER_LANGUAGE CXX)