On 07/07/2011 02:43 PM, Luke Dalessandro wrote: > Hi Everyone, > > I have the following build dependencies that I'm trying to implement in cmake. > > The ultimate target of the build is an archive library, libme.a. > > libme.a is composed of a number of static source files, (s1.cpp, ..., > sn.cpp), and one generated source file, (g.cpp). > > g.cpp is built using a perl script that examines the object files associated > with S. For instance maybe it contains one string array with the names of all > of the symbols in the objects obtained with nm or objdump. > > So traditionally, we have a build cycle that looks like: > > compile s1.cpp -> s1.o > ... > compile sn.cpp -> sn.o > perl getSymbols.pl s1.o ... sn.o -> g.cpp > compile g.cpp -> g.o > archive s1.o ... sn.o g.o ->libme.a > > I'm trying to emulate this with CMake. The only platform we have support for > the getSymbols.pl stuff is on Unix-based systems, in Windows we disable this > particular configuration. > > My current plan is to have a library target libme.a that has the (s1.cpp, > ..., sn.cpp) as its sources, and a second library, libtemp.a, that has g.cpp > as a source. g.cpp is the output of a custom_command that depends on (s1.cpp, > ..., sn.cpp) and is built using getSymbols.pl (modified to account for the > fact that its input is a .a rather than the set of .os). Then I will add a > POST_BUILD custom_command for libtemp.a that extracts the object from > libtemp.a and adds it to the libme.a archive. > > This has the advantage that g.cpp is compiled with all of the same flags as > the rest of the project---I'm not sure that there's a way to do this without > the libtemp intermediate target. I don't know how to add a PRE_LINK command > to libme.a that generates and compiles g.cpp in exactly the way that > everything else is compiled, and I can't add g.cpp as a generated source for > libme.a because I can't depend on the (s1.o, ..., sn.o) object files produced > in its compilation. > > I'm worried that the dependency on the custom g.cpp isn't quite right because > I really depend on their object files. I could depend on libme.a, but that > seems like it will introduce a circular dependency since I update libme.a in > a POST_BUILD command for libtemp.a. I could also just say that > target_link_libraries(me temp) but I don't really want to expose the two > different libraries to users. > > Does anyone know of a cleaner way to do this? > > Luke
Look at the following exemplary project: # CMakeLists.txt: CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR) PROJECT(OBJDEP C) SET(CMAKE_VERBOSE_MAKEFILE ON) FILE(WRITE ${CMAKE_BINARY_DIR}/s1.c "void s1(void){}\n") FILE(WRITE ${CMAKE_BINARY_DIR}/s2.c "void s2(void){}\n") FILE(WRITE ${CMAKE_BINARY_DIR}/s3.c "void s3(void){}\n") FILE(WRITE ${CMAKE_BINARY_DIR}/g.c "") # Initially. ADD_LIBRARY(me STATIC s1.c s2.c s3.c g.c) SET_TARGET_PROPERTIES(me PROPERTIES RULE_LAUNCH_LINK "sh ${CMAKE_SOURCE_DIR}/objects.sh <OBJECTS> --") ADD_CUSTOM_COMMAND(TARGET me POST_BUILD COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/g.cmake COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target me) # objects.sh: if [ "$1" != "--" ]; then OBJECTS="" while [ "$1" != "--" ]; do OBJECTS="${OBJECTS}$1\n"; shift; done echo -ne "${OBJECTS}" > objects.txt fi shift exec $@ # g.cmake: FILE(STRINGS objects.txt OBJECTS) FILE(WRITE g.c.in "/*\n") FOREACH(i IN LISTS OBJECTS) IF(NOT i MATCHES "^.*/g\\.c\\.[^/]*\$") FILE(APPEND g.c.in "${i}\n") ENDIF() ENDFOREACH() FILE(APPEND g.c.in "*/\n") # Actually, use getSymbols.pl here. CONFIGURE_FILE(g.c.in g.c COPYONLY) First of all, the "me" target uses the objects.sh shell script as a launcher at link time to collect the target's object files reliably; since you said that your concern is limited to *nix, this shouldn't be a serious restriction and is also not strictly needed. The check for $1 equaling "--" is necessary since the script is called twice, once for ar with object files and another time for ranlib without. The g.cmake script is run as a POST_BUILD custom command for the "me" target and uses the objects.txt file left by objects.sh to generate a g.c.in template which is finally transferred to the g.c source file by CONFIGURE_FILE(... COPYONLY). This is crucial because g.c must not be touched if the list of object files has not changed, see below. In the end, the POST_BUILD custom command rebuilds the "me" target via CMake's --build switch. This means that the newly (re)generated g.c is compiled and the "me" target relinked. Now, if the custom command does not touch the g.c file - there's no reason to do so since nothing has changed in the meantime - the "me" target's subsequent re-invocation does nothing because all of the target's source and object files are up-to-date; in particular, it doesn't invoke the custom command, so the recursion terminates. The downside of this approach is that the "me" target is sometimes generated more than once - typically twice when the list of object files, i.e. the g.c file, has changed - but this should be bearable. 'hope that helps. Regards, Michael _______________________________________________ Powered by www.kitware.com Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ Follow this link to subscribe/unsubscribe: http://www.cmake.org/mailman/listinfo/cmake