Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I produce only an object file (*.o) from a CMake build target?

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!

like image 624
Nick Avatar asked Jan 22 '11 00:01

Nick


People also ask

Does CMake create a Makefile?

CMake generates a Unix makefile by default when run from the command line in a Unix-like environment. Of course, you can generate makefiles explicitly using the -G option. When generating a makefile, you should also define the CMAKE_BUILD_TYPE variable.

Where does CMake store object files?

The binary directory is sometimes referred to as the build directory and is where CMake will put the resulting object files, libraries, and executables. CMake will not write any files to the source directory, only to the binary directory.

What is a CMake Object library?

CMake Object Libraries can be used to keep build directories less cluttered and speed up the build process. The traditional workflow for Makefile was to create lots of object files (targets) with the relevant compile options, definitions and link flags.

What is a CMake target?

In general, targets comprise executables or libraries which are defined by calling add_executable or add_library and which can have many properties set. They can have dependencies on one another, which for targets such as these just means that dependent ones will be built after their dependencies.


2 Answers

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.

like image 194
watashi16 Avatar answered Oct 21 '22 21:10

watashi16


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)
like image 23
Kevin Avatar answered Oct 21 '22 20:10

Kevin