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:
parent
db045c330b
commit
35ac7776ee
@ -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")
|
||||
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user