Merge lp:~nschloe/libadjoint/cmake into lp:libadjoint

Proposed by Nico Schlömer
Status: Merged
Approved by: Patrick Farrell
Approved revision: 446
Merged at revision: 433
Proposed branch: lp:~nschloe/libadjoint/cmake
Merge into: lp:libadjoint
Diff against target: 301 lines (+241/-5)
7 files modified
CMakeLists.txt (+24/-0)
INSTALL (+38/-0)
Makefile (+1/-1)
python/CMakeLists.txt (+28/-0)
python/setup.py.in (+15/-0)
src/CMakeLists.txt (+118/-0)
tools/create_python_constants.py (+17/-4)
To merge this branch: bzr merge lp:~nschloe/libadjoint/cmake
Reviewer Review Type Date Requested Status
libadjoint developers Pending
Review via email: mp+187564@code.launchpad.net

Description of the change

Added CMake interface.

To post a comment you must log in.
Revision history for this message
Patrick Farrell (pefarrell) wrote :

Hi Nico!

Thanks for starting this work. libadjoint badly needs it, a proper installation procedure is a high priority.

This is a good start, but it's not quite there.

(a) Could you please change the INSTALL to give instructions on how to build using cmake? (Let's remove the old Makefile completely once this works, it is a mess.) Make sure to mention how to tell cmake to install it in a particular directory.

(b) There is a C header, include/libadjoint/adj_constants.h, that is also necessary to use from Fortran. At present, a simple sed script converts adj_constants.h into adj_constants_f.h, which cmake currently neglects, causing a clean build to fail:

[farrellp@blossom:~/src/libadjoint/build]$ make
Scanning dependencies of target adjoint
[ 5%] Building Fortran object src/CMakeFiles/adjoint.dir/adj_fortran.F90.o
/home/farrellp/src/libadjoint/include/libadjoint/adj_fortran.h:1:0: fatal error: libadjoint/adj_constants_f.h: No such file or directory
compilation terminated.
make[2]: *** [src/CMakeFiles/adjoint.dir/adj_fortran.F90.o] Error 1
make[1]: *** [src/CMakeFiles/adjoint.dir/all] Error 2
make: *** [all] Error 2

Now, the easiest thing to do is to change the .h so that it can be used directly from both C and Fortran. This involves getting rid of all the comments, and renaming adj_scalar_f to adj_f_scalar everywhere.

I'm sure there will be more issues once we overcome this!

Cheerio,

Patrick

lp:~nschloe/libadjoint/cmake updated
434. By Nico Schlömer

added build instructions for CMake

435. By Nico Schlömer

add Fortran header file hack

Revision history for this message
Nico Schlömer (nschloe) wrote :

Even easier: I added the same Fortran header hack to CMake. The hack can be removed at a later time.

Revision history for this message
Patrick Farrell (pefarrell) wrote :

Hey Nico,

Great.

(a) Can you make it build the shared library by default?

(b) The Python bindings need a little bit more work:
  (i) clibadjoint.py (Makefile:315) needs to be generated. The Python bindings depend on this. It's generated using gccxml.
  (ii) clibadjoint_constants.py (Makefile:327) also needs to be generated.
  (iii) clibadjoint.py needs to have the location of libadjoint.so hardcoded in it, which is currently the purpose of Makefile:344.

I think it's close. Hopefully with those changes the Python bindings will work and then this will be mergeable.

Revision history for this message
Nico Schlömer (nschloe) wrote :

I'll just try and literally translate the commands over to CMake. There are so many dark hacks in there though that this part of the configuration should be revised after this.

Revision history for this message
Patrick Farrell (pefarrell) wrote :

I see where you're coming from. We started off without any dark hacks, but unfortunately they turned out to be necessary for different situations (especially OSX, which is a royal pain). For the Python bindings, I'd like

(i) that the ctypes wrapper is generated automatically from the header (currently done with gccxml), and
(ii) ideally, that it is in pure Python (so we don't have an extra external compiled dependency).

Anyway, just translate the dark hacks over and I'll look into changing it when it works.

lp:~nschloe/libadjoint/cmake updated
436. By Nico Schlömer

always build shared library

437. By Nico Schlömer

start working on the python bindings

Revision history for this message
Nico Schlömer (nschloe) wrote :

I just worked some more on the Python binding mess in CMake and I must say that I don't think I get it done. It just takes *so* much time trying to figure out what all those scripts are doing, and I'm having a hard time pointing out debugging since I don't know what the various created files are supposed to look like. Any support appreciated.

Revision history for this message
Nico Schlömer (nschloe) wrote :

> (ii) ideally, that it is in pure Python (so we don't have an extra external
> compiled dependency).

I'd say ideally, the configuration utility, i.e. CMake, takes care of the configuration. All those Python helper scripts should be made redundant.

Revision history for this message
Patrick Farrell (pefarrell) wrote :

I agree it's not obvious, but it's not that bad.

The only complex one is the generation of clibadjoint.py Basically, if you were typing it from the command line, it would look like

cpp -DPYTHON_BINDINGS include/libadjoint/libadjoint.h > include/libadjoint/pylibadjoint.h
sed -i "s/__builtin___stpncpy_chk/__builtin___strncpy_chk/" include/libadjoint/pylibadjoint.h # this is a bug in OSX
python/ctypeslib/scripts/h2xml.py -q -I. include/libadjoint/pylibadjoint.h -o python/libadjoint/libadjoint.xml
rm -f include/libadjoint/pylibadjoint.h
python/ctypeslib/scripts/xml2py.py -r '^adj.*' -l /home/pef/src/libadjoint/lib/libadjoint.so python/libadjoint/libadjoint.xml -o python/libadjoint/clibadjoint.py

Does that help?

I took a quick look at using ctypesgen to generate the ctypes API, but the resulting clibadjoint.py segfaults for some reason I don't yet understand.

lp:~nschloe/libadjoint/cmake updated
438. By Nico Schlömer

fixes to the cmake/python magic

439. By Nico Schlömer

work on after-installation script

440. By Nico Schlömer

don't mess around with clibadjoint.py after installation

Revision history for this message
Nico Schlömer (nschloe) wrote :

> cpp -DPYTHON_BINDINGS include/libadjoint/libadjoint.h > include/libadjoint/pylibadjoint.h

It turns out one cannot use the CXX compiler here, but the *C* compiler. The variable name CPP in Makefile is really misleading. Also, the "-E" option was missing.

I fiddled around some more and I think we might be with CMake where we are with Makefile. Check it out.

That said, there *has* to be a simpler way of generating the Python bindings than the magic dance we're doing right now. Unfortunately I'm not too experienced in this though.

lp:~nschloe/libadjoint/cmake updated
441. By Nico Schlömer

remove redundant comments

Revision history for this message
Patrick Farrell (pefarrell) wrote :

CPP always means the C preprocessor. That's why CXX is the variable name for C++ (usually).

On a clean checkout:

bzr co lp:libadjoint
bzr merge lp:~nschloe/libadjoint/cmake
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp/libadjoint/cmake-install -DBUILD_SHARED_LIBS:BOOL=TRUE

yields an error

-- Found PythonInterp: /usr/bin/python (found version "2.7.3")
Traceback (most recent call last):
  File "/home/pef/src/libadjoint/python/ctypeslib/scripts/xml2py.py", line 10, in <module>
    sys.exit(main())
  File "/usr/lib/pymodules/python2.7/ctypeslib/xml2py.py", line 166, in main
    dlls = [load_library(name) for name in options.dlls]
  File "/usr/lib/pymodules/python2.7/ctypeslib/xml2py.py", line 162, in load_library
    return CDLL(path, mode=mode)
  File "/usr/lib/python2.7/ctypes/__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: /home/pef/src/libadjoint/lib/libadjoint.so: cannot open shared object file: No such file or directory
/home/pef/src/libadjoint/

It looks like it's trying to generate the Python bindings before the library is actually built.

Aside: At the moment, it's rigged up to automatically generate the Python bindings each time the library is compiled. But libadjoint is pretty stable, and its API isn't going to change dramatically; and as you point out, the Python binding generation is complicated and confusing for other contributors. I'd be happy instead to just freeze the automatically generated Python bindings --- to add clibadjoint.py and clibadjoint_constants.py to the repository, and pull out all of the Python binding generation stuff to a separate script that's invoked manually. What do you think? It would make your life a lot easier.

lp:~nschloe/libadjoint/cmake updated
442. By Nico Schlömer

make sure that custom code is executed *after* libadjoint.so is built

Revision history for this message
Nico Schlömer (nschloe) wrote :

> CPP always means the C preprocessor.

Right! Too often I mix it up with CXX as in "cee plus plus".

I could reproduce the error that you're getting and I think I fixed most of it. The only thing that's not quite consistent yet is the installation of the generated files, but we're getting there.

> Aside: At the moment, it's rigged up to automatically generate the Python bindings each time the library is compiled.

Instead of freezing the bindings, maybe we should look at what other packages with Python interfaces are doing. For one, I keep seeing SWIG a lot. We can check it out later.

Revision history for this message
Patrick Farrell (pefarrell) wrote :

Same attempt at building:

bzr co lp:libadjoint
cd libadjoint
bzr merge lp:~nschloe/libadjoint/cmake
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/tmp/libadjoint/cmake-install -DBUILD_SHARED_LIBS:BOOL=TRUE
make
Removing libadjoint.xml...
Changing permissions on clibadjoint.py...
Adaptations for clibadjoint.py...
/bin/sh: 1: Syntax error: "(" unexpected
make[2]: *** [src/libadjoint.so.0.9.2] Error 2
make[1]: *** [src/CMakeFiles/adjoint.dir/all] Error 2
make: *** [all] Error 2

Any thoughts? Almost there.

lp:~nschloe/libadjoint/cmake updated
443. By Nico Schlömer

create clibadjoint_constants.py in the build directory

444. By Nico Schlömer

make sure to install the generated python files

Revision history for this message
Nico Schlömer (nschloe) wrote :

It should be good to install now.

Revision history for this message
Patrick Farrell (pefarrell) wrote :

Hey Nico,

The CMake install looks great, now. I think that's correct.

I'd like to keep the Makefile pathway available for a little while (especially with platforms like OSX, where the OS is broken in countless little ways). You changed tools/create_python_constants.py to take in a source_path and a target_path; can you modify the Makefile, too? Should be just change

@python ./tools/create_python_constants.py

to

@python ./tools/create_python_constants.py $(PWD) $(ABSDESTDIR)

Also: do you know anything about changing the Debian packaging to use CMake (debian/rules)? I think we should make it the default. If you don't know anything about this, I'll try to figure out it later this week.

Revision history for this message
Patrick Farrell (pefarrell) wrote :

Update: the Debian packaging *might* be as easy as changing

dh --with=$(PYSUPPORT) $@

to

dh --buildsystem=cmake --with=$(PYSUPPORT) $@

in debian/rules.

lp:~nschloe/libadjoint/cmake updated
445. By Nico Schlömer

make sure the Makefile works again

Revision history for this message
Nico Schlömer (nschloe) wrote :

> target_path; can you modify the Makefile, too? Should be just change
> @python ./tools/create_python_constants.py
> to
> @python ./tools/create_python_constants.py $(PWD) $(ABSDESTDIR)

Done.

> Also: do you know anything about changing the Debian packaging to use CMake
> (debian/rules)?

Yes. The easiest (and recommended) way for this would be to have

%:
  dh $@ --with python2

in `rules`. This should take care of everything automatically. Also, `cmake` should go in the Build-Depends in `control`. Check out https://wiki.debian.org/Python/TransitionToDHPython2 for more details if needed, or see my Trilinos Debian builds, <https://github.com/nschloe/trilinos-ubuntu/tree/master/debian.raring> (which are similar to libadjoint in that Trilinos contains Fortran and Python extensions as well).

Revision history for this message
Patrick Farrell (pefarrell) wrote :

Yes, I already do use dh in debian/rules. The issue is that in dh's list of possible build targets, a simple makefile comes before cmake (see dh_auto_build --list). That's why we need to tell it to use cmake explicitly.

Revision history for this message
Nico Schlömer (nschloe) wrote :

Ah I see. Well, you've got it figured out already.
Feel free to merge the branch and move it over to bitbucket/github then. :)

Revision history for this message
Patrick Farrell (pefarrell) wrote :

One quick question. Is it possible to get cmake to build both the shared and static versions of the library?

lp:~nschloe/libadjoint/cmake updated
446. By Nico Schlömer

build both shared and static libraries by default

Revision history for this message
Nico Schlömer (nschloe) wrote :

I added this functionality, but I must say I find it somewhat unclean since this is a decision that the user classically has to make at configure time. All objects need to be rebuilt anyways.

Revision history for this message
Patrick Farrell (pefarrell) wrote :

I appreciate where you're coming from. The only reason I ask is that I want to build both the .a and the .so for the Debian packaging. If you can suggest a cleaner way (where there's a command line -DCMAKE_SOME_SWITCH) to turn on building the .a, I'd be all for it.

Revision history for this message
Nico Schlömer (nschloe) wrote :

I remember that I once tried to do something similar, but couldn't find a clean solution. I would suggest to build both shared and static the way it is done right now, and revisit this later.

Revision history for this message
Patrick Farrell (pefarrell) wrote :

Dear Nico,

Nice work! I think my modifications of your branch at lp:~libadjoint/libadjoint/cmake are in an mergeable state.

I have one last question. Debian packages require
(a) a different layout of Python files (setup.py install --install-layout=deb)
(b) building with each of the versions of Python on the system (loop over pyversions -r)
(c) to install into DESTDIR/prefix (so that it can bundle all the files in DESTDIR)

Currently these things aren't taken care of by the CMake build system. Do you think it is possible? If so, we could set the Debian packaging to build with CMake, and get rid of the Makefile entirely.

If not, I'll merge the branch, although I think it's a bit ugly to have one build system for Debian packaging and one for users installing from source.

Revision history for this message
Nico Schlömer (nschloe) wrote :

I'm not sure if I unterstand completely. Is there a repo for the Debian packaging of libadjoint so I can look at it?

> (a) a different layout of Python files (setup.py install --install-layout=deb)

No Debian package should install files outside of the build tree, and libadjoint doesn't either. Everything seems okay to me.

> (b) building with each of the versions of Python on the system (loop over pyversions -r)

Isn't the Debian packager taking care of Python versions?

> (c) to install into DESTDIR/prefix (so that it can bundle all the files in DESTDIR)

You can of course specify the prefix (-DCMAKE_INSTALL_PREFIX:PATH=<path>), but I don't think that one should do that.

> If not, I'll merge the branch.

I'd agree with merging, and dealing with the packaging issues in a second thread (maybe already on GitHub/bitbucket).

Revision history for this message
Patrick Farrell (pefarrell) wrote :

All the Debian packaging lives in the main repository, in debian/rules (which sets some variables that are used by Makefile).

(a) I'm not talking about installing files outside the build tree. I'm talking about how they are laid out in the build tree. For example, a python-foo-*.deb will have files in /usr/lib/python2.7/dist-packages/, but setup.py will by default install in site-packages (this is one of the things that python setup.py install --install-layout=deb changes).

(b) Yep. Since I'm the Debian packager, I take care of it, on Makefile:340.

(c) That's different to the prefix. Typically the prefix (./configure --prefix or -DCMAKE_INSTALL_PREFIX) will be /usr, but there's an *additional* variable DESTDIR that gets prepended (e.g. if I'm building in /tmp/foo, DESTDIR will be /tmp/foo/debian/python-foo, and prefix will be /usr, for an install path of /tmp/foo/debian/python-foo/usr/lib/python2.7/dist-packages/foo).

I'll merge anyway.

Thanks for all your help!

Patrick

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'CMakeLists.txt'
2--- CMakeLists.txt 1970-01-01 00:00:00 +0000
3+++ CMakeLists.txt 2013-10-14 16:42:35 +0000
4@@ -0,0 +1,24 @@
5+cmake_minimum_required(VERSION 2.8)
6+
7+project(libadjoint C CXX Fortran)
8+
9+# Set the version. (Used for so-naming of the library.)
10+set(libadjoint_MAJOR_VERSION 0)
11+set(libadjoint_MINOR_VERSION 9)
12+set(libadjoint_PATCH_VERSION 2)
13+set(libadjoint_VERSION
14+ ${libadjoint_MAJOR_VERSION}.${libadjoint_MINOR_VERSION}.${libadjoint_PATCH_VERSION})
15+
16+# Build shared library.
17+SET(BUILD_SHARED_LIBS ON)
18+
19+# Offer the user the choice of overriding the installation directories
20+set(INSTALL_LIB_DIR "lib" CACHE PATH
21+ "Installation directory for libraries")
22+set(INSTALL_BIN_DIR "bin" CACHE PATH
23+ "Installation directory for executables")
24+set(INSTALL_INCLUDE_DIR "include/libadjoint" CACHE PATH
25+ "Installation directory for header files")
26+
27+add_subdirectory(src)
28+add_subdirectory(python)
29
30=== modified file 'INSTALL'
31--- INSTALL 2012-03-23 09:56:49 +0000
32+++ INSTALL 2013-10-14 16:42:35 +0000
33@@ -4,6 +4,44 @@
34 sudo apt-get update
35 sudo apt-get install libadjoint libadjoint-dev python-libadjoint
36
37+Compiling libadjoint
38+====================
39+
40+If you would like to configure and compile libadjoint yourself, you have two
41+possibilities. Using CMake is recommended.
42+
43+Using CMake
44+-----------
45+
46+Create a separate build directory next to the libadjoint source and run CMake
47+in it:
48+
49+$ ls
50+libadjoint-0.9.2
51+$ mkdir build
52+$ cd build
53+$ cmake ../libadjoint-0.9.2
54+
55+All typical CMake commands are available. For example to set the compiler,
56+specify the installation directory, and build a shared library, you would
57+execute
58+
59+$ CC=mpicc CXX=mpicxx FC=mpif90 cmake \
60+ -DCMAKE_INSTALL_PREFIX:PATH=/custom/install/path \
61+ -DBUILD_SHARED_LIBS:BOOL=TRUE \
62+ ../source
63+
64+After the CMake configuration, type
65+
66+$ make
67+$ make install
68+
69+in the build directory to build and install libadjoint.
70+
71+
72+Using Makefile
73+------------
74+
75 The minimum requirements for compiling libadjoint are a C compiler
76 (environment variable CC) and a C++ compiler (environment variable
77 CXX). If these are not specified, the defaults are 'mpicc' and 'mpicxx'.
78
79=== modified file 'Makefile'
80--- Makefile 2013-03-02 14:58:55 +0000
81+++ Makefile 2013-10-14 16:42:35 +0000
82@@ -326,7 +326,7 @@
83 @chmod a-x python/libadjoint/clibadjoint.py
84 python/libadjoint/clibadjoint_constants.py:
85 @echo " PYTHON tools/create_python_constants.py"
86- @python ./tools/create_python_constants.py
87+ @python ./tools/create_python_constants.py $(PWD) $(ABSDESTDIR)
88 endif
89
90 install: lib/libadjoint.a lib/$(SLIB)
91
92=== added file 'python/CMakeLists.txt'
93--- python/CMakeLists.txt 1970-01-01 00:00:00 +0000
94+++ python/CMakeLists.txt 2013-10-14 16:42:35 +0000
95@@ -0,0 +1,28 @@
96+# Python bindings.
97+# <http://bloerg.net/2012/11/10/cmake-and-distutils.html>
98+find_package(PythonInterp)
99+if(PYTHONINTERP_FOUND)
100+ set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")
101+ set(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py")
102+ set(DEPS "${CMAKE_CURRENT_SOURCE_DIR}/libadjoint/__init__.py")
103+ set(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build")
104+
105+ # Generate setup.py
106+ configure_file(${SETUP_PY_IN} ${SETUP_PY})
107+
108+ # Run `python setup.py -q build`
109+ add_custom_command(
110+ OUTPUT ${OUTPUT}/timestamp
111+ COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY}
112+ ARGS -q build
113+ COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT}
114+ DEPENDS ${DEPS}
115+ )
116+
117+ add_custom_target(target ALL DEPENDS ${OUTPUT}/timestamp)
118+
119+ # Run `python setup.py install`
120+ install(CODE
121+ "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} -q install --prefix=${CMAKE_INSTALL_PREFIX})"
122+ )
123+endif()
124
125=== added file 'python/setup.py.in'
126--- python/setup.py.in 1970-01-01 00:00:00 +0000
127+++ python/setup.py.in 2013-10-14 16:42:35 +0000
128@@ -0,0 +1,15 @@
129+from distutils.core import setup, Extension
130+
131+python_utils=Extension("libadjoint.python_utils",
132+ sources=["${CMAKE_CURRENT_SOURCE_DIR}/libadjoint/adj_python_utils.c"]
133+ )
134+
135+setup (name = 'libadjoint',
136+ version = '${libadjoint_VERSION}',
137+ description = 'libadjoint python bindings',
138+ author = 'The libadjoint team',
139+ author_email = 'patrick.farrell06@imperial.ac.uk',
140+ packages = ['libadjoint'],
141+ package_dir={ '': '${CMAKE_CURRENT_SOURCE_DIR}' },
142+ #package_dir = {'libadjoint': 'libadjoint'},
143+ ext_modules = [python_utils])
144
145=== added file 'src/CMakeLists.txt'
146--- src/CMakeLists.txt 1970-01-01 00:00:00 +0000
147+++ src/CMakeLists.txt 2013-10-14 16:42:35 +0000
148@@ -0,0 +1,118 @@
149+include_directories(${libadjoint_SOURCE_DIR}/include)
150+
151+# Here comes a hack: The C headers are adapted for inclusion in Fortran files.
152+# TODO remove this hack
153+execute_process(COMMAND sh -c "sed -e 's@/\\*@!@' -e 's@\\*/@@' -e 's@ADJ_CONSTANTS_H@ADJ_CONSTANTS_F_H@' -e '/adj_scalar /d' ${libadjoint_SOURCE_DIR}/include/libadjoint/adj_constants.h > ${libadjoint_SOURCE_DIR}/include/libadjoint/adj_constants_f.h")
154+execute_process(COMMAND sh -c "grep '^#' ${libadjoint_SOURCE_DIR}/include/libadjoint/adj_error_handling.h | grep -v '^#include' | grep -v 'CHKMALLOC' > ${libadjoint_SOURCE_DIR}/include/libadjoint/adj_error_handling_f.h")
155+
156+file(GLOB libadjoint_SRCS
157+ "${CMAKE_CURRENT_SOURCE_DIR}/*.c"
158+ "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp"
159+ "${CMAKE_CURRENT_SOURCE_DIR}/*.F90"
160+ )
161+file(GLOB libadjoint_HEADERS
162+ "${libadjoint_SOURCE_DIR}/include/libadjoint/*.h"
163+ "${libadjoint_SOURCE_DIR}/include/libadjoint/*.mod"
164+ )
165+
166+# Build both shared and static libraries here. Do not share the object files
167+# (which would be possible using CMake's OBJECT keyword) since objects intended
168+# for linking into a shared library need to be compiled with -fPIC.
169+add_library(adjoint SHARED ${libadjoint_SRCS})
170+
171+set_target_properties(adjoint PROPERTIES
172+ PUBLIC_HEADER "${libadjoint_HEADERS}"
173+ VERSION ${libadjoint_VERSION}
174+ SOVERSION ${libadjoint_MAJOR_VERSION}
175+ )
176+
177+add_library(adjoint-static STATIC ${libadjoint_SRCS})
178+set_target_properties(adjoint-static PROPERTIES
179+ OUTPUT_NAME adjoint
180+ )
181+
182+# Installation of the program
183+install(TARGETS adjoint
184+ # We don't actually need the RUNTIME DESTINATION here since we're only
185+ # installing a library.
186+ RUNTIME DESTINATION "${INSTALL_BIN_DIR}" COMPONENT bin
187+ LIBRARY DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib # .so
188+ ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" COMPONENT shlib # .a
189+ PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}" COMPONENT dev
190+ #PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}/libadjoint" COMPONENT dev
191+ )
192+
193+# -----------------------------------------------------------------------------
194+# Now some hardcore hacks for the Python bindings.
195+find_package(PythonInterp REQUIRED)
196+
197+# 1.) Generate pylibadjoint.h and mess around with it.
198+add_custom_command(TARGET adjoint
199+ POST_BUILD
200+ COMMAND ${CMAKE_C_COMPILER} -E -U__BLOCKS__ -DPYTHON_BINDINGS ${libadjoint_SOURCE_DIR}/include/libadjoint/libadjoint.h > ${CMAKE_BINARY_DIR}/pylibadjoint.h
201+ COMMENT "Generating pylibadjoint.h..."
202+ )
203+ add_custom_command(TARGET adjoint
204+ POST_BUILD
205+ COMMAND sed -i s/__builtin___stpncpy_chk/__builtin___strncpy_chk/ ${CMAKE_BINARY_DIR}/pylibadjoint.h
206+ COMMENT "Adapting pylibadjoint.h..."
207+ )
208+ add_custom_command(TARGET adjoint
209+ POST_BUILD
210+ COMMAND ${libadjoint_SOURCE_DIR}/python/ctypeslib/scripts/h2xml.py -q -I. ${CMAKE_BINARY_DIR}/pylibadjoint.h -o ${CMAKE_BINARY_DIR}/libadjoint.xml
211+ COMMENT "Generating libadjoint.xml..."
212+ )
213+ add_custom_command(TARGET adjoint
214+ POST_BUILD
215+ COMMAND rm -f ${CMAKE_BINARY_DIR}/include/libadjoint/pylibadjoint.h
216+ COMMENT "Removing pylibadjoint.h..."
217+ )
218+ get_filename_component(LIB_REALPATH ${CMAKE_BINARY_DIR}/src/libadjoint.so
219+ REALPATH
220+ )
221+ add_custom_command(TARGET adjoint
222+ POST_BUILD
223+ COMMAND ${libadjoint_SOURCE_DIR}/python/ctypeslib/scripts/xml2py.py -r '^adj.*' -l ${LIB_REALPATH} ${CMAKE_BINARY_DIR}/libadjoint.xml -o ${CMAKE_BINARY_DIR}/clibadjoint.py
224+ COMMENT "Generating clibadjoint.py..."
225+ )
226+ # Some extra adaptations for OS X.
227+ IF(APPLE)
228+ add_custom_command(TARGET adjoint
229+ POST_BUILD
230+ COMMAND sed -i \"s/._pack_ = 4/._pack_ = 8/\" ${CMAKE_BINARY_DIR}/clibadjoint.py
231+ COMMENT "Adaptations for OS X..."
232+ )
233+ ENDIF()
234+ add_custom_command(TARGET adjoint
235+ POST_BUILD
236+ COMMAND rm -f ${CMAKE_BINDARY_DIR}/libadjoint.xml
237+ COMMENT "Removing libadjoint.xml..."
238+ )
239+ add_custom_command(TARGET adjoint
240+ POST_BUILD
241+ COMMAND chmod a-x ${CMAKE_BINARY_DIR}/clibadjoint.py
242+ COMMENT "Changing permissions on clibadjoint.py..."
243+ )
244+
245+ # 2.) Make sure that the installed clibadjoint.py has the
246+ # location of the shared library hardcoded in it.
247+ add_custom_command(TARGET adjoint
248+ POST_BUILD
249+ COMMAND sed -i -e "s@CDLL\\('${libadjoint_SOURCE_DIR}/lib/libadjoint.so'\\)@CDLL\\('${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}/libadjoint.so'\\)@" -e "s@CDLL\\('${LIB_REALPATH}'\\)@CDLL\\('${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}/libadjoint.so'\\)@" ${CMAKE_BINARY_DIR}/clibadjoint.py
250+ COMMENT "Adaptations for clibadjoint.py..."
251+ )
252+
253+ # 3.) Generate python/libadjoint/clibadjoint_constants.py via
254+ # a Python script.
255+ add_custom_command(TARGET adjoint
256+ POST_BUILD
257+ COMMAND ${PYTHON_EXECUTABLE} ${libadjoint_SOURCE_DIR}/tools/create_python_constants.py ${libadjoint_SOURCE_DIR} ${CMAKE_BINARY_DIR}
258+ COMMENT "Generating clibadjoint_constants.py..."
259+ )
260+
261+# Make sure to install the generated files
262+install(FILES ${CMAKE_BINARY_DIR}/clibadjoint.py
263+ ${CMAKE_BINARY_DIR}/clibadjoint_constants.py
264+ DESTINATION lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/libadjoint/
265+ )
266+# -----------------------------------------------------------------------------
267
268=== modified file 'tools/create_python_constants.py'
269--- tools/create_python_constants.py 2011-11-17 11:35:19 +0000
270+++ tools/create_python_constants.py 2013-10-14 16:42:35 +0000
271@@ -1,6 +1,19 @@
272-#!/usr/bin/python
273-
274-f = open('include/libadjoint/adj_constants.h', 'r')
275+#!/usr/bin/env python
276+
277+import sys
278+if len(sys.argv) > 1:
279+ source_path = sys.argv[1] + '/'
280+else:
281+ source_path = ''
282+print source_path
283+
284+if len(sys.argv) > 2:
285+ target_path = sys.argv[2] + '/'
286+else:
287+ target_path = source_path
288+print target_path
289+
290+f = open(source_path + 'include/libadjoint/adj_constants.h', 'r')
291 constants = {}
292
293 for line in f:
294@@ -14,6 +27,6 @@
295
296 code = 'adj_constants = %s' % repr(constants)
297
298-fc = open('python/libadjoint/clibadjoint_constants.py', 'w')
299+fc = open(target_path + '/clibadjoint_constants.py', 'w')
300 fc.write(code)
301 fc.close()

Subscribers

People subscribed via source and target branches