Project Builder: FAQ

ADC Membership Technical Business Join ADC
Search Advanced Search
Project Builder - FAQ

    as of the December 2001 Mac OS X Developer Tools (Project Builder 1.1.1)

General Questions | Files | Building Projects | Debugging

General Questions

Is there any documentation or tutorials available for Project Builder?

    Locally, documentation and tutorials are located in /Developer/Documentation/DeveloperTools/ProjectBuilder/.

    You can also find help through the Help menu in Project Builder, which lets you access on-line help and release notes.

Additionally, you can take a look at further online development tools documentation (including some tutorials) here.

How can I alert Apple to a bug in Project Builder?

    If you find a bug in Project Builder or have an idea for a new feature, you can file this with Apple by logging in and filling out the form here. When filing a bug relating to the underlying build tools used by Project Builder (the gcc compiler, etc.) you will greatly accelerate the fixing of the bug if you turn up the build logs level to "Detailed," do a complete build, and copy the build output window's contents into your bug report.

What is the difference between Project Builder and ProjectBuilderWO?

    ProjectBuilderWO is the Integrated Development Environment (IDE) that was formerly known as ProjectBuilder in NeXT's OpenStep 4.2. To address the limitations of this older version of Project Builder, Apple has rewritten a new Project Builder from scratch, and is now focusing all of its efforts on it. Project Builder version 1.0.1 (and later) supports development of WebObject 5.0 (and later). It is recommended that you do not use ProjectBuilderWO for any new projects.

Files

Working with groups and folder references in Project Builder

    You may have wondered what the difference was between yellow folders and blue folders in Project Builder's file list, or wondered how to perform operations on whole folders instead of file-by-file. A Q&A has been posted that explains it here.

I click on a file in the Files list, but it doesn't appear. What do I do?

    First check the file reference in the Files list. If it is red then the file cannot be found. Select the source file and choose Show Info from the Project menu. If the absolute path that's shown appears in red, it means that the importation process constructed an incorrect path for the file. That would explain why you can't open the file; it simply can't be found. Both the build system and the editor try to access the file using the path shown in the Info panel.
     
    If the path is shown in black, it means that the path is valid, and single-clicking on the file should show its contents in the textview on the right side of the project window. Double-clicking on it should open the contents in a new editing window.
     
    If the path is wrong, you can use the Set Path.. button in the Info panel to correct it.

What's in that last panel in the Project Builder Preferences dialog?

    These are folders that the Open Quickly... command (in the Files menu) searches for header files. By default it contains most of the standard frameworks so that Open Quickly of "NSButton.h" or "MacTypes.h" will work even with no open project that includes those headers. Open Quickly also searches in the active project.

    To edit which folders are searched for header files when you're building your target executable:

    • click the Targets tab
    • select the target in the Targets list
    • click the Build Settings tab
    • scroll down to the Search Paths section
    • select the Headers category and hit return
    • enter the path to the headers folder in the form "/Some/Path/To/YourHeadersFolder"

In the Files & Build Phases panel off of the Targets tab, what's the difference between Bundle Resources and ResourceManager Resources?

    Files in Bundle Resources are copied into the product’s resource folder. These are usually nib files, sounds, and pictures, and are typically used by Cocoa applications (though they can be used by Carbon applications as well).

    Files in ResourceManager Resources are accessed through Carbon Resource Manager routines. In Mac OS 8 and 9, these resources are typically stored in the file’s resource fork. These files are usually Rez (.r) files and resource (.rsrc) files.

Why can't ProjectBuilder find <insert header name here>?

    If your header is part of a framework, you need to do the following:

    1. Add the framework to the project (via the Add Frameworks menu item in the Project menu)
    2. Add the framework to the proper target(s) (simply drag the framework reference to the desired target(s))
    3. Use the proper framework header notation when referencing it (i.e. <AppKit/AppKit.h>),

    If your header is internal to the project or external but not part of a framework make sure that you have added the proper path to the search paths for headers.

    In the case of external non-framework headers, it is also a good idea to add them to the project via the Add Files... dialog.

How can I set the default font to something other than what it is right now?

    To set the source code font and syntax coloring options go to the 'Syntax ' panel in Preferences.

    To set the debugger command line font go to the 'Debugging' panel in Preferences.

    To change the font used for lists, go to the 'General' panel in Preferences.

Building Projects

Library naming conventions for proper building and linking with the Mac OS X Developer Tools

    If you are having trouble linking against a given library and/or are getting undefined symbols errors (for symbols known to be in your library), you may need to check the name of your library to fit proper naming conventions. A new Q&A has been posted that explains all about it.

Information on prebinding

    Documentation has been released on the process known as prebinding - how it works, what it does, and how you can take advantage of it for enhanced application launching speed. Read all about it here.

Using Pascal strings in Project Builder (with gcc)

    Usually Pascal strings work just fine in gcc, but sometimes you have to more explicitly give it the right settings to recognize them. Read all about it here.

Where did my target get built? In the Build Settings panel off of the Targets tab, I changed the Installation Location but my target isn't there.

    The Installation Location field does not control where Project Builder builds your target. Instead, it controls where the pbxbuild command-line tool installs your target. Installing a target lets you test how it will work on the end user’s computer. The Installation Location is where the target's product will appear on the user’s computer.

    To choose where to build your project, choose ProjectBuilder > Preferences and click Building. To choose where a target's product is placed, edit Separate Location for Products controls. To choose where intermediate files (such as object files) are placed, edit Separate Location for Build Files. By default, a project's build files and products go into the Build folder within the project's folder.

    It is also important to note that you can also choose the Products folder or the Build Files folder on a per-project basis by selecting the project in the files list and bringing up the info panel (Show Info from the Project menu). See the How Project Builder Builds -> Where a Project is Built section of Project Builder Help (available from the Help menu in Project Builder) for more details.

How do I build my target from the command line?

    Use pbxbuild, as follows:

    1. cd to your project’s directory.
      This is the directory that contains your project’s .pbproj file. For example, if your project is in ~me/Projects/MyProj, enter cd ~me/Projects/MyProj.

    2. Enter pbxbuild.
      This builds the target at the top of your Targets list. To build a specific target, use
      pbxbuild -target targetname. To do an install build (with optimizations on, etc), use pbxbuild install -target targetname.

Where are the makefiles for my project?

Project Builder does not save copies of a project's makefiles on disk. Instead, it creates them each time you build a target, using Project Builder's own internal build system.
If you need to build a target from the command line, use pbxbuild, described above.
If you want to insert other shell commands in the build process, use a script build phase instead. To create a script build phase, click the Targets tab, select the target, click the Files & Build Phases tab, click on the build phase you want the new script build phase to follow, and choose Project > New Build Phase > New Shell Script Build Phase

I created a new Shell Script Build Phase - but building fails because the script can't be found. Why?

    Shell Script Build Phases are invoked using the environment of the currently logged in user, and since "." is not in your $PATH by default, the current working directory (your project's directory) isn't getting searched for the script. Workarounds include making the path to your shell script an absolute one, or specifying "./yourscriptname" instead.

Where do a framework's resources end up after you build it?

    Non-localized resources go in the Resources directory of the bundle and localized resources go in the <region>.lproj subdirectories of the Resources directory.

You can choose between Minimal, Standard, and Detailed between build logs. How are these different?

    You can select the detail level of build logging by going to the Building pane in Preferences. Minimal is pretty much nothing. Standard is what you typically see and Detailed is full verbose output that includes all the actual command lines being invoked by Project Builder. When filing a bug relating to the underlying build tools used by Project Builder (the gcc compiler, etc.) you will greatly accelerate the fixing of the bug if you turn up the build logs level to "Detailed," do a complete build, and copy the build output window's contents into your bug report.

How can I specify which symbols should be exported from a framework or library?

    Adding EXPORTED_SYMBOLS_FILE to the expert build settings with the value of a path to a file in the format nmedit expects causes all object files for that framework or library to be made into a master object file and edited before linking is done.

Debugging

Project Builder (PB) sometimes crashes when I am debugging. What can I do about it?

    Project Builder can crash when debugging because it accesses some memory that has been deallocated. This happens when the debugger shows current line in a source file and then the user switches to a different source file in that editor. If you just step through code in the debugger and do not switch to other files, then you should not run into this problem.

    If you enable CrashReporter (see "How do I submit a (really useful) Project Builder debuggiing bug"), you can get a partial stack backtrace when Project Builder crashes. If the backtrace includes a frame with "0x76a5aefc in -[PBXDebugSessionModule setInstructionPointerFileName:lineNumber:]", then you have encountered the known crash. If the backtrace is different, please file a bug and include the backtrace.

The GDB Console in PB is not the same as using GDB from Terminal. What works, what doesn't?

    You don't not get the full power of the GDB command interface from within Project Builder because the Project Builder Console is not a complete terminal emulator. However, the Console is still very functional: the a command line can be editted by moving the cursor with the left or right arrow keys or with the mouse. The up and down arrow key forward and backward through a history list of commands you have typed to GDB. 

    One feature that does not work is completion: when using GDB from Terminal, the tab key invokes the GDB completion facility to complete the current word. The development team at Apple knows this is a missing feature in the PB Console.

Why isn't my program's output appearing in the Debugger Console?

    On Mac OS X,  the stdio library buffers output dependent on what stdout is "connected" to. When stdout is connected to a terminal device (like a pseudo-terminal device which is used by Terminal), then it is line buffered; when stdout is connect to a file or a pipe(2) , it is block buffered. See the setbuf(3) man page for details.

    In Project Builder, what the Executable's stdin/out is connected to depends on if it is Run or Debugged. When an Executable is Run, its stdin/out is connected to a pipe and when it is Debugged, it is connected to a pty (pseudo-terminal). This means the buffering behavior for an Executable's stdout varies when it is launch from within Project Builder.

    Here's some sample code:

    void log_to_stdout(char *msg)
    {
        printf("Log message: ");    /* statement 1 */
        printf("%s\n", msg);        /* statement 2 */
    }

    When debugging this code, after stepping over statement 1, the text from printf() will not be displayed; it is still in the stdout buffer because the text string did not contain a newline. After stepping over statement 2, you will see both strings of text output to the Console.  When Running, the output may not appear because stdout is block buffered. To flush the buffer, add a call to fflush() after statement 2.

    Another example:

    {
        int     i;
       
        printf("Enter a number: ");                 /* statement 1 */
        scanf("%d", &i);                            /* statement 2 */
        printf("%d * %d = %d\n", i, i, (i * i));    /* statement 3 */
    }

    When debugging this code, the text for the first printf()  will not be displayed after stepping over statement 1 because it does not contain a newline. However the call to scanf() will cause stdout to be flushed. However, when run, the call to scanf() will not automatically flush stdout because it is connected to a pipe. Add an explicit call to fflush(stdout) after statement 1 and statement 3.

    For C++ code, there is currently a bug in the implementation of cout which causes data to be buffered when it should not be. A work-around is to call cout.sync_with_stdio(false)  before sending any data to cout.

How do GDB commands and the PB User Interface interact?

    The Project Builder User Interface state and the GDB internal state are now synchronized. GDB command issued through the Console execute in the context of the UI state; for example, the "info locals" command lists the local variables in the selected frame of the selected thread in the UI. GDB commands which change the context state are reflected in the UI; for example, the GDB command "up" will change the selected frame in the UI by moving up one frame in the stack. 

    GDB commands which control the execution state of the target (i.e. "next", "step", "continue", etc) can now be issued from the PB Console and will update the UI correctly.

How do I use breakpoint commands?

    GDB provides the ability to define a list GDB commands that are executed when a breakpoint is hit. At this time, there is no facility in the PB UI to specifiy commands; you have to use the Console to enter the commands. You will have to use the GDB command "info breakpoints" (or "info break") to see the internal list of breakpoints managed by GDB. Find the number of the breakpoint you want to add the commands to and use that in the "commands <n>" command.  Enter the commands you want to be executed when the breakpoint is hit. End the list with "end".

    Note: a very common use of breakpoint commands is to print the value of a variable and then "continue" from the breakpoint. This works as of Project Builder 1.1.1 but there is a problem. Due to a bug in the interaction between PB and GDB,  the use of "continue" in a breakpoint command list causes PB not to be able to interrupt the target program. That is, the clicking on the PB UI button which "pauses" (or interrupts) the target will have no effect.  The work-around is to have another breakpoint in your program that you can cause your program to hit; for example, put a breakpoint in the code that handles the "About..." menu item.

How do I debug plugins (or libraries) to other programs?

    If you are developing a shared library or plugin which is used by an external program (i.e. a program for which you do not have the source code), you may want to debug your code in the context of running it in this other program (i.e. the "loader-program"). The Project Builder Target which builds your code does not produce an Executable (i.e. a program to be run); you will have to add the loader-program as an Executable to the Target. Go to the Executables tab in the Target Editor and press Add Executable and navigate to the application which loads your code. Then when you tell PB to Run or Debug, it will launch the loader-program.

    The next step is getting the loader-program to load the correct version of your code. You want to build a Development version of your code that is build with debugging symbols. If you are lucky, the loader-program will have means (via an environment variable or an argument) for specifying an alternate location to look for dynamically loaded code. If not, you will have to setup your system so that the loader program loads the correct version of your plugin. The simplest way is to create a symbolic link (via "ln -s"; see the ln(1) man page) in the plugin folder for the loader-program which points to where your (built-by-PB-for-debugging) plugin reside. 

How do I examine CoreFoundation orObjective-C objects?

    Objects from CoreFoundation, Foundation, and many AppKit classes are opaque: you can't look at their structure fields or instance variables.  To see the state of these objects, you need to inovke a function on the object, which displays the representation of its state as a string. You can use either the "call" or the "print" GDB command to invoke a function in the target. Both evaluate an expression;  if that expression contains a function call, then that function is invoked.

    For CoreFoundation objects, invoke the function CFShow() with the name of the variable or expression you want to inspect. For example,  type "call (void) CFShow(myCFObj)" in the Console to see the string value of the variable "myCFObj". (The  symbolic information for the return type of this function is not supplied by the CoreFoundation library, so you have to cast the function invocation expression to the correct type).

    For Objective-C objects, you can use the "print-object" (or "po") command which invokes the description method on an object. Most Foundation and many AppKit object objects implement this method. You can implement for your objects too. For example to see the value of an NSString object, type "po myString" or the value of an object's name, type "po [myObj name]".

    The CoreFoundation function CFShow() can be used with Objective-C objects. Therefore "call (void) CFShow(myNSString)" is equivalent to "po myNSString" . However, there is a difference between these two approaches: the return value of CFShow() is void; a side-effect of calling this function is the value of the object is printed to stderr. The GDB comamnds "print-object"/"po" actually call a utility function in Foundation which in turn invokes the description method. The utility function has a return value of  "(char *)" and returns a buffer with a cString version of the description string; GDB prints the value of this buffer.

    The Project Builder Debugger UI has a feature to call CFShow() for you.  In the Variables View, select the row of the variable you want to examine and then bring up the Context Menu for the view (i.e. Control-Click) and select the item titled "Print Description to Console".

How do I submit a (really useful) Project Builder debugging bug?

    When submitting a bug, please provide as many details as possible:

  • version of Mac OS X
  • version of Project Builder
  • language (C/C++/ObjC) of program being debugged (or of the frame in which the problem arises)
  • type of program being debugged (Carbon, Cocoa, application, tool, etc)
  • description of what happens and is it reproducible
  • log files from Sampler, sample or CrashReporter

    In tracking down a probjem with the Project Builder Debugger, it is sometimes useful to have the communications session between Project Builder and GDB. You can enable Project Builder to record this information with these steps:

    1. Quit Project Builder and in a Terminal window, type:

      defaults write com.apple.ProjectBuilder PBXDebuggerEnableLogging YES

    2. Restart Project Builder and start debugging; in the Debug menu, you should see a new menu item called "Dump debugging log".
    3. When you encounter a problem with debugging, select the Dump debugging log menu item. This will place a file in /tmp with the name "PBGDB-<AppName>-<pid>". This is a text file which contains the PB/GDB communication. Copy the contents of this file into your bug report.
    4. You might then want to turn off the logging by setting the PBXDebuggerEnableLogging default to NO.



Gray line

Contact ADC |  ADC Site Map |  ADC Advanced Search
For information about Apple Products, please visit Apple.com.
Contact Apple | Privacy Notice
Copyright © 2001 Apple Computer, Inc. All rights reserved.
1-800-MY-APPLE