[CMake] RE: Problems about generating CMakeLists files from existing VC++ 6 project

Dekeyser, Kris Kris.Dekeyser at lms.be
Tue Sep 28 05:34:03 EDT 2004


Hello,

Hmm, where to start?

You mention that your files are in different folders. I asume this means
your application consists of different subsystems (e.g. static/shared
libraries). In that case I would suggest that each subsystem gets it's own
CMakeLists.txt including a PROJECT() command, ADD_xxx command (defining the
target for that subsystem) and INSTALL_xxx command. I would recommend to add
INCLUDE_DIRECTORIES and ADD_DEFINITIONS commands to another CMake file that
you include in your CMakeLists.txt.

If one subsystem depends on another, you should add them with
TARGET_LINK_LIBRARIES in the CMakeLists.txt. Typically the dependent project
will also include some headers from the dependency project. You'll need to
include the header directories. That's where the separate cmake file is
handy, because you can simply include that file from another project.

Then, there is the issue of the third party libraries. I'm, not using any of
those that you mention, but I have experiencied that mostly each third party
library has its own requirements. My approach is to create a CMakeLists.txt
for each of them, but without creating a target. The 3rd party project will
contain the specific settings and if another project needs them, it will be
easier to add.

Finally, you keep it all together with CMakeLists.txt files in the parent
directories that contain SUBDIRS statements. Be sure to put them in the
correct order. Dependency projects should be loaded before dependent
projects.

Now let's be specific. I assume the following:

A - B
  - C
  - D
  - E
  - F

Each dir contains a single subsystem (containing subdirs with the source and
header files) or 3rd party library. Dependencies are as follows:

F depends on E & C
E depends on D & B
C depends on B

B is a 3rd party library, E,D and E are (shared) libraries and F is the
final executable.

A's CMakeLists.txt only contains: "SUBDIRS(B C D E F)"

Our code is organized in two directories: "export" (for headers etc that
need to be accessed by other subsystems) and "local" (source and headers
that are only needed for compilation of the subsystem itself). Within each
of these directories there are subdirs "include" (headers), "code" (source),
"resource", etc.

Now here's my trick: for each subsystem I create three files additional to
CMakeLists.txt:

export.cmake - contains everything needed by other subsystems
local.cmake - contains settings only needed by the current susbsystem
link.cmake - contains settings needed for linking to the susbsystem

Typical contents of these files is:

--- export.cmake ---
1 INCLUDE_DIRECTORIES(${<ThisProject>_SOURCE_DIR}/export/include)
2 ADD_DEFINITIONS(-DUSE_MY_CODE)
3 INCLUDE(${<Dependency>_SOURCE_DIR}/export.cmake)

--- local.cmake ---
4 INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/local/include)
5 ADD_DEFINITIONS(-DEXPORT_MY_CODE)
6 FILE(GLOB MySrc ${PROJECT_SOURCE_DIR}/local/code/*.cpp)
7 FILE(GLOB MyHdr1 ${PROJECT_SOURCE_DIR}/local/include/*.h*)
8 FILE(GLOB MyHdr2 ${PROJECT_SOURCE_DIR}/export/include/*.h*)
9 SET(MyHdr ${MyHdr1} ${MyHdr2})
10 SOURCE_GROUP("Header files" FILES ${MyHdr})

--- link.cmake ---
11 SET(LinkLibs <ThisProject> ${LinkLibs})

--- CMakeLists.txt ---
12 PROJECT(<ThisProject>)
13 SET(MySrc)
14 SET(MyHdr)
15 SET(LinkLibs)
16 INCLUDE(${PROJECT_SOURCE_DIR}/export.cmake)
17 INCLUDE(${PROJECT_SOURCE_DIR}/local.cmake)
18 ADD_LIBRARY(${PROJECT_NAME} ${MySrc} ${MyHdr})
19 INCLUDE(${<Dependency>_SOURCE_DIR}/link.cmake OPTIONAL)
20 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LinkLibs})

I've added line numbers to explain:

1 The full path of the subsystem's source dir should be included, because
other projects will include this file. ${PROJECT_NAME} should not be used in
export.cmake because it will refer to the dependent project when it is
loaded.

2 You will typicall need to set some defines or compiler flags whenever you
include headers of this susbsystem. Putting it here makes sure that
dependent projects inherit these settings.

3 You need to include exports of dependencies here if exported headers will
include the dependency headers, thus generating indirect dependencies. If
the dependencies stay local to the current subsystem, this line can be moved
to local.cmake. In our build system I have called this PUBLIC/PRIVATE
dependencies.

4 Makes sure that the project will find the local headers. I believe you can
use the relative paths like "local/include" in local.cmake

5 The definitions set here will only be available to the current subsystem

6-9 Collect the source code and header files. There are some religion wars
about listing source files explicitly in CMake or collecting them
automatically. I just prefer the second method. If you opt for the second
method, just be aware that adding a file means that you need to communicate
that to the other developers in your team. They will need to regenerate the
projects issuing "cmake ." in their root build tree. In the first case the
file should be added to the CMake file and all developers will automatically
have their projects updated. Make your pick.

10 MsDev gadget to have the header files in a separate folder in the IDE.
Optional.

11 The libraries that need to be linked in should be listed here. The list
variable "LinkLibs" should be extended. Add the libraries in front of the
list. This keeps the link list in proper dependency order, sometimes
avoiding unresolved symbols using linking. CMake takes care of inherited
dependencies for link libraries. So you do not need to recurse over the
dependencies yourself.

If this is a CMake project, simply the target name should be sufficient. If
you're dealing with a 3rd party library, this needs a little more work.
Since CMake does not inherit link directories, it's wise to add you third
party libraries with full paths. There will be a lot of exceptions, wich you
need to take care of in this file. Here are some things I encountered:

- if your 3rd party library links with other libraries (eg. Winsock library)
CMake does not know about that. You will probably need to add these
libraries to the list as well.
- if a certain library is only needed in debug mode, you should add the
keyword "debug" to the list in front of the library path. Use "optimized"
for release-only libs.
- if you need to link in an object file, you should add the file path to the
MySrc list instead of the LinkLibs.
- in at least one occasion I needed special link flags when linking in the
library. This is possible, just change the appropriate CMake variable in
link.cmake

12 I maintain a single-target-per-project configuration. This makes the
build system a little bit easier to maintain. Setting the project name equal
to the target name also simplifies things. Unless you have the habbit of
creating exotic target names ...

13-15 The project should initialize the lists

16-17 include the subsystem's own export.cmake and local.cmake

18 create your target and add the source code and header files to the
compile list.

19 for each dependency, the link.cmake should be loaded to populate the
LinkLibs list

20 finally, tell CMake what the depencies are.

That's more or less my way. Be informed that CMake already has a similar
internal system that uses PackageConfig.cmake. I would recommend that you
investigate that system first before you decide to implement our system. The
reason why I opted for a do-it-myself system is that it integrated easier
with our internal procedures.

I have created all the examples on the fly so there may be some typos. Our
own system has more complex files and several hundreds of subsystems and it
would be impractical to extract these. Furthermore in our system the
export.cmake, local.cmake are generated automatically by a quite large set
of macros from a simple config.txt file. The macros are part of my paid work
for my employer, so I cannot disclose these here.

Last, but certainly not least, if you're serious about using CMake I would
recommend that you order a copy of the manual. The book really contains a
lot of information you would never find on the mailing lists, faq, etc.
(most of the info is there alright, just hard to find. I have read the book
five times in a row before I started :-)). The source code is a good source
of information as well, because some flags/variables aren't even explained
in the book. Even though there is a lot of code it does not take a lot of
effort to find your way in the CMake source code.

I have found the CMake team members on this list to be extremely helpfull.
So if you have questions, do not hesitate to ask them.

Best regards, Kris.

> -----Original Message-----
> From: Henry Joye [mailto:henryjoye at yahoo.com]
> Sent: Monday, September 27, 2004 21:12
> To: Kris.Dekeyser at lms.be
> Subject: Problems about generating CMakeLists files from 
> existing VC++6
> project
> 
> 
> Hi, Kris,
> 
> I read from CMake maillists and know you are
> programming in VC++6 using CMake. I am a beginner for
> CMake and want to write CMakeLists.txt files for my
> existing VC++6 project. My project includes multiple
> folders, that means the source files are located in
> multiple folders. I am also using Open Inventor
> libraries, ITK, and Qt libraries. At the beginning, I
> have no idea about how to write CMakeLists.txt files
> for such a large project. Would you please show me any
> of your VC6 based CMakeLists.txt files for me so that
> I can write my own files? And would you pls give me
> any suggestions about how to write CMake files for my
> case?
> 
> Thank you very much.
> 
> Joye
> 
> 
> 		
> _______________________________
> Do you Yahoo!?
> Declare Yourself - Register online to vote today!
> http://vote.yahoo.com
> 
+-+-+- Email Confidentiality Footer +-+-+- 
Privileged/Confidential Information may be contained in this message. If you
are not the addressee indicated in this message (or responsible for delivery
of the message to such person), you may not print, retain, copy nor
disseminate this message or any part of it to anyone and you should notify
the sender by reply email and destroy this message. Neglecting this clause
could be a breach of confidence. Please advise immediately if you or your
employer does not consent to Internet email for messages of this kind.
Opinions, conclusions and other information in this message that are not
related to the official business of my firm shall be understood as neither
given nor endorsed by it.



More information about the CMake mailing list