Skip to content

Commit

Permalink
msvc: fix same directory pch header
Browse files Browse the repository at this point in the history
Pass to `-Yc` path as was typed by user (not exactly so, B2 automatically turns / to \ on Windows, so force the / in variable expansion).
  • Loading branch information
Kojoley committed Apr 2, 2023
1 parent a6c8b73 commit 5801366
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 23 deletions.
35 changes: 23 additions & 12 deletions src/tools/msvc.jam
Original file line number Diff line number Diff line change
Expand Up @@ -689,15 +689,15 @@ rule compile.c ( targets + : sources * : properties * )
{
set-setup-command $(targets) : $(properties) ;
get-rspline $(targets) : -TC CFLAGS ;
compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
compile-c-c++ $(<) : $(>) ;
}


rule compile.c.preprocess ( targets + : sources * : properties * )
{
set-setup-command $(targets) : $(properties) ;
get-rspline $(targets) : -TC CFLAGS ;
preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
preprocess-c-c++ $(<) : $(>) ;
}


Expand All @@ -706,6 +706,8 @@ rule compile.c.pch ( targets + : sources * : properties * )
set-setup-command $(targets) : $(properties) ;
get-rspline $(targets[1]) : -TC CFLAGS ;
get-rspline $(targets[2]) : -TC CFLAGS ;
local pch-header = [ on $(<) return $(PCH_HEADER) ] ;
PCH_HEADER_AS_SPELLED on $(<) = $(sources:G=) ;
local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
if $(pch-source)
{
Expand Down Expand Up @@ -738,14 +740,14 @@ toolset.flags msvc YLOPTION : "-Yl" ;
# for each source file by rule archive, as in this case compiler must be used
# to create a single PDB for our library.
#
actions compile-c-c++ bind PDB_NAME PCH_HEADER
actions compile-c-c++ bind PDB_NAME PCH_HEADER_AS_SPELLED PCH_FILE
{
$(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[1]:W)" -c -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -I"$(PCH_HEADER:D)" -FI"$(PCH_HEADER:D=)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE)) $(.CC.FILTER)
$(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[1]:W)" -c -Fo"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -FI"$(PCH_HEADER_AS_SPELLED:T)" -Yu"$(PCH_HEADER_AS_SPELLED:T)" -Fp"$(PCH_FILE:W)" $(CC_RSPLINE)) $(.CC.FILTER)
}

actions preprocess-c-c++ bind PDB_NAME PCH_HEADER
actions preprocess-c-c++ bind PDB_NAME PCH_HEADER_AS_SPELLED PCH_FILE
{
$(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[1]:W)" -P -Fi"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -I"$(PCH_HEADER:D)" -FI"$(PCH_HEADER:D=)" -Yu"$(>[3]:D=)" -Fp"$(>[2]:W)" $(CC_RSPLINE))
$(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[1]:W)" -P -Fi"$(<[1]:W)" $(PDB_CFLAG)"$(PDB_NAME)" -FI"$(PCH_HEADER_AS_SPELLED:T)" -Yu"$(PCH_HEADER_AS_SPELLED:T)" -Fp"$(PCH_FILE:W)" $(CC_RSPLINE))
}

rule compile-c-c++ ( targets + : sources * )
Expand All @@ -754,6 +756,8 @@ rule compile-c-c++ ( targets + : sources * )
DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
PDB_NAME on $(<) = $(<[1]:S=.pdb) ;
LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
local pch-header = [ on $(<[1]) return $(PCH_HEADER) ] ;
PCH_HEADER_AS_SPELLED on $(<[1]) = $(pch-header:G=) ;
}

rule preprocess-c-c++ ( targets + : sources * )
Expand All @@ -762,6 +766,8 @@ rule preprocess-c-c++ ( targets + : sources * )
DEPENDS $(<[1]) : [ on $(<[1]) return $(PCH_FILE) ] ;
PDB_NAME on $(<) = $(<:S=.pdb) ;
LOCATE on $(<[1]:S=.pdb) = [ on $(<[1]) return $(LOCATE) ] ;
local pch-header = [ on $(<[1]) return $(PCH_HEADER) ] ;
PCH_HEADER_AS_SPELLED on $(<[1]) = $(pch-header:G=) ;
}

# Action for running the C/C++ compiler using precompiled headers. In addition
Expand All @@ -770,33 +776,33 @@ rule preprocess-c-c++ ( targets + : sources * )
#
# The global .escaped-double-quote variable is used to avoid messing up Emacs
# syntax highlighting in the messy N-quoted code below.
actions compile-c-c++-pch
actions compile-c-c++-pch bind PCH_HEADER_AS_SPELLED
{
$(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[2]:W)" -c -Fo"$(<[2]:W)" -I"$(>[1]:D)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE)) @($(<[1]:W).cpp:<=":>=":E=$(.hash)include $(.escaped-double-quote)$(>[1]:D=)$(.escaped-double-quote)$(.nl)) $(.CC.FILTER)
$(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[2]:W)" -c -Fo"$(<[2]:W)" -Yc"$(PCH_HEADER_AS_SPELLED:T)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE)) @($(<[1]:W).cpp:<=":>=":E=$(.hash)include $(.escaped-double-quote)$(PCH_HEADER_AS_SPELLED:T)$(.escaped-double-quote)$(.nl)) $(.CC.FILTER)
}


# Action for running the C/C++ compiler using precompiled headers. An already
# built source file for compiling the precompiled headers is expected to be
# given as one of the source parameters.
actions compile-c-c++-pch-s
actions compile-c-c++-pch-s bind PCH_HEADER_AS_SPELLED
{
$(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[2]:W)" -c -Fo"$(<[2]:W)" -I"$(>[1]:D)" -Yc"$(>[1]:D=)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE)) $(.CC.FILTER)
$(.SETUP) $(.CC) @($(<[1]:W).rsp:O=FC:<=@":>=":E="$(>[2]:W)" -c -Fo"$(<[2]:W)" -Yc"$(PCH_HEADER_AS_SPELLED:T)" $(YLOPTION)"__bjam_pch_symbol_$(>[1]:D=)" -Fp"$(<[1]:W)" $(CC_RSPLINE)) $(.CC.FILTER)
}


rule compile.c++ ( targets + : sources * : properties * )
{
set-setup-command $(targets) : $(properties) ;
get-rspline $(targets) : -TP C++FLAGS ;
compile-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
compile-c-c++ $(<) : $(>) ;
}

rule compile.c++.preprocess ( targets + : sources * : properties * )
{
set-setup-command $(targets) : $(properties) ;
get-rspline $(targets) : -TP C++FLAGS ;
preprocess-c-c++ $(<) : $(>) [ on $(<) return $(PCH_FILE) ] [ on $(<) return $(PCH_HEADER) ] ;
preprocess-c-c++ $(<) : $(>) ;
}


Expand All @@ -805,6 +811,8 @@ rule compile.c++.pch ( targets + : sources * : properties * )
set-setup-command $(targets) : $(properties) ;
get-rspline $(targets[1]) : -TP C++FLAGS ;
get-rspline $(targets[2]) : -TP C++FLAGS ;
local pch-header = [ on $(<) return $(PCH_HEADER) ] ;
PCH_HEADER_AS_SPELLED on $(<) = $(sources:G=) ;
local pch-source = [ on $(<) return $(PCH_SOURCE) ] ;
if $(pch-source)
{
Expand Down Expand Up @@ -1005,13 +1013,16 @@ class msvc-pch-generator : pch-generator

# If we do not have the PCH source - that is fine. We will just create a
# temporary .cpp file in the action.
local include-path = [ path.relative-to . [ $(pch-header).path ] ] ;
local generated = [ generator.run $(project) $(name)
: [ property-set.create
# Passing of <pch-source> is a dirty trick, needed because
# non-composing generators with multiple inputs are subtly
# broken. For more detailed information see:
# https://zigzag.cs.msu.su:7813/boost.build/ticket/111
<pch-source>$(pch-source)
<pch-header>$(pch-header)
<include>$(include-path)
[ $(property-set).raw ] ]
: $(pch-header) ] ;

Expand Down
47 changes: 36 additions & 11 deletions test/pch.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
t.write("jamroot.jam", """
import pch ;
project : requirements <warnings-as-errors>on ;
cpp-pch pch : a/pch.hpp ;
cpp-pch pch-afx : a/pch.hpp : <define>HELLO ;
cpp-pch pch-msvc-source : a/pch.hpp : <toolset>msvc:<source>a/pch.cpp ;
cpp-pch pch : pch.hpp ;
cpp-pch pch-afx : pch.hpp : <define>HELLO ;
cpp-pch pch-msvc-source : pch.hpp : <toolset>msvc:<source>pch.cpp ;
exe hello : hello.cpp pch ;
exe hello-afx : hello-afx.cpp pch-afx : <define>HELLO ;
exe hello-msvc-source : hello-msvc-source.cpp pch-msvc-source ;
cpp-pch subdir-pch : a/pch_different.hpp ;
exe hello-subdir : a/hello.cpp subdir-pch ;
""")

pch_content = """\
Expand All @@ -31,31 +34,34 @@ class TestClass
TestClass( int, int ) {}
};
"""
t.write("a/pch.hpp", pch_content)
t.write("pch.hpp", pch_content)
t.copy("pch.hpp", "a/pch_different.hpp")

t.write("a/pch.cpp", """#include <pch.hpp>
t.write("pch.cpp", """#include <pch.hpp>
""")

toolset = BoostBuild.get_toolset()
for name in ("hello.cpp", "hello-afx.cpp", "hello-msvc-source.cpp"):
for name in ("hello.cpp", "hello-afx.cpp", "hello-msvc-source.cpp", "a/hello.cpp", "a/hello-rel.cpp"):
t.write(name, """int main() { TestClass c(1, 2); }
""")

t.run_build_system()
t.expect_addition("bin/$toolset/debug*/hello.exe")
t.expect_addition("bin/$toolset/debug*/hello-afx.exe")
t.expect_addition("bin/$toolset/debug*/hello-msvc-source.exe")
t.expect_addition("bin/$toolset/debug*/hello-subdir.exe")


# Now make the header unusable, replace its content with some garbage, but
# preserve the size and timestamp to fool the compiler. If everything is OK,
# B2 will not recreate PCH, and compiler will happily use pre-compiled
# header, not noticing that the real header is bad.

t.rename("a/pch.hpp", "a/pch.hpp.orig")
s = "THIS WILL NOT COMPILE. "
t.write("a/pch.hpp", s + (len(pch_content) - len(s)) * 'x')
t.copy_timestamp("a/pch.hpp.orig", "a/pch.hpp")
t.rename("pch.hpp", "pch.hpp.orig")
s = """#error PCH REBUILD HAPPEND
THIS WILL NOT COMPILE
"""
t.write("pch.hpp", s + (len(pch_content) - len(s)) * 'x')
t.copy_timestamp("pch.hpp.orig", "pch.hpp")

t.rm("bin/$toolset/debug*/hello.obj")
t.rm("bin/$toolset/debug*/hello-afx.obj")
Expand All @@ -66,4 +72,23 @@ class TestClass
t.expect_addition("bin/$toolset/debug*/hello-afx.obj")
t.expect_addition("bin/$toolset/debug*/hello-msvc-source.obj")

t.rm("bin")
t.copy("a/pch_different.hpp", "pch.hpp")
t.rename("a", "b")
t.write("b/jamfile.jam", """\
import pch ;
project : requirements <warnings-as-errors>on ;
cpp-pch pch : pch_different.hpp ;
exe hello : hello.cpp pch ;
cpp-pch pch-rel : ../pch.hpp ;
exe hello-rel : hello-rel.cpp pch-rel ;
""")
t.run_build_system(["-d+2", "b"])
t.expect_addition("b/bin/$toolset/debug*/hello.exe")
t.expect_addition("b/bin/$toolset/debug*/hello-rel.exe")
t.rm("b/bin")
t.run_build_system(["-d+2"], subdir="b")
t.expect_addition("b/bin/$toolset/debug*/hello.exe")
t.expect_addition("b/bin/$toolset/debug*/hello-rel.exe")

t.cleanup()

0 comments on commit 5801366

Please sign in to comment.