diff --git a/src/tools/clang-darwin.jam b/src/tools/clang-darwin.jam index 07ef394769..2745ff7fc8 100644 --- a/src/tools/clang-darwin.jam +++ b/src/tools/clang-darwin.jam @@ -50,6 +50,12 @@ rule init ( version ? : command * : options * ) : version $(version) ] ; common.handle-options clang-darwin : $(condition) : $(command) : $(options) ; + + if $(command) + { + clang.set-target-os-default clang-darwin : $(condition) : $(command-string) : $(options) ; + } + clang.init-flags clang-darwin : $(condition) : $(version) : [ feature.get-values : $(options) ] ; diff --git a/src/tools/clang-linux.jam b/src/tools/clang-linux.jam index 03f5546c29..38918f84d5 100644 --- a/src/tools/clang-linux.jam +++ b/src/tools/clang-linux.jam @@ -74,6 +74,12 @@ rule init ( version ? : command * : options * ) { : version $(version) ] ; common.handle-options clang-linux : $(condition) : $(command) : $(options) ; + + if $(command) + { + clang.set-target-os-default clang-linux : $(condition) : $(command-string) : $(options) ; + } + clang.init-flags clang-linux : $(condition) : $(version) : [ feature.get-values : $(options) ] ; diff --git a/src/tools/clang.jam b/src/tools/clang.jam index b58aedb6bc..8a38f6d734 100644 --- a/src/tools/clang.jam +++ b/src/tools/clang.jam @@ -35,6 +35,37 @@ rule init ( * : * ) } +rule set-target-os-default ( toolset : condition * : command-string : options * ) +{ + # Autodetect target-os from the compiler's own triple, unless the + # toolset was already told what to target + if ! [ feature.get-values : $(options) ] + { + local machine = [ MATCH "^([^ ]+)" : + [ SHELL "$(command-string) -dumpmachine" ] ] ; + local target-os ; + switch $(machine:L) + { + case *android* : target-os ?= android ; + case *mingw* : target-os ?= windows ; + case *cygwin* : target-os ?= cygwin ; + case *linux* : target-os ?= linux ; + case *tvos* : target-os ?= appletv ; + case *watchos* : target-os ?= iphone ; + case *ios* : target-os ?= iphone ; + case *darwin* : target-os ?= darwin ; + case *freebsd* : target-os ?= freebsd ; + case *solaris* : target-os ?= solaris ; + case *qnx* : target-os ?= qnxnto ; + } + if $(target-os) + { + local conditionx = [ regex.replace $(condition) "/" "," ] ; + toolset.add-defaults $(conditionx)\:$(target-os) ; + } + } +} + local rule cxxstd-flags ( toolset : condition * : options * ) { toolset.flags $(toolset).compile.c++ OPTIONS $(condition) : $(options) : unchecked ; diff --git a/src/tools/gcc.jam b/src/tools/gcc.jam index af25131bd4..4aebeff3fc 100644 --- a/src/tools/gcc.jam +++ b/src/tools/gcc.jam @@ -199,11 +199,16 @@ rule init ( version ? : command * : options * : requirement * ) } switch $(machine:L) { - case *mingw* : target-os ?= windows ; - case *cygwin* : target-os ?= cygwin ; - case *linux* : target-os ?= linux ; - case *aix* : target-os ?= aix ; - case *hpux* : target-os ?= hpux ; + case *mingw* : target-os ?= windows ; + case *cygwin* : target-os ?= cygwin ; + case *android* : target-os ?= android ; + case *linux* : target-os ?= linux ; + case *aix* : target-os ?= aix ; + case *hpux* : target-os ?= hpux ; + case *darwin* : target-os ?= darwin ; + case *freebsd* : target-os ?= freebsd ; + case *solaris* : target-os ?= solaris ; + case *qnx* : target-os ?= qnxnto ; # TODO: finish this list. } } diff --git a/test/test_all.py b/test/test_all.py index af5354636f..66936735d5 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -486,6 +486,7 @@ def reorder_tests(tests, first_test): "toolset_intel_darwin", "toolset_msvc", "toolset_requirements", + "toolset_target_os_autodetect", "transitive_skip", "unit_test", "unused", diff --git a/test/toolset_target_os_autodetect.py b/test/toolset_target_os_autodetect.py new file mode 100644 index 0000000000..7ad7ae56ef --- /dev/null +++ b/test/toolset_target_os_autodetect.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at +# https://www.bfgroup.xyz/b2/LICENSE.txt) + +# Test for autodetecting from the compiler's own +# `-dumpmachine` triple when target-os is not given explicitly, covering +# the gcc, clang-linux and clang-darwin toolsets. + +import BoostBuild +import sys +import textwrap + +MOCK_COMPILER_TEMPLATE = '''#!/usr/bin/env python3 +import sys + +args = sys.argv[1:] + +if args == ["-dumpmachine"]: + print("@TRIPLE@") + sys.exit(0) + +if args == ["-print-prog-name=ar"]: + print("ar") + sys.exit(0) + +if "-c" in args and "-o" in args: + if "-DOS_AUTODETECTED_OK" not in args: + sys.exit(1) + with open(args[args.index("-o") + 1], "w") as f: + f.write("mock object\\n") + sys.exit(0) + +sys.exit(1) +''' + + +def test_target_os_gcc_autodetect(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("fake-compiler.py", MOCK_COMPILER_TEMPLATE.replace("@TRIPLE@", "arm-linux-androideabi")) + t.write("project-config.jam", textwrap.dedent(''' + import os ; + path-constant HERE : . ; + local PYTHON = [ os.environ PYTHON_CMD ] ; + using gcc : autodetect : $(PYTHON) $(HERE)/fake-compiler.py ; + ''')) + t.write("Jamroot.jam", textwrap.dedent(''' + obj test : test.cpp : + android:OS_AUTODETECTED_OK ; + ''')) + t.write("test.cpp", "int f() { return 0; }") + + t.run_build_system(["-sPYTHON_CMD=" + sys.executable, "toolset=gcc-autodetect", "test"]) + t.cleanup() + +def test_target_os_clang_linux_autodetect(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("fake-compiler.py", MOCK_COMPILER_TEMPLATE.replace("@TRIPLE@", "aarch64-linux-android21")) + t.write("project-config.jam", textwrap.dedent(''' + import os ; + path-constant HERE : . ; + local PYTHON = [ os.environ PYTHON_CMD ] ; + using clang-linux : autodetect : $(PYTHON) $(HERE)/fake-compiler.py ; + ''')) + t.write("Jamroot.jam", textwrap.dedent(''' + obj test : test.cpp : + android:OS_AUTODETECTED_OK ; + ''')) + t.write("test.cpp", "int f() { return 0; }") + + t.run_build_system(["-sPYTHON_CMD=" + sys.executable, "toolset=clang-linux-autodetect", "test"]) + t.cleanup() + +def test_target_os_clang_darwin_autodetect(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("fake-compiler.py", MOCK_COMPILER_TEMPLATE.replace("@TRIPLE@", "x86_64-pc-solaris2.11")) + t.write("project-config.jam", textwrap.dedent(''' + import os ; + path-constant HERE : . ; + local PYTHON = [ os.environ PYTHON_CMD ] ; + using clang-darwin : autodetect : $(PYTHON) $(HERE)/fake-compiler.py ; + ''')) + t.write("Jamroot.jam", textwrap.dedent(''' + obj test : test.cpp : + solaris:OS_AUTODETECTED_OK ; + ''')) + t.write("test.cpp", "int f() { return 0; }") + + t.run_build_system(["-sPYTHON_CMD=" + sys.executable, "toolset=clang-darwin-autodetect", "test"]) + t.cleanup() + + +def test_target_os_clang_darwin_autodetect_linux(): + t = BoostBuild.Tester(pass_toolset=0) + + t.write("fake-compiler.py", MOCK_COMPILER_TEMPLATE.replace("@TRIPLE@", "armv7-unknown-linux-gnueabihf")) + t.write("project-config.jam", textwrap.dedent(''' + import os ; + path-constant HERE : . ; + local PYTHON = [ os.environ PYTHON_CMD ] ; + using clang-darwin : autodetect : $(PYTHON) $(HERE)/fake-compiler.py ; + ''')) + t.write("Jamroot.jam", textwrap.dedent(''' + obj test : test.cpp : + linux:OS_AUTODETECTED_OK ; + ''')) + t.write("test.cpp", "int f() { return 0; }") + + t.run_build_system(["-sPYTHON_CMD=" + sys.executable, "toolset=clang-darwin-autodetect", "test"]) + t.cleanup() + + +test_target_os_gcc_autodetect() +test_target_os_clang_linux_autodetect() +test_target_os_clang_darwin_autodetect() +test_target_os_clang_darwin_autodetect_linux()