GCC PCH support: closes #155, and decreases build times by a BUNCH!

Changed the default to generating PCH's for all platforms and added a
premake
command line option --without-pch, in case it breaks somewhere (but
AFAIK, Mac's
use recent enough versions of GCC, so it should be fine).

# Added support for precompiled headers into the Linux build system.
Build times are now significantly reduced (up to 50%!)

This was SVN commit r4642.
This commit is contained in:
Simon Brenner 2006-11-12 19:46:47 +00:00
parent db045c330b
commit 35ac7776ee
5 changed files with 114 additions and 70 deletions

View File

@ -1,6 +1,7 @@
addoption("atlas", "Include Atlas scenario editor packages")
addoption("outpath", "Location for generated project files")
addoption("without-tests", "Disable generation of test projects")
addoption("without-pch", "Disable generation and usage of precompiled headers")
dofile("functions.lua")
dofile("extern_libs.lua")
@ -162,6 +163,22 @@ function package_add_contents(source_root, rel_source_dirs, rel_include_dirs, ex
end
-- Detect and set up PCH for the current package
function package_setup_pch(pch_dir, header, source)
if OS == "windows" or not options["without-pch"] then
package.pchheader = header -- "precompiled.h"
package.pchsource = source -- "precompiled.cpp"
if pch_dir then
tinsert(package.files, {
pch_dir..header,
pch_dir..source
})
end
for i,v in project.configs do
tinsert(package.config[v].defines, { "USING_PCH" })
end
end
end
--------------------------------------------------------------------------------
-- engine static libraries
@ -188,27 +205,21 @@ local function setup_static_lib_package (package_name, rel_source_dirs, extern_l
tinsert(static_lib_names, package_name)
if OS == "windows" then
-- Precompiled Headers
-- rationale: we need one PCH per static lib, since one global header would
-- increase dependencies. To that end, we can either include them as
-- "packagedir/precompiled.h", or add "source/PCH/packagedir" to the
-- include path and put the PCH there. The latter is better because
-- many packages contain several dirs and it's unclear where there the
-- PCH should be stored. This way is also a bit easier to use in that
-- source files always include "precompiled.h".
-- Notes:
-- * Visual Assist manages to use the project include path and can
-- correctly open these files from the IDE.
-- * precompiled.cpp (needed to "Create" the PCH) also goes in
-- the abovementioned dir.
pch_dir = source_root.."pch/"..package_name.."/"
package.pchheader = "precompiled.h"
package.pchsource = "precompiled.cpp"
tinsert(package.files, { pch_dir.."precompiled.cpp", pch_dir.."precompiled.h" })
end
-- Precompiled Headers
-- rationale: we need one PCH per static lib, since one global header would
-- increase dependencies. To that end, we can either include them as
-- "packagedir/precompiled.h", or add "source/PCH/packagedir" to the
-- include path and put the PCH there. The latter is better because
-- many packages contain several dirs and it's unclear where there the
-- PCH should be stored. This way is also a bit easier to use in that
-- source files always include "precompiled.h".
-- Notes:
-- * Visual Assist manages to use the project include path and can
-- correctly open these files from the IDE.
-- * precompiled.cpp (needed to "Create" the PCH) also goes in
-- the abovementioned dir.
pch_dir = source_root.."pch/"..package_name.."/"
package_setup_pch(pch_dir, "precompiled.h", "precompiled.cpp")
end
-- this is where the source tree is chopped up into static libs.
@ -420,9 +431,8 @@ function setup_main_exe ()
-- Debugging
"bfd", "iberty"
})
-- For debug_resolve_symbol
-- For debug_resolve_symbol
package.config["Debug"].linkoptions = { "-rdynamic" }
package.config["Testing"].linkoptions = { "-rdynamic" }
elseif OS == "macosx" then
@ -431,10 +441,7 @@ function setup_main_exe ()
"pthread"
})
tinsert(package.libpaths, "/usr/X11R6/lib")
end
end
@ -457,6 +464,10 @@ local function setup_atlas_package(package_name, target_type, rel_source_dirs, r
package_add_contents(source_root, rel_source_dirs, rel_include_dirs, extra_params)
package_add_extern_libs(extern_libs)
if extra_params["pch"] then
package_setup_pch(nil, "stdafx.h", "stdafx.cpp");
end
-- Platform Specifics
if OS == "windows" then
@ -468,11 +479,6 @@ local function setup_atlas_package(package_name, target_type, rel_source_dirs, r
-- required to use WinMain() on Windows, otherwise will default to main()
tinsert(package.buildflags, "no-main")
if extra_params["pch"] then
package.pchheader = "stdafx.h"
package.pchsource = "stdafx.cpp"
end
if extra_params["extra_links"] then
listconcat(package.links, extra_params["extra_links"])
end
@ -640,17 +646,18 @@ function setup_tests()
package_create("test_3_gen", "cxxtestgen")
package.files = hdr_files
package.rootfile = source_root .. "test_root.cpp"
package.testoptions = ""
if OS == "windows" then
-- precompiled headers - the header is added to all generated .cpp files
package.pchheader = "precompiled.h"
package.rootoptions = "--gui=Win32Gui --runner=ParenPrinter --include="..package.pchheader
package.testoptions = "--include="..package.pchheader
package.rootoptions = "--gui=Win32Gui --runner=ParenPrinter"
else
package.rootoptions = "--runner=ErrorPrinter --include=pch/test/precompiled.h"
package.testoptions = "--include=pch/test/precompiled.h"
package.rootoptions = "--runner=ErrorPrinter"
end
-- precompiled headers - the header is added to all generated .cpp files
-- note that the header isn't actually precompiled here, only #included
-- so that the build stage can use it as a precompiled header.
include = " --include=precompiled.h"
package.rootoptions = package.rootoptions .. include
package.testoptions = package.testoptions .. include
package_create("test_2_build", "winexe")
links = static_lib_names
@ -670,13 +677,6 @@ function setup_tests()
-- from "lowlevel" static lib; must be added here to be linked in
tinsert(package.files, source_root.."lib/sysdep/win/error_dialog.rc")
-- precompiled headers
pch_dir = source_root.."pch/test/"
package.pchheader = "precompiled.h"
package.pchsource = "precompiled.cpp"
tinsert(package.files, { pch_dir.."precompiled.cpp", pch_dir.."precompiled.h" })
package.rootoptions = "--include=precompiled.h"
elseif OS == "linux" then
tinsert(package.links, {
@ -686,19 +686,20 @@ function setup_tests()
-- Debugging
"bfd", "iberty"
})
-- For debug_resolve_symbol
package.config["Debug"].linkoptions = { "-rdynamic" }
package.config["Testing"].linkoptions = { "-rdynamic" }
tinsert(package.includepaths, ".")
tinsert(package.includepaths, source_root .. "pch/test/")
tinsert(package.libpaths, "/usr/X11R6/lib")
package.rootoptions = "--include=precompiled.h"
end
package_setup_pch(
source_root .. "pch/test/",
"precompiled.h",
"precompiled.cpp");
tinsert(package.buildflags, "use-library-dep-inputs")

View File

@ -30,7 +30,6 @@ static const char* listCppTargets(const char* name);
static const char* listRcTargets(const char* name);
static const char* listLinkerDeps(const char* name);
int gnu_cpp()
{
int i;
@ -176,6 +175,14 @@ int gnu_cpp()
print_list(prj_get_files(), "\t$(OBJDIR)/", " \\\n", "", listCppSources);
io_print("\n");
io_print("PCHS := \\\n");
if (prj_get_pch_header() != NULL)
{
const char *basename = path_getbasename(prj_get_pch_header());
io_print("\t$(OBJDIR)/%s.h.gch \\\n", basename);
}
io_print("\n");
/* Write out the list of resource files for windows targets */
if (os_is("windows"))
{
@ -214,7 +221,7 @@ int gnu_cpp()
io_print("$(OUTDIR)/$(TARGET)");
}
io_print(": $(OBJECTS) $(LDDEPS) $(RESOURCES)\n");
io_print(": $(PCHS) $(OBJECTS) $(LDDEPS) $(RESOURCES)\n");
if (prj_is_kind("cxxtestgen"))
{
io_print("\t@%s --root", prj_get_cxxtestpath());
@ -278,6 +285,9 @@ int gnu_cpp()
* helps testing and opens the way for per-file configurations */
print_list(prj_get_files(), "", "\n", "", listCppTargets);
// if (prj_get_pch_source() != NULL)
// listGchTarget(prj_get_pch_source());
if (os_is("windows"))
print_list(prj_get_files(), "", "", "", listRcTargets);
@ -330,7 +340,7 @@ static const char* filterLinks(const char* name)
static const char* listCppSources(const char* name)
{
if (is_cpp(name))
if (is_cpp(name) && !matches(path_getname(name), prj_get_pch_source()))
{
strcpy(g_buffer, path_getbasename(name));
strcat(g_buffer, ".o");
@ -369,7 +379,6 @@ static const char* listRcSources(const char* name)
return NULL;
}
/************************************************************************
* Creates the makefile build rules for all source code files
***********************************************************************/
@ -377,12 +386,32 @@ static const char* listRcSources(const char* name)
static const char* listCppTargets(const char* name)
{
const char* ext = path_getextension(name);
const char* basename = path_getbasename(name);
const char* pchHeader = prj_get_pch_header();
const char *pchSource = prj_get_pch_source();
int use_pch = pchHeader?1:0, gen_pch=0;
if (pchSource && matches(path_getname(name), pchSource))
{
gen_pch = 1;
use_pch = 0;
}
if (is_cpp(name))
{
sprintf(g_buffer, "$(OBJDIR)/%s.o: %s\n", basename, name);
strcat(g_buffer, "\t-");
const char* basename = path_getbasename(name);
sprintf(g_buffer, "$(OBJDIR)/%s.%s: %s ",
basename, gen_pch?"h.gch":"o", name);
if (use_pch)
{
basename = path_getbasename(pchHeader);
strcat(g_buffer, "$(OBJDIR)/");
strcat(g_buffer, basename);
strcat(g_buffer, ".h.gch");
// static buffer, *sigh*
basename = path_getbasename(name);
}
strcat(g_buffer, "\n\t-");
if (!g_verbose)
strcat(g_buffer, "@");
strcat(g_buffer, "$(CMD_MKOBJDIR)\n");
@ -437,7 +466,20 @@ static const char* listCppTargets(const char* name)
{
strcat(g_buffer, "$(CXX) $(CXXFLAGS) -MF $(OBJDIR)/");
strcat(g_buffer, basename);
strcat(g_buffer, ".d -o $@ -c $<\n");
strcat(g_buffer, ".d -o $@ -c");
if (gen_pch)
{
strcat(g_buffer, " -x c++-header");
}
else if (use_pch)
{
basename = path_getbasename(pchHeader);
strcat(g_buffer, " -include $(OBJDIR)/");
strcat(g_buffer, basename);
strcat(g_buffer, ".h");
basename = NULL;
}
strcat(g_buffer, " $<\n");
}
}

View File

@ -118,20 +118,22 @@ int io_mkdir(const char* path)
strcpy(buffer, path);
path = buffer;
if (*path == '/')
{
platform_chdir("/");
path++;
}
while (path != NULL)
{
// If this is the first time through, we want to ignore a possible first
// slash (absolute path).
// If this is the N'th time around (N > 1), path will point to the slash
// that was found. Skip it.
char* ptr = strchr(path+1, '/');
char* ptr = strchr(path, '/');
if (ptr != NULL)
*ptr = '\0';
platform_mkdir(path);
platform_chdir(path);
path = ptr;
path = ptr ? ptr+1 : NULL;
}
/* Restore the original working directory */

View File

@ -197,7 +197,7 @@ MaskHandle platform_mask_open(const char* mask)
int platform_mkdir(const char* path)
{
return (mkdir(path, 0) == 0);
return (mkdir(path, 0777) == 0);
}

View File

@ -10,7 +10,6 @@ cd $premake_dir
# build/premake/
mkdir -p $workspace_dir
./premake --target gnu --outpath $workspace_dir --atlas $*
# These files need to be linked; premake makefiles assume that the