| | 1 | = CMT feature requests = |
| | 2 | |
| | 3 | by V.Garonne [[BR]] |
| | 4 | Date: 09.28.2006 [[BR]] |
| | 5 | |
| | 6 | |
| | 7 | == 1. Support for tags & macros in the cmt/project.cmt file (DavidQ) == |
| | 8 | |
| | 9 | The particular motivation for this came from LCGCMT, where LHCb wish to install |
| | 10 | it at CERN within an InstallArea, whereas ATLAS does. Currently this implies two separate |
| | 11 | installations, but the ability to do something like: |
| | 12 | |
| | 13 | {{{ |
| | 14 | macro use_strategy "LHCb" without_installarea "ATLAS" with_installarea |
| | 15 | build_strategy $(use_strategy) |
| | 16 | }}} |
| | 17 | |
| | 18 | would allow the use of a single installation. There was also a |
| | 19 | request for support for the "author" keyword. |
| | 20 | |
| | 21 | == 2. Support for native_version use statements (DavidQ) == |
| | 22 | |
| | 23 | This goes together with 3. The suggestion is for support for |
| | 24 | |
| | 25 | {{{ |
| | 26 | use Foo * -native_version=1.2.3 |
| | 27 | }}} |
| | 28 | |
| | 29 | This would require that Foo declared the Foo_native_version macro to |
| | 30 | be set to 1.2.3 (in this example). |
| | 31 | |
| | 32 | == 3. Wildcard or prioritized project dependency support (DavidQ) == |
| | 33 | |
| | 34 | At the moment CMT does not support wildcarded project dependencies. |
| | 35 | This has two significant consequences: |
| | 36 | |
| | 37 | a. It is not easily possible to test a new version of a project |
| | 38 | within the context of an existing project hierarchy. |
| | 39 | |
| | 40 | b. In some cases a project changes faster than the version of e.g. a |
| | 41 | glue package to an external package. If a package within a higher level |
| | 42 | project only depends upon the version of the external package, the project |
| | 43 | needs to be versioned, even though no code changes have taken place. |
| | 44 | |
| | 45 | Take the example of the tdaq-common project. To first order, it only |
| | 46 | depends upon the Boost, for which there is a glue package within the |
| | 47 | LCGCMT project. The Boost version is stable over periods of many |
| | 48 | months, but the LCGCMT project version changes much more frequently |
| | 49 | because other packages (e.g. ROOT) change more frequently. Thus |
| | 50 | currently tdaq-common would need to be changed and rebuilt at a rate |
| | 51 | that's at least as high as that for LCGCMT, even though nothing has |
| | 52 | changed. My proposal was that if a diamond project dependency existed |
| | 53 | (in our case AtlasConditions depends upon tdaq-common, which depends |
| | 54 | upon LCGCMT, and AtlasConditions also depends upon AtlasCore, which |
| | 55 | depends upon Gaudi and then LCGCMT), then as long as one leg of the |
| | 56 | diamond fully specified the project versions, the other leg could |
| | 57 | "weaken" the dependencies with some sort of wildcarding. Thus as long |
| | 58 | as exact versions of AtlasCore, Gaudi and LCGCMT were specified on |
| | 59 | one branch, then tdaq-common could specify a weak dependency against |
| | 60 | LCGCMT, and use the native_version package use statement described in |
| | 61 | 2. above to ensure that the correct version of Boost was used. |
| | 62 | |
| | 63 | I believe a similar scheme could be used to insert an updated project |
| | 64 | version into an existing project tree for test purposes, although I |
| | 65 | haven't thought it through yet. |
| | 66 | |
| | 67 | == 4. Support for <project> placeholder for patterns (DavidQ) == |
| | 68 | |
| | 69 | CMT provides several placeholders for use within patterns, most |
| | 70 | specifically <package>, which is replaced by the package name at |
| | 71 | build time. I'd like to see <project> added in the same way. One |
| | 72 | motivation for this is shown by the existing installed_library |
| | 73 | pattern. This essentially has: |
| | 74 | {{{ |
| | 75 | macro_append <package>_linkopts " -L$(bin) -l<package> <extras> " |
| | 76 | }}} |
| | 77 | which is anyway incorrect (so needs to be fixed). The correct fix |
| | 78 | would be something like: |
| | 79 | {{{ |
| | 80 | macro_append <package>_linkopts "" \ |
| | 81 | <project>_without_installarea " -L$(<PACKAGE>ROOT)/$ |
| | 82 | (<package>_tag)" ; \ |
| | 83 | macro_append <package>_linkopts " -l<package> <extras> " |
| | 84 | }}} |
| | 85 | Which would use the library from within the package if no InstallArea |
| | 86 | is present, and otherwise use the symlinked version from the |
| | 87 | InstallArea. |
| | 88 | |
| | 89 | == Simplification of the -I<paths> (DavidQ) == |
| | 90 | |
| | 91 | Currently we have a -I<path> entry for every used package, even |
| | 92 | though all the package include directories are symlinked from the |
| | 93 | InstallArea. This results in very long compilation command paths |
| | 94 | which are bulky in logfiles and essentially opaque for humans to |
| | 95 | read. The motivation for this was the use case where someone removes |
| | 96 | a header file from a package, and wants to test whether another |
| | 97 | package that has been checked out has been updated not to include the |
| | 98 | now missing file. Without the long -I<path> the header file will |
| | 99 | still be located within the underlying base release. At the time we |
| | 100 | made this decision Christian proposed that the obsolete header file |
| | 101 | should not be removed, but marked (via a pragma statement) to ensure |
| | 102 | that it would cause clients to fail to compile. I now believe that he |
| | 103 | was right and that we should adopt this strategy. I note that once |
| | 104 | the updated package has been incorporated into the base release the |
| | 105 | now obsolete header file can be deleted if so desired. I played with |
| | 106 | bit to try to get this to work some time ago, but never got it |
| | 107 | completed so now it needs to be resurrected. Note that this has to be |
| | 108 | done per release rather than intrinsically by CMT since old releases |
| | 109 | will still have the existing symlink structure. |
| | 110 | |
| | 111 | == 6. Revisit g77 include path (DavidQ) == |
| | 112 | |
| | 113 | There's a horrible hack I put in because g77 has a character limit, |
| | 114 | not only on the overall command line, but also on the -I<path> |
| | 115 | options. This hack involves some symlinks in the project to other |
| | 116 | projects and causes problems with search paths and is a real mess. We |
| | 117 | should revisit this, perhaps in conjunction with 7. below. |
| | 118 | |
| | 119 | == 7. Investigate whether we can use gfortran instead of g77(DavidQ) == |
| | 120 | |
| | 121 | Currently we use gfortran for the Saclay F90 code, and g77 for |
| | 122 | everything else. I think we should look at using gfortran for |
| | 123 | everything, since that would solved 6. above, and provide additional |
| | 124 | uniformity. We would need to ensure that gfortran was shipped with |
| | 125 | the kit, but that's done already. |
| | 126 | |
| | 127 | == 8. cmt co tag (DavidR) == |
| | 128 | |
| | 129 | Another thing not vital but nice to have, which was suggested several |
| | 130 | time in the past is to be able to specify a cmt co tag like : |
| | 131 | cmt co Reconstruction/RecExample/RecExCommon-01-02-03 |
| | 132 | |
| | 133 | |
| | 134 | == 9. Make CMT a library rather than a static executable (SébastienB) == |
| | 135 | |
| | 136 | This surely is a long-term item but I think it would ease the work of people |
| | 137 | writting scripts (see b.) or building plugins for CMT. |
| | 138 | |
| | 139 | == 10. Have python bindings for CMT (SébastienB) == |
| | 140 | |
| | 141 | Athena (and Gaudi, for that matters) would greatly benefit from having |
| | 142 | official python bindings for CMT. Just have a look at how many python |
| | 143 | wrappers have been written for CMT in the Atlas CVS repository. |
| | 144 | |
| | 145 | == 9. Introduce the concept of a Release (or some equivalent 'meta-data') (SébastienB) == |
| | 146 | |
| | 147 | The central concept in CMT, according to the CMT-documentation, is a Package. |
| | 148 | (Looking at the source code, I'd argue it isn't completely true and would be |
| | 149 | more inclined to say the central concept in CMT is the 'Use statement', |
| | 150 | anyway...) |
| | 151 | I'd like to have the concept of a Release to be introduced. This would be used |
| | 152 | when one installs a (set of) project(s) with a frozen set of packages with |
| | 153 | their version and dependencies (clients+uses). |
| | 154 | Iterrogating this Release object for package dependencies would be much faster |
| | 155 | than letting CMT rebuild and recompute each time the whole set of dependencies |
| | 156 | whenever one does 'make'. |
| | 157 | I believe this would also speed-up the 'cmt show clients CustomerIsTheKing' |
| | 158 | command. |
| | 159 | |
| | 160 | == 10. Separate the 'build' environment from the 'user' environment (SébastienB) == |
| | 161 | |
| | 162 | Having CMT running into its own environment without touching the user |
| | 163 | environment would allow a faster turn-around between nightlies/releases |
| | 164 | (developer-centric) but also ease bug-reporting (user-centric) : the CMT |
| | 165 | environment being described by a single file would dramatically reduce |
| | 166 | confusion (while developers are trying to reproduce users' bugs) and ease |
| | 167 | spotting mis-configuration. |
| | 168 | |
| | 169 | == 11. Introduce a mechanism to describe runtime dependencies between packages (SébastienB) == |
| | 170 | |
| | 171 | Title says it all. |
| | 172 | |
| | 173 | == 12. Use checksums rather than timestamps to decide if a file has been modified (SébastienB) == |
| | 174 | |
| | 175 | Hopefully, this will reduce re-compilation time. |
| | 176 | |
| | 177 | === Additional remarks (AndreiG) === |
| | 178 | |
| | 179 | we agreed that computing checksums can't be faster |
| | 180 | than testing time stamps; the use case he had in mind is when you |
| | 181 | inadvertently touched a file, and ended up with the same content but a |
| | 182 | different time stamp. |
| | 183 | |
| | 184 | === Additional remarks (WimL) === |
| | 185 | |
| | 186 | the point of checksums isn't to save time, it's to increase accuracy. If I |
| | 187 | revert my local sources to an earlier version from CVS, my object files and |
| | 188 | other build products have a time stamp that is newer, even as what they |
| | 189 | depend on has changed. Checksums will save you from having to remove all |
| | 190 | build directories. |
| | 191 | |
| | 192 | |
| | 193 | === Additional remarks (AndreiG) === |
| | 194 | |
| | 195 | Accuracy is important, but the compilation time is also |
| | 196 | important. There is a trade off between the risk of forgetting to |
| | 197 | remove build dirs after going back to an earlier version of a package |
| | 198 | and increasing compilation for each of the builds. I'd say that going |
| | 199 | "back in time" happens rarely, and therefore I am willing to accept |
| | 200 | the inconvenience of removing generated files by hand in such cases |
| | 201 | instead of increasing compilation time under routine circumstances |
| | 202 | (which is way too slow as it is). |
| | 203 | |
| | 204 | === Additional remarks (WimL) === |
| | 205 | |
| | 206 | > > I'd say that going "back in time" happens rarely |
| | 207 | |
| | 208 | YMMV. I do it a couple of times per day. Depends on work style, I guess. |
| | 209 | |
| | 210 | > > of increasing compilation time under routine circumstances |
| | 211 | |
| | 212 | There's a leverage effect. If I have to recompile my complete work directory |
| | 213 | b/c of a backtrack in one package, the total increase is enormous, and may |
| | 214 | surpass the cost of checksums in the routine circumstance. If I loose a day |
| | 215 | b/c of a subtlety, the scale goes even further in the direction of checksums. |
| | 216 | |
| | 217 | |
| | 218 | == 13. Profile and optimise CMT (SébastienB) == |
| | 219 | |
| | 220 | It would be great to reduce the time to compile packages in Atlas. Surely a |
| | 221 | chunk of this time comes from the packages themselves (templates, complicated |
| | 222 | packages dependencies, unneeded dependencies and stuff like that). |
| | 223 | But a simple test on UserAnalysis (which falls exactly in the above caveats): |
| | 224 | {{{ |
| | 225 | make -s 63.46s user 23.47s system 70% cpu 2:03.38 total (first build) |
| | 226 | make -s 10.83s user 7.67s system 96% cpu 19.083 total (no-op build) |
| | 227 | make -s 11.31s user 7.37s system 97% cpu 19.083 total (no-op build) |
| | 228 | }}} |
| | 229 | gives ~10 seconds for a no-op build... |
| | 230 | And for RecExCommon which is a pure python package: |
| | 231 | {{{ |
| | 232 | make -s 31.83s user 24.17s system 97% cpu 57.578 total (first build) |
| | 233 | make -s 10.98s user 8.02s system 99% cpu 19.050 total (no-op build) |
| | 234 | make -s 10.65s user 8.08s system 96% cpu 19.384 total (no-op build) |
| | 235 | }}} |
| | 236 | => still ~10seconds for a no-op build. |
| | 237 | (so I'd naively conclude it comes from CMT/Atlas-macros rather than the |
| | 238 | content of the package) |
| | 239 | |
| | 240 | == 14. have a build-dir location which can be configured (SébastienB) == |
| | 241 | |
| | 242 | Hence it would be possible to install all these possibly large .o,.so,.dict |
| | 243 | files (especially in -dbg mode) under some /tmp/${USER}/build directory |
| | 244 | without wasting AFS space. |
| | 245 | |
| | 246 | == 15. a mechanism to integrate 'plug-ins'(SébastienB) == |
| | 247 | |
| | 248 | Plug-ins are hype. |
| | 249 | I believe the Atlas package structure and the dependencies between packages |
| | 250 | would benefit of the integration of various Atlas-specific CMT plug-ins. Here |
| | 251 | I am thinking about checkreq. If checkreq was integrated during the |
| | 252 | development process of a package (and not 'just' at the nightly step) it |
| | 253 | would improve the overall quality (or correctness) of cmt/requirements files |
| | 254 | content. |
| | 255 | One could think also to Atlas specific default cmt/requirements file which |
| | 256 | would be used during the 'cmt create Foo Foo-00-00-00 Path/toFoo' command and |
| | 257 | check it sticks to Atlas conventions. |
| | 258 | Another useful plug-in, as we are heading towards gcc-3.4.x, would be a |
| | 259 | precompiled-header plug-in. |
| | 260 | |
| | 261 | == 16. produce makefiles structured according to the "Recursive Make Considered Harmful" prescription (AndreiG) == |
| | 262 | |
| | 263 | It would be very useful if cmt could produce makefiles structured |
| | 264 | according to the "Recursive Make Considered Harmful" prescription |
| | 265 | |
| | 266 | [1] http://www.tip.net.au/~millerp/rmch/recu-make-cons-harm.html |
| | 267 | |
| | 268 | This should give a huge speed up compared to "cmt br gmake" for |
| | 269 | someone who needs to recompile a bunch of checked out packages after |
| | 270 | modifying some of them. |
| | 271 | |
| | 272 | I imagine the following work model: |
| | 273 | |
| | 274 | - a developer checks out a set of packages he is working with, |
| | 275 | |
| | 276 | - issues a cmt br command to build a set of makefiles from the |
| | 277 | "topmost" package in his set (or from a specially created test |
| | 278 | package depending in all the checked out packages), |
| | 279 | |
| | 280 | - and from this point he only needs to run "gmake" from that same |
| | 281 | location to recompile exactly what needs to be recompiled after |
| | 282 | making modifications to any of his packages. Or "gmake -j3" :) |
| | 283 | |
| | 284 | The role of the cmt here is to resolve package versions and create |
| | 285 | appropriate makefiles. It only needs to be run once, unless you |
| | 286 | change the set of checked out packages, or the nightly you are working |
| | 287 | with. Gmake run on the master makefile knows all the dependencies, |
| | 288 | and does the minimal job to compile just what is needed, and also to |
| | 289 | re-compute dependencies that are maintained in a granular way (one .d |
| | 290 | file per one .cxx file). Having all the knowledge in one instance of |
| | 291 | gmake makes sure everything is updated properly - even if you use a |
| | 292 | -jN gmake option to build in parallel. (I've heard that cmt develops |
| | 293 | a custom parallel build solution - but gmake is already well debugged, |
| | 294 | why not use that?) |
| | 295 | |
| | 296 | The global gmake approach [1] is used by ROOT, see |
| | 297 | $ROOTSYS/README/BUILDSYSTEM (and perhaps by many other projects). |
| | 298 | |
| | 299 | I also used it for a set of projects, and can assert that |
| | 300 | |
| | 301 | 1) It works beautifully, |
| | 302 | |
| | 303 | 2) It IS easier to implement than it seems at first. |
| | 304 | |
| | 305 | I expect a large speedup because of a proper handling of dependencies |
| | 306 | that are stored and not recomputed unless needed. Also, not asking |
| | 307 | cmt to re-resolve all the used package versions on each "gmake" should |
| | 308 | save us a lot. |
| | 309 | |
| | 310 | |