• No results found

Supporting Other Operating Systems

I hadn’t touched a Windows development IDE in more than ten years, and I wanted to keep the same code base for all three operating systems. Somewhere during the past few years, I heard mention of MinGW (Minimalist GNU for Windows).

As I am familiar developing in a

GNU/Linux environment, this sounded like what I needed. To bring your Linux dev environment to Windows, use mingw-get-inst, and do a full installation.

This will provide you with the MinGW Shell, bundled with many standard GNU tools, including SSH. Next, install TortoiseSVN, which is a Subversion client that integrates with the Windows shell.

Checkout and commit actions are accessed by right-clicking on folders in Explorer to keep files in sync. The MinGW shell allows for changing drives’ letters like a standard DOS shell with cd C:.

The next problem is how to build the code based on operating system. Let’s look at two options: Makefiles and autotools. First, let’s look at basic Makefile-based builds and compare the differences by platform:

# Makefile.linux

all:

mkdir -p deps

g++ -DHAVE_CONFIG_H -I. -I.. -g -O2 -D__LINUX_ALSASEQ__

¯-g -O2 -MT midiio.o -MD -MP -MF deps/RtMidi.Tpo

¯-c -o RtMidi.o RtMidi.cpp

g++ -DHAVE_CONFIG_H -I. -I.. -g -O2 -D__LINUX_ALSASEQ__

¯-g -O2 -MT -midiio.o -MD -MP -MF deps/midiio.TPO

¯-c -o midiio.o midiio.cpp

g++ -g -O2 -o midiio RtMidi.o midiio.o -lasound

# Makefile.mingw

all:

mkdir -p deps

WWW.LINUXJOURNAL.COM SEPTEMBER 2011 | 65

g++ -DHAVE_CONFIG_H -I. -I.. -g -O2 -D__WINDOWS_MM__

¯-g -O2 -MT RtMidi.o -MD -MP -MF deps/RtMidi.Tpo

¯-c -o RtMidi.o RtMidi.cpp

g++ -DHAVE_CONFIG_H -I. -I.. -g -O2 -D__WINDOWS_MM__

¯-g -O2 -MT -midiio.o -MD -MP -MF deps/midiio.TPO

¯-c -o midiio.o midiio.cpp

g++ -g -Wl,--enable-auto-import -O2 -o midiio RtMidi.o

¯midiio.o -lwinmm

The library I used, rtmidi, requires that the platform be defined, so for Linux, define -D_ _LINUX_ALSASEQ_ _, and for Windows, define -D_ _WINDOWS_ _MM_ _.

The last step in each is the linking phase, where you specify system

libraries to link to the binary. To enable a clean build under Windows, I had to add -Wl,--enable-auto-import, so functions would be auto-imported.

Now, let’s look at autotools-based builds. Usually when an autotools-based build is committed to version control, only non-generated files are committed, which includes configure.ac, Makefile.am and src/Makefile.am. The standard practice is to create an autogen.sh script that will call the files to generate configure, Makefile and other required files from *.ac and *.am files:

# Autogen.sh

configure.ac (Listing 1) contains host-based auto-detection and is where to specify which host-based libraries to check for and link against.

Full code for these examples can be downloaded from the game2midi project’s Subversion repository in the basic-midi-io-example folder.

Conclusion

Using GNU libraries and tools can help reduce the time and effort required in supporting multiple platforms. I hope this article encourages you to consider adding multiplatform support to a current or future open-source project.I Nathanael Anderson has been a UNIX systems administrator for five years. Family, coding and all things guitar keep him active.

Feel free to contact him on his blog at wirelessdreamer.com.

FEATURE Multiplatform GNU Development

Resources

Official Midi Specification:

www.midi.org/techspecs/midimessages.php

Posts of Mustang Controller Dumps: www.rockband.com/

forums/showthread.php?t=207792&page=1

Official RtMidi Home Page:

www.music.mcgill.ca/~gary/rtmidi

game2midi Home Page: game2midi.sourceforge.net

WWW.LINUXJOURNAL.COM SEPTEMBER 2011 | 67

Listing 1. configure.ac

#configure.ac

dnl - dnl represents a comment in automake config files dnl here we specify the

AC_INIT(midiio,0.1) AM_INIT_AUTOMAKE(midiio, 0.1) AC_PROG_CXX

AC_LANG_C

dnl Checks for programs.

AC_PROG_AWK AC_PROG_CC

dnl Check for headers AC_CHECK_HEADERS(unistd.h)

dnl Checks for typedefs, structures, and compiler characteristics.

AC_TYPE_SIZE_T

dnl Detect OS we're building on

dnl this next line is required to be able to read the host value AC_CANONICAL_HOST

dnl Use the value here to add support for other operating systems echo "Host Value: '${host}'"

case "${host}" in

*-mingw32*)

dnl specify Windows specific compiler flags

¯and linker options compile_target=win

CPPFLAGS="$CPPFLAGS -D_ _WINDOWS_MM_ _"

LIBS="$LIBS -lwinmm"

;;

*linux-gnu)

dnl specify Linux specific compiler flags

¯and linker options compile_target=linux dnl Check for ALSA

AC_CHECK_LIB(asound, snd_seq_event_output_direct,

¯alsalib=yes,alsalib=no)

AC_CHECK_HEADERS(alsa/asoundlib.h,alsaheader=yes,

¯alsaheader=no)

if test "$alsalib" = "yes"; then

if test "$alsaheader" = "yes"; then LIBS="$LIBS -lasound"

else

AC_MSG_ERROR([** Coulnd't find ALSA

¯header file sys/asoundlib.h **]) fi

else

AC_MSG_ERROR([** Couldn't find ALSA library

¯libasound. **]) fi

CPPFLAGS="$CPPFLAGS -D_ _LINUX_ALSASEQ_ _"

;;

esac

AC_HEADER_STDC

AM_CONFIG_HEADER(config.h) AC_OUTPUT(Makefile src/Makefile)

# Makefile.am

# Here we specify we have files in the source directory to process AUTOMAKE_OPTIONS = foreign

SUBDIRS = src

# src/Makefile.am

# Here we define there are 2 programs we're compiling bin_PROGRAMS = midiio midiout

# and here we define what we put together to make the final programs midiout_SOURCES = midiout.cpp RtMidi.cpp

midiio_SOURCES = midiio.cpp RtMidi.cpp

R

egression testing is a well-established technique to detect both the introduction of new bugs and the re-introduction of old bugs.

However, most regression tests focus exclusively on correctness while ignoring performance. For applications with performance requirements, developers run benchmarks to profile their code in order to determine and resolve bottle-necks. However, unlike regression tests, benchmarks typically are not executed and re-validated for every revision. As a result, performance regressions sometimes are not detected quickly enough.

Compared to correctness issues, performance regressions can be harder to spot. An individual absolute

perfor-mance score rarely is meaningful;

detecting a performance regression requires relating measurements to previous results on the same platform.

Furthermore, small changes in external circumstances (for example, other pro-cesses running at the same time) can cause fluctuations in measurements that then should not be flagged as problematic; this makes it difficult to set hard thresholds for performance scores.

Also, good measurements often take significantly longer than correctness tests. Performance improvements in one area may cause regressions in others, causing system architects some-times to consider multiple metrics at the same time. Finally, performance can be

Performance Regression

Monitoring