2017-12-26 16:44:08 -08:00
const builtin = @import ( " builtin " ) ;
2017-12-11 20:34:59 -08:00
const std = @import ( " std " ) ;
const Builder = std . build . Builder ;
2017-04-18 22:13:15 -07:00
const tests = @import ( " test/tests.zig " ) ;
2017-12-11 20:34:59 -08:00
const BufMap = std . BufMap ;
const warn = std . debug . warn ;
const mem = std . mem ;
const ArrayList = std . ArrayList ;
const io = std . io ;
2019-05-26 10:17:34 -07:00
const fs = std . fs ;
2019-07-14 00:06:20 -07:00
const InstallDirectoryOptions = std . build . InstallDirectoryOptions ;
2017-04-18 22:13:15 -07:00
2018-05-31 07:56:59 -07:00
pub fn build ( b : * Builder ) ! void {
2019-07-04 14:43:56 -07:00
b . setPreferredReleaseMode ( . ReleaseFast ) ;
2017-10-21 14:31:06 -07:00
const mode = b . standardReleaseOptions ( ) ;
2017-11-07 00:22:27 -08:00
var docgen_exe = b . addExecutable ( " docgen " , " doc/docgen.zig " ) ;
2019-05-26 10:17:34 -07:00
const rel_zig_exe = try fs . path . relative ( b . allocator , b . build_root , b . zig_exe ) ;
const langref_out_path = fs . path . join (
2019-02-06 21:42:41 -08:00
b . allocator ,
2019-11-27 00:30:39 -08:00
& [ _ ] [ ] const u8 { b . cache_root , " langref.html " } ,
2019-02-06 21:42:41 -08:00
) catch unreachable ;
breaking changes to zig build API and improved caching
* in Zig build scripts, getOutputPath() is no longer a valid function
to call, unless setOutputDir() was used, or within a custom make()
function. Instead there is more convenient API to use which takes
advantage of the caching system. Search this commit diff for
`exe.run()` for an example.
* Zig build by default enables caching. All build artifacts will go
into zig-cache. If you want to access build artifacts in a convenient
location, it is recommended to add an `install` step. Otherwise
you can use the `run()` API mentioned above to execute programs
directly from their location in the cache. Closes #330.
`addSystemCommand` is available for programs not built with Zig
build.
* Please note that Zig does no cache evicting yet. You may have to
manually delete zig-cache directories periodically to keep disk
usage down. It's planned for this to be a simple Least Recently
Used eviction system eventually.
* `--output`, `--output-lib`, and `--output-h` are removed. Instead,
use `--output-dir` which defaults to the current working directory.
Or take advantage of `--cache on`, which will print the main output
path to stdout, and the other artifacts will be in the same directory
with predictable file names. `--disable-gen-h` is available when
one wants to prevent .h file generation.
* `@cImport` is always independently cached now. Closes #2015.
It always writes the generated Zig code to disk which makes debug
info and compile errors better. No more "TODO: remember C source
location to display here"
* Fix .d file parsing. (Fixes the MacOS CI failure)
* Zig no longer creates "temporary files" other than inside a
zig-cache directory.
This breaks the CLI API that Godbolt uses. The suggested new invocation
can be found in this commit diff, in the changes to `test/cli.zig`.
2019-03-08 19:53:35 -08:00
var docgen_cmd = docgen_exe . run ( ) ;
2019-11-27 00:30:39 -08:00
docgen_cmd . addArgs ( & [ _ ] [ ] const u8 {
2018-01-16 22:50:35 -08:00
rel_zig_exe ,
2019-05-26 10:17:34 -07:00
" doc " + + fs . path . sep_str + + " langref.html.in " ,
2018-09-12 08:49:46 -07:00
langref_out_path ,
2017-11-07 00:22:27 -08:00
} ) ;
docgen_cmd . step . dependOn ( & docgen_exe . step ) ;
const docs_step = b . step ( " docs " , " Build documentation " ) ;
docs_step . dependOn ( & docgen_cmd . step ) ;
2018-01-03 15:25:17 -08:00
const test_step = b . step ( " test " , " Run all the tests " ) ;
2018-01-03 18:32:50 -08:00
// find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library
2019-11-27 00:30:39 -08:00
const build_info = try b . exec ( & [ _ ] [ ] const u8 {
2018-05-17 20:21:44 -07:00
b . zig_exe ,
" BUILD_INFO " ,
} ) ;
2018-01-03 18:32:50 -08:00
var index : usize = 0 ;
2018-11-13 05:08:37 -08:00
var ctx = Context {
2018-07-10 17:18:43 -07:00
. cmake_binary_dir = nextValue ( & index , build_info ) ,
. cxx_compiler = nextValue ( & index , build_info ) ,
. llvm_config_exe = nextValue ( & index , build_info ) ,
. lld_include_dir = nextValue ( & index , build_info ) ,
. lld_libraries = nextValue ( & index , build_info ) ,
2020-02-04 00:39:20 -08:00
. clang_libraries = nextValue ( & index , build_info ) ,
2018-07-10 17:18:43 -07:00
. dia_guids_lib = nextValue ( & index , build_info ) ,
. llvm = undefined ,
} ;
ctx . llvm = try findLLVM ( b , ctx . llvm_config_exe ) ;
2018-01-03 18:32:50 -08:00
2018-07-10 17:18:43 -07:00
var test_stage2 = b . addTest ( " src-self-hosted/test.zig " ) ;
test_stage2 . setBuildMode ( builtin . Mode . Debug ) ;
2019-11-23 12:56:05 -08:00
test_stage2 . addPackagePath ( " stage2_tests " , " test/stage2/test.zig " ) ;
2018-01-03 18:32:50 -08:00
2019-11-27 00:30:39 -08:00
const fmt_build_zig = b . addFmt ( & [ _ ] [ ] const u8 { " build.zig " } ) ;
2019-02-26 15:10:40 -08:00
2018-01-03 18:32:50 -08:00
var exe = b . addExecutable ( " zig " , " src-self-hosted/main.zig " ) ;
exe . setBuildMode ( mode ) ;
2018-03-31 13:34:55 -07:00
2018-07-10 17:18:43 -07:00
try configureStage2 ( b , test_stage2 , ctx ) ;
try configureStage2 ( b , exe , ctx ) ;
2018-01-03 15:25:17 -08:00
2018-07-11 11:09:05 -07:00
const skip_release = b . option ( bool , " skip-release " , " Main test suite skips release builds " ) orelse false ;
2018-09-12 11:50:26 -07:00
const skip_release_small = b . option ( bool , " skip-release-small " , " Main test suite skips release-small builds " ) orelse skip_release ;
const skip_release_fast = b . option ( bool , " skip-release-fast " , " Main test suite skips release-fast builds " ) orelse skip_release ;
const skip_release_safe = b . option ( bool , " skip-release-safe " , " Main test suite skips release-safe builds " ) orelse skip_release ;
2019-05-14 18:21:59 -07:00
const skip_non_native = b . option ( bool , " skip-non-native " , " Main test suite skips non-native builds " ) orelse false ;
2019-09-21 20:55:56 -07:00
const skip_libc = b . option ( bool , " skip-libc " , " Main test suite skips tests that link libc " ) orelse false ;
2020-02-07 09:30:16 -08:00
const skip_self_hosted = ( b . option ( bool , " skip-self-hosted " , " Main test suite skips building self hosted compiler " ) orelse false ) or true ; // TODO evented I/O good enough that this passes everywhere
if ( ! skip_self_hosted ) {
2019-11-23 12:56:05 -08:00
test_step . dependOn ( & exe . step ) ;
2018-01-04 20:30:03 -08:00
}
2017-10-21 14:31:06 -07:00
2019-07-14 00:06:20 -07:00
const only_install_lib_files = b . option ( bool , " lib-files-only " , " Only install library files " ) orelse false ;
2020-02-07 09:30:16 -08:00
if ( ! only_install_lib_files and ! skip_self_hosted ) {
2019-07-14 00:06:20 -07:00
b . default_step . dependOn ( & exe . step ) ;
exe . install ( ) ;
}
b . installDirectory ( InstallDirectoryOptions {
2019-07-15 14:54:50 -07:00
. source_dir = " lib " ,
2019-07-14 00:06:20 -07:00
. install_dir = . Lib ,
2019-07-15 14:54:50 -07:00
. install_subdir = " zig " ,
2019-11-27 00:30:39 -08:00
. exclude_extensions = & [ _ ] [ ] const u8 { " test.zig " , " README.md " } ,
2019-07-14 00:06:20 -07:00
} ) ;
2017-10-21 14:31:06 -07:00
2017-04-18 22:13:15 -07:00
const test_filter = b . option ( [ ] const u8 , " test-filter " , " Skip tests that do not match filter " ) ;
2019-09-21 20:55:56 -07:00
const is_wine_enabled = b . option ( bool , " enable-wine " , " Use Wine to run cross compiled Windows tests " ) orelse false ;
const is_qemu_enabled = b . option ( bool , " enable-qemu " , " Use QEMU to run cross compiled foreign architecture tests " ) orelse false ;
const glibc_multi_dir = b . option ( [ ] const u8 , " enable-foreign-glibc " , " Provide directory with glibc installations to run cross compiled tests that link glibc " ) ;
2018-07-10 17:18:43 -07:00
const test_stage2_step = b . step ( " test-stage2 " , " Run the stage2 compiler tests " ) ;
test_stage2_step . dependOn ( & test_stage2 . step ) ;
2019-11-23 12:56:05 -08:00
test_step . dependOn ( test_stage2_step ) ;
2018-07-10 17:18:43 -07:00
2018-09-12 11:50:26 -07:00
var chosen_modes : [ 4 ] builtin . Mode = undefined ;
var chosen_mode_index : usize = 0 ;
chosen_modes [ chosen_mode_index ] = builtin . Mode . Debug ;
chosen_mode_index + = 1 ;
if ( ! skip_release_safe ) {
chosen_modes [ chosen_mode_index ] = builtin . Mode . ReleaseSafe ;
chosen_mode_index + = 1 ;
}
if ( ! skip_release_fast ) {
chosen_modes [ chosen_mode_index ] = builtin . Mode . ReleaseFast ;
chosen_mode_index + = 1 ;
}
if ( ! skip_release_small ) {
chosen_modes [ chosen_mode_index ] = builtin . Mode . ReleaseSmall ;
chosen_mode_index + = 1 ;
}
const modes = chosen_modes [ 0 . . chosen_mode_index ] ;
2017-11-07 00:22:27 -08:00
2019-02-26 15:10:40 -08:00
// run stage1 `zig fmt` on this build.zig file just to make sure it works
test_step . dependOn ( & fmt_build_zig . step ) ;
const fmt_step = b . step ( " test-fmt " , " Run zig fmt against build.zig to make sure it works " ) ;
fmt_step . dependOn ( & fmt_build_zig . step ) ;
2019-09-21 20:55:56 -07:00
test_step . dependOn ( tests . addPkgTests ( b , test_filter , " test/stage1/behavior.zig " , " behavior " , " Run the behavior tests " , modes , false , skip_non_native , skip_libc , is_wine_enabled , is_qemu_enabled , glibc_multi_dir ) ) ;
2017-04-19 01:12:22 -07:00
2019-09-25 20:57:47 -07:00
test_step . dependOn ( tests . addPkgTests ( b , test_filter , " lib/std/std.zig " , " std " , " Run the standard library tests " , modes , false , skip_non_native , skip_libc , is_wine_enabled , is_qemu_enabled , glibc_multi_dir ) ) ;
2017-04-19 23:26:36 -07:00
2019-09-25 20:57:47 -07:00
test_step . dependOn ( tests . addPkgTests ( b , test_filter , " lib/std/special/compiler_rt.zig " , " compiler-rt " , " Run the compiler_rt tests " , modes , true , skip_non_native , true , is_wine_enabled , is_qemu_enabled , glibc_multi_dir ) ) ;
2017-08-18 10:51:16 -07:00
2018-07-11 16:38:01 -07:00
test_step . dependOn ( tests . addCompareOutputTests ( b , test_filter , modes ) ) ;
2019-07-16 09:15:46 -07:00
test_step . dependOn ( tests . addStandaloneTests ( b , test_filter , modes ) ) ;
2019-09-03 07:08:39 -07:00
test_step . dependOn ( tests . addStackTraceTests ( b , test_filter , modes ) ) ;
2018-09-17 14:08:56 -07:00
test_step . dependOn ( tests . addCliTests ( b , test_filter , modes ) ) ;
2018-07-11 16:38:01 -07:00
test_step . dependOn ( tests . addAssembleAndLinkTests ( b , test_filter , modes ) ) ;
test_step . dependOn ( tests . addRuntimeSafetyTests ( b , test_filter , modes ) ) ;
2017-11-24 11:56:05 -08:00
test_step . dependOn ( tests . addTranslateCTests ( b , test_filter ) ) ;
2020-01-02 19:45:48 -08:00
test_step . dependOn ( tests . addRunTranslatedCTests ( b , test_filter ) ) ;
2020-03-20 15:33:36 -07:00
// tests for this feature are disabled until we have the self-hosted compiler available
//test_step.dependOn(tests.addGenHTests(b, test_filter));
2019-09-03 07:05:19 -07:00
test_step . dependOn ( tests . addCompileErrorTests ( b , test_filter , modes ) ) ;
2018-07-11 11:09:05 -07:00
test_step . dependOn ( docs_step ) ;
2017-04-18 22:13:15 -07:00
}
2017-12-11 20:34:59 -08:00
2018-11-01 21:07:43 -07:00
fn dependOnLib ( b : * Builder , lib_exe_obj : var , dep : LibraryDep ) void {
2017-12-11 20:34:59 -08:00
for ( dep . libdirs . toSliceConst ( ) ) | lib_dir | {
lib_exe_obj . addLibPath ( lib_dir ) ;
}
2019-05-26 10:17:34 -07:00
const lib_dir = fs . path . join (
2019-02-06 21:42:41 -08:00
b . allocator ,
2019-11-27 00:30:39 -08:00
& [ _ ] [ ] const u8 { dep . prefix , " lib " } ,
2019-02-06 21:42:41 -08:00
) catch unreachable ;
2017-12-23 17:21:57 -08:00
for ( dep . system_libs . toSliceConst ( ) ) | lib | {
2018-11-01 21:07:43 -07:00
const static_bare_name = if ( mem . eql ( u8 , lib , " curses " ) )
2019-11-08 12:56:21 -08:00
@as ( [ ] const u8 , " libncurses.a " )
2018-11-01 21:07:43 -07:00
else
2019-12-08 19:53:51 -08:00
b . fmt ( " lib{}.a " , . { lib } ) ;
2019-05-26 10:17:34 -07:00
const static_lib_name = fs . path . join (
2019-02-06 21:42:41 -08:00
b . allocator ,
2019-11-27 00:30:39 -08:00
& [ _ ] [ ] const u8 { lib_dir , static_bare_name } ,
2019-02-06 21:42:41 -08:00
) catch unreachable ;
2018-11-01 21:07:43 -07:00
const have_static = fileExists ( static_lib_name ) catch unreachable ;
if ( have_static ) {
lib_exe_obj . addObjectFile ( static_lib_name ) ;
} else {
lib_exe_obj . linkSystemLibrary ( lib ) ;
}
2017-12-11 20:34:59 -08:00
}
2017-12-23 17:21:57 -08:00
for ( dep . libs . toSliceConst ( ) ) | lib | {
lib_exe_obj . addObjectFile ( lib ) ;
}
2017-12-11 20:34:59 -08:00
for ( dep . includes . toSliceConst ( ) ) | include_path | {
lib_exe_obj . addIncludeDir ( include_path ) ;
}
}
2018-11-01 21:07:43 -07:00
fn fileExists ( filename : [ ] const u8 ) ! bool {
2020-02-16 10:25:30 -08:00
fs . cwd ( ) . access ( filename , . { } ) catch | err | switch ( err ) {
2019-05-26 20:35:26 -07:00
error . FileNotFound = > return false ,
2018-11-01 21:07:43 -07:00
else = > return err ,
} ;
return true ;
}
2018-07-10 17:18:43 -07:00
fn addCppLib ( b : * Builder , lib_exe_obj : var , cmake_binary_dir : [ ] const u8 , lib_name : [ ] const u8 ) void {
2019-11-27 00:30:39 -08:00
lib_exe_obj . addObjectFile ( fs . path . join ( b . allocator , & [ _ ] [ ] const u8 {
2019-02-06 21:42:41 -08:00
cmake_binary_dir ,
" zig_cpp " ,
2019-12-08 19:53:51 -08:00
b . fmt ( " {}{}{} " , . { lib_exe_obj . target . libPrefix ( ) , lib_name , lib_exe_obj . target . staticLibSuffix ( ) } ) ,
2019-02-06 21:42:41 -08:00
} ) catch unreachable ) ;
2017-12-26 16:44:08 -08:00
}
2018-11-13 05:08:37 -08:00
const LibraryDep = struct {
2018-11-01 21:07:43 -07:00
prefix : [ ] const u8 ,
2017-12-11 20:34:59 -08:00
libdirs : ArrayList ( [ ] const u8 ) ,
libs : ArrayList ( [ ] const u8 ) ,
2017-12-23 17:21:57 -08:00
system_libs : ArrayList ( [ ] const u8 ) ,
2017-12-11 20:34:59 -08:00
includes : ArrayList ( [ ] const u8 ) ,
} ;
2018-05-31 07:56:59 -07:00
fn findLLVM ( b : * Builder , llvm_config_exe : [ ] const u8 ) ! LibraryDep {
2019-11-27 00:30:39 -08:00
const shared_mode = try b . exec ( & [ _ ] [ ] const u8 { llvm_config_exe , " --shared-mode " } ) ;
2018-11-01 21:07:43 -07:00
const is_static = mem . startsWith ( u8 , shared_mode , " static " ) ;
const libs_output = if ( is_static )
2019-11-27 00:30:39 -08:00
try b . exec ( & [ _ ] [ ] const u8 {
2018-11-01 21:07:43 -07:00
llvm_config_exe ,
" --libfiles " ,
" --system-libs " ,
} )
else
2019-11-27 00:30:39 -08:00
try b . exec ( & [ _ ] [ ] const u8 {
2018-11-01 21:07:43 -07:00
llvm_config_exe ,
" --libs " ,
} ) ;
2019-11-27 00:30:39 -08:00
const includes_output = try b . exec ( & [ _ ] [ ] const u8 { llvm_config_exe , " --includedir " } ) ;
const libdir_output = try b . exec ( & [ _ ] [ ] const u8 { llvm_config_exe , " --libdir " } ) ;
const prefix_output = try b . exec ( & [ _ ] [ ] const u8 { llvm_config_exe , " --prefix " } ) ;
2017-12-11 20:34:59 -08:00
2018-11-13 05:08:37 -08:00
var result = LibraryDep {
2019-02-04 12:24:06 -08:00
. prefix = mem . tokenize ( prefix_output , " \r \n " ) . next ( ) . ? ,
2017-12-11 20:34:59 -08:00
. libs = ArrayList ( [ ] const u8 ) . init ( b . allocator ) ,
2017-12-23 17:21:57 -08:00
. system_libs = ArrayList ( [ ] const u8 ) . init ( b . allocator ) ,
2017-12-11 20:34:59 -08:00
. includes = ArrayList ( [ ] const u8 ) . init ( b . allocator ) ,
. libdirs = ArrayList ( [ ] const u8 ) . init ( b . allocator ) ,
} ;
{
2019-02-04 12:24:06 -08:00
var it = mem . tokenize ( libs_output , " \r \n " ) ;
2017-12-11 20:34:59 -08:00
while ( it . next ( ) ) | lib_arg | {
if ( mem . startsWith ( u8 , lib_arg , " -l " ) ) {
2018-01-08 21:07:01 -08:00
try result . system_libs . append ( lib_arg [ 2 . . ] ) ;
2020-02-04 12:04:11 -08:00
} else {
2020-03-03 06:17:37 -08:00
if ( fs . path . isAbsolute ( lib_arg ) ) {
try result . libs . append ( lib_arg ) ;
} else {
if ( mem . endsWith ( u8 , lib_arg , " .lib " ) ) {
lib_arg = lib_arg [ 0 . . lib_arg . len - 4 ] ;
}
try result . system_libs . append ( lib_arg ) ;
2017-12-23 18:19:48 -08:00
}
2017-12-11 20:34:59 -08:00
}
}
}
{
2019-02-04 12:24:06 -08:00
var it = mem . tokenize ( includes_output , " \r \n " ) ;
2017-12-11 20:34:59 -08:00
while ( it . next ( ) ) | include_arg | {
if ( mem . startsWith ( u8 , include_arg , " -I " ) ) {
2018-01-08 21:07:01 -08:00
try result . includes . append ( include_arg [ 2 . . ] ) ;
2017-12-11 20:34:59 -08:00
} else {
2018-01-08 21:07:01 -08:00
try result . includes . append ( include_arg ) ;
2017-12-11 20:34:59 -08:00
}
}
}
{
2019-02-04 12:24:06 -08:00
var it = mem . tokenize ( libdir_output , " \r \n " ) ;
2017-12-11 20:34:59 -08:00
while ( it . next ( ) ) | libdir | {
if ( mem . startsWith ( u8 , libdir , " -L " ) ) {
2018-01-08 21:07:01 -08:00
try result . libdirs . append ( libdir [ 2 . . ] ) ;
2017-12-11 20:34:59 -08:00
} else {
2018-01-08 21:07:01 -08:00
try result . libdirs . append ( libdir ) ;
2017-12-11 20:34:59 -08:00
}
}
}
return result ;
}
2017-12-22 21:29:39 -08:00
2018-05-31 07:56:59 -07:00
fn nextValue ( index : * usize , build_info : [ ] const u8 ) [ ] const u8 {
2018-05-17 20:21:44 -07:00
const start = index . * ;
while ( true ) : ( index . * + = 1 ) {
switch ( build_info [ index . * ] ) {
2018-01-03 19:38:13 -08:00
'\n' = > {
2018-05-17 20:21:44 -07:00
const result = build_info [ start . . index . * ] ;
index . * + = 1 ;
2018-01-03 19:38:13 -08:00
return result ;
} ,
'\r' = > {
2018-05-17 20:21:44 -07:00
const result = build_info [ start . . index . * ] ;
index . * + = 2 ;
2018-01-03 19:38:13 -08:00
return result ;
} ,
else = > continue ,
}
}
2018-01-03 01:55:16 -08:00
}
2018-07-10 17:18:43 -07:00
fn configureStage2 ( b : * Builder , exe : var , ctx : Context ) ! void {
exe . addIncludeDir ( " src " ) ;
exe . addIncludeDir ( ctx . cmake_binary_dir ) ;
addCppLib ( b , exe , ctx . cmake_binary_dir , " zig_cpp " ) ;
if ( ctx . lld_include_dir . len ! = 0 ) {
exe . addIncludeDir ( ctx . lld_include_dir ) ;
2019-02-04 12:24:06 -08:00
var it = mem . tokenize ( ctx . lld_libraries , " ; " ) ;
2018-07-10 17:18:43 -07:00
while ( it . next ( ) ) | lib | {
exe . addObjectFile ( lib ) ;
}
} else {
addCppLib ( b , exe , ctx . cmake_binary_dir , " embedded_lld_wasm " ) ;
addCppLib ( b , exe , ctx . cmake_binary_dir , " embedded_lld_elf " ) ;
addCppLib ( b , exe , ctx . cmake_binary_dir , " embedded_lld_coff " ) ;
addCppLib ( b , exe , ctx . cmake_binary_dir , " embedded_lld_lib " ) ;
}
2020-02-04 00:39:20 -08:00
{
var it = mem . tokenize ( ctx . clang_libraries , " ; " ) ;
while ( it . next ( ) ) | lib | {
exe . addObjectFile ( lib ) ;
}
}
2018-11-01 21:07:43 -07:00
dependOnLib ( b , exe , ctx . llvm ) ;
2018-07-10 17:18:43 -07:00
2020-02-25 22:18:23 -08:00
if ( exe . target . getOsTag ( ) = = . linux ) {
2020-03-17 20:03:45 -07:00
// First we try to static link against gcc libstdc++. If that doesn't work,
// we fall back to -lc++ and cross our fingers.
addCxxKnownPath ( b , ctx , exe , " libstdc++.a " , " " ) catch | err | switch ( err ) {
error . RequiredLibraryNotFound = > {
exe . linkSystemLibrary ( " c++ " ) ;
} ,
else = > | e | return e ,
} ;
2018-07-10 17:18:43 -07:00
exe . linkSystemLibrary ( " pthread " ) ;
2018-12-17 18:19:52 -08:00
} else if ( exe . target . isFreeBSD ( ) ) {
try addCxxKnownPath ( b , ctx , exe , " libc++.a " , null ) ;
exe . linkSystemLibrary ( " pthread " ) ;
2019-01-29 18:47:26 -08:00
} else if ( exe . target . isDarwin ( ) ) {
2018-11-01 21:07:43 -07:00
if ( addCxxKnownPath ( b , ctx , exe , " libgcc_eh.a " , " " ) ) {
// Compiler is GCC.
try addCxxKnownPath ( b , ctx , exe , " libstdc++.a " , null ) ;
exe . linkSystemLibrary ( " pthread " ) ;
// TODO LLD cannot perform this link.
// See https://github.com/ziglang/zig/issues/1535
exe . enableSystemLinkerHack ( ) ;
} else | err | switch ( err ) {
error . RequiredLibraryNotFound = > {
// System compiler, not gcc.
exe . linkSystemLibrary ( " c++ " ) ;
} ,
2020-03-17 20:03:45 -07:00
else = > | e | return e ,
2018-11-01 21:07:43 -07:00
}
2018-07-10 17:18:43 -07:00
}
if ( ctx . dia_guids_lib . len ! = 0 ) {
exe . addObjectFile ( ctx . dia_guids_lib ) ;
}
exe . linkSystemLibrary ( " c " ) ;
}
2018-11-01 21:07:43 -07:00
fn addCxxKnownPath (
b : * Builder ,
ctx : Context ,
exe : var ,
objname : [ ] const u8 ,
errtxt : ? [ ] const u8 ,
) ! void {
2019-11-27 00:30:39 -08:00
const path_padded = try b . exec ( & [ _ ] [ ] const u8 {
2018-11-01 21:07:43 -07:00
ctx . cxx_compiler ,
2019-12-08 19:53:51 -08:00
b . fmt ( " -print-file-name={} " , . { objname } ) ,
2018-11-01 21:07:43 -07:00
} ) ;
2019-02-04 12:24:06 -08:00
const path_unpadded = mem . tokenize ( path_padded , " \r \n " ) . next ( ) . ? ;
2018-11-01 21:07:43 -07:00
if ( mem . eql ( u8 , path_unpadded , objname ) ) {
if ( errtxt ) | msg | {
2019-12-08 19:53:51 -08:00
warn ( " {} " , . { msg } ) ;
2018-11-01 21:07:43 -07:00
} else {
2019-12-08 19:53:51 -08:00
warn ( " Unable to determine path to {} \n " , . { objname } ) ;
2018-11-01 21:07:43 -07:00
}
return error . RequiredLibraryNotFound ;
}
exe . addObjectFile ( path_unpadded ) ;
}
2018-11-13 05:08:37 -08:00
const Context = struct {
2018-07-10 17:18:43 -07:00
cmake_binary_dir : [ ] const u8 ,
cxx_compiler : [ ] const u8 ,
llvm_config_exe : [ ] const u8 ,
lld_include_dir : [ ] const u8 ,
lld_libraries : [ ] const u8 ,
2020-02-04 00:39:20 -08:00
clang_libraries : [ ] const u8 ,
2018-07-10 17:18:43 -07:00
dia_guids_lib : [ ] const u8 ,
llvm : LibraryDep ,
} ;