Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Long path and Unicode support on Windows 10+ #316

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ci/azp-windows-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ steps:
$env:path += ';' + $env:CXX_PATH
cd test
echo "using" $env:TEST_TOOLSET ":" ":" $env:CXX ";" > ${env:HOME}/user-config.jam
py test_all.py $env:TEST_TOOLSET
py -X utf8 test_all.py $env:TEST_TOOLSET
cd ..
displayName: Test
- powershell: |
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/core_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ jobs:

- name: Test
working-directory: test
env: { PYTHONUTF8: 1 }
run: ./test_all.py ${{matrix.toolset}}

- name: 'No Warnings'
Expand Down
4 changes: 4 additions & 0 deletions Jamroot.jam
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ exe b2
<toolset>clang-win:<find-static-library>kernel32
<toolset>clang-win:<find-static-library>advapi32
<toolset>clang-win:<find-static-library>user32
<target-os>windows,<toolset>gcc:<source>src/engine/res.rc
<target-os>windows,<toolset>clang:<source>src/engine/res.rc
<toolset>msvc:<embed-manifest-file>src/engine/b2.exe.manifest
<toolset>clang-win:<embed-manifest-file>src/engine/b2.exe.manifest
;
explicit b2 ;

Expand Down
3 changes: 2 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ environment:
job_group: 'Test'
TOOLSET: clang-win
TEST_TOOLSET: clang-win
B2_DONT_EMBED_MANIFEST: true # lld-link: error: unable to find mt.exe in PATH: no such file or directory
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
- job_name: 'Cygwin 3.1.7 x64, Test'
job_group: 'TestCygwin'
Expand Down Expand Up @@ -61,7 +62,7 @@ for:
echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TEST"
echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
cd test
py test_all.py %TEST_TOOLSET%
py -X utf8 test_all.py %TEST_TOOLSET%
cd ..
- cmd: |
echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
Expand Down
22 changes: 22 additions & 0 deletions src/engine/b2.exe.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 10 and 11 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<asmv3:application>
<asmv3:windowsSettings xmlns:ws1="http://schemas.microsoft.com/SMI/2016/WindowsSettings"
xmlns:ws2="http://schemas.microsoft.com/SMI/2019/WindowsSettings">
<ws1:longPathAware>true</ws1:longPathAware>
<ws2:activeCodePage>UTF-8</ws2:activeCodePage>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
4 changes: 4 additions & 0 deletions src/engine/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,10 @@ mod_version.cpp \
if test_true ${B2_DEBUG_OPT} ; then B2_CXXFLAGS="${B2_CXXFLAGS_DEBUG}"
else B2_CXXFLAGS="${B2_CXXFLAGS_RELEASE} -DNDEBUG"
fi
if [ -z "$B2_DONT_EMBED_MANIFEST" ] && [ -x "$(command -v windres)" ] ; then
B2_CXXFLAGS="${B2_CXXFLAGS} -Wl,res.o"
( B2_VERBOSE_OPT=${TRUE} echo_run windres --input res.rc --output res.o )
fi
( B2_VERBOSE_OPT=${TRUE} echo_run ${B2_CXX} ${B2_CXXFLAGS} ${B2_SOURCES} -o b2 )
}

Expand Down
37 changes: 25 additions & 12 deletions src/engine/config_toolset.bat
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ if not "_%B2_TOOLSET_ROOT%_" == "__" (
set "B2_CXX="%CXX%" /nologo /MP /MT /TP /Feb2 /wd4996 /O2 /GL /EHsc"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_VC11
if not defined CXX ( set "CXX=cl" )
Expand All @@ -54,7 +54,7 @@ if NOT "_%B2_TOOLSET_ROOT%_" == "__" (
set "B2_CXX="%CXX%" /nologo /MP /MT /TP /Feb2 /wd4996 /O2 /GL /EHsc"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_VC12
if not defined CXX ( set "CXX=cl" )
Expand All @@ -73,7 +73,7 @@ if NOT "_%B2_TOOLSET_ROOT%_" == "__" (
set "B2_CXX="%CXX%" /nologo /MP /MT /TP /Feb2 /wd4996 /O2 /GL /EHsc"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_VC14
if not defined CXX ( set "CXX=cl" )
Expand All @@ -93,7 +93,7 @@ if NOT "_%B2_TOOLSET_ROOT%_" == "__" (
set "B2_CXX="%CXX%" /nologo /MP /MT /TP /Feb2 /wd4996 /O2 /GL /EHsc"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_VC141
if not defined CXX ( set "CXX=cl" )
Expand All @@ -115,7 +115,7 @@ popd
set "B2_CXX="%CXX%" /nologo /MP /MT /TP /Feb2 /wd4996 /O2 /GL /EHsc"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_VC142
if not defined CXX ( set "CXX=cl" )
Expand All @@ -137,7 +137,7 @@ popd
set "B2_CXX="%CXX%" /nologo /MP /MT /TP /Feb2 /wd4996 /O2 /GL /EHsc"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_VC143
if not defined CXX ( set "CXX=cl" )
Expand All @@ -160,7 +160,7 @@ popd
set "B2_CXX="%CXX%" /nologo -TP /wd4996 /wd4675 /EHs /GR /Zc:throwingNew /O2 /Ob2 /W3 /MD /Zc:forScope /Zc:wchar_t /Zc:inline /Gw /favor:blend /Feb2"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_VCUNK
if NOT "_%B2_TOOLSET%_" == "_vcunk_" goto Skip_VCUNK
Expand All @@ -182,7 +182,7 @@ popd
set "B2_CXX="%CXX%" /nologo /MP /MT /TP /Feb2 /wd4996 /O2 /GL /EHsc"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_BORLAND
if not defined CXX ( set "CXX=bcc32c" )
Expand All @@ -209,13 +209,13 @@ goto :eof
if not defined CXX ( set "CXX=g++" )
set "B2_CXX="%CXX%" -x c++ -std=c++11 -s -O3 -o b2.exe -D_GNU_SOURCE"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Windres

:Config_CLANG
if not defined CXX ( set "CXX=clang++" )
set "B2_CXX="%CXX%" -x c++ -std=c++11 -s -O3 -o b2.exe"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Windres

:Config_CLANG_WIN
if not defined CXX ( set "CXX=clang-cl" )
Expand All @@ -224,10 +224,10 @@ if "_%ProgramFiles(x86)%_" == "__" (
) else (
set "PATH=%PATH%;%ProgramFiles%\LLVM\bin;%ProgramFiles(x86)%\LLVM\bin"
)
set "B2_CXX="%CXX%" /MT /TP /Feb2 /wd4996 /O2 /EHsc /Gw /Zc:inline"
set "B2_CXX="%CXX%" /MT /TP /Feb2 /wd4996 /O2 /EHsc /Gw /Zc:inline -fuse-ld=lld"
set "B2_CXX_LINK=/link kernel32.lib advapi32.lib user32.lib"
set "_known_=1"
goto :eof
goto :Embed_Minafest_Via_Link

:Config_GCC_NOCYGWIN
if not defined CXX ( set "CXX=g++" )
Expand All @@ -249,4 +249,17 @@ if not "_%B2_TOOLSET_ROOT%_" == "__" (
for /F "delims=" %%I in ("%CXX%") do set "PATH=%PATH%;%%~dpI"
set "B2_CXX="%CXX%" -x c++ -std=c++11 -s -O3 -static -o b2.exe"
set "_known_=1"
goto :Embed_Minafest_Via_Windres

:Embed_Minafest_Via_Link
if not defined B2_DONT_EMBED_MANIFEST (
set "B2_CXX_LINK=%B2_CXX_LINK% /MANIFEST:EMBED /MANIFESTINPUT:b2.exe.manifest"
)
goto :eof

:Embed_Minafest_Via_Windres
if not defined B2_DONT_EMBED_MANIFEST (
where windres >NUL 2>NUL
if %ERRORLEVEL% NEQ 0 ( call; ) else ( set "B2_CXX=windres --input res.rc --output res.o && %B2_CXX% -Wl,res.o" )
)
goto :eof
43 changes: 43 additions & 0 deletions src/engine/jam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@
# include <signal.h>
#endif

#ifdef WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif

struct globs globs =
{
0, /* noexec */
Expand Down Expand Up @@ -614,6 +619,44 @@ int guarded_main( int argc, char * * argv )
return status ? EXITBAD : EXITOK;
}

#ifdef WIN32
namespace {

struct SetConsoleCodepage
{
SetConsoleCodepage()
{
// Check whether UTF-8 is actually the default encoding for this process
if (GetACP() != CP_UTF8)
return;

orig_console_cp = GetConsoleCP();
if (orig_console_cp != 0 && orig_console_cp != CP_UTF8)
SetConsoleCP(CP_UTF8);
orig_console_output_cp = GetConsoleOutputCP();
if (orig_console_output_cp != 0 && orig_console_output_cp != CP_UTF8)
SetConsoleOutputCP(CP_UTF8);
}

~SetConsoleCodepage()
{
// Restore original console codepage
if (orig_console_cp != 0 && orig_console_cp != CP_UTF8)
SetConsoleCP(orig_console_cp);
if (orig_console_output_cp != 0 && orig_console_output_cp != CP_UTF8)
SetConsoleOutputCP(orig_console_output_cp);
}

private:
UINT orig_console_cp = 0;
UINT orig_console_output_cp = 0;
};

static const SetConsoleCodepage g_console_codepage_setter{};

}
#endif

int main( int argc, char * * argv )
{
BJAM_MEM_INIT();
Expand Down
1 change: 1 addition & 0 deletions src/engine/res.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1 24 b2.exe.manifest
18 changes: 18 additions & 0 deletions src/tools/clang-linux.jam
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type ;
import numbers ;
import os ;
import property ;
import rc ;
import set ;

feature.extend-subfeature toolset clang : platform : linux ;
Expand Down Expand Up @@ -86,6 +87,23 @@ rule init ( version ? : command * : options * ) {
archiver = $(root)/bin/ar ;
}
toolset.flags clang-linux.archive .AR $(condition) : $(archiver[1]) ;

# - Resource compiler.
local rc = [ common.get-invocation-command-nodefault clang-linux : windres :
[ feature.get-values <rc> : $(options) ] : $(bin) : search-path ] ;
local rc-type = [ feature.get-values <rc-type> : $(options) ] ;
rc-type ?= windres ;
if ! $(rc)
{
# If we can not find an RC compiler we fallback to a null one that
# creates empty object files. This allows the same Jamfiles to work
# across the board. The null RC uses assembler to create the empty
# objects, so configure that.
rc = [ common.get-invocation-command clang-linux : as : : $(bin) : search-path ]
;
rc-type = null ;
}
rc.configure $(rc) : $(condition) : <rc-type>$(rc-type) ;
}

rule get-full-version ( command-string )
Expand Down
1 change: 1 addition & 0 deletions src/tools/msvc.jam
Original file line number Diff line number Diff line change
Expand Up @@ -2000,6 +2000,7 @@ local rule register-toolset-really ( )
toolset.flags msvc.link LINKFLAGS <debug-symbols>on : /DEBUG ;
toolset.flags msvc.link DEF_FILE <def-file> ;
toolset.flags msvc.link MANIFEST_FILE <embed-manifest-via>linker : <embed-manifest-file> ;
toolset.flags msvc.link EMBED_MANIFEST_FILE <embed-manifest-via>mt : <embed-manifest-file> ;

# The linker disables the default optimizations when using /DEBUG so we
# have to enable them manually for release builds with debug symbols.
Expand Down
24 changes: 17 additions & 7 deletions test/BoostBuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,12 @@ def __init__(self, arguments=None, executable=None,

os.chdir(self.workdir)

def __enter__(self):
return self

def __exit__(self, type, value, traceback):
self.cleanup()

def cleanup(self):
try:
TestCmd.TestCmd.cleanup(self)
Expand Down Expand Up @@ -383,11 +389,13 @@ def write(self, file, content, wait=True):
self.__makedirs(os.path.dirname(nfile), wait)
if not type(content) == bytes:
content = content.encode()
f = open(nfile, "wb")
try:
f.write(content)
finally:
f.close()
with open(nfile, "wb") as f:
f.write(content)
except Exception as e:
annotation("failure", f"Could not create file '{nfile}': {e}")
annotate_stack_trace(level=3)
self.fail_test(1)
self.__ensure_newer_than_last_build(nfile)

def rename(self, src, dst):
Expand Down Expand Up @@ -1049,9 +1057,11 @@ def __makedirs(self, path, wait):
os.mkdir(path)
self.__ensure_newer_than_last_build(path)
else:
os.makedirs(path)
except Exception:
pass
os.makedirs(path, exist_ok=True)
except Exception as e:
annotation("failure", f"Could not create path '{path}': {e}")
annotate_stack_trace(level=3)
self.fail_test(1)

def __python_timestamp_resolution(self, path, minimum_resolution):
"""
Expand Down
Loading