20

I'm trying to build an object file using CMake, but I can't seem to get CMake to build something other than a complete executable. I'm basically looking for the result of the following compilation (the result will be loaded on a VxWorks target and linked then):

$(CC) $(CFLAGS) $(INC_DIRS) -c src/object.c

I've tried changing the OUTPUT_NAME property of the target, but that doesn't seem to help, either.

I think I could work around this by using a custom command, but that seems like I'm also working around the nice things that CMake provides.

Thanks for your help!

Kevin
  • 16,549
  • 8
  • 60
  • 74
Nick
  • 201
  • 1
  • 2
  • 3
  • I am wondering why you want the object-file. Is it not possible to build a static lib with CMake? If necessary, a static lib from only one source file? Alternatively you could try to link the executable anyway and "re-use" the generated object-files – André Jan 24 '11 at 09:00
  • @Andre One advantage would be to work on fixing compile errors for a single file when you know there are also compile errors elsewhere in the project (for instance if you're working closely with another developer on code that's not yet ready for general consumption) without needing to edit `CMakeLists.txt` files. – Kyle Strand Sep 12 '15 at 00:12

3 Answers3

8

This answer was given to me in the CMake mailing list and it worked like a charm:

Look at the following ${CMAKE_SOURCE_DIR}/cpo script:

#!/bin/sh
d=$1; shift
while [ "$1" != "--" ]; do
  cp $1 $d/$(basename $1); shift
done

Now, look at the following CMakeLists.txt:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(CPO C) 
FILE(WRITE ${CMAKE_BINARY_DIR}/f.c "void f(void){}\n")
ADD_LIBRARY(f SHARED f.c)
SET_TARGET_PROPERTIES(f PROPERTIES RULE_LAUNCH_LINK
  "${CMAKE_SOURCE_DIR}/cpo ${CMAKE_BINARY_DIR} <OBJECTS> --"
)

The launch script "cpo" makes the target "f" produce object files in the directory passed in as the first parameter instead of a library; everything else should be business as usual. The key is the script's access to the <OBJECTS> placeholder, so it can operate on the object files while the actual link command after the "--" is ignored. That way, you can use all of CMake's capabilities for the compilation and intercept right before linking takes place. IMO, that's a quite clean solution which should be easily adaptable to your needs; the downside is that the use of RULE_LAUNCH_LINK is limited to Makefile generators.

Ayush
  • 457
  • 8
  • 16
watashi16
  • 145
  • 2
  • 6
4

Since CMake 3.1, CMake has had the ability to create Object libraries:

The OBJECT library type defines a non-archival collection of object files resulting from compiling the given source files.

To only create the object file (no library or executable), use this OBJECT keyword with the add_library() command:

# This will create object.c.o (or object.c.obj on Windows) when built.
add_library(MyObj OBJECT ${CMAKE_CURRENT_SOURCE_DIR}/src/object.c)

You can later reference the object file(s) to be compiled into other libraries or executables:

add_library(MyLibrary STATIC $<TARGET_OBJECTS:MyObj> MyClass1.cpp Helpers.cpp)
Kevin
  • 16,549
  • 8
  • 60
  • 74
  • Why won't `add_library(MyLibrary STATIC MyObj MyClass1.cpp Helpers.cpp)` work? – einpoklum Nov 10 '21 at 11:07
  • 1
    @einpoklum The arguments for `add_library` following the `STATIC` keyword (or other library type keyword) should be *source* files. Because `MyObj` is not a source file, but a target name, we must tell CMake about this special case by referencing it with `TARGET_OBJECTS`. – Kevin Nov 12 '21 at 14:06
  • I was under the mistaken impression that files are constitute targets. – einpoklum Nov 12 '21 at 14:18
2

I would go the custom command path. Remember you can still use those object files for compilation with CMake latter if you set the GENERATED and EXTERNAL_OBJECT source file properties.

RobertJMaynard
  • 2,183
  • 14
  • 13