5

Although this duplicate is a very similliar question, it predates the methodology I'm asking about ("imported object libraries"), which was added to Cmake in version 3.9.6 ~1 year ago(?) hence none of the answers there address this.


I've just started using cmake and I'm trying to more or less replicate this kind of behaviour from a makefile:

foo: foo.cpp bar.o
    $(CXX) $^ -o $@

bar.o:
    cp $(EXTERNAL_DIR)/bar.o .

So bar.o is just being copied in from outside. It's not being built, etc. Then it's compiled into the foo target.

In the Cmake documentation this seems pretty straightforward; to import the .o file:

add_library(bar OBJECT IMPORTED GLOBAL)
set_property(TARGET bar PROPERTY IMPORTED_LOCATION ${EXTERNAL_DIR}/bar.o)

And to use it:

add_executable(foo $<TARGET_OBJECTS:bar> foo.cpp) 

But when the build runs, I get all missing symbols for the stuff that's supposed to be in bar.o -- and run verbosely, it's clear why: Cmake never uses it for anything. It's not mentioned in the compiler invocation, and grepping through the build directories, it's not mentioned in any of the generated makefiles either.

Further, I can change the IMPORTED_LOCATION to something non-existent and it doesn't care. It runs exactly the same way.

What have I misunderstood here? How do I get this done (and without having to add anything to EXTERNAL_DIR)?

CodeClown42
  • 11,194
  • 1
  • 32
  • 67
  • Possible duplicate of [how to add prebuilt object files to executable in cmake](https://stackoverflow.com/questions/38609303/how-to-add-prebuilt-object-files-to-executable-in-cmake) – Tsyvarev Jul 15 '18 at 07:17

2 Answers2

4

Your approach looks good with one notable exception (CMake's documentation is not clear here and is going to be fixed with CMake's next release; see Merge Request !2216).

You should use IMPORTED_OBJECTS target property instead of IMPORTED_LOCATION.

See https://cmake.org/cmake/help/git-stage/command/add_library.html#imported-libraries:

The most important such property is [IMPORTED_LOCATION}(https://cmake.org/cmake/help/git-stage/prop_tgt/IMPORTED_LOCATION.html#prop_tgt:IMPORTED_LOCATION) (and its per-configuration variant IMPORTED_LOCATION_<CONFIG>) which specifies the location of the main library file on disk. Or, for object libraries, IMPORTED_OBJECTS (and IMPORTED_OBJECTS_<CONFIG>) specifies the locations of object files on disk.

Florian
  • 39,996
  • 9
  • 133
  • 149
1

All you need is this:

add_executable(foo foo.cpp ${EXTERNAL_DIR}/bar.o) 

For future reference, the CMake docs for add_library(... OBJECT) say:

Object libraries cannot be imported, exported, installed, or linked.

Which partly explains why your original approach does not work.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Just a hint: the "linked" part is not true anymore for [CMake version >= 3.12](https://cmake.org/cmake/help/latest/release/3.12.html). – Florian Jul 15 '18 at 07:27
  • @Florian: CMake 3.12 is not even released yet. The solution I gave is simple and works with all versions. – John Zwinck Jul 15 '18 at 11:39
  • Actually it looks like it is 3.9.6+ (in the synopsis under "Imported Libraries", OBJECT appears as an option for that version), and it does work using `IMPORTED_OBJECTS` instead of `_LOCATION` here (v. 3.11). I think [this is the commit](https://gitlab.kitware.com/cmake/cmake/commit/eec93bceec5411e4409b5e3ee5dc301fca6fcbfd) from a year ago. – CodeClown42 Jul 15 '18 at 12:15