Using Makefile on a Mac

Do you have a typical platform dependent issue you're battling with ? Ask it here. Make sure you mention your platform, compiler, and wxWidgets version.
Post Reply
wilx
In need of some credit
In need of some credit
Posts: 5
Joined: Tue Aug 16, 2005 4:10 pm
Location: Northern Utah, USA
Contact:

Using Makefile on a Mac

Post by wilx »

Greetings members of the Mac OS X wxWidgets community:

I am attempting to answer a question with wxMac. I've not been able to solve this by searching the wxWidgets nor the Apple Developer Connection websites. I've also contacted the authors of 'Cross-Platform GUI Programming with wxWidgets.'

My question is this: How does one create an executable file for Mac OS X (.app) using make instead of Xcode?

I'm an older Solaris developer who likes his command line utilities. I know this can be done. It is done with the samples distributed with wxMac, but I've not been able to decipher how it is done. Obviously, the samples are built using make within the wxMac build directory (see "Building the samples" in http://wiki.wxwidgets.org/wiki.pl?Installing_WxMac ). However, moving a sample out of the wxMac build directory and into a user's directory is not straightforward (see "Setting up your work area: creating an app outside of the wxWidgets folders -- the better alternative" in http://wiki.wxwidgets.org/wiki.pl?Installing_WxMac ).

In attempting to 'make' the minimal sample in my home directory, I followed the instructions in "Cross-Platform GUI Programming with wxWidgets," specifically pages 564-565, 'Any Platform--Makefiles'. I had to make two modifications to the makefile. One, I had to include the full path to wx-config (as there was apparently an older version of wxWidgets installed with Mac OS 10.4, which I did not know about) and I had to include a linker flag for the c++ standard library (-lstdc++).

Now this works and creates the executable file 'minimal'. However it does not create the executable file 'minimal.app'. While 'mimimal' will load and execute, it will not function. The window cannot be selected, so you cannot drag it across the screen. Most (but not all) widgets to not respond.

There must be some other compiler step to take 'mimimal' to 'minimal.app' as it does when the samples are built using make. Or, 'minimal' and 'minimal.app' have separate build rules.

If anyone could be kind enough to point me in the right direction of understanding how Mac OS X applications are built in wxWidgets, I would appreciate it. I will, once I've figured out, create a short write-up for the wxWiki.

Thank you,
Mark
KevinHock
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 236
Joined: Sat Sep 04, 2004 1:49 pm
Location: Ohio, USA
Contact:

Post by KevinHock »

This was posted to the wx-users list in the recent past, and claimed to be a complete sample makefile for wxMac that also created an app bundle. I cannot personally vouch for its accuracy, however.

You certainly did email the authors (me) but I don't recall asking this question. I apologize if I missed answering this additional question if it was in fact posed in emails that I received.

Code: Select all

################################################################################
# Makefile created by CHB from a
# Makefile generated by DialogBlocks
#
# Adapted to the minimal sample
#
################################################################################

PROGRAM=Minimal

OBJECTS=minimal.o \


ICONFILE=minimal.icns
BUNDLESIGNATURE=????
OUTPUTPATH=$(PROGRAM)Mac

BUNDLE=$(OUTPUTPATH)/$(PROGRAM).app

WXCONFIG=wx-config

CXX=g++

MACPACKAGEINFO=$(BUNDLE)/Contents/PkgInfo
LIBS=`$(WXCONFIG) --inplace  --libs`

LINKERFLAGS=
WARNINGFLAGS=
OPTFLAGS=
DEBUGFLAGS=

CPPINC=`$(WXCONFIG) --inplace --cxxflags`
LDFLAGS=$(LIBS) $(LINKERFLAGS)
CPPFLAGS=$(CPPINC) $(GCCFLAGS) $(DEBUGFLAGS) $(OPTFLAGS) $(WARNINGFLAGS)


all: $(BUNDLE)/Contents/MacOS/$(PROGRAM) $(MACPACKAGEINFO)

$(OUTPUTPATH):
    mkdir -p $(OUTPUTPATH)

clean:
    rm -f $(OBJECTS)
    rm -fr $(BUNDLE)

help:
    @echo "Usage: make -f Makefile [all|clean|help]"

# This builds the executable right inside the bundle.
$(BUNDLE)/Contents/MacOS/$(PROGRAM): $(OBJECTS) $(BUNDLE)
    $(CXX) -o $(BUNDLE)/Contents/MacOS/$(PROGRAM) $(OBJECTS) $(LDFLAGS)

# And here we build the Bundle
$(BUNDLE): Info.plist $(ICONFILE)
    @echo " Building: $(BUNDLE)"
    mkdir -p $(BUNDLE)/Contents
    mkdir -p $(BUNDLE)/Contents/MacOS
    mkdir -p $(BUNDLE)/Contents/Resources
    cp Info.plist $(BUNDLE)/Contents/Info.plist
    echo -n "APPL$(BUNDLESIGNATURE)" > $(MACPACKAGEINFO)
#    cp -f $(ICONFILE) $(BUNDLE)/Contents/Resources/$(ICONFILE)
    cp -f $(ICONFILE) $(BUNDLE)/Contents/Resources/wxmac.icns


$(OBJECTS): %.o: %.cpp %.h # each file depends on it's own code and headers, at least!
     $(CXX) -c -o $@ $(CPPFLAGS) $<

.PHONY:    all clean
ssigala
Earned some good credits
Earned some good credits
Posts: 109
Joined: Fri Sep 03, 2004 9:30 am
Location: Brescia, Italy

Post by ssigala »

Very interesting, thanks Kevin!
Sandro Sigala - Kynosoft, Brescia
wilx
In need of some credit
In need of some credit
Posts: 5
Joined: Tue Aug 16, 2005 4:10 pm
Location: Northern Utah, USA
Contact:

Post by wilx »

Kevin:

The stuff we emailed back and forth earlier was very helpful and I was able to solve that problem. I uninstalled all copies of wxWidgets from the machine. Then I did a configure and make, but not a make install. Then I ran everything out of the build directory and specified the full path of wx-config in the makefile. I got further, but ran into another problem. I dug into it and found out that I needed to include the library directive for the c++ standard library (-lstdc++). Then it linked without problems. Next, I ran into the current problem, where the program would execute, but not run properly. I decided to check the community before bothering you with this new problem.

This makefile you sent was extremely helpful. It didn't work out of the box, but required only a little tweaking. I dug into the Mac OS X package structure a little deeper. Some online references and pages 536-537 of your book were really helpful. I expanded upon the makefile and added a whole lot of comments into it. I've attached what I came up with. Let me know what you think about it and if you think I should write something for the wxWiki.

Mark

Code: Select all

##############################################################
#
#  Makefile Template for wxMac Applications
#  Mark Wilkinson
#  August 2005
#
#  This makefile is designed for experienced UNIX 
#  developers who wish to learn how to build Mac OS X 
#  packages (.app) using Makefiles rather than Apple's 
#  Xcode IDE.
#
#  Developed with the assistance of Kevin Hock, CHB, 
#    and DialogBlocks examples.
#  Distribution of this file is subject to the terms of 
#    the wxWindows License, see www.wxwidgets.org
#
##############################################################


##############################################################
#
#  A Brief Tutorial on Packages
#
#  Rather than use resource forks on application
#    files, as Apple did in their Classic operating
#    system, Mac OS X uses application packages.
#  Application packages have a .app extension and
#    are actually directories which contain the
#    true executable as well as several resource 
#    files.  The structure of an application
#    package is:
#
#    (program).app
#     |
#     +-- Contents
#          |
#          +--  Info.plist
#          |
#          +--  MacOS
#          |     |
#          |     +--  (program)
#          |
#          +--  PkgInfo
#          |
#          +--  Resources
#                |
#                +-- (icon file)
#
#    In this diagram "(program)" is the name of 
#    the executable program.  "Contents," "MacOS," 
#    and "Resouces," are directories.  "Info.plist"
#    is an XML DTD file.  And "PkgInfo" is a text
#    file containing data.
#  This makefile generates the package directory
#    structure, and it compiles and places the 
#    executabel in the MacOS directory.  This 
#    makefile also creates the "PkgInfo" and 
#    "Info.plist" files.  The PkgInfo file is very
#    simple.  Info.plist is an XML DTD and contains
#    several variables, which can be examined in
#    this makefile.
#  You need to supply the source code and the icon
#    file.  The icon file is copied into the 
#    Resources directory of the package.
#
##############################################################

##############################################################
#
#  These variables are used to compile the program.  You 
#    will need to provide this information.  You may need
#    to specify the full path to the wx-config executable.
#    The output path may be left blank.  The program name
#    and object names are essential.  You may use the icon
#    file included with the wxMac distribution 
#    (wxMac-2.6.1/src/mac/wxmac.icns) or create your own
#    icon using the Apple Developer Tools 
#    (/Developer/Applications/Utilities/Icon Composer).
#
#
##############################################################

WXCONFIG=/usr/local/wxMac-2.6.1/build-osx/wx-config

OUTPUTPATH=

PROGRAM=Minimal
PROGVER=1.0

OBJECTS=minimal.o

ICONFILE=wxmac.icns

##############################################################
#
#  These variables are used in the Info.plist and PkgInfo
#    files.  Aside from the company name (which should have
#    no spaces, like a domain name), you should not have
#    to modify these variables.
#
##############################################################

COMPANY=towerravens

BUNDLEPACKAGE=APPL

BUNDLESIGNATURE=????

##############################################################
#
#  It should not be necessary to modify the Makefile
#    below this line; although, you may have to make
#    changes depending on your system configuration.
#
##############################################################

CXX=g++

BUNDLE=$(OUTPUTPATH)/$(PROGRAM).app
MACICON=$(BUNDLE)/Contents/$(ICONFILE)
MACPKGINFO=$(BUNDLE)/Contents/PkgInfo
MACINFOPLIST=$(BUNDLE)/Contents/Info.plist 

LIBS=`$(WXCONFIG) --inplace  --libs`
LINKERFLAGS= -lstdc++
WARNINGFLAGS=
OPTFLAGS=
DEBUGFLAGS=

CPPINC=`$(WXCONFIG) --inplace --cxxflags`
LDFLAGS=$(LIBS) $(LINKERFLAGS)
CPPFLAGS=$(CPPINC) $(GCCFLAGS) $(DEBUGFLAGS) $(OPTFLAGS) $(WARNINGFLAGS)

all: $(BUNDLE) $(BUNDLE)/Contents/MacOS/$(PROGRAM) $(MACICON) $(MACPKGINFO) $(MACINFOPLIST)

clean:
	rm -f $(OBJECTS)
	rm -fr $(BUNDLE)

help:
	@echo "Usage: make -f Makefile [all|clean|help]"

#  This builds the bundle's directory structure.
$(BUNDLE):
	@echo "==== Building bundle directory structure ===="
	mkdir -p $(OUTPUTPATH)
	mkdir -p $(BUNDLE)/Contents
	mkdir -p $(BUNDLE)/Contents/MacOS
	mkdir -p $(BUNDLE)/Contents/Resources

#  This builds the executable right inside the bundle.
$(BUNDLE)/Contents/MacOS/$(PROGRAM): $(OBJECTS)
	@echo "==== Building executable ===="
	$(CXX) -o $(BUNDLE)/Contents/MacOS/$(PROGRAM) $(OBJECTS) $(LDFLAGS)

#  This copies the icon file into the bundle.
$(MACICON): $(ICONFILE)
	@echo "==== Copying icon file into bundle ===="
	cp -f $(ICONFILE) $(BUNDLE)/Contents/Resources/$(ICONFILE)

#  This creates the Contents/PkgInfo file.
$(MACPKGINFO):
	@echo "==== Creating PkgInfo ===="
	touch $(MACPKGINFO)
	@echo -n "$(BUNDLEPACKAGE)$(BUNDLESIGNATURE)" > $(MACPKGINFO)

#  This creates the Contents/Info.plist file.
$(MACINFOPLIST):
	@echo "==== Creating Info.plist ===="
	touch $(MACINFOPLIST)
	@echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" >> $(MACINFOPLIST)
	@echo -n "<!DOCTYPE plist PUBLIC " >> $(MACINFOPLIST)
	@echo -n "\"-//Apple Computer//DTD PLIST 1.0//EN\" " >> $(MACINFOPLIST)
	@echo "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" >> $(MACINFOPLIST)
	@echo "<plist version=\"1.0\">" >> $(MACINFOPLIST)
	@echo "<dict>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleDevelopmentRegion</key>" >> $(MACINFOPLIST)
	@echo "	<string>English</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleExecutable</key>" >> $(MACINFOPLIST)
	@echo "	<string>$(PROGRAM)</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleIconFile</key>" >> $(MACINFOPLIST)
	@echo "	<string>$(ICONFILE)</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleName</key>" >> $(MACINFOPLIST)
	@echo "	<string>$(PROGRAM)</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleIdentifier</key>" >> $(MACINFOPLIST)
	@echo "	<string>com.$(COMPANY).$(PROGRAM)</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleInfoDictionaryVersion</key>" >> $(MACINFOPLIST)
	@echo "	<string>6.0</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundlePackageType</key>" >> $(MACINFOPLIST)
	@echo "	<string>$(BUNDLEPACKAGE)</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleSignature</key>" >> $(MACINFOPLIST)
	@echo "	<string>$(BUNDLESIGNATURE)</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleVersion</key>" >> $(MACINFOPLIST)
	@echo "	<string>$(PROGVER)</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleShortVersionString</key>" >> $(MACINFOPLIST)
	@echo "	<string>$(PROGVER)</string>" >> $(MACINFOPLIST)
	@echo "	<key>CFBundleGetInfoString</key>" >> $(MACINFOPLIST)
	@echo "	<string>$(PROGRAM), Version $(PROGVER), $(COMPANY)</string>" >> $(MACINFOPLIST)
	@echo "</dict>" >> $(MACINFOPLIST)
	@echo "</plist>" >> $(MACINFOPLIST)

$(OBJECTS): %.o: %.cpp
	$(CXX) -c -o $@ $(CPPFLAGS) $<

.PHONY:    all clean

ssigala
Earned some good credits
Earned some good credits
Posts: 109
Joined: Fri Sep 03, 2004 9:30 am
Location: Brescia, Italy

Post by ssigala »

wilx: excellent work!!! Thanks :D
Sandro Sigala - Kynosoft, Brescia
KevinHock
Filthy Rich wx Solver
Filthy Rich wx Solver
Posts: 236
Joined: Sat Sep 04, 2004 1:49 pm
Location: Ohio, USA
Contact:

Post by KevinHock »

I agree, this is really great. In hindsight, something like this should have gone into the book. Anyway, including this material on the wiki would be very useful for others, I think.
Post Reply