1.13. Building a Complex Application with an IDE

Problem

You wish to use your IDE to build an executable that depends on several static and dynamic libraries.

Solution

The basic outline is as follows:

  1. If you are building the dependent libraries from the source, and they don’t come with their own IDE projects or makefiles, create projects for them, as described in Recipe 1.11 and Recipe 1.12.

  2. Create a new project and specify that you wish to build an executable rather than a library.

  3. Choose a build configuration (e.g., debug versus release, single-threaded versus multithreaded).

  4. Specify the name of your executable and the directory in which it should be created.

  5. Add your source files to the project.

  6. Tell the compiler where to find the headers for the dependent libraries.

  7. Tell the linker what libraries to use and where to find them.

  8. If your IDE supports project groups, add all the projects mentioned above to a single project group and specify the dependency relationships between them.

  9. If your IDE supports project groups, build the project group from step 8. Otherwise, build the projects individually, taking care to build each project before the projects that depend on it.

As with Recipe 1.11 and Recipe 1.12, the steps in this outline vary somewhat depending on the IDE. The third step is covered in detail in Recipes Recipe 1.21, Recipe 1.22, and Recipe 1.23. For now, you should use the default settings wherever possible.

For example, here’s how to build an executable from the source code in Example 1-3 using the Visual C++ IDE.

Select New Project from the File menu, select Visual C++[11] in the left pane, select Win32 Console Application and enter hellobeatles as your project’s name. From the Win32 Application Wizard go to Application Settings, select Console Application and Empty Project, and press Finish. You should now have an empty project hellobeatles.vcproj with two build configurations, Debug and Release, the former being the active configuration. You should also have a solution hellobeatles.sln containing the single project hellobeatles.vcproj.

Next, display your project’s property pages by right-clicking on the project’s name in the Solution Explorer and selecting Properties. Go to Configuration Properties Linker General and enter the pathname of your project’s output file in the field labeled Output File. The directory portion of the pathname should point to the directory binaries which you created at the beginning of this chapter; the file name portion should be hellobeatles.exe.

Next, use Add Existing Item... from the Project menu to add the source file helllobeatles.cpp, from Example 1-3 to your project. Your project’s property pages should now contain a node labeled C/C++. Go to Configuration Properties C/C++ Code Generation and specify Multi-threaded Debug DLL as the Runtime Library.

Tip

Instead of using Add Existing Item... to add the source file helllobeatles.cpp to your project, you can use Add New Item... to create a blank source .cpp file and add it to your project. Then you can type or paste the content from Example 1-3 into the newly created files. Similar remarks hold for other IDEs.

Next, go to Configuration Properties C/C++ General and enter the directory that contains the directories johnpaul and georgeringo—the grandparent directory of the source files john.hpp, ringo.hpp, etc.—in the edit control labeled Additional Include Directories. This will allow the include directives in the header hellobeatles.hpp to be resolved correctly.

Next, using Add Existing Project... from the File menu, add the project files libjohnpaul.vcproj and libgeorgeringo.vcproj to the solution hellobeatles. Select Project Dependencies... from the Project menu to display the Project Dependencies dialog. Select hellobeatles from the drop-down control and click the checkboxes next to libjohnpaul and libgeorgringo.

Tip

If you know that you’ll be adding several projects to a single solution, it’s not necessary to create a separate solution for each project. You can create an empty solution by selecting New Blank Solution... from the File menu, and then add new projects to the solution by selecting New Project... from the File menu.

Finally, build the solution by selecting Build Solution from the Build menu. Verify that files named libjohnpaul.lib, libgeorgeringo.dll, libgeorgeringo.lib, and hellobeatles.exe have been created in the directory binaries. Now select Start Without Debugging from the Debug menu to run your application.

Discussion

In the preceding example it was easy to specify that hellobeatles.exe depends on the libraries libjohnpaul.lib and libgeorgeringo.dll because both libraries are built from source code using Visual C++ projects. If you are building an application which depends on libraries distributed as pre-built binaries with header files, you can tell Visual C++ how to find them as follows: First, go to Configuration Properties C/C++ General and enter the directories that contain the library header files in the edit control labeled Additional Include Directories. Then, go to Configuration Properties Linker Input and enter the names of the libraries in the field labeled Additional dependencies. Finally, go to Configuration Properties Linker General and enter the pathnames of the directories containing the binary files in the edit control labeled Additional Library Directories. Let’s look at how to build an executable from the source code in Example 1-3 using CodeWarrior, C++Builder, and Dev-C++.

CodeWarrior

Select New... from the File menu, and select the Project tab of the New dialog. Enter hellobeatles.mcp as your project’s name, select a location where your project’s configuration files should be stored, and double-click Mac OS C++ Stationery. From the New Project dialog, expand the nodes Mac OS X Mach-O and Standard Console, then double-click C++ Console Mach-O. You should now have a project with two targets, Mach-O C++ Console Debug and Mach-O C++ Console Final, the former being the default target.

Since you will need to refer to these targets by name when you add dependencies to this project, you should give the targets descriptive names. For now, rename just the debug target, as follows. Select the Targets tab on your project’s window, and double-click on the name of the debug target to display the Target Settings Window. Then go to Target Target Settings and enter hellobeatles Debug in the field labeled Target Name.

Next, Select the Targets tab on your project’s window, and double-click on the name of the debug target to display the Target Settings Window. Go to Target PPC Mac OS X Target, specify Executable as the Project Type, and enter hellobeatles in the field labeled File Name. Go to Target Target Settings and press Choose... to specify the directory binaries as the location where the output file hellobeatles should be created.

Select the Files tab on your project’s window and remove the existing source files and MSL libraries files by dragging them to Trash. Use Add Files... from the Project menu to add the source file hellobeatles.cpp listed in Example 1-3 to your project. Then use Add Files... to add the files MSL_All_Mach-O_D.dylib and MSL_Shared_AppAndDylib_Runtime_D.lib in the directory Metrowerks CodeWarrior/MacOS X Support/Libraries/Runtime/Runtime_PPC/Runtime_MacOSX/Libs. If you were configuring the release target instead of the debug target, you would add the libraries MSL_All_Mach-O.dylib and MSL_Shared_AppAndDylib_Runtime.lib instead. From the Target Settings Window, go to Target Access Paths and click on the panel labeled User Paths. Use the control labeled Add... to add the directory that contains the directories johnpaul and georgeringo — the grandparent directory of the source files john.hpp, ringo.hpp, etc. This will allow the include directives in the header hellobeatles.hpp to be resolved correctly.

Using Add Files... from the Project menu, add the project files libjohnpaul.mcp and libgeorgeringo.mcp to the project hellobeatles.mcp. Go to the Targets tab and expand the nodes labeled hellobeatles Debug, libjohnpaul.mcp and libgeorgeringo.mcp. Click on the target icons next to the first child nodes of libjohnpaul.mcp and libgeorgeringo.mcp, labeled libjohgnpaul Debug and libgeorgeringo Debug. Bold arrows should appear on these two icons. Enlarge your project’s window, if necessary, to expose a small link icon on the window’s far right side. Click twice in this column, opposite the target icons with arrows. Two black dots should appear in this column.

Build the solution by selecting Make from the Project menu. The linker may display a number of warnings about multiply-defined symbols, but these can safely be ignored. You can suppress them by going to Linker Mac OS X Linker and checking Suppress Warning Messages.

Verify that files named libjohnpaul.a, libgeorgeringo.dylib, and hellobeatles have been created in the directory binaries. You can now run hellobeatles by placing a copy of the libraries MSL_All_Mach-O_D.dylib in the directory binaries, changing to the directory binaries, and entering ./hellobeatles from the command line.

C++Builder

Select New from the File menu and then select Console Wizard. From the Console Wizard dialog, select C++, Multi Threaded, and Console Application. You should now have a project containing a single source file Unit1.cpp. Remove Unit1.cpp from the project by right-clicking and selecting Remove From Project. Select Save Project As... on the File menu, select a directory for storing your project’s configuration files and enter your project’s name as hello_beatles. I’ve included an underscore in the project name because C++ Builder does not allow a project to have the same name as a source file.

Next, select Options... from the Project menu to display the Project Options dialog. Then go Directories and Conditionals and use the control next to Final output to specify that your project’s output file, hello_beatles.exe, should be created. By default this file will be created in the same directory as hello_beatles.bpr; tell C++Builder to create it in the directory binaries. If you wish, you can also use the control next to Intermediate output to specify where object files should be created. By default they will be created in the same directory as the source files.

Next, use Add to Project... from the Project menu to add the source file helllobeatles.cpp from Example 1-3 to your project.

Next, from Project Options go to Directories and Conditionals and use the control next to Include path to select directory that contains the directories johnpaul and georgeringo—the grandparent directory of the source files john.hpp, ringo.hpp, etc. This will allow the include directives in the header hellobeatles.hpp to be resolved correctly.

Next, right-click on the label ProjectGroup1, select Save Project Group As, select the directory containing the file hello_beatles.bpr, and enter your project group’s name as hello_beatles.bpg.

Next, add the project files libjohnpaul.bpr and libgeorgeringo.bpr to your project group by right-clicking on the label hello_beatles and selecting Add Existing Project.... Build these two projects, as described in Recipe 1.11 and Recipe 1.12, if you have not already done so, then add the output files libjohnpaul.lib and libgeorgeringo.lib to the project hello_beatles using Add to Project... from the Project menu. Use the up-arrow key while holding down the Ctrl key, move the projects libjohnpaul and libgeorgeringo above the project hello_beatles in the Project Manager to ensure that they will be built first.

Finally, build the solution by selecting Make All Projects from the Build menu. Verify that a file named hellobeatles.exe has been created in the directory binaries. Select Run from the Run menu to run the application.

Dev-C++

Select New Project... from the File menu. From the New project dialog, select Console Application and C++ Project, and enter hellobeatles as your project’s name. After pressing OK, specify the location where your project’s configuration file should be located.

Next, from Project Options go to Build Options and verify that your project’s output file is named hellobeatles.exe. Enter the pathname of the directory binaries under Executable output directory. If you wish, you can enter the directory where object files will be created under Object file output director.

Next, remove any existing source files from your project by right-clicking and selecting Remove file. Use Save Project as... from the File menu to save your project’s configuration file hellobeatles.dev. Finally, use Add to project from the Project menu to add the source file helllobeatles.cpp from Example 1-3 to your project.

Next, select Project Options from the Project menu to display the Project Options dialog. Then go to Directories Include Directories, select the directory that contains the directories johnpaul and georgeringo—the grandparent directory of the source files john.hpp, ringo.hpp, etc.—and press Add. This will allow the include directives in the header hellobeatles.hpp to be resolved correctly.

Finally, from Project Options go to Directories Libraries Directories and add the directories that will contain the output files libjohnpaul.a and libgeorgeringo.a of the projects libjohnpaul and libgeorgeringo. Then go to Parameters Linker and enter the options -ljohnpaul and -lgeorgeringo.

Now build the three projects individually using Compile from the Execute menu, making sure to build hellobeatles last. Run hellobeatles.exe by selecting Run from the Execute menu.



[11] In versions of Visual C++ prior to Visual C++ 2005, this option was labeled Visual C++ Projects.

Get C++ Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.