• Stars
    star
    307
  • Rank 136,109 (Top 3 %)
  • Language
    Go
  • License
    Other
  • Created about 10 years ago
  • Updated about 9 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Another build system for C/C++, I guess? Inspired by 'go build'

qo: a build system for C/C++

qo is a new build system for C and C++ (though I can add other languages later). In contrast to existing build systems, which require the use of not only a Makefile but also an assortment of complex configuration files (or multiple stages thereof), qo doesn't use any. Instead, custom build settings are embedded using simple directives directly into the source code of your program. qo conditionally compiles each source file based on its filename. qo also supports some resource files normally compiled into the program. Debug builds and cross-compiles are also intended to be done as easily as possible.

Enjoy! Suggestions, fixes, etc. welcome.

News

14 April 2015
Added a -nounix flag to inhibit the unix pseudo-OS.

6 April 2015
Added unix pseudo-OS.

2 March 2015
I rewrote the actual build script part of the program a bit: some of the internal names have changed, a script can have an arbitrary number of stages (groups of steps that must be completed before the next group can start), and most important, load balancing. A future change will provide an option to change the number of concurrent build steps (currently set to the number of CPU cores on your system). Please report any bugs should this have broken anything.

Installing

qo is written in Go. It has no outside dependencies and does not use cgo, so a compiled qo binary is statically linked and ready to run out of the box. Once the project matures more, I may offer prebuilt binaries for download.

Getting Started

Let's say you have a simple project in a directory:

$ cd project
$ ls
file1.c  file2.c  file3.c  file4.c  project.h

To build this project as it stands, simply invoke qo with no arguments:

$ qo
[  0%] Beginning build
[ 20%] Compiled file1.c
[ 40%] Compiled file3.c
[ 60%] Compiled file4.c
[ 80%] Compiled file2.c
[100%] Linked project

You should see the status of the build as it happens (as above), and upon completion, the compiled program will be left as the executable project (named after the project directory) in the project directory, ready for running:

$ ./project

To build a debug version, pass -g:

$ qo -g

To see the individual commands as they happen, pass -x.

Note that qo automatically builds with as many reasonable compiler diagnostics as possible enabled.

What is Built?

qo scans the current directory and all subdirectories for files to build. Files matched have the given (case-insensitive) extensions:

  • C files: .c
  • C++ files: .cpp, .cxx, .c++, .cc
    • note the case-insensitive part; .C is recognized as C, not C++
  • C header files: .h, .hpp, .hxx, .h++, .hh
  • Objective-C files: .m
  • Objective-C++ files: .mm
  • Windows Resource files: .rc

Files can be excluded from the build if they are meant for a different operating system and/or CPU architecture; this is also done by filename and is described below, under "Cross-Compiling".

C files are assumed to be C99. C++ files are assumed to be C++11.

Configuring the Build

So how do you specify extra libraries or compiler options for a project? Simple: you include special directives in the source files! Directives take the form

// #qo directive: arguments

where whitespace up to and including the first space after #qo is significant, and where the // must be the first thing on the line.

The two most important (and most portable) directives are pkg-config and LIBS. pkg-config passes the package names listed in arguments to pkg-config, inserting the resultant compiler flags as needed. LIBS takes the library names in arguments and passes them to the linker, applying the correct argument format for the toolchain in use (see "Cross-Compiling" below). For example:

// #qo pkg-config: gtk+-3.0
// #qo LIBS: pwquality sqlite3

For more control over the command lines for compiling each file, the CFLAGS, CXXFLAGS, and LDFLAGS directives pass their arguments as extra arguments to the C compiler, C++ compiler, and linker, respectively.

#qo directives are assembled from all source files together. That is, do not copy the directives into each source file; bad things will happen.

In addition, the $CFLAGS, $CXXFLAGS, and $LDFLAGS environment variables also change compiler/linker command-line arguments.

Cross-Compiling

qo tries to make cross-compiling easy. There are three concepts at play:

  • the target OS
  • the target architecture
  • the toolchain, which defines which compilers and linkers to use

By default, qo builds for the system you are presently running (actually the system the qo binary was built for; but this is a limitation of Go). This is called the host. You can change the target OS, target arch, or toolchain with the -os, -arch, and -tc options, respectively. Pass list to see a list of supported OSs, architectures, and toolchains.

(qo by default tends toward gcc/clang-based toolchains.)

In addition, qo will omit files and folders from the build if they are intended for a different OS and/or architecture than the target. To omit a file, have _OS, _arch, or _OS_arch before the extension. To omit a folder, its name must consist entirely of OS, arch, or OS_arch. For example:

file.c                compiled always
file_windows.c        only compiled if targetting Windows
file_386.c            only compiled if targetting architecture 386
file_windows_386.c    only compiled if targetting 386-based Windows
directory/            trasversed always
windows/              only trasversed on Windows
386/                  only trasversed if targetting 386
windows_386/          only trasversed if targetting 386-based Windows

In addition, the OS name unix is valid on all Unix systems (Linux, FreeBSD, Mac OS X, etc.). You can choose to inhibit this with the -nounix flag.

Cross-Compiler Executable Search Order

Under the hood, however, cross-compiling is a very complex and problematic undertaking for historical and practical reasons. qo assumes you have a correctly configured cross-compiler setup for the target OS, architecture, and toolchain (even if it's just the toolchain).

qo makes the following compromise. Given the following terms:

unqualified binaries - binaries named gcc, g++, clang, and clang++, without any target triplet
multilib flags - -m32 and -m64

  1. If the -triplet option is passed to qo to explicitly specify a triplet to use, that triplet is used, no questions asked. No mulitlib flags will be appended to the command line.
  2. Otherwise, if the target is the same as the host, unqualified binaries are run, and multilib flags may or may not be appended.
  3. Otherwise, if the target OS is the same as the host OS and host OS is not Windows, if the host arch is either 386 or amd64 and the target arch is either 386 or amd64, a multilib flag is appended, and the unqualified binaries are run.
  4. Otherwise, if using clang, a generic target triplet is generated and used.
  5. Otherwise, if the target OS is windows, MinGW-w64 binaries are used.
  6. Otherwise, an error occurs.

For more information, see this and its references.

Notes

A note on optional features and cyclic dependencies

qo does not support the notion of optional features: everything in the recursive directory tree of the current directory is compiled. I personally don't like features being optional; if something really needs to be conditional, it should be a plugin, and there's no reason to ship a gimped or feature-incomplete version of a program. I don't like how graphviz packages in at least Ubuntu don't ship with pic support (even though I'm probably the only person int he world that still uses troff).

In a related vein, cyclic dependencies (usually caused by optional features, as is the case with GLib ↔ GVFS) should also be avoided.

Notes on MSVC

The version of MSVC used defines how much C99 or C++11 can be used.

The following seem to be undocumented as being MinGW extensions to the rc format:

  • arithmetic expressions

More Repositories

1

libui

Simple and portable (but not inflexible) GUI library in C that uses the native GUI technologies of each platform it supports.
C
10,723
star
2

ui

Platform-native GUI library for Go.
Go
8,336
star
3

reallymine

WD MyBook encrypted hard drive decryption (still WIP).
Go
214
star
4

wakeup

Simple alarm clock program; also a demonstration of andlabs/ui.
Go
54
star
5

utf

[development paused; issues and PRs still welcome] Portable UTF-8 and UTF-16 routines in a single C source file.
C
46
star
6

65816disasm

A disassembler for WDC 65816 binaries, specifically SNES ROMs for now.
Go
33
star
7

ews

quick and dirty Go package to send emails via Exchange using EWS instead of SMTP
Go
27
star
8

screentext

Go API for rendering text for on-screen display, using native APIs and system fonts.
Go
13
star
9

idapyscripts

Assorted IDAPython scripts for ROM hacking/research.
Python
13
star
10

a68

A simple, sane Motorola MC68000 assembler.
Go
9
star
11

pcmio

Raw PCM I/O library for Go.
Go
9
star
12

dl

libdl wrapper for Go.
Go
8
star
13

mamefuse

A FUSE filesystem that serves MAME ROMs from various places on your hard disk.
Go
8
star
14

huc6280disasm

A disassembler for HuC6280 binaries, specifically TurboGrafx-16/PC Engine ROMs for now.
Go
7
star
15

dumpattachments

Program to bulk-dump attachments from an IMAP account.
Go
7
star
16

barspy

[development paused; issues and PRs still welcome] Spy++-like program for inspecting Toolbars and Rebars.
C++
6
star
17

misctestprogs

Some miscellaneous test programs.
C
6
star
18

tms34010disasm

A disassembler for Texas Instruments TMS34010 binaries.
Go
5
star
19

mdlist

Mega Drive/Genesis game info list
Go
5
star
20

wintable

Windows API Table control, split from package ui. Not ready for general use.
C
5
star
21

e4jexamine

manual ext4 journal examining and data block extraction
Go
5
star
22

fmux

File multiplexer/interleaver.
Go
5
star
23

pgidl

small custom interface description language package and tools
Go
5
star
24

e4itblcmp

compares ext4 inode table blocks in a bunch of ways
Go
5
star
25

irksome

personal chat client
C
4
star
26

nointrochk

ROM set verifier for clrmamepro datfiles from no-intro dat-o-matic
Go
4
star
27

winiconview

Windows bulk icon resource viewer toy project.
C
4
star
28

enpipe

Force Unix programs to work in pipelines.
C
4
star
29

ohv

Oh! V, or the Omniscient Help Viewer, or the Offline Help Viewer, or whatever other thing you can think of...
C
4
star
30

macgetalbums

[development paused; issues and PRs still welcome] List all the albums you have in iTunes as a text file with the year of earliest release, among other things.
Objective-C
4
star
31

gtkcontrolspy

A silly thing to play around with GTK+ widgets in a sandbox. Inspired by Microsoft's Control Spy (http://msdn.microsoft.com/en-us/library/windows/desktop/bb773165(v=vs.85).aspx).
C
4
star
32

segaret_scans

The scan tracker used by Sega Retro; might be useful to you too
Go
3
star
33

simplesale

Dead-simple point of sale system. Because seriously. [IN ITS INFANCY, BEING REWRITTEN AGAIN]
C
3
star
34

mmbnmapdump

Shell
3
star
35

gogir

GObject Introspection-based bindings generator for Go [IN ITS INFANCY; WILL NOT ACTUALLY PRODUCE USABLE CODE NOW]
Go
3
star
36

windlgunits

An attempt at trying to make sense of the Windows API's dialog base units.
C
2
star
37

gcdown

Google Code scraping file downloader (for the Downloads tab)
Go
2
star
38

mshc2devhelp

Converts Microsoft Help Viewer mshc databases to devhelp files.
Go
2
star
39

ctlineboundstest

[development paused; issues and PRs still welcome] Core Text line height playground
Objective-C
2
star
40

gtkdatetimepicker

GTK+ Date-Time Picker control. Still in its infancy.
C
2
star
41

mwuploadbulk

Simple command-line MediaWiki bulk file uploader.
Go
2
star
42

ym2612

A hardware-accurate Yamaha YM2612 sound chip emulator, written in C and Go and using its concurrency features.
1
star