0

I am looking for a way to tell CMake to make an include directory appear under another name to the compiler.

Let's say I have a project that needs code from a foreign library. This code resides in a directory foreignLib-1.5.0_build123456 in my project's root directory. From time to time I will want to update this library and in this process change the library directory name.

I want to reference this directory as foreignLib in my C++ source files. I want to be able to write

#include "foreignLib/include/lib.h"

and CMake should tell my compiler to translate this to

#include "foreignLib-1.5.0_build123456/include/lib.h"

Now I am wondering:

  • Does a feature like this exist in CMake?
  • If yes, how do I use it?
  • If yes, which compilers are supported?
Chris
  • 6,914
  • 5
  • 54
  • 80
  • 3
    If you're on a Unix-like operating system, you should seriously consider doing this with symbolic links (in the file system). – arne Jun 12 '13 at 07:30
  • This projects aims to be cross-platform so using OS dependant features is not an option. Also, this is using git as version control and it doesn't seem like git can store symbolic links: http://stackoverflow.com/questions/954560/what-does-git-do-to-files-that-are-a-symbolic-link – Chris Jun 12 '13 at 07:32
  • NTFS has symbolic links since Windows Vista. – David Foerster Jun 12 '13 at 07:40
  • @Chris: Have you actually read the accepted answer to the question you referenced? It states that git _can_ store symlinks and handles them just like one would expect. But for cross-platform projects, this is of course not an option. – arne Jun 12 '13 at 07:51
  • @arne Yes, indeed, my bad. I read git stores symlinks as blob and expected it to just copy the link target, but on closer examination it only copies the symlink information and not the target. But still, the problem with incompatible filesystems remains. Git does not use NTFS symlinks: http://stackoverflow.com/questions/11662868/what-happens-when-i-clone-a-repository-with-symlinks-on-windows – Chris Jun 12 '13 at 08:06
  • @Chris Yeah, this is not cross-platform safe, especially if you have to support NTFS and the like. – arne Jun 12 '13 at 08:27

4 Answers4

2

I'd probably just copy the entire include directory into my build tree and make that available.

A decent way of doing that is to use file(GLOB_RECURSE ...) to gather a list of files in the includes folder, then use configure_file(<input> <output> COPYONLY) to copy them to the build tree.

By using configure_file, the files in the build tree are only replaced as required. This means that re-running CMake won't automatically make these files appear out-of-date to the build tool, hence avoiding an unnecessary recompilation.

set(ForeignLibName foreignLib-1.5.0_build123456)
set(ForeignLibRoot ${CMAKE_SOURCE_DIR}/${ForeignLibName})
file(GLOB_RECURSE IncludeFiles RELATIVE ${ForeignLibRoot} ${ForeignLibRoot}/*)
foreach(IncludeFile ${IncludeFiles})
  configure_file(${ForeignLibRoot}/${IncludeFile}
                 ${CMAKE_BINARY_DIR}/${ForeignLibName}/foreignLib/${IncludeFile}
                 COPYONLY)
endforeach()

include_directories(${CMAKE_BINARY_DIR}/${ForeignLibName})

This should allow you to do:

#include "foreignLib/include/lib.h"

When you update the foreign library, you'd have to ensure that you also updated the CMakeLists.txt so that CMake re-runs the next time you go to build. Updating the CMakeLists.txt should only involve changing the single line set(ForeignLibName ...).

Fraser
  • 74,704
  • 20
  • 238
  • 215
1

You could have a look at Cmake's configure_file: Rename your source file into yourfile.cpp.in and do

#include ${DIR_TO_LIB}/include/xy.h

In your CMakeLists, you set the variable DIR_TO_LIB somehow (by parsing command line or something) and issue

configure_file(yourfile.cpp.in, yourfile.cpp)

This will yield yourfile.cpp with the correct path set.

This is probably not exactly what you intended, but I think it would work.

arne
  • 4,514
  • 1
  • 28
  • 47
0

As part of the build process generate an include file at a well known location (later on called "boilerplate/foreignLib_lib.h") with the real include path.

your code file:

#include "boilerplate/foreignLib_lib.h"

boilerplate/foreignLib_lib.h:

#include "foreignLib-1.5.0_build123456/include/lib.h"
David Foerster
  • 1,461
  • 1
  • 14
  • 23
0

Use CMake's include_directories statement or add an -I switch to the *_CXX_FLAGS to add the current foreignLib path to your include path.

David Foerster
  • 1,461
  • 1
  • 14
  • 23
  • That is actually just what I thought of, only that I still want to have a directory containing the files. If I add `foreignLib-1.5.0_build123456/` to my include path, I will reference the files with `#include "include/lib.h"` but I do not want that. The foreign lib include files should not potentially shadow other files from other foreign libs or my project. – Chris Jun 12 '13 at 08:08
  • Then you should add another directory level: `foreignLib-1.5.0_build123456/foreignLib/include/lib.h` – David Foerster Jun 12 '13 at 08:14
  • Yes, but the idea was to keep the `foreignLib-1.5.0_build123456` name from extracting the tarball of the foreign lib so I can just replace it next time. If there are additional steps that I have to take after unzipping, I might as well just change the directory name altogether, but that's not what I want to do. – Chris Jun 12 '13 at 08:17