Skip to content
/ pake Public
forked from podusowski/pake

Friendly C++ build system which doesn't follow trends

Notifications You must be signed in to change notification settings

Quasek/pake

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Welcome to another, another C++ build tool

(example of pake script which does some more things like db generation, see more at rusted)

What is the difference?

The main difference is that pake's script does not allow any logic, it means, you can not make conditions, loops, etc, you just declare what shuold happen in given target and/or configuration and for any other stuff, regular script language can be used (eg. python or bash). Why? Because we seen many projects where build scripts are more complicated than the code behind them.

Meeh, another CMake?

No, CMake is a build system generator which provides some sort of programming language to do so. It's like writing a python script which generates Makefiles, only that CMake syntax is far from being a programming language.

I could stick with Makefiles then

You can, but it's too low-level, make doesn't understand C++ project structure by itself, it doesn't know that your .cpp file include some .hpp, so if this .hpp changes, then .cpp should be rebuilt. You have to write such dependencies (nobody does that) or dependency generation support yourself.

They say Ninja is modern, cool and fast

It is, but its scripts are not supposed to be written by hand, see their description: "it is designed to have its input files generated by a higher-level build system". But CMake has a generator for it, so if for some reason you won't like pake, I would recommend CMake+Ninja.

How to get it?

Because pake is a alpha quality software, the only official way of distributing it is to "build" it using waffle and put in inside your project repository. To simplify this, there is a shell script called make_pake.sh which generates __build/pake.py file which you can directly put and use in your project.

Tutorial

Starting a project

After putting pake.py somewhere suitable (for example in your project directory), create a pake module called build.pake. Note that only .pake extention is important, pake looks for all .pake files (we call them modules) inside your projects directory and you don't need to define them anywhere. Inside your build.pake file, put something like this:

target application my_app sources(main.cpp) # hi, I'ma comment!

this will define a target called my_app which is statically linked application which is built from main.cpp. To build it, just type ./pake.py my_app or ./pake.py -a if you want to build every target found in your tree. After building, your application will be placed into __build/__default directory. In case you wonder, __default is directory named from current build configuration, you will hear about them later.

Adding more files to the project

Say, you want to add some new file into your project, you can write:

target application my_app sources(main.cpp additional_file.cpp)

this will compile main.cpp and additional_file.cpp and link them together. When your list gets too big, you can split it by escaping new line:

target application my_app \
    sources(main.cpp \
            additional_file.cpp)

or you can use variables:

append $sources main.cpp
append $sources additional_file.cpp

target application my_app sources($sources)

Variable defining and dereferencing order

What is neat in pake variable system, is that you can define and reference the variables in any order you like, for example, you can do something like this:

target application my_app sources($all_sources yet_another_file.cpp)

append $sources $main_file
append $sources additional_file.cpp
append $main_file main.cpp

Defining compiler flags to the target

Very often, there is a need for adding compiler switches to the target, there is a possibility to add them to the whole tree, but let us keep it simple for now. To add those, you just need to add compiler_flags parameter to target definition. You can add the directories in which compiler will look for header files, but this way is not very scalable, instead, use include_dirs for that:

append $sources main.cpp
append $sources additional_file.cpp

target application my_app \
    sources($sources) \
    compiler_flags(-std=c++14) \
    include_dirs(includes other_includes)

Hopefully, this example is self-explainatory.

What's wrong with compiler_flags(-Iincludes)?

Because you have to add -I everywhere. For example, every module has special $__path variable, which you can use as your include directory, you can do this like application my_tests include_dirs($gtest.__path) or application my_tests compiler_flags("-I${gtest.__path}").

Bulding static libraries

Static library is just another type of target which pretty much behaves like the application target, only it builds an .a file which you can later link your application.

target static_library my_lib sources(library.cpp)
target application my_app link_with(my_lib) depends_on(my_lib) sources(main.cpp)

Few things here, first, the new, link_with attribute, which doesn't really need to be explained, but why we need depends_on? It's because you can put inside link_with everything which understands your linker, include system wide libraries and pake has no way of knowing if given library should be builts or just passed quietly to the linker.

Splitting your build script into modules

Until now, all examples assumed that you have one file in your source tree (build.pake, but if you remember, base name isn't exactly important; actually it is, but we will get there). Pake gives you ability to split such scripts into modules. For example, you can create two files:

# lib.pake
append $sources library.cpp
target static_library my_lib sources($sources)
# app.pake
append $sources main.cpp
target application my_app link_with(my_lib) depends_on(my_lib) sources($sources)

As you can see, module names don't have to be named after targets inside (you couldn't create multiple targets in one module if this would be a requirement). You can move this modules along with their sources everywhere you want, as long as you stay in your source tree, pake will find them.

Passing variables between the modules

Each module has its own variable namespace which isn't implicitly shared between them, in other words, you can create variables with the same name across modules (like $sources variable in previous example). This doesn't mean that you can't refer to variable from other module:

# lib.pake
# don't create any target, just define variable with the sources
append $sources library.cpp
# app.pake
append $sources main.cpp
append $sources $lib.sources
target application my_app link_with(my_lib) depends_on(my_lib) sources($sources)

It doesn't matter where your modules are, pake will find them and evaluate variables in proper way.

Special modules and variables

There are some so called "special" things predefined in pake.

`$__path` Variable exported in each module, it contains base patch for the directory when the module is. Use it like `$some_module.__path`
`$__null` Just null variable, nothing special, but it's useful when you want to export something from configuration.
`$__configuration` It's a special module in which all exported configuration variables are available from.

Using configurations

During pake invokation, you can define configuration which is pretty much set of rules which build process will follow. By default, pake uses predefined configuration called __default (it is named because you can override it as well as define new one). Now, let us change compiler and flags in default configuration:

configuration __default compiler(clang++) compiler_flags(-std=c++14)

This is default, but you can also create new configurations, see the example how it works:

append $win_graphic_libraries opengl32 # ...
append $linux_graphic_libraries GL # ...

configuration win32 \
    compiler(i686-w64-mingw32-c++) \
    archiver(i686-w64-mingw32-ar) \
    compiler_flags(-m32) \
    application_suffix(.exe) \
    export($win_graphic_libraries:$graphic_libraries)

configuration linux \
    export($linux_graphic_libraries:$graphic_libraries)

target application my_awesome_game \
    sources(main.cpp) \
    link_with($__configuration.graphic_libraries)

More documentation

Stay tuned for more docs here... in the mean time, see the wiki pages, there is some possibly outdated info there.

About

Friendly C++ build system which doesn't follow trends

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 81.3%
  • Shell 15.1%
  • Vim Script 1.8%
  • C++ 1.8%