Automatic tuning (auto-tuning) of software has emerged in recent years as a promising method that tries to automatically adapt the behaviour of a program to attain different performance objectives on a given computing system. This method is gaining momentum due to the increasing complexity of modern multicore-based hardware architectures. Many solutions to auto-tuning have been explored ranging from simple random search to more sophisticate methods like machine learning or evolutionary search. To this day, it is still unclear whether these approaches are general enough to encompass all the complexities of the problem (e.g. search space, parameters influencing the search space, input data sensitivity, etc.), or which approach is best suited for a given problem. Furthermore, the growing interest in auto-tuning a program for several objectives is increasing this confusion even further. The goal of this paper is to formally describe the problem addressed by auto-tuning programs and review existing solutions highlighting the advantages and drawbacks of different techniques for single-objective as well as multi-objective auto-tuning approaches.