2017-10-31 08:47:55 +00:00
const std = @import ( " index.zig " ) ;
2017-05-01 17:12:38 +00:00
const builtin = @import ( " builtin " ) ;
2017-10-31 08:47:55 +00:00
const io = std . io ;
const mem = std . mem ;
const debug = std . debug ;
2017-04-13 21:21:00 +00:00
const assert = debug . assert ;
2017-10-31 08:47:55 +00:00
const warn = std . debug . warn ;
const ArrayList = std . ArrayList ;
const HashMap = std . HashMap ;
const Allocator = mem . Allocator ;
const os = std . os ;
2017-04-02 22:19:59 +00:00
const StdIo = os . ChildProcess . StdIo ;
const Term = os . ChildProcess . Term ;
2017-10-31 08:47:55 +00:00
const BufSet = std . BufSet ;
const BufMap = std . BufMap ;
const fmt_lib = std . fmt ;
2017-03-31 09:48:15 +00:00
2018-11-13 13:08:37 +00:00
pub const Builder = struct {
2017-04-17 10:45:44 +00:00
uninstall_tls : TopLevelStep ,
2017-05-01 01:03:23 +00:00
install_tls : TopLevelStep ,
2017-04-17 10:45:44 +00:00
have_uninstall_step : bool ,
2017-05-01 01:03:23 +00:00
have_install_step : bool ,
2018-05-31 14:56:59 +00:00
allocator : * Allocator ,
2017-05-04 18:05:06 +00:00
lib_paths : ArrayList ( [ ] const u8 ) ,
include_paths : ArrayList ( [ ] const u8 ) ,
rpaths : ArrayList ( [ ] const u8 ) ,
2017-04-06 09:34:04 +00:00
user_input_options : UserInputOptionsMap ,
available_options_map : AvailableOptionsMap ,
2017-05-04 18:05:06 +00:00
available_options_list : ArrayList ( AvailableOption ) ,
2017-04-06 09:34:04 +00:00
verbose : bool ,
2017-10-26 03:10:41 +00:00
verbose_tokenize : bool ,
verbose_ast : bool ,
verbose_link : bool ,
verbose_ir : bool ,
verbose_llvm_ir : bool ,
verbose_cimport : bool ,
2017-04-06 09:34:04 +00:00
invalid_user_input : bool ,
2017-04-13 21:21:00 +00:00
zig_exe : [ ] const u8 ,
2018-05-31 14:56:59 +00:00
default_step : * Step ,
2018-11-08 02:22:42 +00:00
env_map : * BufMap ,
2018-05-31 14:56:59 +00:00
top_level_steps : ArrayList ( * TopLevelStep ) ,
2017-04-13 21:21:00 +00:00
prefix : [ ] const u8 ,
2017-12-24 01:21:57 +00:00
search_prefixes : ArrayList ( [ ] const u8 ) ,
2017-04-17 10:45:44 +00:00
lib_dir : [ ] const u8 ,
2017-05-01 01:03:23 +00:00
exe_dir : [ ] const u8 ,
2017-05-04 18:05:06 +00:00
installed_files : ArrayList ( [ ] const u8 ) ,
2017-04-19 05:13:15 +00:00
build_root : [ ] const u8 ,
2017-04-28 06:22:12 +00:00
cache_root : [ ] const u8 ,
2017-05-10 01:20:09 +00:00
release_mode : ? builtin . Mode ,
2017-04-06 09:34:04 +00:00
2018-11-13 13:08:37 +00:00
pub const CStd = enum {
2018-09-06 20:29:35 +00:00
C89 ,
C99 ,
C11 ,
} ;
2017-04-06 09:34:04 +00:00
const UserInputOptionsMap = HashMap ( [ ] const u8 , UserInputOption , mem . hash_slice_u8 , mem . eql_slice_u8 ) ;
const AvailableOptionsMap = HashMap ( [ ] const u8 , AvailableOption , mem . hash_slice_u8 , mem . eql_slice_u8 ) ;
2018-11-13 13:08:37 +00:00
const AvailableOption = struct {
2017-04-06 09:34:04 +00:00
name : [ ] const u8 ,
type_id : TypeId ,
description : [ ] const u8 ,
} ;
2018-11-13 13:08:37 +00:00
const UserInputOption = struct {
2017-04-06 09:34:04 +00:00
name : [ ] const u8 ,
value : UserValue ,
used : bool ,
} ;
2018-11-13 13:08:37 +00:00
const UserValue = union ( enum ) {
2017-12-04 01:43:56 +00:00
Flag : void ,
2017-04-06 09:34:04 +00:00
Scalar : [ ] const u8 ,
2017-05-04 18:05:06 +00:00
List : ArrayList ( [ ] const u8 ) ,
2017-04-06 09:34:04 +00:00
} ;
2018-11-13 13:08:37 +00:00
const TypeId = enum {
2017-04-06 09:34:04 +00:00
Bool ,
Int ,
Float ,
String ,
List ,
} ;
2017-03-31 09:48:15 +00:00
2018-11-13 13:08:37 +00:00
const TopLevelStep = struct {
2017-04-13 21:21:00 +00:00
step : Step ,
description : [ ] const u8 ,
} ;
2018-05-31 14:56:59 +00:00
pub fn init ( allocator : * Allocator , zig_exe : [ ] const u8 , build_root : [ ] const u8 , cache_root : [ ] const u8 ) Builder {
2018-10-15 22:23:47 +00:00
const env_map = allocator . createOne ( BufMap ) catch unreachable ;
env_map . * = os . getEnvMap ( allocator ) catch unreachable ;
2018-11-13 13:08:37 +00:00
var self = Builder {
2017-04-19 05:13:15 +00:00
. zig_exe = zig_exe ,
. build_root = build_root ,
2018-01-09 05:07:01 +00:00
. cache_root = os . path . relative ( allocator , build_root , cache_root ) catch unreachable ,
2017-04-06 09:34:04 +00:00
. verbose = false ,
2017-10-26 03:10:41 +00:00
. verbose_tokenize = false ,
. verbose_ast = false ,
. verbose_link = false ,
. verbose_ir = false ,
. verbose_llvm_ir = false ,
. verbose_cimport = false ,
2017-04-06 09:34:04 +00:00
. invalid_user_input = false ,
2017-03-31 09:48:15 +00:00
. allocator = allocator ,
2017-05-04 18:05:06 +00:00
. lib_paths = ArrayList ( [ ] const u8 ) . init ( allocator ) ,
. include_paths = ArrayList ( [ ] const u8 ) . init ( allocator ) ,
. rpaths = ArrayList ( [ ] const u8 ) . init ( allocator ) ,
2017-04-06 09:34:04 +00:00
. user_input_options = UserInputOptionsMap . init ( allocator ) ,
. available_options_map = AvailableOptionsMap . init ( allocator ) ,
2017-05-04 18:05:06 +00:00
. available_options_list = ArrayList ( AvailableOption ) . init ( allocator ) ,
2018-05-31 14:56:59 +00:00
. top_level_steps = ArrayList ( * TopLevelStep ) . init ( allocator ) ,
2017-04-13 21:21:00 +00:00
. default_step = undefined ,
2018-10-15 22:23:47 +00:00
. env_map = env_map ,
2017-04-13 21:21:00 +00:00
. prefix = undefined ,
2017-12-24 01:21:57 +00:00
. search_prefixes = ArrayList ( [ ] const u8 ) . init ( allocator ) ,
2017-04-17 10:45:44 +00:00
. lib_dir = undefined ,
2017-05-01 01:03:23 +00:00
. exe_dir = undefined ,
2017-05-04 18:05:06 +00:00
. installed_files = ArrayList ( [ ] const u8 ) . init ( allocator ) ,
2018-11-13 13:08:37 +00:00
. uninstall_tls = TopLevelStep {
2017-04-17 10:45:44 +00:00
. step = Step . init ( " uninstall " , allocator , makeUninstall ) ,
. description = " Remove build artifacts from prefix path " ,
} ,
. have_uninstall_step = false ,
2018-11-13 13:08:37 +00:00
. install_tls = TopLevelStep {
2017-05-01 01:03:23 +00:00
. step = Step . initNoOp ( " install " , allocator ) ,
. description = " Copy build artifacts to prefix path " ,
} ,
. have_install_step = false ,
2017-05-10 01:20:09 +00:00
. release_mode = null ,
2017-04-04 05:52:20 +00:00
} ;
self . processNixOSEnvVars ( ) ;
2017-04-13 21:21:00 +00:00
self . default_step = self . step ( " default " , " Build the project " ) ;
2017-04-04 05:52:20 +00:00
return self ;
}
2018-05-31 14:56:59 +00:00
pub fn deinit ( self : * Builder ) void {
2017-04-04 05:52:20 +00:00
self . lib_paths . deinit ( ) ;
self . include_paths . deinit ( ) ;
self . rpaths . deinit ( ) ;
2017-04-13 21:21:00 +00:00
self . env_map . deinit ( ) ;
self . top_level_steps . deinit ( ) ;
2017-03-31 09:48:15 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn setInstallPrefix ( self : * Builder , maybe_prefix : ? [ ] const u8 ) void {
2018-06-10 05:13:51 +00:00
self . prefix = maybe_prefix orelse " /usr/local " ; // TODO better default
2018-01-09 05:07:01 +00:00
self . lib_dir = os . path . join ( self . allocator , self . prefix , " lib " ) catch unreachable ;
self . exe_dir = os . path . join ( self . allocator , self . prefix , " bin " ) catch unreachable ;
2017-03-31 09:48:15 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addExecutable ( self : * Builder , name : [ ] const u8 , root_src : ? [ ] const u8 ) * LibExeObjStep {
2018-12-01 06:21:59 +00:00
return LibExeObjStep . createExecutable ( self , name , root_src , false ) ;
}
pub fn addStaticExecutable ( self : * Builder , name : [ ] const u8 , root_src : ? [ ] const u8 ) * LibExeObjStep {
return LibExeObjStep . createExecutable ( self , name , root_src , true ) ;
2017-03-31 09:48:15 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addObject ( self : * Builder , name : [ ] const u8 , root_src : [ ] const u8 ) * LibExeObjStep {
2017-04-26 23:17:05 +00:00
return LibExeObjStep . createObject ( self , name , root_src ) ;
2017-04-21 05:56:12 +00:00
}
2018-10-15 22:23:47 +00:00
pub fn addSharedLibrary ( self : * Builder , name : [ ] const u8 , root_src : ? [ ] const u8 , ver : Version ) * LibExeObjStep {
2017-04-26 23:17:05 +00:00
return LibExeObjStep . createSharedLibrary ( self , name , root_src , ver ) ;
2017-04-21 05:56:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addStaticLibrary ( self : * Builder , name : [ ] const u8 , root_src : ? [ ] const u8 ) * LibExeObjStep {
2017-04-26 23:17:05 +00:00
return LibExeObjStep . createStaticLibrary ( self , name , root_src ) ;
2017-04-21 05:56:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addTest ( self : * Builder , root_src : [ ] const u8 ) * TestStep {
2018-06-20 15:40:21 +00:00
const test_step = self . allocator . create ( TestStep . init ( self , root_src ) ) catch unreachable ;
2017-04-19 05:13:15 +00:00
return test_step ;
}
2018-05-31 14:56:59 +00:00
pub fn addAssemble ( self : * Builder , name : [ ] const u8 , src : [ ] const u8 ) * LibExeObjStep {
2017-04-26 23:17:05 +00:00
const obj_step = LibExeObjStep . createObject ( self , name , null ) ;
obj_step . addAssemblyFile ( src ) ;
return obj_step ;
2017-04-19 18:00:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addCStaticLibrary ( self : * Builder , name : [ ] const u8 ) * LibExeObjStep {
2017-09-18 06:50:51 +00:00
return LibExeObjStep . createCStaticLibrary ( self , name ) ;
2017-04-13 21:21:00 +00:00
}
2018-10-15 22:23:47 +00:00
pub fn addCSharedLibrary ( self : * Builder , name : [ ] const u8 , ver : Version ) * LibExeObjStep {
2017-09-18 06:50:51 +00:00
return LibExeObjStep . createCSharedLibrary ( self , name , ver ) ;
2017-04-13 21:21:00 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addCExecutable ( self : * Builder , name : [ ] const u8 ) * LibExeObjStep {
2017-09-18 06:50:51 +00:00
return LibExeObjStep . createCExecutable ( self , name ) ;
2017-04-30 23:48:45 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addCObject ( self : * Builder , name : [ ] const u8 , src : [ ] const u8 ) * LibExeObjStep {
2017-09-18 06:50:51 +00:00
return LibExeObjStep . createCObject ( self , name , src ) ;
2017-04-13 21:21:00 +00:00
}
2017-09-26 05:01:49 +00:00
/// ::argv is copied.
2018-05-31 14:56:59 +00:00
pub fn addCommand ( self : * Builder , cwd : ? [ ] const u8 , env_map : * const BufMap , argv : [ ] const [ ] const u8 ) * CommandStep {
2017-09-26 05:01:49 +00:00
return CommandStep . create ( self , cwd , env_map , argv ) ;
2017-04-13 21:21:00 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addWriteFile ( self : * Builder , file_path : [ ] const u8 , data : [ ] const u8 ) * WriteFileStep {
2018-06-20 15:40:21 +00:00
const write_file_step = self . allocator . create ( WriteFileStep . init ( self , file_path , data ) ) catch unreachable ;
2017-04-19 05:13:15 +00:00
return write_file_step ;
}
2018-05-31 14:56:59 +00:00
pub fn addLog ( self : * Builder , comptime format : [ ] const u8 , args : . . . ) * LogStep {
2017-04-19 19:38:12 +00:00
const data = self . fmt ( format , args ) ;
2018-06-20 15:40:21 +00:00
const log_step = self . allocator . create ( LogStep . init ( self , data ) ) catch unreachable ;
2017-04-19 05:13:15 +00:00
return log_step ;
}
2018-05-31 14:56:59 +00:00
pub fn addRemoveDirTree ( self : * Builder , dir_path : [ ] const u8 ) * RemoveDirStep {
2018-06-20 15:40:21 +00:00
const remove_dir_step = self . allocator . create ( RemoveDirStep . init ( self , dir_path ) ) catch unreachable ;
2017-04-20 06:26:36 +00:00
return remove_dir_step ;
}
2018-05-31 14:56:59 +00:00
pub fn version ( self : * const Builder , major : u32 , minor : u32 , patch : u32 ) Version {
2018-11-13 13:08:37 +00:00
return Version {
2017-04-13 21:21:00 +00:00
. major = major ,
. minor = minor ,
. patch = patch ,
2017-12-22 05:50:30 +00:00
} ;
2017-04-13 21:21:00 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addCIncludePath ( self : * Builder , path : [ ] const u8 ) void {
2018-01-09 05:07:01 +00:00
self . include_paths . append ( path ) catch unreachable ;
2017-04-04 05:52:20 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addRPath ( self : * Builder , path : [ ] const u8 ) void {
2018-01-09 05:07:01 +00:00
self . rpaths . append ( path ) catch unreachable ;
2017-04-04 05:52:20 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addLibPath ( self : * Builder , path : [ ] const u8 ) void {
2018-01-09 05:07:01 +00:00
self . lib_paths . append ( path ) catch unreachable ;
2017-04-04 05:52:20 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn make ( self : * Builder , step_names : [ ] const [ ] const u8 ) ! void {
2018-09-11 22:15:08 +00:00
try self . makePath ( self . cache_root ) ;
2018-05-31 14:56:59 +00:00
var wanted_steps = ArrayList ( * Step ) . init ( self . allocator ) ;
2017-04-13 21:21:00 +00:00
defer wanted_steps . deinit ( ) ;
2017-04-03 08:58:19 +00:00
2017-04-13 21:21:00 +00:00
if ( step_names . len = = 0 ) {
2018-06-15 17:49:39 +00:00
try wanted_steps . append ( self . default_step ) ;
2017-04-13 21:21:00 +00:00
} else {
for ( step_names ) | step_name | {
2018-01-07 21:51:46 +00:00
const s = try self . getTopLevelStepByName ( step_name ) ;
2018-01-15 05:01:02 +00:00
try wanted_steps . append ( s ) ;
2017-04-06 09:34:04 +00:00
}
2017-04-13 21:21:00 +00:00
}
2017-04-06 09:34:04 +00:00
2017-04-13 21:21:00 +00:00
for ( wanted_steps . toSliceConst ( ) ) | s | {
2018-01-07 21:51:46 +00:00
try self . makeOneStep ( s ) ;
2017-04-13 21:21:00 +00:00
}
}
2017-04-03 08:58:19 +00:00
2018-05-31 14:56:59 +00:00
pub fn getInstallStep ( self : * Builder ) * Step {
2018-05-10 04:29:49 +00:00
if ( self . have_install_step ) return & self . install_tls . step ;
2017-05-01 01:03:23 +00:00
2018-01-09 05:07:01 +00:00
self . top_level_steps . append ( & self . install_tls ) catch unreachable ;
2017-05-01 01:03:23 +00:00
self . have_install_step = true ;
return & self . install_tls . step ;
}
2018-05-31 14:56:59 +00:00
pub fn getUninstallStep ( self : * Builder ) * Step {
2018-05-10 04:29:49 +00:00
if ( self . have_uninstall_step ) return & self . uninstall_tls . step ;
2017-04-17 10:45:44 +00:00
2018-01-09 05:07:01 +00:00
self . top_level_steps . append ( & self . uninstall_tls ) catch unreachable ;
2017-04-17 10:45:44 +00:00
self . have_uninstall_step = true ;
return & self . uninstall_tls . step ;
}
2018-11-13 13:08:37 +00:00
fn makeUninstall ( uninstall_step : * Step ) anyerror ! void {
2017-04-19 05:13:15 +00:00
const uninstall_tls = @fieldParentPtr ( TopLevelStep , " step " , uninstall_step ) ;
const self = @fieldParentPtr ( Builder , " uninstall_tls " , uninstall_tls ) ;
2017-04-17 10:45:44 +00:00
for ( self . installed_files . toSliceConst ( ) ) | installed_file | {
2017-05-01 01:03:23 +00:00
if ( self . verbose ) {
2017-10-31 08:47:55 +00:00
warn ( " rm {} \n " , installed_file ) ;
2017-05-01 01:03:23 +00:00
}
2018-08-21 20:07:28 +00:00
_ = os . deleteFile ( installed_file ) ;
2017-04-17 10:45:44 +00:00
}
// TODO remove empty directories
}
2018-11-13 13:08:37 +00:00
fn makeOneStep ( self : * Builder , s : * Step ) anyerror ! void {
2017-04-13 21:21:00 +00:00
if ( s . loop_flag ) {
2017-10-31 08:47:55 +00:00
warn ( " Dependency loop detected: \n {} \n " , s . name ) ;
2017-04-13 21:21:00 +00:00
return error . DependencyLoopDetected ;
}
s . loop_flag = true ;
2017-04-03 08:58:19 +00:00
2017-04-13 21:21:00 +00:00
for ( s . dependencies . toSlice ( ) ) | dep | {
2018-01-07 22:28:20 +00:00
self . makeOneStep ( dep ) catch | err | {
2017-04-13 21:21:00 +00:00
if ( err = = error . DependencyLoopDetected ) {
2017-10-31 08:47:55 +00:00
warn ( " {} \n " , s . name ) ;
2017-04-04 05:52:20 +00:00
}
2017-04-13 21:21:00 +00:00
return err ;
} ;
}
2017-04-04 05:52:20 +00:00
2017-04-13 21:21:00 +00:00
s . loop_flag = false ;
2017-04-04 05:52:20 +00:00
2018-01-07 21:51:46 +00:00
try s . make ( ) ;
2017-04-13 21:21:00 +00:00
}
2017-04-04 05:52:20 +00:00
2018-05-31 14:56:59 +00:00
fn getTopLevelStepByName ( self : * Builder , name : [ ] const u8 ) ! * Step {
2017-04-13 21:21:00 +00:00
for ( self . top_level_steps . toSliceConst ( ) ) | top_level_step | {
if ( mem . eql ( u8 , top_level_step . step . name , name ) ) {
return & top_level_step . step ;
2017-04-06 09:34:04 +00:00
}
2017-04-04 05:52:20 +00:00
}
2017-10-31 08:47:55 +00:00
warn ( " Cannot run step '{}' because it does not exist \n " , name ) ;
2017-04-13 21:21:00 +00:00
return error . InvalidStepName ;
2017-04-04 05:52:20 +00:00
}
2018-05-31 14:56:59 +00:00
fn processNixOSEnvVars ( self : * Builder ) void {
2017-10-15 05:23:10 +00:00
if ( os . getEnvVarOwned ( self . allocator , " NIX_CFLAGS_COMPILE " ) ) | nix_cflags_compile | {
2017-10-06 21:21:21 +00:00
var it = mem . split ( nix_cflags_compile , " " ) ;
2017-04-04 05:52:20 +00:00
while ( true ) {
2018-06-10 05:13:51 +00:00
const word = it . next ( ) orelse break ;
2017-04-04 05:52:20 +00:00
if ( mem . eql ( u8 , word , " -isystem " ) ) {
2018-06-10 05:13:51 +00:00
const include_path = it . next ( ) orelse {
2017-10-31 08:47:55 +00:00
warn ( " Expected argument after -isystem in NIX_CFLAGS_COMPILE \n " ) ;
2017-04-04 05:52:20 +00:00
break ;
} ;
self . addCIncludePath ( include_path ) ;
} else {
2017-10-31 08:47:55 +00:00
warn ( " Unrecognized C flag from NIX_CFLAGS_COMPILE: {} \n " , word ) ;
2017-04-04 05:52:20 +00:00
break ;
}
}
2017-10-15 05:23:10 +00:00
} else | err | {
assert ( err = = error . EnvironmentVariableNotFound ) ;
2017-04-04 05:52:20 +00:00
}
2017-10-15 05:23:10 +00:00
if ( os . getEnvVarOwned ( self . allocator , " NIX_LDFLAGS " ) ) | nix_ldflags | {
2017-10-06 21:21:21 +00:00
var it = mem . split ( nix_ldflags , " " ) ;
2017-04-04 05:52:20 +00:00
while ( true ) {
2018-06-10 05:13:51 +00:00
const word = it . next ( ) orelse break ;
2017-04-04 05:52:20 +00:00
if ( mem . eql ( u8 , word , " -rpath " ) ) {
2018-06-10 05:13:51 +00:00
const rpath = it . next ( ) orelse {
2017-10-31 08:47:55 +00:00
warn ( " Expected argument after -rpath in NIX_LDFLAGS \n " ) ;
2017-04-04 05:52:20 +00:00
break ;
} ;
self . addRPath ( rpath ) ;
} else if ( word . len > 2 and word [ 0 ] = = '-' and word [ 1 ] = = 'L' ) {
2017-05-19 14:39:59 +00:00
const lib_path = word [ 2 . . ] ;
2017-04-04 05:52:20 +00:00
self . addLibPath ( lib_path ) ;
} else {
2017-10-31 08:47:55 +00:00
warn ( " Unrecognized C flag from NIX_LDFLAGS: {} \n " , word ) ;
2017-04-04 05:52:20 +00:00
break ;
}
2017-04-02 22:19:59 +00:00
}
2017-10-15 05:23:10 +00:00
} else | err | {
assert ( err = = error . EnvironmentVariableNotFound ) ;
2017-03-31 09:48:15 +00:00
}
}
2017-04-06 09:34:04 +00:00
2018-05-31 14:56:59 +00:00
pub fn option ( self : * Builder , comptime T : type , name : [ ] const u8 , description : [ ] const u8 ) ? T {
2017-04-19 05:13:15 +00:00
const type_id = comptime typeToEnum ( T ) ;
2018-11-13 13:08:37 +00:00
const available_option = AvailableOption {
2017-04-06 09:34:04 +00:00
. name = name ,
. type_id = type_id ,
. description = description ,
} ;
2018-01-09 05:07:01 +00:00
if ( ( self . available_options_map . put ( name , available_option ) catch unreachable ) ! = null ) {
2017-04-06 09:34:04 +00:00
debug . panic ( " Option '{}' declared twice " , name ) ;
}
2018-01-09 05:07:01 +00:00
self . available_options_list . append ( available_option ) catch unreachable ;
2017-04-06 09:34:04 +00:00
2018-06-10 05:13:51 +00:00
const entry = self . user_input_options . get ( name ) orelse return null ;
2017-04-06 09:34:04 +00:00
entry . value . used = true ;
switch ( type_id ) {
TypeId . Bool = > switch ( entry . value . value ) {
UserValue . Flag = > return true ,
UserValue . Scalar = > | s | {
if ( mem . eql ( u8 , s , " true " ) ) {
return true ;
} else if ( mem . eql ( u8 , s , " false " ) ) {
return false ;
} else {
2017-10-31 08:47:55 +00:00
warn ( " Expected -D{} to be a boolean, but received '{}' \n " , name , s ) ;
2017-04-06 09:34:04 +00:00
self . markInvalidUserInput ( ) ;
return null ;
}
} ,
UserValue . List = > {
2017-10-31 08:47:55 +00:00
warn ( " Expected -D{} to be a boolean, but received a list. \n " , name ) ;
2017-04-06 09:34:04 +00:00
self . markInvalidUserInput ( ) ;
return null ;
} ,
} ,
TypeId . Int = > debug . panic ( " TODO integer options to build script " ) ,
TypeId . Float = > debug . panic ( " TODO float options to build script " ) ,
2017-04-19 05:13:15 +00:00
TypeId . String = > switch ( entry . value . value ) {
UserValue . Flag = > {
2017-10-31 08:47:55 +00:00
warn ( " Expected -D{} to be a string, but received a boolean. \n " , name ) ;
2017-04-19 05:13:15 +00:00
self . markInvalidUserInput ( ) ;
return null ;
} ,
UserValue . List = > {
2017-10-31 08:47:55 +00:00
warn ( " Expected -D{} to be a string, but received a list. \n " , name ) ;
2017-04-19 05:13:15 +00:00
self . markInvalidUserInput ( ) ;
return null ;
} ,
UserValue . Scalar = > | s | return s ,
} ,
2017-04-06 09:34:04 +00:00
TypeId . List = > debug . panic ( " TODO list options to build script " ) ,
}
}
2018-05-31 14:56:59 +00:00
pub fn step ( self : * Builder , name : [ ] const u8 , description : [ ] const u8 ) * Step {
2018-11-13 13:08:37 +00:00
const step_info = self . allocator . create ( TopLevelStep {
2017-04-13 21:21:00 +00:00
. step = Step . initNoOp ( name , self . allocator ) ,
. description = description ,
2018-06-20 15:40:21 +00:00
} ) catch unreachable ;
2018-01-09 05:07:01 +00:00
self . top_level_steps . append ( step_info ) catch unreachable ;
2017-04-13 21:21:00 +00:00
return & step_info . step ;
}
2018-05-31 14:56:59 +00:00
pub fn standardReleaseOptions ( self : * Builder ) builtin . Mode {
2017-05-10 01:20:09 +00:00
if ( self . release_mode ) | mode | return mode ;
2018-06-10 05:13:51 +00:00
const release_safe = self . option ( bool , " release-safe " , " optimizations on and safety on " ) orelse false ;
const release_fast = self . option ( bool , " release-fast " , " optimizations on and safety off " ) orelse false ;
const release_small = self . option ( bool , " release-small " , " size optimizations on and safety off " ) orelse false ;
2017-05-02 21:34:21 +00:00
2018-05-26 22:16:39 +00:00
const mode = if ( release_safe and ! release_fast and ! release_small ) builtin . Mode . ReleaseSafe else if ( release_fast and ! release_safe and ! release_small ) builtin . Mode . ReleaseFast else if ( release_small and ! release_fast and ! release_safe ) builtin . Mode . ReleaseSmall else if ( ! release_fast and ! release_safe and ! release_small ) builtin . Mode . Debug else x : {
2018-04-16 00:26:10 +00:00
warn ( " Multiple release modes (of -Drelease-safe, -Drelease-fast and -Drelease-small) " ) ;
2017-05-02 21:34:21 +00:00
self . markInvalidUserInput ( ) ;
2017-12-22 05:50:30 +00:00
break : x builtin . Mode . Debug ;
2017-05-10 01:20:09 +00:00
} ;
self . release_mode = mode ;
return mode ;
2017-05-02 21:34:21 +00:00
}
2018-08-03 21:22:17 +00:00
pub fn addUserInputOption ( self : * Builder , name : [ ] const u8 , value : [ ] const u8 ) ! bool {
const gop = try self . user_input_options . getOrPut ( name ) ;
if ( ! gop . found_existing ) {
2018-11-13 13:08:37 +00:00
gop . kv . value = UserInputOption {
2018-08-03 21:22:17 +00:00
. name = name ,
2018-11-13 13:08:37 +00:00
. value = UserValue { . Scalar = value } ,
2018-08-03 21:22:17 +00:00
. used = false ,
} ;
return false ;
}
// option already exists
switch ( gop . kv . value . value ) {
UserValue . Scalar = > | s | {
// turn it into a list
var list = ArrayList ( [ ] const u8 ) . init ( self . allocator ) ;
list . append ( s ) catch unreachable ;
list . append ( value ) catch unreachable ;
2018-11-13 13:08:37 +00:00
_ = self . user_input_options . put ( name , UserInputOption {
2018-08-03 21:22:17 +00:00
. name = name ,
2018-11-13 13:08:37 +00:00
. value = UserValue { . List = list } ,
2018-08-03 21:22:17 +00:00
. used = false ,
} ) catch unreachable ;
} ,
UserValue . List = > | * list | {
// append to the list
list . append ( value ) catch unreachable ;
2018-11-13 13:08:37 +00:00
_ = self . user_input_options . put ( name , UserInputOption {
2018-08-03 21:22:17 +00:00
. name = name ,
2018-11-13 13:08:37 +00:00
. value = UserValue { . List = list . * } ,
2018-08-03 21:22:17 +00:00
. used = false ,
} ) catch unreachable ;
} ,
UserValue . Flag = > {
warn ( " Option '-D{}={}' conflicts with flag '-D{}'. \n " , name , value , name ) ;
return true ;
} ,
2017-04-06 09:34:04 +00:00
}
return false ;
}
2018-08-03 21:22:17 +00:00
pub fn addUserInputFlag ( self : * Builder , name : [ ] const u8 ) ! bool {
const gop = try self . user_input_options . getOrPut ( name ) ;
if ( ! gop . found_existing ) {
2018-11-13 13:08:37 +00:00
gop . kv . value = UserInputOption {
2018-08-03 21:22:17 +00:00
. name = name ,
2018-11-13 13:08:37 +00:00
. value = UserValue { . Flag = { } } ,
2018-08-03 21:22:17 +00:00
. used = false ,
} ;
return false ;
}
// option already exists
switch ( gop . kv . value . value ) {
UserValue . Scalar = > | s | {
warn ( " Flag '-D{}' conflicts with option '-D{}={}'. \n " , name , name , s ) ;
return true ;
} ,
UserValue . List = > {
warn ( " Flag '-D{}' conflicts with multiple options of the same name. \n " , name ) ;
return true ;
} ,
UserValue . Flag = > { } ,
2017-04-06 09:34:04 +00:00
}
return false ;
}
2018-01-25 09:10:11 +00:00
fn typeToEnum ( comptime T : type ) TypeId {
2017-12-22 05:50:30 +00:00
return switch ( @typeId ( T ) ) {
2017-05-17 16:26:35 +00:00
builtin . TypeId . Int = > TypeId . Int ,
builtin . TypeId . Float = > TypeId . Float ,
builtin . TypeId . Bool = > TypeId . Bool ,
else = > switch ( T ) {
[ ] const u8 = > TypeId . String ,
[ ] const [ ] const u8 = > TypeId . List ,
else = > @compileError ( " Unsupported type: " + + @typeName ( T ) ) ,
} ,
2017-12-22 05:50:30 +00:00
} ;
2017-04-06 09:34:04 +00:00
}
2018-05-31 14:56:59 +00:00
fn markInvalidUserInput ( self : * Builder ) void {
2017-04-06 09:34:04 +00:00
self . invalid_user_input = true ;
}
2018-01-25 09:10:11 +00:00
pub fn typeIdName ( id : TypeId ) [ ] const u8 {
2017-04-06 09:34:04 +00:00
return switch ( id ) {
2017-04-06 22:07:38 +00:00
TypeId . Bool = > " bool " ,
TypeId . Int = > " int " ,
TypeId . Float = > " float " ,
TypeId . String = > " string " ,
TypeId . List = > " list " ,
2017-04-06 09:34:04 +00:00
} ;
}
2018-05-31 14:56:59 +00:00
pub fn validateUserInputDidItFail ( self : * Builder ) bool {
2017-04-06 09:34:04 +00:00
// make sure all args are used
var it = self . user_input_options . iterator ( ) ;
while ( true ) {
2018-06-10 05:13:51 +00:00
const entry = it . next ( ) orelse break ;
2017-04-06 09:34:04 +00:00
if ( ! entry . value . used ) {
2017-10-31 08:47:55 +00:00
warn ( " Invalid option: -D{} \n \n " , entry . key ) ;
2017-04-06 09:34:04 +00:00
self . markInvalidUserInput ( ) ;
}
}
return self . invalid_user_input ;
}
2017-04-17 06:58:42 +00:00
2018-05-31 14:56:59 +00:00
fn spawnChild ( self : * Builder , argv : [ ] const [ ] const u8 ) ! void {
2018-10-15 22:23:47 +00:00
return self . spawnChildEnvMap ( null , self . env_map , argv ) ;
2017-04-17 07:20:56 +00:00
}
2018-01-25 09:10:11 +00:00
fn printCmd ( cwd : ? [ ] const u8 , argv : [ ] const [ ] const u8 ) void {
2017-10-31 08:47:55 +00:00
if ( cwd ) | yes_cwd | warn ( " cd {} && " , yes_cwd ) ;
2017-10-26 03:10:41 +00:00
for ( argv ) | arg | {
2017-10-31 08:47:55 +00:00
warn ( " {} " , arg ) ;
2017-10-26 03:10:41 +00:00
}
2017-10-31 08:47:55 +00:00
warn ( " \n " ) ;
2017-10-26 03:10:41 +00:00
}
2018-05-31 14:56:59 +00:00
fn spawnChildEnvMap ( self : * Builder , cwd : ? [ ] const u8 , env_map : * const BufMap , argv : [ ] const [ ] const u8 ) ! void {
2017-04-17 06:58:42 +00:00
if ( self . verbose ) {
2017-10-26 03:10:41 +00:00
printCmd ( cwd , argv ) ;
2017-04-17 06:58:42 +00:00
}
2018-01-09 05:07:01 +00:00
const child = os . ChildProcess . init ( argv , self . allocator ) catch unreachable ;
2017-09-26 05:01:49 +00:00
defer child . deinit ( ) ;
2017-04-17 06:58:42 +00:00
2017-09-26 05:01:49 +00:00
child . cwd = cwd ;
child . env_map = env_map ;
2018-01-07 22:28:20 +00:00
const term = child . spawnAndWait ( ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " Unable to spawn {}: {} \n " , argv [ 0 ] , @errorName ( err ) ) ;
2017-04-21 05:56:12 +00:00
return err ;
} ;
2017-09-26 05:01:49 +00:00
2017-04-17 06:58:42 +00:00
switch ( term ) {
2017-09-08 03:10:23 +00:00
Term . Exited = > | code | {
2017-04-17 06:58:42 +00:00
if ( code ! = 0 ) {
2017-10-31 08:47:55 +00:00
warn ( " The following command exited with error code {}: \n " , code ) ;
2017-10-26 03:10:41 +00:00
printCmd ( cwd , argv ) ;
2017-04-21 05:56:12 +00:00
return error . UncleanExit ;
2017-04-17 06:58:42 +00:00
}
} ,
else = > {
2017-10-31 08:47:55 +00:00
warn ( " The following command terminated unexpectedly: \n " ) ;
2017-10-26 03:10:41 +00:00
printCmd ( cwd , argv ) ;
2017-04-21 05:56:12 +00:00
return error . UncleanExit ;
2017-04-17 06:58:42 +00:00
} ,
2017-12-22 05:50:30 +00:00
}
2017-04-17 06:58:42 +00:00
}
2017-04-17 10:45:44 +00:00
2018-05-31 14:56:59 +00:00
pub fn makePath ( self : * Builder , path : [ ] const u8 ) ! void {
2018-01-07 22:28:20 +00:00
os . makePath ( self . allocator , self . pathFromRoot ( path ) ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " Unable to create path {}: {} \n " , path , @errorName ( err ) ) ;
2017-04-30 17:01:35 +00:00
return err ;
} ;
}
2018-05-31 14:56:59 +00:00
pub fn installArtifact ( self : * Builder , artifact : * LibExeObjStep ) void {
2017-05-01 02:09:44 +00:00
self . getInstallStep ( ) . dependOn ( & self . addInstallArtifact ( artifact ) . step ) ;
2017-04-17 10:45:44 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addInstallArtifact ( self : * Builder , artifact : * LibExeObjStep ) * InstallArtifactStep {
2017-09-18 06:50:51 +00:00
return InstallArtifactStep . create ( self , artifact ) ;
2017-05-01 01:03:23 +00:00
}
///::dest_rel_path is relative to prefix path or it can be an absolute path
2018-05-31 14:56:59 +00:00
pub fn installFile ( self : * Builder , src_path : [ ] const u8 , dest_rel_path : [ ] const u8 ) void {
2017-05-01 01:03:23 +00:00
self . getInstallStep ( ) . dependOn ( & self . addInstallFile ( src_path , dest_rel_path ) . step ) ;
}
///::dest_rel_path is relative to prefix path or it can be an absolute path
2018-05-31 14:56:59 +00:00
pub fn addInstallFile ( self : * Builder , src_path : [ ] const u8 , dest_rel_path : [ ] const u8 ) * InstallFileStep {
2018-01-09 05:07:01 +00:00
const full_dest_path = os . path . resolve ( self . allocator , self . prefix , dest_rel_path ) catch unreachable ;
2017-05-01 01:03:23 +00:00
self . pushInstalledFile ( full_dest_path ) ;
2017-04-17 10:45:44 +00:00
2018-06-20 15:40:21 +00:00
const install_step = self . allocator . create ( InstallFileStep . init ( self , src_path , full_dest_path ) ) catch unreachable ;
2017-04-17 10:45:44 +00:00
return install_step ;
}
2018-05-31 14:56:59 +00:00
pub fn pushInstalledFile ( self : * Builder , full_path : [ ] const u8 ) void {
2017-04-17 10:45:44 +00:00
_ = self . getUninstallStep ( ) ;
2018-01-09 05:07:01 +00:00
self . installed_files . append ( full_path ) catch unreachable ;
2017-04-17 10:45:44 +00:00
}
2018-05-31 14:56:59 +00:00
fn copyFile ( self : * Builder , source_path : [ ] const u8 , dest_path : [ ] const u8 ) ! void {
2018-07-26 03:16:13 +00:00
return self . copyFileMode ( source_path , dest_path , os . File . default_mode ) ;
2017-05-01 02:09:44 +00:00
}
2018-07-26 03:16:13 +00:00
fn copyFileMode ( self : * Builder , source_path : [ ] const u8 , dest_path : [ ] const u8 , mode : os . File . Mode ) ! void {
2017-05-01 02:09:44 +00:00
if ( self . verbose ) {
2017-10-31 08:47:55 +00:00
warn ( " cp {} {} \n " , source_path , dest_path ) ;
2017-05-01 02:09:44 +00:00
}
2018-06-14 20:15:32 +00:00
const dirname = os . path . dirname ( dest_path ) orelse " . " ;
2017-04-30 22:56:24 +00:00
const abs_source_path = self . pathFromRoot ( source_path ) ;
2018-01-07 22:28:20 +00:00
os . makePath ( self . allocator , dirname ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " Unable to create path {}: {} \n " , dirname , @errorName ( err ) ) ;
2017-05-01 02:09:44 +00:00
return err ;
2017-04-23 15:09:26 +00:00
} ;
2018-10-01 17:43:25 +00:00
os . copyFileMode ( abs_source_path , dest_path , mode ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " Unable to copy {} to {}: {} \n " , abs_source_path , dest_path , @errorName ( err ) ) ;
2017-05-01 02:09:44 +00:00
return err ;
2017-04-17 10:45:44 +00:00
} ;
}
2017-04-19 05:13:15 +00:00
2018-05-31 14:56:59 +00:00
fn pathFromRoot ( self : * Builder , rel_path : [ ] const u8 ) [ ] u8 {
2018-01-09 05:07:01 +00:00
return os . path . resolve ( self . allocator , self . build_root , rel_path ) catch unreachable ;
2017-04-19 05:13:15 +00:00
}
2017-04-19 19:38:12 +00:00
2018-05-31 14:56:59 +00:00
pub fn fmt ( self : * Builder , comptime format : [ ] const u8 , args : . . . ) [ ] u8 {
2018-01-09 05:07:01 +00:00
return fmt_lib . allocPrint ( self . allocator , format , args ) catch unreachable ;
2017-04-19 19:38:12 +00:00
}
2017-10-16 05:14:28 +00:00
2018-05-31 14:56:59 +00:00
fn getCCExe ( self : * Builder ) [ ] const u8 {
2017-10-16 05:14:28 +00:00
if ( builtin . environ = = builtin . Environ . msvc ) {
return " cl.exe " ;
} else {
2018-05-26 22:16:39 +00:00
return os . getEnvVarOwned ( self . allocator , " CC " ) catch | err | if ( err = = error . EnvironmentVariableNotFound ) ( [ ] const u8 ) ( " cc " ) else debug . panic ( " Unable to get environment variable: {} " , err ) ;
2017-10-16 05:14:28 +00:00
}
}
2017-12-12 21:03:20 +00:00
2018-05-31 14:56:59 +00:00
pub fn findProgram ( self : * Builder , names : [ ] const [ ] const u8 , paths : [ ] const [ ] const u8 ) ! [ ] const u8 {
2017-12-24 01:21:57 +00:00
// TODO report error for ambiguous situations
2018-11-13 13:08:37 +00:00
const exe_extension = ( Target { . Native = { } } ) . exeFileExt ( ) ;
2017-12-24 01:21:57 +00:00
for ( self . search_prefixes . toSliceConst ( ) ) | search_prefix | {
for ( names ) | name | {
if ( os . path . isAbsolute ( name ) ) {
return name ;
}
2018-05-10 04:29:49 +00:00
const full_path = try os . path . join ( self . allocator , search_prefix , " bin " , self . fmt ( " {}{} " , name , exe_extension ) ) ;
2017-12-24 01:21:57 +00:00
if ( os . path . real ( self . allocator , full_path ) ) | real_path | {
return real_path ;
} else | _ | {
continue ;
}
}
}
2017-12-12 21:03:20 +00:00
if ( self . env_map . get ( " PATH " ) ) | PATH | {
for ( names ) | name | {
if ( os . path . isAbsolute ( name ) ) {
return name ;
}
2018-11-13 13:08:37 +00:00
var it = mem . split ( PATH , [ ] u8 { os . path . delimiter } ) ;
2017-12-12 21:03:20 +00:00
while ( it . next ( ) ) | path | {
2018-01-07 21:51:46 +00:00
const full_path = try os . path . join ( self . allocator , path , self . fmt ( " {}{} " , name , exe_extension ) ) ;
2017-12-12 21:03:20 +00:00
if ( os . path . real ( self . allocator , full_path ) ) | real_path | {
return real_path ;
} else | _ | {
continue ;
}
}
}
}
for ( names ) | name | {
if ( os . path . isAbsolute ( name ) ) {
return name ;
}
for ( paths ) | path | {
2018-01-07 21:51:46 +00:00
const full_path = try os . path . join ( self . allocator , path , self . fmt ( " {}{} " , name , exe_extension ) ) ;
2017-12-12 21:03:20 +00:00
if ( os . path . real ( self . allocator , full_path ) ) | real_path | {
return real_path ;
} else | _ | {
continue ;
}
}
}
return error . FileNotFound ;
}
2018-05-31 14:56:59 +00:00
pub fn exec ( self : * Builder , argv : [ ] const [ ] const u8 ) ! [ ] u8 {
2017-12-12 21:03:20 +00:00
const max_output_size = 100 * 1024 ;
2018-01-12 07:12:11 +00:00
const result = try os . ChildProcess . exec ( self . allocator , argv , null , null , max_output_size ) ;
2017-12-12 21:03:20 +00:00
switch ( result . term ) {
os . ChildProcess . Term . Exited = > | code | {
if ( code ! = 0 ) {
warn ( " The following command exited with error code {}: \n " , code ) ;
printCmd ( null , argv ) ;
warn ( " stderr:{} \n " , result . stderr ) ;
std . debug . panic ( " command failed " ) ;
}
return result . stdout ;
} ,
else = > {
warn ( " The following command terminated unexpectedly: \n " ) ;
printCmd ( null , argv ) ;
warn ( " stderr:{} \n " , result . stderr ) ;
std . debug . panic ( " command failed " ) ;
} ,
}
}
2017-12-24 01:21:57 +00:00
2018-05-31 14:56:59 +00:00
pub fn addSearchPrefix ( self : * Builder , search_prefix : [ ] const u8 ) void {
2018-01-09 05:07:01 +00:00
self . search_prefixes . append ( search_prefix ) catch unreachable ;
2017-12-24 01:21:57 +00:00
}
2017-04-13 21:21:00 +00:00
} ;
2017-04-06 09:34:04 +00:00
2018-11-13 13:08:37 +00:00
const Version = struct {
2017-04-13 21:21:00 +00:00
major : u32 ,
minor : u32 ,
patch : u32 ,
2017-03-31 09:48:15 +00:00
} ;
2018-11-13 13:08:37 +00:00
const CrossTarget = struct {
2017-05-01 17:12:38 +00:00
arch : builtin . Arch ,
os : builtin . Os ,
environ : builtin . Environ ,
2017-04-03 08:58:19 +00:00
} ;
2018-11-13 13:08:37 +00:00
pub const Target = union ( enum ) {
2017-12-04 01:43:56 +00:00
Native : void ,
2017-04-03 08:58:19 +00:00
Cross : CrossTarget ,
2017-04-16 18:14:11 +00:00
2018-05-31 14:56:59 +00:00
pub fn oFileExt ( self : * const Target ) [ ] const u8 {
2018-05-10 04:29:49 +00:00
const environ = switch ( self . * ) {
2017-05-01 17:12:38 +00:00
Target . Native = > builtin . environ ,
2017-04-16 18:14:11 +00:00
Target . Cross = > | t | t . environ ,
} ;
return switch ( environ ) {
2017-05-01 17:12:38 +00:00
builtin . Environ . msvc = > " .obj " ,
2017-04-16 18:14:11 +00:00
else = > " .o " ,
} ;
}
2017-04-19 18:00:12 +00:00
2018-05-31 14:56:59 +00:00
pub fn exeFileExt ( self : * const Target ) [ ] const u8 {
2017-09-23 21:59:30 +00:00
return switch ( self . getOs ( ) ) {
builtin . Os . windows = > " .exe " ,
else = > " " ,
} ;
2017-12-27 00:44:08 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn libFileExt ( self : * const Target ) [ ] const u8 {
2017-12-27 00:44:08 +00:00
return switch ( self . getOs ( ) ) {
builtin . Os . windows = > " .lib " ,
else = > " .a " ,
} ;
2017-09-23 21:59:30 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn getOs ( self : * const Target ) builtin . Os {
2018-05-10 04:29:49 +00:00
return switch ( self . * ) {
2017-05-01 17:12:38 +00:00
Target . Native = > builtin . os ,
2017-04-19 18:00:12 +00:00
Target . Cross = > | t | t . os ,
} ;
2017-09-23 21:59:30 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn isDarwin ( self : * const Target ) bool {
2017-09-23 21:59:30 +00:00
return switch ( self . getOs ( ) ) {
2018-05-26 22:16:39 +00:00
builtin . Os . ios , builtin . Os . macosx = > true ,
2017-09-23 21:59:30 +00:00
else = > false ,
2017-04-19 18:00:12 +00:00
} ;
}
2017-10-16 05:14:28 +00:00
2018-05-31 14:56:59 +00:00
pub fn isWindows ( self : * const Target ) bool {
2017-10-16 05:14:28 +00:00
return switch ( self . getOs ( ) ) {
builtin . Os . windows = > true ,
else = > false ,
} ;
}
2018-10-17 19:18:50 +00:00
pub fn isFreeBSD ( self : * const Target ) bool {
return switch ( self . getOs ( ) ) {
builtin . Os . freebsd = > true ,
else = > false ,
} ;
}
2018-05-31 14:56:59 +00:00
pub fn wantSharedLibSymLinks ( self : * const Target ) bool {
2017-10-16 05:14:28 +00:00
return ! self . isWindows ( ) ;
}
2017-04-03 08:58:19 +00:00
} ;
2018-11-13 13:08:37 +00:00
pub const LibExeObjStep = struct {
2017-04-13 21:21:00 +00:00
step : Step ,
2018-05-31 14:56:59 +00:00
builder : * Builder ,
2017-03-31 09:48:15 +00:00
name : [ ] const u8 ,
2017-04-03 08:58:19 +00:00
target : Target ,
2017-04-04 05:52:20 +00:00
link_libs : BufSet ,
2017-09-18 06:50:51 +00:00
linker_script : ? [ ] const u8 ,
out_filename : [ ] const u8 ,
2017-04-19 05:13:15 +00:00
output_path : ? [ ] const u8 ,
2017-09-18 06:50:51 +00:00
static : bool ,
2017-04-21 05:56:12 +00:00
version : Version ,
2017-09-18 06:50:51 +00:00
object_files : ArrayList ( [ ] const u8 ) ,
build_mode : builtin . Mode ,
kind : Kind ,
2017-05-01 02:09:44 +00:00
major_only_filename : [ ] const u8 ,
name_only_filename : [ ] const u8 ,
2017-09-18 06:50:51 +00:00
strip : bool ,
full_path_libs : ArrayList ( [ ] const u8 ) ,
need_flat_namespace_hack : bool ,
is_zig : bool ,
cflags : ArrayList ( [ ] const u8 ) ,
include_dirs : ArrayList ( [ ] const u8 ) ,
2017-12-12 04:34:59 +00:00
lib_paths : ArrayList ( [ ] const u8 ) ,
2017-09-18 06:50:51 +00:00
disable_libc : bool ,
2017-09-23 21:59:30 +00:00
frameworks : BufSet ,
2018-01-05 04:43:46 +00:00
verbose_link : bool ,
2018-07-25 01:28:54 +00:00
no_rosegment : bool ,
2018-09-06 20:29:35 +00:00
c_std : Builder . CStd ,
2017-09-18 06:50:51 +00:00
// zig only stuff
root_src : ? [ ] const u8 ,
output_h_path : ? [ ] const u8 ,
out_h_filename : [ ] const u8 ,
2017-05-04 18:05:06 +00:00
assembly_files : ArrayList ( [ ] const u8 ) ,
packages : ArrayList ( Pkg ) ,
2018-07-08 04:00:05 +00:00
build_options_contents : std . Buffer ,
2018-11-02 04:07:43 +00:00
system_linker_hack : bool ,
2017-05-01 20:35:10 +00:00
2017-09-18 06:50:51 +00:00
// C only stuff
source_files : ArrayList ( [ ] const u8 ) ,
object_src : [ ] const u8 ,
2018-11-13 13:08:37 +00:00
const Pkg = struct {
2017-05-01 20:35:10 +00:00
name : [ ] const u8 ,
path : [ ] const u8 ,
} ;
2017-04-21 05:56:12 +00:00
2018-11-13 13:08:37 +00:00
const Kind = enum {
2017-04-21 05:56:12 +00:00
Exe ,
Lib ,
2017-04-26 23:17:05 +00:00
Obj ,
2017-04-21 05:56:12 +00:00
} ;
2018-10-15 22:23:47 +00:00
pub fn createSharedLibrary ( builder : * Builder , name : [ ] const u8 , root_src : ? [ ] const u8 , ver : Version ) * LibExeObjStep {
2018-06-20 15:40:21 +00:00
const self = builder . allocator . create ( initExtraArgs ( builder , name , root_src , Kind . Lib , false , ver ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
return self ;
2017-04-21 05:56:12 +00:00
}
2018-10-15 22:23:47 +00:00
pub fn createCSharedLibrary ( builder : * Builder , name : [ ] const u8 , version : Version ) * LibExeObjStep {
2018-06-20 15:40:21 +00:00
const self = builder . allocator . create ( initC ( builder , name , Kind . Lib , version , false ) ) catch unreachable ;
2017-09-18 06:50:51 +00:00
return self ;
}
2018-05-31 14:56:59 +00:00
pub fn createStaticLibrary ( builder : * Builder , name : [ ] const u8 , root_src : ? [ ] const u8 ) * LibExeObjStep {
2018-06-20 15:40:21 +00:00
const self = builder . allocator . create ( initExtraArgs ( builder , name , root_src , Kind . Lib , true , builder . version ( 0 , 0 , 0 ) ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
return self ;
2017-04-21 05:56:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn createCStaticLibrary ( builder : * Builder , name : [ ] const u8 ) * LibExeObjStep {
2018-06-20 15:40:21 +00:00
const self = builder . allocator . create ( initC ( builder , name , Kind . Lib , builder . version ( 0 , 0 , 0 ) , true ) ) catch unreachable ;
2017-09-18 06:50:51 +00:00
return self ;
}
2018-05-31 14:56:59 +00:00
pub fn createObject ( builder : * Builder , name : [ ] const u8 , root_src : [ ] const u8 ) * LibExeObjStep {
2018-06-20 15:40:21 +00:00
const self = builder . allocator . create ( initExtraArgs ( builder , name , root_src , Kind . Obj , false , builder . version ( 0 , 0 , 0 ) ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
return self ;
2017-04-21 05:56:12 +00:00
}
2017-04-04 05:52:20 +00:00
2018-05-31 14:56:59 +00:00
pub fn createCObject ( builder : * Builder , name : [ ] const u8 , src : [ ] const u8 ) * LibExeObjStep {
2018-06-20 15:40:21 +00:00
const self = builder . allocator . create ( initC ( builder , name , Kind . Obj , builder . version ( 0 , 0 , 0 ) , false ) ) catch unreachable ;
2017-09-18 06:50:51 +00:00
self . object_src = src ;
return self ;
}
2018-12-01 06:21:59 +00:00
pub fn createExecutable ( builder : * Builder , name : [ ] const u8 , root_src : ? [ ] const u8 , static : bool ) * LibExeObjStep {
const self = builder . allocator . create ( initExtraArgs ( builder , name , root_src , Kind . Exe , static , builder . version ( 0 , 0 , 0 ) ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
return self ;
}
2018-05-31 14:56:59 +00:00
pub fn createCExecutable ( builder : * Builder , name : [ ] const u8 ) * LibExeObjStep {
2018-06-20 15:40:21 +00:00
const self = builder . allocator . create ( initC ( builder , name , Kind . Exe , builder . version ( 0 , 0 , 0 ) , false ) ) catch unreachable ;
2017-09-18 06:50:51 +00:00
return self ;
}
2018-10-15 22:23:47 +00:00
fn initExtraArgs ( builder : * Builder , name : [ ] const u8 , root_src : ? [ ] const u8 , kind : Kind , static : bool , ver : Version ) LibExeObjStep {
2018-11-13 13:08:37 +00:00
var self = LibExeObjStep {
2018-07-25 01:28:54 +00:00
. no_rosegment = false ,
2017-09-18 06:50:51 +00:00
. strip = false ,
2017-04-13 21:21:00 +00:00
. builder = builder ,
2018-01-05 04:43:46 +00:00
. verbose_link = false ,
2017-05-02 21:34:21 +00:00
. build_mode = builtin . Mode . Debug ,
2017-04-21 05:56:12 +00:00
. static = static ,
. kind = kind ,
2017-04-13 21:21:00 +00:00
. root_src = root_src ,
. name = name ,
2017-12-12 21:40:04 +00:00
. target = Target . Native ,
2017-04-28 14:46:01 +00:00
. linker_script = null ,
2017-04-13 21:21:00 +00:00
. link_libs = BufSet . init ( builder . allocator ) ,
2017-09-23 21:59:30 +00:00
. frameworks = BufSet . init ( builder . allocator ) ,
2017-04-13 21:21:00 +00:00
. step = Step . init ( name , builder . allocator , make ) ,
2017-04-19 05:13:15 +00:00
. output_path = null ,
2017-04-30 22:56:24 +00:00
. output_h_path = null ,
2018-10-15 22:23:47 +00:00
. version = ver ,
2017-04-21 05:56:12 +00:00
. out_filename = undefined ,
2017-04-30 22:56:24 +00:00
. out_h_filename = builder . fmt ( " {}.h " , name ) ,
2017-05-01 02:09:44 +00:00
. major_only_filename = undefined ,
. name_only_filename = undefined ,
2017-05-04 18:05:06 +00:00
. object_files = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. assembly_files = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. packages = ArrayList ( Pkg ) . init ( builder . allocator ) ,
2017-09-18 06:50:51 +00:00
. is_zig = true ,
. full_path_libs = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. need_flat_namespace_hack = false ,
. cflags = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. source_files = undefined ,
. include_dirs = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
2017-12-12 04:34:59 +00:00
. lib_paths = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
2017-09-18 06:50:51 +00:00
. object_src = undefined ,
. disable_libc = true ,
2018-07-08 04:00:05 +00:00
. build_options_contents = std . Buffer . initSize ( builder . allocator , 0 ) catch unreachable ,
2018-09-06 20:29:35 +00:00
. c_std = Builder . CStd . C99 ,
2018-11-02 04:07:43 +00:00
. system_linker_hack = false ,
2017-09-18 06:50:51 +00:00
} ;
self . computeOutFileNames ( ) ;
return self ;
}
2018-10-15 22:23:47 +00:00
fn initC ( builder : * Builder , name : [ ] const u8 , kind : Kind , version : Version , static : bool ) LibExeObjStep {
2018-11-13 13:08:37 +00:00
var self = LibExeObjStep {
2018-07-25 01:28:54 +00:00
. no_rosegment = false ,
2017-09-18 06:50:51 +00:00
. builder = builder ,
. name = name ,
. kind = kind ,
2018-10-15 22:23:47 +00:00
. version = version ,
2017-09-18 06:50:51 +00:00
. static = static ,
2017-12-12 21:40:04 +00:00
. target = Target . Native ,
2017-09-18 06:50:51 +00:00
. cflags = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. source_files = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. object_files = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. step = Step . init ( name , builder . allocator , make ) ,
. link_libs = BufSet . init ( builder . allocator ) ,
2017-09-23 21:59:30 +00:00
. frameworks = BufSet . init ( builder . allocator ) ,
2017-09-18 06:50:51 +00:00
. full_path_libs = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. include_dirs = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
2017-12-12 04:34:59 +00:00
. lib_paths = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
2017-09-18 06:50:51 +00:00
. output_path = null ,
. out_filename = undefined ,
. major_only_filename = undefined ,
. name_only_filename = undefined ,
. object_src = undefined ,
. build_mode = builtin . Mode . Debug ,
. strip = false ,
. need_flat_namespace_hack = false ,
. disable_libc = false ,
. is_zig = false ,
. linker_script = null ,
2018-09-06 20:29:35 +00:00
. c_std = Builder . CStd . C99 ,
2018-11-02 04:07:43 +00:00
. system_linker_hack = false ,
2017-09-18 06:50:51 +00:00
. root_src = undefined ,
2018-01-05 04:43:46 +00:00
. verbose_link = false ,
2017-09-18 06:50:51 +00:00
. output_h_path = undefined ,
. out_h_filename = undefined ,
. assembly_files = undefined ,
. packages = undefined ,
2018-07-08 04:00:05 +00:00
. build_options_contents = undefined ,
2017-04-21 05:56:12 +00:00
} ;
self . computeOutFileNames ( ) ;
return self ;
2017-04-13 21:21:00 +00:00
}
2018-07-25 01:28:54 +00:00
pub fn setNoRoSegment ( self : * LibExeObjStep , value : bool ) void {
self . no_rosegment = value ;
}
2018-05-31 14:56:59 +00:00
fn computeOutFileNames ( self : * LibExeObjStep ) void {
2017-04-21 05:56:12 +00:00
switch ( self . kind ) {
2017-04-26 23:17:05 +00:00
Kind . Obj = > {
self . out_filename = self . builder . fmt ( " {}{} " , self . name , self . target . oFileExt ( ) ) ;
} ,
2017-04-21 05:56:12 +00:00
Kind . Exe = > {
self . out_filename = self . builder . fmt ( " {}{} " , self . name , self . target . exeFileExt ( ) ) ;
} ,
Kind . Lib = > {
if ( self . static ) {
self . out_filename = self . builder . fmt ( " lib{}.a " , self . name ) ;
} else {
2017-09-23 21:59:30 +00:00
switch ( self . target . getOs ( ) ) {
2018-05-26 22:16:39 +00:00
builtin . Os . ios , builtin . Os . macosx = > {
2018-05-10 04:29:49 +00:00
self . out_filename = self . builder . fmt ( " lib{}.{d}.{d}.{d}.dylib " , self . name , self . version . major , self . version . minor , self . version . patch ) ;
2017-09-23 17:27:36 +00:00
self . major_only_filename = self . builder . fmt ( " lib{}.{d}.dylib " , self . name , self . version . major ) ;
2017-08-27 21:16:42 +00:00
self . name_only_filename = self . builder . fmt ( " lib{}.dylib " , self . name ) ;
} ,
builtin . Os . windows = > {
2017-10-16 05:14:28 +00:00
self . out_filename = self . builder . fmt ( " {}.dll " , self . name ) ;
2017-08-27 21:16:42 +00:00
} ,
else = > {
2018-05-10 04:29:49 +00:00
self . out_filename = self . builder . fmt ( " lib{}.so.{d}.{d}.{d} " , self . name , self . version . major , self . version . minor , self . version . patch ) ;
2017-08-27 21:16:42 +00:00
self . major_only_filename = self . builder . fmt ( " lib{}.so.{d} " , self . name , self . version . major ) ;
self . name_only_filename = self . builder . fmt ( " lib{}.so " , self . name ) ;
} ,
}
2017-04-21 05:56:12 +00:00
}
} ,
}
2017-04-04 05:52:20 +00:00
}
2017-04-03 08:58:19 +00:00
2018-05-31 14:56:59 +00:00
pub fn setTarget ( self : * LibExeObjStep , target_arch : builtin . Arch , target_os : builtin . Os , target_environ : builtin . Environ ) void {
2018-11-13 13:08:37 +00:00
self . target = Target {
. Cross = CrossTarget {
2018-05-26 22:16:39 +00:00
. arch = target_arch ,
. os = target_os ,
. environ = target_environ ,
} ,
} ;
2017-04-26 23:17:05 +00:00
self . computeOutFileNames ( ) ;
2017-04-03 08:58:19 +00:00
}
2017-09-18 06:50:51 +00:00
// TODO respect this in the C args
2018-05-31 14:56:59 +00:00
pub fn setLinkerScriptPath ( self : * LibExeObjStep , path : [ ] const u8 ) void {
2017-04-28 14:46:01 +00:00
self . linker_script = path ;
2017-04-03 08:58:19 +00:00
}
2017-04-04 05:52:20 +00:00
2018-05-31 14:56:59 +00:00
pub fn linkFramework ( self : * LibExeObjStep , framework_name : [ ] const u8 ) void {
2017-09-23 21:59:30 +00:00
assert ( self . target . isDarwin ( ) ) ;
2018-01-09 05:07:01 +00:00
self . frameworks . put ( framework_name ) catch unreachable ;
2017-09-23 21:59:30 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn linkLibrary ( self : * LibExeObjStep , lib : * LibExeObjStep ) void {
2017-09-18 06:50:51 +00:00
assert ( self . kind ! = Kind . Obj ) ;
assert ( lib . kind = = Kind . Lib ) ;
self . step . dependOn ( & lib . step ) ;
2018-01-09 05:07:01 +00:00
self . full_path_libs . append ( lib . getOutputPath ( ) ) catch unreachable ;
2017-09-18 06:50:51 +00:00
// TODO should be some kind of isolated directory that only has this header in it
2018-01-09 05:07:01 +00:00
self . include_dirs . append ( self . builder . cache_root ) catch unreachable ;
2017-09-18 06:50:51 +00:00
self . need_flat_namespace_hack = true ;
2017-09-23 21:59:30 +00:00
// inherit the object's frameworks
if ( self . target . isDarwin ( ) and lib . static ) {
var it = lib . frameworks . iterator ( ) ;
while ( it . next ( ) ) | entry | {
2018-01-09 05:07:01 +00:00
self . frameworks . put ( entry . key ) catch unreachable ;
2017-09-23 21:59:30 +00:00
}
}
2017-09-18 06:50:51 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn linkSystemLibrary ( self : * LibExeObjStep , name : [ ] const u8 ) void {
2017-09-18 06:50:51 +00:00
assert ( self . kind ! = Kind . Obj ) ;
2018-01-09 05:07:01 +00:00
self . link_libs . put ( name ) catch unreachable ;
2017-04-04 05:52:20 +00:00
}
2017-04-06 09:34:04 +00:00
2018-05-31 14:56:59 +00:00
pub fn addSourceFile ( self : * LibExeObjStep , file : [ ] const u8 ) void {
2017-09-18 06:50:51 +00:00
assert ( self . kind ! = Kind . Obj ) ;
assert ( ! self . is_zig ) ;
2018-01-09 05:07:01 +00:00
self . source_files . append ( file ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn setVerboseLink ( self : * LibExeObjStep , value : bool ) void {
2018-01-05 04:43:46 +00:00
self . verbose_link = value ;
2017-04-19 18:00:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn setBuildMode ( self : * LibExeObjStep , mode : builtin . Mode ) void {
2017-05-02 21:34:21 +00:00
self . build_mode = mode ;
2017-04-19 18:00:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn setOutputPath ( self : * LibExeObjStep , file_path : [ ] const u8 ) void {
2017-09-18 22:01:58 +00:00
self . output_path = file_path ;
// catch a common mistake
if ( mem . eql ( u8 , self . builder . pathFromRoot ( file_path ) , self . builder . pathFromRoot ( " . " ) ) ) {
debug . panic ( " setOutputPath wants a file path, not a directory \n " ) ;
}
2017-04-19 18:00:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn getOutputPath ( self : * LibExeObjStep ) [ ] const u8 {
2018-05-26 22:16:39 +00:00
return if ( self . output_path ) | output_path | output_path else os . path . join ( self . builder . allocator , self . builder . cache_root , self . out_filename ) catch unreachable ;
2017-04-30 22:56:24 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn setOutputHPath ( self : * LibExeObjStep , file_path : [ ] const u8 ) void {
2017-09-18 22:01:58 +00:00
self . output_h_path = file_path ;
// catch a common mistake
if ( mem . eql ( u8 , self . builder . pathFromRoot ( file_path ) , self . builder . pathFromRoot ( " . " ) ) ) {
debug . panic ( " setOutputHPath wants a file path, not a directory \n " ) ;
}
2017-04-30 22:56:24 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn getOutputHPath ( self : * LibExeObjStep ) [ ] const u8 {
2018-05-26 22:16:39 +00:00
return if ( self . output_h_path ) | output_h_path | output_h_path else os . path . join ( self . builder . allocator , self . builder . cache_root , self . out_h_filename ) catch unreachable ;
2017-04-30 22:56:24 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addAssemblyFile ( self : * LibExeObjStep , path : [ ] const u8 ) void {
2018-01-09 05:07:01 +00:00
self . assembly_files . append ( path ) catch unreachable ;
2017-04-19 18:00:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addObjectFile ( self : * LibExeObjStep , path : [ ] const u8 ) void {
2017-04-26 23:17:05 +00:00
assert ( self . kind ! = Kind . Obj ) ;
2017-04-19 18:00:12 +00:00
2018-01-09 05:07:01 +00:00
self . object_files . append ( path ) catch unreachable ;
2017-04-19 18:00:12 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addObject ( self : * LibExeObjStep , obj : * LibExeObjStep ) void {
2017-04-26 23:17:05 +00:00
assert ( obj . kind = = Kind . Obj ) ;
assert ( self . kind ! = Kind . Obj ) ;
2017-04-19 18:00:12 +00:00
2017-04-26 16:56:10 +00:00
self . step . dependOn ( & obj . step ) ;
2018-01-09 05:07:01 +00:00
self . object_files . append ( obj . getOutputPath ( ) ) catch unreachable ;
2017-09-18 06:50:51 +00:00
// TODO make this lazy instead of stateful
if ( ! obj . disable_libc ) {
self . disable_libc = false ;
}
// TODO should be some kind of isolated directory that only has this header in it
2018-01-09 05:07:01 +00:00
self . include_dirs . append ( self . builder . cache_root ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2018-07-08 04:00:05 +00:00
pub fn addBuildOption ( self : * LibExeObjStep , comptime T : type , name : [ ] const u8 , value : T ) void {
assert ( self . is_zig ) ;
const out = & std . io . BufferOutStream . init ( & self . build_options_contents ) . stream ;
out . print ( " pub const {} = {}; \n " , name , value ) catch unreachable ;
}
2018-05-31 14:56:59 +00:00
pub fn addIncludeDir ( self : * LibExeObjStep , path : [ ] const u8 ) void {
2018-01-09 05:07:01 +00:00
self . include_dirs . append ( path ) catch unreachable ;
2017-04-26 16:56:10 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addLibPath ( self : * LibExeObjStep , path : [ ] const u8 ) void {
2018-01-09 05:07:01 +00:00
self . lib_paths . append ( path ) catch unreachable ;
2017-12-12 04:34:59 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addPackagePath ( self : * LibExeObjStep , name : [ ] const u8 , pkg_index_path : [ ] const u8 ) void {
2017-09-18 06:50:51 +00:00
assert ( self . is_zig ) ;
2018-11-13 13:08:37 +00:00
self . packages . append ( Pkg {
2017-05-01 20:35:10 +00:00
. name = name ,
. path = pkg_index_path ,
2018-01-09 05:07:01 +00:00
} ) catch unreachable ;
2017-05-01 20:35:10 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn addCompileFlags ( self : * LibExeObjStep , flags : [ ] const [ ] const u8 ) void {
2017-09-18 06:50:51 +00:00
for ( flags ) | flag | {
2018-01-09 05:07:01 +00:00
self . cflags . append ( flag ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
}
2018-05-31 14:56:59 +00:00
pub fn setNoStdLib ( self : * LibExeObjStep , disable : bool ) void {
2017-09-18 06:50:51 +00:00
assert ( ! self . is_zig ) ;
self . disable_libc = disable ;
}
2018-11-02 04:07:43 +00:00
pub fn enableSystemLinkerHack ( self : * LibExeObjStep ) void {
self . system_linker_hack = true ;
}
2018-05-31 14:56:59 +00:00
fn make ( step : * Step ) ! void {
2017-04-26 23:17:05 +00:00
const self = @fieldParentPtr ( LibExeObjStep , " step " , step ) ;
2017-09-18 06:50:51 +00:00
return if ( self . is_zig ) self . makeZig ( ) else self . makeC ( ) ;
}
2018-05-31 14:56:59 +00:00
fn makeZig ( self : * LibExeObjStep ) ! void {
2017-04-19 18:00:12 +00:00
const builder = self . builder ;
2017-09-18 06:50:51 +00:00
assert ( self . is_zig ) ;
2017-04-26 23:17:05 +00:00
if ( self . root_src = = null and self . object_files . len = = 0 and self . assembly_files . len = = 0 ) {
2017-10-31 08:47:55 +00:00
warn ( " {}: linker needs 1 or more objects to link \n " , self . step . name ) ;
2017-04-19 18:00:12 +00:00
return error . NeedAnObject ;
}
2017-05-04 18:05:06 +00:00
var zig_args = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ;
2017-04-19 18:00:12 +00:00
defer zig_args . deinit ( ) ;
2018-01-09 05:07:01 +00:00
zig_args . append ( builder . zig_exe ) catch unreachable ;
2017-09-26 05:01:49 +00:00
2017-04-26 23:17:05 +00:00
const cmd = switch ( self . kind ) {
2017-09-16 05:00:59 +00:00
Kind . Lib = > " build-lib " ,
Kind . Exe = > " build-exe " ,
Kind . Obj = > " build-obj " ,
2017-04-19 18:00:12 +00:00
} ;
2018-01-09 05:07:01 +00:00
zig_args . append ( cmd ) catch unreachable ;
2017-04-19 18:00:12 +00:00
2017-05-03 21:23:11 +00:00
if ( self . root_src ) | root_src | {
2018-01-09 05:07:01 +00:00
zig_args . append ( builder . pathFromRoot ( root_src ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
}
2018-07-08 04:00:05 +00:00
if ( self . build_options_contents . len ( ) > 0 ) {
const build_options_file = try os . path . join ( builder . allocator , builder . cache_root , builder . fmt ( " {}_build_options.zig " , self . name ) ) ;
2018-08-21 20:07:28 +00:00
try std . io . writeFile ( build_options_file , self . build_options_contents . toSliceConst ( ) ) ;
2018-07-08 04:00:05 +00:00
try zig_args . append ( " --pkg-begin " ) ;
try zig_args . append ( " build_options " ) ;
try zig_args . append ( builder . pathFromRoot ( build_options_file ) ) ;
try zig_args . append ( " --pkg-end " ) ;
}
2017-04-19 18:00:12 +00:00
for ( self . object_files . toSliceConst ( ) ) | object_file | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --object " ) catch unreachable ;
zig_args . append ( builder . pathFromRoot ( object_file ) ) catch unreachable ;
2017-04-19 18:00:12 +00:00
}
2017-04-26 23:17:05 +00:00
for ( self . assembly_files . toSliceConst ( ) ) | asm_file | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --assembly " ) catch unreachable ;
zig_args . append ( builder . pathFromRoot ( asm_file ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
}
2018-01-09 05:07:01 +00:00
if ( builder . verbose_tokenize ) zig_args . append ( " --verbose-tokenize " ) catch unreachable ;
if ( builder . verbose_ast ) zig_args . append ( " --verbose-ast " ) catch unreachable ;
if ( builder . verbose_cimport ) zig_args . append ( " --verbose-cimport " ) catch unreachable ;
if ( builder . verbose_ir ) zig_args . append ( " --verbose-ir " ) catch unreachable ;
if ( builder . verbose_llvm_ir ) zig_args . append ( " --verbose-llvm-ir " ) catch unreachable ;
if ( builder . verbose_link or self . verbose_link ) zig_args . append ( " --verbose-link " ) catch unreachable ;
2017-04-19 18:00:12 +00:00
2017-09-18 06:50:51 +00:00
if ( self . strip ) {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --strip " ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2017-05-02 21:34:21 +00:00
switch ( self . build_mode ) {
builtin . Mode . Debug = > { } ,
2018-01-09 05:07:01 +00:00
builtin . Mode . ReleaseSafe = > zig_args . append ( " --release-safe " ) catch unreachable ,
builtin . Mode . ReleaseFast = > zig_args . append ( " --release-fast " ) catch unreachable ,
2018-04-16 00:26:10 +00:00
builtin . Mode . ReleaseSmall = > zig_args . append ( " --release-small " ) catch unreachable ,
2017-04-19 18:00:12 +00:00
}
2018-01-09 05:07:01 +00:00
zig_args . append ( " --cache-dir " ) catch unreachable ;
zig_args . append ( builder . pathFromRoot ( builder . cache_root ) ) catch unreachable ;
2017-04-30 22:56:24 +00:00
const output_path = builder . pathFromRoot ( self . getOutputPath ( ) ) ;
2018-01-09 05:07:01 +00:00
zig_args . append ( " --output " ) catch unreachable ;
zig_args . append ( output_path ) catch unreachable ;
2017-04-30 22:56:24 +00:00
2017-05-01 20:35:10 +00:00
if ( self . kind ! = Kind . Exe ) {
const output_h_path = self . getOutputHPath ( ) ;
2018-01-09 05:07:01 +00:00
zig_args . append ( " --output-h " ) catch unreachable ;
zig_args . append ( builder . pathFromRoot ( output_h_path ) ) catch unreachable ;
2017-05-01 20:35:10 +00:00
}
2017-04-19 18:00:12 +00:00
2018-01-09 05:07:01 +00:00
zig_args . append ( " --name " ) catch unreachable ;
zig_args . append ( self . name ) catch unreachable ;
2017-04-19 18:00:12 +00:00
2017-04-26 23:17:05 +00:00
if ( self . kind = = Kind . Lib and ! self . static ) {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --ver-major " ) catch unreachable ;
zig_args . append ( builder . fmt ( " {} " , self . version . major ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
2018-01-09 05:07:01 +00:00
zig_args . append ( " --ver-minor " ) catch unreachable ;
zig_args . append ( builder . fmt ( " {} " , self . version . minor ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
2018-01-09 05:07:01 +00:00
zig_args . append ( " --ver-patch " ) catch unreachable ;
zig_args . append ( builder . fmt ( " {} " , self . version . patch ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
}
2018-12-01 06:21:59 +00:00
if ( self . kind = = Kind . Exe and self . static ) {
zig_args . append ( " --static " ) catch unreachable ;
}
2017-04-26 23:17:05 +00:00
2017-04-19 18:00:12 +00:00
switch ( self . target ) {
Target . Native = > { } ,
Target . Cross = > | cross_target | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --target-arch " ) catch unreachable ;
zig_args . append ( @tagName ( cross_target . arch ) ) catch unreachable ;
2017-04-19 18:00:12 +00:00
2018-01-09 05:07:01 +00:00
zig_args . append ( " --target-os " ) catch unreachable ;
zig_args . append ( @tagName ( cross_target . os ) ) catch unreachable ;
2017-04-19 18:00:12 +00:00
2018-01-09 05:07:01 +00:00
zig_args . append ( " --target-environ " ) catch unreachable ;
zig_args . append ( @tagName ( cross_target . environ ) ) catch unreachable ;
2017-04-19 18:00:12 +00:00
} ,
}
2017-05-03 21:23:11 +00:00
if ( self . linker_script ) | linker_script | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --linker-script " ) catch unreachable ;
zig_args . append ( linker_script ) catch unreachable ;
2017-04-19 18:00:12 +00:00
}
{
var it = self . link_libs . iterator ( ) ;
while ( true ) {
2018-06-10 05:13:51 +00:00
const entry = it . next ( ) orelse break ;
2018-01-09 05:07:01 +00:00
zig_args . append ( " --library " ) catch unreachable ;
zig_args . append ( entry . key ) catch unreachable ;
2017-04-19 18:00:12 +00:00
}
}
2017-09-18 06:50:51 +00:00
if ( ! self . disable_libc ) {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --library " ) catch unreachable ;
zig_args . append ( " c " ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2017-05-01 20:35:10 +00:00
for ( self . packages . toSliceConst ( ) ) | pkg | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --pkg-begin " ) catch unreachable ;
zig_args . append ( pkg . name ) catch unreachable ;
zig_args . append ( builder . pathFromRoot ( pkg . path ) ) catch unreachable ;
zig_args . append ( " --pkg-end " ) catch unreachable ;
2017-05-01 20:35:10 +00:00
}
2017-12-12 04:34:59 +00:00
for ( self . include_dirs . toSliceConst ( ) ) | include_path | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " -isystem " ) catch unreachable ;
zig_args . append ( self . builder . pathFromRoot ( include_path ) ) catch unreachable ;
2017-12-12 04:34:59 +00:00
}
2017-04-26 23:17:05 +00:00
for ( builder . include_paths . toSliceConst ( ) ) | include_path | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " -isystem " ) catch unreachable ;
zig_args . append ( builder . pathFromRoot ( include_path ) ) catch unreachable ;
2017-04-26 23:17:05 +00:00
}
2017-04-19 18:00:12 +00:00
for ( builder . rpaths . toSliceConst ( ) ) | rpath | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " -rpath " ) catch unreachable ;
zig_args . append ( rpath ) catch unreachable ;
2017-04-19 18:00:12 +00:00
}
2017-12-12 04:34:59 +00:00
for ( self . lib_paths . toSliceConst ( ) ) | lib_path | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --library-path " ) catch unreachable ;
zig_args . append ( lib_path ) catch unreachable ;
2017-12-12 04:34:59 +00:00
}
2017-04-19 18:00:12 +00:00
for ( builder . lib_paths . toSliceConst ( ) ) | lib_path | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --library-path " ) catch unreachable ;
zig_args . append ( lib_path ) catch unreachable ;
2017-04-19 18:00:12 +00:00
}
2017-09-18 06:50:51 +00:00
for ( self . full_path_libs . toSliceConst ( ) ) | full_path_lib | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " --library " ) catch unreachable ;
zig_args . append ( builder . pathFromRoot ( full_path_lib ) ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2017-09-23 21:59:30 +00:00
if ( self . target . isDarwin ( ) ) {
var it = self . frameworks . iterator ( ) ;
while ( it . next ( ) ) | entry | {
2018-01-09 05:07:01 +00:00
zig_args . append ( " -framework " ) catch unreachable ;
zig_args . append ( entry . key ) catch unreachable ;
2017-09-23 21:59:30 +00:00
}
}
2018-07-25 01:28:54 +00:00
if ( self . no_rosegment ) {
try zig_args . append ( " --no-rosegment " ) ;
}
2018-11-02 04:07:43 +00:00
if ( self . system_linker_hack ) {
try zig_args . append ( " --system-linker-hack " ) ;
}
2018-07-25 01:28:54 +00:00
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( zig_args . toSliceConst ( ) ) ;
2017-04-26 23:17:05 +00:00
2017-10-16 05:14:28 +00:00
if ( self . kind = = Kind . Lib and ! self . static and self . target . wantSharedLibSymLinks ( ) ) {
2018-05-10 04:29:49 +00:00
try doAtomicSymLinks ( builder . allocator , output_path , self . major_only_filename , self . name_only_filename ) ;
2017-04-26 23:17:05 +00:00
}
2017-04-19 18:00:12 +00:00
}
2018-05-31 14:56:59 +00:00
fn appendCompileFlags ( self : * LibExeObjStep , args : * ArrayList ( [ ] const u8 ) ) void {
2017-09-18 06:50:51 +00:00
if ( ! self . strip ) {
2018-01-09 05:07:01 +00:00
args . append ( " -g " ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
switch ( self . build_mode ) {
builtin . Mode . Debug = > {
2017-09-18 19:30:07 +00:00
if ( self . disable_libc ) {
2018-01-09 05:07:01 +00:00
args . append ( " -fno-stack-protector " ) catch unreachable ;
2017-09-18 19:30:07 +00:00
} else {
2018-01-09 05:07:01 +00:00
args . append ( " -fstack-protector-strong " ) catch unreachable ;
args . append ( " --param " ) catch unreachable ;
args . append ( " ssp-buffer-size=4 " ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
} ,
builtin . Mode . ReleaseSafe = > {
2018-01-09 05:07:01 +00:00
args . append ( " -O2 " ) catch unreachable ;
2017-09-18 19:30:07 +00:00
if ( self . disable_libc ) {
2018-01-09 05:07:01 +00:00
args . append ( " -fno-stack-protector " ) catch unreachable ;
2017-09-18 19:30:07 +00:00
} else {
2018-01-09 05:07:01 +00:00
args . append ( " -D_FORTIFY_SOURCE=2 " ) catch unreachable ;
args . append ( " -fstack-protector-strong " ) catch unreachable ;
args . append ( " --param " ) catch unreachable ;
args . append ( " ssp-buffer-size=4 " ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
} ,
2018-05-26 22:16:39 +00:00
builtin . Mode . ReleaseFast , builtin . Mode . ReleaseSmall = > {
2018-01-09 05:07:01 +00:00
args . append ( " -O2 " ) catch unreachable ;
args . append ( " -fno-stack-protector " ) catch unreachable ;
2017-09-18 06:50:51 +00:00
} ,
}
2017-04-19 05:13:15 +00:00
2017-09-18 06:50:51 +00:00
for ( self . include_dirs . toSliceConst ( ) ) | dir | {
2018-01-09 05:07:01 +00:00
args . append ( " -I " ) catch unreachable ;
args . append ( self . builder . pathFromRoot ( dir ) ) catch unreachable ;
2017-04-19 05:13:15 +00:00
}
2017-09-18 06:50:51 +00:00
for ( self . cflags . toSliceConst ( ) ) | cflag | {
2018-01-09 05:07:01 +00:00
args . append ( cflag ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2017-04-19 05:13:15 +00:00
2017-09-18 06:50:51 +00:00
if ( self . disable_libc ) {
2018-01-09 05:07:01 +00:00
args . append ( " -nostdlib " ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2017-04-19 05:13:15 +00:00
}
2018-05-31 14:56:59 +00:00
fn makeC ( self : * LibExeObjStep ) ! void {
2017-09-18 06:50:51 +00:00
const builder = self . builder ;
2017-04-19 05:13:15 +00:00
2017-10-16 05:14:28 +00:00
const cc = builder . getCCExe ( ) ;
2017-09-18 06:50:51 +00:00
assert ( ! self . is_zig ) ;
2017-04-19 19:38:12 +00:00
2017-09-18 06:50:51 +00:00
var cc_args = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ;
defer cc_args . deinit ( ) ;
2017-04-19 19:38:12 +00:00
2018-01-09 05:07:01 +00:00
cc_args . append ( cc ) catch unreachable ;
2017-09-26 05:01:49 +00:00
2017-09-23 21:59:30 +00:00
const is_darwin = self . target . isDarwin ( ) ;
2017-09-23 17:27:36 +00:00
2018-09-06 20:29:35 +00:00
const c_std_arg = switch ( self . c_std ) {
Builder . CStd . C89 = > " -std=c89 " ,
Builder . CStd . C99 = > " -std=c99 " ,
Builder . CStd . C11 = > " -std=c11 " ,
} ;
try cc_args . append ( c_std_arg ) ;
2017-09-18 06:50:51 +00:00
switch ( self . kind ) {
Kind . Obj = > {
2018-01-09 05:07:01 +00:00
cc_args . append ( " -c " ) catch unreachable ;
cc_args . append ( builder . pathFromRoot ( self . object_src ) ) catch unreachable ;
2017-08-30 18:55:26 +00:00
2017-09-18 06:50:51 +00:00
const output_path = builder . pathFromRoot ( self . getOutputPath ( ) ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( " -o " ) catch unreachable ;
cc_args . append ( output_path ) catch unreachable ;
2017-09-17 18:43:51 +00:00
2017-09-18 06:50:51 +00:00
self . appendCompileFlags ( & cc_args ) ;
2017-04-19 05:13:15 +00:00
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( cc_args . toSliceConst ( ) ) ;
2017-09-18 06:50:51 +00:00
} ,
Kind . Lib = > {
for ( self . source_files . toSliceConst ( ) ) | source_file | {
2018-01-09 05:07:01 +00:00
cc_args . resize ( 0 ) catch unreachable ;
cc_args . append ( cc ) catch unreachable ;
2017-04-19 05:13:15 +00:00
2017-09-18 06:50:51 +00:00
if ( ! self . static ) {
2018-01-09 05:07:01 +00:00
cc_args . append ( " -fPIC " ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2017-04-19 05:13:15 +00:00
2017-09-18 06:50:51 +00:00
const abs_source_file = builder . pathFromRoot ( source_file ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( " -c " ) catch unreachable ;
cc_args . append ( abs_source_file ) catch unreachable ;
2017-04-19 05:13:15 +00:00
2018-01-09 05:07:01 +00:00
const cache_o_src = os . path . join ( builder . allocator , builder . cache_root , source_file ) catch unreachable ;
2018-06-14 20:15:32 +00:00
if ( os . path . dirname ( cache_o_src ) ) | cache_o_dir | {
try builder . makePath ( cache_o_dir ) ;
}
2017-09-18 06:50:51 +00:00
const cache_o_file = builder . fmt ( " {}{} " , cache_o_src , self . target . oFileExt ( ) ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( " -o " ) catch unreachable ;
cc_args . append ( builder . pathFromRoot ( cache_o_file ) ) catch unreachable ;
2017-04-19 05:13:15 +00:00
2017-09-18 06:50:51 +00:00
self . appendCompileFlags ( & cc_args ) ;
2017-08-30 18:55:26 +00:00
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( cc_args . toSliceConst ( ) ) ;
2017-04-21 06:26:48 +00:00
2018-01-09 05:07:01 +00:00
self . object_files . append ( cache_o_file ) catch unreachable ;
2017-04-30 23:48:45 +00:00
}
2017-04-13 21:21:00 +00:00
2017-04-30 23:48:45 +00:00
if ( self . static ) {
2017-05-01 00:29:33 +00:00
// ar
2018-01-09 05:07:01 +00:00
cc_args . resize ( 0 ) catch unreachable ;
cc_args . append ( " ar " ) catch unreachable ;
2017-09-26 05:01:49 +00:00
2018-01-09 05:07:01 +00:00
cc_args . append ( " qc " ) catch unreachable ;
2017-05-01 00:29:33 +00:00
const output_path = builder . pathFromRoot ( self . getOutputPath ( ) ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( output_path ) catch unreachable ;
2017-05-01 00:29:33 +00:00
for ( self . object_files . toSliceConst ( ) ) | object_file | {
2018-01-09 05:07:01 +00:00
cc_args . append ( builder . pathFromRoot ( object_file ) ) catch unreachable ;
2017-05-01 00:29:33 +00:00
}
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( cc_args . toSliceConst ( ) ) ;
2017-05-01 00:29:33 +00:00
// ranlib
2018-01-09 05:07:01 +00:00
cc_args . resize ( 0 ) catch unreachable ;
cc_args . append ( " ranlib " ) catch unreachable ;
cc_args . append ( output_path ) catch unreachable ;
2017-05-01 00:29:33 +00:00
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( cc_args . toSliceConst ( ) ) ;
2017-04-30 23:48:45 +00:00
} else {
2018-01-09 05:07:01 +00:00
cc_args . resize ( 0 ) catch unreachable ;
cc_args . append ( cc ) catch unreachable ;
2017-04-16 18:14:11 +00:00
2017-09-23 17:27:36 +00:00
if ( is_darwin ) {
2018-01-09 05:07:01 +00:00
cc_args . append ( " -dynamiclib " ) catch unreachable ;
2017-09-23 17:27:36 +00:00
2018-01-09 05:07:01 +00:00
cc_args . append ( " -Wl,-headerpad_max_install_names " ) catch unreachable ;
2017-09-23 17:27:36 +00:00
2018-01-09 05:07:01 +00:00
cc_args . append ( " -compatibility_version " ) catch unreachable ;
cc_args . append ( builder . fmt ( " {}.0.0 " , self . version . major ) ) catch unreachable ;
2017-04-16 18:14:11 +00:00
2018-01-09 05:07:01 +00:00
cc_args . append ( " -current_version " ) catch unreachable ;
cc_args . append ( builder . fmt ( " {}.{}.{} " , self . version . major , self . version . minor , self . version . patch ) ) catch unreachable ;
2017-09-23 17:27:36 +00:00
2018-01-09 05:07:01 +00:00
const install_name = builder . pathFromRoot ( os . path . join ( builder . allocator , builder . cache_root , self . major_only_filename ) catch unreachable ) ;
cc_args . append ( " -install_name " ) catch unreachable ;
cc_args . append ( install_name ) catch unreachable ;
2017-09-23 17:27:36 +00:00
} else {
2018-01-09 05:07:01 +00:00
cc_args . append ( " -fPIC " ) catch unreachable ;
cc_args . append ( " -shared " ) catch unreachable ;
2017-09-23 17:27:36 +00:00
const soname_arg = builder . fmt ( " -Wl,-soname,lib{}.so.{d} " , self . name , self . version . major ) ;
defer builder . allocator . free ( soname_arg ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( soname_arg ) catch unreachable ;
2017-09-23 17:27:36 +00:00
}
2017-04-13 21:21:00 +00:00
2017-04-30 23:48:45 +00:00
const output_path = builder . pathFromRoot ( self . getOutputPath ( ) ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( " -o " ) catch unreachable ;
cc_args . append ( output_path ) catch unreachable ;
2017-04-13 21:21:00 +00:00
2017-04-30 23:48:45 +00:00
for ( self . object_files . toSliceConst ( ) ) | object_file | {
2018-01-09 05:07:01 +00:00
cc_args . append ( builder . pathFromRoot ( object_file ) ) catch unreachable ;
2017-04-30 23:48:45 +00:00
}
2017-04-16 18:14:11 +00:00
2017-09-23 17:27:36 +00:00
if ( ! is_darwin ) {
2018-08-22 00:28:37 +00:00
const rpath_arg = builder . fmt ( " -Wl,-rpath,{} " , try os . path . realAlloc (
builder . allocator ,
builder . pathFromRoot ( builder . cache_root ) ,
) ) ;
2017-09-23 17:27:36 +00:00
defer builder . allocator . free ( rpath_arg ) ;
2018-08-22 00:28:37 +00:00
try cc_args . append ( rpath_arg ) ;
2017-04-16 18:14:11 +00:00
2018-08-22 00:28:37 +00:00
try cc_args . append ( " -rdynamic " ) ;
2017-09-23 17:27:36 +00:00
}
2017-04-16 18:14:11 +00:00
2017-04-30 23:48:45 +00:00
for ( self . full_path_libs . toSliceConst ( ) ) | full_path_lib | {
2018-01-09 05:07:01 +00:00
cc_args . append ( builder . pathFromRoot ( full_path_lib ) ) catch unreachable ;
2017-04-30 23:48:45 +00:00
}
2017-04-16 18:14:11 +00:00
2017-10-21 16:58:47 +00:00
{
var it = self . link_libs . iterator ( ) ;
while ( it . next ( ) ) | entry | {
2018-01-09 05:07:01 +00:00
cc_args . append ( builder . fmt ( " -l{} " , entry . key ) ) catch unreachable ;
2017-10-21 16:58:47 +00:00
}
}
2017-09-23 21:59:30 +00:00
if ( is_darwin and ! self . static ) {
var it = self . frameworks . iterator ( ) ;
while ( it . next ( ) ) | entry | {
2018-01-09 05:07:01 +00:00
cc_args . append ( " -framework " ) catch unreachable ;
cc_args . append ( entry . key ) catch unreachable ;
2017-09-23 21:59:30 +00:00
}
}
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( cc_args . toSliceConst ( ) ) ;
2017-04-16 18:14:11 +00:00
2017-10-16 05:14:28 +00:00
if ( self . target . wantSharedLibSymLinks ( ) ) {
2018-05-10 04:29:49 +00:00
try doAtomicSymLinks ( builder . allocator , output_path , self . major_only_filename , self . name_only_filename ) ;
2017-10-16 05:14:28 +00:00
}
2017-04-30 23:48:45 +00:00
}
} ,
Kind . Exe = > {
for ( self . source_files . toSliceConst ( ) ) | source_file | {
2018-01-09 05:07:01 +00:00
cc_args . resize ( 0 ) catch unreachable ;
cc_args . append ( cc ) catch unreachable ;
2017-04-30 23:48:45 +00:00
2017-05-01 00:11:35 +00:00
const abs_source_file = builder . pathFromRoot ( source_file ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( " -c " ) catch unreachable ;
cc_args . append ( abs_source_file ) catch unreachable ;
2017-04-30 23:48:45 +00:00
2018-01-09 05:07:01 +00:00
const cache_o_src = os . path . join ( builder . allocator , builder . cache_root , source_file ) catch unreachable ;
2018-06-14 20:15:32 +00:00
if ( os . path . dirname ( cache_o_src ) ) | cache_o_dir | {
try builder . makePath ( cache_o_dir ) ;
}
2017-04-30 23:48:45 +00:00
const cache_o_file = builder . fmt ( " {}{} " , cache_o_src , self . target . oFileExt ( ) ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( " -o " ) catch unreachable ;
cc_args . append ( builder . pathFromRoot ( cache_o_file ) ) catch unreachable ;
2017-04-30 23:48:45 +00:00
for ( self . cflags . toSliceConst ( ) ) | cflag | {
2018-01-09 05:07:01 +00:00
cc_args . append ( cflag ) catch unreachable ;
2017-04-30 23:48:45 +00:00
}
2017-04-16 18:14:11 +00:00
2017-04-30 23:48:45 +00:00
for ( self . include_dirs . toSliceConst ( ) ) | dir | {
2018-01-09 05:07:01 +00:00
cc_args . append ( " -I " ) catch unreachable ;
cc_args . append ( builder . pathFromRoot ( dir ) ) catch unreachable ;
2017-04-30 23:48:45 +00:00
}
2017-04-16 18:14:11 +00:00
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( cc_args . toSliceConst ( ) ) ;
2017-04-16 18:14:11 +00:00
2018-01-09 05:07:01 +00:00
self . object_files . append ( cache_o_file ) catch unreachable ;
2017-04-30 23:48:45 +00:00
}
2017-04-16 18:14:11 +00:00
2018-01-09 05:07:01 +00:00
cc_args . resize ( 0 ) catch unreachable ;
cc_args . append ( cc ) catch unreachable ;
2017-04-13 21:21:00 +00:00
2017-04-30 23:48:45 +00:00
for ( self . object_files . toSliceConst ( ) ) | object_file | {
2018-01-09 05:07:01 +00:00
cc_args . append ( builder . pathFromRoot ( object_file ) ) catch unreachable ;
2017-04-30 23:48:45 +00:00
}
2017-04-16 18:14:11 +00:00
2017-04-30 23:48:45 +00:00
const output_path = builder . pathFromRoot ( self . getOutputPath ( ) ) ;
2018-01-09 05:07:01 +00:00
cc_args . append ( " -o " ) catch unreachable ;
cc_args . append ( output_path ) catch unreachable ;
2017-04-16 18:14:11 +00:00
2018-08-22 00:28:37 +00:00
const rpath_arg = builder . fmt ( " -Wl,-rpath,{} " , try os . path . realAlloc (
builder . allocator ,
builder . pathFromRoot ( builder . cache_root ) ,
) ) ;
2017-04-30 23:48:45 +00:00
defer builder . allocator . free ( rpath_arg ) ;
2018-08-22 00:28:37 +00:00
try cc_args . append ( rpath_arg ) ;
2017-04-16 18:14:11 +00:00
2018-08-22 00:28:37 +00:00
try cc_args . append ( " -rdynamic " ) ;
2017-04-16 18:14:11 +00:00
2017-10-21 16:58:47 +00:00
{
var it = self . link_libs . iterator ( ) ;
while ( it . next ( ) ) | entry | {
2018-01-09 05:07:01 +00:00
cc_args . append ( builder . fmt ( " -l{} " , entry . key ) ) catch unreachable ;
2017-10-21 16:58:47 +00:00
}
}
2017-09-23 21:59:30 +00:00
if ( is_darwin ) {
if ( self . need_flat_namespace_hack ) {
2018-01-09 05:07:01 +00:00
cc_args . append ( " -Wl,-flat_namespace " ) catch unreachable ;
2017-09-23 21:59:30 +00:00
}
2018-01-09 05:07:01 +00:00
cc_args . append ( " -Wl,-search_paths_first " ) catch unreachable ;
2017-08-27 21:16:42 +00:00
}
2017-04-30 23:48:45 +00:00
for ( self . full_path_libs . toSliceConst ( ) ) | full_path_lib | {
2018-01-09 05:07:01 +00:00
cc_args . append ( builder . pathFromRoot ( full_path_lib ) ) catch unreachable ;
2017-04-30 23:48:45 +00:00
}
2017-05-01 00:11:35 +00:00
2017-09-23 21:59:30 +00:00
if ( is_darwin ) {
var it = self . frameworks . iterator ( ) ;
while ( it . next ( ) ) | entry | {
2018-01-09 05:07:01 +00:00
cc_args . append ( " -framework " ) catch unreachable ;
cc_args . append ( entry . key ) catch unreachable ;
2017-09-23 21:59:30 +00:00
}
}
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( cc_args . toSliceConst ( ) ) ;
2017-04-30 23:48:45 +00:00
} ,
2017-04-16 18:14:11 +00:00
}
}
2017-09-18 06:50:51 +00:00
} ;
2018-11-13 13:08:37 +00:00
pub const TestStep = struct {
2017-09-18 06:50:51 +00:00
step : Step ,
2018-05-31 14:56:59 +00:00
builder : * Builder ,
2017-09-18 06:50:51 +00:00
root_src : [ ] const u8 ,
build_mode : builtin . Mode ,
verbose : bool ,
link_libs : BufSet ,
name_prefix : [ ] const u8 ,
filter : ? [ ] const u8 ,
target : Target ,
exec_cmd_args : ? [ ] const ? [ ] const u8 ,
2018-03-14 09:19:51 +00:00
include_dirs : ArrayList ( [ ] const u8 ) ,
2018-07-11 00:18:43 +00:00
lib_paths : ArrayList ( [ ] const u8 ) ,
object_files : ArrayList ( [ ] const u8 ) ,
2018-07-25 01:28:54 +00:00
no_rosegment : bool ,
2018-09-11 21:23:36 +00:00
output_path : ? [ ] const u8 ,
2018-11-02 04:07:43 +00:00
system_linker_hack : bool ,
2017-09-18 06:50:51 +00:00
2018-05-31 14:56:59 +00:00
pub fn init ( builder : * Builder , root_src : [ ] const u8 ) TestStep {
2017-09-18 06:50:51 +00:00
const step_name = builder . fmt ( " test {} " , root_src ) ;
2018-11-13 13:08:37 +00:00
return TestStep {
2017-09-18 06:50:51 +00:00
. step = Step . init ( step_name , builder . allocator , make ) ,
. builder = builder ,
. root_src = root_src ,
. build_mode = builtin . Mode . Debug ,
. verbose = false ,
. name_prefix = " " ,
. filter = null ,
. link_libs = BufSet . init ( builder . allocator ) ,
2018-11-13 13:08:37 +00:00
. target = Target { . Native = { } } ,
2017-09-18 06:50:51 +00:00
. exec_cmd_args = null ,
2018-03-14 09:19:51 +00:00
. include_dirs = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
2018-07-11 00:18:43 +00:00
. lib_paths = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
. object_files = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ,
2018-07-25 01:28:54 +00:00
. no_rosegment = false ,
2018-09-11 21:23:36 +00:00
. output_path = null ,
2018-11-02 04:07:43 +00:00
. system_linker_hack = false ,
2017-12-22 05:50:30 +00:00
} ;
2017-09-18 06:50:51 +00:00
}
2018-07-25 01:28:54 +00:00
pub fn setNoRoSegment ( self : * TestStep , value : bool ) void {
self . no_rosegment = value ;
}
2018-07-11 00:18:43 +00:00
pub fn addLibPath ( self : * TestStep , path : [ ] const u8 ) void {
self . lib_paths . append ( path ) catch unreachable ;
}
2018-05-31 14:56:59 +00:00
pub fn setVerbose ( self : * TestStep , value : bool ) void {
2017-09-18 06:50:51 +00:00
self . verbose = value ;
}
2018-05-31 14:56:59 +00:00
pub fn addIncludeDir ( self : * TestStep , path : [ ] const u8 ) void {
2018-03-14 09:19:51 +00:00
self . include_dirs . append ( path ) catch unreachable ;
}
2018-05-31 14:56:59 +00:00
pub fn setBuildMode ( self : * TestStep , mode : builtin . Mode ) void {
2017-09-18 06:50:51 +00:00
self . build_mode = mode ;
}
2018-09-11 21:23:36 +00:00
pub fn setOutputPath ( self : * TestStep , file_path : [ ] const u8 ) void {
self . output_path = file_path ;
// catch a common mistake
if ( mem . eql ( u8 , self . builder . pathFromRoot ( file_path ) , self . builder . pathFromRoot ( " . " ) ) ) {
debug . panic ( " setOutputPath wants a file path, not a directory \n " ) ;
}
}
pub fn getOutputPath ( self : * TestStep ) [ ] const u8 {
if ( self . output_path ) | output_path | {
return output_path ;
} else {
const basename = self . builder . fmt ( " test{} " , self . target . exeFileExt ( ) ) ;
return os . path . join ( self . builder . allocator , self . builder . cache_root , basename ) catch unreachable ;
}
}
2018-05-31 14:56:59 +00:00
pub fn linkSystemLibrary ( self : * TestStep , name : [ ] const u8 ) void {
2018-01-09 05:07:01 +00:00
self . link_libs . put ( name ) catch unreachable ;
2017-09-18 06:50:51 +00:00
}
2017-04-16 18:14:11 +00:00
2018-05-31 14:56:59 +00:00
pub fn setNamePrefix ( self : * TestStep , text : [ ] const u8 ) void {
2017-09-18 06:50:51 +00:00
self . name_prefix = text ;
}
2018-05-31 14:56:59 +00:00
pub fn setFilter ( self : * TestStep , text : ? [ ] const u8 ) void {
2017-09-18 06:50:51 +00:00
self . filter = text ;
}
2018-09-06 20:29:35 +00:00
pub fn addObject ( self : * TestStep , obj : * LibExeObjStep ) void {
assert ( obj . kind = = LibExeObjStep . Kind . Obj ) ;
self . step . dependOn ( & obj . step ) ;
self . object_files . append ( obj . getOutputPath ( ) ) catch unreachable ;
// TODO should be some kind of isolated directory that only has this header in it
self . include_dirs . append ( self . builder . cache_root ) catch unreachable ;
}
2018-07-11 00:18:43 +00:00
pub fn addObjectFile ( self : * TestStep , path : [ ] const u8 ) void {
self . object_files . append ( path ) catch unreachable ;
}
2018-05-31 14:56:59 +00:00
pub fn setTarget ( self : * TestStep , target_arch : builtin . Arch , target_os : builtin . Os , target_environ : builtin . Environ ) void {
2018-11-13 13:08:37 +00:00
self . target = Target {
. Cross = CrossTarget {
2018-05-26 22:16:39 +00:00
. arch = target_arch ,
. os = target_os ,
. environ = target_environ ,
} ,
} ;
2017-04-13 21:21:00 +00:00
}
2017-09-18 06:50:51 +00:00
2018-05-31 14:56:59 +00:00
pub fn setExecCmd ( self : * TestStep , args : [ ] const ? [ ] const u8 ) void {
2017-09-18 06:50:51 +00:00
self . exec_cmd_args = args ;
}
2018-11-02 04:07:43 +00:00
pub fn enableSystemLinkerHack ( self : * TestStep ) void {
self . system_linker_hack = true ;
}
2018-05-31 14:56:59 +00:00
fn make ( step : * Step ) ! void {
2017-09-18 06:50:51 +00:00
const self = @fieldParentPtr ( TestStep , " step " , step ) ;
const builder = self . builder ;
var zig_args = ArrayList ( [ ] const u8 ) . init ( builder . allocator ) ;
defer zig_args . deinit ( ) ;
2018-01-09 05:07:01 +00:00
try zig_args . append ( builder . zig_exe ) ;
2017-09-26 05:01:49 +00:00
2018-01-09 05:07:01 +00:00
try zig_args . append ( " test " ) ;
try zig_args . append ( builder . pathFromRoot ( self . root_src ) ) ;
2017-09-18 06:50:51 +00:00
if ( self . verbose ) {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --verbose " ) ;
2017-09-18 06:50:51 +00:00
}
switch ( self . build_mode ) {
builtin . Mode . Debug = > { } ,
2018-01-09 05:07:01 +00:00
builtin . Mode . ReleaseSafe = > try zig_args . append ( " --release-safe " ) ,
builtin . Mode . ReleaseFast = > try zig_args . append ( " --release-fast " ) ,
2018-04-16 00:26:10 +00:00
builtin . Mode . ReleaseSmall = > try zig_args . append ( " --release-small " ) ,
2017-09-18 06:50:51 +00:00
}
2018-09-11 21:23:36 +00:00
const output_path = builder . pathFromRoot ( self . getOutputPath ( ) ) ;
try zig_args . append ( " --output " ) ;
try zig_args . append ( output_path ) ;
2017-09-18 06:50:51 +00:00
switch ( self . target ) {
Target . Native = > { } ,
Target . Cross = > | cross_target | {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --target-arch " ) ;
try zig_args . append ( @tagName ( cross_target . arch ) ) ;
2017-09-18 06:50:51 +00:00
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --target-os " ) ;
try zig_args . append ( @tagName ( cross_target . os ) ) ;
2017-09-18 06:50:51 +00:00
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --target-environ " ) ;
try zig_args . append ( @tagName ( cross_target . environ ) ) ;
2017-09-18 06:50:51 +00:00
} ,
}
if ( self . filter ) | filter | {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --test-filter " ) ;
try zig_args . append ( filter ) ;
2017-09-18 06:50:51 +00:00
}
if ( self . name_prefix . len ! = 0 ) {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --test-name-prefix " ) ;
try zig_args . append ( self . name_prefix ) ;
2017-09-18 06:50:51 +00:00
}
2018-07-11 00:18:43 +00:00
for ( self . object_files . toSliceConst ( ) ) | object_file | {
try zig_args . append ( " --object " ) ;
try zig_args . append ( builder . pathFromRoot ( object_file ) ) ;
}
2017-09-18 06:50:51 +00:00
{
var it = self . link_libs . iterator ( ) ;
while ( true ) {
2018-06-10 05:13:51 +00:00
const entry = it . next ( ) orelse break ;
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --library " ) ;
try zig_args . append ( entry . key ) ;
2017-09-18 06:50:51 +00:00
}
}
if ( self . exec_cmd_args ) | exec_cmd_args | {
for ( exec_cmd_args ) | cmd_arg | {
if ( cmd_arg ) | arg | {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --test-cmd " ) ;
try zig_args . append ( arg ) ;
2017-09-18 06:50:51 +00:00
} else {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --test-cmd-bin " ) ;
2017-09-18 06:50:51 +00:00
}
}
}
2018-03-14 09:19:51 +00:00
for ( self . include_dirs . toSliceConst ( ) ) | include_path | {
try zig_args . append ( " -isystem " ) ;
try zig_args . append ( builder . pathFromRoot ( include_path ) ) ;
}
2017-09-18 06:50:51 +00:00
for ( builder . include_paths . toSliceConst ( ) ) | include_path | {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " -isystem " ) ;
try zig_args . append ( builder . pathFromRoot ( include_path ) ) ;
2017-09-18 06:50:51 +00:00
}
for ( builder . rpaths . toSliceConst ( ) ) | rpath | {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " -rpath " ) ;
try zig_args . append ( rpath ) ;
2018-07-11 00:18:43 +00:00
}
for ( self . lib_paths . toSliceConst ( ) ) | lib_path | {
try zig_args . append ( " --library-path " ) ;
try zig_args . append ( lib_path ) ;
2017-09-18 06:50:51 +00:00
}
for ( builder . lib_paths . toSliceConst ( ) ) | lib_path | {
2018-01-09 05:07:01 +00:00
try zig_args . append ( " --library-path " ) ;
try zig_args . append ( lib_path ) ;
2017-09-18 06:50:51 +00:00
}
2018-07-25 01:28:54 +00:00
if ( self . no_rosegment ) {
try zig_args . append ( " --no-rosegment " ) ;
}
2018-11-02 04:07:43 +00:00
if ( self . system_linker_hack ) {
try zig_args . append ( " --system-linker-hack " ) ;
}
2018-07-25 01:28:54 +00:00
2018-01-07 21:51:46 +00:00
try builder . spawnChild ( zig_args . toSliceConst ( ) ) ;
2017-09-18 06:50:51 +00:00
}
2017-04-13 21:21:00 +00:00
} ;
2018-11-13 13:08:37 +00:00
pub const CommandStep = struct {
2017-04-13 21:21:00 +00:00
step : Step ,
2018-05-31 14:56:59 +00:00
builder : * Builder ,
2017-09-26 05:01:49 +00:00
argv : [ ] [ ] const u8 ,
2017-04-30 22:56:24 +00:00
cwd : ? [ ] const u8 ,
2018-05-31 14:56:59 +00:00
env_map : * const BufMap ,
2017-04-13 21:21:00 +00:00
2017-09-26 05:01:49 +00:00
/// ::argv is copied.
2018-05-31 14:56:59 +00:00
pub fn create ( builder : * Builder , cwd : ? [ ] const u8 , env_map : * const BufMap , argv : [ ] const [ ] const u8 ) * CommandStep {
2018-11-13 13:08:37 +00:00
const self = builder . allocator . create ( CommandStep {
2017-04-17 07:20:56 +00:00
. builder = builder ,
2017-09-26 05:01:49 +00:00
. step = Step . init ( argv [ 0 ] , builder . allocator , make ) ,
2018-01-09 05:07:01 +00:00
. argv = builder . allocator . alloc ( [ ] u8 , argv . len ) catch unreachable ,
2017-04-13 21:21:00 +00:00
. cwd = cwd ,
. env_map = env_map ,
2018-06-20 15:40:21 +00:00
} ) catch unreachable ;
2017-09-26 05:01:49 +00:00
mem . copy ( [ ] const u8 , self . argv , argv ) ;
self . step . name = self . argv [ 0 ] ;
2017-04-30 22:56:24 +00:00
return self ;
2017-04-13 21:21:00 +00:00
}
2018-05-31 14:56:59 +00:00
fn make ( step : * Step ) ! void {
2017-04-18 06:28:05 +00:00
const self = @fieldParentPtr ( CommandStep , " step " , step ) ;
2017-04-13 21:21:00 +00:00
2017-11-07 08:22:27 +00:00
const cwd = if ( self . cwd ) | cwd | self . builder . pathFromRoot ( cwd ) else self . builder . build_root ;
2017-09-26 05:01:49 +00:00
return self . builder . spawnChildEnvMap ( cwd , self . env_map , self . argv ) ;
2017-04-13 21:21:00 +00:00
}
} ;
2018-11-13 13:08:37 +00:00
const InstallArtifactStep = struct {
2017-09-18 06:50:51 +00:00
step : Step ,
2018-05-31 14:56:59 +00:00
builder : * Builder ,
artifact : * LibExeObjStep ,
2017-09-18 06:50:51 +00:00
dest_file : [ ] const u8 ,
2018-09-13 20:34:33 +00:00
const Self = @This ( ) ;
2017-09-18 06:50:51 +00:00
2018-05-31 14:56:59 +00:00
pub fn create ( builder : * Builder , artifact : * LibExeObjStep ) * Self {
2017-09-18 06:50:51 +00:00
const dest_dir = switch ( artifact . kind ) {
LibExeObjStep . Kind . Obj = > unreachable ,
LibExeObjStep . Kind . Exe = > builder . exe_dir ,
LibExeObjStep . Kind . Lib = > builder . lib_dir ,
} ;
2018-11-13 13:08:37 +00:00
const self = builder . allocator . create ( Self {
2017-09-18 06:50:51 +00:00
. builder = builder ,
. step = Step . init ( builder . fmt ( " install {} " , artifact . step . name ) , builder . allocator , make ) ,
. artifact = artifact ,
2018-01-09 05:07:01 +00:00
. dest_file = os . path . join ( builder . allocator , dest_dir , artifact . out_filename ) catch unreachable ,
2018-06-20 15:40:21 +00:00
} ) catch unreachable ;
2017-09-18 06:50:51 +00:00
self . step . dependOn ( & artifact . step ) ;
builder . pushInstalledFile ( self . dest_file ) ;
if ( self . artifact . kind = = LibExeObjStep . Kind . Lib and ! self . artifact . static ) {
2018-05-10 04:29:49 +00:00
builder . pushInstalledFile ( os . path . join ( builder . allocator , builder . lib_dir , artifact . major_only_filename ) catch unreachable ) ;
builder . pushInstalledFile ( os . path . join ( builder . allocator , builder . lib_dir , artifact . name_only_filename ) catch unreachable ) ;
2017-04-17 10:45:44 +00:00
}
2017-09-18 06:50:51 +00:00
return self ;
}
2017-04-17 10:45:44 +00:00
2018-05-31 14:56:59 +00:00
fn make ( step : * Step ) ! void {
2017-09-18 06:50:51 +00:00
const self = @fieldParentPtr ( Self , " step " , step ) ;
const builder = self . builder ;
2017-04-17 10:45:44 +00:00
2018-02-11 01:55:13 +00:00
const mode = switch ( builtin . os ) {
builtin . Os . windows = > { } ,
else = > switch ( self . artifact . kind ) {
LibExeObjStep . Kind . Obj = > unreachable ,
LibExeObjStep . Kind . Exe = > u32 ( 0o755 ) ,
LibExeObjStep . Kind . Lib = > if ( self . artifact . static ) u32 ( 0o666 ) else u32 ( 0o755 ) ,
} ,
2017-09-18 06:50:51 +00:00
} ;
2018-01-07 21:51:46 +00:00
try builder . copyFileMode ( self . artifact . getOutputPath ( ) , self . dest_file , mode ) ;
2017-09-18 06:50:51 +00:00
if ( self . artifact . kind = = LibExeObjStep . Kind . Lib and ! self . artifact . static ) {
2018-05-10 04:29:49 +00:00
try doAtomicSymLinks ( builder . allocator , self . dest_file , self . artifact . major_only_filename , self . artifact . name_only_filename ) ;
2017-04-17 10:45:44 +00:00
}
}
2017-09-18 06:50:51 +00:00
} ;
2017-04-17 10:45:44 +00:00
2018-11-13 13:08:37 +00:00
pub const InstallFileStep = struct {
2017-04-17 10:45:44 +00:00
step : Step ,
2018-05-31 14:56:59 +00:00
builder : * Builder ,
2017-04-17 10:45:44 +00:00
src_path : [ ] const u8 ,
dest_path : [ ] const u8 ,
2018-05-31 14:56:59 +00:00
pub fn init ( builder : * Builder , src_path : [ ] const u8 , dest_path : [ ] const u8 ) InstallFileStep {
2018-11-13 13:08:37 +00:00
return InstallFileStep {
2017-04-17 10:45:44 +00:00
. builder = builder ,
2017-04-19 19:38:12 +00:00
. step = Step . init ( builder . fmt ( " install {} " , src_path ) , builder . allocator , make ) ,
2017-04-17 10:45:44 +00:00
. src_path = src_path ,
. dest_path = dest_path ,
} ;
}
2018-05-31 14:56:59 +00:00
fn make ( step : * Step ) ! void {
2017-04-18 06:28:05 +00:00
const self = @fieldParentPtr ( InstallFileStep , " step " , step ) ;
2018-01-07 21:51:46 +00:00
try self . builder . copyFile ( self . src_path , self . dest_path ) ;
2017-04-17 10:45:44 +00:00
}
} ;
2018-11-13 13:08:37 +00:00
pub const WriteFileStep = struct {
2017-04-19 05:13:15 +00:00
step : Step ,
2018-05-31 14:56:59 +00:00
builder : * Builder ,
2017-04-19 05:13:15 +00:00
file_path : [ ] const u8 ,
data : [ ] const u8 ,
2018-05-31 14:56:59 +00:00
pub fn init ( builder : * Builder , file_path : [ ] const u8 , data : [ ] const u8 ) WriteFileStep {
2018-11-13 13:08:37 +00:00
return WriteFileStep {
2017-04-19 05:13:15 +00:00
. builder = builder ,
2017-04-19 19:38:12 +00:00
. step = Step . init ( builder . fmt ( " writefile {} " , file_path ) , builder . allocator , make ) ,
2017-04-19 05:13:15 +00:00
. file_path = file_path ,
. data = data ,
} ;
}
2018-05-31 14:56:59 +00:00
fn make ( step : * Step ) ! void {
2017-04-19 05:13:15 +00:00
const self = @fieldParentPtr ( WriteFileStep , " step " , step ) ;
const full_path = self . builder . pathFromRoot ( self . file_path ) ;
2018-06-14 20:15:32 +00:00
const full_path_dir = os . path . dirname ( full_path ) orelse " . " ;
2018-01-07 22:28:20 +00:00
os . makePath ( self . builder . allocator , full_path_dir ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " unable to make path {}: {} \n " , full_path_dir , @errorName ( err ) ) ;
2017-04-20 06:26:36 +00:00
return err ;
2017-04-19 05:13:15 +00:00
} ;
2018-08-21 20:07:28 +00:00
io . writeFile ( full_path , self . data ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " unable to write {}: {} \n " , full_path , @errorName ( err ) ) ;
2017-04-20 06:26:36 +00:00
return err ;
2017-04-19 05:13:15 +00:00
} ;
}
} ;
2018-11-13 13:08:37 +00:00
pub const LogStep = struct {
2017-04-19 05:13:15 +00:00
step : Step ,
2018-05-31 14:56:59 +00:00
builder : * Builder ,
2017-04-19 05:13:15 +00:00
data : [ ] const u8 ,
2018-05-31 14:56:59 +00:00
pub fn init ( builder : * Builder , data : [ ] const u8 ) LogStep {
2018-11-13 13:08:37 +00:00
return LogStep {
2017-04-19 05:13:15 +00:00
. builder = builder ,
2017-04-19 19:38:12 +00:00
. step = Step . init ( builder . fmt ( " log {} " , data ) , builder . allocator , make ) ,
2017-04-19 05:13:15 +00:00
. data = data ,
} ;
}
2018-11-13 13:08:37 +00:00
fn make ( step : * Step ) anyerror ! void {
2017-04-19 05:13:15 +00:00
const self = @fieldParentPtr ( LogStep , " step " , step ) ;
2017-10-31 08:47:55 +00:00
warn ( " {} " , self . data ) ;
2017-04-19 05:13:15 +00:00
}
} ;
2018-11-13 13:08:37 +00:00
pub const RemoveDirStep = struct {
2017-04-20 06:26:36 +00:00
step : Step ,
2018-05-31 14:56:59 +00:00
builder : * Builder ,
2017-04-20 06:26:36 +00:00
dir_path : [ ] const u8 ,
2018-05-31 14:56:59 +00:00
pub fn init ( builder : * Builder , dir_path : [ ] const u8 ) RemoveDirStep {
2018-11-13 13:08:37 +00:00
return RemoveDirStep {
2017-04-20 06:26:36 +00:00
. builder = builder ,
. step = Step . init ( builder . fmt ( " RemoveDir {} " , dir_path ) , builder . allocator , make ) ,
. dir_path = dir_path ,
} ;
}
2018-05-31 14:56:59 +00:00
fn make ( step : * Step ) ! void {
2017-04-20 06:26:36 +00:00
const self = @fieldParentPtr ( RemoveDirStep , " step " , step ) ;
const full_path = self . builder . pathFromRoot ( self . dir_path ) ;
2018-01-07 22:28:20 +00:00
os . deleteTree ( self . builder . allocator , full_path ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " Unable to remove {}: {} \n " , full_path , @errorName ( err ) ) ;
2017-04-20 06:26:36 +00:00
return err ;
} ;
}
} ;
2018-11-13 13:08:37 +00:00
pub const Step = struct {
2017-04-13 21:21:00 +00:00
name : [ ] const u8 ,
2018-11-13 13:08:37 +00:00
makeFn : fn ( self : * Step ) anyerror ! void ,
2018-05-31 14:56:59 +00:00
dependencies : ArrayList ( * Step ) ,
2017-04-13 21:21:00 +00:00
loop_flag : bool ,
done_flag : bool ,
2018-11-13 13:08:37 +00:00
pub fn init ( name : [ ] const u8 , allocator : * Allocator , makeFn : fn ( * Step ) anyerror ! void ) Step {
return Step {
2017-04-13 21:21:00 +00:00
. name = name ,
. makeFn = makeFn ,
2018-05-31 14:56:59 +00:00
. dependencies = ArrayList ( * Step ) . init ( allocator ) ,
2017-04-13 21:21:00 +00:00
. loop_flag = false ,
. done_flag = false ,
2017-12-22 05:50:30 +00:00
} ;
2017-04-13 21:21:00 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn initNoOp ( name : [ ] const u8 , allocator : * Allocator ) Step {
2017-12-22 05:50:30 +00:00
return init ( name , allocator , makeNoOp ) ;
2017-04-13 21:21:00 +00:00
}
2018-05-31 14:56:59 +00:00
pub fn make ( self : * Step ) ! void {
2018-05-10 04:29:49 +00:00
if ( self . done_flag ) return ;
2017-04-13 21:21:00 +00:00
2018-01-07 21:51:46 +00:00
try self . makeFn ( self ) ;
2017-04-13 21:21:00 +00:00
self . done_flag = true ;
}
2018-05-31 14:56:59 +00:00
pub fn dependOn ( self : * Step , other : * Step ) void {
2018-01-09 05:07:01 +00:00
self . dependencies . append ( other ) catch unreachable ;
2017-04-13 21:21:00 +00:00
}
2018-11-13 13:08:37 +00:00
fn makeNoOp ( self : * Step ) anyerror ! void { }
2017-04-13 21:21:00 +00:00
} ;
2017-04-30 22:56:24 +00:00
2018-05-31 14:56:59 +00:00
fn doAtomicSymLinks ( allocator : * Allocator , output_path : [ ] const u8 , filename_major_only : [ ] const u8 , filename_name_only : [ ] const u8 ) ! void {
2018-06-14 20:15:32 +00:00
const out_dir = os . path . dirname ( output_path ) orelse " . " ;
2017-04-30 22:56:24 +00:00
const out_basename = os . path . basename ( output_path ) ;
// sym link for libfoo.so.1 to libfoo.so.1.2.3
2018-01-09 05:07:01 +00:00
const major_only_path = os . path . join ( allocator , out_dir , filename_major_only ) catch unreachable ;
2018-01-07 22:28:20 +00:00
os . atomicSymLink ( allocator , out_basename , major_only_path ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " Unable to symlink {} -> {} \n " , major_only_path , out_basename ) ;
2017-04-30 22:56:24 +00:00
return err ;
} ;
// sym link for libfoo.so to libfoo.so.1
2018-01-09 05:07:01 +00:00
const name_only_path = os . path . join ( allocator , out_dir , filename_name_only ) catch unreachable ;
2018-01-07 22:28:20 +00:00
os . atomicSymLink ( allocator , filename_major_only , name_only_path ) catch | err | {
2017-10-31 08:47:55 +00:00
warn ( " Unable to symlink {} -> {} \n " , name_only_path , filename_major_only ) ;
2017-04-30 22:56:24 +00:00
return err ;
} ;
}