├── .gitignore ├── README.md ├── ex_01 └── configure.ac ├── ex_02 ├── Makefile └── program.cc ├── ex_03 ├── Makefile.in ├── configure.ac └── program.cc ├── ex_04 ├── Makefile.in ├── configure.ac └── program.cc ├── ex_05 ├── Makefile.in ├── configure.ac └── program.cc ├── ex_06 ├── Makefile.in ├── configure.ac ├── hello_libz.cc ├── hello_no_libz.cc └── program.cc ├── ex_07 ├── Makefile.in ├── config.h.in ├── configure.ac └── program.cc ├── ex_08 ├── Makefile.in ├── configure.ac ├── hello_libz.cc ├── hello_no_libz.cc └── program.cc ├── ex_09 ├── Makefile.in ├── configure.ac ├── hello_libz.cc ├── hello_no_libz.cc └── program.cc ├── ex_10 └── configure.ac ├── ex_11 ├── configure.ac └── m4 │ └── ax_cxx_compile_stdcxx.m4 ├── ex_12 └── configure.ac └── ex_13 └── configure.ac /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | Makefile 3 | autom4te.cache 4 | *.o 5 | config.log 6 | config.status 7 | configure 8 | program 9 | config.h 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A brief introduction to Autoconf (2nd edition) 2 | 3 | ## Preface 4 | 5 | A long time ago I autoconf-ized the build system for 6 | [libCVD](http://www.edwardrosten.com/cvd/index.html). 7 | It was one of the 8 | best decisions I made with that library. It took me a while because there wasn't 9 | a good “getting started” guide, so 10 | [I wrote one](http://www.edwardrosten.com/code/autoconf/). It's been the 11 | top link for “autoconf tutorial” on google for a while. 12 | 13 | Don't go there. 14 | 15 | The trouble is I wrote it after my first Autoconf project back in 2005 or so. 16 | I've learned how to use it better since then and it's also moved on. It'll get 17 | you started, but probably teach you bad habits. I've also since come to the 18 | conclusion that while autoconf is entirely separate from make and can be used 19 | without it, it makes much more sense to have examples with makefiles because 20 | they are almost always used together. 21 | 22 | 23 | ## Introduction 24 | 25 | Autoconf is a system for generating a script which will automatically determine 26 | the presence of things which your project either depends upon, or can make use 27 | of. Once these have been determined, autoconf can export this information in 28 | various formats suitable for your project to use. Autoconf scripts themselves 29 | are written in a combination of shell and M4 (a macro processing language 30 | considerably more capable than the C preprocessor). Autoconf essentially runs 31 | the preprocessor on your script to produce a portable shell script which will 32 | perform all the requisite tests, produce handy log files, preprocess template 33 | files, for example to generate `Makefile` from `Makefile.in` and and take a standard 34 | set of command line arguments. 35 | 36 | There are several tools in the suite, including automake (for automatically 37 | generating makefiles) and autoscan (for scanning source trees to make configure 38 | scripts). I'm not going to cover them. However, while autoconf has nothing to 39 | do with Make, by far the most common use of it is to generate a Makefile. I only 40 | use GNU Make, and so the examples may well use GNU Make only features. 41 | 42 | In order to read this tutorial, a knowledge of shell scripting is assumed, but 43 | not essential for the basic examples. No knowledge of M4 is needed, but it worth 44 | knowing especially if you want to write your own custom tests which you wish to 45 | reuse. 46 | 47 | ## Hello, World. 48 | 49 | Grab the code in [example 1](ex_01), or put this in configure.ac: 50 | 51 | ```autoconf 52 | AC_INIT(myconfig, version-0.1) 53 | AC_MSG_NOTICE([Hello, world.]) 54 | 55 | ``` 56 | Now compile it and run it 57 | ```bash 58 | autoconf 59 | ./configure 60 | ``` 61 | And you get: 62 | ```text 63 | ex_01 $./configure 64 | configure: Hello, world. 65 | ex_01 $ 66 | ``` 67 | Alriiight! :) 68 | 69 | Now that that's out of the way, there's a few basic things. 70 | * All public Autoconf M4 macros look like `A[CST]_??????`. There may be private versions starting with `_`, but it's generally a bad idea to use them. 71 | * M4 arguments are quoted with `[` and `]`. There is NO WAY to escape these, however, you have several options if you wish to insert `[`'s or `]`'s: 72 | 1. Use a ‘Quadrigaph’. `@<:@` gives you `[` and `@>:@` gives you `]`. Those look as nasty as they sound. 73 | 2. Balance your quotes. M4 will turn `[[]]` in to `[]`. Beware of using this in arguments to macros. Sometimes, you need to double quote as well (`[[[]]]`). This is not as nasty as it sounds, it's much, much nastier. M4 programming is quite fun in that you have such a huge of acievement when the quotes finally work correctly. 74 | 3. Change the quoting using: `changequote(<<,>>)` to change the quoting to `<<` and `>>`. The autoconf documentation (rightly, in my opinion) warns against the (over) use of this, since it can lead to unexpected results. This is also as nasty... see the pattern here? 75 | 4. Avoid `[` and `]` whereever possible. 76 | As a result, you can't easily use the shell command `[` to perform tests. You have to use test instead. 77 | * If you make bad shell code, the errors probably won't appear until you run the configure script. 78 | * Configure scripts are almost always called configure.ac 79 | * Bear in mind that this is a tutorial. Many macros provide optional arguments which allow you to change the way of doing things. There may be many more ways of solving a problem than I've covered here. 80 | 81 | ## A basic project 82 | 83 | Since the purpose of autoconf is compiling projects, it makes most sense to 84 | start with [a simple project](ex_02). The project as it stands just has a 85 | Makefile. Go in to [ex_02](ex_02) and do: 86 | ```bash 87 | make 88 | ./program 89 | ``` 90 | If all goes well and you have a C++ compiler installed, then you should get: 91 | ```text 92 | Hello, I am a program 93 | ``` 94 | [It's now going to be autoconfized](ex_03). First, we rename `Makefile` to 95 | `Makefile.in` and edit it look like this: 96 | ```make 97 | CXX=@CXX@ 98 | LD=@CXX@ 99 | CXXFLAGS=@CXXFLAGS@ 100 | 101 | program: program.o 102 | $(LD) -o $@ $^ 103 | 104 | .PHONY: clean 105 | clean: 106 | rm -f program *.o 107 | 108 | ``` 109 | It's more or less the same, but instead of hard-wiring the compiler names and 110 | flags and so on, we put in placeholders that the configure script will 111 | substitute. All the placeholders are of the form @foo@. I've also added 112 | a "make clean" rule. 113 | 114 | We now need a matching configure script: 115 | ```autoconf 116 | AC_INIT(program, 1.0) 117 | 118 | dnl Switch to a C++ compiler, and check if it works. 119 | AC_LANG(C++) 120 | AC_PROG_CXX 121 | 122 | dnl Process Makefile.in to create Makefile 123 | AC_OUTPUT(Makefile) 124 | ``` 125 | By the way, dnl in autoconf is a comment. That's because of M4 and M4 126 | is... best not to go there right now. 127 | 128 | Now, compile the configure script by typing "autoconf" and you're ready to 129 | perform the standard build incantation: 130 | ```bash 131 | ./configure && make 132 | ``` 133 | I get the output: 134 | ```text 135 | checking for g++... g++ 136 | checking whether the C++ compiler works... yes 137 | checking for C++ compiler default output file name... a.out 138 | checking for suffix of executables... 139 | checking whether we are cross compiling... no 140 | checking for suffix of object files... o 141 | checking whether we are using the GNU C++ compiler... yes 142 | checking whether g++ accepts -g... yes 143 | configure: creating ./config.status 144 | config.status: creating Makefile 145 | g++ -g -O2 -c -o program.o program.cc 146 | g++ -o program program.o 147 | 148 | ``` 149 | That's basically it. You now have a fully armed and operational configure 150 | script. Because autoconf is a decent system, it already comes with all the 151 | different features. You can, for example change the compiler flags: 152 | ```text 153 | make clean 154 | ./configure CXXFLAGS="-Wall -Wextra" && make 155 | ``` 156 | or, you can change the compiler if you like: 157 | ```bash 158 | make clean 159 | ./configure CXX=g++-5 && make 160 | 161 | ``` 162 | Naturally that will fail if you don't have that compiler. You can even cross 163 | compile! First, install the AVR toolchain (on ubuntu sudo apt-get install gcc-avr binutils-avr avr-libc) if you can, then run: 164 | ```bash 165 | ./configure --host avr && make 166 | ``` 167 | You should get the output: 168 | ```text 169 | checking for avr-g++... avr-g++ 170 | checking whether the C++ compiler works... yes 171 | checking for C++ compiler default output file name... a.out 172 | checking for suffix of executables... 173 | checking whether we are cross compiling... yes 174 | checking for suffix of object files... o 175 | checking whether we are using the GNU C++ compiler... yes 176 | checking whether avr-g++ accepts -g... yes 177 | configure: creating ./config.status 178 | config.status: creating Makefile 179 | avr-g++ -g -O2 -c -o program.o program.cc 180 | program.cc:1:20: fatal error: iostream: No such file or directory 181 | #include 182 | ^ 183 | compilation terminated. 184 | make: *** [program.o] Error 1 185 | ``` 186 | Wait, what? 187 | 188 | The AVR is a “non hosted” platform in that it has no OS. That means that you 189 | can't expect obvious bits of the C++ standard library to be there. While this is 190 | an obscure case, it does illustrate the next topic very nicely which is: 191 | 192 | ## Performing basic tests 193 | 194 | So first we need some tests to perform. The iostream example is a little 195 | contrived, so I'll bring in a really common library, [zlib](http://zlib.com). 196 | The new program [example 5](ex_05) now outputs its data gzip compressed. 197 | 198 | First, we need to modify the [Makefile.in](ex_05/Makefile.in) to use the library 199 | flags. First, we add the template substitutions: 200 | ```Make 201 | LDFLAGS=@LDFLAGS@ 202 | LIBS=@LIBS@ 203 | ``` 204 | then we change the build line to use them: 205 | ```Make 206 | program: program.o 207 | $(LD) -o $@ $^ $(LDFLAGS) $(LIBS) 208 | ``` 209 | At this point you might wonder, “Why not save typing and just use `@LIBS@` 210 | everywhere?”. It's a good question. The answer is that you can, but if you ever 211 | end up debugging things and you want to make a quick, temporary change by 212 | editing the generated Makefile, you will curse yourself because instead of changing things in 213 | one place, you have to change it everywhere. 214 | 215 | So, now, put the following lines in the `configure.ac` file: 216 | ```autoconf 217 | AC_CHECK_HEADERS(zlib.h) 218 | AC_SEARCH_LIBS(deflate, z) 219 | ``` 220 | The first function compiles a minimal program against each of the specified 221 | headers (you can give more than one), and the second checks for the function 222 | "deflate" in any one of the listed libraries. 223 | If you were to run the configure script, you'd get something like this in the 224 | output: 225 | ```text 226 | checking zlib.h usability... yes 227 | checking zlib.h presence... yes 228 | checking for zlib.h... yes 229 | checking for library containing deflate... -lz 230 | ``` 231 | That's pretty good, and you can now build the program, however, if the test 232 | fails then the configure script will continue and give you a makefile which 233 | would fail to build your program. 234 | 235 | So now what? 236 | 237 | At this point you need to do something with the results of the test. What you 238 | want to do, and how you want to do it depend strongly on what you're trying to 239 | achieve. The simplest case is a hard dependency, where failure to find the 240 | library prevents the configure script from completing. 241 | 242 | Both the functions above set various variables on success, in this case: 243 | ```shell 244 | ac_cv_header_zlib_h=yes 245 | ac_cv_search_deflate=-lz 246 | ``` 247 | You can look in config.log, that has a list of everything which is defined. You 248 | can perform tests with shell logic on those if you like. However, those 249 | functions also provide two optional arguments: action on success and action on 250 | failure. 251 | 252 | Probably the easiest solution is to do this: 253 | 254 | ```autoconf 255 | AC_CHECK_HEADERS(zlib.h, [], [AC_ERROR([A working zlib is required])]) 256 | AC_SEARCH_LIBS(deflate, z, [], [AC_ERROR([A working zlib is required])]) 257 | ``` 258 | Now try misspelling “deflate” and rerunning autoconf and configure. You'll see 259 | it fail like this: 260 | ```text 261 | checking zlib.h usability... yes 262 | checking zlib.h presence... yes 263 | checking for zlib.h... yes 264 | checking for library containing deflte... no 265 | configure: error: A working zlib is required 266 | ``` 267 | 268 | ## What's going on under the hood? 269 | 270 | I find many tools and systems easier to understand if I know what's going on 271 | under the hood. I think it makes predicting the behaviour and debugging 272 | substantially easier. Fortunately, autoconf is fairly straightforward in that 273 | regard. 274 | 275 | Autoconf is essentially a compiler that compiles the `configure.ac` script into 276 | a shell script which can then run on any platform without autoconf being 277 | present. Well, I say compiler... It's actually all in a language called M4. M4 278 | is a macro processing system, like the C preprocessor on steroids (and PCP). 279 | When you run autoconf, it defines a whole bunch of M4 macros and then runs your 280 | script through the M4 preprocessor. The macros all get expanded (they all 281 | contain shell code) and out comes pure shell code with no trace of the M4 or 282 | autoconf languages left behind. 283 | 284 | The macros are in all caps, and everything else is passed through as-is with no 285 | modification. That's why you can write logic in shell code too: it just ends up 286 | in the configure script. 287 | 288 | Most of the tests in autoconf are to do with compiled code. To do these, 289 | autoconf emits small programs to a file, then runs that file through the 290 | compiler and possibly linker, and checks the resulting error codes. For example: 291 | 292 | ```M4 293 | AC_CHECK_LIB(m, cos) 294 | ``` 295 | Will generate a program looking something like this: 296 | ```C 297 | char cos (); 298 | int main () 299 | { 300 | cos (); 301 | return 0; 302 | } 303 | ``` 304 | Then attempt to compile and link it with libm. Autoconf does similar things for 305 | `AC_CHECK_HEADERS`, but only runs the compiler, not the linker too. If you want 306 | to see more details, then create a test which you know will fail, run the script 307 | and and look in `config.log`. It only stores the program fragments from tests 308 | that fail. 309 | 310 | 311 | ## More advanced test results 312 | 313 | Sometimes, dependencies are optional. There are of course an infinite number of 314 | ways of dealing with those. The two common ones are via conditional compilation 315 | (i.e. setting macros) or via choosing between different source files. I strongly 316 | prefer the latter if possible. 317 | 318 | Now, the tests so far will set things which can be used (like the presence or 319 | absence of `-lz` in the library flags), but they are independent. You want to 320 | enable the dependency if and only if all relavent tests pass. I find the easiest 321 | way of doing that is using a construct like this: 322 | 323 | ```autoconf 324 | a=0 325 | AC_CHECK_HEADERS(zlib.h, [], [a=1]) 326 | AC_SEARCH_LIBS(deflate, z, [], [a=1]) 327 | 328 | if test $a == 0 329 | then 330 | dnl Thing to do if the library is present 331 | ; 332 | else 333 | dnl Thing to do if the library is not present 334 | ; 335 | fi 336 | 337 | ``` 338 | 339 | I'm now going to make zlib an optional dependency. 340 | 341 | ### Compiling alternate files 342 | 343 | The first thing to do is to [provide two alternatives](ex_06), one for zlib and 344 | one without. Obviously in this case the example is a little contrived but we 345 | want to compile [hello_libz.cc](ex_06/hello_libz.cc) if we find zlib and 346 | [hello_no_libz.cc](ex_06/hello_no_libz.cc) if we don't. Either way, `main()` is 347 | the same, and just calls the `hello()` function. 348 | 349 | Now, alter [Makefile.in](ex_06/Makefile.in) so it can use another parameter that 350 | we get from `configure`: 351 | ```make 352 | objs=@objs@ 353 | 354 | program: program.o $(objs) 355 | $(LD) -o $@ $^ $(LDFLAGS) $(LIBS) 356 | ``` 357 | And alter [configure.ac](ex_06/configure.ac) so it populates @objs@ with either 358 | one object file or another. 359 | ```autoconf 360 | dnl List of object files as determined by autoconf 361 | object_files="" 362 | 363 | a=0 364 | AC_CHECK_HEADERS(zlib.h, [], [a=1]) 365 | AC_SEARCH_LIBS(deflate, z, [], [a=1]) 366 | 367 | if test $a == 0 368 | then 369 | object_files="$object_files hello_libz.o" 370 | else 371 | object_files="$object_files hello_no_libz.o" 372 | fi 373 | 374 | dnl Make AC_OUTPUT substitute the contents of $object_files for @objs@ 375 | AC_SUBST(objs, ["$object_files"]) 376 | ``` 377 | 378 | Now `configure` will choose between one of the two source files to compile and 379 | link, depending on the result of the test. The complete program will work either 380 | way. 381 | 382 | ### Conditional compilation 383 | 384 | The [other main way](ex_07) of having autoconf affect the build is via conditional 385 | compilation. You could export `-D` definitions to the CXXFLAGS or a custom 386 | variable. That's a bad idea because your program will have a dependency on the 387 | arguments, and make doesn't track or examine those dependencies. The standard 388 | way is to generate a `config.h` file instead. The process is similar to, but not 389 | identical to creating a makefile. The relevant part of 390 | [configure.ac](ex_07/configure.ac) is: 391 | ```autoconf 392 | a=0 393 | AC_CHECK_HEADERS(zlib.h, [], [a=1]) 394 | AC_SEARCH_LIBS(deflate, z, [], [a=1]) 395 | 396 | if test $a == 0 397 | then 398 | AC_DEFINE(HAVE_LIBZ) 399 | fi 400 | 401 | AC_CONFIG_HEADERS(config.h) 402 | ``` 403 | `AC_DEFINE` will cause a #define to be written in `config.h`. **IMPORTANT:** 404 | `AC_CONFIG_HEADERS` must come before `AC_OUTPUT` otherwise it willbe silently 405 | ignored. [config.h.in](ex_07/config.h.in) is a template of an include file, but 406 | substitutions are done on `#undef` lines, it must contain: 407 | ```C 408 | #undef HAVE_LIBZ 409 | ``` 410 | If `HAVE_LIBZ` is exported by `configure`, then that line is commented out. The 411 | [C++ code](ex_07/program.c) can then `#include ` and use the macros. 412 | 413 | #### :neckbeard: Ed's Soapbox :neckbeard: 414 | 415 | Avoid `config.h` as much as possible. Disadvantages are: 416 | 417 | 1. Every file depending on `config.h` must be rebuilt if `config.h` changes even 418 | if the change is irrelevant. 419 | 2. Conditional compilation is ugly and can lead to tangled messes of dead code. 420 | 3. It's generally good practice to avoid the preprocessor where possible. 421 | 4. If you're building a library and you've got a `config.h` included from the 422 | public headers, then everything using the library has to be rebuilt if 423 | `config.h` changes. 424 | 5. More source files means better parallel builds. 425 | 426 | This isn't a rigid rule. Sometimes the clearest, simplest and most elegant 427 | solution to some gnarly cross-platform portability problem involves the 428 | preprocessor. In most cases though however, the cleanest portable designs will 429 | rely on separating off platform specific parts into different modules and files. 430 | 431 | Regarding point 4, you should really avoid having a public config.h if at all 432 | possible. When you can't keep the dependencies on it as small as possible, by putting 433 | anything not required to be public in a private config.h. Autoconf allows you to 434 | specify a whole list of headers. 435 | 436 | ### Nicer dependencies with --with and --enable 437 | 438 | So if you've made it this far, you probably noticed that debugging and checking 439 | the scripts was a bit of a pain, because you had to edit them to make one of the 440 | tests fail then rerun autoconf, then put it back again. Autoconf provides two 441 | methods of configuration. They are almost identical in function, but the 442 | conventions are: 443 | * `--enable-foo` enable feature foo. This is typically used to enable or disable 444 | an entire feature, such as `--enable-gui`. 445 | * `--with-bar` use dependency bar. This is typically used to switch on/off a 446 | dependency. That may have an effect on a whole feature. For example 447 | `--without-gtk` might end up disabling the GUI if no other toolkit is 448 | available. 449 | 450 | If a script understands `--with-bar`, it will also understand `--without-bar` 451 | which is exactly equivalent to `--with-bar=no`. That means you can also supply 452 | arguments to `with`. `--enable-foo` works in the same way. Both styles simply 453 | set an environment variable. You can then act on that with the usual shell 454 | scripting. 455 | 456 | The format is: 457 | ```autoconf 458 | AC_ARG_WITH(zlib, [AS_HELP_STRING([--without-zlib], [do not use zlib])]) 459 | ``` 460 | The first argument is the feature, and it will set `$with_zlib` to the value 461 | specified (blank if the argument is not used). The second argument is the text 462 | which appears if `./configure --help` is run. `AS_HELP_STRING` simply makes 463 | everything line up and look pretty. Much like the other tests, you can also 464 | specify actions for if the commandline argument is present or absent. 465 | 466 | 467 | [This example](ex_08) is very similar to [Example 6](ex_06), except that the 468 | relevant part of [configure.ac](ex_08/configure.ac) is now: 469 | ```configure 470 | AC_ARG_WITH(zlib, [AS_HELP_STRING([--without-zlib], [do not use zlib])]) 471 | 472 | zlib_objs=hello_no_libz.o 473 | if test "$with_zlib" != no 474 | then 475 | a=0 476 | AC_CHECK_HEADERS(zlib.h, [], [a=1]) 477 | AC_SEARCH_LIBS(deflate, z, [], [a=1]) 478 | 479 | if test $a == 0 480 | then 481 | zlib_objs=hello_libz.o 482 | fi 483 | fi 484 | 485 | object_files="$object_files $zlib_objs" 486 | 487 | ``` 488 | Now, if `--without-zlib` is specified then it doesn't even try to run the tests, 489 | and carries on as if the tests have failed. 490 | 491 | ## Out of tree builds 492 | 493 | Out of tree builds are one of those features that are rarely used, but probably 494 | ought to be used more. They're kind of handy because with the same source tree, 495 | you can build various versions (standard, debugging, cross compiled) from a 496 | single source tree, without having to keep multiple copies in sync. It's also so 497 | easy to do that you may as well do it. 498 | 499 | Autoconf supports it by providing @srcdir@ which tells you the directory of the 500 | configure script and of course by extension the source code. That's it as far as 501 | autoconf goes, it's completely automatic. 502 | 503 | You then need to use the virtual path (vpath) feature of make. Essentially, add 504 | the line 505 | ```make 506 | VPATH=@srcdir@ 507 | ``` 508 | to Makefile.in, and now make will more or less overlay VPATH on the current 509 | directory when it comes to file lookups. 510 | 511 | That's all there is to is. Go into [example 9](ex_09) and run autoconf to create 512 | the configure script. Now go into /tmp and type something like: 513 | ```shell 514 | /path/to/autoconf_tutorial/ex_09/configure && make && ./program | zcat 515 | ``` 516 | It should work just as well as if you ran configure and make from within the 517 | source directory. 518 | 519 | ## Moving on 520 | 521 | At this point you now have a basic, but fully featured autoconf build system. 522 | Most of what to do can probably be accomplished with what you've covered so far, 523 | however you may come across things which aren't covered. 524 | 525 | If you do get into writing your own tests, then it's a very good idea to build 526 | off the autoconf macros if at all possible. I know from experience that it's an 527 | especially bad idea to write tests that probe the machine you're running the 528 | autoconf script from because then you won't be able to deploy the resulting 529 | program on a different mahchine (for example if you're cross compiling). 530 | 531 | Even without machine specific tests, there are other things you might want to 532 | look for or other parts of the build system you might want to probe. 533 | 534 | ### Debugging 535 | 536 | There are several levels of debugging which you need to do. There's debugging 537 | your shell code (I'm not going to help there), debugging tests in the configure 538 | script and debugging the generated files. 539 | 540 | If you're debugging autoconf tests, the best place to look is `config.log`. That 541 | stores lots of useful information about tests that fail, including the compiler 542 | line with all flags and the bit of code being compiled. It's often quite large, 543 | so you'll have to search through it. You can also put your own text in the log 544 | to aid that process. 545 | 546 | Here's [an example](ex_10): 547 | 548 | ```autoconf 549 | AC_INIT(myconfig, version-0.1) 550 | AC_PROG_CXX 551 | 552 | 553 | AC_SEARCH_LIBS(cos, m) 554 | 555 | echo "This library check will fail" >&AS_MESSAGE_LOG_FD 556 | AC_SEARCH_LIBS(foo, bar) 557 | 558 | AC_MSG_NOTICE([This message will appear in the log and on the screen]) 559 | AC_CHECK_HEADERS(foo, bar) 560 | ``` 561 | Run the script and look in the log file. 562 | 563 | Assuming your configure script runs correctly, the next layer of the stack with 564 | bugs is the generated Makefile and `config.h` if either exist. It would be 565 | awfully tedious if you had to re-run configure every time you changed one of 566 | those. Fortunately you don't. 567 | 568 | Before autoconf completes, it generates a script called `config.status`, then 569 | executes it. This script stores the results of autoconf and does the template 570 | substitutions on the .in files. So, if you edit your `Makefile.in` and run 571 | `config.status`, it'll re-generate the Makefile. 572 | 573 | 574 | ### Using other languages 575 | 576 | Autoconf supports several languages. The easiest way to switch is: 577 | ```autoconf 578 | AC_LANG(Fortran) 579 | ``` 580 | which changes the language that tests are run in. There's also a stack of 581 | languages so you can push and pop them to make temporary changes. 582 | 583 | 584 | ### Other tests 585 | 586 | At this point I'm just going to list a selection of what's available. The usage 587 | should be reasonably obvious from the names. Quite a few of the marcros have 588 | `IF_ELSE` in the name, which means they just give you places to insert code for 589 | success or failure. For quite a lot of common cases, there are more specialised 590 | macros to help. Note again, this is a small selection to give a flavour. Since 591 | this is a tutorial I can't cover them all, so it's best to browse 592 | [the manual](https://www.gnu.org/software/autoconf/manual/autoconf.html) at this 593 | point. 594 | * `AC_COMPILE_IFELSE` --- useful for testing C++ header only libraries 595 | * `AC_PREPROCESS_IFELSE` 596 | * `AC_LINK_IFELSE` 597 | * `AC_RUN_IFELSE` --- this one is tricky. If you're cross compiling, you 598 | probably can't run a program you've just compiled, so you need to provide 599 | the script with some way of making a decision in that case. 600 | * `AC_PROG_AWK` --- find a working AWK. Versions exist for many of the common 601 | tools. 602 | * `AC_CHECK_TYPES([long long])`, `AC_TYPE_UINT8_T` --- check for various 603 | typedefs 604 | * `AC_OPENMP` 605 | * Anything starting `AC_MSG` for generting output that's consistent with the 606 | built in tests. 607 | 608 | 609 | ## Help! I can't test for C++14 (or something else) 610 | 611 | ### Other people's macros 612 | 613 | Autoconf provides good underlying tools, but doesn't provide tests for 614 | everything. In many cases, instead of writing your own you can instead grab one 615 | already written from [the huge official archive of 616 | macros](http://www.gnu.org/software/autoconf-archive/index.html). They're also 617 | very easy to use precisely because M4 is a macro language. 618 | 619 | Here's [an example](ex_11) for C++14. First get [this extension 620 | macro](http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html) 621 | and put it in the `m4` subdirectory. Then use it in the following way: 622 | ```M4 623 | AC_INIT(myconfig, version-0.1) 624 | AC_LANG(C++) 625 | AC_PROG_CXX 626 | 627 | 628 | m4_include([m4/ax_cxx_compile_stdcxx.m4]) 629 | AX_CXX_COMPILE_STDCXX(14) 630 | ``` 631 | Now your script will test for C++ 14 and fail if it isn't found. The official 632 | extension macros are generally very well tested and so it's better to use those 633 | than roll your own. 634 | 635 | ### Writing your own tests 636 | 637 | Sooner or later, you'll probably find that there's not a test for something you 638 | want to do repeatedly. For example, I like to routinely add flags to do with 639 | warnings, GDB symbols and so on. [Here's](ex_12) an example of a custom test 640 | and its use 641 | ```autoconf 642 | dnl TEST_AND_SET_CXXFLAG(flag, [program]) 643 | dnl 644 | dnl This attempts to compile a program with a certain compiler flag. 645 | dnl If no program is given, then the minimal C++ program is compiled, and 646 | dnl this tests just the validity of the compiler flag. 647 | dnl 648 | define([TEST_AND_SET_CXXFLAG],[ 649 | AC_MSG_CHECKING([if compiler flag $1 works]) 650 | 651 | dnl Store the current CXXFLAGS 652 | save_CXXFLAGS="$CXXFLAGS" 653 | 654 | dnl Append the flag of interest 655 | CXXFLAGS="$CXXFLAGS $1" 656 | 657 | dnl Create an M4 macro, "prog", which expands to a C++ program. 658 | dnl This should either be a default one or the one specified. 659 | dnl Note that macros are not local, but there is a stack so push 660 | dnl the definition on to the stack to prevent clobbering a definition 661 | dnl that might already exist. 662 | m4_if([$2],[],[pushdef(prog, [int main(){}])], [pushdef(prog, [$2])]) 663 | 664 | flag_test=0 665 | 666 | dnl See if the compiler runs 667 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([prog])], [flag_test=1],[flag_test=0]) 668 | 669 | dnl De-clobber the "prog" macro 670 | popdef([prog]) 671 | 672 | if test $flag_test = 1 673 | then 674 | AC_MSG_RESULT(yes) 675 | else 676 | AC_MSG_RESULT(no) 677 | dnl The flag doesn't work, so restore the old CXXFLAGS 678 | CXXFLAGS="$save_CXXFLAGS" 679 | fi 680 | ]) 681 | 682 | dnl Add flags, but only if the flags weren't overridden already 683 | if test "$CXXFLAGS" == "-g -O2" 684 | then 685 | 686 | TEST_AND_SET_CXXFLAG(-Wall) 687 | TEST_AND_SET_CXXFLAG(-Wextra) 688 | TEST_AND_SET_CXXFLAG(-W) 689 | TEST_AND_SET_CXXFLAG(-O3) 690 | TEST_AND_SET_CXXFLAG(-ggdb) 691 | TEST_AND_SET_CXXFLAG(-fnot-a-valid-flag) 692 | fi 693 | ``` 694 | If you run the configure script it will attempt to add a whole bunch of flags to 695 | the compiler, but it won't cause errors if any of those flags are invalid. 696 | 697 | 698 | ## Making the world a better place 699 | 700 | Who doesn't want to make the world a better place? 701 | 702 | Have you ever had the following process: 703 | 704 | 1. `./confiugure && make && make install` 705 | 2. Try running the program to discover some feature you want is missing. 706 | 3. Re configure. 707 | 4. Examine output of autoconf until your eyes bleed. 708 | 5. Finally discover the most likely things which have failed. 709 | 6. Install packages, configure and make. 710 | 7. Discover you were wrong, and repeat 4-6 until you finally get the package 711 | working 712 | 8. Then repeat 1-8 until you finally have every feature you care about, or 713 | until you simply lose the will to carry on. 714 | 9. Use your new prorgam in a desultory manner. 715 | 716 | The good news is there's no need to inflict that on your users. [In this 717 | example](ex_13), there's a configure script for a hypothetical library which 718 | handles images and video. All dependencies are optional---if it's missing 719 | libjpeg, it'll work but just not be able to handle that format for example. 720 | 721 | Here's what I do to make my scripts look nice. Firstly, I make pretty section 722 | headers in the configure output using a macro like this: 723 | ```autoconf 724 | define(SECTION_TITLE, 725 | [ 726 | echo >& AS_MESSAGE_FD 727 | echo ' $1 ' | sed -e's/./-/g' >&AS_MESSAGE_FD 728 | echo ' $1' >& AS_MESSAGE_FD 729 | echo ' $1 ' | sed -e's/./-/g' >&AS_MESSAGE_FD 730 | ]) 731 | 732 | 733 | SECTION_TITLE([Checking for image libraries]) 734 | ``` 735 | Then, I keep track of what possible options there are. First, define a list of 736 | all possible options: 737 | ```autoconf 738 | all_options="jpeg png tiff funkyimage v4l2 ffmpeg awesomevideo" 739 | ``` 740 | then have another list which is the options which have been found. Whenever, you 741 | find something, then append it to the list: 742 | ```autoconf 743 | options= 744 | ... 745 | options="$options jpeg" 746 | 747 | ``` 748 | So, a complete test would look like this: 749 | ```autoconf 750 | a=0 751 | AC_CHECK_HEADERS(png.h, [], [a=1]) 752 | AC_SEARCH_LIBS(png_create_info_struct, png, [], [a=1]) 753 | if test $a == 0 754 | then 755 | options="$options png" 756 | fi 757 | 758 | ``` 759 | Then at the end of the script, print out both a list of options and list of the 760 | missing options. I do that with a little bit of shell scripting: 761 | ```shell 762 | echo "$options" "$all_options" | tr ' ' '\n' | sort | uniq -u | tr '\n' ' ' 763 | ``` 764 | The [resulting configure script](ex_13/configure.ac) gives an output which I 765 | think is much easier to read and to figure out the results of than the usual 766 | wall of text: 767 | ```text 768 | $ ./configure 769 | checking for g++... g++ 770 | checking whether the C++ compiler works... yes 771 | checking for C++ compiler default output file name... a.out 772 | checking for suffix of executables... 773 | checking whether we are cross compiling... no 774 | checking for suffix of object files... o 775 | checking whether we are using the GNU C++ compiler... yes 776 | checking whether g++ accepts -g... yes 777 | checking how to run the C++ preprocessor... g++ -E 778 | checking for grep that handles long lines and -e... /bin/grep 779 | checking for egrep... /bin/grep -E 780 | checking for ANSI C header files... yes 781 | checking for sys/types.h... yes 782 | checking for sys/stat.h... yes 783 | checking for stdlib.h... yes 784 | checking for string.h... yes 785 | checking for memory.h... yes 786 | checking for strings.h... yes 787 | checking for inttypes.h... yes 788 | checking for stdint.h... yes 789 | checking for unistd.h... yes 790 | checking iostream usability... yes 791 | checking iostream presence... yes 792 | checking for iostream... yes 793 | 794 | ---------------------------------- 795 | Checking for image libraries 796 | ---------------------------------- 797 | checking jpeglib.h usability... yes 798 | checking jpeglib.h presence... yes 799 | checking for jpeglib.h... yes 800 | checking for library containing jpeg_set_defaults... -ljpeg 801 | checking png.h usability... yes 802 | checking png.h presence... yes 803 | checking for png.h... yes 804 | checking for library containing png_create_info_struct... -lpng 805 | checking tiffio.h usability... yes 806 | checking tiffio.h presence... yes 807 | checking for tiffio.h... yes 808 | checking for library containing TIFFOpen... -ltiff 809 | checking funkyimage.h usability... no 810 | checking funkyimage.h presence... no 811 | checking for funkyimage.h... no 812 | checking for library containing funkyopen... no 813 | 814 | -------------------------------- 815 | Checking for video options 816 | -------------------------------- 817 | checking linux/videodev2.h usability... yes 818 | checking linux/videodev2.h presence... yes 819 | checking for linux/videodev2.h... yes 820 | checking for ffmpeg... 821 | checking libavcodec/avcodec.h usability... yes 822 | checking libavcodec/avcodec.h presence... yes 823 | checking for libavcodec/avcodec.h... yes 824 | checking libavformat/avformat.h usability... yes 825 | checking libavformat/avformat.h presence... yes 826 | checking for libavformat/avformat.h... yes 827 | checking libswscale/swscale.h usability... yes 828 | checking libswscale/swscale.h presence... yes 829 | checking for libswscale/swscale.h... yes 830 | checking for library containing main... none required 831 | checking for library containing av_read_frame... -lavformat 832 | checking for library containing avcodec_open2... -lavcodec 833 | checking for library containing sws_getContext... -lswscale 834 | checking awesomevid.h usability... no 835 | checking awesomevid.h presence... no 836 | checking for awesomevid.h... no 837 | checking for library containing openawesome... no 838 | 839 | --------------------------- 840 | Configuration results 841 | --------------------------- 842 | Options: 843 | jpeg png tiff v4l2 ffmpeg 844 | 845 | Missing options: 846 | awesomevideo funkyimage 847 | 848 | 849 | CXXFLAGS=-g -O2 850 | LDFLAGS= 851 | LIBS=-lswscale -lavcodec -lavformat -ltiff -lpng -ljpeg 852 | $ █ 853 | ``` 854 | 855 | 856 | 857 | 858 | ## What about automake and libtool? 859 | 860 | Er... yes they exist. 861 | 862 | I'm not going to cover them because I don't use them for a variety of reasons. 863 | Back when I learned autoconf, automake always generated recursive Makefiles. 864 | [Those are bad](aegis.sourceforge.net/auug97.pdf) for many reasons but 865 | especially if you do parallel builds with `make -J 4`. I had a dual processor 866 | machine back when multiple processors or cores were rare so it mattered to me 867 | more than most people. I also like GNU Make particularly, and I'm entirely happy 868 | with writing Makefiles to the point where I don't feel the need for extra 869 | automation. 870 | 871 | Libtool was (for me) a relatively frequent and hard to debug source of build 872 | errors in other people's packages. In fairness, this may well have been due to 873 | misuse of libtool, but either way I never learned it. Libtool was especially 874 | important back in the olden days when systems were very diverse, and when static 875 | libraries were measureably more efficient than dynamic ones. These days I tend 876 | to compile my .a files with PIC (so I can blob them into a .so plugin easily), 877 | and platforms with significant differences seem to have reduced to Linux/\*BSD, 878 | OSX and Cygwin and MinGW though in the latter cases it will also work the same 879 | way as Linux. So, in short I've not felt I'd gain all that much by learning it. 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | -------------------------------------------------------------------------------- /ex_01/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(myconfig, version-0.1) 2 | AC_MSG_NOTICE([Hello, world.]) 3 | -------------------------------------------------------------------------------- /ex_02/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | LD=g++ 3 | CXXFLAGS=-Wall -Wextra 4 | 5 | 6 | program: program.o 7 | $(LD) -o $@ $^ 8 | -------------------------------------------------------------------------------- /ex_02/program.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Hello, I am a program\n"; 8 | } 9 | -------------------------------------------------------------------------------- /ex_03/Makefile.in: -------------------------------------------------------------------------------- 1 | CXX=@CXX@ 2 | LD=@CXX@ 3 | CXXFLAGS=@CXXFLAGS@ 4 | 5 | program: program.o 6 | $(LD) -o $@ $^ 7 | 8 | .PHONY: clean 9 | clean: 10 | rm -f program *.o 11 | 12 | -------------------------------------------------------------------------------- /ex_03/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(program, 1.0) 2 | 3 | dnl Switch to a C++ compiler, and check if it works. 4 | AC_LANG(C++) 5 | AC_PROG_CXX 6 | 7 | dnl Process Makefile.in to create Makefile 8 | AC_OUTPUT(Makefile) 9 | 10 | -------------------------------------------------------------------------------- /ex_03/program.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Hello, I am a program\n"; 8 | } 9 | -------------------------------------------------------------------------------- /ex_04/Makefile.in: -------------------------------------------------------------------------------- 1 | CXX=@CXX@ 2 | LD=@CXX@ 3 | CXXFLAGS=@CXXFLAGS@ 4 | 5 | program: program.o 6 | $(LD) -o $@ $^ 7 | 8 | .PHONY: clean 9 | clean: 10 | rm -f program *.o 11 | 12 | -------------------------------------------------------------------------------- /ex_04/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(program, 1.0) 2 | 3 | dnl Switch to a C++ compiler, and check if it works. 4 | AC_LANG(C++) 5 | AC_PROG_CXX 6 | 7 | AC_CHECK_HEADERS(iostream) 8 | 9 | dnl Process Makefile.in to create Makefile 10 | AC_OUTPUT(Makefile) 11 | 12 | -------------------------------------------------------------------------------- /ex_04/program.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Hello, I am a program\n"; 8 | } 9 | -------------------------------------------------------------------------------- /ex_05/Makefile.in: -------------------------------------------------------------------------------- 1 | CXX=@CXX@ 2 | LD=@CXX@ 3 | CXXFLAGS=@CXXFLAGS@ 4 | LDFLAGS=@LDFLAGS@ 5 | LIBS=@LIBS@ 6 | 7 | program: program.o 8 | $(LD) -o $@ $^ $(LDFLAGS) $(LIBS) 9 | 10 | .PHONY: clean 11 | clean: 12 | rm -f program *.o 13 | 14 | -------------------------------------------------------------------------------- /ex_05/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(program, 1.0) 2 | 3 | dnl Switch to a C++ compiler, and check if it works. 4 | AC_LANG(C++) 5 | AC_PROG_CXX 6 | 7 | AC_CHECK_HEADERS(zlib.h, [], [AC_ERROR([A working zlib is required])]) 8 | AC_SEARCH_LIBS(deflate, z, [], [AC_ERROR([A working zlib is required])]) 9 | 10 | dnl Process Makefile.in to create Makefile 11 | AC_OUTPUT(Makefile) 12 | 13 | -------------------------------------------------------------------------------- /ex_05/program.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | //Output a string, compressed in gzip format. 9 | unsigned char in[] = "Hello, I am a program\n"; 10 | unsigned char out[1024] = {}; 11 | 12 | z_stream strm = {}; 13 | deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 8+16, 9, Z_DEFAULT_STRATEGY); 14 | strm.next_in = in; 15 | strm.avail_in = sizeof(in); 16 | strm.next_out = out; 17 | strm.avail_out = sizeof(out); 18 | deflate(&strm, Z_FINISH); 19 | deflateEnd(&strm); 20 | 21 | cout.write((const char*)out, strm.total_out); 22 | } 23 | -------------------------------------------------------------------------------- /ex_06/Makefile.in: -------------------------------------------------------------------------------- 1 | CXX=@CXX@ 2 | LD=@CXX@ 3 | CXXFLAGS=@CXXFLAGS@ 4 | LDFLAGS=@LDFLAGS@ 5 | LIBS=@LIBS@ 6 | 7 | objs=@objs@ 8 | 9 | program: program.o $(objs) 10 | $(LD) -o $@ $^ $(LDFLAGS) $(LIBS) 11 | 12 | .PHONY: clean 13 | clean: 14 | rm -f program *.o 15 | 16 | -------------------------------------------------------------------------------- /ex_06/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(program, 1.0) 2 | 3 | dnl Switch to a C++ compiler, and check if it works. 4 | AC_LANG(C++) 5 | AC_PROG_CXX 6 | 7 | dnl List of object files as determined by autoconf 8 | object_files="" 9 | 10 | a=0 11 | AC_CHECK_HEADERS(zlib.h, [], [a=1]) 12 | AC_SEARCH_LIBS(deflate, z, [], [a=1]) 13 | 14 | if test $a == 0 15 | then 16 | object_files="$object_files hello_libz.o" 17 | else 18 | object_files="$object_files hello_no_libz.o" 19 | fi 20 | 21 | dnl Make AC_OUTPUT substitute the contents of $object_files for @objs@ 22 | AC_SUBST(objs, ["$object_files"]) 23 | 24 | dnl Process Makefile.in to create Makefile 25 | AC_OUTPUT(Makefile) 26 | 27 | -------------------------------------------------------------------------------- /ex_06/hello_libz.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void hello() 7 | { 8 | //Output a string, compressed in gzip format. 9 | unsigned char in[] = "Hello, I am a program\n"; 10 | unsigned char out[1024] = {}; 11 | 12 | z_stream strm = {}; 13 | deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 8+16, 9, Z_DEFAULT_STRATEGY); 14 | strm.next_in = in; 15 | strm.avail_in = sizeof(in); 16 | strm.next_out = out; 17 | strm.avail_out = sizeof(out); 18 | deflate(&strm, Z_FINISH); 19 | deflateEnd(&strm); 20 | 21 | cout.write((const char*)out, strm.total_out); 22 | } 23 | -------------------------------------------------------------------------------- /ex_06/hello_no_libz.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void hello() 6 | { 7 | char data[]={0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 8 | 0x03,0xf3,0x48,0xcd,0xc9,0xc9,0xd7,0x51,0xf0, 9 | 0x54,0x48,0xcc,0x55,0x48,0x54,0x28,0x28,0xca, 10 | 0x4f,0x2f,0x4a,0xcc,0xe5,0x62,0x00,0x00,0x45, 11 | 0x29,0xde,0xb8,0x17,0x00,0x00,0x00}; 12 | 13 | cout.write(data, sizeof(data)); 14 | } 15 | -------------------------------------------------------------------------------- /ex_06/program.cc: -------------------------------------------------------------------------------- 1 | using namespace std; 2 | 3 | //The purpose here is to teach autoconf, not C++ best 4 | //practices... 5 | void hello(); 6 | 7 | int main() 8 | { 9 | hello(); 10 | } 11 | -------------------------------------------------------------------------------- /ex_07/Makefile.in: -------------------------------------------------------------------------------- 1 | CXX=@CXX@ 2 | LD=@CXX@ 3 | CXXFLAGS=@CXXFLAGS@ 4 | LDFLAGS=@LDFLAGS@ 5 | LIBS=@LIBS@ 6 | 7 | program: program.o 8 | $(LD) -o $@ $^ $(LDFLAGS) $(LIBS) 9 | 10 | .PHONY: clean 11 | clean: 12 | rm -f program *.o 13 | 14 | -------------------------------------------------------------------------------- /ex_07/config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_CONFIG_H_df90858 2 | #define INCLUDE_CONFIG_H_df90858 3 | 4 | #undef HAVE_ZLIB 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /ex_07/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(program, 1.0) 2 | 3 | dnl Switch to a C++ compiler, and check if it works. 4 | AC_LANG(C++) 5 | AC_PROG_CXX 6 | 7 | 8 | a=0 9 | AC_CHECK_HEADERS(zlib.h, [], [a=1]) 10 | AC_SEARCH_LIBS(deflate, z, [], [a=1]) 11 | 12 | if test $a == 0 13 | then 14 | AC_DEFINE(HAVE_LIBZ) 15 | fi 16 | 17 | 18 | AC_CONFIG_HEADERS(config.h) 19 | AC_OUTPUT(Makefile) 20 | 21 | -------------------------------------------------------------------------------- /ex_07/program.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "config.h" 3 | using namespace std; 4 | 5 | 6 | #ifdef HAVE_ZLIB 7 | #include 8 | void hello() 9 | { 10 | //Output a string, compressed in gzip format. 11 | unsigned char in[] = "Hello, I am a program\n"; 12 | unsigned char out[1024] = {}; 13 | 14 | z_stream strm = {}; 15 | deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 8+16, 9, Z_DEFAULT_STRATEGY); 16 | strm.next_in = in; 17 | strm.avail_in = sizeof(in); 18 | strm.next_out = out; 19 | strm.avail_out = sizeof(out); 20 | deflate(&strm, Z_FINISH); 21 | deflateEnd(&strm); 22 | 23 | cout.write((const char*)out, strm.total_out); 24 | } 25 | #else 26 | void hello() 27 | { 28 | char data[]={0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 29 | 0x03,0xf3,0x48,0xcd,0xc9,0xc9,0xd7,0x51,0xf0, 30 | 0x54,0x48,0xcc,0x55,0x48,0x54,0x28,0x28,0xca, 31 | 0x4f,0x2f,0x4a,0xcc,0xe5,0x62,0x00,0x00,0x45, 32 | 0x29,0xde,0xb8,0x17,0x00,0x00,0x00}; 33 | 34 | cout.write(data, sizeof(data)); 35 | } 36 | #endif 37 | 38 | int main() 39 | { 40 | hello(); 41 | } 42 | -------------------------------------------------------------------------------- /ex_08/Makefile.in: -------------------------------------------------------------------------------- 1 | CXX=@CXX@ 2 | LD=@CXX@ 3 | CXXFLAGS=@CXXFLAGS@ 4 | LDFLAGS=@LDFLAGS@ 5 | LIBS=@LIBS@ 6 | 7 | objs=@objs@ 8 | 9 | program: program.o $(objs) 10 | $(LD) -o $@ $^ $(LDFLAGS) $(LIBS) 11 | 12 | .PHONY: clean 13 | clean: 14 | rm -f program *.o 15 | 16 | -------------------------------------------------------------------------------- /ex_08/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(program, 1.0) 2 | 3 | dnl Switch to a C++ compiler, and check if it works. 4 | AC_LANG(C++) 5 | AC_PROG_CXX 6 | 7 | dnl List of object files as determined by autoconf 8 | object_files="" 9 | 10 | 11 | AC_ARG_WITH(zlib, [AS_HELP_STRING([--without-zlib], [do not use zlib])]) 12 | 13 | zlib_objs=hello_no_libz.o 14 | if test "$with_zlib" != no 15 | then 16 | a=0 17 | AC_CHECK_HEADERS(zlib.h, [], [a=1]) 18 | AC_SEARCH_LIBS(deflate, z, [], [a=1]) 19 | 20 | if test $a == 0 21 | then 22 | zlib_objs=hello_libz.o 23 | fi 24 | fi 25 | 26 | object_files="$object_files $zlib_objs" 27 | 28 | 29 | 30 | dnl Make AC_OUTPUT substitute the contents of $object_files for @objs@ 31 | AC_SUBST(objs, ["$object_files"]) 32 | 33 | dnl Process Makefile.in to create Makefile 34 | AC_OUTPUT(Makefile) 35 | 36 | -------------------------------------------------------------------------------- /ex_08/hello_libz.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void hello() 7 | { 8 | //Output a string, compressed in gzip format. 9 | unsigned char in[] = "Hello, I am a program\n"; 10 | unsigned char out[1024] = {}; 11 | 12 | z_stream strm = {}; 13 | deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 8+16, 9, Z_DEFAULT_STRATEGY); 14 | strm.next_in = in; 15 | strm.avail_in = sizeof(in); 16 | strm.next_out = out; 17 | strm.avail_out = sizeof(out); 18 | deflate(&strm, Z_FINISH); 19 | deflateEnd(&strm); 20 | 21 | cout.write((const char*)out, strm.total_out); 22 | } 23 | -------------------------------------------------------------------------------- /ex_08/hello_no_libz.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void hello() 6 | { 7 | char data[]={0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 8 | 0x03,0xf3,0x48,0xcd,0xc9,0xc9,0xd7,0x51,0xf0, 9 | 0x54,0x48,0xcc,0x55,0x48,0x54,0x28,0x28,0xca, 10 | 0x4f,0x2f,0x4a,0xcc,0xe5,0x62,0x00,0x00,0x45, 11 | 0x29,0xde,0xb8,0x17,0x00,0x00,0x00}; 12 | 13 | cout.write(data, sizeof(data)); 14 | } 15 | -------------------------------------------------------------------------------- /ex_08/program.cc: -------------------------------------------------------------------------------- 1 | using namespace std; 2 | 3 | //The purpose here is to teach autoconf, not C++ best 4 | //practices... 5 | void hello(); 6 | 7 | int main() 8 | { 9 | hello(); 10 | } 11 | -------------------------------------------------------------------------------- /ex_09/Makefile.in: -------------------------------------------------------------------------------- 1 | CXX=@CXX@ 2 | LD=@CXX@ 3 | CXXFLAGS=@CXXFLAGS@ 4 | LDFLAGS=@LDFLAGS@ 5 | LIBS=@LIBS@ 6 | VPATH=@srcdir@ 7 | objs=@objs@ 8 | 9 | program: program.o $(objs) 10 | $(LD) -o $@ $^ $(LDFLAGS) $(LIBS) 11 | 12 | .PHONY: clean 13 | clean: 14 | rm -f program *.o 15 | 16 | -------------------------------------------------------------------------------- /ex_09/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(program, 1.0) 2 | 3 | dnl Switch to a C++ compiler, and check if it works. 4 | AC_LANG(C++) 5 | AC_PROG_CXX 6 | 7 | dnl List of object files as determined by autoconf 8 | object_files="" 9 | 10 | 11 | AC_ARG_WITH(zlib, [AS_HELP_STRING([--without-zlib], [do not use zlib])]) 12 | 13 | zlib_objs=hello_no_libz.o 14 | if test "$with_zlib" != no 15 | then 16 | a=0 17 | AC_CHECK_HEADERS(zlib.h, [], [a=1]) 18 | AC_SEARCH_LIBS(deflate, z, [], [a=1]) 19 | 20 | if test $a == 0 21 | then 22 | zlib_objs=hello_libz.o 23 | fi 24 | fi 25 | 26 | object_files="$object_files $zlib_objs" 27 | 28 | 29 | 30 | dnl Make AC_OUTPUT substitute the contents of $object_files for @objs@ 31 | AC_SUBST(objs, ["$object_files"]) 32 | 33 | dnl Process Makefile.in to create Makefile 34 | AC_OUTPUT(Makefile) 35 | 36 | -------------------------------------------------------------------------------- /ex_09/hello_libz.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void hello() 7 | { 8 | //Output a string, compressed in gzip format. 9 | unsigned char in[] = "Hello, I am a program\n"; 10 | unsigned char out[1024] = {}; 11 | 12 | z_stream strm = {}; 13 | deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 8+16, 9, Z_DEFAULT_STRATEGY); 14 | strm.next_in = in; 15 | strm.avail_in = sizeof(in); 16 | strm.next_out = out; 17 | strm.avail_out = sizeof(out); 18 | deflate(&strm, Z_FINISH); 19 | deflateEnd(&strm); 20 | 21 | cout.write((const char*)out, strm.total_out); 22 | } 23 | -------------------------------------------------------------------------------- /ex_09/hello_no_libz.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void hello() 6 | { 7 | char data[]={0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00,0x00, 8 | 0x03,0xf3,0x48,0xcd,0xc9,0xc9,0xd7,0x51,0xf0, 9 | 0x54,0x48,0xcc,0x55,0x48,0x54,0x28,0x28,0xca, 10 | 0x4f,0x2f,0x4a,0xcc,0xe5,0x62,0x00,0x00,0x45, 11 | 0x29,0xde,0xb8,0x17,0x00,0x00,0x00}; 12 | 13 | cout.write(data, sizeof(data)); 14 | } 15 | -------------------------------------------------------------------------------- /ex_09/program.cc: -------------------------------------------------------------------------------- 1 | using namespace std; 2 | 3 | //The purpose here is to teach autoconf, not C++ best 4 | //practices... 5 | void hello(); 6 | 7 | int main() 8 | { 9 | hello(); 10 | } 11 | -------------------------------------------------------------------------------- /ex_10/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(myconfig, version-0.1) 2 | AC_PROG_CXX 3 | 4 | 5 | AC_SEARCH_LIBS(cos, m) 6 | 7 | echo "This library check will fail" >&AS_MESSAGE_LOG_FD 8 | AC_SEARCH_LIBS(foo, bar) 9 | 10 | AC_MSG_NOTICE([This message will appear in the log and on the screen]) 11 | AC_CHECK_HEADERS(foo, bar) 12 | -------------------------------------------------------------------------------- /ex_11/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(myconfig, version-0.1) 2 | AC_LANG(C++) 3 | AC_PROG_CXX 4 | 5 | 6 | m4_include([m4/ax_cxx_compile_stdcxx.m4]) 7 | AX_CXX_COMPILE_STDCXX(14) 8 | 9 | -------------------------------------------------------------------------------- /ex_11/m4/ax_cxx_compile_stdcxx.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the specified 12 | # version of the C++ standard. If necessary, add switches to CXX and 13 | # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) 14 | # or '14' (for the C++14 standard). 15 | # 16 | # The second argument, if specified, indicates whether you insist on an 17 | # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. 18 | # -std=c++11). If neither is specified, you get whatever works, with 19 | # preference for an extended mode. 20 | # 21 | # The third argument, if specified 'mandatory' or if left unspecified, 22 | # indicates that baseline support for the specified C++ standard is 23 | # required and that the macro should error out if no mode with that 24 | # support is found. If specified 'optional', then configuration proceeds 25 | # regardless, after defining HAVE_CXX${VERSION} if and only if a 26 | # supporting mode is found. 27 | # 28 | # LICENSE 29 | # 30 | # Copyright (c) 2008 Benjamin Kosnik 31 | # Copyright (c) 2012 Zack Weinberg 32 | # Copyright (c) 2013 Roy Stogner 33 | # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov 34 | # Copyright (c) 2015 Paul Norman 35 | # Copyright (c) 2015 Moritz Klammler 36 | # 37 | # Copying and distribution of this file, with or without modification, are 38 | # permitted in any medium without royalty provided the copyright notice 39 | # and this notice are preserved. This file is offered as-is, without any 40 | # warranty. 41 | 42 | #serial 4 43 | 44 | dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro 45 | dnl (serial version number 13). 46 | 47 | AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl 48 | m4_if([$1], [11], [], 49 | [$1], [14], [], 50 | [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])], 51 | [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl 52 | m4_if([$2], [], [], 53 | [$2], [ext], [], 54 | [$2], [noext], [], 55 | [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl 56 | m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], 57 | [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], 58 | [$3], [optional], [ax_cxx_compile_cxx$1_required=false], 59 | [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) 60 | AC_LANG_PUSH([C++])dnl 61 | ac_success=no 62 | AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, 63 | ax_cv_cxx_compile_cxx$1, 64 | [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 65 | [ax_cv_cxx_compile_cxx$1=yes], 66 | [ax_cv_cxx_compile_cxx$1=no])]) 67 | if test x$ax_cv_cxx_compile_cxx$1 = xyes; then 68 | ac_success=yes 69 | fi 70 | 71 | m4_if([$2], [noext], [], [dnl 72 | if test x$ac_success = xno; then 73 | for switch in -std=gnu++$1 -std=gnu++0x; do 74 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 75 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 76 | $cachevar, 77 | [ac_save_CXX="$CXX" 78 | CXX="$CXX $switch" 79 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 80 | [eval $cachevar=yes], 81 | [eval $cachevar=no]) 82 | CXX="$ac_save_CXX"]) 83 | if eval test x\$$cachevar = xyes; then 84 | CXX="$CXX $switch" 85 | if test -n "$CXXCPP" ; then 86 | CXXCPP="$CXXCPP $switch" 87 | fi 88 | ac_success=yes 89 | break 90 | fi 91 | done 92 | fi]) 93 | 94 | m4_if([$2], [ext], [], [dnl 95 | if test x$ac_success = xno; then 96 | dnl HP's aCC needs +std=c++11 according to: 97 | dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf 98 | dnl Cray's crayCC needs "-h std=c++11" 99 | for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do 100 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 101 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 102 | $cachevar, 103 | [ac_save_CXX="$CXX" 104 | CXX="$CXX $switch" 105 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 106 | [eval $cachevar=yes], 107 | [eval $cachevar=no]) 108 | CXX="$ac_save_CXX"]) 109 | if eval test x\$$cachevar = xyes; then 110 | CXX="$CXX $switch" 111 | if test -n "$CXXCPP" ; then 112 | CXXCPP="$CXXCPP $switch" 113 | fi 114 | ac_success=yes 115 | break 116 | fi 117 | done 118 | fi]) 119 | AC_LANG_POP([C++]) 120 | if test x$ax_cxx_compile_cxx$1_required = xtrue; then 121 | if test x$ac_success = xno; then 122 | AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) 123 | fi 124 | fi 125 | if test x$ac_success = xno; then 126 | HAVE_CXX$1=0 127 | AC_MSG_NOTICE([No compiler with C++$1 support was found]) 128 | else 129 | HAVE_CXX$1=1 130 | AC_DEFINE(HAVE_CXX$1,1, 131 | [define if the compiler supports basic C++$1 syntax]) 132 | fi 133 | AC_SUBST(HAVE_CXX$1) 134 | ]) 135 | 136 | 137 | dnl Test body for checking C++11 support 138 | 139 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], 140 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 141 | ) 142 | 143 | 144 | dnl Test body for checking C++14 support 145 | 146 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], 147 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 148 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 149 | ) 150 | 151 | 152 | dnl Tests for new features in C++11 153 | 154 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ 155 | 156 | // If the compiler admits that it is not ready for C++11, why torture it? 157 | // Hopefully, this will speed up the test. 158 | 159 | #ifndef __cplusplus 160 | 161 | #error "This is not a C++ compiler" 162 | 163 | #elif __cplusplus < 201103L 164 | 165 | #error "This is not a C++11 compiler" 166 | 167 | #else 168 | 169 | namespace cxx11 170 | { 171 | 172 | namespace test_static_assert 173 | { 174 | 175 | template 176 | struct check 177 | { 178 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 179 | }; 180 | 181 | } 182 | 183 | namespace test_final_override 184 | { 185 | 186 | struct Base 187 | { 188 | virtual void f() {} 189 | }; 190 | 191 | struct Derived : public Base 192 | { 193 | virtual void f() override {} 194 | }; 195 | 196 | } 197 | 198 | namespace test_double_right_angle_brackets 199 | { 200 | 201 | template < typename T > 202 | struct check {}; 203 | 204 | typedef check single_type; 205 | typedef check> double_type; 206 | typedef check>> triple_type; 207 | typedef check>>> quadruple_type; 208 | 209 | } 210 | 211 | namespace test_decltype 212 | { 213 | 214 | int 215 | f() 216 | { 217 | int a = 1; 218 | decltype(a) b = 2; 219 | return a + b; 220 | } 221 | 222 | } 223 | 224 | namespace test_type_deduction 225 | { 226 | 227 | template < typename T1, typename T2 > 228 | struct is_same 229 | { 230 | static const bool value = false; 231 | }; 232 | 233 | template < typename T > 234 | struct is_same 235 | { 236 | static const bool value = true; 237 | }; 238 | 239 | template < typename T1, typename T2 > 240 | auto 241 | add(T1 a1, T2 a2) -> decltype(a1 + a2) 242 | { 243 | return a1 + a2; 244 | } 245 | 246 | int 247 | test(const int c, volatile int v) 248 | { 249 | static_assert(is_same::value == true, ""); 250 | static_assert(is_same::value == false, ""); 251 | static_assert(is_same::value == false, ""); 252 | auto ac = c; 253 | auto av = v; 254 | auto sumi = ac + av + 'x'; 255 | auto sumf = ac + av + 1.0; 256 | static_assert(is_same::value == true, ""); 257 | static_assert(is_same::value == true, ""); 258 | static_assert(is_same::value == true, ""); 259 | static_assert(is_same::value == false, ""); 260 | static_assert(is_same::value == true, ""); 261 | return (sumf > 0.0) ? sumi : add(c, v); 262 | } 263 | 264 | } 265 | 266 | namespace test_noexcept 267 | { 268 | 269 | int f() { return 0; } 270 | int g() noexcept { return 0; } 271 | 272 | static_assert(noexcept(f()) == false, ""); 273 | static_assert(noexcept(g()) == true, ""); 274 | 275 | } 276 | 277 | namespace test_constexpr 278 | { 279 | 280 | template < typename CharT > 281 | unsigned long constexpr 282 | strlen_c_r(const CharT *const s, const unsigned long acc) noexcept 283 | { 284 | return *s ? strlen_c_r(s + 1, acc + 1) : acc; 285 | } 286 | 287 | template < typename CharT > 288 | unsigned long constexpr 289 | strlen_c(const CharT *const s) noexcept 290 | { 291 | return strlen_c_r(s, 0UL); 292 | } 293 | 294 | static_assert(strlen_c("") == 0UL, ""); 295 | static_assert(strlen_c("1") == 1UL, ""); 296 | static_assert(strlen_c("example") == 7UL, ""); 297 | static_assert(strlen_c("another\0example") == 7UL, ""); 298 | 299 | } 300 | 301 | namespace test_rvalue_references 302 | { 303 | 304 | template < int N > 305 | struct answer 306 | { 307 | static constexpr int value = N; 308 | }; 309 | 310 | answer<1> f(int&) { return answer<1>(); } 311 | answer<2> f(const int&) { return answer<2>(); } 312 | answer<3> f(int&&) { return answer<3>(); } 313 | 314 | void 315 | test() 316 | { 317 | int i = 0; 318 | const int c = 0; 319 | static_assert(decltype(f(i))::value == 1, ""); 320 | static_assert(decltype(f(c))::value == 2, ""); 321 | static_assert(decltype(f(0))::value == 3, ""); 322 | } 323 | 324 | } 325 | 326 | namespace test_uniform_initialization 327 | { 328 | 329 | struct test 330 | { 331 | static const int zero {}; 332 | static const int one {1}; 333 | }; 334 | 335 | static_assert(test::zero == 0, ""); 336 | static_assert(test::one == 1, ""); 337 | 338 | } 339 | 340 | namespace test_lambdas 341 | { 342 | 343 | void 344 | test1() 345 | { 346 | auto lambda1 = [](){}; 347 | auto lambda2 = lambda1; 348 | lambda1(); 349 | lambda2(); 350 | } 351 | 352 | int 353 | test2() 354 | { 355 | auto a = [](int i, int j){ return i + j; }(1, 2); 356 | auto b = []() -> int { return '0'; }(); 357 | auto c = [=](){ return a + b; }(); 358 | auto d = [&](){ return c; }(); 359 | auto e = [a, &b](int x) mutable { 360 | const auto identity = [](int y){ return y; }; 361 | for (auto i = 0; i < a; ++i) 362 | a += b--; 363 | return x + identity(a + b); 364 | }(0); 365 | return a + b + c + d + e; 366 | } 367 | 368 | int 369 | test3() 370 | { 371 | const auto nullary = [](){ return 0; }; 372 | const auto unary = [](int x){ return x; }; 373 | using nullary_t = decltype(nullary); 374 | using unary_t = decltype(unary); 375 | const auto higher1st = [](nullary_t f){ return f(); }; 376 | const auto higher2nd = [unary](nullary_t f1){ 377 | return [unary, f1](unary_t f2){ return f2(unary(f1())); }; 378 | }; 379 | return higher1st(nullary) + higher2nd(nullary)(unary); 380 | } 381 | 382 | } 383 | 384 | namespace test_variadic_templates 385 | { 386 | 387 | template 388 | struct sum; 389 | 390 | template 391 | struct sum 392 | { 393 | static constexpr auto value = N0 + sum::value; 394 | }; 395 | 396 | template <> 397 | struct sum<> 398 | { 399 | static constexpr auto value = 0; 400 | }; 401 | 402 | static_assert(sum<>::value == 0, ""); 403 | static_assert(sum<1>::value == 1, ""); 404 | static_assert(sum<23>::value == 23, ""); 405 | static_assert(sum<1, 2>::value == 3, ""); 406 | static_assert(sum<5, 5, 11>::value == 21, ""); 407 | static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); 408 | 409 | } 410 | 411 | // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae 412 | // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function 413 | // because of this. 414 | namespace test_template_alias_sfinae 415 | { 416 | 417 | struct foo {}; 418 | 419 | template 420 | using member = typename T::member_type; 421 | 422 | template 423 | void func(...) {} 424 | 425 | template 426 | void func(member*) {} 427 | 428 | void test(); 429 | 430 | void test() { func(0); } 431 | 432 | } 433 | 434 | } // namespace cxx11 435 | 436 | #endif // __cplusplus >= 201103L 437 | 438 | ]]) 439 | 440 | 441 | dnl Tests for new features in C++14 442 | 443 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ 444 | 445 | // If the compiler admits that it is not ready for C++14, why torture it? 446 | // Hopefully, this will speed up the test. 447 | 448 | #ifndef __cplusplus 449 | 450 | #error "This is not a C++ compiler" 451 | 452 | #elif __cplusplus < 201402L 453 | 454 | #error "This is not a C++14 compiler" 455 | 456 | #else 457 | 458 | namespace cxx14 459 | { 460 | 461 | namespace test_polymorphic_lambdas 462 | { 463 | 464 | int 465 | test() 466 | { 467 | const auto lambda = [](auto&&... args){ 468 | const auto istiny = [](auto x){ 469 | return (sizeof(x) == 1UL) ? 1 : 0; 470 | }; 471 | const int aretiny[] = { istiny(args)... }; 472 | return aretiny[0]; 473 | }; 474 | return lambda(1, 1L, 1.0f, '1'); 475 | } 476 | 477 | } 478 | 479 | namespace test_binary_literals 480 | { 481 | 482 | constexpr auto ivii = 0b0000000000101010; 483 | static_assert(ivii == 42, "wrong value"); 484 | 485 | } 486 | 487 | namespace test_generalized_constexpr 488 | { 489 | 490 | template < typename CharT > 491 | constexpr unsigned long 492 | strlen_c(const CharT *const s) noexcept 493 | { 494 | auto length = 0UL; 495 | for (auto p = s; *p; ++p) 496 | ++length; 497 | return length; 498 | } 499 | 500 | static_assert(strlen_c("") == 0UL, ""); 501 | static_assert(strlen_c("x") == 1UL, ""); 502 | static_assert(strlen_c("test") == 4UL, ""); 503 | static_assert(strlen_c("another\0test") == 7UL, ""); 504 | 505 | } 506 | 507 | namespace test_lambda_init_capture 508 | { 509 | 510 | int 511 | test() 512 | { 513 | auto x = 0; 514 | const auto lambda1 = [a = x](int b){ return a + b; }; 515 | const auto lambda2 = [a = lambda1(x)](){ return a; }; 516 | return lambda2(); 517 | } 518 | 519 | } 520 | 521 | namespace test_digit_seperators 522 | { 523 | 524 | constexpr auto ten_million = 100'000'000; 525 | static_assert(ten_million == 100000000, ""); 526 | 527 | } 528 | 529 | namespace test_return_type_deduction 530 | { 531 | 532 | auto f(int& x) { return x; } 533 | decltype(auto) g(int& x) { return x; } 534 | 535 | template < typename T1, typename T2 > 536 | struct is_same 537 | { 538 | static constexpr auto value = false; 539 | }; 540 | 541 | template < typename T > 542 | struct is_same 543 | { 544 | static constexpr auto value = true; 545 | }; 546 | 547 | int 548 | test() 549 | { 550 | auto x = 0; 551 | static_assert(is_same::value, ""); 552 | static_assert(is_same::value, ""); 553 | return x; 554 | } 555 | 556 | } 557 | 558 | } // namespace cxx14 559 | 560 | #endif // __cplusplus >= 201402L 561 | 562 | ]]) 563 | -------------------------------------------------------------------------------- /ex_12/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(myconfig, version-0.1) 2 | AC_LANG(C++) 3 | AC_PROG_CXX 4 | 5 | 6 | dnl TEST_AND_SET_CXXFLAG(flag, [program]) 7 | dnl 8 | dnl This attempts to compile a program with a certain compiler flag. 9 | dnl If no program is given, then the minimal C++ program is compiled, and 10 | dnl this tests just the validity of the compiler flag. 11 | dnl 12 | define([TEST_AND_SET_CXXFLAG],[ 13 | AC_MSG_CHECKING([if compiler flag $1 works]) 14 | 15 | dnl Store the current CXXFLAGS 16 | save_CXXFLAGS="$CXXFLAGS" 17 | 18 | dnl Append the flag of interest 19 | CXXFLAGS="$CXXFLAGS $1" 20 | 21 | dnl Create an M4 macro, "prog", which expands to a C++ program. 22 | dnl This should either be a default one or the one specified. 23 | dnl Note that macros are not local, but there is a stack so push 24 | dnl the definition on to the stack to prevent clobbering a definition 25 | dnl that might already exist. 26 | m4_if([$2],[],[pushdef(prog, [int main(){}])], [pushdef(prog, [$2])]) 27 | 28 | flag_test=0 29 | 30 | dnl See if the compiler runs 31 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([prog])], [flag_test=1],[flag_test=0]) 32 | 33 | dnl De-clobber the "prog" macro 34 | popdef([prog]) 35 | 36 | if test $flag_test = 1 37 | then 38 | AC_MSG_RESULT(yes) 39 | else 40 | AC_MSG_RESULT(no) 41 | dnl The flag doesn't work, so restore the old CXXFLAGS 42 | CXXFLAGS="$save_CXXFLAGS" 43 | fi 44 | ]) 45 | 46 | 47 | dnl Add flags, but only if the flags weren't overridden already 48 | if test "$CXXFLAGS" == "-g -O2" 49 | then 50 | 51 | TEST_AND_SET_CXXFLAG(-Wall) 52 | TEST_AND_SET_CXXFLAG(-Wextra) 53 | TEST_AND_SET_CXXFLAG(-W) 54 | TEST_AND_SET_CXXFLAG(-O3) 55 | TEST_AND_SET_CXXFLAG(-ggdb) 56 | TEST_AND_SET_CXXFLAG(-fnot-a-valid-flag) 57 | fi 58 | 59 | -------------------------------------------------------------------------------- /ex_13/configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT(myconfig, version-0.1) 2 | AC_LANG(C++) 3 | AC_PROG_CXX 4 | 5 | dnl list of all possible optional components 6 | all_options="jpeg png tiff funkyimage v4l2 ffmpeg awesomevideo" 7 | 8 | dnl When a component is found, append it here 9 | options= 10 | 11 | dnl Force the compiler to run once and do all the basic checks 12 | dnl if you don't, it will do the test on the first invocation 13 | dnl below and so your pretty section titles won't work as well 14 | AC_CHECK_HEADERS(iostream) 15 | 16 | dnl Small macro to print out a nice, pretty section title. 17 | define(SECTION_TITLE, 18 | [ 19 | echo >& AS_MESSAGE_FD 20 | echo ' $1 ' | sed -e's/./-/g' >&AS_MESSAGE_FD 21 | echo ' $1' >& AS_MESSAGE_FD 22 | echo ' $1 ' | sed -e's/./-/g' >&AS_MESSAGE_FD 23 | ]) 24 | 25 | 26 | SECTION_TITLE([Checking for image libraries]) 27 | 28 | a=0 29 | AC_CHECK_HEADERS(jpeglib.h, [], [a=1]) 30 | AC_SEARCH_LIBS(jpeg_set_defaults, jpeg, [], [a=1]) 31 | if test $a == 0 32 | then 33 | options="$options jpeg" 34 | fi 35 | 36 | a=0 37 | AC_CHECK_HEADERS(png.h, [], [a=1]) 38 | AC_SEARCH_LIBS(png_create_info_struct, png, [], [a=1]) 39 | if test $a == 0 40 | then 41 | options="$options png" 42 | fi 43 | 44 | a=0 45 | AC_CHECK_HEADERS(tiffio.h, [], [a=1]) 46 | AC_SEARCH_LIBS(TIFFOpen, tiff, [], [a=1]) 47 | if test $a == 0 48 | then 49 | options="$options tiff" 50 | fi 51 | 52 | a=0 53 | AC_CHECK_HEADERS(funkyimage.h, [], [a=1]) 54 | AC_SEARCH_LIBS(funkyopen, funkyimage, [], [a=1]) 55 | if test $a == 0 56 | then 57 | options="$options tiff" 58 | fi 59 | 60 | 61 | SECTION_TITLE([Checking for video options]) 62 | 63 | a=0 64 | AC_CHECK_HEADERS(linux/videodev2.h, [], [a=1]) 65 | if test $a == 0 66 | then 67 | options="$options v4l2" 68 | fi 69 | 70 | 71 | 72 | dnl this one is quite big, so give some helpful extra 73 | dnl messages 74 | AC_MSG_CHECKING([for ffmpeg]) 75 | AC_MSG_RESULT([]) 76 | 77 | a=0 78 | AC_CHECK_HEADERS([libavcodec/avcodec.h libavformat/avformat.h libswscale/swscale.h], [], [a=1]) 79 | AC_SEARCH_LIBS(main, avutil, [], [a=1]) 80 | AC_SEARCH_LIBS(av_read_frame, avformat, [], [a=1]) 81 | AC_SEARCH_LIBS(avcodec_open2, avcodec, [], [a=1]) 82 | AC_SEARCH_LIBS(sws_getContext, swscale, [], [a=1]) 83 | if test $a == 0 84 | then 85 | options="$options ffmpeg" 86 | else 87 | AC_MSG_NOTICE([ffmpeg not found]) 88 | fi 89 | 90 | a=0 91 | AC_CHECK_HEADERS(awesomevid.h, [], [a=1]) 92 | AC_SEARCH_LIBS(openawesome, awesomevid, [], [a=1]) 93 | if test $a == 0 94 | then 95 | options="$options awesomevideo" 96 | fi 97 | 98 | 99 | 100 | 101 | dnl Now process the options strings. Essentially, we want two lists 102 | dnl one for the options present (which we have) and one for the options 103 | dnl missing (which we don't) 104 | 105 | SECTION_TITLE([Configuration results]) 106 | 107 | echo "Options:" >& AS_MESSAGE_FD 108 | echo "$options" >& AS_MESSAGE_FD 109 | echo >& AS_MESSAGE_FD 110 | 111 | echo "Missing options:" >& AS_MESSAGE_FD 112 | echo "$options" "$all_options" | tr ' ' '\n' | sort | uniq -u | tr '\n' ' ' >& AS_MESSAGE_FD 113 | 114 | 115 | echo -e "\n\n" >& AS_MESSAGE_FD 116 | echo "CXXFLAGS=$CXXFLAGS" >& AS_MESSAGE_FD 117 | echo "LDFLAGS=$LDFLAGS" >& AS_MESSAGE_FD 118 | echo "LIBS=$LIBS" >& AS_MESSAGE_FD 119 | --------------------------------------------------------------------------------