Install sources and rebuild from installed sources after build?

Hello CMakers,

Bear with me, as I think this may be an unusual scenario.

I will illustrate it with an example. Let’s say we have a file /home/sam/project/x.m. This file is compiled into /home/sam/project/x.o and then linked to /home/sam/project/ The file has a link to /home/sam/project/x.m to get the sources, and at runtime it can interrogate /home/sam/project/x.m for the source. CMake can accomplish this scheme well, and is what is usually expected.

Now here is the twist. When the file /home/sam/project/ gets installed into /usr/local/lib/, it still refers back to /home/sam/project/x.m for source information; but that file can be modified or deleted. I know this is not a common scenario, as in most compiled languages, there is no link back to the sources.

The way we have dealt with this in our pre-CMake days is to have two separate sets of compilations/linking:

  1. “make”: compile x.m in the user directory, into x.o and link into; and then run tests on that.
  2. “make install”: copy x.m into a system directory (say /usr/local/src/x.m), compile it and link it again, but this time using the copy in /usr/local/src, and install into /usr/local/lib/

I wonder if CMake has a way for us to do the second step (first step CMake can handle well…).


Instead of dealing with absolute paths, my advice would be to use paths relative to the shared library. It’s possible to find the path to the shared library by using dladdr1(). From there, you can traverse to where you expect the source file to be.

Instead of dealing with absolute paths, my advice would be to use paths relative to the shared library.

Thank you Kyle. Your reply is instructive in that what we want to accomplish is not easily doable in CMake.

That’s not what I said.

If you really want to use absolute paths, you could create two different targets that compile from the same source files but have a preprocessor definition to control where it reads the source from at runtime. For example:

add_library(build_lib SHARED ${sources})
target_compile_definitions(build_lib PRIVATE "SOURCE_LOCATION=${CMAKE_CURRENT_SOURCE_DIR}")
add_library(install_lib SHARED ${sources})
target_compile_definitions(install_lib PRIVATE "SOURCE_LOCATION=/usr/local/src")

However, I suggest using relative paths if you can, because that eliminates both the complexity and increased build time (admittedly not much if it’s just a single .o file) associated with compiling the target twice. The CMake executable itself uses this approach - the executable determines its absolute location, then traverses from there to figure out whether it’s in a build directory or install directory, then traverses to its Modules directory to get the files that it needs.

Thank you again. It does give me an idea of what’s possible.